v3.0.2 is out — restored design-system guidance and corrected navigation. Read the notes
projectious·work
On this page

Space, shape, and motion

The 4px spacing base, the radius and elevation ladders, and the motion tokens.

Spacing#

A 4px base with a nine-step scale. Every margin, padding, and gap resolves to one of these values.

TokenValueTypical use
--space-14pxIcon-to-label gaps
--space-28pxTight component padding
--space-312pxControl padding
--space-416pxDefault element spacing
--space-524pxCard padding, paragraph rhythm
--space-632pxComponent separation
--space-748pxSub-section separation
--space-864pxSection separation
--space-996pxPage-level bands

Content sits inside a 1100px measure. Wider viewports gain margin, not line length.

Radius#

TokenValueApplied to
--radius-sm3pxTags, chips, small indicators
--radius-md6pxButtons, inputs, code blocks
--radius-lg9pxCards, panels
--radius-xl13pxLarge panels, modals
--radius-full9999pxPills, avatars

Radius is a signal of scale: the larger the surface, the larger the radius. Mixing radii on nested surfaces reads as a mistake — a 6px control inside a 9px card is correct; a 13px control inside a 6px card is not.

Elevation#

Four levels. Shadows are soft and low-contrast; the system leans on borders and surface tint before it reaches for shadow.

TokenValueApplied to
--shadow-0noneFlat surfaces, default
--shadow-10 1px 3px rgba(0,0,0,0.06)Cards under hover
--shadow-20 4px 12px rgba(0,0,0,0.08)Popovers, dropdowns
--shadow-30 8px 24px rgba(0,0,0,0.12)Modals

There are no inner, glow, or coloured shadows. Most surfaces remain level 0; cards do not need a resting shadow when surface and border already establish their edge.

In both dark appearances, elevation is expressed first by lightening the surface. The ladder climbs midnight steps 1 → 2 → 4 → 6, adds a subtle top rim, and deepens the shadow only to seat the panel. Adjacent steps are too close to carry the hierarchy; a shadow alone is invisible against a dark page.

Motion#

Things slide into place. They do not bounce.

Durations#

TokenValueUse
--duration-micro100msColour and opacity changes
--duration-standard200msHover, focus, small moves
--duration-expand300msHeight and width changes, accordions
--duration-page400msRoute and view transitions

Easing#

TokenValueUse
--ease-outcubic-bezier(0.33, 1, 0.68, 1)Entering — arriving on screen
--ease-incubic-bezier(0.32, 0, 0.67, 0)Exiting — leaving screen
Radius ladder — 3 / 6 / 9 / 13 / full
sm 3px
md 6px
lg 9px
xl 13px
full
Elevation — shadow-0 through shadow-3
level 0 · flat
level 1 · card
level 2 · popover
level 3 · modal
Motion — slides into place, never bounces
200ms · ease-out — entering
100ms · colour and opacity

Motion rules#

  • All animation wraps in @media (prefers-reduced-motion: no-preference), or is disabled under prefers-reduced-motion: reduce.
  • CSS-only for HTML. For React, use Framer Motion with these same timing values.
  • Never animate text character-by-character.
  • Page transitions cap at 400ms.
  • Pressed controls do not scale down. Their colour remains at the hover state.
  • Slide transitions are a cut or 200ms fade. Sequential elements may fade up with 40–80ms staggered delays.
  • Do not use overshoots, parallax, or autoplay video.
css
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
Do

Use --ease-out for anything appearing and --ease-in for anything leaving. Keep durations on the ladder.

Don't

Add spring or bounce easing, animate layout-shifting properties, or exceed 400ms for any single transition.

Updated Aug 17, 2026