Motion
The motion vocabulary of the 2026-09-02 airmond.com rebuild, as tokens in dist/css/airmond.css (--motion-*) and dist/ts/tokens.ts (motionWeb). Six durations, five curves, one damping number, and two rules that matter more than any of them. The app keeps its own shorter motion scale (90 / 160 / 240 / 420); this page is marketing web: landers, decks, anything that reveals itself on scroll.
Tokens
| Token | Duration | Ease (CSS) | GSAP | Use |
|---|---|---|---|---|
--motion-arrive | 700ms | cubic-bezier(0.22, 1, 0.36, 1) | power3.out | anything entering the page |
--motion-land | 600ms | cubic-bezier(0.16, 1, 0.3, 1) | expo.out | elements that settle: cards, pills, check marks |
--motion-micro | 180ms | cubic-bezier(0.25, 0.46, 0.45, 0.94) | power2.out | hover, focus and press feedback |
--motion-press-in | 90ms | ease-out | power1.out | the press itself: scale 0.98 |
--motion-press-out | 260ms | cubic-bezier(0.34, 1.56, 0.64, 1) | back.out(1.6) | the release: a small spring back to 1 |
--motion-ambient-min / -max | 4s to 8s | cubic-bezier(0.37, 0, 0.63, 1) | sine.inOut | the one or two things allowed to breathe: a waveform, a portrait row |
--motion-scrub-damping | 0.6 | ScrollTrigger scrub | lag for scroll-bound motion (the hero parallax, the steps highlight) | |
--motion-reduced | 200ms | ease | under prefers-reduced-motion every state change is this opacity fade, with no travel | |
The eases ship as --motion-ease-arrive, --motion-ease-land, --motion-ease-micro, --motion-ease-press-in, --motion-ease-press-out and --motion-ease-ambient, and as Tailwind ease-arrive, ease-land, ease-micro, ease-press-out, ease-ambient.
Live
Each box plays its token once. Hover and press the button for micro and press; the portrait breathes on the ambient curve (1.00 to 1.015 over 6s). Under prefers-reduced-motion this page does what every Airmond surface does: the boxes fade in 200ms with no travel and the portrait holds still.

The reduced-motion rule
prefers-reduced-motion: reduce no timeline is built at all: nothing is hidden, nothing travels, the film stays on its poster, nothing loops, hover and press keep their colour change and lose their transform. The one motion left is the 200ms opacity fade on a state change (a field appearing, an error, success), because a block that appears from nothing reads as a glitch.@media (prefers-reduced-motion: reduce) {
.loop, .breathe, .dot { animation: none; }
.btn, .tile { transition-property: background-color, box-shadow, opacity, color; }
.btn:hover, .btn:active, .tile:hover { transform: none; }
.state-change { animation: fade var(--motion-reduced) ease both; }
}
The budget
- Reveals play once per page load, on enter, and stay. Nothing re-animates on scroll back.
- At most two ambient loops per page: on the landing page the waveform (while its tile is on screen) and the portraits' breathing. Trust never breathes.
- Transform and opacity only. A hover shadow lives on a pseudo-element and fades in. Height is animated once, on the sign-up card's reveal, because a block appearing from nothing is worse than one 260ms reflow.
- No scroll-jacking. Scroll-bound motion is scrubbed at 0.6 and reversible; nothing pins for a beat, nothing listens to the wheel, and a smooth scroll is the browser's own.
- Nothing stays hidden for want of JavaScript. Every reveal has a CSS fallback and every trigger the page is already past fast-forwards.
- Not in the vocabulary: confetti, bouncy springs beyond the 1.6 release, gradient backgrounds, parallax faster than the copy. The tokens cap it on purpose.
Where each token is used on the landing page
| Moment | Token | What moves |
|---|---|---|
| The arrival (0 to 1.4s) | arrive | the pill (0.4s), the headline line by line (24px up, 0.7s, stagger 0.08), the sentence, the card rising 16px as its shadow blooms, the film's left fade opening from 60% to 31% |
| Sections entering | arrive, land | tiles rise 32px on a diagonal (stagger 0.09); icons materialise from 0.85 with a small settle; check marks draw themselves (0.45s, 120ms apart) |
| The sign-up card | arrive, micro, press | the recap and trust blocks grow in over 260ms; a refused number shakes the field 2px twice; success draws a check in confirm blue over 0.6s |
| Ambient | ambient | waveform (only while on screen), portrait breathing (6s, phased), the live chip's dot (2.4s) |
| Scroll | scrub-damping | the hero film scales 1.00 to 1.08 from its bottom edge and slides 64px; the three steps light in turn, never pinned |