Reference

Design system

The single source of truth, rendered in the real font. Every value on the site resolves to a token here. Premium comes from restraint, typography, and space, not decoration.

This page documents the system as built. Where it disagrees with the original design.md spec, this page wins: the spec still describes three typefaces, warm neutrals, and uppercase mono labels, none of which shipped.

01

Colour

Around 90% of the page is paper. Lime is a fill only, always carrying ink text, and it goes loud only on dark sections. One accent, no second brand hue.

--paper#FAFAFAPage canvas, neutral near-white
--paper-2#F5F5F5Recessed surface, alt sections
--surface#F5F5F5Neutral surface (alias of --paper-2)
--surface-raised#FFFFFFCard lifted off the page canvas
--surface-chip#EBEFF5Work-card brand chip pill
--line#E5E5E5Hairlines, borders, dividers
--soft#858585Tertiary text, labels
--read#666666Secondary reading text
--ink-2#404040Mid text, between read and ink
--ink#161618Primary text, dark sections

On dark

--on-dark#F3F0E8Primary text on ink
--on-dark-2rgba(243, 240, 232, 0.62)Secondary, the dim half of a two-tone lead
--on-dark-3rgba(243, 240, 232, 0.35)Tertiary, quiet rules under links
--line-on-darkrgba(243, 240, 232, 0.14)Hairlines on ink and dark sections

Accent

--accent#DDFF00Brand lime, fills only
--accent-deep#D2F200Accent hover
--on-accent#161618Text on lime, always ink

Rules

  • Lime is a fill only, and always carries ink text.
  • Never lime text on paper. Never white text on lime.
  • Links, marks, and focus rings on light surfaces use ink, not lime.
  • One accent. Differentiate categories with labels, never a second hue.
  • Lime appears about once per light view, and goes loud only on dark sections.

02

Typography

One typeface, PP Neue Montreal. Two weights, 400 and 500. Differentiate by size, weight, colour, and tracking, never by another family. Inverse tracking and inverse leading do most of the work. No italic, no serif accent word, and never all-caps or all-lower-case.

Display XLWeight 500 · clamp 2.4 to 4.6rem · leading 1.02 · tracking -0.02em
We design and build
Display LWeight 500 · clamp 1.9 to 3.4rem · leading 1.04 · tracking -0.02em
Products that ship
Display MWeight 500 · clamp 1.45 to 2.3rem · leading 1.1 · tracking -0.015em
A studio that performs
HeadingWeight 500 · clamp 1.15 to 1.5rem · leading 1.2 · tracking -0.01em
Card and block titles
LeadWeight 400 · clamp 1.05 to 1.28rem · leading 1.5 · muted, two-tone capable
A design and engineering studio taking products from first idea to launched.
BodyWeight 400 · 17px · leading 1.6 · primary reading
Primary reading text. Restraint over noise, and a scaffolding that signals an engineer’s rigor.
Body SWeight 400 · 15px · leading 1.55 · secondary, captions
Secondary reading text and captions, a touch quieter than body.
CaptionWeight 400 · 12px · leading 1.4 · figure marks, fine print
Fig. 01 / warm editorial, grotesk-forward
Two-toneInk phrase, rest recedes to --read. The emphasis device.

We take products from first idea to launched.Built to perform, not just look the part.

Measures

.m-display16chDisplay headlines
.m-lead46chLeads and intros
.m-body64chBody copy

How the face is delivered

  • Static per-weight instances, not the variable font. The variable file defaults its weight axis to 200, and WebKit does not reliably apply the CSS weight over it, so Safari and iOS rendered the whole site hairline.
  • Three instances ship: 400 and 500 are the system. A 600 exists only for the Figma-literal Design Solutions section, which sits outside these tokens by design.
  • Adding a weight means generating a new instance, not switching back to the variable file. Astro's Fonts API owns --font-display.

03

Spacing

