<!-- SOLID CITY · part 2550 -->
.7],[935,-1860],[890,-1897.5],[858.8,-1888.7],[836.3,-1903.7],[800,-1910],[791.3,-1903.7],[757.5,-1948.7],[757.5,-1997.5],[708.8,-2031.2],[650,-2015],[590,-2025],[547.5,-2057.5],[543.8,-2068.7],[525,-2125],[505,-2180],[480,-2230],[445,-2277.5],[436.3,-2336.2],[460,-2385]],
    // S: the East Plain Spur — from the column head to the East Plain 'ohana
    [[915,-1285],[915,-1281.2],[907.5,-1232.5],[907.5,-1221.2],[880,-1180]]
  ];
  var roadPts = [];
  var ROAD_SEGS = [];
  ROAD_DEFS.forEach(function (line) { for (var i = 0; i < line.length - 1; i++) ROAD_SEGS.push([line[i], line[i + 1]]); });
  function roadClear(x, z, lotR) {
    // THE ROAD'S VERGE (2026-10-13, on the King's report): no lot may reach
    // the carriageway — a home is sited only when its whole lot circle
    // clears every road segment by the road's half-width plus a verge.
    for (var i = 0; i < ROAD_SEGS.length; i++) {
      var a = ROAD_SEGS[i][0], b = ROAD_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));
      if (Math.hypot(x - (a[0] + dx * t), z - (a[1] + dz * t)) < lotR + 4.6) return false;
    }
    return true;
  }
  /* ================= ROADS — THE ROAD SMITH (2026-10-13) =================
   * The old slab roads are REMOVED on the King's word and every road
   * in the district is built by the Road Smith (roads.js): one
   * station table per road, from which the mesh, the standing, and
   * the road points all read. Homes re-site by the verge law against
   * these very lines; driveways are served from the smith's
   * stations; lamps perch perpendicular to them. The Rim Step
   * demonstration is absorbed into Road B, whose whole length now
   * carries what the pitch proved. */
  var smithRoads = {};
  var apronSamples = [];   // the aprons' ring samples, recorded for the clearance law   // name -> the smith's built road
  function pourSurf(surf, batch, color) {
    if (!surf.pos.length) return;
    var g = new T.BufferGeometry();
    g.setAttribute('position', new T.Float32BufferAttribute(surf.pos, 3));
    g.setAttribute('normal', new T.Float32BufferAttribute(surf.nor, 3));
    batch.add(g, new T.Matrix4(), color);
  }
  function triPush(S, a, b, c) {
    var ux = b[0] - a[0], uy = b[1] - a[1], uz = b[2] - a[2];
    var vx = c[0] - a[0], vy = c[1] - a[1], vz = c[2] - a[2];
    var nx = uy * vz - uz * vy, ny = uz * vx - ux * vz, nz = ux * vy - uy * vx;
    var L = Math.hypot(nx, ny, nz) || 1;
    if (ny < 0) { var t = b; b = c; c = t; nx = -nx; ny = -ny; nz = -nz; }
    S.pos.push(a[0], a[1], a[2], b[0], b[1], b[2], c[0], c[1], c[2]);
    for (var i = 0; i < 3; i++) S.nor.push(nx / L, ny / L, nz / L);
  }
  // a junction APRON: a fan whose rim is stitched to the roads
  // themselves — each rim point takes its height from the nearest
  // stations' own planes (grade along, bank across), the highest
  // claim winning, as the world's standing law also takes the
  // highest — so the apron meets every road on that road's own
  // terms, and its skirts fall to the land. A disc planed from one
  // station is a table wherever the host's own surface curves;
  // an apron stitched to all the roads is a junction.
  function apronAt(x, z, host) {
    var S = { pos: [], nor: [] }, SEG = 20, fr = 7.0, ctr = [x, host.y + 0.03, z];
    var all = [];
    for (var rn in smithRoads) all = all.concat(smithRoads[rn].stations);
    function heightAt(px, pz) {
      var best = null, wsum = 0, ysum = 0;
      for (var q = 0; q < all.length; q++) {
        var s2 = all[q], dx = px - s2.x, dz = pz - s2.z;
        var dd = dx * dx + dz * dz;
        if (dd > 100) continue;
        var y = s2.y + s2.grade * (dx * s2.fx + dz * s2.fz) + Math.tan(s2.bank) * (dx * s2.rx + dz * s2.rz);
        var wgt = 1 / ((dd + 0.5) * (dd + 0.5)); wsum += wgt; ysum += wgt * y;
      }
      best = wsum > 0 ? ysum / wsum : host.y + host.grade * ((px - x) * host.fx + (pz - z) * host.fz) + Math.tan(host.bank) * ((px - x) * host.rx + (pz - z) * host.rz);
      return best + 0.03;
    }
    var rim = [];
    for (var k = 0; k < SEG; k++) { var an = k / SEG * Math.PI * 2, px = x + Math.cos(an) * fr, pz = z + Math.sin(an) * fr; rim.push([px, heightAt(px, pz), pz]); }
    // THE FAIRING OF THE RIM: two passes of a quarter, a half,
    // a quarter around the circle — no single sector is asked
    // to climb the whole braid at once.
    for (var fp = 0; fp < 2; fp++) { var fairs = rim.map(function (r3, ri) { var rp2 = rim[(ri + SEG - 1) % SEG], rn2 = rim[(ri + 1) % SEG]; return [r3[0], rp2[1] * 0.25 + r3[1] * 0.5 + rn2[1] * 0.25, r3[2]]; }); rim = fairs; }
    for (k = 0; k < SEG; k++) {
      var r1 = rim[k], r2 = rim[(k + 1) % SEG];
      triPush(S, ctr, r1, r2);
      standTris.push(ctr[0], ctr[1], ctr[2], r1[0], r1[1], r1[2], r2[0], r2[1], r2[2]);
      var d1 = [r1[0], groundAt(r1[0], r1[2]) - 0.3, r1