Motion
Motion is restrained and purposeful, it guides attention without calling attention to itself.
All motion respects prefers-reduced-motion: reduce, durations collapse and transforms are removed. Never animate around it.
Durations & easing
Each animated element pairs a duration with an easing curve. Short and soft for UI feedback; longer and smoother for ambient motion.
| Element | Animation | Duration | Easing |
|---|---|---|---|
| Chroma headline sweep | bg-position + blur | 0.9s | ease-in-out |
| Card lift on hover | translateY(-2px) | 0.4s | cubic-bezier(0.34,1.2,0.64,1) |
| Scroll reveal | opacity + translateY(16px) | 0.5s | cubic-bezier(0.16,1,0.3,1) |
| Text-link arrow | translateX(3px) | 0.2s | ease |
| Navbar hide | translateY(-100%) | 0.3s | cubic-bezier(0.4,0,0.2,1) |
Scroll reveal
Content eases into place as it enters the viewport. An IntersectionObserver adds .reveal--visible to each .reveal element the first time it scrolls into view. The hidden state lives only on the .reveal class JS applies, so with no JS, content stays fully visible.
.reveal {
opacity: 0;
transform: translateY(16px);
}
.reveal--visible {
opacity: 1;
transform: none;
transition: opacity 0.5s cubic-bezier(0.16,1,0.3,1),
transform 0.5s cubic-bezier(0.16,1,0.3,1);
}