<!-- SOLID CITY · part 3085 -->
riangles at all, because a
         * vertex spent painting the inside of a hill is a vertex
         * stolen from the frame. The drape's data still walks its
         * full profile (the census reads its drops and meets as
         * before), and standing truth never rode the skirts —
         * feet lose nothing when the inside stops dressing. */
        var SKIRT_BROW = 2;
        for (var dk = 0; dk < Math.min(SKIRT_BROW, pA.length - 1); dk++) {
          quad(sk, pA[dk], pB[dk], pB[dk + 1], pA[dk + 1], [sd * A.rx, sd * A.rz]);
          quad(sk, pB[dk], pA[dk], pA[dk + 1], pB[dk + 1], [sd * A.rx, sd * A.rz]);   // both faces: a bank is read from either side
        }
        /* THE GRASS AMENDMENT (the King's word, minutes later):
         * an invisible inside shows as GAPS, and a gap reads as a
         * bug where a bank reads as a hillside. So the deep drape
         * returns — but as grass, not the full staircase of
         * segments, and the factory pours it with its lawn. The
         * grass itself is no longer emitted here, station by
         * station: THE ONE BLOCK (the King's next word) sweeps it
         * after the run is surveyed — see bankSweep below. */
        var dropA = eA[1] - pA[pA.length - 1][1], riseA = pA[pA.length - 1][1] - eA[1];
        if (sd < 0 && Math.max(dropA, riseA) > stats.maxSkirtL) stats.maxSkirtL = Math.max(dropA, riseA);
        if (sd > 0 && Math.max(dropA, riseA) > stats.maxSkirtR) stats.maxSkirtR = Math.max(dropA, riseA);
        if (sd === upSide) { if (riseA > stats.cutBank) stats.cutBank = riseA; }
        else { if (dropA > stats.bank) stats.bank = dropA; if (!dCache[i].met) stats.bankUnmet++; }
      }
    }
    /* THE ONE BLOCK (the King's design, 2026-10-13 ~22:15):
     * "finding the measurements of the clear area and set it to
     * one block instead of many." The clear area beneath each bank
     * is MEASURED from the drape the survey already walked — the
     * brow point and the foot point at every station — and built
     * as ONE swept grass strip per stretch. A station earns a kept
     * point only where the brow's true line strays more than half
     * a metre from the chord across it, or the stretch runs past
     * 24 stations: a straight bank becomes a few long blocks, a
     * curving bank keeps its points exactly where the land turns.
     * One block instead of many, measured before it is built. */
    function bankSweep(cache, sdSign) {
      var brow = [], foot = [];
      for (var i2 = 0; i2 < N; i2++) {
        var dc = cache[i2];
        if (dc && dc.pts.length - 1 > 2) { brow[i2] = dc.pts[2]; foot[i2] = dc.pts[dc.pts.length - 1]; }
        else { brow[i2] = null; foot[i2] = null; }
      }
      function dev3(p, a, b) {
        var abx = b[0] - a[0], aby = b[1] - a[1], abz = b[2] - a[2];
        var t = ((p[0] - a[0]) * abx + (p[1] - a[1]) * aby + (p[2] - a[2]) * abz) / (abx * abx + aby * aby + abz * abz || 1);
        t = Math.max(0, Math.min(1, t));
        var dx = p[0] - (a[0] + abx * t), dy = p[1] - (a[1] + aby * t), dz = p[2] - (a[2] + abz * t);
        return Math.sqrt(dx * dx + dy * dy + dz * dz);
      }
      var a3 = 0;
      while (a3 < N - 1) {
        if (!brow[a3]) { a3++; continue; }
        var b3 = a3 + 1;
        while (b3 < N - 1) {
          var nb = b3 + 1;
          if (!brow[nb]) break;
          var bad = false;
          for (var m = a3 + 1; m < nb; m++) { if (brow[m] && dev3(brow[m], brow[a3], brow[nb]) > 0.5) { bad = true; break; } }
          if (bad || nb - a3 > 24) break;
          b3 = nb;
        }
        if (brow[b3]) {
          var outw3 = [sdSign * st[a3].rx, sdSign * st[a3].rz];
          quad(bankGrass, brow[a3], brow[b3], foot[b3], foot[a3], outw3);
          quad(bankGrass, brow[b3], brow[a3], foot[a3], foot[b3], outw3);
        }
        a3 = b3;
      }
    }
    /* THE BANK SKIN (the King's order + the Architect's ruling,
     * 2026-10-13 ~23:09): "rebuild the affected road surfaces as
     * continuous, smoothly joined sections." The hairpin census
     * convicted the One Block's long flat chords: honest on straight
     * land, but across falling, turning ground a 30 m flat block
     * detaches from the hillside — it hovers, it gaps, and stacked
     * at a hairpin it reads as the pale pleated sheets in the
     * King's photographs. So the grass now FOLLOWS the drape's own
     * surveyed profile — every step of it, both faces — wherever
     * the land turns or falls (brow or foot straying more than
     * 0.35 m from straight over the coming stations, judged station
     * by station), and keeps the sweep's economy only on stretches
     * proven tame by the same measure. The skin's edge is the
     * drape's own foot, so bank, rail line, and road edge finally
     * describe one continuous section. bankSweep above stands as
     * the record of the ruling it served; the skin succeeds it. */
    function bankSkin(cache, sdSign) {
      var