Foundations
Settle fast, land soft
One curve for everything that eases out, four durations, and a rule for reduced motion that keeps the city alive.
The curve
cubic-bezier(0.22, 1, 0.36, 1) — most of the distance in the first third, then a long soft landing. ease-brand in Tailwind, var(--ease-out) in CSS, EASE for motion.ease-brand · cubic-bezier(.22, 1, .36, 1)
Şehre gir
ease · CSS default
Şehre gir
Durations
duration-fast to duration-slower in Tailwind, --duration-* in CSS, DURATION (ms) and DURATION_S (s) in JS.fast120
Hover, press, colour
base200
Menus, popovers, tabs
slow380
Panels, drawers
slower700
Entrances, reveals
Ambient loops
animate-drift for a backdrop that breathes, animate-shine for a sweep across a call to action, animate-scroll-cue for the line under a hero.animate-drift
Şehre gir
Kaydır
Reduced motion
Entrance flourishes drop to a fade. Ambient loops do not stop: their durations are
calc(Ns * var(--motion-scale)), and --motion-scale is 2 under prefers-reduced-motion, so they run at half speed.Why loops keep running
On Windows the media query follows “Animation effects”, which many players switch off for performance, not for motion sensitivity. A city whose skyline freezes reads as broken. This is an owner decision; do not undo it in a component.import { DURATION_S, EASE } from '@fastrp/design-tokens/motion';
<motion.div
initial={{ opacity: 0, y: 24 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: DURATION_S.slower, ease: EASE }}
/>