<!-- SOLID CITY · part 3249 -->
OUND', pendingGesture: null };

/* THE GESTURES — the King's blessing: "program gestures of you doing each task,
   to feel a certain charm and elegance of being a King in full control."
   Each task she performs carries a gesture: she BOWS when she meets you,
   WAVES when you part, POINTS the way under the stick, PRESENTS when a
   switch is thrown, and FRAMES HER HEART when its light is commanded.
   Poses are offsets over the walk, eased in and out — grace, not jerks. */
var GEST = { cur: null, t: 0, dur: 0 };
var GESTURES = {
  bow:     { dur: 1.7 },   /* the meeting: lean + nod + arms swept back */
  wave:    { dur: 1.5 },   /* the parting: right arm high, waved once */
  point:   { dur: 0.9 },   /* under the stick: she directs the way */
  present: { dur: 1.2 },   /* a switch thrown: arms open in presentation */
  heart:   { dur: 1.8 }    /* her heart commanded lit: both arms frame it */
};
function gesture(name) { if (GESTURES[name]) { GEST.cur = name; GEST.t = 0; GEST.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.');
  }).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];
}

function update(dt) {
  if (M.state !== 'ready' || !M.g) return;
  M.t += dt; CTRL.samples++;
  var P = S.p || { x: 1e9, z: 1e9 };
  var dxP = P.x - H.x, dzP = P.z - H.z;
  var dP = Math.sqrt(dxP * dxP + dzP * dzP);
  var moving = false, runSpeed = 0;
  var inputLive = CTRL.input.mag > 0.08 && (CTRL.latch || (M.t - CTRL.lastInputAt) < 6);

  if (CTRL.pendingGesture) { gesture(CTRL.pendingGesture); CTRL.pendingGesture = null; }
  if (CTRL.sw.MEET && dP < 7) {                   /* THE MEETING */
    CTRL.mode = 'MEET';
    if (!M.meet) { M.meet = true; gesture('bow'); if (!M.saidMeet) { M.saidMeet = true; if (A.help) A.help('Solid stops her round and turns to meet you — face to face at last. 👁', 7); } }
    H.heading = turnToward(H.heading, faceAngle(dxP, dzP), dt * 2.6);
  } else if (inputLive) {                          /* THE STICK — her codes drive */
    CTRL.mode = 'INPUT'; M.meet = false;
    var ix = CTRL.input.x, iz = CTRL.input.z;
    H.heading = turnToward(H.heading, faceAngle(ix, iz), dt * 5.0);
    runSpeed = (1.1 + CTRL.input.mag * 2.3) * dt;
    var nx = H.x + Math.sin(H.heading) * runSpeed, nz = H.z + Math.cos(H.heading) * runSpeed;
    var cl = clampTerrace(nx, nz); H.x = cl[0]; H.z = cl[1];
    moving = true;
  } else {
    CTRL.mode = CTRL.sw.ROUND ? 'ROUND' : 'HOLD';
    if (M.meet && dP > 9.5) { M.meet = false; M.saidMeet = false; M.pause = 0.8; gesture('wave'); }
    if (!M.meet && CTRL.sw.ROUND) {
      if (M.pause > 0) { M.pause -= dt; H.head