# Style tokens

Every look in Zvessa comes from a **style**: a small record of settings called tokens. Screens and
blocks never pick a colour, font or size of their own; they ask the style. So changing one token
changes every screen at once, and anyone (or their AI) can make a new look without code.

There are three built-in styles, made exactly the way anyone's own style is made:

| Style | id | Feel |
| --- | --- | --- |
| **Classic** | `classic` | Clean surfaces, soft corners, gentle shadows. chat-app's classic look. |
| **Futuristic** | `futuristic` | Deep background, glowing outlines, a grid with moving coloured lines. |
| **Tech** | `tech` | chat-app's futuristic look, value for value: near-black glass, thin lit lines, a quiet grid, Space Grotesk and mono numbers. |

This page lists every token: what it controls and its value in each built-in style. Values are
generated from `convex/lib/styles.ts`, so they match the app.

## The five tokens that change the most

If you only change a few things, change these. Ask the AI ("make the accent green") or set them in
`/look/changes`:

| Token | Example | What you see |
| --- | --- | --- |
| `look.style` | `"tech"` | The whole look at once. |
| `colors.accent` | `"#22c55e"` | Buttons, links, the open chat, glows. |
| `colors.bg` | `"#0b0d12"` | The page behind everything. |
| `shape.radius` | `8` | How round cards and bubbles are. |
| `type.body` | `"grotesk"` | The font for all words. |

```json
{ "look": { "style": "tech", "changes": { "colors": { "accent": "#22c55e" } } } }
```

## How tokens fit together

- **Groups.** Tokens sit in eight groups: `colors`, `type`, `shape`, `space`, `surface`,
  `backdrop`, `motion` and `parts`. A style only lists what it changes; everything else comes from
  Classic.
- **Layers.** Lowest first: Classic's base → the style (and what it `extends`) → the space's
  `look.changes` → a page's own `look` → a person's own look on their device. Each layer has the
  same shape, so any of them can change any token.
- **Schemes.** `schemes.dark` and `schemes.light` (or any name, like `night`) hold the colours that
  differ between them. `colors` holds the ones that don't.
- **Colour values** can be `#rrggbb`, `#rrggbbaa`, `white`, `black`, `transparent`, another colour's
  name (`accent`), `mix(a, b, 30%)` (30% of a, the rest b), `alpha(a, 20%)` or `contrast(a)`.
  Formulas nest. Any new colour name you add (say `brand2`) can be used by blocks and mini-apps.

## 1. Colours

`colors` and `schemes.<name>`. The five columns are the built-in styles in their schemes;
"·" means the style doesn't set it (screens fall back as described).

### Ground and panels

| Token | Controls | Classic light | Classic dark | Futuristic dark | Tech dark | Tech light |
| --- | --- | --- | --- | --- | --- | --- |
| `bg` | The page behind everything. | `#f6f7f9` | `#0d0f14` | `#06080c` | `#06080c` | `#edeceb` |
| `surface` | Cards, panes and sheets (Tech: see-through glass). | `#ffffff` | `#171a22` | `rgba(34, 211, 238, 0.04)` | `rgba(13, 19, 27, 0.82)` | `rgba(245, 245, 244, 0.82)` |
| `raised` | Things that sit on a card: menus, their bubbles, popovers. | `#ffffff` | `#1d212b` | `rgba(34, 211, 238, 0.09)` | `#121a24` | `#fffdf8` |
| `panel` | Tech only: the glass colour that surface (82%) and rowFill (55%) are made from. | · | · | · | `#0d131b` | `#f5f5f4` |
| `elev` | Tech only: sheets, menus and toasts that float over everything. | · | · | · | `#0a0f15` | `#fffdf8` |
| `glass` | Tech only: header and tab bar fill (bg at 66%, frosted on the web). | · | · | · | `rgba(6, 8, 12, 0.66)` | `rgba(237, 236, 235, 0.8)` |
| `rowFill` | Tech only: the faint card behind each chat list row. | · | · | · | `rgba(13, 19, 27, 0.55)` | `rgba(245, 245, 244, 0.55)` |
| `grid` | The backdrop grid lines (transparent = no grid). | `rgba(0, 0, 0, 0)` | `rgba(0, 0, 0, 0)` | `rgba(34, 211, 238, 0.07)` | `rgba(120, 200, 255, 0.035)` | `rgba(61, 107, 255, 0.07)` |

