<!-- SOLID CITY · part 3060 -->
1][0], errZ = dense[dense.length - 1][1] - V[nv - 1][1];
    /* two passes, always: measure the traverse BEFORE touching it.
     * A single pass that reads lengths off points it is already
     * correcting feeds on itself — the weights outrun the total
     * and a two-metre seed error leaves the county (measured:
     * trillion-metre steps from exactly that feedback). */
    var cum = [0];
    for (var di = 1; di < dense.length; di++) cum.push(cum[di - 1] + Math.hypot(dense[di][0] - dense[di - 1][0], dense[di][1] - dense[di - 1][1]));
    var totalLen = cum[cum.length - 1] || 1;
    for (di = 1; di < dense.length; di++) {
      var wgt = cum[di] / totalLen;
      dense[di][0] -= errX * wgt; dense[di][1] -= errZ * wgt;
    }
    dense[dense.length - 1][0] = V[nv - 1][0]; dense[dense.length - 1][1] = V[nv - 1][1];
    /* frequency sampling: close where curvature lives, easy elsewhere */
    var line = [[dense[0][0], dense[0][1]]], head = [dense[0][2]], kap = [dense[0][3]];
    var acc = 0;
    for (di = 1; di < dense.length; di++) {
      acc += Math.hypot(dense[di][0] - dense[di - 1][0], dense[di][1] - dense[di - 1][1]);
      var want = Math.abs(dense[di][3]) > 1 / 60 ? stepCurve : stepStraight;
      if (acc >= want || di === dense.length - 1) { line.push([dense[di][0], dense[di][1]]); head.push(dense[di][2]); kap.push(dense[di][3]); acc = 0; }
    }
    var minR = Infinity;
    for (si = 0; si < sites.length; si++) minR = Math.min(minR, sites[si].R);
    return { line: line, head: head, kap: kap, sites: sites.length, minR: minR };
  }

  /* ---------- buildRoad: the whole craft ---------- */
  function buildRoad(spec) {
    var pts = spec.points, W = spec.width || 7.6, hw = W / 2;
    var stepM = spec.stationStep || (spec.furniture === 'bench' ? 1.25 : 2);
    var gradeCap = spec.gradeCap || 0.38;
    var bankCap = (spec.bankCapDeg || 5) * Math.PI / 180;
    /* THE CORRIDOR FRONT: the alignment is fitted to elements and
     * sampled analytically; the stations inherit exact headings
     * and curvatures from the elements themselves. Frequency: the
     * corridor closes its stations where curvature lives and
     * walks easy on the straights — stepM stays the road's base
     * grain, and curves sample at 1.25 m whatever the base. */
    var aligned = fitAlignment(pts, Math.min(stepM, 1.25), stepM);
    var line = aligned.line;
    /* a fitted chain can still leave two stations close in plan
     * where an arc doubles near itself — merge micro-stations as
     * the spline era taught: no station within 1.2 m of its
     * predecessor (the ends are promises and stay exact). */
    var keptLine = [line[0]], keptHead = [aligned.head[0]], keptKap = [aligned.kap[0]];
    for (var li = 1; li < line.length - 1; li++) {
      var lastK = keptLine[keptLine.length - 1];
      if (Math.hypot(line[li][0] - lastK[0], line[li][1] - lastK[1]) >= 1.2) { keptLine.push(line[li]); keptHead.push(aligned.head[li]); keptKap.push(aligned.kap[li]); }
    }
    keptLine.push(line[line.length - 1]); keptHead.push(aligned.head[aligned.head.length - 1]); keptKap.push(aligned.kap[aligned.kap.length - 1]);
    line = keptLine;
    var fairDev = 0;   // the corridor moves no station after sampling; the name stays for the record books

    var N = line.length;

    /* tangents and headings — ANALYTIC, from the elements */
    var i, st = [];
    for (i = 0; i < N; i++) {
      var hh = keptHead[i];
      var fx = Math.sin(hh), fz = Math.cos(hh);
      st.push({ x: line[i][0], z: line[i][1], fx: fx, fz: fz, rx: fz, rz: -fx, h: hh, ds: 0, kappa: keptKap[i] });
    }
    /* NOTE the right vector: forward (fx, fz) with the city's heading
     * convention (heading = atan2(fx, fz), forward = (sin, cos)) has its
     * right hand at (fz, -fx) in plan — at heading 0 (facing +z) the
     * right is +x: (fz, -fx) = (1, 0). Verified against the factory's
     * own frames before a single triangle was drawn. */
    for (i = 1; i < N; i++) st[i].ds = Math.hypot(st[i].x - st[i - 1].x, st[i].z - st[i - 1].z);
    /* curvature (signed) rides in st.kappa from the alignment:
     * positive = turning toward the right hand, continuous by
     * construction — ramps on the clothoids, constant on the arcs,
     * zero on the straights. No finite differences anywhere. */

    /* THE BENCH (the King's technique, from his photographs of the
     * Waipiʻo road, 2026-10-13): a mountain road is DUG INTO the
     * topography — dirt on ONE side. The uphill edge keys to the land
     * and the cut bank rises above it; the downhill edge carries a
     * shoulder and a guardrail over the drop. Dirt on both sides
     * belongs only to a through-cut where a road pierces a ridge.
     * So: first learn which side is uphill over the road's whole run. */
    var upScore = 0;
    for (i = 0; i < N; i++) {
      var sU = st[i];
      var uRg = groundAt(sU.x + sU.rx * (hw + 1.2), sU.z + sU.rz * (hw + 1.2));
      var uLg = groundAt