One-Clock Reveal / skeleton first, then matter, on one declared timeline

Noctuary's intro works because nothing improvises: a table declares when each stage starts and ends, one clock advances them, and the stages are forbidden from overlapping into mush — the sweep finishes before anything fills in. Reduced motion collapses the same table, not just the CSS. The terrain below is generated, seeded, and driven by the extracted clock.

SWEEP 000% IDLE t 0.00s
Drop-in · executed live above
  1. One rAF-driven update(dt) the host already has, and anywhere to write numbers. No DOM requirements, no dependencies — canvas2d, WebGL or three.js all consume the same values.
  2. A scene that can render partially: every layer reads a radius/fade pair, so any frame between 0 and done is a valid frame.
  3. makeClock(T){update(dt), reset(), intro, state, progress}; T-table helpers inv / easeOut / clamp / lerp; collapseForReducedMotion(T).
  4. Named states for HUDs and ready predicates: sweeping → resolving → complete, plus progress ∈ [0,1] and raw intro seconds.
  5. Skeleton first, then matter. In the reference table the wireframe pulse owns [0.18s, 1.70s] alone; solidification begins at 1.85s. Read order is the design — overlapping stages were Noctuary's original bug.
  6. One table, one clock. Every stage window lives in T; layers read radii written once per frame (uScanR, uSolidR, uWireFade, uEdge). Nothing animates on its own timer.
  7. Reduced motion collapses THE TABLE — wireIn → [0, .01], solidIn → [0, .02], wireOut → [0, .03] — so the page lands finished instantly. Shortening only UI cues leaves a three-second sweep running behind a finished layout; that was the other bug.
  8. The reveal is skippable and replayable: reset() returns to t=0 cleanly; hosts typically bind R and a visible replay control.
  9. A reveal ends in a composition. The final frame is designed (wire fully burned off, edge glow spent); screenshots wait for it via a ready predicate, not a clock guess.
  10. Noctuary (designpages.dev/noctuary): the T table, inv()/easeOut(), updateIntro()'s radii-and-fade writes, and the REDUCED collapse block — re-expressed without three.js so any renderer can adopt it. The demo draws procedural ridges from a seeded value-noise field (mulberry32).