[@layout]: ../docs.layout.md

# Typography

Typefaces, body text and headings come from a few tokens. Set them in a theme
stylesheet or in `theme:` frontmatter; see [Themes](./themes.reference.md).

---

## Fonts

| Token | Default | Sets |
| --- | --- | --- |
| `--pmx-font-body` | `ui-sans-serif, system-ui, sans-serif` | Body text. |
| `--pmx-font-heading` | `var(--pmx-font-body)` | Document headings. |
| `--pmx-font-mono` | `ui-monospace, SFMono-Regular, Menlo, monospace` | Code. |

To use your own typeface, save its `.woff2` file in your project and declare it in
the stylesheet that uses it. A `url()` resolves beside the stylesheet:

```css
@font-face {
  font-family: "Studio Display";
  src: url("./fonts/display.woff2") format("woff2");
  font-weight: 200 800;
  font-display: swap;
}

:root {
  --pmx-font-heading: "Studio Display", var(--pmx-font-body);
}
```

End each stack with a fallback so text appears while the file loads. Keep the
font's license file beside it. Presets bring their own typefaces, served from your
site with their licenses.

---

## Body text

| Token | Sets |
| --- | --- |
| `--pmx-prose-size` | Document text size; `1rem`. |
| `--pmx-prose-leading` | Line height; `1.6`. |
| `--pmx-prose-flow` | Space between paragraphs, lists, headings and Blocks; `1em`. |
| `--pmx-prose-gutter` | Side padding of the document, at least `1rem`; `1.75rem`. |
| `--pmx-document-measure` | Maximum reading width, about 70 characters; `52ch`. |

In frontmatter, the first four are `prose` keys (`size`, `leading`, `flow`,
`gutter`) and the measure is `measure`:

```yaml
---
theme:
  prose:
    size: 1.0625rem
  measure: 64ch
---
```

---

## Heading sizes

Heading sizes step by one ratio from the body size: `h4` is one step larger and
`h1` four. `h5` and `h6` match the body size. Change the ratio on `:root` to
rebalance every level at once:

```css
:root { --pmx-prose-scale: 1.333; }
```

| Scale | `h4` | `h3` | `h2` | `h1` |
| --- | ---: | ---: | ---: | ---: |
| `1.2` | 1.2em | 1.44em | 1.73em | 2.07em |
| `1.25` (default) | 1.25em | 1.56em | 1.95em | 2.44em |
| `1.333` | 1.33em | 1.78em | 2.37em | 3.16em |

The scale applies at 48rem and wider. Narrower screens use a gentler ratio derived
from it, so `1.25` becomes `1.2` on a phone and every level keeps its proportion.
`1.2` suits dense reference pages; `1.333` gives a page more contrast. The same
setting works as `theme: { prose: { scale: 1.333 } }` in frontmatter.

`--pmx-prose-h1`, `--pmx-prose-h2` and `--pmx-prose-h3` override one level without
changing the others, for example a responsive title:

```css
:root { --pmx-prose-h1: clamp(2rem, 6vw, 3rem); }
```

Each preset chooses its own ratio, and a scale you set replaces it. Player sizes
slide headings for presentation separately.

---

## Heading blocks

Each Markdown heading renders as a heading block: the heading and its permalink
inside `.pmx-heading`, with a `level-h1` through `level-h6` class.

```html
<div class="pmx-heading level-h2">
  <h2 id="materials">Materials</h2>
  <a class="pmx-heading-anchor" href="#materials" aria-labelledby="materials"></a>
</div>
```

Style the heading element for its type and the block for its place in the flow:

```css
.workshop .pmx-heading.level-h2 { margin-block: 2.5rem 1rem; }
.workshop h2 { font: 700 1.6rem/1.2 var(--pmx-font-heading); }
.workshop .level-h1 + p { font-size: 1.25rem; }
```

The last rule styles the paragraph after a page title. Margins on the heading
element itself add to the block's spacing rather than replacing it. The permalink
sits beside the heading so the heading's accessible name stays its own text. Raw
HTML headings render as written, without a block or permalink.

## Related

- [Theme a site](./theme-a-site.guide.md)
- [Themes](./themes.reference.md)
- [Stylesheets](./styles.reference.md)
