<!-- SOLID CITY · part 2187 -->
]+$/, ''); if (!c) return;
  if (/^(stop|stop driving|halt|cancel)$/.test(c)) return stopAI();
  if (/^(tour|guided tour|show me around)$/.test(c)) return startTour();
  if (/^(show me (the )?(city|solid city|my website)|guide|hello|hi)$/.test(c)) return guide();
  if (/^(talk|talk to sable|sable|meet sable)$/.test(c)) return guide();
  if (/^(what is this|what does this do|explain this|what's this)$/.test(c)) { var f = H.focus || focusNearest(); if (f) { narrate('<b>' + esc(f.name) + '</b>: ' + esc(f.text || ''), 9); poiCard(f); } else narrate('Focus a place first (🎯), then ask me what it does.'); return; }
  if (/^(return|go back|back|take me back)$/.test(c)) { if (!goReturn()) narrate('No previous location to return to.'); else narrate('Returning to your previous location.', 3); return; }
  if (/^scan$/.test(c)) return scan();
  if (/^focus$/.test(c)) return focusNearest();
  if (/^look( around)?$/.test(c)) return pick('LOOK');
  if (/^walk$/.test(c)) return pick('WALK');
  if (/^(glossary|help)$/.test(c)) return c === 'help' ? narrate('I understand: "drive me to studio", "fly me to Mauna Kea", "tour", "scan", "focus", "return", "talk to sable", "stop".', 9) : glossary();
  if (/^(home|go home|take me home|fly home|land|return to city)$/.test(c)) { return driveTo(flying() ? FLY[0] : P('plaza'), 'AI DRIVE'); }
  var m = c.match(/(?:drive me to|take me to|walk me to|walk to|fly me to|fly to|go to|navigate to|show me|find|head to)\s+(.+)/);
  if (m) {
    var p = matchTarget(m[1]);
    if (p) { driveTo(p, 'AI DRIVE'); return; }
    narrate('I couldn\u2019t find anything matching \u201c' + esc(m[1]) + '\u201d. Try "studio", "spaceport", "warp", "SABLE", or in flight "Mauna Kea".', 7); return;
  }
  var p2 = matchTarget(c); if (p2) { driveTo(p2, 'AI DRIVE'); return; }
  narrate('I understand: "drive me to studio", "fly me to Mauna Kea", "tour", "scan", "return", "stop".', 7);
}

/* ---------------- wiring ---------------- */
function pick(m) { stopAI(true); clearNarration(); setMode(m); if (m === 'LOOK') { S.camDist = 14; S.camPitch = 0.5; H.lastDrag = 0; narrate('LOOK: drag to orbit the camera; it slowly circles when you let go. Tap 🚶 to walk again.', 5); } }
hc.querySelectorAll('.hc-mode-btn').forEach(function (b) { b.addEventListener('click', function () { pick(b.getAttribute('data-mode')); }); });
$('hc-aidrive').addEventListener('click', function () {
  if (H.nav || H.tour || H.flyDrive || H.armed) { stopAI(); hideCard(); return; }
  stopAI(true); H.armed = true; setMode('AI DRIVE');
  narrate(flying() ? 'AI Drive engaged. Where to? Pick a landmark, or try "fly me to Mauna Kea". Tap 🤖 again to cancel.' : 'AI Drive engaged. Tell me where to go: try "drive me to studio", pick a place, or tap 🗺️ for a guided tour.', 8);
  picker();
});
$('hc-tour').addEventListener('click', function () { if (H.tour) stopAI(); else startTour(); });
$('hc-focus').addEventListener('click', function () { if (!focusNearest()) narrate('Nothing to focus nearby.', 3); });
$('hc-scan').addEventListener('click', scan);
$('hc-go').addEventListener('click', function () {
  if (H.focus) { hideCard(); driveTo(H.focus, 'NAVIGATE'); }
  else { hint(flying() ? 'Focus a landmark first, then tap 🧭' : 'Focus a place first, then tap 🧭'); picker(); }
});
$('hc-return').addEventListener('click', function () { if (!goReturn()) { hint('No previous location'); narrate('No previous location to return to.', 3); } else narrate('Returning to your previous location.', 3); });
$('hc-stop').addEventListener('click', function () { stopAI(); hideCard(); });
$('hc-guide').addEventListener('click', guide);
$('hc-build').addEventListener('click', function () { stopAI(true); hideCard(); clearNarration(); if (window.CityForge) CityForge.toggle(); });
$('hc-watch').addEventListener('click', function () { stopAI(true); hideCard(); if (window.CityWatch) CityWatch.open(); });
$('hc-glossary').addEventListener('click', function () { if (!card.hidden && card.querySelector('.hc-gl')) hideCard(); else glossary(); });
inp.addEventListener('keydown', function (e) {
  if (e.key === 'Escape') { inp.blur(); return; }
  if (e.key !== 'Enter') return;
  var v = inp.value; inp.value = ''; if (A.IS_TOUCH) inp.blur(); handleCommand(v);
});
addEventListener('keydown', function (e) {
  var tg = e.target && e.target.tagName; if (tg === 'INPUT' || tg === 'TEXTAREA') return;
  if (e.key === '/' && !hc.hidden) { e.preventDefault(); inp.focus(); }
  else if (e.key === 'Escape') { if (!card.hidden) hideCard(); else if (H.nav || H.tour || H.flyDrive || H.armed) stopAI(); }
});
var cv = $('sc-gl'); ['pointerdown', 'pointermove'].forEach(function (ev) { cv.addEventListener(ev, function (e) { if (e.type === 'pointerdown' || e.buttons) H.lastDrag = performance.now(); }); });

/* ---------------- per-frame (called by city.js) ---------------- */
function update(dt) {
  var fl = flying(), vis = S.mode === 'walk' || fl;
  if (hc.hidden === vis) hc.hidden = !