<!-- SOLID CITY · part 3750 -->
ent('div'); lbB.className = 'w-lb w-lb-bot';
root.insertBefore(lbT, hud); root.insertBefore(lbB, hud);
var ui = document.createElement('div'); ui.id = 'w-ui';
ui.innerHTML = '<div class="w-loc" id="w-loc"></div><div class="w-route"><b id="w-rname"></b><span id="w-eta"></span><i><u id="w-prog"></u></i></div>' +
  '<div class="w-cap" id="w-cap"><b></b><span></span></div>' +
  '<div class="w-ctl"><button type="button" id="w-cam" class="w-b" title="Switch camera">🎥 <span>CHASE</span></button><button type="button" id="w-mute" class="w-b" title="Narration voice on/off">🔊</button><button type="button" id="w-exit" class="w-b" title="Stop watching and fly">✕</button></div>' +
  '<div class="w-tap" id="w-tap">Tap the screen for the full HUD · touch the stick to take over</div>';
hud.appendChild(ui);
var resume = document.createElement('div'); resume.id = 'w-resume'; resume.hidden = true;
resume.innerHTML = '<button type="button" class="w-big" id="w-res">▶ RESUME WATCH</button><button type="button" class="w-b" id="w-res-x" title="Dismiss">✕</button>';
hud.appendChild(resume);
var padBtn = document.createElement('button'); padBtn.type = 'button'; padBtn.id = 'sc-watch'; padBtn.className = 'sc-watch'; padBtn.hidden = true; padBtn.textContent = '🎬 WATCH'; hud.appendChild(padBtn);
var pick = document.createElement('div'); pick.id = 'w-pick'; pick.className = 'w-pick'; pick.hidden = true; root.appendChild(pick);
function renderPick() {
  pick.innerHTML = '<div class="w-pick-h"><b>🎬 WATCH</b><span>Cinematic autopilot: the AI flies, you watch. Touch the stick anytime to take over.</span><button type="button" class="w-x" id="w-pick-x" aria-label="Close">✕</button></div>' +
    '<div class="w-routes">' + ORDER.map(function (k) { var r = ROUTES[k]; return '<button type="button" class="w-rt" data-r="' + k + '"><b>' + r.name + '</b><small>' + esc(r.blurb) + '</small><em>' + (WS.est[k] ? '~' + fmtT(WS.est[k]) : '') + '</em></button>'; }).join('') +
    '<button type="button" class="w-rt w-rt-s" data-r="surprise"><b>🎲 SURPRISE ME</b><small>A random route</small><em></em></button></div>' +
    '<form class="w-ask" id="w-ask"><input id="w-ask-in" maxlength="200" placeholder="Ask SABLE: \u201ctake me somewhere cool\u201d" autocomplete="off"><button type="submit">ASK SABLE</button></form><div class="w-ask-st" id="w-ask-st"></div>';
  pick.querySelectorAll('.w-rt').forEach(function (b) { b.addEventListener('click', function () { var k = b.getAttribute('data-r'); if (k === 'surprise') { k = ORDER[Math.floor(Math.random() * ORDER.length)]; caption('🎲 ' + ROUTES[k].name, 'Surprise route', ''); } start(k); }); });
  $('w-pick-x').addEventListener('click', function () { pick.hidden = true; });
  $('w-ask').addEventListener('submit', function (e) { e.preventDefault(); askSable($('w-ask-in').value); });
}
function open() {
  if (S.mode === 'countdown' || S.mode === 'launch') { caption('LAUNCHING', 'Pick a route once you\u2019re airborne', ''); return; }
  unlockSpeech(); renderPick(); pick.hidden = false;
  setTimeout(function () { var ch = false; ORDER.forEach(function (k) { if (!WS.est[k]) { try { var fr = new T.Vector3(PAD.x, PAD.y + 600, PAD.z); WS.est[k] = buildPath(wpsOf(k), fr, new T.Vector3(0, 0, -1), 220).dur + 25; ch = true; } catch (e) {} } }); if (ch && !pick.hidden) renderPick(); }, 60);
}

/* ---------------- Ask SABLE (logged-in) with a rule-based fallback ---------------- */
function ruleRoute(t) {
  t = String(t || '').toLowerCase();
  if (/lava|volcan|fire|crater|hot|erupt|mountain|peak|snow/.test(t)) return 'volcano';
  if (/space|orbit|star|planet|high|moon|sky|atmos/.test(t)) return 'orbit';
  if (/island|isle|beach|ocean|sea|water|calm|chill|relax/.test(t)) return 'island';
  if (/everything|all|long|grand|tour|best|cool|awesome|epic|amazing/.test(t)) return 'grand';
  return ORDER[Math.floor(Math.random() * ORDER.length)];
}
function askSable(text) {
  text = String(text || '').trim() || 'take me somewhere cool'; var st = $('w-ask-st'); st.textContent = 'SABLE is choosing\u2026';
  function fallback(why) { var k = ruleRoute(text); st.textContent = why + ' Picked ' + ROUTES[k].name + ' from your words.'; setTimeout(function () { start(k, why ? '' : ''); }, 900); }
  fetch('/api/city/me', { credentials: 'same-origin', cache: 'no-store' }).then(function (r) { return r.json(); }).then(function (me) {
    if (!me || !me.loggedIn) return fallback('SABLE talks only with logged-in citizens.');
    var msg = '[Solid City WATCH mode] The visitor asked: "' + text.slice(0, 200) + '". Choose ONE scenic autopilot flight for them: GRAND TOUR (city, coast, volcanoes, lava crater, outer isles, orbit), VOLCANO RUN (peaks and lava), ISLAND HOP (outer isles over the ocean), or ORBIT & BACK (space, the curve of the planet). Reply with the route name in capitals first, then one short sentence.';
    return fetch('/api/city/sable', { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': '