<!-- SOLID CITY · part 2864 -->
) audio.currentTime = Math.min(audio.duration - 0.5, audio.currentTime + ((d && d.seekOffset) || 10)); msPos(); });
  }
  function msState() { if ('mediaSession' in navigator) try { navigator.mediaSession.playbackState = audio.paused ? 'paused' : 'playing'; } catch (e) {} }
  function msPos() {
    if (!('mediaSession' in navigator) || !navigator.mediaSession.setPositionState) return;
    var d = audio.duration; if (!d || !isFinite(d)) return;
    try { navigator.mediaSession.setPositionState({ duration: d, playbackRate: audio.playbackRate || 1, position: Math.min(d, Math.max(0, audio.currentTime || 0)) }); } catch (e) {}
  }
  function renderBtns() {
    var playing = !audio.paused;
    document.querySelectorAll('.mp-play').forEach(function (b) { b.textContent = playing ? '❚❚' : '▶'; b.setAttribute('aria-label', playing ? 'Pause' : 'Play'); });
    if (el.mini) el.mini.classList.toggle('is-playing', playing);
    if (el.shuf) { el.shuf.classList.toggle('is-on', st.shuffle); el.rep.classList.toggle('is-on', st.repeat !== 'off'); el.rep.textContent = st.repeat === 'one' ? '↻1' : '↻'; el.rep.title = 'Repeat: ' + st.repeat; }
  }
  function open(on) { el.panel.hidden = !on; if (on) { if (!data) load(); else { renderList(); var r = el.list.querySelector('.is-cur'); if (r) r.scrollIntoView({ block: 'center' }); } } }
  function emit() { var s = { title: cur ? cur.title : '', kind: cur ? cur.kind : '', playing: !audio.paused }; listeners.forEach(function (f) { try { f(s); } catch (e) {} }); }

  return {
    mount: function (host) { build(host); renderList(); },
    preload: function () { return load(); },
    /* called inside a user gesture (ENTER THE CITY) — iOS needs this tap */
    gesture: function () {
      ensureCtx();
      if (st.paused) return;
      if (data && cur) playSong(cur, st.t);
      else { load().then(function () { if (cur && !st.paused) playSong(cur, st.t); }); }
    },
    toggle: toggle, next: function () { step(1); }, prev: prev, open: open,
    setCockpit: function (on) { if (el.mini) { el.mini.classList.toggle('is-cockpit', !!on); el.mini.querySelector('.mp-mkind').textContent = on ? 'SHIP AUDIO · CH 1 · ' + (cur ? (KIND[cur.kind] || '') : '') : (cur ? (KIND[cur.kind] || '') + ' · SOLIDBIGISLAND' : 'SOLIDBIGISLAND · TAP TO OPEN'); } },
    setBoost: function (b) { b = Math.max(1, Math.min(1.35, b)); if (Math.abs(b - boost) > 0.01) { boost = b; applyVol(); } if (el.boost) el.boost.hidden = b < 1.04; },
    duck: function (on) { duckF = on ? 0.25 : 1; applyVol(); },
    onChange: function (f) { listeners.push(f); },
    state: function () { return { title: cur ? cur.title : '', kind: cur ? cur.kind : '', playing: !audio.paused, n: cur ? cur.n : 0, t: audio.currentTime, vol: st.vol, songs: data ? data.songs.length : 0, covers: data ? data.covers : null, hiddenCovers: data ? data.hiddenCovers : null, ctx: 'none', element: true, fixedVolume: FIXED_VOL, mediaSession: msHandlers.slice() }; },
    audio: function () { return audio; }
  };
})();


===== FILE: public/city/podium.js =====
/* SOLID CITY: the speaker's podium "ALL THAT WE CAN DO!" (2026-10-10, the King: "Write on a podium All that we can do!").
   WHERE: the Forum Plaza, 14 m from the King's Book of Law and 12 m left of the arrival point, clear of every citizen walking
   line (>= 8.9 m), the arrival-to-Book sightline and the spawn. Gold-engraved plaque; collision; no-build zone (forge-core.js);
   radar "DO!"; Hyper stop "ALL THAT WE CAN DO! podium" (READ); ?to=podium.
   READ opens a portrait-first glass panel built from ONE data file, /city/features.json (only real, working features), plus
   the University course catalog (/city/curriculum.json) and the Beauty Log catalog (/api/beauty?brief=1): three cross-linked tabs.
   Everything is put on screen escaped (textContent / esc). */
(function () {
'use strict';
if (!window.SC || !SC.api) return;
var A = SC.api, T = A.T, S = A.S, Y = A.CITY_Y, curve = A.curve || function (m) { return m; };
var POS = { x: -6, z: 60 }, FACE = Math.atan2(6 - POS.x, 62 - POS.z);   // the lectern faces the arrival point
var READ = { x: POS.x + Math.sin(FACE) * 2.9, z: POS.z + Math.cos(FACE) * 2.9 };
var FEAT_URL = '/city/features.json?v=20261010b', CUR_URL = '/city/curriculum.json';
var D = { state: 'idle', wait: 1.6, feat: null, cur: null, beauty: null, tab: 'features' };
function $(id) { return document.getElementById(id); }
function esc(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]; }); }
function getJSON(u, nc) { return fetch(u, { credentials: 'same-origin', cache: nc ? 'no-store' : 'default' }).then(function (r) { if (!r.ok) throw new Error(u + ' ' + r.status); return r.json(); }); }

/* ---------------- the podium ---------------- */
function Merge() { this.g = []; }
Merge.prototype.add = function (geo, x, y, z, rx, ry, rz) { var g = geo.index ? geo.toNonIn