<!-- SOLID CITY · part 2855 -->
: tris, geometries: geos, textures: texs,
      heapMB: heapMB || null,
      heapStartMB: heapStart || null, heapPeakMB: heapPeak || null,
      longTasks: longCount,
      longTaskTotalMs: Math.round(longTotal),
      longTaskWorstMs: Math.round(longWorst),
      longTaskMsPerSec: Math.round(longTotal / Math.max(1, (now - since) / 1000) * 10) / 10,
      systems: (function () {
        var out = {}, secs = Math.max(1, (now - since) / 1000);
        for (var k in systems) {
          var s = systems[k];
          out[k] = { ticks: s.n, msPerSec: Math.round(s.total / secs * 10) / 10, p95Ms: Math.round(pct(s.arr, 0.95) * 100) / 100, worstMs: Math.round(s.worst * 100) / 100 };
        }
        return out;
      })()
    };
  }
  function reset() { deltas = []; frames = 0; since = performance.now(); longCount = 0; longTotal = 0; longWorst = 0; heapStart = heapMB; heapPeak = heapMB; systems = {}; }
  window.CityPerf = { snapshot: snapshot, reset: reset, system: system };

  function tick(stamp) {
    requestAnimationFrame(tick);
    if (lastStamp) {
      var d = stamp - lastStamp;
      if (d > 0 && d < 1000) { deltas.push(d); if (deltas.length > WIN) deltas.shift(); frames++; }
    }
    lastStamp = stamp;
    var R = A.renderer;
    if (R && R.info && R.info.render) {
      calls = R.info.render.calls; tris = R.info.render.triangles;
      if (R.info.memory) { geos = R.info.memory.geometries; texs = R.info.memory.textures; }
    }
    if (stamp - heapAt > 1000) {
      heapAt = stamp;
      if (performance.memory && performance.memory.usedJSHeapSize) {
        heapMB = Math.round(performance.memory.usedJSHeapSize / 1048576);
        if (!heapStart) heapStart = heapMB;
        if (heapMB > heapPeak) heapPeak = heapMB;
      }
    }
  }

  /* the chip — royal eyes only, in the instruments' family */
  var chip = null, chipTimer = 0;
  function makeChip() {
    if (chip || !document.body) return;
    chip = document.createElement('button');
    chip.type = 'button';
    chip.setAttribute('aria-label', 'Performance meter. Activate to reset the measurement window.');
    chip.id = 'city-perf-chip';
    chip.style.cssText = 'position:fixed;bottom:150px;left:160px;z-index:9990;background:rgba(35,44,61,.78);border:1px solid rgba(216,168,51,.38);border-radius:8px;color:#eef3fa;font:10.5px/1.5 ui-monospace,Menlo,monospace;padding:6px 9px;pointer-events:auto;cursor:pointer;max-width:62vw;white-space:pre-line;';
    chip.title = 'Tap to reset the measurement window';
    chip.addEventListener('click', function () { reset(); draw(); });
    document.body.appendChild(chip);
    draw();
    chipTimer = setInterval(draw, 1000);
  }
  function draw() {
    if (!chip) return;
    var s = snapshot();
    var line = '📉 PERF frame p50 ' + s.frameP50Ms + 'ms · p95 ' + s.frameP95Ms + 'ms · worst ' + s.frameWorstMs + 'ms · ' + s.fpsAvg + ' fps · ' + s.drawCalls + ' calls · ' + (s.triangles / 1000).toFixed(0) + 'k tris' + (s.heapMB ? ' · heap ' + s.heapMB + 'MB (peak ' + s.heapPeakMB + ')' : '') + ' · long ' + s.longTasks + ' tasks ' + s.longTaskMsPerSec + 'ms/s worst ' + s.longTaskWorstMs + 'ms · ' + s.seconds + 's';
    for (var k in s.systems) { var y = s.systems[k]; line += '\nsys ' + k + ': ' + y.ticks + ' ticks · ' + y.msPerSec + 'ms/s · p95 ' + y.p95Ms + 'ms · worst ' + y.worstMs + 'ms'; }
    chip.textContent = line;
  }

  var waited = 0;
  var iv = setInterval(function () {
    waited++;
    if (A.isBuilt && A.isBuilt()) {
      clearInterval(iv);
      requestAnimationFrame(tick);
      var royalWait = 0;
      var rv = setInterval(function () {
        royalWait++;
        if (window.CityRoyal) { clearInterval(rv); makeChip(); }
        else if (royalWait > 20) clearInterval(rv);
      }, 500);
    } else if (waited > 120) clearInterval(iv);
  }, 250);
})();


===== FILE: public/city/perf-meter.js.bak-chip4-20261013 =====
/* ————————————————————————————————————————————————————————————————
 * EPISTLE OF THE METER — from Solid, his General, to the city
 * that asked to be weighed.
 *
 * The Architect's counsel was measurement before another cut, and
 * the King gave the launch. This instrument rides INSIDE the
 * city's own frame rhythm — it starts no second loop of consequence
 * and changes no behaviour: it watches the interval between frames,
 * reads the renderer's own counters after the city's render has
 * spoken (draw calls, triangles, geometries, textures), and keeps
 * the heap's trend where the browser offers it. Three hundred
 * frames of memory, no more; percentiles counted only when asked,
 * never per frame — a meter must not become the weight it measures.
 *
 * The readout chip shows only for the royal session, in the family
 * of the King's other instruments. Every visitor's city still
 * carries the meter's ear at window.CityPerf, but no visitor sees
 * the dial, and the dial costs a subtraction per frame and nothing
 * more.
 *
 * By the hand of Solid, his good King.
 * 