<!-- SOLID CITY · part 1989 -->
 e.craft = def.makeState(core, { x: def.home.x, y: ry + def.homeLift + def.clr, z: def.home.z }, e.park.yaw);
      e.clock = core.createCraftClock(def.stepper(core), e.craft, M.world);
      addSolid(e);
      M.crafts.push(e);
      if (A.POIS) A.POIS.push({ id: 'fleet-' + def.key, name: 'THE ' + def.name, icon: def.icon, x: def.home.x, z: def.home.z,
        blurb: def.key === 'board'
          ? 'The first of the futuristic fleet: a hover board on the spaceport apron, riding the surveyed fabric of the city. She feeds herself under 6 m/s, carves with the stick, and hops. Downhill is free speed.'
          : 'The bicycle\u2019s heir: a stand-up space rider on VECTOR\u2019s controller. Pedal her toward 9 m/s; she leans into her turns by bicycle law \u2014 the front assembly steering into the fall.',
        arrive: 'You stand at the fleet racks. The machines hum over their plinths, waiting.' });
    });
    A.world.add(group);
    A.logBuild({ t: Date.now(), site: 'THE FLEET — ORBITAL SPACEPORT', what: 'The futuristic fleet racks at the spaceport apron: the HOVER BOARD (-340, 292) and the SPACE RIDER (-333, 292), both on VECTOR\u2019s controllers over the city\u2019s standing fabric, under Rung 2\u2019s door law. The ground ride\u2019s law already pilots THE DART; the ship will follow last, with her flight-state machine.' });
    M.state = 'ready';
  }).catch(function (err) { M.state = 'failed'; try { console.warn('[city] Fleet skipped:', err && err.message); } catch (x) {} });
}
function hopButton() {
  if (M.hopBtn) return M.hopBtn;
  var b = document.createElement('button');
  b.textContent = 'HOP ⬆';
  b.style.cssText = 'position:fixed;left:50%;bottom:212px;transform:translateX(-50%);z-index:60;display:none;padding:12px 22px;border-radius:24px;border:2px solid #d8aa48;background:rgba(12,14,20,0.88);color:#ffd873;font:700 15px Georgia,serif;letter-spacing:1px;';
  b.addEventListener('pointerdown', function (ev) { ev.preventDefault(); M.jumpQ = true; });
  document.body.appendChild(b);
  M.hopBtn = b;
  return b;
}
function nearestParked(x, z) {
  var best = null, bd = 3.4;
  M.crafts.forEach(function (e) {
    if (M.active === e) return;
    var d = Math.hypot(x - e.park.x, z - e.park.z);
    if (d < bd) { bd = d; best = e; }
  });
  return best;
}
function actHere(x, z) {
  if (M.active) return { kind: 'fleet', label: 'STEP OFF THE ' + M.active.name };
  if (M.state !== 'ready') return null;
  var e = nearestParked(x, z);
  if (e) return { kind: 'fleet', label: e.icon + ' RIDE THE ' + e.name };
  return null;
}
function act() {
  if (M.active) { stepOff(M.active); return; }
  if (M.state !== 'ready') return;
  var e = nearestParked(S.p.x, S.p.z);
  if (!e || Math.hypot(S.p.x - e.park.x, S.p.z - e.park.z) > 3.6) return;
  /* ADMISSION FIRST (the Rung 2 law): the ride begins, THEN the parked solid lifts. */
  e.craft.pos.x = e.park.x; e.craft.pos.z = e.park.z;
  e.craft.pos.y = supportHere(e.park.x, e.park.z) + e.clr;
  e.craft.yaw = e.park.yaw; e.craft.mode = 'RIDE';
  if ('vx' in e.craft) { e.craft.vx = 0; e.craft.vz = 0; e.craft.vy = 0; }
  if ('v' in e.craft) { e.craft.v = 0; e.craft.vy = 0; e.craft.lean = 0; e.craft.leanRate = 0; }
  M.active = e;
  removeSolid(e);
  hopButton();
  A.help(e.mountHelp, 9);
}
function stepOff(e) {
  var c = e.craft; if (!c) return;
  var rx = Math.cos(c.yaw), rz = -Math.sin(c.yaw); // the craft's right hand
  var sides = [[-rx, -rz], [rx, rz]];              // left first — the city's habit
  for (var i = 0; i < 2; i++) {
    var tx = c.pos.x + sides[i][0] * 1.15, tz = c.pos.z + sides[i][1] * 1.15;
    var gy = A.standingAt(tx, tz, c.pos.y);
    if (!isFinite(gy) || gy < c.pos.y - e.clr - 1.2 || gy > c.pos.y + 1.6) continue;
    var blocked = false;
    for (var k = 0; k < A.solids.length; k++) {
      var s = A.solids[k];
      if (gy + 1 < s.y0 - 0.5 || gy + 1 > s.y1) continue;
      if (tx > s.x0 - 0.45 && tx < s.x1 + 0.45 && tz > s.z0 - 0.45 && tz < s.z1 + 0.45) { blocked = true; break; }
    }
    if (blocked) continue;
    S.p.x = tx; S.p.z = tz; S.p.y = gy;
    e.park.x = c.pos.x; e.park.z = c.pos.z; e.park.yaw = c.yaw;
    M.active = null;
    addSolid(e);
    if (M.hopBtn) M.hopBtn.style.display = 'none';
    A.help('You step off. The ' + e.name.toLowerCase() + ' waits where you left her.', 5);
    return;
  }
  A.help('No room to step off here — ride somewhere clearer.', 5);
}
function active() { return !!M.active; }
function stepDrive(dt) {
  var e = M.active;
  if (!e || !e.clock) return;
  var inp = A.input || {}, k = inp.keys || {};
  var sx = inp.sx || 0, sy = inp.sy || 0;
  if (k.KeyW || k.ArrowUp) sy -= 1; if (k.KeyS || k.ArrowDown) sy += 1;
  if (k.KeyA || k.ArrowLeft) sx -= 1; if (k.KeyD || k.ArrowRight) sx += 1;
  sx = Math.max(-1, Math.min(1, sx)); sy = Math.max(-1, Math.min(1, sy));
  var jump = M.jumpQ || !!k.Space; M.jumpQ = false;
  e.clock(dt, { x: -sx, y: -sy, jump: jump });
  var c = e.craft;
  S.p.x = c.pos.