Foundations

Motion

Motion is communication, not decoration. Five durations, four easing curves. Anything more is noise.

Durations

Each token's dot travels at its own duration so you can feel the difference. The pause between cycles is the same; only the move time changes.

DemoTokenValueUsage
--duration-instant
75ms
State flips (focus, checked)
--duration-fast
150ms
Hover, button press
--duration-base
200ms
Default — show/hide
--duration-slow
300ms
Modals, drawers
--duration-slower
500ms
Page transitions, large reveals

Easing

in
cubic-bezier(0.4, 0, 1, 1)
UI leaving view, dismissal
out
cubic-bezier(0.16, 1, 0.3, 1)
Default — UI entering view
in-out
cubic-bezier(0.4, 0, 0.2, 1)
Position changes, drag
spring
cubic-bezier(0.34, 1.56, 0.64, 1)
Confirmation, success states

Reduced motion

All non-essential animation respects prefers-reduced-motion. Confirmation feedback (✓, save, send) remains; decorative shimmer, page transitions, and parallax do not.

Mechanical wiring: tokens.css ships a @media (prefers-reduced-motion: reduce) block that zeros out every --duration-* token. Any component consuming the tokens automatically becomes instant — no per-component @media rule needed. Components that need to stay non-instant for FUNCTIONAL reasons (multi-step transitions where intermediate state is meaningful) should opt out of --duration-* and use a fixed duration value with a local @media escape.