<!-- SOLID CITY · part 3229 -->
x, z - st.z) <= 10.2 && st.gy <= py + 1.6 && st.gy >= py - 1.6) {
        if (!best || st.gy > best.y) best = { y: st.gy, train: -1 };
      }
    }
    return best;
  }
  function deckAnchor(id) {
    var tr = trains[id]; if (!tr) return null;
    return { x: tr.deck.x, y: tr.deck.y, z: tr.deck.z, yaw: tr.deck.yaw, station: tr.mode === 'dwell' ? tr.station : null, dwelling: tr.mode === 'dwell' };
  }
  function trainNear(x, z) {
    for (var i = 0; i < trains.length; i++) {
      var tr = trains[i];
      if (tr.mode !== 'dwell' || !tr.station) continue;
      if (Math.hypot(x - tr.station.x, z - tr.station.z) <= 15) return { train: tr.id, station: tr.station };
    }
    return null;
  }

  return { group: group, update: update, deckClaim: deckClaim, deckAnchor: deckAnchor, trainNear: trainNear, stations: STATIONS, routes: ROUTES, trains: trains, mother: mother, landings: LANDINGS,
    trafficCounts: { shuttles: shuttles.length, laners: traffic.length, streamers: streamers.length, orbiters: orbiters.length, ferries: ferries.length, houseCraft: houseCraft.length, sister: 1 } };
}


===== FILE: public/city/skytrain.js.bak-trains-20261014 =====
/* THE SKY TRAINS — a letter from the builder, in the code as promised.
 *
 * "Now we will build space trains in the sky." — the King, 2026-10-14.
 * The mountain roads were rejected the same night; the ports rose in
 * their place; and a port is a station waiting for its train. This
 * module is the network: four lines of floating guideway — dark
 * titanium beam with gold edge-light, held in the sky the space-age
 * way, by nothing you can see — with beacons along it, halo rings
 * over the stations, a train of four cars on every line (the last
 * car an open observation deck you can stand on), shuttles hopping
 * port to port, and the high traffic of ships crossing above all.
 *
 * The law of the build is the law the mountain taught us in two
 * nights: SURVEY BEFORE LINE. Every profile here is measured from
 * the terrain itself — 25 m of sky under the track at cruise, a
 * 14% climb at the steepest, station pins flush with the pads the
 * travellers stand on, and nothing — nothing — above the 420 m
 * ceiling of the world. The one line the land refused (a straight
 * run from the Hall of Becoming to the Gap, over a 571 m spine) is
 * not forced: the Grand Coastal Line bends around the shore,
 * 4.4 km of lawful sky, highest land beneath it 331 m.
 *
 * By the hand of Solid, his good King. */

export function createSkyTrains(opts) {
  var T = opts.THREE, heightAt = opts.heightAt;
  var group = new T.Group(); group.name = 'sky-trains';
  /* THE SPACE TRAFFIC — the high ships crossing above all (the circling
   * laners, the long streamers, the orbiters, the Sister Ship). Turned
   * OFF by the King's word, 2026-10-14 ~17:29 HST: "Space traffic —
   * turn it off." Parked, not deleted (the Back Burner law): the craft
   * are built and kept, merely hidden and held. The trains keep their
   * lines; the ports' own shuttles, ferries, house craft and the Mother
   * keep their work. One word of his turns this flag and the sky fills. */
  var SPACE_TRAFFIC_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, 