# Typography

Two typefaces: Geist for interface text and JetBrains Mono for code, IDs, shortcuts and numbers in tables. Content text is 14px, and the scale is tuned around it.

## Typefaces

Geist is the interface font. JetBrains Mono is for code, IDs, shortcuts and numbers in tables.

| Use | Stack | Token |
| --- | --- | --- |
| Interface | Geist, ui-sans-serif, system-ui, sans-serif | `font-family-sans` |
| Code | 'JetBrains Mono', ui-monospace, monospace | `font-family-mono` |

The quick brown fox jumps over the lazy dog. 0123456789

Both are licensed under the SIL Open Font License 1.1.

## Type roles

A role sets size, weight and leading together. Use a role for headings and body text, never one role's size with another's weight.

Heading 1
Heading 2
Heading 3
Body text, 14px, for paragraphs and table cells.

| Role | Size | Weight | Leading |
| --- | --- | --- | --- |
| `heading-1` | 32px | 500 | 1.2 |
| `heading-2` | 24px | 500 | 1.25 |
| `heading-3` | 18px | 500 | 1.3 |
| `body` | 14px | 400 | 1.5 |

## UI sizes

Small interface text uses the `font-size-*` steps, so labels and captions stay in the same scale as the roles.

| Token | Size | Use for |
| --- | --- | --- |
| `font-size-xs` | 12px | Badges, tokens, captions and timestamps. |
| `font-size-sm` | 13px | Secondary text next to a primary line: descriptions, helper and error text, and `sm` controls. |
| `font-size-md` | 14px | Body copy, input values, table cells, and default (`md`) and `lg` controls. |
| `font-size-lg` | 16px | Headings and `xl` controls. |
| `font-size-xl` | 18px | Larger headings. |
| `font-size-input` | 14px | Inputs, selects and textareas. 16px on touch screens, so iOS Safari does not zoom the page on focus. |

## Rules

Four rules from the design skill, each with one thing to write and one to avoid.

### Headings use sentence case

Capitalize only the first word and proper nouns. Product and feature names keep the casing their owner uses. Title Case and `uppercase` make headings slower to read and louder than the content under them.

```tsx
// Do
<h2 className="text-heading-3">Billing history</h2>
// Avoid
<h2 className="text-heading-3">Billing History</h2>
<h2 className="text-heading-3 uppercase">Billing history</h2>
```

### Never change letter spacing

No `tracking-*` classes and no `letter-spacing` in CSS. Geist and JetBrains Mono are already spaced for the sizes in the scale; tightening or loosening them is how generated UI starts to look generated.

```tsx
// Do
<span className="text-xs font-medium text-text-secondary">Last 30 days</span>
// Avoid
<span className="text-xs font-medium tracking-wide uppercase text-text-secondary">Last 30 days</span>
```

### No bold

The scale has regular (400), medium (500) and semibold (600). There is no 700, and `font-bold` does nothing in a Werewolf project.

- Headings: the weight comes with the role (`text-heading-1` to `-3` set it). Don't add a weight class on top.
- Emphasis inside text, labels, button text: `font-medium`.
- `font-semibold` only when medium can't separate a label from medium text right next to it.

```tsx
// Do
<p className="text-body">Payment failed. <span className="font-medium">Update your card</span> to keep access.</p>
// Avoid
<p className="text-body">Payment failed. <b>Update your card</b> to keep access.</p>
```

### Inline code is 0.9em

Mono text sitting inside a sans sentence looks bigger than the words around it at the same size. Use `code-inline`: it sets the mono family at `0.9em`, so it follows whatever size the sentence is.

```tsx
// Do
<p className="text-body">Run <code className="code-inline">npm run build</code> again.</p>
// Avoid
<p className="text-body">Run <code className="font-mono">npm run build</code> again.</p>
```
