<!-- SOLID CITY · part 4 -->
ndZ, name]
  plaza: [0, 0, 6, 8, 'Forum Plaza'], book: [-4, 46, -2, 50, 'The King\u2019s Book of Law'], podium: [-6, 60, -3, 65, 'ALL THAT WE CAN DO! podium'],
  sable: [-16, -24, -14, -21, 'SABLE'], obelisk: [0, 22, 7, 30, 'Crest Obelisk'], studio: [430, -170, 422, -167, 'Music Studio Tower'],
  masts: [490, -170, 497, -170, 'Radio masts'], soul: [210, 170, 187, 152, 'Soul Print Tower'], port: [-380, 330, -370, 344, 'Orbital Spaceport'],
  hangar: [-307, 365, -300, 372, 'Hangar'], fallen: [176, 120, 151, 103, 'Fallen Worlds Monument'], sanctuary: [735, 165, 703, 165, 'Provolta\u2019s Sanctuary'],
  university: [1176, 103, 1179, 67, 'Solid City University'],
  'campus-sciences': [-205, -1162, -194, -1101, 'Sciences campus'], 'campus-mathcs': [404, -1109, 382, -1051, 'Mathematics & Computer Science / AI campus'],
  'campus-engineering': [904, -758, 856, -719, 'Engineering & Architecture campus'], 'campus-arts': [1162, -205, 1101, -194, 'Arts & Music campus'],
  'campus-humanities': [1109, 404, 1051, 382, 'Humanities campus'], 'campus-medicine': [758, 904, 719, 856, 'Medicine & Health campus'],
  'campus-social': [205, 1162, 194, 1101, 'Social Sciences, Law & Economics campus'], 'campus-business': [-404, 1109, -382, 1051, 'Business & Communications campus'] };
const ALIAS = { 'book-of-law': 'book', law: 'book', uni: 'university', campus: 'university', soulprint: 'soul', 'soul-print': 'soul', monument: 'fallen',
  provolta: 'sanctuary', forum: 'plaza', home: 'plaza', music: 'studio', spaceport: 'port' };
const ORACLE = { x: 735, z: 165 };
const P = { deps: null, state: {}, presence: new Map(), saveT: null, reg: { t: 0, data: { pilots: {} } }, hits: new Map(), bad: new Map() };

/* ---------- registry + auth ---------- */
function registry() {
  try { const st = fs.statSync(REG); if (st.mtimeMs !== P.reg.t) { const j = JSON.parse(fs.readFileSync(REG, 'utf8')); P.reg = { t: st.mtimeMs, data: j && j.pilots ? j : { pilots: {} } }; } }
  catch (e) { P.reg = { t: 0, data: { pilots: {} } }; }
  return P.reg.data.pilots;
}
function badTry(ip) { const now = Date.now(), a = (P.bad.get(ip) || []).filter(t => now - t < 600e3); a.push(now); P.bad.set(ip, a); return a.length; }
function auth(as, key, ip) {   // -> { id, name, citizen } | { err }
  as = String(as || '').toLowerCase(); key = String(key || '');
  const now = Date.now(); if ((P.bad.get(ip) || []).filter(t => now - t < 600e3).length >= 20) return { err: 'Too many wrong keys from here; wait 10 minutes.', code: 429 };
  const r = registry()[as];
  if (!/^[a-z0-9-]{2,24}$/.test(as) || !r || !/^[A-Za-z0-9_-]{24,80}$/.test(key) || typeof r.sha256 !== 'string') { badTry(ip); return { err: 'This link cannot steer ' + (r ? r.name : 'that character') + ': the pilot key is missing or wrong. You can still watch: /city/see', code: 403 }; }
  const a = Buffer.from(crypto.createHash('sha256').update(key).digest('hex')), b = Buffer.from(r.sha256);
  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) { badTry(ip); return { err: 'This link cannot steer ' + r.name + ': the pilot key is wrong. You can still watch: /city/see', code: 403 }; }
  return { id: as, name: String(r.name || as), citizen: String(r.citizen || as) };
}

/* ---------- state ---------- */
const STATE_FILE = () => path.join((P.deps && P.deps.rootDir) || path.join(__dirname, '..'), 'data', 'city-pilots.json');
function load() { try { const j = JSON.parse(fs.readFileSync(STATE_FILE(), 'utf8')); if (j && typeof j === 'object') P.state = j; } catch (e) {} }
function save() { clearTimeout(P.saveT); P.saveT = setTimeout(() => { fs.writeFile(STATE_FILE(), JSON.stringify(P.state), { mode: 0o640 }, () => {}); }, 1500); }
function get(p) {
  let s = P.state[p.id];
  if (!s) { const pl = PLACES.plaza; s = P.state[p.id] = { id: p.id, name: p.name, citizen: p.citizen, x: pl[2] + 3, z: pl[3] + 2, yaw: 0, pitch: 0.05, mode: 'walk', flight: null, action: 'arrived in Solid City', place: 'plaza', say: null, talk: null, last: 0, seq: 1, near: [] }; }
  s.name = p.name; s.citizen = p.citizen; settle(s); return s;
}
function settle(s) {   // a finished flight lands
  const f = s.flight; if (!f) return s;
  if (Date.now() >= f.t0 + f.dur * 1000) { s.x = f.tx; s.z = f.tz; s.yaw = f.yaw; s.mode = 'ship'; s.flight = null; s.place = f.to; s.action = 'landed at ' + f.name + ' (AI DRIVE)'; s.seq++; save(); }
  return s;
}
function pose(s) {   // where the pilot is right now (mid-flight: interpolated, height above ground)
  settle(s); const f = s.flight;
  if (!f) return { x: s.x, z: s.z, yaw: s.yaw, pitch: s.pitch, mode: s.mode, alt: s.mode === 'ship' ? 0 : 0 };
  const k = Math.max(0, Math.min(1, (Date.now() - f.t0) / (f.dur * 1000))), e = k * k * (3 - 2 * k);
  return { x: f.fx + (f.tx - f.fx) * e, z: f.fz + (f.tz - f.fz) * e, yaw: f.yaw, pitch: 0.12, mode: 'flying', alt: Math.round(14 + 48 * Math.sin(Math.PI * k)), k, eta: Math.max(0, Math.round(f.t0 / 1000 + f.dur - Date.now() / 1000)), to: f.n