# Design tokens

> Site self-constraints in tokens and global styles: paper and ink palette, single editorial red, hierarchy rules, and banned slop defaults.

- Repository: yetone/kill-ai-slop
- GitHub: https://github.com/yetone/kill-ai-slop
- Human docs: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb
- Complete Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/llms-full.txt

## Source Files

- `website/src/styles/tokens.css`
- `website/src/styles/global.css`
- `website/src/styles/demos.css`
- `website/src/layouts/Base.astro`
- `website/src/components/ThemeToggle.astro`

---

---
title: "Design tokens"
description: "Site self-constraints in tokens and global styles: paper and ink palette, single editorial red, hierarchy rules, and banned slop defaults."
---

The field-guide site encodes its anti-slop rules as CSS custom properties in `website/src/styles/tokens.css`, imported first by `website/src/styles/global.css` (then `demos.css`). `website/src/layouts/Base.astro` loads `global.css` for every page. Tokens define paper/ink surfaces, the two intentional accent colors (`--mark`, `--slop`), type scale, spacing, radius, hairlines, and elevation; global rules and clean demo panes consume them. Slop demo panes intentionally hard-code banned defaults (gradients, pills, rainbow semantics) outside the token set.

## File surface

```text
website/src/
├── layouts/Base.astro          # imports global.css; pre-paint theme/lang
├── components/ThemeToggle.astro
└── styles/
    ├── tokens.css              # :root design tokens + dark overrides
    ├── global.css              # @import tokens + demos; base type/layout
    └── demos.css               # .ba-stage / .demo-* before→after styles
```

| Path | Role |
|------|------|
| `tokens.css` | Canonical token definitions and dark-mode overrides |
| `global.css` | Reset, body chrome, heading scale, layout primitives, locale visibility |
| `demos.css` | Scoped before/after demo styles; clean sides use tokens; slop sides hard-code anti-patterns |
| `Base.astro` | Imports `global.css`; pre-paint `kas-theme` / `kas-lang` / `kas-sound` |
| `ThemeToggle.astro` | Forces `data-theme` light/dark; persists `localStorage` key `kas-theme` |

## Self-constraints (token contract)

Comments in `tokens.css` state the rules the site holds itself to:

| Rule | Implementation |
|------|----------------|
| Monochrome base | Ink on paper: structure, nav, numbers stay ink; no decorative color on chrome |
| Color only for verdict | `--mark` (pine green) flags slop sparingly; `--slop` (specimen coral) colors the “before” side in demos; clean is unmarked |
| No gradient / cozy / rainbow defaults | Banned as site defaults; only appear inside slop demo panes |
| Hierarchy without serif swaps or mid-sentence color | Scale, weight, and space only |
| Modest radius + hairlines | `--radius` / `--radius-lg`, `--hair`, `--rule` — not pill chrome or diffuse glow |
| Mono for code only | `--font-mono` on `code` / `kbd` / `samp` / `pre`; not UI chrome |

## Color tokens

### Light defaults (`:root`)

| Token | Value | Use |
|-------|--------|-----|
| `--paper` | `#f2f4f6` | Page background |
| `--paper-2` | `#e9ebed` | Recessed panels |
| `--card` | `#fafcfe` | Soft card surface (not pure `#fff`) |
| `--ink` | `#1a1b1d` | Primary text / solid chrome |
| `--ink-2` | `#5e5f61` | Secondary text |
| `--ink-3` | `#8e8f91` | Meta, captions, eyebrows |
| `--rule` | `#e1e3e5` | Hairline borders |
| `--rule-strong` | `#c5c7c9` | Stronger rules / link underlines |
| `--mark` | `#246a50` | Deep emerald-pine proof-mark (verdict / flag) |
| `--mark-soft` | `#dde7e0` | Faint green wash |
| `--slop` | `#ff5c5c` | Specimen coral — commentary color on slop “before” panes |

### Dark overrides

Dark applies when:

1. `prefers-color-scheme: dark` **and** `:root` is not `[data-theme="light"]`, or  
2. `:root[data-theme="dark"]` is set explicitly.

Both selectors carry the **identical** dark token set (CSS cannot OR a media query with a selector).

| Token | Dark value |
|-------|------------|
| `--paper` | `#131316` |
| `--paper-2` | `#1b1c20` |
| `--card` | `#202127` |
| `--ink` | `#ecebe6` |
| `--ink-2` | `#a9a8a2` |
| `--ink-3` | `#74736e` |
| `--rule` | `#2c2d33` |
| `--rule-strong` | `#3d3e45` |
| `--mark` | `#6faa8e` |
| `--mark-soft` | `#1e2f28` |
| `--shadow-e1` | `0 1px 1px rgba(0, 0, 0, 0.4)` |
| `--shadow-e2` | `0 1px 1px rgba(0, 0, 0, 0.5), 0 4px 4px -1px rgba(0, 0, 0, 0.3)` |

