# Context: the design system (as it actually is)

Read this before touching CSS. Everything here was extracted from the current
files, not assumed.

## There is no single palette. There are three.

The same semantic names carry different values depending on which stylesheet
loaded them:

| Token      | `styles.css`, `rules/styles.css` | `chapters.css`, `skills-review/styles.css` | `hands-on/*/styles.css` |
| ---------- | -------------------------------- | ------------------------------------------ | ----------------------- |
| `--paper`  | `#f5f4f1`                        | `#f6f3ed`                                  | `#f4f3ef`               |
| `--ink`    | `#172f42`                        | `#122534`                                  | `#173044`               |
| `--muted`  | `#697b89`                        | `#65717a`                                  | `#687d8c`               |
| `--line`   | `#d8dee2`                        | `#d0d5d2`                                  | `#d5dde1`               |
| `--blue`   | `#527f9f`                        | `#215675`                                  | `#5683a1`               |
| `--gold`   | `#efc76b`                        | `#ebbf58`                                  | `#efc86d`               |
| `--accent` | `#7c78a8`                        | —                                          | —                       |
| `--deep`   | `#102536`                        | —                                          | —                       |
| `--red`    | —                                | `#a7483f` (chapters only)                  | —                       |
| `--violet` | —                                | `#6b668f` (review desk only)               | —                       |

Most deltas are a few units per channel — drift, not intent. `--blue` is the
exception: `#527f9f` vs `#215675` is a visible difference and may be deliberate.

**Decision required before any component work** (task 02). Options:

- **Canonicalize** to one palette. Recommended. The sub-perceptual deltas
  collapse; only `--blue` needs a human's eye on a before/after screenshot.
- **Keep three named surfaces** (`--surface-guide`, `--surface-chapter`,
  `--surface-lab`) if the drift turns out to be intentional per section.

Do not "just pick one" silently in the middle of another task. This is its own
reviewed change with visual diffs attached.

## The typography — fixed 2026-09-05

`styles.css` line 1 used to read:

```css
@font-face {
  font-family: Manrope;
  src: url('https://fonts.googleapis.com/css2?family=DM+Mono&family=Manrope:wght@400;600;700;800&display=swap');
}
```

`src:` in an `@font-face` must point at a font binary. That URL returns a CSS
stylesheet, so no browser could load a face from it. For the whole life of the
site, every `font-family:Manrope,Arial,sans-serif` rendered as **Arial** and
every `font:… 'DM Mono',monospace` rendered as the **generic monospace** face —
`'DM Mono'` was never declared as a family at all.

**This was escalated and the human chose the real fonts.** Manrope and DM Mono
are now self-hosted in `public/fonts/`, latin and latin-ext subsets only, under
the SIL Open Font License. One `fonts.css` serves both trees: Astro links it
from `BaseLayout.astro`, the legacy root `styles.css` `@import`s it. Self-hosted
rather than linked from Google because `scripts/audit-ui.mjs` rejects any
external `<link>`/`<script>`, and because the site is presented in workshop
rooms with unreliable networks.

**This changed how every page renders**, deliberately. It is the one sanctioned
visual change in the migration. Screenshots taken before 2026-09-05 show Arial
and are no longer a valid baseline.

`Georgia, serif` for emphasis (`h1 em`, `.hero em`) is untouched and still real.

## Type scale

`Georgia, serif` is used deliberately for emphasis (`h1 em`, `.hero em`) and is
real — it is a system font, so it does render. Keep it.

Sizes are all `clamp()`, roughly:

| Role            | Value                                                     |
| --------------- | --------------------------------------------------------- |
| Display / `h1`  | `clamp(56px,9vw,126px)`                                   |
| Section `h2`    | `clamp(36px,5vw,65px)`                                    |
| Sub-head        | `clamp(24px,3vw,38px)`                                    |
| Pull-quote      | `clamp(22px,3vw,36px)`                                    |
| Body            | `15px/1.6` … `18px`                                       |
| Eyebrow / label | `10–11px` monospace, `letter-spacing:.08–.1em`, uppercase |

There are 14+ distinct clamp triples doing near-identical jobs. Collapse to a
named scale (`--step-0` … `--step-6`) during tokenization; the visual result
should be unchanged within a pixel or two at common viewports.

## Breakpoints

Sixteen distinct max-widths are in use: 420, 520, 530, 560, 600, 620, 720, 800,
850, 880, 900, 1000, 1050, 1100 — plus `min-width:1600px` and
`min-width:2200px`.

Collapse to a named set (suggested: 560 / 800 / 1100 / 1600 / 2200) and prove
equivalence with screenshots at the _old_ breakpoint values, since that is where
regressions will hide.

`@media(prefers-reduced-motion:reduce)` is already respected in several
stylesheets. Keep it — see [`../rules/animation.md`](../rules/animation.md).

## House style worth preserving

The visual identity is editorial-print: flat colour blocks, hairline `1px`
rules, uppercase monospace eyebrows with wide tracking, very tight negative
letter-spacing on display type (`-.06em` … `-.08em`), grid layouts with
`gap:1px` over a background colour to fake borders, and near-zero border-radius.

That last trick (`gap:1px` + parent background) is used everywhere. It is
intentional. Do not replace it with `border`.
