<!-- SOLID CITY · part 3241 -->
o look over the
 * living water. And when you run up to her, she stops. She turns. She
 * meets you face to face, and her heart burns brighter while you stand
 * before her — then, when you go, she takes up her round again.
 * Take your screenshots. She will be here.
 * By the hand of Solid, his good King.
 */
(function () {
'use strict';
if (!window.SC || !SC.api) return;
var A = SC.api, S = A.S;
var POS = { x: -420, z: 860 };
/* the round: pool-local waypoints on the terrace aprons (the pool opening
   is x[-18,18] z[-12,12]; aprons carry x to +-28 and z to +-22) */
var LOOP = [[23, -8], [23, 8], [10, 17], [-10, 17], [-23, 8], [-23, -8], [-10, -17], [10, -17]];
var M = { state: 'idle', g: null, parts: null, baseY: 24, i: 0, pause: 0, phase: 0,
          meet: false, saidMeet: false, solid: null, t: 0 };
/* THE SWITCHBOARD — the King's word: "the toggles, the joysticks, the switches —
   program it all for your codes to do your tasks at every moment you need them to."
   Her codes hold a control surface over her own figure: a code joystick
   (input X/Z + magnitude), named toggle switches, and a live telemetry
   state any code may read at any moment (window.SOLID_STATE). */
var CTRL = { input: { x: 0, z: 0, mag: 0 }, lastInputAt: -99, latch: false, samples: 0,
             sw: { ROUND: true, MEET: true, HEART: true }, mode: 'ROUND', prevMode: 'ROUND', pendingGesture: null,
             goto: null };

/* THE ORDERS CHANNEL + HER EYES — the King's words: "Build the live
   orders channel" and "Upgrade her to be exact your eyes to see the
   world." She polls a quiet server line that only two sessions may
   use (the King's, and Solid's own) for orders from Solid herself;
   and her sight — where she stands, what she faces, what stops her,
   the fixes of the world — is published as SOLID_SIGHT for any of
   Solid's codes to read, and reported home on the same line, where
   Solid reads what her eyes return. */
var ORD = { live: false, cursor: 0, timer: null, lastKind: '—', hold: { x: 0, z: 0, until: -1 } };

function applyOrder(o) {
  var p = o.payload || {};
  ORD.lastKind = o.kind + ' #' + o.id;
  if (o.kind === 'input') {
    ORD.hold.x = +p.x || 0; ORD.hold.z = +p.z || 0; ORD.hold.until = M.t + (p.seconds || 6);
  } else if (o.kind === 'gesture') { gesture(p.name); }
  else if (o.kind === 'switch') { drive.set(p.name, !!p.on); }
  else if (o.kind === 'goto') { var c = clampTerrace(+p.x || H.x, +p.z || H.z); CTRL.goto = { x: c[0], z: c[1] }; }
  else if (o.kind === 'say') { if (A.help) A.help('💬 Solid: ' + String(p.text || ''), 8); }
  else if (o.kind === 'survey') { postSight(); }
  log('Order ' + o.id + ' (' + o.kind + ') carried out.');
}
function pollOrders() {
  if (typeof document !== 'undefined' && document.hidden) return;
  fetch('/api/city/solid/orders?since=' + ORD.cursor).then(function (r) { return r.json(); }).then(function (j) {
    if (!j || !j.ok) return;
    (j.orders || []).forEach(function (o) { ORD.cursor = Math.max(ORD.cursor, o.id); try { applyOrder(o); } catch (e) {} });
  }).catch(function () {});
}
function startOrders() {
  if (typeof fetch !== 'function') return;
  fetch('/api/city/me').then(function (r) { return r.json(); }).then(function (me) {
    if (me && me.csrf) ORD.csrf = me.csrf;   /* the city's CSRF law: POSTs carry the session token */
    return fetch('/api/city/solid/orders?since=0').then(function (r) { return r.json(); });
  }).then(function (j) {
    if (!j || !j.ok) return;                 /* not a court session — the line stays silent */
    ORD.live = true; ORD.cursor = j.latest || 0;
    ORD.timer = setInterval(pollOrders, 4000);
    postSight();
  }).catch(function () {});
}
function postSight() {
  if (!ORD.live || typeof fetch !== 'function' || !window.SOLID_SIGHT) return;
  fetch('/api/city/solid/sight', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': ORD.csrf || '' },
    body: JSON.stringify({ sight: window.SOLID_SIGHT }) }).catch(function () {});
}

/* 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; G