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
base200
slow380
slower700

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 }}
/>