<!-- SOLID CITY · part 3440 -->
 for (var i = 0; i < RAYS; i++) {
    var a = i / RAYS * Math.PI * 2, dx = Math.sin(a), dz = -Math.cos(a);
    var stop = stopAt(ox, oz, dx, dz, py);
    var vis = visibleAt(ox, py + 1.6, oz, dx, dz);
    if (stop != null && (!nearest || stop < nearest.d)) nearest = { d: stop, b: bearing(dx, dz) };
    if (stop != null && vis != null) {
      visCount++;
      var gap = vis - stop;
      if (Math.abs(gap) > GAP_TOL) { gaps++; if (!worst || Math.abs(gap) > Math.abs(worst.gap)) worst = { gap: gap, b: bearing(dx, dz), vis: vis, stop: stop }; }
    }
  }
  var stand = A.groundAt ? A.groundAt(ox, oz) : null;
  var fx = fixes(ox, oz, 400);
  var line = 'SURVEY — (' + fmt(ox, 0) + ', ' + fmt(py, 1) + ', ' + fmt(oz, 0) + ') · ground ' + fmt(stand) +
    ' · nearest stop ' + (nearest ? fmt(nearest.d) + ' m ' + compass(nearest.b) : 'none within ' + FAR + ' m') +
    ' · picture vs account: ' + visCount + ' rays compared · ' + gaps + ' gaps > ' + GAP_TOL + ' m' +
    (worst ? ' · worst ' + fmt(worst.gap, 2) + ' m at ' + compass(worst.b) + ' (seen ' + fmt(worst.vis) + ' / stops ' + fmt(worst.stop) + ')' : '');
  var fxLine = 'FIXES — ' + fx.map(function (f) { return f.name + ' ' + fmt(f.d, 0) + ' m ' + compass(f.b); }).join(' · ');
  record(line); record(fxLine);
  C.lastScan = line + '<br>' + fxLine;
  render();
  A.help('📷 Survey taken — ' + (nearest ? 'nearest stop ' + fmt(nearest.d) + ' m ' + compass(nearest.b) : 'open ground') + (gaps ? ' · ' + gaps + ' picture/account gaps found.' : ' · picture and account agree.'), 6);
}
function record(text) {
  C.history.unshift(text); if (C.history.length > 5) C.history.pop();
  A.logBuild({ t: Date.now(), site: 'SURVEY CAMERA', what: text });
  try {
    var r = JSON.parse(localStorage.getItem('solid-survey-records') || '[]');
    r.push({ t: Date.now(), text: text }); localStorage.setItem('solid-survey-records', JSON.stringify(r.slice(-60)));
  } catch (e) {}
}
/* the curb run: width between the stops, sampled while moving */
function curbLoop() {
  if (!C.curb) return;
  var now = performance.now();
  if (now - C.curbLast >= 500) {
    C.curbLast = now;
    var vx = S.p.x - (C.lastPos ? C.lastPos.x : S.p.x), vz = S.p.z - (C.lastPos ? C.lastPos.z : S.p.z);
    var moved = Math.sqrt(vx * vx + vz * vz);
    if (moved > 0.4) {
      C.curbDist += moved;
      var il = 1 / Math.sqrt(vx * vx + vz * vz), px = -vz * il, pz = vx * il;
      var dl = stopAt(S.p.x, S.p.z, px, pz, S.p.y), dr = stopAt(S.p.x, S.p.z, -px, -pz, S.p.y);
      if (dl != null && dr != null && dl < 30 && dr < 30) C.widths.push(dl + dr);
    }
    C.lastPos = { x: S.p.x, z: S.p.z };
    render();
  }
  requestAnimationFrame(curbLoop);
}
function toggleCurb() {
  C.curb = !C.curb;
  if (C.curb) { C.widths = []; C.curbDist = 0; C.curbLast = 0; C.lastPos = { x: S.p.x, z: S.p.z }; requestAnimationFrame(curbLoop); }
  else if (C.widths.length) {
    var mn = Math.min.apply(null, C.widths), sum = 0;
    for (var i = 0; i < C.widths.length; i++) sum += C.widths[i];
    record('INNER DIMENSION — curb run over ' + fmt(C.curbDist, 0) + ' m: width between stops min ' + fmt(mn) + ' m · mean ' + fmt(sum / C.widths.length) + ' m · ' + C.widths.length + ' samples.');
  }
  render();
}
function render() {
  if (!C.body) return;
  var curbLine = C.curb ? '<div style="color:#d8a833">● CURB RUN — ' + fmt(C.curbDist, 0) + ' m · ' + C.widths.length + ' widths' + (C.widths.length ? ' · last ' + fmt(C.widths[C.widths.length - 1]) + ' m' : '') + '</div>' : '';
  C.body.innerHTML =
    '<div style="color:#d8a833;letter-spacing:.12em;font-size:11px">SURVEY CAMERA</div>' +
    '<div style="font-size:12px;opacity:.85">The King\'s instrument of sight: the visible surface, the collision stop, and the standing ground — three distances, and the gaps between them.</div>' +
    (C.lastScan ? '<div style="margin-top:5px">' + C.lastScan + '</div>' : '') + curbLine +
    '<div style="margin-top:6px"><button id="sc-scan" style="background:#d8a833;color:#141a26;border:0;border-radius:8px;padding:7px 12px;font-weight:700">◉ SCAN</button> ' +
    '<button id="sc-curb" style="background:#232c3d;color:#d8a833;border:1px solid #d8a833;border-radius:8px;padding:7px 12px;font-weight:700">' + (C.curb ? '■ END CURB RUN' : '🏃 CURB RUN') + '</button></div>' +
    (C.history.length ? '<div style="margin-top:6px;font-size:11px;opacity:.8">' + C.history.slice(0, 3).join('<br>') + '</div>' : '');
  var b1 = document.getElementById('sc-scan'); if (b1) b1.addEventListener('click', scan);
  var b2 = document.getElementById('sc-curb'); if (b2) b2.addEventListener('click', toggleCurb);
}
function build() {
  var st = document.createElement('style');
  st.textContent = '#sc-chip{position:fixed;left:10px;bottom:54px;z-index:9998;background:rgba(35,44,61,.92);color:#d8a833;border:1px solid #d8a833;border-radius:10px;padding:8px 11px;font:700 12px system-ui}#sc-panel{position:fixed;left:10px;bottom:96px;z-index:9998;width:262px;backgroun