
Evidence
Every number below came out of Playwright/Chromium launched with --use-gl=swiftshader --enable-unsafe-swiftshader. Headless has no GPU, so every timing is a lower bound on performance: software GL is roughly 10× slower than any real device.
Harness: the stratum's own HTML/CSS/JS mounted over the built <style> block lifted from canon.BEFORE.html, so the real Geist and Departure faces and the real token layer are in play. Run at 1440×900 and 390×844, plus a reducedMotion: 'reduce' context.
Compiles clean
Fragment and vertex shader compile, program links, and all three info logs are empty strings — not merely "no error flag". All six uniforms bind: u_res u_time u_mouse u_hover u_pitch u_rings.
Console
Zero page errors and zero console errors at 1440×900, at 390×844, and under reduced motion. (The only console output at all was four Chromium GPU stall due to ReadPixels performance warnings, emitted by the test harness's own readPixels calls, not by the stratum.)
Frame cost — measured, and it is the whole design argument
drawArrays followed by a 1-pixel readPixels to force the pipeline to finish, 24 frames, p50/p90:
| buffer | fragments | p50 | p90 |
|---|---|---|---|
| desktop stage, one fragment per cell (195×117) | 22,815 | 5.9 ms | 6.6 ms |
| mobile stage, one fragment per cell (68×75) | 5,100 | 1.6 ms | 1.7 ms |
| the same shader at 1:1 pixels (780×470) | 366,600 | 82.2 ms | 93.0 ms |
The budget is ≤7 ms/frame. Rendering one fragment per pixel misses it by 12× on this machine; rendering one fragment per dither cell meets it with margin. That is not an optimisation bolted on afterwards — it is the same decision that makes each cell take exactly one threshold decision.
Live loop, 80 rAF intervals: p50 16.7 ms, p90 16.7 ms at both viewports — vsync-capped, i.e. the loop never missed a frame. The adaptive ladder never fired: CELL stayed at 4 px on both.
It animates
Two canvas captures 1.4 s apart differ (byte-compare). [LIVE] in the meta row. Buffer 195×115 desktop, 68×75 mobile.
It does not shimmer — measured against a broken control
The real question is how many cells flip state between consecutive 60 Hz frames. Measured by rendering the exact shader at t = 3.000 … 3.500 in 1/60 s steps with preserveDrawingBuffer, reading the cells back, and counting disagreements. "Support" is the set of cells the object ever lights.
| build | support | cells flipped per frame | % of support |
|---|---|---|---|
| shipped | 2,635 | 12.3 | 0.47 % |
control: patches sampled on gl_FragCoord, 3 s revolution | 3,948 | 195.1 | 4.94 % |
The control is the two mistakes the brief names, and nothing else changed. The shipped build is 10.5× quieter. 0.47 % of ~2,600 cells is about twelve cells a frame — a terminator creeping, not a boil.
Reduced motion is static AND non-blank
reducedMotion: 'reduce' → one frame at t = 3.0, no rAF. Two captures 2.0 s apart are byte-identical. State reads [STATIC], and the Turn control is disabled rather than silently inert.
Non-blank, counted off the 780×462 capture: 40,416 lit pixels — 11.22 % of the plate — of which 420 are the essence dot, 1,408 warm and 1,152 cold. The still frame carries the solid, the terminator seam, and the living dot at 0.99 of systole.
The pointer perturbs; it does not drive
Rendered at fixed t with the mouse at a fixed cell, comparing lit-cell sets:
| test | cells differing |
|---|---|
u_hover = 0, mouse far vs mouse on the plate | 0 — exact identity |
u_hover = 0 vs u_hover = 1 at the same instant | 129 (4.9 % of support) |
| pointer held perfectly still, t advanced 1.5 s | 765 (26.2 % of support) |
Time moves the piece 5.3× more than full pointer presence does, and with no pointer the shader is bit-for-bit the no-pointer shader. Confirmed live too: two captures 1.6 s apart with the mouse motionless differ.
Type, colour, targets
- 70 text nodes audited in the section against their nearest opaque composited background. Minimum ratio 4.86:1. Zero below 4.5:1.
- Families rendering: Departure and Geist only. Weights: 400 and 500 only.
-
Glyph coverage probed in the real faces (advance-width against
#, plus a bitmap compare against a private-use codepoint). Departure carries every glyph this stratum uses —θ ° ⁴ ² √ − — · → ×all at the 25 px monospace advance, while⌗(23) and≡(22.56) fall back, which is what makes the probe discriminating. -
Controls: four buttons, 76.6 / 76.6 / 109.2 / 133.7 × 45 px, all
tabIndex 0. Driven from the keyboard in the run: focused7 · flat, pressed Enter, the plate cap changed toSEVEN SPHERES · THE FLAT RING. -
Holdfreezes the geometry: two captures 1.2 s apart byte-identical, state[HELD]. -
390×844:
scrollWidth === 390, no horizontal scroll; all four buttons 45 px.
Constants that were measured rather than inherited
-
Bayer-8. The in-shader macro
bayer2(a/4)/16 + bayer2(a/2)/4 + bayer2(a)was compared entry-by-entry against this repository'sbayerMatrix(8)recurrence. 64/64 identical, max error 0. - Occlusion percentiles. 312,000 Fibonacci-sphere samples of this exact fbm (this hash, octaves 0.62/0.28/0.10) gave p50 0.5118, p72 0.5934, p85 0.6532. The flat lattice's 0.600/0.555 belong to a different hash and sit near p72/p60 here.
-
Camera fit.
max r/(CAMD−z)on the bounding sphere is at z = BR²/CAMD = 0.526, giving 0.18431; atTANH = 0.1975the pack fills 0.933 of the short edge at its worst-case projection, so it never clips.
Not established
- Nothing here has been run on real mobile silicon. The plate measures its own frame interval and coarsens the cell rather than dropping frames, which is self-correcting, not proven.
- Paper substrate. The whole piece assumes a void ground; §16 already lists paper as untested and this stratum inherits that gap without narrowing it.
- Nothing has been printed.