Design System

Paper and ink, hairline rules, letterspaced small print, one loaded Riso drum, and motion that stays out of the way. Every value below is read from the site’s stylesheets at build time and every component is the real one, so this page cannot drift from the site.

01

Color

Two neutral palettes, no tint. Emphasis is ink itself: --accent is the highlight text color and selection is inverted ink. Dark is the default; .theme-dark pins it to a subtree, which keeps the search dialog dark on paper.

Dark, default
  • --bg-primary #0a0a0a
  • --bg-secondary #161616
  • --bg-tertiary #222
  • --text-primary #ededed 16.9:1
  • --text-secondary #a3a3a3 7.8:1
  • --text-tertiary #818181 5.1:1
  • --text-highlight #fff 19.8:1
  • --border-primary #262626
  • --border-secondary #4d4d4d
  • --surface-hover #ffffff14
Paper
  • --bg-primary #f5f5f5
  • --bg-secondary #e7e7e7
  • --bg-tertiary #dcdcdc
  • --text-primary #111 17.3:1
  • --text-secondary #555 6.8:1
  • --text-tertiary #666 5.3:1
  • --text-highlight #000 19.3:1
  • --border-primary #d9d9d9
  • --border-secondary #a5a5a5
  • --surface-hover #00000010

Ratios are each text color on its own --bg-primary (WCAG 2).

02

Riso drum

One loaded drum as a print mark: a 6px swatch beside a kicker, shown here magnified and at actual size. Never body text, never a wash, never a second palette.

Latest

  • Fluorescent Pink --ink #ff48b0
  • Blue --ink-offset #0078bf
03

Type

Three families, self-hosted through the Astro font pipeline, and only the cuts listed are loaded. Headings are set in the sans; the serif is an editorial accent.

  • PP Neue Montreal --ff-base 350 · 400 · 400 italic · 500 · 600 · 700 Everything: text, headings, labels and pills.
  • Instrument Serif --ff-serif 400 · 400 italic Editorial accent: work titles and quotes.
  • Geist Mono --ff-mono 400 · 500 Small print: specs, captions and numbers.

Weights

  • Aa Book 350 --font-weight-book Long-form reading
  • Aa Regular 400 --font-weight-regular Body text (default)
  • Aa Italic 400 --font-weight-regular Emphasis in running text
  • Aa Medium 500 --font-weight-medium Labels, pills and kickers
  • Aa SemiBold 600 --font-weight-semibold Thesis title, strong
  • Aa Bold 700 --font-weight-bold Headings (--font-weight-heading)

Scale

  • --fs-xs clamp(0.72rem, 0.1vi + 0.68rem, 0.76rem) Identities, illustrations and websites that stay readable in print, on a phone, and years from now.
  • --fs-sm clamp(0.9375rem, 0.25vi + 0.74rem, 0.96rem) Identities, illustrations and websites that stay readable in print, on a phone, and years from now.
  • --fs-base clamp(1.125rem, 0.45vi + 0.89rem, 1.25rem) Identities, illustrations and websites that stay readable in print, on a phone, and years from now.
  • --fs-md clamp(1.25rem, 0.76vi + 1.06rem, 1.67rem) Identities, illustrations and websites that stay readable in print, on a phone, and years from now.
  • --fs-lg clamp(1.56rem, 1.2vi + 1.26rem, 2.22rem) Identities, illustrations and websites that stay readable in print, on a phone, and years from now.
  • --fs-prose clamp(1.25rem, 0.875rem + 1.5vi, 1.5rem) Identities, illustrations and websites that stay readable in print, on a phone, and years from now.
  • --fs-prose-lg clamp(1.1875rem, 1rem + 0.8vi, 1.625rem) Identities, illustrations and websites that stay readable in print, on a phone, and years from now.

Fluid sizes with floors: small print never under 11.5px, small text never under 15px. The right column is the size at this viewport.

--font-weight-heading
700
--line-height-heading
1.1
--letter-spacing-heading
-0.02em
--line-height-base
calc(2ex + 6px)
04

Space & layout

A fixed step scale inside components, a fluid one for page rhythm. The gutter never drops under a display cutout.

Steps

  • --space-4xs 0.125rem · 2px
  • --space-3xs 0.25rem · 4px
  • --space-2xs 0.375rem · 6px
  • --space-xs 0.5rem · 8px
  • --space-s 0.75rem · 12px
  • --space-m 1rem · 16px
  • --space-l 1.5rem · 24px
  • --space-xl 2rem · 32px
  • --space-2xl 3rem · 48px

Fluid

  • --space-fluid-2xs clamp(0.375rem, 0.3182rem + 0.2424vi, 0.5rem)
  • --space-fluid-s clamp(0.75rem, 0.6364rem + 0.4848vi, 1rem)
  • --space-fluid-l clamp(1.5rem, 1.2727rem + 0.9697vi, 2rem)
  • --space-fluid-2xl clamp(3rem, 2.3182rem + 2.9091vi, 4.5rem)

