---
name: token-selection
description: >-
  Answers which color token/role an adia-ui surface should use — role
  grammar, pairing laws, state families, the --a-* alias layer. Use when
  asked "which token for this background/text/hover/border" or "--a-* or
  --md-sys-color-*". ANSWERS only. NOT for composing the screen
  (screen-composition) or designing/verifying palettes (framework-side).
disable-model-invocation: false
user-invocable: false
---

# token-selection — which color role, answered

The color system's public API is semantic roles, never values: if a color
isn't a `--md-sys-color-*` role or an `--a-*` alias, it doesn't go in UI
code — no hex, no `oklch()`, no raw `-050…-950` stop, no `color-mix()`
state synthesis. This pack answers the "which role" question; the values
themselves live in the installed CSS and are never restated here.

## The grammar

`--md-sys-color-{palette}{suffix}` — the palettes (count them in
[`references/role-roster.md`](references/role-roster.md), the generated
source; today: `neutral` chrome ·
`primary` brand accent · `secondary`/`tertiary` support · the four intents
`info/success/warning/danger`, which carry MEANING only, never decoration).
The on-accent role uses the palette's OWN slug:
`--md-sys-color-danger-on-danger` sits on `--md-sys-color-danger`. The full
suffix roster with per-family meaning: [`references/role-roster.md`](references/role-roster.md)
(GENERATED from the installed export — trust it over memory).

## The laws (violating any is a defect)

1. **Pairing** — ink sits only on its own palette's legal ground:
   `-on-{p}` on the accent fill; `-on-surface` on that palette's
   surfaces/containers/background. Never cross palettes mid-pair.
2. **States ship as families** — where `-hover/-active/-disabled` siblings
   exist, use them verbatim; never synthesize a state with opacity or
   `color-mix()`. Not every role has siblings — the roster is the map.
3. **The scheme is baked in** — every role flips via `light-dark()`; write
   each color once. Force a subtree with `color-scheme:`, never per-color
   `@media` overrides.
4. **Elevation is the surface ladder** — raise/recess with
   `-surface-{dim…bright}` / `-surface-{low…high}` tiers; shadows are
   garnish, opacity is a defect.
5. **On-accent ink is fixed light in both schemes, by design** — it
   deliberately overrides per-pair contrast math (operator ruling
   2026-07-16, recorded in the framework's color-bridge contract: fill-pair
   contrast is an upstream design decision — do not "fix" it locally with
   dark text or auto-contrast).
6. **Roles by their named purpose, never by coincidental value** — no
   `--a-bg` as a foreground, no chart identity tokens (`--a-data-0..9`)
   for semantic state, and vice versa.

Depth and adia-specific notes per law: [`references/pairing-laws.md`](references/pairing-laws.md).

## Which layer — `--a-*` or `--md-sys-color-*`?

Both are public. `--a-*` is the compact alias layer most component CSS and
older app code consumes; the Material roles are the source of truth it
reads from. Match the file you're editing (don't mix mid-file); for NEW
code prefer the Material role — it's the finer-grained vocabulary. The
full alias→role mapping: [`references/a-alias-layer.md`](references/a-alias-layer.md)
(GENERATED — the authoritative bridge table).

## Consult table

| Ask | Answer from |
| --- | --- |
| "which role for this button/badge/toast/border/text" | the grammar + laws above, then [`role-roster.md`](references/role-roster.md) for the exact suffix |
| "what does `--a-<x>` actually resolve to" | [`a-alias-layer.md`](references/a-alias-layer.md) |
| "hover/disabled color for X" | law 2 — the role's own state family, from the roster |
| "make it work in dark mode" | law 3 — it already does; check the subtree's `color-scheme` before touching tokens |
| "this pair looks low-contrast" | law 5 first (on-accent is by design); genuine canvas-text pairs are gated by the framework's `verify:contrast` |

The generated references are produced in the framework monorepo at cut
time (producer-side, CI-gated) — in a consumer repo they describe the
version you installed; never edit them. Choosing and wiring the tokens into a
screen is `screen-composition`'s job; this pack only answers.
