Rows cascade in — each waits one stagger step behind the last.
Height and chevron ride the same move token, so the panel opening reads as one gesture rather than two.
This panel arrived via a view transition — the old tab cross-faded into it.
The toggles ride the move / hover tokens.
view()Each card animates in as it crosses the viewport edge, driven by animation-timeline: view() — timed by your enter token. No JS on supporting browsers.
That reading-progress bar tracks the scrollbar via animation-timeline: scroll() — scroll position is the axis, no duration.
Reveal distance and easing come from the very same --role-* variables the shell above uses. Edit the system and this re-times live too.
Where native scroll timelines are missing (Firefox today), an IntersectionObserver triggers the reveal and a scroll listener drives the bar — the same recipes the export emits.
Nothing here blocks content: reduced-motion pins the end state, and unsupported browsers just show the cards.
The dialog rises and the scrim fades on enter; both reverse — faster — on exit.