The audit's headline UX finding, measured on production: cold load showed a
black screen for ~5s, then a wordless constellation. At 9 seconds the number
of words on screen was zero — no name, no title, no hint that anything was
clickable. A recruiter could not learn one fact without clicking.
- New Hud.svelte: name, market-legible title and a one-line hook, always on
screen, sourced from the origin node. Readable at ~1s instead of never.
Added `tagline` to OriginNode so it lives with the rest of the content.
- New CoachHint.svelte: first-run "drag / scroll / click" hint. The icons
gave no affordance that the tree was interactive at all.
- Skip intro control. runEntranceAnimations now returns a handle whose skip()
enumerates the entrance's own nested GSAP context and calls progress(1) on
each finite tween — which fires their onComplete, so node interactivity and
the ambient pulses come up exactly as if the intro had played through.
Verified: a node is clickable immediately after skipping.
- Returning visitors land on the settled tree (localStorage), reusing the
same code path as reduced motion. The flag is set once the intro has
actually been seen, not at mount — otherwise someone who bounced after a
second would be marked as having seen it and never get it.
- Entrance timings cut: title 2.5s -> 1.6s, zoom 4.5s -> 2s, stagger 0.08 ->
0.045 (that last one was 4.5s of cascade on its own across 56 nodes).
Two bugs found while building this:
- animation.ts hardcoded its timings as literals instead of reading
config.ts TIMINGS, so editing config silently did nothing. Now derived.
- Skip and the coach hint were timed off a magic 3200ms, so Skip vanished
while the intro was still running and "Click a node" appeared before the
nodes did. Both now derive from the entrance's real computed length, which
the handle exposes as durationMs.
- Skip sat bottom-right underneath the service-worker update toast (same z
token, later in DOM order). Moved to bottom-centre; the toast got its own
layer token.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>