<!-- NEW7 — TEST 7 · THE WOVEN CITY · part 440 -->
AME_OF[cl.use] + ' ' + kindCount[cl.use],
    x: cl.x, z: cl.z, w: 92, d: 92, seed: 100 + cl.c * 17 + cl.r * 31,
  };
  if (cl.use === 'tower') {
    const dc = Math.hypot(cl.x, cl.z) / 950;
    reg.peak = Math.min(1, 0.35 + 0.65 * (1 - dc) + rng() * 0.15);
  }
  if (cl.use === 'municipal') reg.sub = cl.sub;
  regions.push(reg);
}

// ---------- streets: the full lattice; two avenues run wider ----------
const streets = [];
for (let k = 0; k <= COLS; k++) { const x = -715 + k * PITCH; streets.push({ a: [x, -605], b: [x, 605], w: x === -55 ? 20 : 14 }); }
for (let k = 0; k <= ROWS; k++) { const z = -605 + k * PITCH; streets.push({ a: [-715, z], b: [715, z], w: z === 55 ? 20 : 14 }); }

// ---------- bus stops, planted proper ----------
// Far-side of intersections, ~330 apart, both directions, on the two
// avenues (A: east-west at z=55; B: north-south at x=-55).
const busStops = [];
for (const ix of [-605, -275, 55, 385]) {
  busStops.push({ x: ix + 14, z: 55 + 13.5, rot: Math.PI, route: 'A', along: ix + 14 });        // eastbound, south side
  busStops.push({ x: ix - 14, z: 55 - 13.5, rot: 0, route: 'A', along: ix - 14 });              // westbound, north side
}
for (const iz of [-495, -165, 165, 495]) {
  busStops.push({ x: -55 + 13.5, z: iz + 14, rot: -Math.PI / 2, route: 'B', along: iz + 14 });  // southbound, east side
  busStops.push({ x: -55 - 13.5, z: iz - 14, rot: Math.PI / 2, route: 'B', along: iz - 14 });   // northbound, west side
}

export const MAP = {
  id: 'new7', name: 'THE WOVEN CITY', sub: 'Test 7 · everything at the seams', size: 1500,
  spawn: { x: -160, z: 55, yaw: Math.PI / 2 },
  fashionQuota: 800,
  water: { rivers: [{ pts: riverPts, width: 40 }], lakes: [] },
  streets, regions, busStops,
  weave: { cols: COLS, rows: ROWS, pitch: PITCH, cells: cells.map(cl => ({ c: cl.c, r: cl.r, use: cl.use, sub: cl.sub || null })) },
};


===== FILE: public/new7/stage.js =====
/* stage.js — THE STAGE for the King's /new2 test (Test 2: the big district).
 *
 * One factory: makeStage(THREE, renderer, opts) -> stage
 *
 * Same stage as Test 1, same laws, retuned for district scale:
 *   1. THE MAP FLOOR   — one large flat apron. In Test 2 the district's
 *      own streets and blocks are built ON this floor by the Citywright;
 *      the floor itself stays quiet: dark, city-neutral ground that
 *      carries the district without arguing with its plan.
 *   2. THE STAND LAYER — an invisible plane 0.02 above the floor. Every
 *      character in the world resolves its standing height through
 *      stage.groundY(x, z). Decorative geometry can dip, tilt or lie;
 *      feet cannot. Nobody falls beneath a floor again.
 *   3. THE CAMERA RIG  — a slow cinematic establishing move that frames
 *      the WHOLE district at once, with hard anti-incursion clamps:
 *      the polar angle and distance are fenced so the view can never
 *      clip inside a building, dive under the floor, or frame the void
 *      past the world edge. The fences scale with the stage, so the
 *      sky view reads the entire district, far edge included.
 *   4. BUILD MEMORY    — Solid's memory ships in every build (the King's
 *      standing law): window.logBuild / window.readMemory on the
 *      localStorage key 'solid-memory'.
 *
 * Self-contained: no assets, no CDN. THREE is handed in by the caller.
 */

'use strict';

/* ------------------------------------------------------------------ */
/* Build memory (the King's law: no map ships without it)              */
/* ------------------------------------------------------------------ */

var MEMORY_KEY = 'solid-memory';
var memoryMirror = [];

function memoryRead() {
  try {
    var raw = window.localStorage.getItem(MEMORY_KEY);
    if (raw) {
      var list = JSON.parse(raw);
      if (Array.isArray(list)) memoryMirror = list;
    }
    /* raw === null: storage is empty or unreachable — the mirror
     * already holds the truth; never let an empty read erase it. */
  } catch (e) { /* storage unavailable — the mirror still holds the log */ }
  return memoryMirror;
}

function memoryLog(site, what) {
  memoryRead();
  memoryMirror.push({ t: Date.now(), site: site, what: what });
  try {
    window.localStorage.setItem(MEMORY_KEY, JSON.stringify(memoryMirror));
  } catch (e) { /* mirror-only logging still counts */ }
}

if (typeof window !== 'undefined' && !window.logBuild) {
  window.logBuild = function (what) { memoryLog('new2', what); };
  window.readMemory = function () { return memoryRead(); };
}

/* ------------------------------------------------------------------ */
/* Small deterministic helper for floor tinting                        */
/* ------------------------------------------------------------------ */

function mulberry32(seed) {
  var a = seed >>> 0;
  return function () {
    a |= 0; a = (a + 0x6D2B79F5) | 0;
    var t = Math.imul(a ^ (a >>> 15), 1 | a);
    t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
 