# Postie components — the rules every component obeys

Four P2 named elements are not components. They are rules at token level, and every component
in `core/`, `forms/` and `data/` is written against them. Argue with them by name.

## `ground-role-split`
Charcoal `#1F1D1E` is the **brand ground**: chrome-bar, masthead-band, hero, agent card,
brand-tone buttons. The **working ground** is where dense mail reads: `#111011` on dark,
paper `#FBFAFA` on light. Brand-ground components stay charcoal in BOTH themes; working-ground
components flip. Mechanism: the theme scope sets the working context (`--postie-c-*`); the
`.postie-brand` class sets the brand context. A working component dropped inside a brand block
(the `paper-preview`) re-enters the working context with `.postie-working`. Never a saturated
colour behind dense text; never a working surface tinted to "match" the chrome.

**How the re-entry wins (fixed 2026-09-20, ui_kits component-gap #1).** The context is a
custom-property layer and nothing else: every ground-dependent role a component can paint —
ground, raised, ink, body, muted, edge, accent-text, accent-hover, and now the pebble steps
(`--postie-c-pebble-1/-2/-ink`), the selected tint (`--postie-c-selected`) and the segment
fill (`--postie-c-select-fill/-ink`) — is a `--postie-c-*` token that the theme scope,
`.postie-brand` and `.postie-working` each declare in full. A component reads ONLY those
tokens; it never writes a `.postie-brand <component>` descendant rule, because that rule
(`0,2,0`) out-ranks the re-entry class (`0,1,0`) and a pebble or Live chip inside a
`.postie-working` block on the chrome renders brand colours on paper. Since the context is
resolved by inheritance, whichever of `.postie-brand` / `.postie-working` is the nearest
ancestor wins — no specificity, no order dependence. Panel `tone="feature"` is the one
theme-resolved re-entry (raised-brand on dark, paper on light) and it re-declares the same
layer under `[data-theme="light"]`.

## `tonal-step`
Separation is a change of ground (`surface → raised → selected`) or space. No rules, no shadows,
no borders as separators. `--postie-rule` is decorative and legal only inside dense tables
(`DataTable`, the mail list inside `ProductPreview`). Nothing casts a shadow. Nothing glows.

## `edge`
`--postie-edge` (`#6E6566` dark · `#8A8788` light, 1.5px) is the only visible UI border in the
system: text inputs, the reply well and the dashed `AddSlot`. It clears 3:1 on its ground and is
never text. On the brand ground the only edge is the ghost button's, drawn in `--postie-muted-brand`.
The oxblood fill has no edge on any ground — a primary button is read by its light ink and its
pill shape, not its silhouette (1.84:1 on charcoal is a recorded, accepted non-text case).

## `nunito-pair`
Display and wordmark: **Nunito 800**, tracked −0.03em (−0.04em above 60px). UI and body:
**Nunito Sans 400 / 600 / 700**, tabular figures on. Heavy rounded weight is for the wordmark,
page titles, tile figures and message subjects. It never sets running text. Labels are 11–13px,
700, uppercase, tracked +0.14em. Fallback stack: Helvetica Neue, Arial.

## Colour discipline that falls out of the pairings
- Oxblood `#8A1E2B` is **never text on any charcoal** — the lifted face `#E4606C` exists for that,
  in both themes wherever the ground is charcoal.
- `#E4606C` is **never text on paper** — on paper the accent-as-text face IS the oxblood.
- Charcoal ink never sits on the oxblood fill — always `#F6EDED`.
- Nothing sets body text in the accent. The accent is the primary action, the live dot, the link,
  the count, the triage band (light only as a fill). ≈5% of any view.
- No amber, no red, no green, no blue — no status hue exists in colourway 4. State is always
  word + dot; a non-live state is a tonal (muted) chip, never a second hue. If a real status colour
  is ever needed it is a P2 decision, not a component decision.
- No opacity on text. Step down the ramp: ink → body → muted.

## Every `.prompt.md` also carries the brief's `never` list
corporate blue/grotesk-flat · clinical white + thin grey · brown (any role) · faceless-giant badge
clutter · cold grey monochrome · mascots / springs / exclamation marks · speed clichés (bolts,
rockets, motion lines) · nature / foliage colour coding · garden-centre green · teal / soft blue ·
wellness-serene softness (soft gradients, pastel, glow).
