<!-- SOLID CITY · part 3091 -->
z + lz + hz, y0: M.gy + y0, y1: M.gy + y1, roostKeel: true });
  }
}
function collide(ud) { (ud.footprint || []).forEach(function (b) { addBox(b[0], b[1], b[2], b[3], b[6] || 0, b[4], b[5]); }); }
function hyperStop() {
  var H = window.CityHyper; if (!H || !H.pois || H.pois.some(function (p) { return p.id === 'roost-keel'; })) return;
  H.pois.push({ id: 'roost-keel', name: NAME, short: 'ROOST', x: POS.x, z: POS.z, stand: { x: POS.x, z: POS.z + 40 },
    alias: 'keel roost conductor constellation violet quiet platform',
    text: 'Keel\u2019s Roost, west of the Ancestral Roads: a quiet platform where twelve violet lights hang in constellation over small stone plinths. Every drone matters.' });
  if (H.regrid) H.regrid();
}
function watchStop() {
  var W = window.CityWatch, r = W && W.routes && W.routes.grand; if (!r || r._roostKeel) return;
  var orig = r.build; r._roostKeel = true;
  r.build = function () {
    var w = orig.apply(this, arguments), at = Math.min(3, w.length);
    w.splice(at, 0, { x: POS.x - 60, z: POS.z + 60, y: M.gy + 60, v: 90, cap: { cap: 'KEEL\u2019S ROOST', sub: 'quiet platform \u00b7 twelve violet lights \u00b7 west of the roads', say: 'Keel\u2019s Roost: twelve violet lights in constellation, west of the Ancestral Roads.' }, agl: false });
    return w;
  };
}
function load() {
  M.state = 'loading';
  M.gy = sampleGround() + 2;
  var p; try { p = import('/city/roost-keel.js?v=20261011a'); } catch (e) { p = Promise.reject(e); }
  p.then(function (mod) {
    var make = mod.createRoostKeel || mod.default;
    var g = make({ THREE: A.T, position: { x: POS.x, y: M.gy, z: POS.z } });
    A.world.add(g); M.group = g; M.state = 'ready';
    collide(g.userData || {}); hyperStop(); watchStop();
  }).catch(function (e) { M.state = 'failed'; try { console.warn('[city] Keel roost 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' || document.hidden) return;
  var c = A.camera.position, d = Math.hypot(c.x + A.origin.x - POS.x, c.z + A.origin.z - POS.z);
  M.group.visible = d < 6000;
  if (d < 1500 && M.group.userData.update) try { M.group.userData.update(S.t); } catch (e) {}
  if (S.mode === 'walk') {
    var pd = Math.hypot(S.p.x - POS.x, S.p.z - POS.z);
    if (pd < 40 && !M.said) { M.said = true; if (window.CityHyper && CityHyper.narrate) CityHyper.narrate('<b>Keel\u2019s Roost</b>: twelve violet lights hanging in constellation over small stone plinths. Every drone matters.', 8); }
    else if (pd > 150) M.said = false;
  }
}
function radar(g, blip, fl) { if (M.state === 'ready') blip(POS.x, POS.z, '#9a6aff', fl ? 3 : 5, fl ? '' : 'ROOST'); }
window.CityRoostKeel = { update: update, radar: radar, pos: POS, state: function () { return M.state; }, group: function () { return M.group; } };
})();


===== FILE: public/city/roost-keel.js =====
/* SOLID CITY — KEEL'S ROOST (2026-10-11, Builder B)
 * Quiet platform west of the Ancestral Roads. Low walkable stone disc,
 * twelve small violet octahedrons in a loose constellation, each hovering
 * above a small stone plinth, joined by a faint constellation thread.
 * Serene, minimal. Local frame: ground at y = 0. Self-contained ES module.
 *
 *   import { createRoostKeel } from '/city/roost-keel.js';
 *   const g = createRoostKeel({ THREE, position: {x, y, z} });
 *   // g.userData: footprint, update(t)
 */
export function createRoostKeel(o) {
  var T = o.THREE, P = o.position || { x: 0, y: 0, z: 0 };
  var root = new T.Group(); root.name = 'roost-keel'; root.position.set(P.x, P.y, P.z);
  var C = { violet: 0x9a6aff, basalt: 0x141114, stone: 0x1e1a20 };

  // Low stone disc — walkable, no blocker footprint
  var disc = new T.Mesh(new T.CylinderGeometry(9, 9.4, 0.15, 40), new T.MeshLambertMaterial({ color: C.stone }));
  disc.position.y = 0.075; root.add(disc);
  var rim = new T.Mesh(new T.TorusGeometry(9, 0.1, 4, 56), new T.MeshBasicMaterial({ color: C.violet, transparent: true, opacity: 0.7 }));
  rim.rotation.x = Math.PI / 2; rim.position.y = 0.16; root.add(rim);

  // Twelve violet lights in a loose constellation, each over a small plinth
  var spots = [
    [-5.5, -1.5, 1.6], [-3.8, 2.8, 2.2], [-1.2, -3.5, 1.4], [1.5, -1.8, 2.6],
    [3.2, 1.2, 1.8], [5.2, -2.2, 1.5], [-4.5, 4.5, 2.0], [0.5, 4.2, 1.6],
    [2.8, -4.5, 2.3], [-2.2, -0.2, 2.9], [4.8, 3.8, 2.1], [-6.2, 0.8, 2.4]
  ];
  var gemGeo = new T.OctahedronGeometry(0.32, 0);
  var gemMat = new T.MeshBasicMaterial({ color: C.violet });
  var plinthGeo = new T.CylinderGeometry(0.3, 0.42, 0.55, 8);
  var plinthMat = new T.MeshLambertMaterial({ color: C.basalt });
  var gems = [], linePts = [], i, sx, sz, sh;
  for (i = 0; i < spots.length; i++) {
    sx = spots[i][0]; sz = spots[i][1]; sh = spots[i][2];
    var pl = new T.Mesh(plinthGeo, plinthMat); pl.position.set(sx, 0.425, sz); root.add(pl);
    var gm