Starting a new game reuses block ids (1,2,3...). The reveal clock's per-block
start times (activeRevealBlockStarts in the lab) and the renderer's animation/
revealed sets are keyed by block id and were never cleared on a client reset, so
a new game over already-cached content inherited the previous run's start times.
beginPageReveal then computed a huge elapsed and the shader treated the reveal as
already complete — showing everything at once instead of animating.
resetClientPlaybackAndDisplay (run on new game and restore) now emits
story:client-reset; the lab clears activeRevealBlockStarts/pending reveal state,
the texture renderer clears active animations and revealed-block ids, and the
timeline invalidates prepared segments. So each game starts with a clean reveal
clock.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Establish book-playback-timeline as the sole playback owner driving the
scene through formal webgl-book:* events (not the BookLabDebug surface),
with a single reveal clock in the scene render loop and webgl-page-cache as
the only texture cache. Remove the legacy dual playback path and the
ownsPageFlipCommit gating.
Fixes:
- Flip page detached/folded at the spine: restore the raw page-cap line for
flip geometry (matches the prototype/pre-regression), removing
normalizeFlipLineToVisiblePage which moved the pivot off the spine arc.
- Flip textures: distance-based UVs (no horizontal compression),
direction-aware face material (source on the camera-facing side), source
meta derived from the visible spread (manual flips), prewarm shape fix.
- Reveal: flash removed on the static page and the flip back surface;
spanning blocks rebuild the reveal plan at activate and continue the
reveal on the next spread after the fill flip.
- Cache staleness is contentVersion-primary; nav clamps to spreadCount.
Docs updated to describe the intended single-owner architecture. Regression
checks updated to match.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>