git:20260927.f9d8d40 to git:20261005.4992c34

2 added, 2 removed. Audit A to A.

---
name: variant-design-system
- description: Design System mode — tokens → components → pages three-layer workflow. Generate a complete token set (palette/type/spacing/motion/elevation/radius), confirm it, then all downstream outputs are visually consistent. Triggers on: ds, design system, tokens, create token set, define palette, define tokens, set up tokens, ds confirm, compose
+ description: "Design System mode — tokens → components → pages three-layer workflow. Generate a complete token set (palette/type/spacing/motion/elevation/radius), confirm it, then all downstream outputs are visually consistent. Triggers on: ds, design system, tokens, create token set, define palette, define tokens, set up tokens, ds confirm, compose"
---
> Before generating code, load `skills/shared/code-output.md`, `references/project-context.md`, and `references/quality-baseline.md`.
For product-critical work, also read `references/design-declaration.md` and `references/product-integrity-gate.md`. A confirmed design system locks the declaration's product constraints as well as visual tokens.
## Design System Mode
The canonical workflow for production-quality work. Define once, generate consistently.
```
ds → confirm → component [name] → compose [page]
↑ ↑ ↑
Token foundation Atomic pieces Assembled layouts
```
### Triggers
| User says | Action |
|---|---|
| `ds` / "create a design system" / "define tokens" / "set up tokens" | Generate design system → preview → confirm |
| `ds confirm` | Lock the current design system and any product-critical Design Declaration for future outputs |
| `ds edit [section]` | Edit one section of the design system (palette / type / spacing / motion) without regenerating all |
| `ds show` | Print current design system token summary in terminal |
| `component [name]` (after DS confirmed) | Generate component using locked DS tokens, all 8 states |
| `compose [page name]` | Assemble confirmed components into a page, 3 layout variations |
| `compose [page] using A B C` | Compose page from specific named components |
### Step 1 — Generate Design System (`ds`)
- **Before generating**, ask 3 focused questions (can be answered in one message):
+ **Before generating**, infer these dimensions from the brief and repository. Ask at most two material unanswered questions across the entire request; no mandatory intake:
1. **Brand personality** — 2–3 adjectives that describe the feel (e.g. "precise, warm, understated")
2. **Color direction** — existing brand color, or a reference (hex / site URL / mood word)
3. **Typeface preference** — existing fonts, or a direction ("editorial serif", "clean geometric sans", "monospace-forward")
If user says "surprise me" or has no preferences, infer from their codebase (README, existing CSS, component names) or pick a strongly opinionated direction and state it.
**Generate `variant-output/design-system.css`** — a complete, self-documenting token file:
```css
/* ═══════════════════════════════════════════════════
DESIGN SYSTEM — [Project Name]
Generated by variant-design · [date]
Confirm with: ds confirm
Edit with: ds edit [palette | type | spacing | motion | elevation | radius]
═══════════════════════════════════════════════════ */
/* ── Primitives ─────────────────────────────────── */
:root {
/* Color primitives — OKLCH */
--p-brand-50: oklch(97% 0.02 [H]);
--p-brand-100: oklch(93% 0.04 [H]);
--p-brand-200: oklch(86% 0.08 [H]);
--p-brand-300: oklch(76% 0.13 [H]);
--p-brand-400: oklch(66% 0.18 [H]);
--p-brand-500: oklch(56% 0.20 [H]); /* primary */
--p-brand-600: oklch(46% 0.18 [H]);
--p-brand-700: oklch(36% 0.15 [H]);
--p-brand-800: oklch(26% 0.10 [H]);
--p-brand-900: oklch(16% 0.06 [H]);
--p-neutral-50: oklch(98% 0.005 [H]);
--p-neutral-100: oklch(95% 0.008 [H]);
--p-neutral-200: oklch(90% 0.010 [H]);
--p-neutral-300: oklch(82% 0.012 [H]);
--p-neutral-400: oklch(68% 0.010 [H]);
--p-neutral-500: oklch(55% 0.008 [H]);
--p-neutral-600: oklch(42% 0.008 [H]);
--p-neutral-700: oklch(30% 0.006 [H]);
--p-neutral-800: oklch(20% 0.005 [H]);
--p-neutral-900: oklch(12% 0.004 [H]);
--p-success: oklch(55% 0.18 145);
--p-warning: oklch(60% 0.18 80);
--p-error: oklch(55% 0.22 25);
--p-info: oklch(55% 0.18 250);
}
/* ── Semantic tokens ─────────────────────────────── */
:root {
/* Surfaces */
--color-bg: var(--p-neutral-50);
--color-surface: #ffffff;
--color-surface-2: var(--p-neutral-100);
--color-surface-3: var(--p-neutral-200);
/* Borders */
--color-border: var(--p-neutral-200);
--color-border-strong: var(--p-neutral-300);
/* Text */
--color-text-primary: var(--p-neutral-900);
--color-text-secondary: var(--p-neutral-600);
--color-text-tertiary: var(--p-neutral-400);
--color-text-on-accent: #ffffff;
/* Brand */
--color-accent: var(--p-brand-500);
--color-accent-hover: var(--p-brand-600);
--color-accent-subtle: var(--p-brand-50);
--color-accent-border: var(--p-brand-200);
/* Semantic */
--color-success: var(--p-success);
--color-success-subtle: oklch(97% 0.03 145);
--color-warning: var(--p-warning);
--color-warning-subtle: oklch(98% 0.03 80);
--color-error: var(--p-error);
--color-error-subtle: oklch(97% 0.03 25);
}
/* ── Typography ─────────────────────────────────── */
:root {
--font-display: '[Display Font]', serif; /* or sans-serif */
--font-body: '[Body Font]', sans-serif;
--font-mono: 'IBM Plex Mono', monospace;
/* Scale — ratio [ratio] */
--text-xs: clamp(0.69rem, 0.65rem + 0.2vw, 0.75rem);
--text-sm: clamp(0.8rem, 0.77rem + 0.2vw, 0.875rem);
--text-base: clamp(0.95rem, 0.9rem + 0.25vw, 1.0625rem);
--text-lg: clamp(1.1rem, 1rem + 0.5vw, 1.25rem);
--text-xl: clamp(1.3rem, 1.1rem + 1vw, 1.75rem);
--text-2xl: clamp(1.6rem, 1.2rem + 2vw, 2.5rem);
--text-3xl: clamp(2rem, 1.4rem + 3vw, 3.5rem);
--text-4xl: clamp(2.5rem, 1.6rem + 5vw, 5.5rem);
/* Weights */
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
/* Line heights */
--leading-tight: 1.2;
--leading-snug: 1.35;
--leading-normal: 1.5;
--leading-relaxed: 1.7;
/* Tracking */
--tracking-tight: -0.04em;
--tracking-snug: -0.02em;
--tracking-normal: 0;
--tracking-wide: 0.04em;
--tracking-caps: 0.08em;
}
/* ── Spacing ─────────────────────────────────────── */
:root {
/* 4pt base grid */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
--space-12: 48px;
--space-16: 64px;
--space-20: 80px;
--space-24: 96px;
/* Layout */
--container-sm: 640px;
--container-md: 768px;
--container-lg: 1024px;
--container-xl: 1280px;
--container-2xl: 1440px;
}
/* ── Radius ──────────────────────────────────────── */
:root {
--radius-xs: 2px;
--radius-sm: 4px;
--radius-md: 6px;
--radius-lg: 10px;
--radius-xl: 16px;
--radius-2xl: 24px;
--radius-full: 9999px;
}
/* ── Elevation (shadow) ──────────────────────────── */
:root {
--shadow-xs: 0 1px 2px rgba(0,0,0,0.05);
--shadow-sm: 0 1px 4px rgba(0,0,0,0.07), 0 0 0 1px rgba(0,0,0,0.04);
--shadow-md: 0 4px 12px rgba(0,0,0,0.08), 0 0 0 1px rgba(0,0,0,0.04);
--shadow-lg: 0 8px 24px rgba(0,0,0,0.10), 0 0 0 1px rgba(0,0,0,0.04);
--shadow-xl: 0 16px 48px rgba(0,0,0,0.12), 0 0 0 1px rgba(0,0,0,0.05);
/* Focus ring */
--ring-width: 2px;
--ring-offset: 2px;
--ring-color: var(--color-accent);
}
/* ── Motion ──────────────────────────────────────── */
:root {
/* Durations */
--duration-instant: 80ms;
--duration-fast: 150ms;
--duration-normal: 250ms;
--duration-slow: 400ms;
--duration-slower: 600ms;
/* Easings */
--ease-out: cubic-bezier(0.0, 0.0, 0.2, 1);
--ease-in: cubic-bezier(0.4, 0.0, 1, 1);
--ease-in-out: cubic-bezier(0.4, 0.0, 0.2, 1);
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
--ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
/* Common transitions */
--transition-fast: all var(--duration-fast) var(--ease-out);
--transition-normal: all var(--duration-normal) var(--ease-out);
--transition-colors: color var(--duration-fast) var(--ease-out),
background-color var(--duration-fast) var(--ease-out),
border-color var(--duration-fast) var(--ease-out);
}
/* ── Z-index ─────────────────────────────────────── */
:root {
--z-base: 0;
--z-raised: 10;
--z-dropdown: 100;
--z-sticky: 200;
--z-overlay: 300;
--z-modal: 400;
--z-toast: 500;
}
```
**Also generate `variant-output/design-system-preview.html`** — a visual token preview showing:
- Color palette swatches (brand scale + neutrals + semantic)
- Typography specimens at each size step with sample text
- Spacing scale as a visual bar chart
- Shadow/elevation showcase
- Motion demo (hover cards to see transition, animated duration reference)
- Border radius examples
Open the preview immediately in browser.
### Step 2 — Confirm Design System (`ds confirm`)
When the user approves (says `ds confirm`, "looks good", "confirm this", "ship it"):
1. Write the confirmed status to `.variant-context.json`:
```json
{
"designSystem": {
"confirmed": true,
"file": "variant-output/design-system.css",
"palette": "[palette name]",
"fonts": ["[Display]", "[Body]"],
"confirmedAt": "[ISO date]"
}
}
```
2. Print confirmation:
```
✦ Design system confirmed — locked as visual foundation
File: variant-output/design-system.css
Palette: [name] · [hue]° OKLCH
Type: [Display font] + [Body font]
Next steps:
component [name] → build atomic components on this foundation
compose [page] → assemble components into page layouts
ds edit palette → refine colors before building
```
3. From this point forward, **all Generate, Component, and Compose outputs** must `<link rel="stylesheet" href="design-system.css">` (or inline the tokens) — no aesthetic invention allowed outside the locked token system.
4. For product-critical work, compile the confirmed declaration into `variant-output/design-contract.md` and run the Product Integrity Gate separately from the visual quality gate.
### Step 3 — Build Components (`component [name]`)
When design system is confirmed, Component Mode runs on a tighter brief:
- All colors from `design-system.css` semantic tokens — **no new colors**
- All spacing from `design-system.css` spacing scale — **no new values**
- Typography from `design-system.css` type tokens
- Add to component registry in `.variant-context.json`:
```json
{
"components": {
"button": "variant-output/component-button.html",
"card": "variant-output/component-card.html",
"form": "variant-output/component-form.html"
}
}
```
Terminal output:
```
✦ Component: Button System [DS: confirmed · Amber Warm · DM Sans]
Tokens used: --color-accent, --color-surface, --space-2/3/4, --radius-md
New tokens added: none
variant-output/component-button.html ← opened in browser
Registry: button · (no other components yet)
Next: component card · component form · compose [page] using button
```
### Step 4 — Compose Pages (`compose [page name]`)
Assembles registered components into page layouts. **3 structural variations** — layout and composition differ; visual language does not.
**Process:**
1. Read `.variant-context.json` to get component registry
2. Read `design-system.css` for tokens
3. For each variation, invent a different **structural arrangement**:
- Variation A: canonical / expected layout for this page type
- Variation B: unconventional hierarchy (e.g. sidebar-dominant, reversed stack)
- Variation C: density variant (compact/information-dense vs. spacious/editorial)
4. All three use identical tokens and components — the only differences are grid, order, proportion, and density
5. Write `variant-output/compose-[page]-A.html`, `-B.html`, `-C.html`
**What changes across compose variations:**
| Dimension | Can vary | Cannot vary |
|---|---|---|
| Grid structure | ✓ | |
| Section order / hierarchy | ✓ | |
| Column count / proportion | ✓ | |
| Density (padding, gap) | ✓ — within spacing scale | |
| Which components are prominent | ✓ | |
| Colors | | ✗ — all from DS |
| Typography | | ✗ — all from DS |
| Component visual design | | ✗ — use as-built |
| New spacing values | | ✗ — DS scale only |
Terminal output:
```
✦ Compose: Dashboard page [DS confirmed · 3 components registered]
Components used: button · card · data-table
Layout variations:
A — Standard: left sidebar + main content grid
B — Topbar: horizontal nav + full-width zones
C — Focused: single column, task-driven, no sidebar
Files:
variant-output/compose-dashboard-A.html ← opened in browser
variant-output/compose-dashboard-B.html
variant-output/compose-dashboard-C.html
Next: pick A/B/C · compose [another page] · tokens A
```
### DS Quick Triggers
| User types | Action |
|---|---|
| `ds` | Start design system generation workflow |
| `ds confirm` | Lock design system — constrains all future outputs |
| `ds show` | Print current DS summary (palette, fonts, status) |
| `ds edit palette` | Regenerate color section only, keep everything else |
| `ds edit type` | Regenerate typography section only |
| `ds edit spacing` | Regenerate spacing/radius section only |
| `ds edit motion` | Regenerate motion/animation section only |
| `ds preview` | Re-open design-system-preview.html in browser |
| `ds reset` | Remove DS lock, allow aesthetic invention again |
| `compose [page]` | Assemble page from registered components |
| `compose [page] using A B C` | Compose using only specified components |
| `registry` | Print component registry (which components are built) |
### When DS is NOT Confirmed
Standard Generate mode — full aesthetic invention per the normal workflow. Each variation picks its own palette, fonts, and direction.
### When DS IS Confirmed
Visual language is locked. The freedom space narrows to:
- Layout composition (grid, order, proportion)
- Content hierarchy (what's prominent, what's secondary)
- Interaction specifics (animation choreography within motion tokens)
- Copywriting and content strategy
Print a one-line reminder on every generation:
```
✦ DS locked: Amber Warm · DM Sans + Newsreader · variations differ in layout only
```