`--slop` is not redefined in dark mode; it stays `#ff5c5c`. Dark mode remains paper-and-ink logic inverted: same mark accent, no neon glow.

### `color-scheme`

| Selector | `color-scheme` |
|----------|----------------|
| `:root` (default) | `light dark` |
| `:root[data-theme="light"]` | `light` |
| `:root[data-theme="dark"]` | `dark` |

Native controls (e.g. language `<select>` options, scrollbars) follow the forced scheme.

## Type tokens

| Token | Value |
|-------|--------|
| `--font-sans` | `ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif` |
| `--font-mono` | `ui-monospace, "SF Mono", "JetBrains Mono", "Cascadia Code", Menlo, Consolas, monospace` |

Modular scale (~1.2), display caps kept modest:

| Token | Clamp |
|-------|--------|
| `--step--1` | `clamp(0.78rem, 0.76rem + 0.08vw, 0.82rem)` |
| `--step-0` | `clamp(0.94rem, 0.92rem + 0.1vw, 1rem)` |
| `--step-1` | `clamp(1.05rem, 1rem + 0.24vw, 1.18rem)` |
| `--step-2` | `clamp(1.25rem, 1.14rem + 0.5vw, 1.55rem)` |
| `--step-3` | `clamp(1.5rem, 1.3rem + 0.9vw, 2rem)` |
| `--step-4` | `clamp(1.85rem, 1.5rem + 1.5vw, 2.6rem)` |
| `--step-5` | `clamp(2.2rem, 1.75rem + 2.2vw, 3.2rem)` |

## Space and structure tokens

| Token | Value | Notes |
|-------|--------|--------|
| `--s-1` … `--s-9` | `0.25rem` … `7rem` | 8px-base spacing ladder |
| `--measure` | `68ch` | Readable prose width (`.measure`) |
| `--container` | `76rem` | Page max width (`.container`) |
| `--radius` | `8px` | Control / button radius (not pills) |
| `--radius-lg` | `12px` | Larger surfaces / clean demo cards |
| `--hair` | `1px` | Hairline rules |
| `--shadow-e1` | tight 1px contact | Light default |
| `--shadow-e2` | ring + tight lift | Clean elevated panels |
| `--ease` | `cubic-bezier(0.2, 0, 0, 1)` | Motion easing |

Shadows are contact shadows (small blur, negative spread), not diffuse drops or glows.

## Theme resolution

```text
localStorage "kas-theme"
        │
        ├─ "light" | "dark"  →  documentElement.dataset.theme  (pre-paint in Base.astro)
        └─ unset             →  data-theme absent; @media prefers-color-scheme drives dark tokens

ThemeToggle click
        → effective() = explicit data-theme OR OS
        → flip light ↔ dark
        → set data-theme + localStorage kas-theme
```

| Storage key | Values | Default behavior |
|-------------|--------|------------------|
| `kas-theme` | `"light"` \| `"dark"` | Unset → follow OS via media query |
| `kas-lang` | `en` \| `zh` \| `ja` \| `ko` | Unset → OS language if supported, else `en` |
| `kas-sound` | `"off"` or other | Default `"on"` unless stored `"off"` |

Theme toggle UI: sun icon in light, moon in dark; icons driven by global CSS on effective theme (`prefers-color-scheme` + `data-theme`). Toggle chrome uses `var(--ink-3)` / hover `var(--ink)`.

## Global styles that enforce hierarchy

`global.css` applies tokens to base chrome:

| Element / class | Token / rule |
|-----------------|--------------|
| `body` | `background: var(--paper)`; `color: var(--ink)`; `font-family: var(--font-sans)`; `font-size: var(--step-0)`; `line-height: 1.6` |
| `h1` | `var(--step-5)`, weight `620`, letter-spacing `-0.038em` |
| `h2` | `var(--step-3)`, letter-spacing `-0.028em` |
| `h3` | `var(--step-1)`, letter-spacing `-0.018em` |
| `h1–h4` (default) | `line-height: 1.04`, weight `640`, `text-wrap: balance` |
| CJK headings (`[data-lang="zh"|"ja"|"ko"]`) | `line-height: 1.4` |
| `a` | inherit color; underline `var(--rule-strong)`; hover `var(--ink)` |
| `code, kbd, samp, pre` | `var(--font-mono)` |
| `:focus-visible` | `2px solid var(--ink)`, `border-radius: 0` |
| `::selection` | `background: var(--ink)`; `color: var(--paper)` |
| `.container` | `max-width: var(--container)` + fluid inline padding |
| `.measure` | `max-width: var(--measure)` |
| `.section` | fluid block padding; `border-top: var(--hair) solid var(--rule)` |
| `.eyebrow` | `var(--step--1)`, tracked uppercase, `var(--ink-3)`; index via `data-index` in `var(--ink)` |
| `.mark-hl` | empty rule — emphasis by weight/structure, not underline/highlight |
| `.lede` | `var(--step-2)`, weight `480`; CJK locales `line-height: 1.5` |