Base unit 4px. Tight gaps for things that belong together, large gaps between distinct ideas. Air reads as expensive.

--s-14px
--s-28px
--s-312px
--s-416px
--s-524px
--s-632px
--s-748px
--s-864px
--s-996px
--s-10128px
--s-11192px

Layout

--container1200pxMax content width
--section-yclamp(5rem, 10vw, 10rem)Section vertical rhythm
--header-hcalc(var(--s-6) * 2 + 32px)Overlay header height

Container padding is clamp(1.2rem, 5vw, 4rem). Gaps run 8 to 12px for related elements, 48 to 96px between distinct ideas.

04

Radius and borders

Three radii for interface: pill, card, chip. Borders are 1px hairlines. The system is flat, no ambient shadows or glows, so depth comes from space and hairlines. One honest exception: the Figma-derived project cards on the home page and /work carry larger art-directed corners (16 to 40px) that predate --r-card and do not resolve to it. Treat those as art direction, not as a fourth step to reach for.

--r-pill100pxInteractive, buttons
--r-card14pxCards, panels
--r-chip8pxChips, inputs

05

Motion

A few durations and eases, reused. Consistency is what makes expressive motion read as designed. Everything is gated behind reduced-motion.

Duration

--dur-hover180msHover, micro
--dur-ui320msUI transitions
--dur-item520msMenu item rise
--dur-reveal800msScroll and entrance reveals
--dur-panel1250msMenu panel reveal
--stagger-base140msFirst nav item delay
--stagger-step55msDelay between nav items

Easing

--ease-uicubic-bezier(.4, 0, .2, 1)UI motion
--ease-outcubic-bezier(.32, .72, 0, 1)Entrances, the default
--ease-cinematiclinear(0, 0.029, … 1)Spring overshoot, menu panel. Full curve in tokens.css

06

Components

The small, shared set, all defined in base.css. Never hand-copy one into a component's scoped styles; extend the shared class instead.

6.1 Actions

Two primaries, chosen by the surface they sit on, plus one quiet secondary.

  • .cta-badge is primary on light surfaces: ink pill, lime arrow badge nested left.
  • .cta is primary on dark surfaces, where an ink pill would read ink-on-ink.
  • Gloss is the one deliberate exception to the flat rule, and it belongs to the primaries only: the whole of .cta, and the arrow disc inside .cta-badge. Everything else stays flat.

Badge CTA, primary on light

.cta-badge

Glossy CTA, primary on dark

.cta

Quiet link, secondary

.link-quiet

6.2 Labels and metadata

The quiet scaffolding: what names a section, tags a card, or carries a figure.

Label, the eyebrow base

.label
Design and engineering studio

Eyebrow, leads every section

.eyebrow .label

What we believe

Chip, grey pill and white mark

.work__chip pattern
ServicesWhat we do

6.3 Surfaces

Where a section changes ground. Flat everywhere: separation comes from the surface tone and a hairline, never a shadow.

Dark punctuation section

.section--dark

Selected work

Where the lime sings.

Start a project

Card, flat on paper

--r-card + --line

A card title

White on paper, one hairline, no shadow.

6.4 Section anatomy

Every section leads with an eyebrow, a label plus a short rule, then a two-tone statement, then content on a 1px hairline grid. Metadata rows sit at 12px in--soft, separated by middots or slashes.

07

Accessibility and motion gating

The floor, not the ceiling. These are non-negotiable.

  • Focus ring: 2px solid ink, offset 3px, on every interactive element. It switches to lime on dark surfaces, and it is the only box-shadow the system allows.
  • Motion is gated on html.anim, added pre-paint only when motion is allowed. Reduced-motion and no-JS both render the final state, with zero JS and no flash. Always include a failsafe that reveals content if setup throws.
  • The shared entrance is .reveal, a one-shot fade and 16px rise. At most one or two pinned or scrubbed scenes per page.
  • AA contrast, keyboard navigable, responsive to mobile.