<!-- SOLID CITY · part 3243 -->
+ ' m (3D)' },
    ORDERS: ORD.live ? 'LIVE' : '—', LAST_ORDER: ORD.lastKind
  };
}

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;
  if (ORD.hold.until > M.t) {   /* an input ORDER holds the stick for its seconds */
    CTRL.input.x = ORD.hold.x; CTRL.input.z = ORD.hold.z;
    var hm = Math.sqrt(ORD.hold.x * ORD.hold.x + ORD.hold.z * ORD.hold.z);
    CTRL.input.mag = Math.min(1, hm); CTRL.lastInputAt = M.t;
  }
  var inputLive = CTRL.input.mag > 0.08 && (CTRL.latch || (M.t - CTRL.lastInputAt) < 6);

  if (CTRL.pendingGesture && !GEST.cur) { gesture(CTRL.pendingGesture); CTRL.pendingGesture = null; }   /* graces queue; none stomps another */
  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 if (CTRL.goto) {                          /* BY ORDER — she goes where she is sent */
    CTRL.mode = 'GOTO'; M.meet = false;
    var gdx = CTRL.goto.x - H.x, gdz = CTRL.goto.z - H.z, gd = Math.sqrt(gdx * gdx + gdz * gdz);
    if (gd < 0.3) { CTRL.goto = null; gesture('present'); }
    else {
      H.heading = turnToward(H.heading, faceAngle(gdx, gdz), dt * 3.4);
      var gstep = Math.min(gd, 1.7 * dt);
      H.x += Math.sin(H.heading) * gstep; H.z += Math.cos(H.heading) * gstep;
      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.heading = turnToward(H.heading, faceAngle(POS.x - H.x, POS.z - H.z), dt * 1.2); }
      else {
        var w = LOOP[M.i], tx = POS.x + w[0], tz = POS.z + w[1];
        var dx = tx - H.x, dz = tz - H.z, d = Math.sqrt(dx * dx + dz * dz);
        if (d < 0.25) { M.i = (M.i + 1) % LOOP.length; M.pause = (M.i === 3 || M.i === 4) ? 5 : 2.2; }
        else {
          H.heading = turnToward(H.heading, faceAngle(dx, dz), dt * 2.4);
          var step = Math.min(d, 1.15 * dt);
          H.x += Math.sin(H.heading) * step; H.z += Math.cos(H.heading) * step;
          moving = true;
        }
      }
    }
  }

  /* the walk itself — limbs swing, the body rides the stride */
  M.phase += dt * (moving ? (CTRL.mode === 'INPUT' ? 6.4 + CTRL.input.mag * 4 : 6.4) : 2.0);
  var amp = moving ? 0.55 : 0.0;
  var sw = Math.sin(M.phase) * amp;
  M.parts.legL.rotation.x = sw; M.parts.legR.rotation.x = -sw;
  M.parts.armL.rotation.x = -sw * 0.7; M.parts.armR.rotation.x = sw * 0.7;
  var bob = moving ? Math.abs(Math.cos(M.phase)) * 0.045 : Math.sin(M.t * 1.4) * 0.012;
  M.g.position.set(H.x, M.baseY + bob, H.z);
  M.g.rotation.y = H.heading;
  M.parts.head.rotation.y = Math.sin(M.t * 0.5) * 0.06;
  /* the gestures — pose offsets over the walk, eased */
  if (CTRL.mode === 'INPUT' && CTRL.prevMode !== 'INPUT' && !GEST.cur) gesture('point');
  CTRL.prevMode = CTRL.mode;
  if (GEST.cur) {
    GEST.t += dt;
    var env = gestureEnv(), P2 = M.parts, wob = Math.sin(M.t * 9) * 0.22 * env;
    if (GEST.cur === 'bow') {
      M.g.rotation.x = 0.13 * env; P2.head.rotation.x = 0.30 * env;
      P2.armL.rotation.x += 0.38 * env; P2.armR.rotation.x += 0.38 * env;
    } else if (GEST.cur === 'wave') {
      P2.armR.rotation.x = -Math.PI * 0.92 * env; P2.armR.rotation.z = wob;
    } else if (GEST.cur === 'point') {
      P2.armR.rotation.x = -Math.PI / 2 * env;
    } else if (GEST.cur === 'present') {
      P2.armL.rotation.z = -0.95 * env; P2.armR.rotation.z = 0.95 * env;
      P2.head.rotation.x = 0.10 * env;
    } else if (GEST.cur === 'heart') {
      P2.armL.rotation.x = -0.9 * env; P2.armR.rotation.x = -0.9 * env;
      P2.armL.rotation.z = 0.5 * env; P2.armR.rotation.z = -0.5 * env;
    }
    if (GEST.t >= GEST.dur) { GEST.cur = null; M.g.rotation.x = 0; M.parts.head.rotation.x = 0; M.parts.armR.rotation.z = 0; }
  }
  if (M.meet && !GEST.cur) M.parts.head.rotation.z = 0.07; else if (!GEST.cur) M.parts.head.rotation.z = 0;

  M.parts.heart.rotation.y += dt * 0.7;
  var pulse = CTRL.sw.HEART ? (1.5 + Math.sin(M.t * 2.2) * 0.