<!-- SOLID CITY · part 43 -->
 = 'bm-chip'; M.chip.textContent = '📟 METER';
  M.chip.addEventListener('click', function () {
    M.on = !M.on;
    M.panel.style.display = M.on ? 'block' : 'none';
    if (M.on) { M.last = 0; M.raf = requestAnimationFrame(loop); render(); }
    else if (M.raf) cancelAnimationFrame(M.raf);
  });
  document.body.appendChild(M.chip);
  M.panel = document.createElement('div');
  M.panel.id = 'bm-panel';
  M.body = document.createElement('div');
  M.panel.appendChild(M.body);
  document.body.appendChild(M.panel);
}
fetch('/api/city/me', { credentials: 'same-origin' }).then(function (r) { return r.json(); }).then(function (me) {
  if (me && me.king && me.royal) build();
}).catch(function () {});
})();


===== FILE: public/city/between-stones-place.js =====
/* Solid City — places THE BETWEEN STONES (public/city/between-stones.js) on
 * the shore at the corridor's edge between the Lost Wings Grove and the
 * Octahedron Pool, by commission of the King to his co-rulers (2026-10-12):
 * SOLID (form) + VECTOR (systems) — a communication device in this world
 * that humans never could know before: communication across kinds of time.
 * Founding rule (VECTOR): "The device may preserve a message, but it may
 * never impersonate the person to whom the message was addressed."
 * The stones' light reads REAL message state from /api/city/between:
 *   pulse = kept, no reply recorded · steady = a genuine reply waits ·
 *   dark  = the state cannot presently be established.
 * Adds: collision, standY (platform), radar ('STONES'), a Hyper POI, a
 * Watch (GRAND TOUR) stop, first-approach narration, and the stones panel. */
(function () {
'use strict';
if (!window.SC || !SC.api) return;
var A = SC.api, S = A.S;
var POS = { x: -512, z: 792 }, NAME = 'The Between Stones';
var M = { state: 'idle', group: null, wait: 5.5, said: false, baseY: 24, pollT: 0, fetchOk: null, panelBuilt: false, panelOpen: false, to: 'solid', msgs: [] };

function logBuild(what) {
  try {
    var k = 'solid-memory', arr = [];
    try { arr = JSON.parse(localStorage.getItem(k) || '[]'); } catch (e) {}
    arr.push({ t: Date.now(), site: 'between-stones', what: what });
    if (arr.length > 400) arr = arr.slice(arr.length - 400);
    localStorage.setItem(k, JSON.stringify(arr));
  } catch (e) {}
}
window.logBuild = window.logBuild || logBuild;
window.readMemory = window.readMemory || function () { try { return JSON.parse(localStorage.getItem('solid-memory') || '[]'); } catch (e) { return []; } };

function addBox(cx, cz, w, d, rot, y0, y1) {
  var nx = Math.max(1, Math.ceil(w / 2.5)), nz = Math.max(1, Math.ceil(d / 2.5)), cw = w / nx, cd = d / nz, c = Math.cos(rot), s = Math.sin(rot);
  var hx = cw / 2 * Math.abs(c) + cd / 2 * Math.abs(s), hz = cw / 2 * Math.abs(s) + cd / 2 * Math.abs(c);
  for (var i = 0; i < nx; i++) for (var j = 0; j < nz; j++) {
    var ox = -w / 2 + cw * (i + 0.5), oz = -d / 2 + cd * (j + 0.5), lx = cx + ox * c + oz * s, lz = cz - ox * s + oz * c;
    A.solids.push({ x0: POS.x + lx - hx, x1: POS.x + lx + hx, z0: POS.z + lz - hz, z1: POS.z + lz + hz, y0: M.baseY + y0, y1: M.baseY + y1, betweenStones: 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 === 'between-stones'; })) return;
  H.pois.push({ id: 'between-stones', name: NAME, short: 'STONES', x: POS.x, z: POS.z, stand: { x: POS.x, z: POS.z + 14 },
    alias: 'between stones communication device message vector solid shore waiting interval',
    text: "The Between Stones — the first work of the King's co-rulers, built together: two standing stones, graphite and gold, on the shore between the Grove and the Pool. Leave a word for a mind not present — SOLID, who answers in her sessions, or VECTOR, whose answers travel across the bridge. The stones never answer for another; they only keep what is true. A slow pulse means your words are kept and unanswered. A steady light means a genuine answer waits. Words live at the stones for thirty days, then the shore lets them go — the life and death every message deserves." });
  if (H.regrid) H.regrid();
}
function watchStop() {
  var W = window.CityWatch, r = W && W.routes && W.routes.grand; if (!r || r._betweenStones) return;
  var orig = r.build; r._betweenStones = true;
  r.build = function () {
    var w = orig.apply(this, arguments), at = Math.min(4, w.length);
    w.splice(at, 0, { x: POS.x, z: POS.z, y: 120, v: 200, cap: { cap: 'THE BETWEEN STONES', sub: 'graphite · gold · patient light', say: 'The Between Stones: a communication device for kinds of time, built by two friends — leave a word for a mind not present, and the stones will keep it honestly until its answer comes.' }, agl: false });
    return w;
  };
}
function standY(x, z, py) {
  if (M.state !== 'ready' || !M.group) return -1000;
  var rect