### Text

| Token | Controls | Classic light | Classic dark | Futuristic dark | Tech dark | Tech light |
| --- | --- | --- | --- | --- | --- | --- |
| `text` | Main words. | `#0f172a` | `#eef1f7` | `#e6f6ff` | `#e6edf3` | `#1b1d22` |
| `text2` | Second lines: previews, descriptions. | `#545a68` | `#abadb3` | `#a7b3bb` | `#b7c2cf` | `#464b55` |
| `text3` | Quiet words: times, hints, labels. | `#777c87` | `#898b91` | `#7a848a` | `#8c9aab` | `#636a75` |

### Lines

| Token | Controls | Classic light | Classic dark | Futuristic dark | Tech dark | Tech light |
| --- | --- | --- | --- | --- | --- | --- |
| `line` | Every thin line: card edges, dividers, outlined chips. | `rgba(15, 23, 42, 0.1)` | `rgba(255, 255, 255, 0.09)` | `rgba(34, 211, 238, 0.3)` | `rgba(120, 200, 240, 0.14)` | `rgba(59, 83, 145, 0.22)` |
| `lineTint` | Tech only: the hue lines are made from (chat-app's --fx-line). | · | · | · | `#78c8f0` | `#3b5391` |
| `lineStrong` | Tech only: a slightly brighter line (their bubbles). | · | · | · | `rgba(120, 200, 240, 0.2)` | `rgba(59, 83, 145, 0.3)` |

### Accent

| Token | Controls | Classic light | Classic dark | Futuristic dark | Tech dark | Tech light |
| --- | --- | --- | --- | --- | --- | --- |
| `accent` | The space's colour: buttons, links, the open row, glows. | `#3d6bff` | `#6d8dff` | `#22d3ee` | `#6d8dff` | `#3d6bff` |
| `accent2` | A second accent: gradients (Classic's own bubble runs accent → accent2). | `#5c65ff` | `#7979ff` | `#a78bfa` | `#8a76ff` | `#8a76ff` |
| `onAccent` | Text on a filled accent. | `#ffffff` | `#ffffff` | `#111827` | `#ffffff` | `#ffffff` |
| `accentSoft` | Tech only: the faint accent fill of selected things. | · | · | · | `rgba(109, 141, 255, 0.06)` | `rgba(61, 107, 255, 0.07)` |
| `accentLine` | Tech only: the lit accent outline (buttons, your bubbles). | · | · | · | `rgba(109, 141, 255, 0.6)` | `rgba(61, 107, 255, 0.6)` |

### Status

| Token | Controls | Classic light | Classic dark | Futuristic dark | Tech dark | Tech light |
| --- | --- | --- | --- | --- | --- | --- |
| `success` | Done, online, applied. | `#16a34a` | `#16a34a` | `#34d399` | `#4fe3a0` | `#12804f` |
| `warn` | Waiting, needs a look. | `#d97706` | `#d97706` | `#fbbf24` | `#f2a35e` | `#b8620f` |
| `danger` | Errors, failed replies, delete. | `#dc2626` | `#dc2626` | `#f87171` | `#ff6b6b` | `#cc3339` |
| `gold` | Coins, prizes, 1st place. | `#f59e0b` | `#f59e0b` | `#fbbf24` | `#f59e0b` | `#f59e0b` |
| `win` | Wins in games. | `#12a150` | `#12a150` | `#34d399` | `#4fe3a0` | `#4fe3a0` |

### Chat

| Token | Controls | Classic light | Classic dark | Futuristic dark | Tech dark | Tech light |
| --- | --- | --- | --- | --- | --- | --- |
| `bubbleMine` | Tech only: fill of your bubbles (Classic uses an accent gradient). | · | · | · | `rgba(109, 141, 255, 0.05)` | `#e0e5f6` |
| `bubbleTheirs` | Tech only: fill of other people's bubbles (Classic uses raised). | · | · | · | `rgba(255, 255, 255, 0.02)` | `rgba(255, 253, 248, 0.7)` |
| `field` | Tech only: the message box and search fill. | · | · | · | `rgba(255, 255, 255, 0.02)` | `rgba(255, 253, 248, 0.6)` |
| `note` | Tech only: team-only notes. | · | · | · | `#1c1810` | `#fbf2dc` |
| `noteText` | Tech only: words in a note. | · | · | · | `#f2c46e` | `#7a4f00` |

### Media

| Token | Controls | Classic light | Classic dark | Futuristic dark | Tech dark | Tech light |
| --- | --- | --- | --- | --- | --- | --- |
| `media` | Behind photos and videos. | `#000000` | `#000000` | `#000000` | `#000000` | `#000000` |
| `onMedia` | Words over photos and videos. | `#ffffff` | `#ffffff` | `#ffffff` | `#ffffff` | `#ffffff` |

## 2. Text

`type`. Fonts are names, never files: `system`, `rounded`, `serif`, `mono`, and two bundled with
the app, `grotesk` (Space Grotesk) and `jetbrains` (JetBrains Mono). They load only when a style
uses them (about 145 KB together).

| Token | Controls | Classic | Futuristic | Tech |
| --- | --- | --- | --- | --- |
| `type.body` | Font for all words. | `system` | `system` | `grotesk` |
| `type.display` | Font for titles and headings. | `system` | `mono` | `grotesk` |
| `type.mono` | Font for numbers, times, counts and status lines. | `mono` | `mono` | `jetbrains` |
| `type.scale` | Multiplies every text size (0.75 to 1.5). | `1` | `1` | `1` |
| `type.bodyWeight` | Weight of normal words (400 to 800). | `400` | `400` | `400` |
| `type.headingWeight` | Weight of titles. | `700` | `600` | `700` |
| `type.headingCase` | `upper` makes titles capitals. | `none` | `upper` | `none` |
| `type.tracking` | Letter spacing of titles, in px. | `0` | `1.5` | `0` |

**Text roles** (`type.roles`, from the "Layout and text blocks" work): every piece of text is one of
`display`, `title`, `headline`, `subtitle`, `body`, `callout`, `caption`, `label`, `overline`,
`number`, `quote`, `code`. Each role can set `size`, `weight`, `font` (`body`, `display`, `mono` or
a font name), `case`, `tracking`, `leading` and `tone` (a colour). A block names a role, never a
size. Tech's `label` and `overline` are chat-app's small caps line: 10.5 px, mono, uppercase, wide
tracking, in `text3`; its `number` role is mono.

## 3. Shape

`shape`.

| Token | Controls | Classic | Futuristic | Tech |
| --- | --- | --- | --- | --- |
| `shape.radius` | Corners of cards, sheets and bubbles (0 to 40). | `14` | `4` | `18` |
| `shape.radiusSmall` | Corners of buttons, fields and chips. | `10` | `2` | `12` |
| `shape.line` | Width of every line (0 to 4). | `1` | `1` | `1` |
| `shape.marks` | Marks on cards: `true`/`corners` = small L marks on all four corners; `lit` = one lit top-left corner (Tech). | `False` | `True` | `lit` |

## 4. Space

`space`.

| Token | Controls | Classic | Futuristic | Tech |
| --- | --- | --- | --- | --- |
| `space.density` | `compact` (6 px steps), `regular` (8), `roomy` (10). | `regular` | `regular` | `regular` |

## 5. Surfaces, edges and glow

`surface`. How boxes are drawn.

| Token | Controls | Classic | Futuristic | Tech |
| --- | --- | --- | --- | --- |
| `surface.treatment` | `fill` (solid), `outline` (a line, nearly empty inside), `glass` (see-through), `gradient`. | `fill` | `outline` | `glass` |
| `surface.depth` | `flat`, `shadow` (soft drop shadow) or `glow` (a light in the accent). | `shadow` | `glow` | `glow` |
| `surface.edge` | Header bottoms and tab bar tops: `line`, or `lit` = an accent line that fades out at both ends (chat-app's futuristic headers). | `line` | `line` | `lit` |
| `surface.glow` | How strong glows are, 0 to 1. Under 0.5 a soft halo (Futuristic); 0.5 and up a tight neon edge (Tech). | `0.22` | `0.22` | `1` |

## 6. Backdrop

`backdrop`. The ground behind pages and chats. It never moves while you read, stops when the app is in the background, and turns off when the device asks for less motion.

| Token | Controls | Classic | Futuristic | Tech |
| --- | --- | --- | --- | --- |
| `backdrop.kind` | `plain`, `grid`, `dots` or `gradient`. | `"plain"` | `"grid"` | `"grid"` |
| `backdrop.size` | Grid or dot spacing, in px. | `24` | `24` | `30` |
| `backdrop.beams` | A line of light that sweeps down the grid, again and again. | `false` | `true` | `false` |
| `backdrop.lights` | Now and then a short light runs along one grid line, across or down (chat-app's; one about every 20 s). | `false` | `false` | `true` |
| `backdrop.lines` | 1 to 4 colours the grid lines sweep through. | `[]` | `["#22d3ee", "#a78bfa", "#ff5c9a"]` | `[]` |
| `backdrop.glow` | 0 to 3 colours of soft light that drift behind everything. | `[]` | `["rgba(34, 211, 238, 0.5)"]` | `[]` |
| `backdrop.floor` | A lit floor of lines at the bottom that moves toward you. | `false` | `false` | `false` |
| `backdrop.streaks` | 0 to 3 thin light streaks that cross now and then. | `0` | `2` | `0` |

## 7. Motion

`motion`.

| Token | Controls | Classic | Futuristic | Tech |
| --- | --- | --- | --- | --- |
| `motion.speed` | `off`, `calm`, `normal` or `snappy`. | `normal` | `snappy` | `normal` |
| `motion.haptics` | Taps you feel: `off`, `light` or `full`. | `light` | `light` | `light` |

## 8. Parts

`parts.<part>`. One piece of the screen restyled on its own, on top of `surface`. Each part can set
`treatment`, `depth`, `radius`, `bg`, `text` and `line` (colours or formulas).

| Part | What it is | Without a setting |
| --- | --- | --- |
| `pane` | A large area (a side pane). | `surface` |
| `card` | Cards and panels. | `raised` |
| `button` | Main buttons. | filled `accent` |
| `input` | Text fields. | `surface` |
| `bubbleMine` | Your chat bubbles. | Classic: accent → accent2 gradient |
| `bubbleTheirs` | Other people's bubbles. | Classic: `raised` with a faint shadow |
| `tabbar` | The bottom tab bar. | `surface` |
| `header` | Top bars. | `surface` |
| `row` | Chat list rows (and HQ, AI and page rows). | bare (no box) |
| `avatar` | Pictures without a photo. | a gradient in the name's colour |
| `badge` | Unread counts. | filled `accent` |
| `tile`, `chip` | App tiles and small pills (Layout work). | from `surface` |

What the built-in styles set:

**Futuristic**

| Part | treatment | depth | radius | bg | text | line |
| --- | --- | --- | --- | --- | --- | --- |
| `bubbleMine` | `outline` | · | · | `rgba(34, 211, 238, 0.08)` | `#e6f6ff` | `#22d3ee` |
| `button` | `outline` | · | · | `rgba(34, 211, 238, 0.1)` | `#22d3ee` | `#22d3ee` |

**Tech (dark)**

| Part | treatment | depth | radius | bg | text | line |
| --- | --- | --- | --- | --- | --- | --- |
| `card` | `glass` | `flat` | · | `rgba(13, 19, 27, 0.82)` | · | `rgba(120, 200, 240, 0.14)` |
| `pane` | `glass` | `flat` | · | `rgba(13, 19, 27, 0.82)` | · | `rgba(120, 200, 240, 0.14)` |
| `button` | `outline` | `glow` | `12` | `rgba(109, 141, 255, 0.06)` | `#6d8dff` | `rgba(109, 141, 255, 0.6)` |
| `input` | `outline` | `flat` | `12` | `rgba(255, 255, 255, 0.02)` | · | `rgba(109, 141, 255, 0.28)` |
| `bubbleMine` | `outline` | `glow` | · | `rgba(109, 141, 255, 0.05)` | `#e6edf3` | `rgba(109, 141, 255, 0.6)` |
| `bubbleTheirs` | `outline` | `flat` | · | `rgba(255, 255, 255, 0.02)` | `#e6edf3` | `rgba(120, 200, 240, 0.2)` |
| `header` | `glass` | `flat` | · | `rgba(6, 8, 12, 0.66)` | · | `rgba(0, 0, 0, 0)` |
| `tabbar` | `glass` | `flat` | `22` | `rgba(10, 15, 21, 0.9)` | · | `rgba(120, 200, 240, 0.14)` |
| `row` | `outline` | `flat` | `16` | `rgba(13, 19, 27, 0.55)` | · | `rgba(120, 200, 240, 0.08)` |
| `avatar` | `outline` | `glow` | · | · | · | · |
| `badge` | `outline` | `glow` | · | `rgba(109, 141, 255, 0.1)` | `#6d8dff` | `rgba(109, 141, 255, 0.65)` |

Classic sets no parts.

## Examples

**Tech with a green accent.** Everything else stays Tech:

```json
{ "look": { "style": "tech", "changes": { "colors": { "accent": "#22c55e" } } } }
```

**A style of your own, made from Tech.** List only what changes:

```json
{
  "id": "midnight",
  "name": "Midnight",
  "extends": "tech",
  "schemes": { "dark": { "bg": "#05060a", "accent": "#f59e0b" } },
  "shape": { "radius": 12 },
  "backdrop": { "lights": false }
}
```

**Classic, rounder and roomier, in a serif:**

```json
{ "look": { "style": "classic", "changes": { "shape": { "radius": 22 }, "space": { "density": "roomy" }, "type": { "display": "serif" } } } }
```

**A page with its own look** (a games page that glows), in `/pages/N/look`:

```json
{ "schemes": { "dark": { "bg": "#070814" } }, "backdrop": { "kind": "grid", "lines": ["#2dd4bf", "#a78bfa"], "glow": ["alpha(accent, 40%)"], "floor": true } }
```

## For developers

- Read the resolved style through `src/lib/workspace.tsx`: `useWorkspace().theme`, `surface(theme, part)`,
  `bodyText`, `headingText`, `monoText`, `captionText`, `glowShadow`, `litEdges`, `fontFamily(font, weight)`.
- Chat pieces read `src/kits/talk/look.ts` (rows, counts, pills, search) and `src/kits/talk/chatLook.tsx`
  (bubbles, message box, send button), so every chat in the app matches.
- `Marks` and `EdgeLine` in `src/components/ui.tsx` draw a card's lit corner and a header's lit line.
- Never write a hex value, font or fixed size in a screen; add a token instead, with a value for each built-in style.
