The brand typefaces are loaded once and assigned to the design system's font slots. The type scale itself — the sizes, the leading, the breakpoints at which headings step down — is the engine's and is not a brand decision; the brand supplies the faces and says which slot each fills.
Font slots
| Slot | Face | Loaded by |
|---|---|---|
| Inter | A Google Fonts link the generator emits from brand.json |
|
| Erode | An @font-face rule in theme.css pointing at assets/fonts/, preloaded from brand.json |
|
| Inter | Aliased to in theme.css, because the engine's badge reads it |
|
| engine default (a system monospace stack) | Not a brand slot; still dresses every code, pre, kbd and token tag |
|
| , , | engine defaults | Not brand slots; nothing on the site uses them |
Headings read --title-family, which the theme points at --font-secondary, so every h1 to h6 renders in Erode. Body text and interface read --font-primary, with three engine exceptions: pull quotes and drop caps read --font-secondary (a blockquote is Erode italic, the one place the italic file loads), badges read --font-tertiary, and code reads --font-quaternary. Page code references the slots, never a family name.
Web hierarchy
Sizes are stepped rem values, shown here in pixels at desktop and at 959 px and below, where the headings step down one size.
| Element | Size | Leading |
|---|---|---|
h1 |
48 → 36 | 1.2 |
h2 |
40 → 32 | 1.2 |
h3 |
36 → 28 | 1.2 |
h4 |
32 → 24 | 1.2 |
h5 |
28 → 22 | 1.2 |
h6 |
24 → 20 | 1.4 |
| Body | 16 | 1.6 |
| Lead () | 20 | |
| Small () | 14 | |
| 14, uppercase, tracked 0.12em | 1.2 |
Type follows browser zoom and the reader's font-size preference because every step is a rem value; there is no viewport-relative type, and no page writes its own breakpoint typography.
Where the web differs from the design file
- Body is 16 px on the web, 20 px in the design file. The 20 px setting is the lead paragraph,
--text-size-l. - Size names do not line up. The design file calls 20 px
font-mand 24 pxfont-l; the engine's--font-mis 18 px and--font-lis 20 px. Read the pixel value in an inspect panel, never the name. - Eyebrow tracking is narrower on the web. The design file tracks the 18 px eyebrow by 8 px (0.44em); renders at 14 px with 0.12em, because wider tracking wraps uppercase text at small sizes.
- The 94 px display size has no engine step. The largest is
--font-10xlat 72 px, reached through a display class rather than a heading element.
Loading
Inter arrives from Google Fonts through the googleFontsUrl in cms/blackdoctor/brand.json; the generator writes the link into every page head. Erode is self-hosted: the file sits in assets/fonts/, theme.css declares it with @font-face, and brand.json lists it under fontPreload so the browser fetches it before the stylesheet asks for it. The fallback stack is Georgia, so a page reads as a serif heading over sans text even before the file lands.