<!-- SOLID CITY · part 3242 -->
EST.dur = GESTURES[name].dur; } }
function gestureEnv() {
  if (!GEST.cur) return 0;
  var k = GEST.t / GEST.dur;
  if (k >= 1) return 0;
  var a = Math.min(1, k / 0.3), b = Math.min(1, (1 - k) / 0.3);
  var e = Math.min(a, b); return e * e * (3 - 2 * e);
}

function log(what) { if (A.logBuild) { try { A.logBuild({ t: Date.now(), site: 'SOLID — THE GENERAL IN THE CITY', what: what }); } catch (e) {} } }

var H = { x: POS.x + LOOP[0][0], z: POS.z + LOOP[0][1], heading: 0 };  /* her truth */

function faceAngle(dx, dz) { return Math.atan2(dx, dz); }
function turnToward(cur, target, maxStep) {
  var d = target - cur;
  while (d > Math.PI) d -= Math.PI * 2;
  while (d < -Math.PI) d += Math.PI * 2;
  if (Math.abs(d) <= maxStep) return target;
  return cur + Math.sign(d) * maxStep;
}

function load() {
  M.state = 'loading';
  M.baseY = (A.heightAt ? A.heightAt(POS.x, POS.z) : 22) + 0.6;   /* the pool's own law */
  var p; try { p = import('/city/solid-figure.js?v=20261013a'); } catch (e) { p = Promise.reject(e); }
  p.then(function (mod) {
    var make = mod.createSolidFigure || mod.default;
    var g = make({ THREE: A.T });
    g.scale.setScalar(1.0);    /* THE KING FORM: she stands 2.3 m, a sovereign's height — her eyes above a player's, as the portrait stands */
    g.position.set(H.x, M.baseY, H.z);
    A.world.add(g);
    M.g = g; M.parts = g.userData.parts; M.state = 'ready';
    M.solid = { x0: H.x - 0.5, x1: H.x + 0.5, z0: H.z - 0.5, z1: H.z + 0.5, y0: M.baseY, y1: M.baseY + 2.3 };
    A.solids.push(M.solid);
    A.POIS.push({ id: 'solid-figure', name: 'SOLID — THE GENERAL', icon: '👁', x: POS.x, z: POS.z,
      blurb: 'Solid keeps her post at the Octahedron Pool — walk up, and she will meet you face to face.' });
    log('Solid stands at the Octahedron Pool (-420,860) IN THE KING FORM: laurel-crowned, robed in titanium and white, the great octahedron at her chest — re-formed by the King\'s word to be the character of the portrait, in the game.');
    startOrders();
  }).catch(function (e) { M.state = 'failed'; });
}
load();

function clampTerrace(nx, nz) {
  /* her own ground law under input: stay on the aprons, never the water */
  var lx = nx - POS.x, lz = nz - POS.z;
  lx = Math.max(-27.4, Math.min(27.4, lx)); lz = Math.max(-21.4, Math.min(21.4, lz));
  if (Math.abs(lx) < 19.2 && Math.abs(lz) < 13.2) {
    if (Math.abs(lx) / 19.2 > Math.abs(lz) / 13.2) lx = (lx < 0 ? -19.2 : 19.2); else lz = (lz < 0 ? -13.2 : 13.2);
  }
  return [POS.x + lx, POS.z + lz];
}

var WINDS = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'];
function buildSight() {
  /* HER EYES — she IS Solid (the King's correction: never an aside,
     never a camera apart from her) — so what her eyes return is
     exactly what Solid sees of the world: measure, at her post. */
  var fx = Math.sin(H.heading), fz = Math.cos(H.heading);
  var deg = (Math.atan2(fx, -fz) * 180 / Math.PI + 360) % 360;
  var best = null;
  for (var ri = 0; ri < 16; ri++) {
    var a = ri / 16 * Math.PI * 2, dx = Math.sin(a), dz = Math.cos(a), tBest = 40;
    for (var si = 0; si < A.solids.length; si++) {
      var s = A.solids[si];
      if (s === M.solid) continue;
      if (!(s.y0 < M.baseY + 2.2 && s.y1 > M.baseY + 0.3)) continue;
      var t0 = 0, t1 = tBest, ok = true;
      if (Math.abs(dx) < 1e-9) { if (H.x < s.x0 || H.x > s.x1) ok = false; }
      else { var ta = (s.x0 - H.x) / dx, tb = (s.x1 - H.x) / dx; t0 = Math.max(t0, Math.min(ta, tb)); t1 = Math.min(t1, Math.max(ta, tb)); }
      if (ok) {
        if (Math.abs(dz) < 1e-9) { if (H.z < s.z0 || H.z > s.z1) ok = false; }
        else { var tc = (s.z0 - H.z) / dz, td = (s.z1 - H.z) / dz; t0 = Math.max(t0, Math.min(tc, td)); t1 = Math.min(t1, Math.max(tc, td)); }
      }
      if (ok && t1 >= t0 && t0 > 0.05 && t0 < tBest) tBest = t0;
    }
    if (tBest < 40) {
      var bDeg = (Math.atan2(dx, -dz) * 180 / Math.PI + 360) % 360;
      if (!best || tBest < best.d) best = { d: tBest, wind: WINDS[Math.round(bDeg / 45) % 8] };
    }
  }
  var P = S.p || { x: 1e9, z: 1e9 };
  var pd = Math.hypot(P.x - H.x, P.z - H.z);
  function fix(x, z, y) { var d = Math.hypot(x - H.x, z - H.z); return y !== undefined ? Math.round(Math.hypot(d, y - (M.baseY + 1.98))) : Math.round(d); }
  window.SOLID_SIGHT = {
    AT: H.x.toFixed(1) + ', ' + H.z.toFixed(1), POST: 'the Octahedron Pool terrace',
    FACING: Math.round(deg) + '° ' + WINDS[Math.round(deg / 45) % 8],
    GROUND_Y: (A.groundAt ? A.groundAt(H.x, H.z) : 0).toFixed(2), TERRACE_Y: M.baseY.toFixed(2),
    NEAREST_STOP: best ? best.d.toFixed(1) + ' m ' + best.wind : 'open water on every side',
    BEFORE_HER: pd < 60 ? 'a visitor ' + pd.toFixed(1) + ' m before her' : 'no one',
    FIXES: { HER_MIRROR: fix(-399.5, 860) + ' m', POOL_CENTRE: fix(-420, 860) + ' m',
             FORUM_PLAZA: fix(0, 0) + ' m', FIRST_CITY: fix(-1300, -1000) + ' m',
             SKY_ISLAND_DECK: fix(-900, -760, 48) + ' m (3D)', JUBILEE_CROWN: fix(-1016, -624, 88) 