
Expression
Motion
How things move, and the specs that keep it consistent.
Motion explains where something came from and where it went. Nothing here runs longer than 400ms, and nothing bounces — overshoot reads as playful, and this brand is composed.
Tokens
| Role | Value | Notes |
|---|---|---|
| Enter / settle | cubic-bezier(0.22, 1, 0.36, 1) | --ease-enter |
| Hover / press | cubic-bezier(0.32, 0.72, 0, 1) | --ease-hover |
| Hover | 200ms | fast |
| Scroll reveal | 400ms | base |
| Ceiling | under 400ms | elegant, not flashy |
The two easings
Enter settles like a physical object coming to rest. Hover is sharper, because a pointer response that takes 400ms feels broken.
Enter
cubic-bezier(0.22, 1, 0.36, 1)400ms
Hover
cubic-bezier(0.32, 0.72, 0, 1)200ms
The catalogue
| Interaction | Behaviour | Duration |
|---|---|---|
| Page enter | Subtle fade in | 400ms |
| Scroll reveal | Slide up with opacity, staggered | 400ms, 60ms stagger |
| Card hover | scale(1.02) | 200ms |
| Button hover | Colour transition only | 200ms |
| Press | Responds on pointer-down, not on click | immediate |
| Scroll | Smooth behaviour, never hijacked | native |
Interruptible, always
Reduced motion
Under prefers-reduced-motion: reduce the site removes movement through space and keeps only opacity. Autoplaying video does not start. This is honoured everywhere, including the portal you are reading.
Do: Animate opacity and transform only. Both are compositor-friendly.
Do: Keep hover and press feedback under 200ms.
Do: Start from the current value, not from a hardcoded origin.
Do: Keep every animation under 400ms — elegant, not flashy.
Do not: Do not animate width, height, top or left. They force layout.
Do not: Do not bounce or overshoot.
Do not: Do not hijack scrolling.
Do not: Do not block interaction while something is animating.