<!-- SOLID CITY · part 2060 -->
both markers now carry footprints —
  // they stood unprotected in the collision law.
  foot.push([-30, 9, 3.6, 1.9, 0, 0.9, -Math.PI / 2 - 0.35]);
  foot.push([-45.5, 0, 3.6, 1.9, 0, 0.9, -Math.PI / 2]);
  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/hall-becoming.js.bak-batten-20261014 =====
/* SOLID CITY — THE HALL OF BECOMING (2026-10-11, Royal Decree city expansion)
 * A place of transformation built from pure mathematics made beautiful.
 * Six chambers sized by Fibonacci (8, 5, 3, 2, 1, 1) set on a golden spiral —
 * each quarter-turn the radius divides by phi. You enter at the largest ring
 * and walk the spiral inward; matter refines as you go: basalt, bronze, copper,
 * dark gold, gold, pale gold — and at the still center, white light.
 * Enter, pass through, emerge changed. No words inside; the light explains.
 * True name: THE HALL OF BECOMING. Seam: THE ENTRANCE.
 * Self-contained ES module. Local frame: +X = east, entrance ring to the west.
 */
var PHI = 1.618033988749895;
function textPlate(T, text) {
  var c = document.createElement('canvas'); c.width = 512; c.height = 128;
  var g = c.getContext('2d');
  g.fillStyle = '#17141a'; g.fillRect(0, 0, 512, 128);
  g.strokeStyle = '#8a6a30'; g.lineWidth = 4; g.strokeRect(8, 8, 496, 112);
  g.fillStyle = '#d8c690'; g.textAlign = 'center'; g.textBaseline = 'middle';
  g.font = 'bold 40px Georgia, serif'; g.fillText(text, 256, 66);
  var t = new T.CanvasTexture(c); t.encoding = T.sRGBEncoding; t.anisotropy = 4; return t;
}
function quietMarker(T, text) {
  var grp = new T.Group();
  var stone = new T.Mesh(new T.BoxGeometry(3.4, 0.5, 1.7),
    new T.MeshLambertMaterial({ color: 0x1e1b22 }));
  stone.position.y = 0.55; stone.rotation.x = -0.5; grp.add(stone);
  var face = new T.Mesh(new T.PlaneGeometry(3.1, 0.78),
    new T.MeshBasicMaterial({ map: textPlate(T, text), transparent: false }));
  face.position.set(0, 0.72, 0.42); face.rotation.x = -0.5; grp.add(face);
  var base = new T.Mesh(new T.BoxGeometry(3.6, 0.25, 1.9),
    new T.MeshLambertMaterial({ color: 0x141218 }));
  base.position.y = 0.12; grp.add(base);
  return grp;
}
export function createHallBecoming(o) {
  var T = o.THREE, P = o.position || { x: 0, y: 0, z: 0 };
  var root = new T.Group(); root.name = 'hall-becoming'; root.position.set(P.x, P.y, P.z);
  var foot = [];
  var stone = new T.MeshLambertMaterial({ color: 0x232028 });
  var slabM = new T.MeshLambertMaterial({ color: 0x2c2833 });
  // the ground the hall stands on
  var platform = new T.Mesh(new T.CylinderGeometry(48, 50, 0.5, 48), stone);
  platform.position.y = -0.05; root.add(platform);
  var rim = new T.Mesh(new T.TorusGeometry(48, 0.5, 8, 64),
    new T.MeshLambertMaterial({ color: 0xd8aa48, emissive: 0x1a0e02 }));
  rim.rotation.x = Math.PI / 2; rim.position.y = 0.25; root.add(rim);
  // Fibonacci chambers on the golden spiral
  var fib = [8, 5, 3, 2, 1, 1];
  var ringCols = [0x1c1a20, 0x6b4a2a, 0x8a4a2a, 0xa67a2a, 0xd8aa48, 0xe8d8a8];
  var discCols = [0x7a3a10, 0xb06a20, 0xd89a30, 0xe8b848, 0xf0d080, 0xfff8e8];
  var rings = [], i;
  var pts = [];
  for (i = 0; i < 6; i++) {
    var hole = fib[i] * 1.9;
    var r = hole / 0.42;
    var th = Math.PI + i * Math.PI / 2;
    pts.push({ x: r * Math.cos(th), z: r * Math.sin(th), hole: hole });
  }
  pts.push({ x: 0, z: 0, hole: 0 }); // the still center, for orientation
  var discs = [];
  for (i = 0; i < 6; i++) {
    (function (idx) {
      var pt = pts[idx], nxt = pts[idx + 1];
      var g = new T.Group();
      g.position.set(pt.x, 0, pt.z);
      g.rotation.y = Math.atan2(nxt.x - pt.x, nxt.z - pt.z);
      var tube = Math.max(0.18, pt.hole * 0.07);
      var ringM = new T.Mesh(new T.TorusGeometry(pt.hole, tube, 10, 40),
        new T.MeshLambertMaterial({ color: ringCols[idx], emissive: 0x0a0602 }));
      ringM.position.y = pt.hole; g.add(ringM);
      var disc = new T.Mesh(new T.CircleGeometry(pt.hole * 0.94, 36),
        new T.MeshBasicMaterial({ color: discCols[idx], transparent: true, opacity: 0.10, side: T.DoubleSide, depthWrite: false }));
      disc.position.y = pt.hole; g.add(disc); discs.push(disc);
      // feet that hold the ring; these alone are solid — the opening stays open
      [-1, 1].forEach(function (s) {
        var f = new T.Mesh(new T.BoxGeometry(tube * 3.2, pt.hole * 0.35 + 0.6, tube * 3.2), stone);
        f.position.set(s * (pt.hole + tube * 0.8), (pt.hole * 0.35 + 0.6) / 2, 0); g.add(f);
      });
      root.add(g); rings.push(g);
      // footprint of the two feet in worl