<!-- SOLID CITY · part 2692 -->
0.14, 0, C.woodDark);   // ridge cap
  }
  function putS(batch, geo, x, y, z, ry, sx, sy, sz, color) {
    _e.set(0, ry || 0, 0, 'YXZ'); _q.setFromEuler(_e);
    var m = new T.Matrix4().compose(new T.Vector3(x, y, z), _q.clone(), new T.Vector3(sx, sy, sz));
    if (BASE) m.premultiply(BASE);
    batch.add(geo, m, color);
  }
  function dickeyRoof(w, d, wh, color) {
    var ovLo = 1.7;
    var lo = new T.CylinderGeometry(0.60, 1, 1.2, 4);
    putS(solid, lo, 0, wh + 0.6, 0, Math.PI / 4, (w / 2 + ovLo) / 0.7071, 1, (d / 2 + ovLo) / 0.7071, color);
    // upper steep pitch sits INSIDE the lower section's top square
    var hiBotW = 0.60 * (w / 2 + ovLo) - 0.45, hiBotD = 0.60 * (d / 2 + ovLo) - 0.45;
    var hi = new T.CylinderGeometry(0.16, 0.60, 2.6, 4);
    putS(solid, hi, 0, wh + 1.2 + 1.3, 0, Math.PI / 4, hiBotW / (0.60 * 0.7071), 1, hiBotD / (0.60 * 0.7071), color);
    box(solid, w * 0.3, 0.2, d * 0.26, 0, wh + 3.9, 0, C.woodDark);
  }
  function wallSegs(w, d, wh, wallColor, doorHalf, winGlow) {
    // front wall (z=+d/2) with centered door gap 1.7 wide
    var doorTop = Math.min(2.35, wh - 0.12), segW = (w / 2 - doorHalf);
    box(solid, segW, wh, 0.28, -(doorHalf + segW / 2), wh / 2, d / 2, wallColor);
    box(solid, segW, wh, 0.28, (doorHalf + segW / 2), wh / 2, d / 2, wallColor);
    footprint(-(doorHalf + segW / 2), d / 2, segW, 0.5, 0, wh);
    footprint((doorHalf + segW / 2), d / 2, segW, 0.5, 0, wh);
    if (wh - doorTop > 0.05) {
      box(solid, doorHalf * 2, wh - 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.