# Agentic Coding — Design System
You are implementing UI for a monochrome-first design system. Color exists only for semantic meaning. All surfaces, borders, and text are achromatic by default.
## Constraints
1. **Achromatic base** — Use pure gray for all surfaces, borders, and text. Do NOT use tinted neutrals. Instead, use the neutral palette (C:0.000) for all non-semantic elements.
2. **Color = meaning** — Apply chromatic color only for semantic callouts, diagrams, status indicators, and data viz. Before using any color, answer: "what does this hue mean here?" If there is no semantic answer, use neutral gray instead.
3. **Equal hue standing** — All 9 chromatic hues have equal weight. Do NOT treat any single hue as "the brand color." Instead, select hue based on semantic meaning (see Color Selection Procedure).
4. **Flat construction** — Do NOT use gradients, shadows, or glows. Instead, use solid fills, clean borders (1px solid), and whitespace for visual hierarchy. Exception: All emoji representations (Noto SVGs via `scripts/fetch-emoji.js`, custom inline SVG recreations, or `` fallbacks) are exempt — emoji visuals must never be modified to conform to this system.
5. **Typographic interaction** — Identify interactive elements by typography and shape. Use underlines + font-weight for links. Use dark/light fills for buttons. Do NOT rely on color to signal interactivity. Instead, use shape, weight, and underlines.
6. **Color budget: 60-30-10** — 60% achromatic surfaces, 30% elevated gray, 10% semantic color. Default to 95/5 for content pages. Reserve 60-30-10 for diagram-heavy pages only.
7. **Curved default, angular accent** — Use rounded forms (squircle containers, Bezier connectors) as the default shape vocabulary. Reserve angular forms (diamonds, chevrons, sharp miters) for high-arousal semantic states (error, warning, code). Do NOT mix angular containers with positive-valence content. Instead, match shape curvature to semantic valence (see Illustration System).
8. **Motion is purposive** — Every animated element must answer: "what does this motion orient, teach, or confirm?" If no answer, use no animation. Do NOT animate for decoration. Reserve looping motion (idle states) for semantic signals only: active authoring, AI processing, data flow, system readiness. Max 2 simultaneous idle loop *classes* per figure (staggered DOM instances of the same animation class count as 1).
9. **Static completeness** — Design the final settled state first. Animation reveals content; it does not define it. Every figure must communicate its full concept in the phase=1 state with no motion.
---
## Color Selection Procedure
### Step 1: Determine semantic category
| Hue | Semantic Role | Apply To |
|-----|--------------|----------|
| Error (H:25°) | Danger, critical | Error states, breaking changes, destructive actions |
| Warning (H:70°) | Caution, attention | Warnings, deprecation notices, hallucination risk |
| Success (H:155°) | Validated, complete | Completed states, validation passes, active connections |
| Cyan (H:195°) | System, code | System components, code generation, infrastructure |
| Indigo (H:250°) | Knowledge, data | Documentation, context retrieval, data references |
| Violet (H:285°) | AI transformation | AI processing, transformation steps, synthesis operations |
| Magenta (H:320°) | AI creative | LLM agents, creative processes, prompt engineering |
| Neutral | Human actor / base | Human actors, developer intent — achromatic by design |
**Removed hues:** Lime (H:110°) aliased to Success — semantically overlapping at 45° gap.
Rose (H:355°) aliased to Neutral — human actors represented achromatic per the base principle.
CSS tokens `--visual-lime` and `--visual-rose` remain as aliases for backward compatibility.
### Step 2: Select shade by context
| Context | Light Mode Shade | Dark Mode Shade |
|---------|-----------------|-----------------|
| Semantic text and icons | Pareto-optimal¹ (WCAG AA ≥4.5:1 on white) | 400 (WCAG AA on #0d1117) |
| Subtle tinted backgrounds | 50 | 950 |
| Borders, decorative fills | 100–200 | 700–800 |
| Mid-tone accents | 500 | 500 |
| Darkest text on colored bg | 900 | — |
### Step 3: Use CSS tokens (not raw hex)
| Token | Light mode | Dark mode | OKLCH |
|-------|------------|-----------|-------|
| `--visual-error` | #ee0028 | #ec7069 | Pareto-optimal, H:25° |
| `--visual-warning` | #a76900 | #cd8c37 | Gamut-clipped C=0.125, H:70° |
| `--visual-success` | #00894d | #48b475 | C=0.137, H:155° |
| `--visual-cyan` | #008485 | #00b2b2 | Gamut-clipped C=0.095, H:195° |
| `--visual-indigo` | #307ac0 | #53a0ec | C=0.13, H:250° |
| `--visual-violet` | #736cc3 | #938eeb | C=0.13, H:285° |
| `--visual-magenta` | #9d5fab | #c07ecf | C=0.13, H:320° |
| `--visual-neutral` | #666666 | #9b9b9b | Achromatic |
| `--visual-lime` | → `--visual-success` | → `--visual-success` | Alias — removed from spectrum |
| `--visual-rose` | → `--visual-neutral` | → `--visual-neutral` | Alias — removed from spectrum |
**Chroma normalization:** Categorical hues (indigo, violet, magenta) are capped at C=0.13 to
enforce visual equal-standing. The previous Pareto-optimal approach produced violet/magenta at
C≈0.29 — three times louder than cyan (C=0.095). The 1.37× residual variation is physical gamut
limits at constrained hue angles (cyan, warning). Error retains Pareto-optimal for its semantic
role as a high-arousal danger signal.
### Step 4: For diagram region fills, use background tokens
Transparent tints at 10% light / 15% dark:
```css
--visual-bg-{hue}: color-mix(in srgb, var(--visual-{hue}) 10%, transparent);
/* Dark mode: 15% instead of 10% */
```
All 10 hues (error, warning, lime, success, cyan, indigo, violet, magenta, rose, neutral) have `--visual-bg-*` tokens.
---
## Typography
### Font Assignment
| Role | Font | CSS Variable | Weights |
|------|------|-------------|---------|
| Display / headings | Space Grotesk | `--font-display` | 600, 700 |
| Body text | Inter | `--font-body` | 400, 500, 600, 700, 800 |
| Code — default | Monaspace Neon | `--font-mono` | 400, 500, 600, 700 |
| Code — AI voice | Monaspace Argon | `--font-mono-ai` | 400, 500 |
| Code — spec/schema | Monaspace Xenon | `--font-mono-spec` | 400, 500, 600 |
| Code — human note | Monaspace Radon | `--font-mono-human` | 400 |
| Code — keyword/op | Monaspace Krypton | `--font-mono-keyword` | 400, 500 |
```css
--font-display: 'Space Grotesk', system-ui, sans-serif;
--font-body: 'Inter', system-ui, sans-serif;
--font-mono: 'Monaspace Neon', monospace;
--font-mono-ai: 'Monaspace Argon', monospace;
--font-mono-spec: 'Monaspace Xenon', monospace;
--font-mono-human: 'Monaspace Radon', monospace;
--font-mono-keyword: 'Monaspace Krypton', monospace;
--font-mono-features: 'calt' 1, 'liga' 0;
```
Apply `--font-display` to `h1`, `h2`. Apply `--font-body` to body. Monaspace faces share identical metrics — mix freely.
### OpenType Features
Apply to all Monaspace containers:
```css
font-feature-settings: var(--font-mono-features);
```
- `calt` ON — Texture healing for even visual density across the monospace grid.
- `liga` OFF — Prevents ambiguous ligatures. Opt in per-context via stylistic sets (`ss01`–`ss10`), never globally.
### Typographic Voice Selection
Color encodes *category*. Typeface encodes *speaker*. These axes are orthogonal — a keyword can be Krypton *and* cyan; a comment can be Radon *and* muted gray.
| Face | Voice | Apply To |
|------|-------|----------|
| **Neon** | System / neutral | Source code, terminal output, config files. Default for all `` and prompt block base text. |
| **Argon** | AI agent | LLM responses, agent reasoning traces, AI-generated explanations, ghost text. |
| **Xenon** | Authoritative / structural | Spec IDs, schema keys, API contracts, system boundary labels, constraint rules. |
| **Radon** | Human / informal | Code comments, developer notes, prompt drafts, TODO markers. |
| **Krypton** | Technical / mechanical | Keywords, operators, CLI flags, file paths in callouts, taxonomy labels. |
### Voice Application by Content Type
**Code blocks:** Neon base. Comments in Radon. Keywords in Krypton. AI output in Argon.
**Prompt blocks:** Five classes, each assigned two voices (max-2 constraint applies per block):
| Class | Base | Highlight | Highlight tokens |
|-------|------|-----------|-----------------|
| Example | Neon | Krypton | Tool names, file paths, HTTP codes/headers, library names, protocol refs, search queries |
| Template | Neon | Xenon | Placeholders (`$VAR`, `{VAR}`, `[name]`), deliverable filenames, section headers |
| Command | Krypton | Xenon | URLs, file paths, `@element-refs` |
| Response | Argon | Krypton | Code tokens within AI-generated text |
| Constraint | Neon | Xenon | `DO NOT`, `ALWAYS`, `Instead` — rule-enforcement keywords |
| Human | Radon | — | Human-voice text: persona attribution ("You are a [role]"), conversational/polite phrasing, natural-language requests |
Radon marks any text written in a human voice — persona strings, polite conversational prompts, natural-language requests. It is never used for technical content. Apply as `` within a Neon block. Radon is scarce: one span per block maximum.
**Spec tables:** Spec IDs in Xenon. Verification methods in Neon. Rationale in Argon.
**Diagram labels:** System/boundary names in Xenon. Agent labels in Argon. Human actors in Radon. Data flows in Krypton.
**Inline code:** Default Neon. Override via utility class: ``, ``, etc. Inside `.prompt-example`, bare `` defaults to Krypton — no class needed. Override to Xenon with `` for Template/Constraint highlights.
### Voice Constraints
Voice faces: monospace only. Max 2 per block. Radon is scarce — human voice only, never for emphasis or technical content. Fallback: `var(--font-mono)` → `monospace`.
### Prompt Block Component
Use `` for all inline prompt illustrations in MDX docs. Do NOT use fenced code blocks for prompt examples — they lose the typographic voice layer.
```tsx
import PromptExample from '@site/src/components/PromptExample';
```
The component renders a `
` and **automatically colorizes markdown structural punctuation** (`#`, `##`, `-`, `1.`) in cyan (`--visual-cyan`) by wrapping them in ``. No manual `` needed — just use the component.
**CSS class: `.prompt-example`** (defined in `website/src/css/custom.css`)
- Base font: `--font-mono` (Neon)
- `` children default to `--font-mono-keyword` (Krypton) — correct for Example and Command classes
- Override for Template/Constraint class: add `className="mono-spec"` to placeholder or constraint-keyword `` elements (Xenon)
- Override for Response class: add `className="mono-ai"` to the `
` itself (Argon base)
```jsx
{/* Example class — Krypton highlights */}
Use ChunkHound to search for "error patterns" in our codebase.
{/* Template class — Xenon placeholders */}
Analyze $FAILURE_DESCRIPTION and propose a fix.
{/* Constraint class — Xenon enforcement keywords */}
Do NOT store passwords in plain text.
Instead, use bcrypt with 10 salt rounds.
{/* Human class — Radon for human-voice text */}
Could you help me write a function to validate email addresses?
Thanks in advance!
{/* Response class — Argon base (pass className via wrapper if needed) */}
I found 3 locations where raw errors leak: auth.ts:47, users.ts:112…
```
**`.md-punct`** — Applied automatically by `` to leading markdown structural characters (`#`, `##`, `-`, `1.`). Color: `var(--visual-cyan)`. Do not apply manually.
For line breaks within a prompt block: use ` ` only for **intentional structural breaks** (one requirement per line in Exact/Command prompts). Prose-style prompts (Exploration) wrap freely — no ` `.
---
## Design Tokens
### Token Architecture
| Tier | Purpose | Naming | Example |
|------|---------|--------|---------|
| Primitive | Raw palette values | `{hue}-{shade}` | `cyan-600`, `neutral-200` |
| Semantic | UI surfaces, text, borders, illustration | `--{category}-{role}` | `--surface-page`, `--visual-cyan` |
| Component | Per-component overrides | (not in this document) | — |
### Surface, Text & Border Tokens
| Token | Light Mode | Dark Mode |
|-------|-----------|-----------|
| `--surface-page` | #ffffff | #0d1117 |
| `--surface-raised` | #f5f5f5 (neutral-50) | #161b22 |
| `--surface-muted` | #e8e8e8 (neutral-100) | #3d3d3d (neutral-800) |
| `--text-heading` | #2b2b2b (neutral-900) | #e8e8e8 (neutral-100) |
| `--text-body` | #505050 (neutral-700) | #d4d4d4 (neutral-200) |
| `--text-muted` | #808080 (neutral-500) | #9b9b9b (neutral-400) |
| `--border-subtle` | #d4d4d4 (neutral-200) | #3d3d3d (neutral-800) |
| `--border-default` | #b7b7b7 (neutral-300) | #505050 (neutral-700) |
---
## Spatial System
Base unit: 8px. All spacing and line-heights snap to 8px grid multiples.
### Spacing Scale
| Token | Value |
|-------|-------|
| `--space-0` | 0px |
| `--space-px` | 1px |
| `--space-0h` | 4px |
| `--space-1` | 8px |
| `--space-2` | 16px |
| `--space-3` | 24px |
| `--space-4` | 32px |
| `--space-5` | 48px |
| `--space-6` | 64px |
| `--space-7` | 80px |
| `--space-8` | 96px |
| `--space-9` | 128px |
| `--space-10` | 160px |
| Purpose | Steps | Values |
|---------|-------|--------|
| Component padding | step 2–3 | 16–24px |
| Section gap | step 5–6 | 48–64px |
| Page margin | step 7–8 | 80–96px |
Do NOT use arbitrary pixel values for spacing. Instead, use `--space-*` tokens.
### Type Scale
Minor Third (1.200), base 16px. Sizes integer-rounded. Line-heights 8px-snapped.
| Token | Size | Line-Height | Role |
|-------|------|-------------|------|
| `--text-xs` | 11px | 24px (`--lh-sm`) | Fine print, captions |
| `--text-sm` | 13px | 24px (`--lh-sm`) | Secondary, metadata |
| `--text-base` | 16px | 24px (`--lh-sm`) | Body text |
| `--text-lg` | 19px | 32px (`--lh-lg`) | Lead paragraphs |
| `--text-xl` | 23px | 32px (`--lh-lg`) | h4 subheadings |
| `--text-2xl` | 28px | 40px (`--lh-2xl`) | h3 section headings |
| `--text-3xl` | 33px | 40px (`--lh-2xl`) | h2 major headings |
| `--text-4xl` | 40px | 48px (`--lh-3xl`) | h1 page titles |
Do NOT use computed `line-height: 1.5`. Instead, assign `--lh-*` tokens.
Apply `max-width: 66ch` to text containers.
### Border Radius
| Token | Value |
|-------|-------|
| `--radius-none` | 0px |
| `--radius-sm` | 4px |
| `--radius-md` | 8px |
| `--radius-lg` | 12px |
| `--radius-xl` | 16px |
| `--radius-2xl` | 24px |
| `--radius-full` | 9999px |
| Context | Adjustment | Radius |
|---------|-----------|--------|
| Error/danger | -50% | 2px |
| Warning | -25% | 2px |
| Success | +25% | 4px |
| Neutral/info | default | 3px |
| Avatar | circle | 50% |
| Input fields | -25% | 2px |
Do NOT apply high curvature (`--radius-full`) to error or warning elements. Instead, use `--radius-sm` or lower.
Use `--radius-md` (8px) for cards and containers. Use `--radius-sm` (4px) for inputs and badges.
Do NOT apply border-radius to accent-bordered elements (3–4px `border-left` or `border-top` callouts, blockquotes, step indicators). Radius rounds the accent stroke's endpoints into decoration that communicates nothing. Instead, use `border-radius: 0` and let the accent border terminate with sharp edges. Exception: cards with a full surrounding `border` (all four sides) may use `--radius-md` even when one side carries a thicker accent override.
### Line Weight
| Token | Thickness | Light Color | Dark Color |
|-------|-----------|-------------|------------|
| `--border-subtle` | 1px | #d4d4d4 (neutral-200) | #3d3d3d (neutral-800) |
| `--border-default` | 1px | #b7b7b7 (neutral-300) | #505050 (neutral-700) |
| `--border-emphasis` | 1px | #808080 (neutral-500) | #808080 (neutral-500) |
| `--border-strong` | 2px | #505050 (neutral-700) | #b7b7b7 (neutral-300) |
| `--border-accent` | 3px | semantic color | semantic color |
Do NOT exceed 4 visible structural borders per viewport section. Instead, use spacing or surface tone for grouping.
Reserve `--border-accent` (3px) for semantic callouts only.
### Target Sizes
| Token | Height | H-Padding | Use |
|-------|--------|-----------|-----|
| `--target-sm` | 32px | 16px | Tertiary actions, inline buttons, tags |
| `--target-md` | 40px | 24px | Secondary actions, form inputs |
| `--target-lg` | 48px | 32px | Primary actions, main CTAs |
| `--target-xl` | 56px | 48px | Hero CTAs, prominent actions |
All interactive elements must be at least 24×24 CSS px (WCAG 2.2 AA). Primary actions use `--target-lg` (48px) to meet WCAG AAA.
Do NOT place adjacent interactive elements closer than 8px apart.
### Proximity Grouping
| Relationship | Spacing |
|-------------|---------|
| Tightly related | 8px (`--space-1`) |
| Within-group | 16px (`--space-2`) |
| Between-group | 48px (`--space-5`) |
| Between-section | 64–96px (`--space-6` – `--space-8`) |
Within-group spacing must be less than half the between-group spacing.
Do NOT use equal spacing within and between groups. Instead, ensure at least a 2× step difference.
---
## Content Composition
### Page Reading Flow
Content follows a single-column vertical flow. Block elements (figures, code blocks, admonitions) interrupt the prose column and span its full width.
| Transition | Spacing | Token |
|-----------|---------|-------|
| Paragraph → paragraph | 16px | `--space-2` |
| Paragraph → block element | 32px | `--space-4` |
| Block element → paragraph | 32px | `--space-4` |
| Block element → block element | 24px | `--space-3` |
| Section heading → first element | 16px | `--space-2` |
| Last element → section heading | 64px | `--space-6` |
Apply `max-width: 66ch` to prose containers. Block elements (figures, code blocks) may extend to the content column's full width but do NOT exceed it.
Do NOT place a figure before its first textual reference. Instead, the figure appears immediately after the paragraph that introduces it.
### Figure Integration
Use semantic `` and `` for all visual block elements — diagrams, screenshots, illustrations, and annotated code.
```html
Figure 4.3 — Context window token allocation across three agent turns.
```
| Property | Value |
|----------|-------|
| Caption font | `--text-sm` (13px) |
| Caption color | `--text-muted` |
| Caption spacing | `--space-1` above caption |
| Figure margin | `--space-4` top and bottom |
| Numbering | Optional, section-based: `Figure {section}.{n} —` |
| Figure Type | Width | Alignment |
|------------|-------|-----------|
| Diagram (SVG) | 100% of content column | Centered via `margin-inline: auto` |
| Screenshot | Intrinsic, max 100% | Centered |
| Inline icon pair | Intrinsic | Inline with text |
Do NOT use figures without captions. Every `` must contain a `` that describes the content.
Do NOT use `` directly for diagrams or illustrations. Instead, wrap in `` with a descriptive caption.
### Progressive Disclosure
| Pattern | Primitive | Use When |
|---------|-----------|----------|
| Collapsible depth | `` / `` | Optional deep-dive, implementation detail, proof, or derivation |
| Parallel alternatives | `` | Multiple equivalent approaches (languages, frameworks, OS) |
| Semantic alert | Admonition (`:::type`) | Contextual warnings, tips, or prerequisites that interrupt flow |
| Question | If Yes → |
|----------|----------|
| Is this content required to understand the main argument? | Keep inline — do NOT hide it |
| Does the reader choose one of N equivalent paths? | `` |
| Is this a tangent that only some readers need? | `` |
| Does this interrupt flow with a warning, tip, or prerequisite? | Admonition |
Do NOT hide critical content behind ``. Instead, keep essential information in the primary prose flow.
Do NOT nest disclosure patterns. A `` inside a `` panel (or vice versa) adds cognitive overhead. Instead, flatten the structure.
### Content Block Hierarchy
Content occupies three tiers; tiers 1–2 must be self-sufficient.
| Tier | Elements | Role |
|------|----------|------|
| 1 — Primary | Prose paragraphs, headings, inline code | Core argument and explanation |
| 2 — Secondary | Figures, code blocks, tables | Evidence, demonstration, specification |
| 3 — Tertiary | Admonitions, ``, footnotes | Supplementary context, caveats, deep-dives |
Do NOT place essential information exclusively in tier 3. Instead, state the key point in tier 1 prose, then elaborate in tier 3 if needed.
Do NOT exceed 3 consecutive block elements (tier 2 or 3) without intervening prose. Instead, add a bridging sentence that connects the blocks to the argument.
---
## UI Patterns
### Buttons
| Variant | Background | Border | Text | Use |
|---------|-----------|--------|------|-----|
| Primary CTA | cyan-600 (light) / cyan-400 (dark) | none | white | Main conversion action (1 per page max) |
| Primary | #2b2b2b (light) / #e8e8e8 (dark) | none | white (light) / dark (dark) | Standard primary actions |
| Outline | transparent | dark | dark | Secondary actions |
| Ghost | transparent | none | underlined dark | Tertiary / inline actions |
Chromatic color is permitted on **Primary CTA only** — one per page, using `var(--visual-cyan)` as background. This is the sole exception to achromatic buttons. All other button variants remain neutral. Do NOT introduce additional hue variants. Hover: darken fill (shift to cyan-700/cyan-300). Do NOT change hue on hover.
White text on cyan-600 (#007576) achieves 5.38:1 contrast ratio (WCAG AA). White text on cyan-400 (#00b2b2) in dark mode achieves sufficient contrast on the lighter teal fill.
### Badges
| Mode | Background | Text | Border |
|------|-----------|------|--------|
| Light | shade-50 | shade-600 | 1px solid shade-600 |
| Dark | shade-600 | white | none |
Example (cyan light): `background: #d4fffe; color: #007576; border: 1px solid #007576;`
Example (cyan dark): `background: #007576; color: #fff;`
### Cards
- Border: `1px solid var(--border-default)`, `border-radius: var(--radius-md)`
- Background: `var(--surface-raised)` or `var(--surface-page)`
- Hover: shift border to neutral-400. Do NOT add color on hover. Instead, increase border contrast only.
### Callout Borders
- 3px left border in semantic color + colored label text. Body text stays neutral.
- Example: `border-left: 3px solid #1369b0;` with `TIP`
- Do NOT apply border-radius to callout containers. Instead, use `border-radius: 0`. The accent border's sharp endpoints reinforce its directional intent.
### Interactive States
| State | Treatment |
|-------|-----------|
| Rest | neutral border |
| Hover | border lightens (neutral-700 → neutral-400) |
| Focus | darker border (contrast shift) |
| Active | darker fill or inverted contrast |
All state changes use contrast/weight shifts. Do NOT introduce hue changes on interaction states. Instead, shift lightness within the neutral palette.
### Inputs
- Border: neutral. Focus: darker border.
- Do NOT use colored focus rings. Instead, increase border contrast on focus.
### Admonitions
Docusaurus admonition types map to the semantic hue palette and use the Callout Borders pattern (3px left border + colored label).
| Admonition | Hue | Token | Label Color |
|-----------|-----|-------|-------------|
| `:::tip` | Cyan (H:195°) | `--visual-cyan` | `var(--visual-cyan)` |
| `:::info` | Indigo (H:250°) | `--visual-indigo` | `var(--visual-indigo)` |
| `:::note` | Neutral | `--visual-neutral` | `var(--visual-neutral)` |
| `:::caution` | Warning (H:70°) | `--visual-warning` | `var(--visual-warning)` |
| `:::danger` | Error (H:25°) | `--visual-error` | `var(--visual-error)` |
Body text inside admonitions stays `--text-body`. Only the label and left border carry the semantic color.
Do NOT apply background tints to admonitions. Instead, use `--surface-raised` for the container background, matching the flat construction constraint.
---
## Illustration System
Curved forms (Smooth Circuit) are default. Angular forms (Terminal Geometry) reserved for high-arousal states. See `ILLUSTRATION_GUIDE.md`.
### Actor Primitives
All actor primitives share a bounding-box grid for visual equal-standing.
#### Bounding Box Grid
| Primitive | Emoji Ref | Bounding Box | Semantic Color |
|-----------|-----------|--------------|----------------|
| `OperatorNode` | 🧑💻 | 40×40 (primary) / 32×32 (worker) | Neutral (`--visual-neutral`) |
| `AgentNode` | 🤖 | 40×40 (primary) / 32×32 (worker) | Original emoji palette (hardcoded) |
All coordinates in `ActorNodes.tsx` are annotated: `// Computed via scripts/compute-actor-coords.js`.
#### Size Encoding
Hierarchy is expressed through **size only**, never through color.
| Role | BB Size | Use |
|------|---------|-----|
| Primary / orchestrator | 40×40 | Top of hierarchy, one per level |
| Worker / delegate | 32×32 | Bottom of hierarchy, multiple parallel |
Do NOT distinguish orchestrator from worker agents by color. Use 40→32 size differential only.
Do NOT place primary and worker actors in the same horizontal row without applying the size step.
#### Construction
**OperatorNode** — Smooth Circuit head, Terminal Geometry legs:
- Head circle: `r = BB × 0.15`. Fill `--visual-bg-neutral`, stroke `--visual-neutral` 2px.
- Shoulder U-path: Smooth Circuit (`stroke-linecap="round"` `stroke-linejoin="round"`). Span = BB × 0.90, corner radius = BB × 0.10.
- Legs: two lines (Terminal Geometry, `stroke-linecap="square"`) spreading to BB base.
**AgentNode** — Original Google Noto 🤖 emoji (`/img/emoji/u1f916.svg`):
- Delegates to `NotoEmoji` component with `codepoint="1f916"`.
- Gradient ID isolation is automatic; SVG `` renders as a separate document.
**NotoEmoji** — Generic wrapper for any Noto emoji:
- `` renders `/img/emoji/u1f4a1.svg`.
- Add new emojis via `node scripts/fetch-emoji.js ` — caches raw in `scripts/.noto-cache/`, writes cleaned SVG to `website/static/img/emoji/u{cp}.svg`.
#### Animated Emoji: `NotoEmoji` vs Hand-Coded Components
Use **`NotoEmoji`** (via ``) for static emoji nodes. The SVG renders as an opaque sub-document — individual paths inside it are not accessible to the parent SVG's CSS or SMIL, so per-path animation is impossible.
Use a **hand-coded component** (e.g. `AuthorWaveNode`) when the emoji needs animation. Inline the paths directly into the parent SVG so CSS transforms and `className` can target individual elements. Obtain source paths from the Noto SVG (via `scripts/fetch-emoji.js`); simplify fills to flat colors (no gradients) and omit any paths not visible at the target size.
#### Emoji Node Rendering
ALL `NotoEmoji` instances render **bare** — no background ``, no filled container, no exceptions.
- The emoji IS the node. Its bounding box IS the hit area.
- Do NOT wrap `NotoEmoji` in a colored ``, ``, or any other filled shape.
- Do NOT add squircle or pill containers behind emoji nodes — those are structural region shapes (see Shape Selection Procedure).
#### Ghost Placeholders
Ghost placeholders provide spatial mass before a node enters, preserving layout balance (per the "every act-state must be visually complete" rule).
- **Construction:** dashed-stroke rect (`strokeDasharray="3 4"`, `strokeWidth={1}`), semantic background fill (`--visual-bg-{hue}`), semantic stroke (`--visual-{hue}`).
- **Size:** matches the emoji's bounding box (or the head portion for actor primitives with body geometry).
- **Lifecycle:** `ghostShown` → visible while node is pending; `ghostHidden` → `opacity: 0` when node enters.
- The ghost is the ONLY rect. The settled node is a bare emoji with no background shape.
#### Communication Medium
> **Note:** `PromptCard` was renamed to `PromptIcon`. `TravelingPromptCard` is its animated variant — used for delegation-flow motion along an edge path; not a separate primitive.
Every edge connecting actor nodes carries either:
- A `PromptIcon` artifact (36×20 centered prompt card, used in delegation flows), or
- A plain Bezier arc with arrowhead (for return flow / result propagation).
Do NOT use other metaphors (looms, punch cards, pipes) for prompt artifacts.
---
### Shape Vocabulary
| Family | Forms | Superellipse n | Default For |
|--------|-------|----------------|-------------|
| Smooth Circuit | Squircle containers, Bezier connectors, circular endpoints, round caps | n = 3–4 (squircle), n = 2 (circle) | Positive-valence: success, AI, system, knowledge, progress |
| Terminal Geometry | Diamond accents, chevron arrows, angular miters, bracket syntax | n = 1–1.5 (diamond), 45° angles | High-arousal: error, warning, code structure, human action |
Do NOT use strict-rectangle-only construction (90° routing, sharp corners on all containers). Instead, use squircle containers (n=3–4) even for box-like elements.
Do NOT apply angular containers (diamonds, sharp-cornered shapes) to success, AI, or system content. Instead, use squircle or circular containers for positive-valence elements.
### Shape Selection Procedure
Smooth Circuit for all hues except Error and Warning (Terminal Geometry).
#### Step 1: Select container shape
| Content Type | Container | SVG Implementation |
|-------------|-----------|-------------------|
| System node / module | Squircle | `` (40px box) or superellipse `` |
| Agent / AI process region | Circle or pill | `` or `` |
| Data / knowledge | Rounded rect | `` |
| Human actor region | Circle or squircle | `` or `` |
| Generic container | Squircle | `` to `` |
| Code / terminal | Diamond or sharp rect | `` (4-point) or `` |
| Error state | Sharp rect or diamond | `` or `` |
| Warning state | Triangle or diamond | `` (3-point up) |
> **Note:** These containers describe **structural regions and grouping shapes** — not per-node backgrounds. Emoji icon nodes always render bare (see Actor Primitives → Emoji Node Rendering). `AgentNode` is a bare 🤖 emoji, not a circle container; "Agent / AI process region" refers to a panel or zone grouping multiple agent nodes.
#### Step 3: Choose connector style
| Connection Type | Connector | SVG Implementation |
|----------------|-----------|-------------------|
| Data flow (happy path) | Bezier curve | `` with `stroke-linecap="round"` |
| Error / rejection path | Angular polyline | `` with `stroke-linecap="square"` |
| Bidirectional | Bezier with markers at both ends | `marker-start` + `marker-end` |
| Optional / dashed | Bezier with dash array | `stroke-dasharray="6 4"` |
### Stroke Weight Scale
| Token | Value | Purpose |
|-------|-------|---------|
| `--stroke-fine` | 1px | Grid lines, hairlines, decorative rules |
| `--stroke-light` | 1.5px | Secondary connectors, annotations |
| `--stroke-default` | 2px | Standard connectors, internal details |
| `--stroke-medium` | 2.5px | Container outlines, primary shapes |
| `--stroke-heavy` | 3px | Emphasized elements, primary flow arrows |
| `--stroke-accent` | 4px | Semantic accent strokes (1 per diagram max) |
Do NOT exceed 4px stroke width. Instead, use fill-weight or size increase for emphasis.
Do NOT use more than 3 distinct stroke weights in a single diagram.
### Arrow Markers
| Type | Marker Size | refX | Polygon Points |
|------|------------|------|---------------|
| Standard | 6×6 | 5 | `0 0, 6 3, 0 6` |
| Large | 8×8 | 6 | `0 0, 8 4, 0 8` |
Use Standard (6px) by default. Use Large (8px) only in narrow viewBox diagrams (< 400px wide). Arrow fill inherits from stroke color.
### Construction Rules
1. **Grid snap** — All anchor points snap to the 8px spatial grid (`--space-*` tokens). Minimum shape dimension = 8px.
2. **Preferred angles** — 15°, 30°, 45°, 60°, 75°, 90°. Other angles require justification.
3. **Proportional corner radius** — Scale `rx` proportionally: `rx = height × 0.25` (range 8–16px). Do NOT use a fixed `rx` regardless of box size.
4. **Minimum gap** — 8px (`--space-1`) between shapes. 16px (`--space-2`) between shape and label.
5. **Label placement** — Labels go directly adjacent to elements (spatial contiguity). Do NOT use a separate legend when inline labels fit.
6. **Coherence** — Every shape serves a communicative purpose. Do NOT add decorative shapes.
### Flat Construction Enforcement
Do NOT use SVG filters (``, `feDropShadow`, `feGaussianBlur`). Instead, use stroke-weight hierarchy and surface tone for emphasis.
Do NOT use SVG `` or `` for fills. Instead, use solid `--visual-bg-*` tint tokens.
Do NOT use `box-shadow` on diagram containers. Instead, use `border` with `--border-default` or semantic color.
---
## Icon & Diagram Geometry
### Icon Tiers
| Tier | Canvas / viewBox | Style | Use |
|------|-----------------|-------|-----|
| UI icon | `0 0 24 24` | Outline stroke (`currentColor`) | Inline text, buttons, nav, phase indicators |
| Illustration icon | `0 0 128 128` | Flat filled (Noto emoji style) | Bullet icons, feature cards, hero callouts |
Both tiers share `--icon-*` size tokens for rendered width/height. The viewBox is fixed per tier; scaling is via `width`/`height` attributes.
### Icon Sizes
| Token | Value | Purpose |
|-------|-------|---------|
| `--icon-sm` | 16px | Inline text icons |
| `--icon-md` | 24px | Default UI icons |
| `--icon-lg` | 32px | Card/callout icons |
| `--icon-xl` | 48px | Diagram node icons |
| `--icon-2xl` | 64px | Hero/feature icons |
Do NOT create icons at arbitrary sizes. Instead, use `--icon-*` tokens.
### UI Icon Construction
| Property | Value |
|----------|-------|
| `fill` | `none` (outline style) |
| `stroke` | `currentColor` |
| `stroke-width` | `2` (at 24px canvas) |
| `stroke-linecap` | `round` (Smooth Circuit) or `square` (Terminal Geometry) |
| `stroke-linejoin` | `round` (Smooth Circuit) or `miter` (Terminal Geometry) |
### Illustration Icon Construction
Illustration icons follow a Noto Color Emoji–inspired flat construction standard. All 128×128 viewBox icons must comply. This section applies to *custom* illustration icons — emoji representations (fetched, inlined, or recreated from Noto) are exempt per constraint #4.
#### Core Principles
1. **Flat fills only** — solid color shapes. No tonal gradation within the same structural part.
2. **Layered silhouette** — 3–5 overlapping filled shapes that read as a bold silhouette at 32px.
3. **Geometric simplicity** — minimize path points; prefer arcs and clean curves over organic detail.
4. **Achromatic structure + chromatic accent** — neutral fills for structure, `currentColor` for the one semantic layer.
#### Fill Budget
Maximum 4 distinct fill values per icon:
| Slot | Fill | Neutral shade | Role |
|------|------|---------------|------|
| Body | hardcoded hex | neutral-600 (`#666666`) | Primary structural mass |
| Detail | hardcoded hex | neutral-900 (`#2b2b2b`) | Dark accents, internal features |
| Secondary | hardcoded hex | neutral-300 (`#b7b7b7`) | Secondary body, bezels, minor marks |
| Accent | `currentColor` | inherited from parent | Semantic tint (solid or `opacity="0.15"` wash) |
Slot usage: Body + Accent are required. Detail and Secondary are optional. Total ≤ 4.
#### Accent Layer
- Every illustration icon MUST have ≥1 element with `fill="currentColor"`.
- Two permitted opacity values: `1` (solid accent) and `0.15` (tinted wash). No other opacities.
- Do NOT hardcode semantic hex colors (e.g., `#ad3735`). Use `currentColor` so the parent assigns meaning via `--visual-*`.
- Structural fills must be opaque. A path that serves as backdrop for other visible elements (e.g., a clock face behind tick marks) must use a neutral hex fill, not a `currentColor` wash. Reserve `opacity="0.15"` washes for overlay accents that layer on top of opaque structure (e.g., a tinted face layered over a `#666666` body).
#### Banned Techniques
- Highlight fills (lighter neutral on darker to simulate reflection)
- Shadow ridge fills (darker neutral alongside structural neutral to simulate depth)
- Multiple tonal layers on the same part (e.g., neutral-100 + -300 + -500 + -600 on one object)
- SVG filters, gradients, or opacity shading on neutral fills
- neutral-50 (`#f5f5f5`), neutral-100 (`#e8e8e8`), neutral-400 (`#9b9b9b`), neutral-500 (`#808080`) as fill colors — these exist only for 3D simulation
### Diagram Sizing
| Diagram Type | ViewBox Width | Typical Height |
|-------------|--------------|---------------|
| Inline icon pair | 100–200 | 48–64px |
| Flow diagram | 400–600 | 160–240px |
| System diagram | 500–1000 | 300–500px |
| Comparison (side-by-side) | 600–1000 | 200–400px |
| Figure caption | Same as parent figure | `--text-sm` line-height (24px) |
All diagram containers use `width: 100%` with SVG `viewBox` controlling aspect ratio. Do NOT set fixed pixel widths on diagram containers.
### Diagram Accessibility
Every SVG diagram requires:
1. `role="img"` on the `