<!-- SOLID CITY · part 3214 -->
 - tr.v));
        tr.s += tr.v * dt * tr.dir;
        if ((target.s - tr.s) * tr.dir < 0) tr.s = target.s;
      }
    }
    placeTrain(tr, dt);
  }

  /* ================= SHUTTLES =================
   * Small craft hopping port to port on their own business:
   * climb, cruise, descend, hover a while beside the disc,
   * and away again. The sky's ordinary errands. */
  function buildShuttle() {
    var g = new T.Group();
    var hull = new T.Mesh(new T.SphereGeometry(1.6, 12, 8), MAT.titanium); hull.scale.set(1, 0.55, 2.2); hull.position.y = 0.4; g.add(hull);
    var dome = new T.Mesh(new T.SphereGeometry(0.95, 10, 6), MAT.glass); dome.scale.set(1, 0.6, 1.4); dome.position.set(0, 0.95, 0.7); g.add(dome);
    g.add(box(1.9, 0.14, 3.4, MAT.gold, 0, -0.25, 0));
    g.add(box(0.3, 0.3, 0.3, MAT.white, 0, 0.5, 3.55));
    g.add(box(0.3, 0.3, 0.3, MAT.red, 0, 0.5, -3.55));
    return g;
  }
  var shuttles = [];
  for (var si = 0; si < 3; si++) {
    var sh = { mesh: buildShuttle(), mode: 'hover', t: 2 + si * 5, at: STATIONS[1 + si * 4], from: null, to: null, ph: 0, laneY: 0, x: 0, y: -1000, z: 0, yaw: 0 };
    sh.x = sh.at.x + 14; sh.z = sh.at.z; sh.y = sh.at.gy + 12;
    group.add(sh.mesh); shuttles.push(sh);
  }
  function pickDest(notId) {
    var c = STATIONS.filter(function (s) { return s.id !== notId && !s.ownPad; });
    return c[Math.floor(Math.random() * c.length)];
  }
  function stepShuttle(sh, dt) {
    sh.t -= dt;
    if (sh.mode === 'hover') {
      sh.y = sh.at.gy + 12 + Math.sin(perfNow * 0.9 + sh.x) * 0.3;
      if (sh.t <= 0) { sh.from = sh.at; sh.to = pickDest(sh.at.id); var mx = -1e12; for (var i = 0; i <= 10; i++) { var gx = sh.from.x + (sh.to.x - sh.from.x) * i / 10, gz = sh.from.z + (sh.to.z - sh.from.z) * i / 10, gg = heightAt(gx, gz); if (gg > mx) mx = gg; } sh.laneY = Math.min(398, Math.max(sh.from.gy, sh.to.gy) + 48, mx + 42); sh.mode = 'go'; }
    } else {
      var tx = sh.to.x + 14, tz = sh.to.z, ty = sh.to.gy + 12;
      var dx = tx - sh.x, dz = tz - sh.z, dh = Math.hypot(dx, dz);
      var desY = dh > 90 ? sh.laneY : ty;
      var vy = Math.max(-9, Math.min(9, (desY - sh.y) * 0.8));
      sh.y += vy * dt;
      if (dh > 1) {
        var sp = 36, step = Math.min(dh, sp * dt);
        sh.x += dx / dh * step; sh.z += dz / dh * step;
        var wantYaw = Math.atan2(dx, dz), dy = wantYaw - sh.yaw;
        while (dy > Math.PI) dy -= Math.PI * 2; while (dy < -Math.PI) dy += Math.PI * 2;
        sh.yaw += dy * Math.min(1, dt * 2.2);
      }
      if (dh < 2 && Math.abs(sh.y - ty) < 1.2) { sh.at = sh.to; sh.mode = 'hover'; sh.t = 5 + Math.random() * 6; }
    }
    sh.mesh.position.set(sh.x, sh.y, sh.z);
    sh.mesh.rotation.set(0, sh.yaw, 0);
  }

  /* ================= THE MOTHER SHIP =================
   * She flies really far around the whole mountain: a great
   * ellipse, centre (700,-1400), radii 2600 by 2100, at the
   * height the land beneath her demands — never below 375,
   * climbing to terrain + 120 over the eastern wall, where
   * the land itself stands taller than any lawful ceiling
   * for lesser craft. She is a capital ship; her law is her
   * own. One stately circuit takes her about nine minutes. */
  var mother = (function () {
    var g = new T.Group();
    var hull = new T.Mesh(new T.CylinderGeometry(6, 6, 62, 14), MAT.titanium); hull.rotation.x = Math.PI / 2; g.add(hull);
    var nose = new T.Mesh(new T.SphereGeometry(6, 14, 10), MAT.titanium); nose.scale.set(1, 1, 1.6); nose.position.z = 31; g.add(nose);
    var dome = new T.Mesh(new T.SphereGeometry(4.2, 12, 8), MAT.glass); dome.scale.set(1, 0.55, 1.6); dome.position.set(0, 4.6, 16); g.add(dome);
    var ring = new T.Mesh(new T.TorusGeometry(10.5, 1.1, 10, 28), MAT.silver); ring.position.z = -4; g.add(ring);
    g.add(box(15, 0.7, 9, MAT.gold, 0, -5.4, -18));
    var tail = new T.Mesh(new T.CylinderGeometry(6.8, 3.5, 9, 14), MAT.silver); tail.rotation.x = Math.PI / 2; tail.position.z = -35; g.add(tail);
    var eng = new T.Mesh(new T.CircleGeometry(3.2, 14), MAT.white); eng.position.z = -39.6; eng.rotation.y = Math.PI; g.add(eng);
    var navR = box(0.7, 0.7, 0.7, MAT.red, -10.8, 0, -4), navG = box(0.7, 0.7, 0.7, new T.MeshBasicMaterial({ color: 0x3dff7a }), 10.8, 0, -4);
    g.add(navR); g.add(navG);
    group.add(g);
    return { mesh: g, ring: ring, navR: navR, navG: navG, a: 0, x: 0, y: 380, z: 0, vx: 0, vz: 0, yaw: 0 };
  })();
  var MOTHER = { cx: 700, cz: -1400, rx: 2600, rz: 2100, w: (Math.PI * 2) / 540 };
  function stepMother(dt) {
    mother.a += MOTHER.w * dt;
    var nx = MOTHER.cx + Math.cos(mother.a) * MOTHER.rx, nz = MOTHER.cz + Math.sin(mother.a) * MOTHER.rz;
    mother.vx = (nx - mother.x) / Math.max(dt, 0.001); mother.vz = (nz - mother.z) / Math.max(dt, 0.001);
    mother.x = nx; mother.z = nz;
    var need = 375;
    for (var i = 0; i <= 6; i++) { var aa = mother.a + i * 0.012, gx = MOTHER.cx + Math.cos(aa) * MOTHER.rx, gz = MOTHER.cz + Math.sin(aa) * MOTHE