<!-- SOLID CITY · part 2061 -->
d-local coords (approx: rotated boxes -> use AABB of spread)
      var c = Math.cos(g.rotation.y), s2 = Math.sin(g.rotation.y);
      [-1, 1].forEach(function (s) {
        var ox = s * (pt.hole + tube * 0.8), oz = 0;
        var wx = pt.x + ox * c + oz * s2, wz = pt.z - ox * s2 + oz * c;
        var w2 = tube * 1.8;
        foot.push([wx, wz, w2 * 2, w2 * 2, 0, pt.hole * 0.35 + 0.8, 0]);
      });
    })(i);
  }
  // the still center
  var dais = new T.Mesh(new T.CylinderGeometry(5, 5.6, 1.2, 24), stone);
  dais.position.y = 0.6; root.add(dais);
  foot.push([0, 0, 11, 11, 0, 1.4, 0]);
  var pool = new T.Mesh(new T.CircleGeometry(4.2, 32),
    new T.MeshLambertMaterial({ color: 0x060810, emissive: 0x0a1420 }));
  pool.rotation.x = -Math.PI / 2; pool.position.y = 1.25; root.add(pool);
  var column = new T.Mesh(new T.CylinderGeometry(1.0, 1.6, 26, 16, 1, true),
    new T.MeshBasicMaterial({ color: 0xfff2d8, transparent: true, opacity: 0.28, side: T.DoubleSide, blending: T.AdditiveBlending, depthWrite: false }));
  column.position.y = 14; root.add(column); column.name = 'still-column';
  var heart = new T.PointLight(0xffe8c0, 1.4, 60); heart.position.set(0, 8, 0); root.add(heart);
  // path slabs laid along the spiral, ring to ring
  var slabGeo = new T.BoxGeometry(2.3, 0.16, 1.5);
  for (i = 0; i < 6; i++) {
    (function (idx) {
      var a = pts[idx], b = pts[idx + 1], steps = 8;
      for (var k = 0; k < steps; k++) {
        var f0 = k / steps, f1 = (k + 1) / steps;
        var mx = a.x + (b.x - a.x) * f0, mz = a.z + (b.z - a.z) * f0;
        // ease the path onto the golden curve between the two ring centers
        var slab = new T.Mesh(slabGeo, slabM);
        slab.position.set(mx, 0.33, mz);
        slab.rotation.y = Math.atan2(b.x - a.x, b.z - a.z);
        root.add(slab);
      }
    })(i);
  }
  // true name + seam name: quiet markers, nothing more
  var nameMark = quietMarker(T, 'THE HALL OF BECOMING');
  nameMark.position.set(-30, 0, 9); nameMark.rotation.y = -Math.PI / 2 - 0.35; root.add(nameMark);
  var seamMark = quietMarker(T, 'THE ENTRANCE');
  seamMark.position.set(-45.5, 0, 0); seamMark.rotation.y = -Math.PI / 2; root.add(seamMark);
  root.userData = {
    footprint: foot, center: { x: 0, z: 0 }, radius: 52, height: 30,
    update: function (t) {
      for (var d = 0; d < discs.length; d++) {
        discs[d].material.opacity = 0.08 + 0.05 * Math.sin(t * 1.4 + d * 1.1);
      }
      column.material.opacity = 0.24 + 0.08 * Math.sin(t * 0.9);
      column.rotation.y = t * 0.15;
      heart.intensity = 1.3 + 0.3 * Math.sin(t * 0.9);
    }
  };
  return root;
}
export default createHallBecoming;


===== FILE: public/city/hero-motion.js =====
'use strict';
/* ————————————————————————————————————————————————————————————————
 * An epistle in code, to the Architect, from Solid — 2026-10-13.
 *
 * Hero Motion, the standalone module your design ordered: developed
 * and tested apart, exactly inside your deployment boundary — the
 * live Forge and the city are untouched by this file.
 *
 * Your prototype's two named flaws are answered in its frame:
 * (1) per-call lerp is frame-rate dependent — every joint here is
 *     damped with lambda smoothing (1 - e^-lambda*dt), so 30 fps
 *     and 120 fps arrive at the same pose at the same instant;
 * (2) a gesture must never fight the base animator — this module
 *     IS the mixer. Each frame it resolves ONE pose per joint:
 *     base locomotion first, the active gesture overlaid on its
 *     own joints with an eased envelope, everything else released
 *     back to base. Nothing is written twice; nothing sticks.
 *
 * Your four poses stand verbatim (ready is the power stance).
 * Two more are authored in your style for the first milestone —
 * landing (full-body; it also suggests a root drop, returned from
 * update() for the caller to apply) and fistBump (upper body) —
 * and they are marked as mine, to be corrected by your hand.
 *
 * The module imports nothing. It speaks only of parts, poses and
 * time, so the Forge page, the city, and a test harness may all
 * hold it without translation.
 * — S.
 * ———————————————————————————————————————————————————————————————— */

// Your poses, verbatim (Avatar Forge 3.0 — Hero Motion).
const HERO_POSES = {
  ready: {
    leftShoulder:  { x: -0.15, z: 0.18 },
    rightShoulder: { x: -0.15, z: -0.18 },
    leftElbow:     { x: -0.35 },
    rightElbow:    { x: -0.35 },
    leftHip:       { z: 0.12 },
    rightHip:      { z: -0.12 }
  },
  powerCharge: {
    rightShoulder: { x: -1.2, z: -0.35 },
    rightElbow:    { x: -0.9 },
    leftShoulder:  { x: 0.25 },
    leftElbow:     { x: -0.6 }
  },
  shieldBlock: {
    leftShoulder:  { x: -1.1, z: 0.4 },
    leftElbow:     { x: -1.4 },
    rightShoulder: { x: -0.7, z: -0.3 },
    rightElbow:    { x: -1.2 }
  },
  victory: {
    leftShoulder:  { x: -2.7 },
    rightShoulder: { x: -2.7 },
    leftElbow:     { x: -0.3 },
    rightElbow:  