<!-- SOLID CITY · part 2194 -->
mode !== 'LOOK') { var want = Math.atan2(-dx, -dz), da = ((want - S.camYaw + Math.PI * 3) % (Math.PI * 2)) - Math.PI; S.camYaw += da * Math.min(1, dt * 2.2); }
  return { vx: dx / d * n.sp, vz: dz / d * n.sp, sp: n.sp };
}
/* ARRIVED toast (2026-10-10): every arrival (AI Drive, radar Go, the AI pilot, tour stops, flights) shows
   'ARRIVED: <place>', logs it in the narration and fires window 'city-arrived' {name} (hyper-auto -> #ai-status). */
var arrEl = null;
function arrived(name, narr) {
  if (!arrEl) { arrEl = document.createElement('div'); arrEl.id = 'hc-arrived'; arrEl.setAttribute('role', 'status'); arrEl.setAttribute('aria-live', 'polite'); (document.getElementById('sc-hud') || document.body).appendChild(arrEl); }
  arrEl.textContent = '\u2713 ARRIVED: ' + name; arrEl.classList.add('show');
  clearTimeout(arrEl._h); arrEl._h = setTimeout(function () { arrEl.classList.remove('show'); }, 3500);
  narrate('<b>ARRIVED:</b> ' + esc(name) + '.' + (narr ? ' ' + narr : ''), narr ? 8 : 5);
  try { dispatchEvent(new CustomEvent('city-arrived', { detail: { name: name } })); } catch (e) {}
}
function arrive() {
  var n = H.nav, p = n.p; H.nav = null; S.ai = null; clearPath();
  S.camYaw = Math.atan2(-(p.x - S.p.x), -(p.z - S.p.z)) || S.camYaw;
  if (H.tour) { tourArrived(p); return; }
  setMode('WALK'); H.armed = false;
  arrived(p.name);
  if (n.onArrive) n.onArrive(); else poiCard(p);
}
function flyTo(t, mode, reason) {
  if (!flying()) return false;
  pushHist();
  if (t.home) { A.startAuto(true); H.flyDrive = { t: t }; setMode(mode || 'AI DRIVE'); narrate('Flying home to the <b>Orbital Spaceport</b>; autopilot will land on the pad. ' + (reason || '') + ' <span class="hc-dim">Move the stick to take over.</span>'); return true; }
  var d = Math.hypot(t.x - S.ship.x, t.z - S.ship.z), alt = t.alt || Math.max(0, A.heightAt(t.x, t.z)) + 600;
  S.mode = 'auto'; H.flyDrive = { t: t };
  S.auto = { phase: 'cruise', tx: t.x, tz: t.z, alt: alt, arrive: Math.min(700, Math.max(250, d * 0.2)), onArrive: function () {
    H.flyDrive = null; setMode('FLIGHT'); H.focus = t;
    arrived(t.name, 'You have the stick. ' + esc(t.text || '')); beacon(t, 6);
  } };
  setMode(mode || 'AI DRIVE');
  narrate('Flying to <b>' + esc(t.name) + '</b>: ' + fmtDist(d) + ', cruising with terrain look-ahead. ' + (reason || '') + ' <span class="hc-dim">Move the stick to take over.</span>');
  return true;
}
function driveTo(p, mode, onArrive) {
  H.focus = p;
  if (flying()) {
    if (p.id === 'port') p = FLY[0];
    if (!FLY.includes(p)) p = { name: p.name, x: p.x, z: p.z, alt: Y + 380, text: p.text };
    return flyTo(p, mode);
  }
  if (S.mode !== 'walk') { narrate('Launch first. AI Drive works on foot and in flight.', 4); return false; }
  if (FLY.includes(p)) {
    if (p.id === 'home') p = P('port');
    else if (p.id === 'city') p = P('plaza');
    else { narrate('<b>' + esc(p.name) + '</b> is a flight destination. Walking you to the Orbital Spaceport: board a ship, LAUNCH, then tap 🤖 again.', 9); return startWalk(P('port'), mode, '', null); }
  }
  return startWalk(p, mode, '', onArrive);
}
function stopAI(silent) {
  var was = !!(H.nav || H.tour || H.flyDrive || H.armed);
  H.nav = null; H.tour = null; H.armed = false; S.ai = null; clearPath();
  if (H.flyDrive) { H.flyDrive = null; if (S.mode === 'auto') { S.mode = 'fly'; S.auto = null; } }
  if (!silent) { setMode(baseMode()); if (was) narrate('AI Drive stopped. You have manual control.', 4); else narrate('Nothing to stop. You already have manual control.', 3); }
}

/* ---------------- TOUR ---------------- */
var TOUR = ['plaza', 'sable', 'forumgate', 'studio', 'port', 'warp'];
function startTour() {
  if (flying()) { narrate('Tours run on foot. Say "fly me to Mauna Kea", or tap 🤖 and pick a landmark.'); return; }
  if (S.mode !== 'walk') return;
  stopAI(true); H.tour = { i: -1, wait: 0 };
  narrate('Starting guided tour. I\u2019ll visit ' + TOUR.length + ' places and explain each one. Move the stick anytime to take over.', 5);
  H.tour.wait = 1.2;
}
function tourNext() {
  var t = H.tour; t.i++;
  if (t.i >= TOUR.length) { H.tour = null; setMode('WALK'); narrate('Tour complete. You\u2019ve seen ' + TOUR.length + ' places. Board a ship at the spaceport to see the islands from the air.', 9); return; }
  var p = P(TOUR[t.i]), tour = t;
  if (!startWalk(p, 'AI DRIVE', 'Stop ' + (t.i + 1) + ' of ' + TOUR.length + ' on the tour.')) { H.tour = null; return; }
  H.tour = tour;
}
function tourArrived(p) {
  setMode('AI DRIVE'); H.focus = p; beacon(p, 4);
  arrived(p.name, esc(p.text || ''));
  H.tour.wait = 6;
}

/* ---------------- FOCUS / SCAN ---------------- */
function focusNearest() {
  var fl = flying(), me = fl ? S.ship : S.p, fx, fz;
  if (fl) { var f = A.shipVectors().f; fx = f.x; fz = f.z; } else { fx = -Math.sin(S.camYaw); fz = -Math.cos(S.camYaw); }
  var fl2 = Math.hypot(fx, fz) || 1; fx /= fl2; fz /= fl2;
  var list = fl ? FLY : POIS, best