Typography

One family, thirteen styles, four weights. Type belongs to the scale layer, because it does not change between themes.

See it

The styles as they meet in a card: a title in heading/h4, a lead line in subheading/md, body copy, a button label, and a timestamp in caption/md. Five styles are usually all one surface needs.

Waiting room

Upcoming appointments

Three clinicians available this afternoon

The appointment was moved to Thursday at 14:30 and the client has been notified. The room is ready from 14:15.

ConfirmedLast edited 4 minutes ago

Choosing a style

The name says the job, not the size. heading/h1 is the page title and there is one per page; h2 a section, h3 a subsection, h4 a card, and each level is a step down the scale, so a subordinate heading can never overpower its parent. subheading/lg is a lead paragraph or a prominent label, and subheading/md a panel heading.

body/md, at 14px, is the default, and it is the most used style in the system. Fourteen rather than sixteen is a reason you can name: this is a dense professional tool, where a table of forty rows has to fit a screen, and Inter holds at fourteen. body/lg is for long-form copy — a letter, a note the reader settles into — and nothing else. caption/md is helper text and metadata, caption/sm the dense table cell and the timestamp, and caption/caps an overline for a section of a panel, the one place capitals earn their tracking; it is not a label style, and a form label is body text.

Button labels have their own two styles because a label is set tighter than a line of body copy and never wraps. Everything is Inter; code and the site’s own measurements are the system monospace. Two families, and the second only where the content is a value.

The scale

Line height follows the role: headings sit near 1.1, body copy between 1.5 and 1.6, and a caption in between, because a caption wraps to two lines at most. Tracking follows the size — negative on the large sizes, where Inter’s letters drift apart, and positive on the small ones, where they crowd — and body copy at reading size takes none.

heading/h140/44, ×1.10, -1.8px · Page title

Thursday, 14:30

heading/h232/36, ×1.13, -1.6px · Section title

Thursday, 14:30

heading/h328/32, ×1.14, -1.1px · Subsection title

Upcoming appointments

heading/h424/28, ×1.17, -0.8px · Card title

Upcoming appointments

subheading/lg20/24, ×1.20, -0.3px · Lead paragraph, prominent label

Three clinicians available this afternoon

subheading/md18/24, ×1.33, -0.2px · Panel heading

Three clinicians available this afternoon

body/lg16/24, ×1.50, -0.1px · Long-form copy

The appointment was moved to Thursday at 14:30 and the client has been notified.

body/md14/22, ×1.57, 0px · Default body — the most used style in the system

The appointment was moved to Thursday at 14:30 and the client has been notified.

button/lg16/20, ×1.25, -0.2px · Large button label

Confirm booking

button/md14/18, ×1.29, -0.1px · Default button label

Confirm booking

caption/md12/16, ×1.33, +0.2px · Helper text, metadata

Last edited 4 minutes ago

caption/sm11/14, ×1.27, +0.8px · Dense table cells, timestamps

Last edited 4 minutes ago

caption/caps10/12, ×1.20, +0.8px · Section eyebrows, overline labels

Waiting room

Weights

Four, and they mean things. Regular is text. Medium is the current item — the page in the sidebar, the selected row’s name — and a label that needs to hold its own beside body copy. Semibold is a heading and a button label. Bold is reserved; nothing in the system uses it yet, and the first thing that does should say why. Nothing goes under regular: a light weight disappears at text sizes, and the smallest size here is ten pixels.

regular 400 — The appointment was moved to Thursday.

medium 500 — The appointment was moved to Thursday.

semibold 600 — The appointment was moved to Thursday.

bold 700 — The appointment was moved to Thursday.

Setting text

A line of prose is capped at 37.5rem — the 68 characters of the body size, set as a length rather than in ch so a heading gets the same measure as a paragraph. Headings wrap balanced, so a two-line title breaks evenly; descriptions wrap pretty, so a single word never lands alone on the last line. Long-form text takes neither.

Numbers that change or line up — a table column, a timer, the ratios in the margin of this site — are set in tabular figures, so 14 and 27 take the same width and a sort changes nothing but the order. Nothing truncates without a way to the whole value: a dialog title wraps, and a token name does not break across lines because a broken identifier cannot be copied.

Punctuation is the real thing: curly quotes in prose and straight ones in code, an en dash for a range — 14:00–15:30 — and the ellipsis character rather than three stops. Copy is stored in its natural case and capitals are a transform, so a redesign never means retyping.

1,114 · 27 · 2,003 — tabular

1,114 · 27 · 2,003 — proportional

“Moved to Thursday, 14:00–15:30 … and confirmed.”

Corrections carried over

Three defects in the source are fixed here: two caption styles were set in Montserrat while everything else was Inter; letter-spacing mixed px and percent between weights of the same style, resolving to fractions of a pixel that were plainly not the intent; and the all-caps family carried its transform on the regular weight but not on medium or semibold.

The system this was derived from stored the cross-product of style and weight as forty-four separate text styles. Weight is an independent axis, so thirteen styles plus four weights expresses the same system in seventeen tokens — and makes it possible to change every semibold at once.

Accessibility

Text is real text, selectable and resizable: the site sets text-size-adjust: 100% so a phone does not inflate it on its own, and the page reflows to 320px and to 200% zoom without a sideways scroll. Font smoothing is set once on the root, where macOS would otherwise render every weight heavier than drawn. The document declares its language, so quotes, hyphenation and a screen reader’s voice follow it.

One thing is recorded rather than solved. A text field is body size, 14px, and iOS Safari zooms the whole page into a field under sixteen. The two fixes look different — sixteen on a phone, or fourteen held by a transform — and the choice is still to be made.