# Tokens — full reference

Canonical source: `src/index.css` (`@theme { }` block). This document mirrors that source. If they disagree, fix one — they must match.

The system is **paper-and-ink**. Light surfaces (off-white papers), near-black text on a cool axis (ink), one accent (mint). Status — ok / warn / danger — is desaturated and reserved for actual state. Hairlines are earned, never default.

---

## Paper — surfaces

| Token | Value | Tailwind | When to use |
|---|---|---|---|
| `--color-paper`   | `#FBFBFC` | `bg-paper`   | Page background. Resting state. The default canvas. |
| `--color-paper-2` | `#F2F3F5` | `bg-paper-2` | Default surface for cards, composers, tool chips. Hover state for ghost rows. |
| `--color-paper-3` | `#E8EAEE` | `bg-paper-3` | Pressed state. Hover state when the resting bg is already paper-2. |
| `--color-paper-4` | `#DCDFE4` | `bg-paper-4` | Deep press, double-stacked surfaces. Rare. |

**Rules:**
- Never introduce a 5th paper shade. Add depth with shadow or hairline, not a new fill.
- A surface with `paper-2` background hovers to `paper-3`, not `paper-2` (you'd lose the change).
- Use the `.scrim` class (`rgba(14, 16, 20, 0.20)`) for modal backdrops, not `bg-paper-4`.

---

## Ink — foreground

| Token | Value | Tailwind | When to use |
|---|---|---|---|
| `--color-ink`   | `#0E1014` | `text-ink`   | Primary text. Headings, body. |
| `--color-fg-1`  | `#2A2D35` | `text-fg-1`  | Strong meta — emphasized labels, hover state of muted text. |
| `--color-ink-2` | `#5A6072` | `text-ink-2` | Secondary text — descriptions, labels, ghost-button text at rest. |
| `--color-ink-3` | `#9CA1AE` | `text-ink-3` | Tertiary — timestamps, hints, placeholders, disabled text, ordinal counters. |

**Rules:**
- `ink-3` is *deemphasized but readable*. It's also the `disabled` text color. Don't reach for it as a synonym for "lighter ink-2."
- Action affordances (button text, link text) use `ink-2` minimum. `ink-3` reads as disabled.
- `fg-1` is rarely used directly — most components hover from `ink-2` to `ink`.

---

## Mint — accent

The single accent. Use sparingly — one accent per screen as a guideline.

| Token | Value | Tailwind | When to use |
|---|---|---|---|
| `--color-mint-100`   | `#C8EEDF` | `bg-mint-100`   | Soft accent surface — picker recommendation, callout fill, selection bg. |
| `--color-mint-300`   | `#6FD4B5` | `bg-mint-300`   | The logo dot. Rarely used elsewhere. |
| `--color-mint-500`   | `#2EBC95` | `bg-mint-500`   | Bright mint — for use on dark surfaces (e.g. block-code chrome). |
| `--color-mint-500-d` | `#14906F` | (use `accent`)  | The AA-rated mint primitive. |
| `--color-accent`     | `#14906F` | `bg-accent`, `text-accent`, `border-accent` | The default accent. **Use this, not `mint-500-d`.** |
| `--color-mint-600`   | `#0E7A5C` | `bg-mint-600`   | Pressed accent — `filled-mint` button hover. |
| `--color-mint-700`   | `#0A5A44` | `text-mint-700` | Deepest accent — label text on `mint-100` fills. |

**Common pairings:**
- `bg-mint-100` + `text-mint-700` — the picker-recommendation pattern.
- `bg-accent` + `text-paper` — `filled-mint` button.
- `bg-accent` (1px shadow) — focus ring (`.shadow-focus`).
- `text-accent` + 1px hairline-2 underline → `text-accent` + `border-accent` — markdown link hover.

---

## Status — desaturated, reserved

Signal only. Never branding, never decoration.

| Token | Value | Tailwind | When to use |
|---|---|---|---|
| `--color-ok`     | `#0E7A5C` | `text-ok`     | Completion, success — green that doesn't shout. |
| `--color-warn`   | `#B97712` | `text-warn`   | Caution, drift — desaturated amber. |
| `--color-danger` | `#A82E15` | `text-danger` | Error, destruction — desaturated brick. |

These tokens are deliberately near-mint in chroma so they don't fight the accent. If a fill is needed for warn/danger, use `bg-paper-2` plus the colored text — there are no `*-soft` background tokens. Pair with an icon or label; never communicate state by color alone.

---

## Hairlines — earned, not default

| Token | Value | Tailwind | When to use |
|---|---|---|---|
| `--color-hairline`   | `rgba(14, 16, 20, 0.06)` | `border-hairline`   | Internal separators that the eye barely registers. Row dividers, table cell borders. |
| `--color-hairline-2` | `rgba(14, 16, 20, 0.12)` | `border-hairline-2` | Borders that need to read. Card border on `paper`, button outline (`soft` variant), input border. |

**Rule:** if the layout works without a hairline, don't add one. Spacing and surface shifts do most separation work.

---

## Selection

| Token | Value |
|---|---|
| `--color-selection-bg` | `#C8EEDF` (mint-100) |

Native text selection. Foreground falls back to current ink.

---

## Type scale

Single source of truth. Components use these classes — never inline `text-[Npx]`. Each class sets size, weight, letter-spacing, line-height, and the default color.

| Class | Size | Weight | Tracking | Line | Family | Default color |
|---|---|---|---|---|---|---|
| `.text-display`  | 56px | 600 | -0.04em | 1.0  | sans | `ink` |
| `.text-h1`       | 40px | 600 | -0.02em | 1.1  | sans | `ink` |
| `.text-h2`       | 28px | 600 | -0.02em | 1.25 | sans | `ink` |
| `.text-h3`       | 22px | 500 | -0.01em | 1.25 | sans | `ink` |
| `.text-h4`       | 18px | 500 | -0.01em | —    | sans | `ink` |
| `.text-body-lg`  | 16px | 400 | 0       | 1.6  | sans | `ink` |
| `.text-body`     | 14px | 400 | 0       | 1.45 | sans | `ink` |
| `.text-small`    | 13px | 400 | 0       | 1.5  | sans | `ink-2` |
| `.text-eyebrow`  | 11px | 500 | +0.16em UC | — | sans | `ink-2` |
| `.text-mono`     | 12px | 400 | 0       | —    | mono | `ink-3` |
| `.text-quote`    | 22px | 400 italic | 0 | 1.4 | display | `ink-2` |

**Rules:**
- `.text-display` is for the rare 56px hero. `.text-h1` (40px) is the normal big heading.
- `.text-quote` is the only place `font-display` (Instrument Serif italic) appears.
- Eyebrows are lowercase in copy (`activity`, not `Activity`); the class applies `text-transform: uppercase` on top.
- `.text-mono` (Geist Mono) is for paths, ordinals, timestamps, kbd chips.

### Font feature settings

Applied globally on `body`:

```css
font-feature-settings: "ss01", "cv11", "tnum";
```

- `ss01` — single-storey `a` (cleaner at small sizes)
- `cv11` — slashed zero (disambiguates 0 from O)
- `tnum` — tabular numerals (column alignment in lists, tables)

---

## Spacing

Base 4px. The full scale:

| Token | px |
|---|---|
| `--spacing-1`  | 4 |
| `--spacing-2`  | 8 |
| `--spacing-3`  | 12 |
| `--spacing-4`  | 16 |
| `--spacing-5`  | 20 |
| `--spacing-6`  | 24 |
| `--spacing-7`  | 32 |
| `--spacing-8`  | 40 |
| `--spacing-9`  | 48 |
| `--spacing-10` | 64 |
| `--spacing-11` | 80 |
| `--spacing-12` | 96 |
| `--spacing-13` | 128 |

Sub-grid (`-0.5` = 2px, `-1.5` = 6px) is allowed only inside a single component for icon alignment.

### Component sizes

| Token | px | Use |
|---|---|---|
| `--spacing-row-dense` | 28 | `h-row-dense` — dense lists, small buttons |
| `--spacing-row`       | 36 | `h-row` — default button, default row |
| `--spacing-row-loose` | 44 | `h-row-loose` — comfortable file/thread rows |
| `--spacing-icon`      | 16 | `w-icon h-icon` — default icon (Lucide) |

### Container widths

| Token | px | Tailwind | Use |
|---|---|---|---|
| `--container-sidebar` | 260 | — | Left-rail sidebar |
| `--container-files`   | 320 | — | Files panel |
| `--container-chat`    | 720 | `max-w-chat` | Chat thread, palette, modal default |
| `--container-content` | 880 | `max-w-content` | Markdown reader, dashboard |

### Reading measure

Body text caps at 65–75ch. Below 50ch reads fragmented; above 80ch causes return-saccade fatigue.

---

## Radii

| Token | Value | Tailwind | Use |
|---|---|---|---|
| `--radius-xs`   | 3px  | `rounded-xs`   | Inline tags, kbd, code chips |
| `--radius-sm`   | 6px  | `rounded-sm`   | Buttons, inputs, small chips |
| `--radius-md`   | 10px | `rounded-md`   | Cards, popovers, tool chips, composers |
| `--radius-lg`   | 16px | `rounded-lg`   | Panels, modals |
| `--radius-xl`   | 24px | `rounded-xl`   | Large surfaces (rare) |
| `--radius-pill` | 9999px | `rounded-pill` | Pills, avatar chips |

**Rule:** never radius > 16px on an interactive control.

---

## Shadows

Utility classes declared in `src/index.css`. Don't inline `shadow-[...]`.

| Class | Definition | Use |
|---|---|---|
| `.shadow-1`     | `0 1px 0 rgba(14, 15, 17, 0.04)` | Subtle lift — cards that genuinely float |
| `.shadow-2`     | `0 1px 2px / 0 2px 8px` | Overlay, popover, dropdown |
| `.shadow-3`     | `0 2px 4px / 0 12px 32px` | Modal, command palette |
| `.shadow-focus` | `0 0 0 1px var(--color-accent)` | Focus ring (1px mint) |

**Rules:**
- The global `:focus-visible` already applies `.shadow-focus`. Don't reinvent it.
- Composers / search fields wrap input with the focus ring and add `.no-focus-ring` to the inner input to avoid the double ring.

---

## Motion

| Token | Value | Use |
|---|---|---|
| `--dur-instant` | 80ms | Tooltip show, hover snap |
| `--dur-fast`    | 140ms | Default for color, border, opacity transitions |
| `--dur-med`     | 220ms | Transforms, layout shifts |
| `--dur-slow`    | 360ms | Panel slides |
| `--dur-page`    | 520ms | Page transitions |
| `--ease`        | `cubic-bezier(0.32, 0.72, 0, 1)` | Default — exits fast, settles slow |
| `--ease-out`    | `cubic-bezier(0.16, 1, 0.3, 1)` | Entrances |
| `--ease-in`     | `cubic-bezier(0.7, 0, 0.84, 0)` | Exits |
| `--ease-spring` | `cubic-bezier(0.34, 1.56, 0.64, 1)` | Earned bounce only |

**The default transition is `.transition-default`** — animates `background-color`, `color`, `border-color`, `box-shadow`, `opacity` at `--dur-fast` with `--ease`. Use it everywhere unless you have a reason. Never `transition: all`. Never `duration-[Nms]` inline.

Honor `prefers-reduced-motion: reduce` — keep state changes, drop the animation.

---

## Z-index

| Class | Value | Use |
|---|---|---|
| `.z-base`    | 0  | Default — page content |
| `.z-raised`  | 10 | Sticky headers within scrolls |
| `.z-sticky`  | 20 | App-level sticky chrome |
| `.z-overlay` | 50 | Scrim, popover backdrop |
| `.z-modal`   | 60 | Modal dialog |
| `.z-cmdk`    | 70 | Command palette (above modals) |
| `.z-toast`   | 80 | Toast notifications (above everything) |

---

## assistant-ui overrides

`assistant-ui` ships with `--aui-*` HSL variables. `src/index.css` overrides them to mirror the paper-and-ink palette (mint primary, ink foreground, paper background). If you upgrade `assistant-ui`, re-check the override block — variables can be added or renamed.