Layout

--gutter
max(clamp(1.25rem, 5vw, 4rem), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px))
--page-width
1480px
--dock-clearance
6.75rem
05

Radius & rules

Two radii plus pill. A button sits one step under its card, so the pair stays concentric.

  • --radius-sm 6px
  • --radius-md 0.5rem
  • --radius-pill 9999px
  • 6 + 2 = 8 Concentric --radius-card · --space-4xs
--radius-card
var(--radius-md)
--button-radius
var(--radius-sm)

Borders

  • --border-width-hairline 1px
  • --border-width-strong 2px
06

Motion

Short, plain transitions for chrome; authored curves only where something travels. Play runs every row at once. With reduced motion nothing travels.

Durations

  • --duration-instant 100ms
  • --duration-fast 150ms
  • --duration-base 200ms
  • --duration-moderate 250ms
  • --duration-slow 300ms
  • --duration-slower 400ms
  • --duration-slowest 500ms

Curves

  • --ease-default ease
  • --ease-in ease-in
  • --ease-out ease-out
  • --ease-in-out ease-in-out
  • --ease-standard cubic-bezier(0.4, 0, 0.2, 1)
  • --ease-accelerate cubic-bezier(0.4, 0, 1, 1)
  • --ease-out-quad cubic-bezier(0.25, 0.46, 0.45, 0.94)
  • --ease-out-quint cubic-bezier(0.22, 1, 0.36, 1)
  • --ease-out-back cubic-bezier(0.175, 0.885, 0.32, 1.275)
  • --ease-sheet cubic-bezier(0.32, 0.72, 0, 1)
  • --ease-in-out-strong cubic-bezier(0.8, 0.01, 0.11, 0.98)

Shorthands

--transition-fast
var(--duration-fast) var(--ease-default)
--transition-base
var(--duration-base) var(--ease-default)
--lift-distance
-10px
07

Layers

Fixed chrome from back to front. The bottom fade sits under the dock and the top fade over it; the menu clears both. Skip link, theme-swap snapshot and cursor always win.

  1. 10000 --z-cursor
  2. 9999 --z-theme-transition
  3. 2000 --z-skip-link
  4. 1002 --z-menu-toggle
  5. 1001 --z-menu
  6. 1000 --z-fade-top
  7. 999 --z-dock
  8. 900 --z-fade-bottom
08

Touch targets

24px is the floor everywhere and --tap-target-size on a coarse pointer. Hit areas grow; the drawn shape and the row spacing do not move.

All
  • Interactive pills draw at 24px; an unpainted ::after carries the hit area to 44px.
  • Social links use the same strip as ::before, and the 28px video control grows to 44px.
  • Small standalone links take 4px of padding and -4px of margin: bigger target, same layout.
09

Components

Live, rendered with the site’s own components and classes.

Pills

Medium caps trimmed to cap height; active is ink on paper. They run the works filter and the grid and list toggle.

Quiet caps with ↗ for off-site links. Email copies the address and says so.

Small print

Kickers, spec blocks and captions at --fs-xs in --text-tertiary, in letterspaced caps or Geist Mono.

Selected

Type
PP Neue Montreal, Instrument Serif, Geist Mono
Print
Riso, fluorescent pink and process blue

Fig. 1 Astro and Contentful

Video

Muted loops load near the viewport. One control pauses every loop on the site and remembers it; with reduced motion the poster stays.

A native dialog pinned to the dark palette in both themes. ⌘ K opens it from anywhere.

⌘ K

Cursor lens

A fine pointer gets a custom cursor. Over “view” and “read” it turns into a frosted lens, the one glass surface on the site.

Point here

Dock

The floating bar at the foot of every page, this one included. --dock-clearance keeps content and keyboard focus above it.

--z-dock
999
--dock-clearance
6.75rem

Toast

At most one per session, on --bg-secondary with --shadow-elevated. It pauses on hover, focus and open dialogs and is announced politely.

--shadow-elevated
0 25px 30px -7px rgb(0 0 0 / 45%), 0 12px 20px -8px rgb(0 0 0 / 35%)
10

Rules

Interaction

  • Keyboard first: Full support per WAI-ARIA. Visible focus rings are mandatory.
  • Touch targets: 24px minimum, 44px on touch.
  • Feedback: Toasts and status messages are announced politely. Loading states keep their label.

Typography & layout

  • Optical alignment: Adjust by ±1px when perception beats geometry.
  • Text glue: Use non-breaking spaces for terms like 10 MB and ⌘ K.
  • Line height: Headings 1.1; body calc(2ex + 6px), which tracks the x-height.

Accessibility

  • Contrast: Meet APCA contrast, and raise it on hover and focus.
  • Motion: Respect prefers-reduced-motion. Animate transform and opacity only.
  • Semantics: Use native elements (`button`, `a`, `dialog`) before ARIA.