<!-- SOLID CITY · part 2729 -->
; driveMouths.push([tgt.x, tgt.z]); }
      }
    }
    // walking path: parking pad -> front steps, lined with small yellow stones (the King's photos)
    steppedPath(pkX, pkZ, doorX, doorZ, 1.7, C.path, 2.6);
    var plen = Math.hypot(doorX - pkX, doorZ - pkZ), pn = Math.max(2, Math.floor(plen / 2.2));
    for (var i = 0; i <= pn; i++) {
      var t = i / pn, sx2 = pkX + (doorX - pkX) * t, sz2 = pkZ + (doorZ - pkZ) * t;
      var ox = -(doorZ - pkZ) / (plen || 1) * 1.25, oz = (doorX - pkX) / (plen || 1) * 1.25;
      BASE = M4(sx2 + ox, groundAt(sx2 + ox, sz2 + oz) + 0.02, sz2 + oz, 0, 0, 0);
      rock(solid, 0.3, 0, 0.1, 0, C.yellowStone);
      BASE = new T.Matrix4();
    }
    // a mailbox where the path meets the drive
    BASE = M4(pkX - rx * 2.2, groundAt(pkX - rx * 2.2, pkZ - rz * 2.2), pkZ - rz * 2.2, rec.ry, 0, 0);
    box(solid, 0.14, 1.05, 0.14, 0, 0.52, 0, C.woodDark);
    box(solid, 0.75, 0.4, 0.45, 0, 1.2, 0, R() < 0.5 ? 0x8a3030 : C.stoneDark);
    BASE = new T.Matrix4();
    rec.door = [doorX, doorZ]; rec.park = [pkX, pkZ];
  }
  /* THE APARTMENT'S DRIVE (the same sitting): a block keeps
   * its own lot — the strip and cars its builder lays — but
   * the lot stood 65 m from the road's end with no drive at
   * all. It is served like a house now: one drive from the
   * lot's front to the gentlest station within the same
   * 100 m reach, under the same law. */
  function serveApartment(rec) {
    var fx = Math.sin(rec.ry), fz = Math.cos(rec.ry);
    var lotX = rec.x + fx * (rec.d / 2 + 5.2), lotZ = rec.z + fz * (rec.d / 2 + 5.2);
    var lotY = groundAt(lotX, lotZ);
    var tgt = null, tScore = 1e12;
    for (var rn3 in smithRoads) { var ests2 = smithRoads[rn3].stations; for (var eq2 = 0; eq2 < ests2.length; eq2++) { var es2 = ests2[eq2], edx2 = es2.x - lotX, edz2 = es2.z - lotZ, edist2 = Math.sqrt(edx2 * edx2 + edz2 * edz2); if (edist2 > 100) continue; var esc2 = Math.abs(es2.y - (lotY + 0.06)) / Math.max(edist2, 2.5); if (esc2 < tScore) { tScore = esc2; tgt = es2; } } }
    if (tgt) { steppedPath(lotX, lotZ, tgt.x, tgt.z, 3.4, C.drive, 3.6, tgt.y); driveMouths.push([tgt.x, tgt.z]); rec.drive = [tgt.x, tgt.z]; }
  }
  var CAR_COLS = [0xb8bcc2, 0x7a2e2e, 0x2e4a6a, 0xd8d3c3, 0x3a3a3e, 0x6a7a4a];

  /* ================= CLUSTERS — homes for Hawaiian families ================= */
  var plates = [];   // {x, z, ry, name}
  /* the built centreline as true segments (consecutive stations of
   * one road stand metres apart; the jump between roads is wide) —
   * the measure the Verge Law judges by, because on hairpin ground
   * a distance to the nearest station POINT can read clear while
   * the neighbouring leg's SEGMENT passes through the same ground. */
  var VERGE_SEGS = null;
  function segDistToRoad(x, z) {
    if (!VERGE_SEGS) {
      VERGE_SEGS = [];
      for (var vi = 0; vi < roadPts.length - 1; vi++) { var va = roadPts[vi], vb = roadPts[vi + 1]; if (Math.hypot(vb[0] - va[0], vb[1] - va[1]) < 4) VERGE_SEGS.push([va, vb]); }
    }
    var bd = 1e12, bx = x, bz = z;
    for (var i = 0; i < VERGE_SEGS.length; i++) {
      var a = VERGE_SEGS[i][0], b = VERGE_SEGS[i][1];
      var dx = b[0] - a[0], dz = b[1] - a[1], L2 = dx * dx + dz * dz;
      var t = L2 ? ((x - a[0]) * dx + (z - a[1]) * dz) / L2 : 0; t = Math.max(0, Math.min(1, t));
      var px = a[0] + dx * t, pz = a[1] + dz * t, d = Math.hypot(x - px, z - pz);
      if (d < bd) { bd = d; bx = px; bz = pz; }
    }
    return { d: bd, x: bx, z: bz };
  }
  function plateFor(name, x, z) {
    var rp = nearestRoad(x, z);
    /* THE VERGE LAW FOR SIGNS (the King's report, 2026-10-13 ~23:12:
     * "trees and signs in the middle — I can't move up or down with
     * that"). A cluster's centre is a survey idea, and several sit
     * ON the road's own line — a plate planted there stands in the
     * carriageway (the Eastern Benches plate measured 0.6 m from
     * the centreline). So the plate walks out to the verge: at
     * least 7.5 m from every built centreline segment, toward its
     * own cluster's nearest home — ground the siting law already
     * keeps clear — still facing the road it names. Plates already
     * clear stand where they were planted. No seed is drawn here;
     * the census of homes cannot shift. */
    if (segDistToRoad(x, z).d < 7.5) {
      var hb = null, hd = 1e12;
      homes.forEach(function (h) { var dd = Math.hypot(h.x - x, h.z - z); if (dd < hd) { hd = dd; hb = h; } });
      var ux, uz;
      if (hb) { ux = hb.x - rp.x; uz = hb.z - rp.z; } else { ux = x - rp.x; uz = z - rp.z; }
      var ul = Math.hypot(ux, uz); if (ul < 0.01) { ux = 1; uz = 0; ul = 1; }
      ux /= ul; uz /= ul;
      var D = 7.5;
      x = rp.x + ux * D; z = rp.z + uz * D;
      while (segDistToRoad(x, z).d < 7.5 && D < 44) { D += 0.5; x = rp.x + ux * D; z = rp.z + uz * D; }
      rp = nearestRoad(x, z);
    }
    plates.push({ x: x, z: z, ry: faceAngle(x, z, rp.x, rp.z), name: name });
  }
  functi