Skip to content

Keep the hero prism when the footage paints nothing, and draw its light crisp - #129

Merged
inxbit merged 1 commit into
mainfrom
fix-safari-prism-plate
Nov 3, 2026
Merged

inxbit merged 1 commit into
mainfrom
fix-safari-prism-plate

Conversation

@inxbit

@inxbit inxbit commented Nov 3, 2026

Copy link
Copy Markdown
Owner

Two fixes to the hero seam, found in the owner's Safari:

  • Missing prism. The hero hid the still prism plate on the video's playing event, before any frame had painted. Safari 27 on the owner's Mac ran the clip's clock but presented no frames at all (121 of 121 dropped, requestVideoFrameCallback never fired, even for a synthetic test clip), so the prism slot went empty while the beam and dust still came on. The plate now steps aside only once requestVideoFrameCallback reports a frame and the footage is unhidden, whichever comes last; settle() drops footage that never produced a frame and keeps the plate. Browsers without the API keep the old swap on playing. The hidden check matters because a frame can be reported for the still-hidden element (Firefox on load, any engine while paused off screen), which would otherwise leave the slot empty for a frame or, with reduced motion switched on mid-load, for good.
  • Fuzzy light. On a 1x display the flow dashes were 12u soft blobs riding a crisp beam line (and up to 3u off it, since the line falls 1.29deg), and the dust motes were 0.5 to 1.4 px discs that smeared. The flow band now hugs the line (2u core, 1u edges, tilted onto it) and the motes are whole-device-pixel points. Same motion, same timing.

Checks:

  • Real Safari 27, beacon loop against a local copy: before, plate hidden and slot empty; after, plate visible throughout and the light comes on at settle. After a Safari relaunch the footage paints again and the plate yields on the first frame.
  • Playwright oracle (rVFC that never fires plus an invisible video, the Safari symptom): red on main, green here in Chromium and WebKit; the normal path still ends on the footage's last frame, the swap lands on the first frame (3 ms after playing in Chromium, 16 ms in WebKit).
  • State probes (reduced motion or scroll-away before the first frame, stalled media, normal): 0 frames with an empty slot in Chromium and WebKit. Headless Firefox 159 scroll-away race: 1 empty in-view frame per run before the hidden check, 0 after.
  • node --test tests/*.test.mjs 49/49, privacy scan clean.

The repo has no browser test harness in CI, so the probes above live outside the repo.

…ht crisp

The hero hid the still prism plate on the video's 'playing' event. A
browser can run the clock and present no frames: the owner's Safari 27
did that for every clip (121 of 121 frames dropped,
requestVideoFrameCallback never fired), so the prism slot went empty
while the beam and dust still came on.

The plate now steps aside only once requestVideoFrameCallback reports a
frame and the footage is unhidden, whichever comes last, and settle()
drops footage that never produced a frame in favor of the plate. A frame
can be reported for the hidden element (Firefox on load, any engine
while paused off screen), hence the hidden check. Browsers without the
API keep the old swap on 'playing'.

The light layer is drawn crisp: the flow band hugs the beam line (2u
core, tilted 1.29deg to its fall) instead of a 12u soft strip, and dust
motes are whole-device-pixel points instead of sub-pixel discs.
@inxbit
inxbit merged commit f14b599 into main Nov 3, 2026
6 checks passed
@inxbit
inxbit deleted the fix-safari-prism-plate branch November 3, 2026 19:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant