# Radius & motion

> Soft, never round. Motion with a job: entrances, counters and light that follows the cursor, each one earning its place. Every animation has a reduced-motion path.

## Border radius

| Token | Value | Use |
| --- | --- | --- |
| `--radius-sm` | 6px | badge |
| `--radius-md` | 10px | button, input |
| `--radius-lg` | 16px | card, dialog |
| `--radius-xl` | 24px | featured |
| `--radius-full` | 9999px | avatar, dot |

## Motion

| Token | Value | Use |
| --- | --- | --- |
| `--motion-fast` | 120ms | hover, tooltip |
| `--motion-base` | 200ms | card, button, a menu opening |
| `--motion-slow` | 320ms | sheet, collapse, theme switch |
| `--ease-out` | cubic-bezier(0.2, 0.8, 0.2, 1) | entrances and feedback |
| `--ease-in-out` | cubic-bezier(0.4, 0, 0.2, 1) | a height that opens and closes |

The global reset collapses every CSS animation and transition to about 0ms for people who ask for less motion. Components that animate through JavaScript call useReducedMotion() on their own.

## Motion components

3 of them animate through JavaScript. They share lib/motion.ts: the ease-out curve, one viewport rule and a stagger cap of six. The motion package installs with them and nowhere else.

- [Reveal](https://entrepta.vercel.app/docs/components/reveal.md): Entrance that rises and fades in once on screen, with a capped list stagger
- [TypeIn](https://entrepta.vercel.app/docs/components/type-in.md): Text that assembles piece by piece, with the full sentence always in the DOM
- [RollingNumber](https://entrepta.vercel.app/docs/components/rolling-number.md): Odometer counter that rolls into place and turns once on hover
- [ArrowLink](https://entrepta.vercel.app/docs/components/arrow-link.md): Text link with a traveling arrow and a brand rule that wipes in. CSS only

## Motion in CSS

For what has to move before JavaScript runs, such as a loading screen or an overlay. They live in globals.css, and the reduced-motion reset stops them.

- `.type-line`: a line that types itself with no JS, set --type-chars
- `.type-fade`: a line that fades up after --type-delay
- `.type-caret`: a blinking block caret
- `.type-late`: a line that only shows when a wait runs long
- `.skeleton-sweep`: one band of light over a grid of skeletons
- `.motion-fade, .motion-pop, .motion-sheet`: an overlay or a sheet opening and closing
- `.motion-collapse`: a panel opening to its height, handed over as --collapse-height

## Motion rules

- Do: Trigger entrances with whileInView and once, everywhere. Don't: Use animate above the fold. One trigger leaves no judgement call to get wrong.
- Do: Ask useReducedMotion() in anything animated through JS. Don't: Assume the CSS reset caught it. Motion never goes through that block.
- Do: Keep the real text in the DOM and animate a hidden copy. Don't: Grow a string in state. Crawlers and screen readers get an empty heading.
- Do: Move glows and shines with transform. Don't: Rebuild a gradient every frame. It repaints the card and stalls other animations.
