ETS27 prototype, round 3 · 2026-10-13 · scope: prototype/index.html, prototype/shared.css, the baked head stills in prototype/img/, and the fork's hand-off into prototype/mind.html
Stance: clean-room. This pass used the round-2 verdict (studio/verify-02-opening.md), the fixer's structured claims, the brief and the design direction. It did not open any studio/fix-*.md or studio/critique-*.md file, and it did not use the fixer's r3-* screenshots. Every verdict below comes from fresh pixels and measurements taken in this pass, or from the code.
Score: 86 / 100 for the opening group as shipped now (round 2: 78).
The two items that held round 2 back are fixed.
Every minor and nit from round 2 that the fixer took on also checks out. Nothing in the round-2 landed set regressed. That covers the nudge line, the small phones, burst typing, muted contrast, the bare WebGL probe, dead tokens, the touch toggle, the 1 px hairline and the 14 px eyebrow.
What keeps this from the 90s:
Browser and server
- Headless Chrome for Testing 151.0.7922.34 (chromium-1234), driven through the Playwright library, deviceScaleFactor 1. No headed browser was used.
- GPU path: ANGLE Metal on Apple M1 Max, with --use-angle=metal --ignore-gpu-blocklist.
- SwiftShader path: forced with --use-angle=swiftshader --enable-unsafe-swiftshader. The renderer string was confirmed as SwiftShader, and failIfMajorPerformanceCaveat does not reject it.
- No-GPU path: --disable-gpu. Here the caveat probe returns null.
- Pages came from python3 -I -m http.server 8704 --bind 127.0.0.1, run from prototype/. The port was confirmed free first. The server was stopped by its exact PID at the end, and the port was confirmed free again.
Zero live Claude calls
- Port 8777 was never contacted; the network log shows zero requests to it.
- There were zero non-GET requests.
- mind.html was loaded only through the static server, to test the hand-off. It fell back to demo mode after the expected /api/health 404.
Instruments
- Head luminance probe. Stdlib Python, run with uv run --script. It works on realm-only captures (stage hidden), inside a head box computed from __ets.frame. It reports:
- the minimum, and the count of pixels under 120, 150, 160, 170 and 180;
- the count inside the shading-floor band. That band is 142.5-148: floor 0.51 after distance fog at t 4.5-5.0, plus or minus 2 levels;
- the longest dark column run under the cut at 150 and 120;
- the low histogram, the most populated levels below 215, and a row profile through the darkest pixel;
- a levels view, with L stretched over 60 levels above the minimum, to expose plateaus.
- Silhouette metrics.
- Concavity: the edge's deviation from its convex hull.
- Corner sharpness: the turn of the edge direction over 24 rows.
- Frame-time emulation. requestAnimationFrame was rescheduled on timers, with and without blocking the main thread. A background tab was emulated by overriding document.hidden and visibilityState and holding animation frames until a set time. Timers kept running, as they do in a real background tab.
- Fixed-pose captures. ?yaw=0, ?yaw=9 and ?yaw=-9 gave fixed-pose heads.
- Keyboard tests. Real keyboard sequences at 40, 60 and 200 ms per key.
- Contrast.
- Muted text was made transparent, then the page was screenshotted 10 times, 5 s apart, at 1440x900 and 1280x720.
- Each text rect was expanded by 2 px, and the darkest pixel inside it was taken by relative luminance.
- That darkest pixel was compared with the computed text colour.
- Stills.
- Stdlib PNG decode, alpha extents, border alpha, and the straight-versus-premultiplied check.
- Composites over #ffffff and #fafaf9, plus #cfcfcb as a stress background.
- 4x nearest-neighbour edge zooms.
- A best-fit overlay against the ?still=1 frame, over scale 370-396 px and offset.
- Robustness and counters.
- Route interception to stall three.module.js by 6 s and to abort three.core.js.
- WEBGL_lose_context at a realm time of 2.0 s.
- A drawArrays counter.
- Upstream three.js 0.180.0 downloaded from jsdelivr for a byte comparison.
- Pixels read. Every capture listed at the end was read as an image before it was used.
| Frame | Yaw | Min L | px < 170 | px < 150 | px in floor band 142.5-148 | Dark runs under cut (150 / 120) | Most populated level below 215 |
|---|---|---|---|---|---|---|---|
| Settled 1440x900 (t 7.58) | 7.95 | 171.1 | 0 | 0 | 0 | 0 / 0 | 207-208, 1,735 px each of 39,026 |
Still 1440x900 (?still=1) |
4.0 | 170.3 | 0 | 0 | 0 | 0 / 0 | 206, 1,571 of 34,895 |
| 390x844 (t 7.60) | 7.96 | 171.1 | 0 | 0 | 0 | 0 / 0 | 207, 844 of 18,884 |
?yaw=9, 1440 |
9.0 | 171.6 | 0 | 0 | 0 | 0 / 0 | 207, 1,864 |
?yaw=-9, 1440 |
-9.0 | 169.6 | 3 | 0 | 0 | 0 / 0 | 204, 1,580 |
?yaw=0, 1440 |
0 | 170.1 | 0 | 0 | 0 | 0 / 0 | 201, 1,633 |
Round 2 for reference: - Minimum 164. - A spike of 8,096 px at 165-166 in the settled crop: the clamped plateau.
Round 3 has no plateau. The low histogram climbs smoothly in the settled frame: 7, 27, 48, 74, 85, 126, 236, 312, 344 and 450 px at levels 171 to 180.
The row profile through the darkest pixel (y 367) runs left to right as follows:
The fixer's three dish numbers check out:
| Claim | Measured |
|---|---|
| Each dish is 0.24 wide | About 24% of the 354 px head |
| The dishes stop well inside the silhouette | Their outer edges sit 48 px inside it on the near side and 78 px on the far side |
| The interiors keep a gradient | They do: darkest under the brow, lifting toward the lower rim from the ground bounce (v3-opening-head-levels-1440.png, -levels-still-1440.png) |
The code matches the claim:
- Dishes: socket at (0.25, 0.20, 0.93), radii (0.12, 0.08, 0.10), ssub k 0.12 (index.html 605-606).
- Lighting: AO factor 0.65 (642), ground bounce 0.24 (678), floor 0.51 (679).
From v3-opening-head-1440.png, -head-still-1440.png, -head-yaw0-1440.png, -head-yaw+9-1440.png, -head-yaw-9-1440.png, -head-390.png, and the full frames v3-opening-1440x900.png and -390x844.png:
v2-opening-head-1440.png, round 2's full-width grey plateaus read as a mask. Round 3's read as eye dishes.Remaining (V3-2): the cheek corner on the turned side. The edge direction turns: - 24.2 degrees within plus or minus 12 rows at the dish level on the turned side at yaw 7.9 (22.8 degrees at yaw 9); - 16.2 degrees on both sides at yaw 0; - 9.5 degrees on the leading side.
The corner is visible as an angular cheekbone at 1440 and more so at 390 (v3-opening-head-yaw+9-1440.png, v3-opening-390x844.png). It is the round-2 "notch", unchanged. The fixer skipped it on purpose. It is not a concavity: the measured hull deviation is at most 3.8 px.
Status: fixed. The head is no longer partial. The turned-side corner is a separate minor polish item.
| Claim | Status | Evidence |
|---|---|---|
| Decision 5 head: dish geometry, AO 0.65, ground bounce 0.24, floor 0.51 | Fixed | Code matches the claim; probe in the table above. Min L is 171.1 at 1440 and 171.1 at 390 (claimed 170 and 169). There are 0 px under 150, 0 px in the floor band, 0 dark runs, and the frames at yaw -9, 0 and 9 are all clean. |
Head geometry otherwise untouched; ?yaw=deg debug parameter |
Fixed | The silhouette, temple corner and dissolve match v2-opening-head-1440.png and v2-opening-1440x900.png. ?yaw=9 gives a fixed yaw of 9.00. |
Baked stills ?headonly=1: img/head-still.png 800x924 and @2x 1600x1848, straight alpha, no halo |
Fixed | Format: RGBA 8-bit at both sizes. Alpha: x 26-773 (748 px) and 52-1547 (1496 px); border alpha 0 on both; centre column opaque to row 742 and 1486, with alpha 0 from row 896 and 1792. Edges: the opaque minimum is 170.6, and only 1 semi-transparent pixel is darker than that (170.3 at alpha 21), so the alpha is straight, not premultiplied. The composites over #ffffff and #fafaf9 have edge-ring minima of 171.1 and 170.6, with no dark or light fringe and no rectangle, including over #cfcfcb (v3-opening-still-over-ffffff.png, -over-fafaf9.png, -still-edges-zoom.png). Same head: best fit against the ?still=1 frame at 384 px wide gives a mean absolute luminance difference of 0.63 levels over the cranium and dish band. The fixer said 383 px reproduces the 358 px head. Differences sit only under the dishes, where the live frame has deck haze (v3-opening-still-vs-frame-1440.png). |
| N1: probe window opens after the first frame; under 4 samples, median over 45 ms or mean over 135 ms is slow; hopeless windows skip the half-scale step | Fixed | Steady 400 ms frames fall back at 2.74 s (timer-scheduled) and 2.69 s (main thread blocked); the reason logged is 3 frames in 1500 ms. Frames of 70 ms and 55 ms take two rounds and fall back at 3.45 s and 3.52 s. Frames of 40 ms stay WebGL (median 41.8). |
| N1: 250 ms wall-clock guard, 4 s first-frame watchdog, hidden-tab pause; claimed timings 3.4 s, 5.3 s and 6.2 s | Partial | Timings: a 1.8 s first frame then 120 ms frames falls back at 5.28 s (lag guard) or 5.32 s (blocking variant, probe round 1). Forced SwiftShader falls back at 6.24 s (v3-opening-swiftshader-1440.png). No false fallback: a 2.5 s first frame then 16 ms stays WebGL, and so does a 4.5 s blocking first frame. Hidden-tab pause: works for a tab hidden mid-intro; away from 1.0 to 8.0 s, the clock paused at 0.78 and resumed in WebGL. Fails: the 4 s watchdog runs while the tab is hidden. Hidden at load and shown at 6.0 s gives the CSS realm at 4.29 s with no frame rendered within 4000 ms (v3-opening-background-tab-1440.png). See V3-1. |
| N3: nudge is a reserved second line; no overflow at 1024x680 (665), 1280x720 (708), 1366x768 (753), 1440x900 (882) | Fixed | See the viewport table: the nudge bottoms are exactly 665, 708, 753 and 882. scrollHeight equals the viewport height before and after the nudge, and doors and hint do not move when it fades in. |
| N4: short-phone framing; 375x667 and 360x640 fit with and without the nudge; 390x844 unchanged | Fixed | See the viewport table. The crown is clear of the corner tags: tags end at y 29 and the crown sits at about 40-47 (v3-opening-vp-375x667-nudge.png, -vp-360x640-touch.png). 390x844 is unchanged: doors 358 px wide, 12 px gap, head-bottom 369, mark at 370. |
N5: keys buffered until a 350 ms pause; Enter flushes; Backspace edits; / immediate; door click drops the buffer; who arrives whole |
Fixed | See the hand-off table. |
| N5: mind.html untouched | Not verified | mind.html now carries a composerFirst() hand-off block labelled N5 (lines 741-760), presumably from the mind/standard group. Which fixer edited it cannot be told from the artifacts. The hand-off works end to end. |
N6: --muted #585753; worst 5.03:1 over the darkest adjacent cloud; 7.3:1 on white |
Fixed | Worst 5.03:1 at both 1440x900 (hint) and 1280x720 (door A explainer). On white the measure is 7.23:1, so the "7.3" in the claim and in the shared.css comment rounds up. See the contrast table. |
N8: --ets-sun, --ets-ember, --ets-glow, --ets-sun-halo deleted |
Fixed | Grep of index, mind, standard and shared.css finds no token and no e8a06a or 232,160,106. The only "ember" hits are the words November and remembered, plus the shared.css comment that says no ember token exists. All four tokens compute empty, and no var() in any page is undefined. |
N7: bare webgl2 probe with failIfMajorPerformanceCaveat |
Fixed | --disable-gpu gives the CSS realm at 0.61 s with exactly one console message, [ets27] CSS realm: WebGL2 unavailable or software-rendered (bare probe), and zero errors (v3-opening-nogpu-1440.png). |
| N9: shortcuts toggle hidden under hover none and pointer coarse until a keydown | Fixed | Touch emulation at 390x844, 375x667 and 360x640 shows the toggle at display: none. A Shift keydown adds has-keys and the toggle shows. Corner tags are always shown, and the nudge is display: none and never fires (v3-opening-390x844-touch.png, -390x844-touch-afterkey.png). |
| N11: door B top hairline 1 px; eyebrow 14 px, 0.02em tracking, line height 1.35 | Fixed | Hairline: door B ::before measures 1 px tall, top -1px, raspberry. On hover the pixel rows at the top edge read raspberry (193,17,90) for 1 row, then ink for 1 row of inset (v3-opening-hover-mind-1440.png). Eyebrow: 14 px Geist Mono, letter-spacing 0.28 px, line height 18.9 px, colour #585753. |
| Zero console errors on every index.html load | Fixed | Every GPU-path index.html load in this pass logged zero console messages, zero failed requests and zero HTTP errors. |
| Skipped: door B socket glow on hover (direction 3.3) | Not fixed (skipped) | No glow uniform or hover hook exists in the shader. |
| Skipped: brow-to-temple inflection at plus or minus 9 degrees | Not fixed (skipped) | See V3-2. |
| Not re-run by the fixer: context loss, stall, 30 fps cap | Re-run here: pass | See the regression set. |
| Viewport | scrollHeight at settle |
After nudge | Nudge box (top-bottom) | Doors or hint moved |
|---|---|---|---|---|
| 1024x680 | 680 | 680 | 647-665 | No |
| 1280x720 | 720 | 720 | 690-708 | No |
| 1366x768 | 768 | 768 | 735-753 | No |
| 1440x900 | 900 | 900 | 864-882 | No |
| 375x667 | 667 | 667 | 625-643 | No |
| 360x640 | 640 | 640 | 609-628 | No |
| 390x844 | 844 | 844 | 782-801 | No |
| 375x667 touch | 667 | n/a (nudge display: none) |
n/a | Toggle hidden |
| 360x640 touch | 640 | n/a | n/a | Toggle hidden |
| 390x844 touch | 844 | n/a | n/a | Toggle hidden |
scrollWidth equals the viewport width everywhere.
Small phones, an observation rather than a defect: the mark's top sits about 11 px into the head's dissolve band (mark 262 vs head-bottom 273 at 375x667; 248 vs 259 at 360x640). It reads as the lockup resting on the fog.
| Input on the fork | Composer value | Focused | Caret | ets27.draft after |
Turns | POSTs | Navigation after last key |
|---|---|---|---|---|---|---|---|
who at 40 ms, settled |
who |
Yes | 3/3 | Removed | 0 | 0 | 383 ms |
who at 40 ms during the intro (t 1.2 s) |
who |
Yes | 3/3 | Removed | 0 | 0 | 376 ms |
who at 200 ms |
who |
Yes | 3/3 | Removed | 0 | 0 | 227 ms |
who is at 60 ms |
who is |
Yes | 6/6 | Removed | 0 | 0 | 366 ms |
w, h, Backspace, o |
wo |
Yes | 2/2 | Removed | 0 | 0 | 421 ms |
hi then Enter |
hi |
Yes | 2/2 | Removed | 0 | 0 | 70 ms after Enter |
/ |
empty | Yes | 0 | none | 0 | 0 | 58 ms |
w |
w |
Yes | 1/1 | Removed | 0 | 0 | 430 ms |
| Shift+W | W |
Yes | 1/1 | Removed | 0 | 0 | 420 ms |
x, then click door A within 80 ms |
lands on standard.html | n/a | n/a | never written | n/a | 0 | n/a |
Captures: v3-opening-handoff-who-mind-1440.png, -handoff-slash-mind-1440.png.
Each figure is the worst of 10 samples taken 5 s apart.
| Element (colour) | 1440x900 | 1280x720 |
|---|---|---|
| Door A explainer (#585753, 15 px, 300) | 5.04 | 5.03 |
| Door B explainer (#585753) | 5.22 | 5.23 |
Hint // you can switch any time. (#585753, 12 px) |
5.03 | 5.08 |
| Shortcuts toggle (#585753) | 5.12 | 5.22 |
| Eyebrow (#585753, 14 px) | 5.38 | 5.17 |
| Corner tags (#585753) | 6.52 | 6.52 |
| Nudge (#3a3836) | 8.19 | 8.20 |
| Lockup dates (#3a3836) | 9.36 | 9.19 |
| Theme line (#3a3836, 200) | 8.77 | 8.68 |
The darkest background behind muted text was rgb(216,215,213). The frames with the darkest backgrounds are saved as v3-opening-contrast-bg-1440x900.png and -1280x720.png.
The door outline is unchanged. Computed over the same darkest bank, it is about 3.4:1, above 3:1.
| Round-2 item | Status now | Evidence |
|---|---|---|
| F1 / decision 5: hollows oversized and flat | Fixed | Probe and read above. |
| Head step 3: turned profile at plus or minus 9 degrees | Not fixed (skipped) | V3-2. |
| N1: probe fails open on the slowest devices | Fixed | 400 ms falls back at 2.7 s, the 1.8 s first frame at 5.3 s, SwiftShader at 6.2 s. A new regression sits in the replacement watchdog: V3-1. |
| N3: nudge overflows laptops | Fixed | Viewport table. |
| N4: small phones overflow | Fixed | Viewport table. |
| N5: burst typing keeps one character | Fixed | Hand-off table. |
| N6 and F13: muted borderline AA | Fixed | Contrast table, 5.03:1 at worst. |
| N7: no-GPU console errors | Fixed | One warning, zero errors. |
| N8: dead tokens | Fixed | Grep and computed tokens. |
| N9: toggle on touch | Fixed | Touch captures. |
| N10 (cross-group): unavailable card used the em-dash explainer | Fixed by the other group | mind.html 657 now uses the colon form. |
| N11: hairline 2 px and eyebrow 12 px | Fixed | 1 px and 14 px. |
| N11: socket glow on door B hover | Not fixed (skipped) | Absent in code. |
Every item still passes.
Fork copy and names (DOM)
- Eyebrow // two ways in.
- Labels Open the map and Ask the mind: Unbounded 400, 28 px, no transform.
- Explainers in the colon form.
- Tags [ browse ] and [ ask ]: aria-hidden, opacity 0 at rest.
- aria-labels exactly per direction 3.2.
- Rest border 1px solid rgba(11,11,12,.5).
- Focus ring raspberry, 2 px, offset 4 px (v3-opening-focus-map-1440.png, -focus-mind-1440.png).
Keys
- No navigation and scrollY 0 for:
- Ctrl+K, Meta+K, Alt+K and Meta+Shift+K;
- Escape and F2;
- Enter and Space on the body;
- ArrowDown and Shift;
- a synthetic isComposing event and a defaultPrevented event;
- typing in an input.
- Tab order: skip link, map, mind, toggle.
- ArrowRight and ArrowLeft move between the doors and wrap.
- Space on door A opens standard.html.
- Enter on door B opens mind.html with #q focused.
Toggle and nudge
- The toggle reads [ shortcuts on ] with aria Turn single-key shortcuts on.
- It stores off, survives a reload and makes keys inert (v3-opening-shortcuts-off-1440.png).
- The nudge appears at 9.9 s with text > pick a door, or just start typing., once per session (v3-opening-nudge-1440.png).
Lockup, palette and title
- Lockup // MAY 3-6, 2027 and // AUSTIN, TX, set by tag--caps.
- Tokens:
- --bg #ffffff
- --line #e2e2df
- --line-ui rgba(11,11,12,.5)
- --accent and --focus #c1115a
- --accent-ink #8f0c43
- --accent-tint #fbe9f0
- --ets-signal empty
- Title ETS27 | free_your_mind [OPEN]; theme-color #ffffff.
three.js
- vendor/three.module.js and vendor/three.core.js are byte-identical to the jsdelivr three@0.180.0 build files.
- sha384 wyxAlyAV…NRoZKv and r1q8Si7x…n+8m8; REVISION 180.
- The import map holds only three.
- Requests go only to the same origin and Google Fonts.
Failure paths
| Test | Result | Capture |
|---|---|---|
| Stall: three.module.js held 6 s | is-live and quick-reveal at 1.69 s, CSS realm at 2.75 s, doors at opacity 1 by 3.16 s. The module arrives at 6.03 s; still CSS and settled at 10.0 s. |
v3-opening-stall-1440.png |
| Abort three.core.js | CSS realm at 0.24 s, settled at 5.84 s | — |
| Context loss at realm t 2.00 | CSS realm within 0.4 s with the clock at 2.40, settled at clock 5.61. No page errors. | v3-opening-context-lost-1440.png |
Intro
- Skip: visible at 0.71 s. A click jumps the clock to 5.84 with doors at opacity 1. A click on the sky at 0.6 s jumps it to 5.88 (v3-opening-skip-visible-1440.png, -after-skip-1440.png).
- Early focus: Tab at 0.5 s lands on the skip link with the doors at opacity 1. The next Tab focuses door A at opacity 1 with no filter (v3-opening-focus-early-1440.png).
- No-JS: CSS realm, dated lockup, plain links, toggle hidden (v3-opening-nojs-1440x900.png, -390x844.png).
- Reduced motion: doors at opacity 1 by 0.39 s over the still frame (v3-opening-reduced-motion-early-1440.png).
- No WebGL: ?nowebgl=1 gives the CSS realm (v3-opening-nowebgl-1440x900.png).
Rendering - 30 fps cap: 359 draws per second during the intro and 85 once settled (3 draws per frame). - Resize: 1440 to 900 to 390 to 1440 reframes each time (cut at 397, 335 and 437) with no scroll.
V3-1 (major, regression introduced in round 3). A tab opened in the background loses the realm.
The first-frame watchdog (index.html 994) starts when boot() runs and fires after 4 s whatever the visibility. A background tab gets no animation frames, but its timers still run. So a page opened with cmd-click, middle-click, "open in new tab" or session restore falls back to the CSS realm while nobody is looking. When the visitor switches to it, they get the CSS egg instead of the head.
The pause added for hidden tabs covers only the lag guard and the probe window. The watchdog does not check document.hidden.
| Emulation | Result |
|---|---|
| Hidden at load, shown at 6.0 s | Warning no frame rendered within 4000 ms at 4.29 s, CSS realm (v3-opening-background-tab-1440.png) |
| Hidden at load, shown at 2.0 s | Stays WebGL |
| Hidden from 1.0 to 8.0 s mid-intro | Stays WebGL |
Suggested fix: count only visible time. Either:
- arm the watchdog when document.visibilityState is visible, and on visibilitychange re-arm it, or
- inside the callback, if document.hidden, wait for the next visibilitychange to visible and give it a fresh 4 s.
Then re-run: hidden at load and shown at 6 s should end in WebGL.
V3-2 (minor, pre-existing, skipped by the fixer). The turned side shows an angular cheek corner.
At the dish level, the silhouette's edge direction turns by: - 24 degrees within 24 px on the turned side at yaw 8-9; - 16 degrees on both sides at yaw 0; - 9.5 degrees on the leading side.
It is visible as a cheekbone corner, more so at 390 (v3-opening-head-yaw+9-1440.png, v3-opening-390x844.png). The slow yaw spends roughly half of each 44 s cycle above 6 degrees, so the corner is often on screen. It is the one remaining skull-leaning cue, and a soft one.
Suggested fix: widen or soften the temple cutter's lower reach (lower k at the cheek, or a larger y radius so the plane fades out before the dish level). Alternatively, cap the yaw at about 6 degrees.
V3-3 (minor, open, not claimed). Every fallback path still draws the CSS egg.
The CSS realm's head is still the radial-gradient egg with a faint band (v3-opening-nowebgl-1440x900.png, -nojs-1440x900.png, -background-tab-1440.png). img/head-still.png and @2x are correct (see the claims table), but nothing references them yet; the fixer handed the swap to a later agent.
This matters more now that more devices fall back: - slow and blocked devices; - SwiftShader; - background tabs, until V3-1 is fixed.
Suggested fix:
- Use the still as the CSS-realm head: 383 px wide reproduces the 1440 head.
- Add a white-to-fog veil over its lower 20%. The still has no deck haze, so its lower face shows greyer than in the live frame (v3-opening-still-vs-frame-1440.png, right panel).
V3-4 (nit). [ skip ] lingers after a late fallback.
When the realm falls back late, the CSS phase clock resumes from the stalled realm time. Examples: - SwiftShader at 6.2 s with the realm clock at 0.17; - the background tab at 4.3 s with the realm clock at 0.
The [ skip ] button then stays visible for up to 5.6 s more, although quick-reveal has already shown everything (v3-opening-swiftshader-1440.png, -first1800-1440.png).
Suggested fix: when fallbackToCss runs after domSafetyMs, treat the intro as done (call realm.skip).
V3-5 (nit). The nudge's live region reads the prompt glyph.
#nudge is aria-live="polite", so a screen reader announces > pick a door, or just start typing. with the leading > read as "greater than".
Suggested fix: wrap the glyph in an aria-hidden span.
V3-6 (nit, carried). The door B socket glow on hover (direction 3.3) is not built. The fixer skipped it, as in round 2.
v2-opening- captures: no regression. Compared:v2-opening-1440x900.png;-mid-intro-b-1440x900.png;-nojs-1440x900.png;-head-1440.png.The realm, cloud deck, corner tags, theme line, lockup mark, mid-intro beat and the no-JS and no-WebGL layouts are unchanged. The only difference is that the stack sits 4-21 px higher at 1440x900 (vh-scaled gaps, with the hint at 841 vs 862) to leave room for the reserved nudge line.
| Run | Console and network |
|---|---|
index.html on the GPU path: settled, still, 390, ?yaw, hover, focus, mid-intro, viewports, keys, contrast, resize, draw counter |
Zero console messages, zero failed requests, zero HTTP errors |
| Steady 400 ms, 70 ms, 55 ms and 1.8 s first-frame emulations | One [ets27] CSS realm: warning each, naming its reason |
--disable-gpu, ?nowebgl=1 and the background-tab emulation |
One [ets27] CSS realm: warning each, naming its reason |
| Stall | One warning |
| Abort | The forced net::ERR_FAILED with its console error, plus one warning |
| Context loss | three.js Context Lost. log plus one warning |
| SwiftShader | Two Chrome GL driver warnings (GPU stall due to ReadPixels) plus one CSS-realm warning; no errors |
| No-JS | Two blocked modulepreloads, which is how Playwright disables scripts, not a page fault |
| mind.html on the static server | /api/health 404, an environment artifact, after which demo mode is used |
Across all runs: zero non-GET requests and zero requests to port 8777. Requests went to the same origin and Google Fonts only. One extra network fetch was made on purpose: three.js 0.180.0 from jsdelivr, outside the page, for the byte comparison.
document.hidden, visibilityState and held animation frames.Every file below was read as an image in this pass.
1440x900, 390x844, still-1440x900, mid-intro-1440x900, mid-intro-b-1440x900, hover-mind-1440, hover-map-1440, focus-mind-1440, focus-map-1440, nojs-1440x900, nojs-390x844, nowebgl-1440x900, reduced-motion-early-1440, reduced-motion-1440.head-1440, head-still-1440, head-390, head-yaw0-1440, head-yaw+9-1440, head-yaw-9-1440, head-levels-1440, head-levels-still-1440.still-over-ffffff, still-over-fafaf9, still-edges-zoom, still-vs-frame-1440.steady400-1440, first1800-1440, swiftshader-1440, nogpu-1440, background-tab-1440, stall-1440, context-lost-1440.skip-visible-1440, after-skip-1440, focus-early-1440, shortcuts-off-1440, nudge-1440, handoff-who-mind-1440, handoff-slash-mind-1440.vp-1024x680, vp-1024x680-nudge, vp-1280x720, vp-1280x720-nudge, vp-1366x768, vp-1366x768-nudge, vp-1440x900, vp-1440x900-nudge, vp-375x667, vp-375x667-nudge, vp-375x667-touch, vp-360x640, vp-360x640-nudge, vp-360x640-touch, vp-390x844, vp-390x844-nudge, vp-390x844-touch, 390x844-touch, 390x844-touch-afterkey.contrast-bg-1440x900, contrast-bg-1280x720.http.server on 8704 (PID 72880) was stopped by that exact PID. The port was confirmed free with lsof, and curl to 8704 was refused. Port 8766 and the tu session ets27-docs were not touched. No pattern kill was used.scratchpad/v3-opening/ (7.3 MB) was denied by the permission layer, so the directory is still there. It holds scripts, probe frames, JSON and the upstream three.js copies; nothing in it is a secret. It needs removing by whoever holds that permission. No workaround was attempted.