<!-- SOLID CITY · part 3059 -->
m * 0.92 / Math.max(tanH, 1e-3)));
      var Ls = Math.min(14, Math.max(2.5, 0.55 * R * aD));
      /* THE DEVIATION CAP — the surveyed points on the mountain
       * legs are PATH points, not PIs of an imagined design: a
       * generous arc on a hard turn swings metres inside the
       * vertex, through ground the district has already given to
       * homes. The arc's apex may stand at most ~3 m from the
       * surveyed vertex (the spline's own habit), so R shrinks
       * until the geometry honours it — at a true hairpin the
       * survey's own radius was always small, and the chain
       * degrades to it honestly. */
      var TOL_DEV = 2.0, R_FLOOR = 4.5;
      for (var dv = 0; dv < 6; dv++) {
        if (R <= R_FLOOR) break;   // the cap yields at true hairpins: a civil radius swinging wide beats a crushed kink
        var pShift = Ls * Ls / (24 * R);
        var dev = (R + pShift) * (1 / Math.cos(aD / 2) - 1);
        if (dev <= TOL_DEV) break;
        var scale = Math.max(0.45, TOL_DEV / dev * 0.92);
        R *= scale; Ls *= scale;
        if (R < R_FLOOR) { Ls *= R_FLOOR / R; R = R_FLOOR; }
      }
      function consumed(Rx, Lx) { return (Rx + Lx * Lx / (24 * Rx)) * tanH + Lx / 2 - Math.pow(Lx, 3) / (240 * Rx * Rx); }
      var guard = 0;
      while (consumed(R, Ls) > s3.room && guard++ < 6) { Ls *= 0.6; if (Ls < 1.2) { Ls = 0; break; } }
      if (consumed(R, Ls) > s3.room) { R = Math.max(4.5, s3.room / Math.max(tanH, 1e-3)); Ls = 0; }
      if (Ls > 0 && Ls / R > aD * 0.9) Ls = 0.9 * R * aD;   // the spirals may not eat the arc
      s3.R = R; s3.Ls = Ls; s3.T = consumed(R, Ls);
    }
    /* the element chain, walked forward from the first point */
    var els = [];   // {kind, len, k0, k1, h0} — curvature linear in s for clothoids
    var px = V[0][0], pz = V[0][1], hdg = phi[0];
    function pushLine(toX, toZ) {
      var d = Math.hypot(toX - px, toZ - pz);
      if (d > 0.01) els.push({ kind: 'line', len: d, k0: 0, k1: 0, h0: hdg });
      px = toX; pz = toZ;
    }
    for (si = 0; si < sites.length; si++) {
      var s4 = sites[si], vv = s4.v;
      var inX = V[vv][0] - Math.sin(phi[vv - 1]) * s4.T, inZ = V[vv][1] - Math.cos(phi[vv - 1]) * s4.T;
      pushLine(inX, inZ);
      var sgn = Math.sign(s4.D), kArc = sgn / s4.R;
      if (s4.Ls > 0.01) { els.push({ kind: 'cloth', len: s4.Ls, k0: 0, k1: kArc, h0: hdg }); hdg += kArc * s4.Ls / 2; }
      var arcSweep = s4.D - (s4.Ls > 0.01 ? kArc * s4.Ls : 0);
      if (Math.abs(arcSweep) > 1e-4) { els.push({ kind: 'arc', len: Math.abs(arcSweep) * s4.R, k0: kArc, k1: kArc, h0: hdg }); hdg += arcSweep; }
      if (s4.Ls > 0.01) { els.push({ kind: 'cloth', len: s4.Ls, k0: kArc, k1: 0, h0: hdg }); hdg += kArc * s4.Ls / 2; }
      px = V[vv][0] + Math.sin(phi[vv]) * s4.T; pz = V[vv][1] + Math.cos(phi[vv]) * s4.T;
      // the walker's position after the elements is integrated below; px/pz here only anchor the NEXT tangent's start in exact geometry
    }
    // final tangent to the last surveyed point (exact)
    els.push({ kind: 'line', len: 0, k0: 0, k1: 0, h0: hdg, toEnd: true });
    /* integrate: fine steps, midpoint rule on the analytic heading;
     * the final line element's length is whatever closes the chain */
    var totalEls = els.length;
    // first pass: lengths of all but the closing line
    var dense = [[V[0][0], V[0][1], phi[0], 0]];   // x, z, heading, kappa
    var cx = V[0][0], cz = V[0][1], th = phi[0], sAcc = 0;
    var DT = 0.2;
    for (var ei = 0; ei < totalEls; ei++) {
      var el = els[ei];
      var elLen = el.len;
      if (el.toEnd) {
        // direction is th (== final leg heading); length closes to V[nv-1]
        var ex = V[nv - 1][0] - cx, ez = V[nv - 1][1] - cz;
        elLen = ex * Math.sin(th) + ez * Math.cos(th);
        if (elLen < 0) elLen = 0;
      }
      var steps = Math.max(1, Math.ceil(elLen / DT)), dt = elLen / steps;
      for (var q = 0; q < steps; q++) {
        // heading at the substep's midpoint, from the element's own
        // law: θ(s) = h0 + k0·s + (k1−k0)·s²/(2L) — exact for lines,
        // arcs, and clothoids alike; the midpoint rule on an analytic
        // heading keeps position error at millimetres per element
        var sMid = (q + 0.5) * dt;
        var thMid = el.h0 + el.k0 * sMid + (elLen > 0 ? (el.k1 - el.k0) * sMid * sMid / (2 * elLen) : 0);
        cx += Math.sin(thMid) * dt; cz += Math.cos(thMid) * dt;
        sAcc += dt;
        var sEnd = (q + 1) * dt;
        var thEnd = el.h0 + el.k0 * sEnd + (elLen > 0 ? (el.k1 - el.k0) * sEnd * sEnd / (2 * elLen) : 0);
        var kEnd = el.k0 + (el.k1 - el.k0) * (elLen > 0 ? sEnd / elLen : 0);
        dense.push([cx, cz, thEnd, kEnd]);
        th = thEnd;
      }
    }
    /* the compass rule: distribute the closure error back along
     * the traverse, and set the last point exact — the junction
     * keeps its promise to the centimetre */
    var errX = dense[dense.length - 1][0] - V[nv - 