03 · Type
Typography
Three families, three jobs: Space Grotesk speaks, Inter reads, JetBrains Mono measures. All three load from Google Fonts and everything sits on the tokenized scale below.
Families
Display, body, mono
The differential is infinitesimal change — the moment where one state becomes another.
Sphinx of black quartz, judge my vow.
ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 ∂ & ? ! % @ ( ) [ ] — æøß
400Sphinx of black quartz, judge my vow.
500Sphinx of black quartz, judge my vow.
600Sphinx of black quartz, judge my vow.
700Sphinx of black quartz, judge my vow.
ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 ∂ & ? ! % @ ( ) [ ] — æøß
Sphinx of black quartz, judge my vow.
const d = (f, x, h = 1e-9) => (f(x + h) - f(x)) / h;
ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 {} [] () => !== 0O 1lI
The eyebrow motif
Small, mono, amber
The signature typographic move: a tiny tracked-out mono label above the heading, always in the accent amber. It kicks off nearly every section on every DiffLab surface — including this one, live, just above.
Live demo · The eyebrow
Then the heading answers
Eyebrow whispers the category; the heading makes the claim.
.eyebrow {
font-family: var(--dl-font-family-mono); /* JetBrains Mono */
font-size: 0.8125rem; /* --dl-font-scale-eyebrow-size */
font-weight: 500;
letter-spacing: 0.1em; /* --dl-font-scale-eyebrow-tracking */
line-height: 1.4;
text-transform: uppercase;
color: var(--dl-accent); /* amber; amber-bright on dark */
}
Scale
Six steps, tokenized
Headings are Space Grotesk with negative tracking that tightens as the
size grows; body is Inter; the eyebrow is mono. Every value below is a
--dl-font-scale-* token — each sample renders live at its
own size.
| Style | Live sample | Size | Weight | Tracking | Line-height | Family |
|---|---|---|---|---|---|---|
h1 |
Differential |
2.25rem | 900 | -0.05em | 1.1 | Space Grotesk |
h2 |
Differential |
1.875rem | 800 | -0.04em | 1.15 | Space Grotesk |
h3 |
Differential |
1.5rem | 700 | -0.03em | 1.2 | Space Grotesk |
h4 |
Differential |
1.25rem | 600 | -0.02em | 1.3 | Space Grotesk |
body |
Differential |
1.125rem | 400 | 0 | 1.6 | Inter |
eyebrow |
Differential |
0.8125rem | 500 | 0.1em | 1.4 | JetBrains Mono |
App conventions
Type inside internal apps
The internal-app system keeps the same families but tunes the metrics for dense, data-heavy screens.
html { font-size: 106.25% }— a 17px base (--dl-layout-html-font-size), slightly larger than browser default for long working sessions.line-height: 1.55for app UI text (--dl-layout-line-height) — tighter than the marketing body’s 1.6.font-variant-numeric: tabular-numsin every data table, so digit columns align.
- 1,111,111
- 8,808,808
- 4,914,141
- 1,111,111
- 8,808,808
- 4,914,141
Implementation
Loading & one known bug
All three families come from Google Fonts. Put this in the <head>:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400..700&family=Inter:wght@400..700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
The font-grotesk bug
difflab.ai currently references a font-grotesk utility class
that is never defined, so headings silently fall back to Inter and the
display voice disappears. This guide is the corrected standard — headings
must render in Space Grotesk. If you inherit markup using that class, the
fix is one line:
.font-grotesk { font-family: var(--dl-font-family-display); }