Reduced motion: under `prefers-reduced-motion: reduce`, animations/transitions collapse to `0.01ms`; scroll stays `auto`. Smooth scroll only after `.nav-ready` is added post-load (and not when reduced motion is preferred).

## Banned slop defaults (demo contrast)

Clean demo panes reuse site tokens. Slop panes hard-code anti-patterns the tokens ban. Representative mappings in `demos.css`:

| Tell (demo id) | Slop (hard-coded) | Clean (tokens) |
|----------------|-------------------|----------------|
| `demo-indigo-violet-gradient` | `linear-gradient(135deg, #6366f1, #a855f7)`, purple glow, pill button | `var(--card)`, `var(--rule)`, solid `var(--ink)` / `var(--paper)` button |
| `demo-gradient-text` | multi-stop indigo→pink→amber clipped text | solid `var(--ink)` heading |
| `demo-warm-cozy-palette` | amber wash `#fdf6ec`, coral button, `9999px` pill | `var(--card)` + `var(--rule)` neutral card |
| `demo-default-semantic-palette` | five candy status chips (indigo/green/amber/red/violet) | neutral chips (`var(--ink)` mix + `var(--rule)`); semantic color only in small dots |
| `demo-serif-emphasis` | Georgia italic mid-phrase in `var(--slop)` | single sans weight hierarchy |
| `demo-serif-body-misuse` | Georgia body rows | `var(--font-sans)` body; mono tabular nums for numbers |
| Shared clean cards | — | `var(--radius-lg)` + `var(--shadow-e2)` (hairline + tight lift) |

Shared demo primitives under `.ba-stage` also use steps, ink tiers, and `var(--radius)` for clean controls.

## Consuming tokens in components

Use variables only — do not reintroduce banned hard-coded hues on site chrome:

```css
.example {
  background: var(--card);
  color: var(--ink);
  border: var(--hair) solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-e1);
  font-size: var(--step--1);
  padding: var(--s-4);
}
```

Verdict / proof-mark color:

```css
.flag {
  color: var(--mark);
  background: var(--mark-soft);
}
```

Slop commentary (demos only):

```css
.slop-comment {
  color: var(--slop);
}
```

## Verification checklist

When changing tokens or site chrome:

1. **Monochrome chrome** — numbers, nav, structure stay ink; no new accent on chrome.
2. **Verdict colors only** — `--mark` / `--slop` (and soft mark wash); clean remains unmarked.
3. **No new gradients / pills / rainbow semantics** on non-demo UI.
4. **Radius** — prefer `--radius` (8px) or `--radius-lg` (12px); avoid `9999px` outside slop demos.
5. **Elevation** — hairline + `--shadow-e1` / `--shadow-e2`; no diffuse glow.
6. **Theme** — light `:root` defaults; dark via media **or** `data-theme="dark"`; force-light via `data-theme="light"`; pre-paint still reads `kas-theme`.
7. **CJK** — heading/lede line-heights still apply under `[data-lang="zh"|"ja"|"ko"]`.
8. **Demos** — slop panes may hard-code banned styles; clean panes must stay on tokens.

## Related pages

<CardGroup>
  <Card title="Run the field guide site" href="/run-field-guide-site">
    Install, dev server, and static build for the Astro field guide that consumes these tokens.
  </Card>
  <Card title="Build and deploy" href="/build-and-deploy">
    Static `dist` output and deploy-anywhere notes for the zero-JS-by-default site.
  </Card>
  <Card title="Fixes playbook" href="/fixes-playbook">
    Per-tell clean remediations that match the clean side of before/after demos.
  </Card>
  <Card title="Slop taxonomy" href="/slop-taxonomy">
    Named tells the demos and skill share; visual anti-patterns tokens deliberately reject.
  </Card>
  <Card title="Contributing" href="/contributing">
    Where to change site styles vs skill references while keeping taxonomy aligned.
  </Card>
</CardGroup>
