Typography
Two typefaces: Inter carries UI and body copy, DM Sans the headings, with the system monospace as the code fallback. The scale, weights, tracking and leading come straight from Tailwind v4.
Font families#
Two bundled typefaces, both variable fonts loaded via next/font. font-sans (Inter) is the workhorse for UI, body and the smallest headings (h5–h6); font-heading (DM Sans, with an optical-size axis) carries the headings h1–h4, so the display voice reaches the content-level titles too. font-mono falls back to the platform UI monospace - nothing to download. A heading that acts as a 14px UI label rather than a title opts back into Inter with a plain font-sans, which beats the bare element rule.
Type scale#
Sizes are absolute (rem). Each ships a paired line-height that snaps the rendered leading onto the 4px / 0.25rem grid - the lead column.
text-xs
0.75rem · 12px
lh 1.333 → 1rem / 16px
text-sm
0.875rem · 14px
lh 1.429 → 1.25rem / 20px
text-base
1rem · 16px
lh 1.5 → 1.5rem / 24px
text-lg
1.125rem · 18px
lh 1.556 → 1.75rem / 28px
text-xl
1.25rem · 20px
lh 1.4 → 1.75rem / 28px
text-2xl
1.5rem · 24px
lh 1.333 → 2rem / 32px
text-3xl
1.875rem · 30px
lh 1.2 → 2.25rem / 36px
text-4xl
2.25rem · 36px
lh 1.111 → 2.5rem / 40px
text-5xl
3rem · 48px
lh 1 → 3rem / 48px
These are raw sizes, not heading roles. A bare h1–h4 carries the DM Sans face (with the negative tracking on h1–h2 only) while h5–h6 stay in Inter (see Font families), but none carry an intrinsic size, so each context steps off this scale on its own. For the document scale the Rich Text Editor maps onto H1–H4 and body copy, see its Prose scale.
Weights#
Four stops off the variable weight axis, shared by both faces. We skip 100–300 (too fragile at text sizes) and everything above 700 (heavier than the brand needs).
font-normal
400
body
font-medium
500
UI labels
font-semibold
600
headings
font-bold
700
emphasis
Tracking#
letter-spacing in em, so it scales with size. The px column is resolved at this 18px sample. Rule of thumb: tighten large display text (tracking-tight), leave body at normal, and only open up small all-caps labels.
tracking-tighter
-0.05em
−0.90px @ 18px
tracking-tight
-0.025em
−0.45px @ 18px
tracking-normal
0em
0px @ 18px
tracking-wide
0.025em
+0.45px @ 18px
tracking-wider
0.05em
+0.90px @ 18px
tracking-widest
0.1em
+1.80px @ 18px
Leading#
Unitless line-height, multiplied by the font-size. The px column is resolved at this 16px sample. Most components inherit the type scale’s paired leading; reach for these only to override it.
leading-tight
1.25
Vertical rhythm is the heartbeat of a page. Leading sets how far each line falls from the next, and on a tuned scale it lands on the grid.
20px @ 16px
leading-snug
1.375
Vertical rhythm is the heartbeat of a page. Leading sets how far each line falls from the next, and on a tuned scale it lands on the grid.
22px @ 16px
leading-normal
1.5
Vertical rhythm is the heartbeat of a page. Leading sets how far each line falls from the next, and on a tuned scale it lands on the grid.
24px @ 16px
leading-relaxed
1.625
Vertical rhythm is the heartbeat of a page. Leading sets how far each line falls from the next, and on a tuned scale it lands on the grid.
26px @ 16px
leading-loose
2
Vertical rhythm is the heartbeat of a page. Leading sets how far each line falls from the next, and on a tuned scale it lands on the grid.
32px @ 16px
Eyebrow#
The small tracked caps line that names a group or a section from above it: a sidebar group, a table-of-contents title, a band in a comparison table, a panel’s “Recent activity”. It is a role, not a size, so it ships as one utility from the token layer instead of five classes copied from screen to screen, where the size and the tracking used to drift a step apart at every call site.
eyebrow
12 / 16px
500 · 0.05em
eyebrow-mono
12 / 16px
400 · 0.08em
eyebrow is the sans label of the UI. eyebrow-mono is the typed-note voice (a Hero sign-off, a spec or build line); mono is already wide, so it opens less. Both carry the meta ink and sit on text-xs with its paired 16px leading. They set the role and nothing else: spacing and alignment stay where the label is used, and any one trait yields to the matching utility on the same element (font-semibold, tracking-wide, text-brand, text-white/80 on a photo). Never shrink one to 10 or 11px: a caps label smaller than the scale is a Badge.
// ✓ The role, in one class.
<p className="eyebrow">Recent activity</p>
<span className="eyebrow-mono">Build 2.4.1 · eu-west</span>
// ✓ One trait tuned, the rest of the role kept.
<h3 className="eyebrow font-semibold">On this page</h3>
<p className="eyebrow text-brand">New in 2.4</p>
// ✗ Hand-rolled: the size and tracking drift one call site at a time.
<p className="text-[0.6875rem] tracking-wide uppercase text-muted-foreground">Recent activity</p>