ZDDC/shared/fonts/README.md
ZDDC 6260aa4860 feat(typography): bake IBM Plex Sans + Source Serif 4 into every tool
System-default font stack ('-apple-system, BlinkMacSystemFont, Segoe UI,
…') is the textbook generic admin-tool look. The tools have a real point
of view (engineering documents, traceability, immutability); the
typography should reflect that.

Picks:
  --font          → IBM Plex Sans (400 + 600). UI body text. Distinctive
                    engineering sans with tabular nums and proper figures.
  --font-display  → Source Serif 4 (600). Headings, page titles,
                    .app-header__title. Reads as "document" not "UI label."
  --font-mono     → unchanged. Platform mono fonts are already excellent
                    and engineering tools rarely benefit from a custom mono.

Wiring:
  - Raw .woff2 files live in shared/fonts/ (~60 KB total, latin subset,
    SIL OFL 1.1 — both families)
  - shared/fonts.css is base64-inlined data URIs for those three fonts
    (~80 KB after b64 overhead). Generated once from the snippet in
    shared/fonts/README.md.
  - Every tool's build.sh prepends shared/fonts.css before shared/base.css
    so @font-face is parsed before any rule references the family names.
  - Headings (h1-h6) and .app-header__title now use var(--font-display);
    .app-header__title bumped 17→18px and letter-spacing reset since the
    serif doesn't need the original sans-text tightening.
  - table/code/.tabular-nums get font-variant-numeric: tabular-nums so
    tracking-number columns align vertically.

"Ship the record player with the record": zero CDN dependency at render
time. Tools render identically offline and online. Per-tool dist sizes
grew by ~80 KB.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 20:09:59 -05:00

63 lines
2.2 KiB
Markdown

# shared/fonts/
Source `.woff2` files for the typography baked into every tool. These are
the *raw* font bytes; the actual `@font-face` declarations live in
`shared/fonts.css` as base64 data URIs so single-file HTML tools render
identically offline (`file://`) and online with no CDN dependency.
## Files
- `ibm-plex-sans-400.woff2` — UI body text (regular weight)
- `ibm-plex-sans-600.woff2` — UI emphasis (semibold)
- `source-serif-4-600.woff2` — display/headings (semibold)
Latin subsets only. ~60 KB total raw; ~80 KB once base64-inlined.
## Regenerating `shared/fonts.css`
Run from the repo root:
```sh
python3 - <<'PY'
import base64, pathlib
fonts = [
('IBM Plex Sans', 400, 'ibm-plex-sans-400.woff2'),
('IBM Plex Sans', 600, 'ibm-plex-sans-600.woff2'),
('Source Serif 4', 600, 'source-serif-4-600.woff2'),
]
out = pathlib.Path('shared/fonts.css')
lines = ['/* shared/fonts.css — base64-inlined woff2. Generated by',
' * shared/fonts/README.md instructions; do NOT edit by hand. */', '']
for family, weight, fn in fonts:
b64 = base64.b64encode((pathlib.Path('shared/fonts') / fn).read_bytes()).decode('ascii')
lines += ['@font-face {',
f" font-family: '{family}';",
' font-style: normal',
f' font-weight: {weight};',
' font-display: swap;',
f" src: url(data:font/woff2;base64,{b64}) format('woff2');",
'}', '']
out.write_text('\n'.join(lines))
PY
```
## Adding or swapping a font
1. Download the new `.woff2` into this directory (latin subset only — keep
the bundle small).
2. Update the `fonts` list in the snippet above to include the new family
+ weight + filename.
3. Re-run the regen snippet.
4. Update `--font` or `--font-display` tokens in `shared/base.css`.
5. `./build` and verify every tool's `dist/*.html` still includes
`@font-face` (three by default).
## Sourcing
Originally downloaded from the `@fontsource` npm packages via jsdelivr:
- IBM Plex Sans 400/600: `@fontsource/ibm-plex-sans@5.0.18`
- Source Serif 4 600: `@fontsource/source-serif-4@5.0.5`
Both licenses are SIL Open Font License 1.1. Fontsource bundles only the
latin subset by default, which is exactly what we want.