Typography
Three families, no more. Self-hosted as woff2 in public/fonts/ — never a
runtime call to Google to paint our own identity. Declared in
styles/ds/typography.css; the @font-face blocks live at the top of
styles/globals.css.
| Family | Variable | Job |
|---|---|---|
DM Sans | --font-display | Display. H1s, big numerals, marquee callouts |
Inter | --font-body | Workhorse. Body, UI, buttons, nav, captions |
JetBrains Mono | --font-mono | Data. Figures, codes, labels, anything that should read as system output |
Rules from the guide, and they are hard: never more than three weights on one screen, never more than two families in one paragraph, never the display font for body copy.
The seven tiers
These are Tailwind sizes minted in @theme — use the tier, not a pixel value.
| Class | Size / line-height | Used for |
|---|---|---|
text-display | 26px / 1.25 | The page <h1>, DM Sans 800, tracking-tight |
text-section | 17px / 1.3 | A panel or section title, 600 |
text-body | 15px / 1.6 | Body copy, descriptions, prose |
text-caption | 13px / 1.45 | Dense UI text, menu items, tile sublabels |
text-data | 14px / 1.3 | Figures in mono, tabular-nums |
text-eyebrow | 11px | Mono-caps labels (use .mono-caps, below) |
text-stat | 56px / 1.0 | The stat-tile numeral, DM Sans 800 |
A new tier must be registered in TYPE_TIERS in lib/utils.ts on the same
commit — see 11-traps.md. This is not optional; skipping it deletes type
sizes at random.
Marketing surfaces get the guide's larger ramp (hero 56–72px, H2 36–44px, H3 24–28px, body 16–18px). Product surfaces use the tiers above — a dashboard with a 64px h1 is a landing page with a table in it.
.mono-caps — the system's label voice
font-family: var(--font-mono);
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.08em;
This is how a section, a column, a role, a state, or a scope is labelled — in the rail, on a stat tile, in a badge, in a table cell. A section is marked with type, never with a coloured rule or a filled header band.
Use Eyebrow from components/brand/devices.tsx when it is a standalone label;
the raw .mono-caps class when it is inline in a cell or a badge.
Figures
Anything a reader compares vertically is mono and tabular:
font-mono tabular-nums. The table's align="number" column does this for you
and right-aligns it. A figure that shifts by a pixel as it updates is a figure
that cannot be scanned.
Accent in headlines
One to three words maximum, and only when those words are the subject
(--accent-ink, never --brand-accent as text). Never more than 30% of a
headline.
Copy voice
Short, English, and it reads like a tool, not documentation. Caveats belong in a docs page or a provenance record, not in the chrome. No em-dashes or en-dashes in product or marketing copy — commas, periods, or "to" for ranges (guide section 17).