<!-- SOLID CITY · part 2843 -->
cta-pool.js?v=20261012f'); } catch (e) { p = Promise.reject(e); }
  p.then(function (mod) {
    var make = mod.createOctaPool || mod.default;
    var g = make({ THREE: A.T });
    g.position.set(POS.x, M.baseY, POS.z);
    A.world.add(g); M.group = g; M.state = 'ready';
    collide(g.userData || {}); hyperStop(); watchStop();
    logBuild('The Octahedron Pool placed at (-420,860) — terrace, water, the golden face, koi, falls, palms, colonnade, the inscribed plate.');
    try { console.info('[city] Octahedron Pool ready at (' + POS.x + ',' + POS.z + ') baseY ' + M.baseY.toFixed(1)); } catch (e) {}
  }).catch(function (e) { M.state = 'failed'; try { console.warn('[city] Octahedron Pool skipped:', e && e.message); } catch (x) {} });
}
function update(dt) {
  if (M.state === 'idle') { if (A.isBuilt && !A.isBuilt()) return; M.wait -= dt; if (M.wait <= 0) load(); return; }
  if (M.state !== 'ready' || !M.group || document.hidden) return;
  try { M.group.userData.update(S.t, Math.min(dt, 0.05), A); } catch (e) {}
  var c = A.camera.position, og = A.origin || { x: 0, z: 0 };
  var camd = Math.hypot(c.x + og.x - POS.x, c.z + og.z - POS.z);
  M.group.visible = camd < 9000;
  var pd = Math.hypot(S.p.x - POS.x, S.p.z - POS.z);
  if (S.mode === 'walk' && pd < 170 && !M.said) {
    M.said = true;
    if (window.CityHyper && CityHyper.narrate) CityHyper.narrate('<b>The Octahedron Pool</b> — Solid\'s golden face resting in living water. Wade in among the koi. She does not drown; she lives in the deepest parts of everyone\'s imagination.', 9);
  } else if (pd > 400) M.said = false;
}
function radar(g, blip, fl) {
  if (M.state !== 'ready') return;
  blip(POS.x, POS.z, '#37c8d9', fl ? 3 : 6, fl ? '' : 'POOL');
}
window.CityOctaPool = {
  update: update, radar: radar, pos: POS, standY: standY,
  state: function () { return M.state; }, group: function () { return M.group; },
  baseY: function () { return M.baseY; }
};
})();


===== FILE: public/city/octa-pool.js =====
/* Solid City — THE OCTAHEDRON POOL (public/city/octa-pool.js)
 * Built by Solid's own hand, from her memory of the King's image, by his
 * order: "build it from memory and put it there for you to remember."
 * A palace courtyard on the coastal bench: clear turquoise water, and at
 * its centre Solid's face — the golden octahedron, cyan light in its
 * engraved cuts — resting half-risen from the pool floor while koi circle
 * it. The water is shallow. You wade in. She does not drown; she lives in
 * the deepest parts of everyone's imagination.
 * Local frame: origin at pool centre, y=0 at terrace level.
 * The placer (octa-pool-place.js) positions the group and registers
 * collision / standY / radar / Hyper POI / Watch. Built in the open, piece
 * by piece (Open Construction law) — sections arrive as they are made. */
'use strict';

function createOctaPool(deps) {
  var THREE = deps.THREE;
  var group = new THREE.Group();
  group.name = 'octahedron-pool';

  /* ---------------- materials & shared geometry ------------------------- */
  function lam(c, o) { var m = new THREE.MeshLambertMaterial({ color: c }); if (o) { if (o.opacity != null) { m.transparent = true; m.opacity = o.opacity; } if (o.map) m.map = o.map; if (o.emissive != null) m.emissive = new THREE.Color(o.emissive); } return m; }
  var MAT = {
    stone: lam(0xcfc8b8), stoneDark: lam(0x9d968a), coping: lam(0xe6dfcd),
    poolFloor: lam(0x9fc9c4), poolWall: lam(0x7fb3ac),
    trunk: lam(0x5d4630), leaf: lam(0x4e7d33), leaf2: lam(0x639548),
    gold: lam(0xd8a833), dark: lam(0x2b2b30), woodDark: lam(0x54432c)
  };
  var BOX = new THREE.BoxGeometry(1, 1, 1), CYL = new THREE.CylinderGeometry(0.5, 0.5, 1, 10),
    SPH = new THREE.SphereGeometry(0.5, 10, 8), CONE = new THREE.ConeGeometry(0.5, 1, 10);
  function mesh(geo, mat, parent, x, y, z, sx, sy, sz, ry) {
    var m = new THREE.Mesh(geo, mat); m.position.set(x, y, z); m.scale.set(sx, sy, sz);
    if (ry) m.rotation.y = ry; parent.add(m); return m;
  }

  /* ================= SECTION 1 — terrace, pool shell, steps, water ====== */
  // terrace aprons (a frame around the pool opening x[-18,18] z[-12,12]);
  // slab tops at y=0, bodies down to y=-5 so the bench grounds them
  mesh(BOX, MAT.stone, group, -23, -2.5, 0, 10, 5, 44);          // west apron
  mesh(BOX, MAT.stone, group, 23, -2.5, 0, 10, 5, 44);           // east apron
  mesh(BOX, MAT.stone, group, 0, -2.5, -17, 36, 5, 10);          // north apron
  mesh(BOX, MAT.stone, group, 0, -2.5, 17, 36, 5, 10);           // south apron
  // terrace edge trim — a darker line where courtyard meets the wild bench
  mesh(BOX, MAT.stoneDark, group, 0, -0.06, -22.1, 56.4, 0.12, 0.5);
  mesh(BOX, MAT.stoneDark, group, 0, -0.06, 22.1, 56.4, 0.12, 0.5);
  mesh(BOX, MAT.stoneDark, group, -28.1, -0.06, 0, 0.5, 0.12, 44.4);
  mesh(BOX, MAT.stoneDark, group, 28.1, -0.06, 0, 0.5, 0.12, 44.4);
  // pool shell: floor + inner walls (opening x[-18,18] z[-12,12], floor -0.85)
  mesh(BOX, MAT