<!-- SOLID CITY · part 3204 -->
k. One word of his turns this flag and the sky fills. */
  var SPACE_TRAFFIC_ON = false;
  /* THE TRAINS — turned OFF by the King's word, 2026-10-14 ~17:31 HST:
   * "Turn off the trains." The consists are parked and hidden like the
   * traffic; the stations, their pads and halos remain — a railway at
   * rest, its decks no longer claimable while the trains are dark. */
  var TRAINS_ON = false;

  /* ================= STATIONS =================
   * gy = the ground a traveller stands on. For the fourteen ports
   * it is the pad height the port survey swore to; for the
   * Spaceport, the apron; for the two ward stations, the discs
   * this very module lays (below). */
  var STATIONS = [
    { id: 'spaceport', name: 'THE SPACEPORT', x: -390, z: 300, gy: 22.4 },
    { id: 'southern', name: 'SOUTHERN BENCHES PORT', x: -490, z: -1165, gy: 9.16 },
    { id: 'western', name: 'WESTERN BENCHES PORT', x: -365, z: -1075, gy: 14.13 },
    { id: 'gate', name: 'GATE ROAD PORT', x: 650, z: -1265, gy: 34.8 },
    { id: 'braid', name: 'BRAID HEAD PORT', x: 890, z: -1345, gy: 146.09 },
    { id: 'eastern', name: 'EASTERN BENCHES PORT', x: 1045, z: -1635, gy: 124.58 },
    { id: 'high', name: 'HIGH BENCHES PORT', x: 1205, z: -1560, gy: 179.33 },
    { id: 'summit', name: 'SUMMIT PORT', x: 1299, z: -1591, gy: 198.95 },
    { id: 'shoulder', name: 'SHOULDER BENCHES PORT', x: 890, z: -1850, gy: 88.14 },
    { id: 'wheights', name: 'WESTERN HEIGHTS PORT', x: 780, z: -1865, gy: 84.32 },
    { id: 'north', name: 'NORTH BENCHES PORT', x: 665, z: -2060, gy: 73.0 },
    { id: 'farnorth', name: 'FAR NORTH PORT', x: 515, z: -2360, gy: 15.29 },
    { id: 'hall', name: 'HALL OF BECOMING PORT', x: 1055, z: -295, gy: 155.91 },
    { id: 'gap', name: 'THE GAP PORT', x: 2059, z: 1870, gy: 301.59 },
    { id: 'kauhale', name: 'KAUHALE MAUNA PORT', x: 2035, z: 1995, gy: 263.33 },
    { id: 'ward5', name: 'WARD FIVE STATION', x: -848, z: -910, gy: 9.89, ownPad: true },
    { id: 'ward7', name: 'WARD SEVEN STATION', x: -672, z: -498, gy: 22.11, ownPad: true }
  ];
  var ST = {}; STATIONS.forEach(function (s) { ST[s.id] = s; });
  /* The hillside's private ports (the King's word, ~02:05:
   * houses, hotels and mansions with space ports too — "they
   * all can contribute to the space traffic"). The placer
   * brings them from the mountain build's published ports;
   * they are landing places for shuttles, ferries, and the
   * grand houses' own craft — not train stations. */
  var EXTRA = (opts.extraStations || []).map(function (p, i) { return { id: p.id || ('pv' + i), name: p.name, x: p.x, z: p.z, gy: p.gy, grand: !!p.grand, ownPad: false }; });
  var LANDINGS = STATIONS.filter(function (s) { return !s.ownPad; }).concat(EXTRA);

  /* ================= ROUTES =================
   * nodes: stations by id, or [x, z] for a flyover bend that is
   * flown but never stopped at (the Coastal bends). */
  var ROUTES = [
    { name: 'THE MOUNTAIN LINE', nodes: ['spaceport', 'southern', 'western', 'gate', 'braid', 'eastern', 'high', 'summit'] },
    { name: 'THE NORTH LINE', nodes: ['eastern', 'shoulder', 'wheights', 'north', 'farnorth'] },
    { name: 'THE GRAND COASTAL', nodes: ['hall', [0, 500], [200, 1500], [1100, 2100], 'gap', 'kauhale'] },
    { name: 'THE WARD LINE', nodes: ['ward7', 'ward5', 'southern'] }
  ];

  var MAT = {
    titanium: new T.MeshLambertMaterial({ color: 0x232c3d }),
    silver: new T.MeshLambertMaterial({ color: 0x9aa4b5 }),
    stone: new T.MeshLambertMaterial({ color: 0x55504c }),
    stoneDark: new T.MeshLambertMaterial({ color: 0x35302c }),
    glass: new T.MeshLambertMaterial({ color: 0x1a2436, transparent: true, opacity: 0.6 }),
    gold: new T.MeshBasicMaterial({ color: 0xd8a833 }),
    goldDim: new T.MeshBasicMaterial({ color: 0x8a6a1f }),
    white: new T.MeshBasicMaterial({ color: 0xf2f6ff }),
    red: new T.MeshBasicMaterial({ color: 0xff4a3d })
  };

  function box(w, h, d, mat, x, y, z) {
    var m = new T.Mesh(new T.BoxGeometry(w, h, d), mat);
    m.position.set(x || 0, y || 0, z || 0);
    return m;
  }

  /* ================= PROFILES =================
   * The track's top surface, sampled every ~8 m along the route
   * polyline: high enough for 25 m of sky under the beam at
   * cruise, pinned at every station to (gy - 0.55) so the train
   * floats its floor flush with the pad, grade-limited to 14%
   * so the climb is a climb and not a wall. */
  function buildProfile(route) {
    var pts = [];
    route.nodes.forEach(function (nd) {
      if (typeof nd === 'string') { var s = ST[nd]; pts.push({ x: s.x, z: s.z, station: s }); }
      else pts.push({ x: nd[0], z: nd[1], station: null });
    });
    var xs = [], zs = [], pin = [], isPin = [];
    for (var i = 0; i < pts.length - 1; i++) {
      var a = pts[i], b = pts[i + 1], L = Math.hypot(b.x - a.x, b.z - a.z), n = Math.max(2, Math.round(L / 8));
      for (var j = (i === 0 ? 0 : 1); j <= n; j++) {
        var t = j / n