Two font families — Inter for UI and Literata for reading content — paired with Open Props size, weight, line-height, and letter-spacing scales.
Inter — body / UI text (default font-family on <body>).
Literata — long-form reading content (.font-reading). Italic variant supported.
Both typefaces are files in this tree, under /vendor/fonts/ — six
.woff2 faces next to the @font-face rules that name them, in
/vendor/fonts/fonts.css. Nothing fetches them from a font service, and
no page may load a typeface from another origin: a third family means
adding its .woff2 files and its @font-face blocks beside those,
never a <link> to a CDN.
Fonts must be local so the offline snapshot can include them. Externally hosted fonts can require network requests at startup and fall back to another font when offline. A cross-origin font URL also sends the reader's IP address to a third party before any consent prompt appears, adds a connection before the font can display, and makes browser tests depend on internet access.
Six faces: two subsets — latin and latin-ext — across
three family/style pairs. Each face is the variable font, so one file carries a
weight range rather than a single weight:
300–600.300–600.300–400.
Font weights above the supplied range use the maximum available weight. For example, Inter at --font-weight-7 renders at 600, while bold Literata italic renders at 400. Inter has no italic file, so browsers synthesize its slant; Literata has a true italic face. Glyphs outside the Latin and Latin Extended subsets use the next suitable font in the stack. To support another subset, add its font file and @font-face declaration.
Every face declares font-display: swap, so text paints in the fallback
immediately and re-paints when the face arrives. The fallback fonts reduce layout changes during this swap: the body font stack ends with fonts whose metrics resemble Helvetica, rather than the
sans-serif generic, and .font-reading falls back to Georgia. A generic family can resolve to different fonts on different machines, changing the text width when the preferred font is unavailable.
--font-size-*Static: --font-size-00 .. --font-size-8. Fluid: --font-size-fluid-0..3 (scale with viewport via clamp()).
Size 0 — small / caption (--font-size-0)
Size 1 — button / compact (--font-size-1)
Size 2 — body copy / section heading (--font-size-2)
Size 3 — subheading (--font-size-3)
Size 5 — section heading (--font-size-5)
Fluid 2 — scales with viewport (--font-size-fluid-2)
Nothing declares a font-size on <body> or <html>, so text starts at
the 1 rem root default — the same value as --font-size-1, which is also what buttons and inputs
take. Reach for --font-size-2 for larger body copy or section headings.
Guideline: fluid sizes for headlines, static sizes for body text.
--font-weight-*Range: --font-weight-1 (thin) .. --font-weight-9 (black).
Weight 3 (300 — light) · Weight 4 (400 — regular) · Weight 5 (500 — medium) · Weight 6 (600 — semibold) · Weight 7 (700 — bold)
--font-lineheight-00 .. --font-lineheight-5 — tight (display, .95) to loose (caption, 2).--font-letterspacing-0 .. --font-letterspacing-7 — tracking. The scale is not
monotonic: 0 is the only negative step (-.05em, for tightening display text),
1..7 widen from .025em to 1em./index.css adds --font-size-xs (0.6875 rem, between --font-size-00 and --font-size-0) for pills and micro-snippets.
--text-1 / --text-2..truncate, .visually-hidden.font-display: swap, and why adding a font-loading shim requires review.