Overview

ANVIL uses two token layers: primitive (raw values) and semantic (usage meaning). Components must consume semantic tokens only.

Token Anatomy

How to read a semantic token

--c-bg-surface-muted Full token example
-- CSS custom property prefix
c Category: color
bg Group: background role
surface Context: component surface
muted State/intensity modifier

1. Primitive Tokens

Raw values with no intent. Naming: --p-{category}-{value}. Never used directly in components.

Categories

Color --p-red-50 … --p-red-900, --p-neutral-50 … --p-neutral-900, --p-gold-50 … --p-gold-900
Spacing --p-space-1 (4px) … --p-space-16 (64px), --p-space-11 (44px touch)
Radius --p-radius-sm, --p-radius-md, --p-radius-lg, --p-radius-full
Typography --p-ff-condensed, --p-ff-sans, --p-ff-mono; --p-fs-12 … --p-fs-40
Border --p-border-thin, --p-border-medium, --p-border-focus

2. Semantic Tokens

Meaning-driven aliases by category prefix.

Categories and meaning

--c-* Color roles: --c-brand-primary, --c-text-base, --c-bg-surface, --c-border-subtle, --c-state-focus
--sp-* Spacing scale and interaction size: --sp-1 … --sp-16, --sp-touch
--r-* Radii: --r-none, --r-sm, --r-md, --r-lg, --r-full
--ff-* Typography families: --ff-display, --ff-body, --ff-mono
--fs-* Typography sizes: --fs-caption, --fs-small, --fs-body, --fs-lead, --fs-h4 … --fs-h1

Primitive → Semantic Mapping

Core examples

--p-red-500 → --c-brand-primary / --c-state-error
--p-neutral-900 → --c-text-base / --c-brand-secondary / --c-state-focus
--p-space-11 → --sp-touch
--p-ff-condensed → --ff-display
--p-fs-16 → --fs-body

Rules

Naming Decision

We keep the --p-* prefix for now. Renaming primitives to plain --* would increase ambiguity and create a breaking change across documentation, future exports, and tooling integrations. If needed, we can introduce short aliases later with a deprecation phase.