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

RoleValueNotes
Enter / settlecubic-bezier(0.22, 1, 0.36, 1)--ease-enter
Hover / presscubic-bezier(0.32, 0.72, 0, 1)--ease-hover
Hover200msfast
Scroll reveal400msbase
Ceilingunder 400mselegant, 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

InteractionBehaviourDuration
Page enterSubtle fade in400ms
Scroll revealSlide up with opacity, staggered400ms, 60ms stagger
Card hoverscale(1.02)200ms
Button hoverColour transition only200ms
PressResponds on pointer-down, not on clickimmediate
ScrollSmooth behaviour, never hijackednative

Interruptible, always

Every animation starts from the value currently on screen and can be reversed mid-flight. Nothing waits for a transition to finish before it will accept input.

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.