# Styling Token Contract (T02)

Date: 2026-03-27  
Scope: `recipe-manager/frontend`

## Canonical token source

**Single source of truth:**
- `src/styles/tokens.css`

All design-token values (color, typography scales, spacing, radius, elevation/focus) must be authored in `tokens.css` first.

## Allowed token consumption paths

1. **Preferred in UI markup:** tokenized classes and `ui-*` primitives from `src/index.css`
   - Examples: `ui-card`, `ui-btn`, `text-[var(--text)]`, `border-[var(--border)]`
2. **Tailwind theme keys** mapped to CSS vars in `tailwind.config.js`
   - Examples: `bg-surface`, `text-primary`, `shadow-card`
3. **TS access layer:** `src/theme.ts`
   - Must expose `var(--...)` references only.
   - Must not hardcode competing token values.

## Explicit non-contract patterns

- Do **not** introduce new hardcoded design-token values in `theme.ts`.
- Do **not** define duplicate token constants in TS that can drift from `tokens.css`.
- Avoid ad-hoc palette classes (`bg-blue-*`, `text-slate-*`, etc.) in shared shell/feature UI when tokenized equivalents exist.

## `theme.ts` role after T02

`theme.ts` is now a **typed token accessor/compatibility layer**, not an independent token definition file.

- ✅ Allowed: `colors.primary = 'var(--color-primary)'`
- ❌ Not allowed: `colors.primary = '#ea580c'`

If a token does not exist yet:
1. Add it to `tokens.css`
2. (Optional) Map it in `tailwind.config.js` if utility-class access is needed
3. Expose accessor in `theme.ts` only as `var(--token-name)`

## Practical authoring guide (for future tasks)

- Use `ui-*` classes first for common controls/layout shells.
- Use tokenized Tailwind utilities or `var(--...)` references for one-off styling.
- Keep inline `style={{ ... }}` for runtime/dynamic values only (e.g., tag color from DB), not for static design tokens.

## Current known exceptions (post-T02)

- Some components/pages still import `radius`/`colors` from `theme.ts` for inline styling; values are now token references, so no hardcoded drift remains.
- `recipeAccentPalette` still includes a few non-tokenized accent hexes pending a future semantic palette pass.
