<!-- SOLID CITY · part 2801 -->
- doorTop, 0.28, 0, doorTop + (wh - doorTop) / 2, d / 2, wallColor);  // lintel
      footprint(0, d / 2, doorHalf * 2, 0.5, doorTop, wh);   // blocks only above head height at floor level
    }
    // back wall + side walls
    box(solid, w, wh, 0.28, 0, wh / 2, -d / 2, wallColor);
    box(solid, 0.28, wh, d, -w / 2, wh / 2, 0, wallColor);
    box(solid, 0.28, wh, d, w / 2, wh / 2, 0, wallColor);
    footprint(0, -d / 2, w, 0.5, 0, wh);
    footprint(-w / 2, 0, 0.5, d, 0, wh);
    footprint(w / 2, 0, 0.5, d, 0, wh);
    if (winGlow) {   // warm window panes: sides + back (thin boxes read from both sides)
      box(glowB, 0.1, 1.1, 1.6, -w / 2, 1.7, -d / 5, C.warm);
      box(glowB, 0.1, 1.1, 1.6, w / 2, 1.7, d / 5, C.warm);
      box(glowB, 1.7, 1.1, 0.1, -w / 5, 1.7, -d / 2, C.warm);
      box(glowB, 1.7, 1.1, 0.1, w / 4, 1.7, -d / 2, C.warm);
      // dark-framed glass door row flanking the entry (the King's Hilo photos)
      box(solid, 1.15, 2.2, 0.1, -(doorHalf + 0.75), 1.1, d / 2 + 0.16, C.doorFrame);
      box(glassB, 0.95, 2.0, 0.06, -(doorHalf + 0.75), 1.1, d / 2 + 0.17, C.glass);
      box(solid, 1.15, 2.2, 0.1, (doorHalf + 0.75), 1.1, d / 2 + 0.16, C.doorFrame);
      box(glassB, 0.95, 2.0, 0.06, (doorHalf + 0.75), 1.1, d / 2 + 0.17, C.glass);
    }
    // the door leaf itself, swung open inside against the wall (visual — never blocks)
    box(solid, 0.08, 2.3, 1.6, -doorHalf - 0.75, 1.15, d / 2 - 1.05, C.doorFrame, 0.5);
    box(glassB, 0.05, 1.9, 1.3, -doorHalf - 0.72, 1.15, d / 2 - 1.03, C.glass);
  }
  function furnish(kind, w, d) {
    // a table with benches — the heart of the living space
    box(solid, 1.9, 0.1, 1.0, -w / 5, 0.78, 0.4, C.lanaiWood);
    box(solid, 0.18, 0.75, 0.8, -w / 5, 0.38, 0.4, C.woodDark);
    box(solid, 1.7, 0.09, 0.42, -w / 5, 0.45, 1.35, C.lanaiWood);
    box(solid, 1.7, 0.09, 0.42, -w / 5, 0.45, -0.55, C.lanaiWood);
    footprint(-w / 5, 0.4, 2.0, 1.1, 0, 1.5);
    if (kind === 'full') {   // a second room: partition with a gap + a bed beyond it
      box(solid, w * 0.55, 2.5, 0.16, -w * 0.2, 1.25, -d / 4, C.stucco2);
      footprint(-w * 0.2, -d / 4, w * 0.55, 0.4, 0, 2.5);
      box(solid, 1.5, 0.42, 2.2, w / 4, 0.21, -d / 3, C.woodDark);
      box(solid, 1.4, 0.22, 2.1, w / 4, 0.53, -d / 3, 0x9a4a3a);
      box(solid, 1.3, 0.18, 0.5, w / 4, 0.62, -d / 3 - 0.75, C.white);
      footprint(w / 4, -d / 3, 1.6, 2.3, 0, 1.5);
      box(solid, 0.9, 0.85, 0.45, -w / 3, 0.42, -d / 3, C.woodDark);   // storage chest
    } else {                 // simple: a sleeping platform along the back wall
      box(solid, 1.5, 0.4, 2.1, w / 4, 0.2, -d / 3, C.woodDark);
      box(solid, 1.4, 0.2, 2.0, w / 4, 0.5, -d / 3, 0x7a8a5a);
      footprint(w / 4, -d / 3, 1.6, 2.2, 0, 1.5);
    }
  }
  function lanaiBuild(w, d, wh, depth, enclosed) {
    var lz = d / 2 + depth / 2;   // lanai floor center z (pad already extends here)
    // posts
    [-w / 2 + 0.4, 0, w / 2 - 0.4].forEach(function (px) {
      cyl(solid, 0.14, 0.17, wh - 0.15, 6, px, (wh - 0.15) / 2, d / 2 + depth - 0.25, C.woodDark);
    });
    // lanai roof: a shallower slope continuing the front roof line
    var sl = Math.hypot(depth + 0.7, 0.85);
    box(solid, w + 1.2, 0.14, sl, 0, wh + 0.35, d / 2 + depth / 2, C.shingle2, 0, Math.atan2(0.85, depth + 0.7), 0);
    // railing on the front edge with a center entry gap (2.2 wide)
    var railW = (w / 2 - 1.1);
    box(solid, railW, 0.1, 0.12, -(1.1 + railW / 2), 1.0, d / 2 + depth - 0.2, C.lanaiWood);
    box(solid, railW, 0.1, 0.12, (1.1 + railW / 2), 1.0, d / 2 + depth - 0.2, C.lanaiWood);
    box(solid, railW, 0.08, 0.1, -(1.1 + railW / 2), 0.5, d / 2 + depth - 0.2, C.lanaiWood);
    box(solid, railW, 0.08, 0.1, (1.1 + railW / 2), 0.5, d / 2 + depth - 0.2, C.lanaiWood);
    footprint(-(1.1 + railW / 2), d / 2 + depth - 0.2, railW, 0.4, 0, 1.1);
    footprint((1.1 + railW / 2), d / 2 + depth - 0.2, railW, 0.4, 0, 1.1);
    if (enclosed) {  // Dickey enclosed lanai: glass panels between posts
      box(glassB, w - 1, 1.9, 0.06, 0, 1.55, d / 2 + depth - 0.22, C.glass);
    }
    return lz;
  }
  function stepsDown(n, zFront) {   // stone steps from pad front (y=0) down toward the path
    for (var i = 0; i < n; i++) {
      var sy = -0.28 * (i + 1), sz = zFront + 0.55 + i * 0.62;
      box(solid, 2.4, 0.26, 0.66, 0, sy - 0.13, sz, C.stone);
      stand(0, sz, 2.4, 0.7, sy);
    }
  }

  var STYLE_COUNT = { waa: 0, noa: 0, plantation: 0, dickey: 0, mission: 0 };
  function buildHome(style, x, z, ry, scale, interior) {
    scale = scale || 1;
    var w, d, wh, wallColor, roofColor;
    if (style === 'waa') { w = 10.5; d = 7.5; wh = 2.3; wallColor = C.woodWall; roofColor = 0x8a6a3a; }
    else if (style === 'noa') { w = 9; d = 7; wh = 2.5; wallColor = C.woodWall; roofColor = 0x8a6a3a; }
    else if (style === 'plantation') { w = 10; d = 7.5; wh = 2.9; wallColor = R() < 0.5 ? C.white : 0xd8cfb8; roofColor = C.shingle2; }
    else if (style 