<!-- SOLID CITY · part 2636 -->
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[2]], d2 = [r2[0], groundAt(r2[0], r2[2]) - 0.3, r2[2]];
      triPush(S, r1, r2, d2); triPush(S, r1, d2, d1);
    }
    for (var rk = 0; rk < 24; rk++) { var ra = rk / 24 * Math.PI * 2, rpx = x + Math.cos(ra) * 5.5, rpz = z + Math.sin(ra) * 5.5; apronSamples.push([rpx, rpz, heightAt(rpx, rpz)]); }
    pourSurf(S, solid, C.road);
  }
  function buildRoads() {
    var smith = createRoadSmith({ groundAt: groundAt });
    var triBase = standTris.length;   // the clearance law judges the roads' and aprons' triangles
    function buildOne(name, points, furniture, pinY, pinEndY, pinHost, taperStart, taperEnd) {
      var spec = { points: points, width: 7.6, furniture: furniture };
      if (pinY != null) spec.pinStartY = pinY;
      if (pinEndY != null) spec.pinEndY = pinEndY;
      if (pinHost) spec.pinHost = pinHost;
      if (taperStart) spec.taperStart = taperStart;
      if (taperEnd) spec.taperEnd = taperEnd;
      var built = smith.buildRoad(spec);
      pourSurf(built.ribbon, solid, C.road);
      pourSurf(built.skirtL, solid, C.stone); pourSurf(built.skirtR, solid, C.stone);
      pourSurf(built.fans, solid, C.conc);
      if (furniture === 'bench') {
        pourSurf(built.shoL, solid, C.soil); pourSurf(built.shoR, solid, C.soil);
        pourSurf(built.rail, solid, 0x9aa4b5); pourSurf(built.posts, solid, C.stoneDark);
      } else {
        pourSurf(built.curbL, solid, C.stoneDark); pourSurf(built.curbR, solid, C.stoneDark);
        pourSurf(built.walk, solid, C.conc);
        pourSurf(built.goldL, glowB, 0xd8a833); pourSurf(built.goldR, glowB, 0xd8a833);
      }
      for (var i = 0; i < built.standTris.length; i++) standTris.push(built.standTris[i]);
      built.stations.forEach(function (s) { roadPts.push([s.x, s.z]); });
      smithRoads[name] = built;
      return built;
    }
    function surfSt(built, x, z) {
      var best = null, bd = 1e12;
      built.stations.forEach(function (s) { var d = (s.x - x) * (s.x - x) + (s.z - z) * (s.z - z); if (d < bd) { bd = d; best = s; } });
      return best;
    }
    var headIdx = ROAD_DEFS[1].findIndex(function (p) { return p[0] === 915 && p[1] === -1285; });
    // THE HEAD'S HEIGHT IS B2'S OWN: the traverse's natural first
    // height is probed first, and the climb is pinned to ARRIVE at
    // it — the junction pad stands on honest fill so the three
    // roads that meet here meet LEVEL, because the face east of
    // this shoulder forbids the traverse to dive to the climb.
    var probeB2 = smith.buildRoad({ points: ROAD_DEFS[1].slice(headIdx), width: 7.6, furniture: 'bench' });
    var nodeY = probeB2.stations[0].y;
    var bB1 = buildOne('B1', ROAD_DEFS[1].slice(0, headIdx + 1), 'bench', null, nodeY, n