Typography
Newsreader for display. Geist for UI. Geist Mono for IDs and queries. Body never below 16. Caption 12 never as the only text on a control. Sentence case labels, never all-caps.
The voice is in Tone of voice. This page is the scale.
Roles
Compact is the 0–1279 instrument. Wide is 1280+. Only display, title, and metrics step. Body stays 16.
| Role | Face | Compact | Wide | Line-height | Tracking | Use |
|---|---|---|---|---|---|---|
| Display | Newsreader | 32/40 | 40/48 | 1.2 | −0.015em | Empty headlines, brand moments |
| Title | Newsreader | 24/32 | 28/36 | 1.25 | −0.015em | Section theses |
| Heading | Geist 600 | 18/28 | 20/28 | 1.4 | −0.011em | Panel titles, in-page headings |
| Body | Geist 400 | 16/24 | 16/24 | 1.5 | −0.011em | Reading. Does not shrink. |
| Body-sm | Geist | 14/20 | 14/20 | 1.45 | −0.011em | Tables, dense chrome |
| Caption | Geist | 12/18 | 12/18 | 1.5 | +0.01em | Metadata. Never the only text on a control. |
| Label | Geist 500 | 12/16 | 12/16 | 1.35 | −0.011em | Control labels, sentence case |
| Metric | Geist 500 tabular | 28/36 | 32/40 | 1.2 | −0.02em | The number an operator came for |
| Metric-lg | Geist 500 tabular | 40/48 | 48/56 | 1.15 | −0.02em | Hero metric |
| Mono | Geist Mono | 13/20 | 13/20 | 1.5 | 0 | IDs, queries, tokens |
| Mono payload | Geist Mono | 12/18 | 12/18 | 1.5 | 0 | Payloads, raw lines |
Sizes are font-size / line-height in px. Geist UI tracking is −0.011em unless noted.
Responsiveness
Only display, title, and metrics step down on compact viewports. Body stays 16.
Shrinking body to fit more dashboard makes it unreadable. Density changes padding, not the floor. See Layout.
Grid relation
16/24 body is the 4px grid (24px = 6 units). Icon 24 pairs with body. 16-box icons pair only with caption.
Metrics are unconstrained in measure. Prose is not.
Readability
- Prose measure: 45–75ch. Metrics: unconstrained.
- Tabular numerals on every number (
font-variant-numeric: tabular-nums). - Hyphens off on metrics. A value does not break.
- Sentence case on labels. Never all-caps, including kickers that are not the brand wordmark.
- Caption 12 is metadata. It is not a button label.
Performance
font-display: swap. UI is Geist, so Newsreader never blocks the instrument.
Fallbacks: ui-sans-serif, system-ui for Geist; Georgia, ui-serif for Newsreader.
System-only is rejected: we need tabular numerals and the brand voice. Subset if self-hosting later.
Guidelines
| Do | Don't |
|---|---|
| One display role per view. | Newsreader on tables, buttons, or metrics. |
| Step through the scale. Heading then title, not display then caption. | Skip sizes to make a panel feel “more branded.” |
| Body in Geist. IDs in mono. | Body in mono. A paragraph is not a payload. |
| True weight (400 / 500 / 600). | Fake bold (synthetic, text-stroke, or a heavier fallback). |
Specimen
Every role, live. Display, title, and metrics step at 1280px. Body stays 16.
A dashboard is an instrument.
Signal over chrome
Compose, don't template
Operators scan. Chrome that competes with data is a defect.
Compact / standard / roomy. Sparse is useless; crushed is unreadable.
Updated 12:04 · range 24h
Refresh interval
1,284
99.95
svc.metrics.ingest
POST /v1/query