<!-- SOLID CITY · part 2712 -->
t the pad)
  function dressHome(rec, opts) {
    opts = opts || {};
    var dx = Math.sin(rec.ry), dz = Math.cos(rec.ry);          // front direction (local +z in world)
    var sx = Math.cos(rec.ry), sz = -Math.sin(rec.ry);         // right direction (local +x in world)
    function at(lx, lz) { return [rec.x + lx * sx + lz * dx, rec.z + lx * sz + lz * dz]; }
    function onGround(lx, lz, fn) {
      var p = at(lx, lz), gy = groundAt(p[0], p[1]);
      BASE = M4(p[0], gy - 0.15, p[1], R() * Math.PI * 2, 0, 0); fn(); BASE = new T.Matrix4();
    }
    // flowering shrubs against the front wall corners
    onGround(-rec.w / 2 - 1.2, rec.d / 2 + rec.lanaiDepth + 0.6, function () { shrub(C.flower1); });
    onGround(rec.w / 2 + 1.1, rec.d / 2 + rec.lanaiDepth + 0.5, function () { shrub(R() < 0.5 ? C.flower2 : C.flower3); });
    // a fruit tree beside the home — banana or breadfruit, woven into the green
    onGround((R() < 0.5 ? -1 : 1) * (rec.w / 2 + 3.4), 1.5, function () { if (R() < 0.55) banana(); else breadfruit(0.9 + R() * 0.4); });
    if (opts.taro) {   // a lo'i kalo at the compound's low side
      onGround(opts.taro[0], opts.taro[1], function () { taroPatch(7.5, 5); });
    }
    if (opts.palm) onGround(rec.w / 2 + 5.5, rec.d / 2 + 4, function () { palm(0.9 + R() * 0.3); });
  }

  /* ================= APARTMENT BLOCKS (the base flats) =================
   * 3 floors x 2 units, balcony corridors, exterior stair, ground lobby.
   * Corridor slabs are standY-only (walk under them); railings are the solids.
   */
  function buildApartment(x, z, ry) {
    var w = 27, d = 11, fh = 3.3, floors = 3;
    var baseY = lotHeight(x, z, 10);
    setHome(x, z, baseY, ry);
    box(solid, w + 3, 0.5, d + 5.5, 0, -0.25, 1, C.path);            // ground slab + porch apron
    stand(0, 1, w + 3, d + 5.5, 0.02);
    footprint(0, 1, w + 3, d + 5.5, -2.5, -0.35);                    // slab edge blocks from below-grade only
    for (var f = 0; f < floors; f++) {
      var fy = f * fh;
      // back + side walls
      box(solid, w, fh, 0.3, 0, fy + fh / 2, -d / 2, C.aptWall);
      box(solid, 0.3, fh, d, -w / 2, fy + fh / 2, 0, C.aptWall);
      box(solid, 0.3, fh, d, w / 2, fy + fh / 2, 0, C.aptWall);
      footprint(0, -d / 2, w, 0.5, fy, fy + fh);
      footprint(-w / 2, 0, 0.5, d, fy, fy + fh);
      footprint(w / 2, 0, 0.5, d, fy, fy + fh);
      // front wall with two unit door gaps (doors at x=-w/4, +w/4)
      var doors = [-w / 4, w / 4], segs = [[-w / 2, doors[0] - 0.8], [doors[0] + 0.8, doors[1] - 0.8], [doors[1] + 0.8, w / 2]];
      segs.forEach(function (sg) {
        var sw = sg[1] - sg[0], cx = (sg[0] + sg[1]) / 2;
        box(solid, sw, fh, 0.3, cx, fy + fh / 2, d / 2, C.aptWall);
        footprint(cx, d / 2, sw, 0.5, fy, fy + fh);
      });
      doors.forEach(function (dx2) {
        box(solid, 1.6, fh - 2.3, 0.3, dx2, fy + 2.3 + (fh - 2.3) / 2, d / 2, C.aptWall);   // lintel
        box(solid, 0.08, 2.25, 1.5, dx2 - 0.7, fy + 1.12, d / 2 - 0.95, C.doorFrame, 0.5); // leaf open inside
      });
      // corridor (balcony walkway) + railing with a gap at the stair end
      box(solid, w, 0.22, 2.3, 0, fy - 0.02, d / 2 + 1.15, C.path);
      stand(0, d / 2 + 1.15, w, 2.3, fy + 0.1);
      if (f > 0) {
        box(solid, w - 2.6, 0.09, 0.1, -1.3, fy + 1.02, d / 2 + 2.25, C.stoneDark);
        footprint(-1.3, d / 2 + 2.25, w - 2.6, 0.35, fy, fy + 1.05);
      }
      // windows: warm panes on the back wall, one per unit + corridor-end glass
      box(glowB, 2.2, 1.2, 0.1, -w / 4, fy + 1.8, -d / 2, C.warm);
      box(glowB, 2.2, 1.2, 0.1, w / 4, fy + 1.8, -d / 2, C.warm);
      // interiors: partition + bed + table per unit
      [-w / 4, w / 4].forEach(function (ux) {
        box(solid, 0.16, 2.5, d * 0.5, ux, fy + 1.25, -d / 4, C.stucco2);
        footprint(ux, -d / 4, 0.4, d * 0.5, fy, fy + 2.5);
        box(solid, 1.5, 0.4, 2.1, ux + 2.8, fy + 0.2, -d / 3, C.woodDark);
        box(solid, 1.4, 0.2, 2.0, ux + 2.8, fy + 0.5, -d / 3, 0x9a7a4a);
        footprint(ux + 2.8, -d / 3, 1.6, 2.2, fy, fy + 1.5);
        box(solid, 1.6, 0.1, 0.9, ux - 2.6, fy + 0.78, 0.6, C.lanaiWood);
        footprint(ux - 2.6, 0.6, 1.7, 1.0, fy, fy + 1.5);
      });
      stand(0, 0, w, d, fy + 0.05);   // unit floors
    }
    // roof slab + parapet + a shaded roof corner
    box(solid, w + 1, 0.3, d + 3.4, 0, floors * fh + 0.15, 0.55, C.path);
    box(solid, w + 1, 0.7, 0.25, 0, floors * fh + 0.6, -d / 2 - 0.4, C.aptWall);
    box(solid, w + 1, 0.7, 0.25, 0, floors * fh + 0.6, d / 2 + 2.85, C.aptWall);
    box(solid, 0.25, 0.7, d + 3.4, -w / 2 - 0.4, floors * fh + 0.6, 0.55, C.aptWall);
    box(solid, 0.25, 0.7, d + 3.4, w / 2 + 0.4, floors * fh + 0.6, 0.55, C.aptWall);
    footprint(0, -d / 2 - 0.4, w + 1, 0.4, floors * fh, floors * fh + 1.05);
    footprint(0, d / 2 + 2.85, w + 1, 0.4, floors * fh, floors * fh + 1.05);
    footprint(-w / 2 - 0.4, 0.55, 0.4, d + 3.4, floors * fh, floors * fh + 1.0