# Design System — Agent Orchestrator ## Product Context - **What this is:** A web-based dashboard for managing fleets of parallel AI coding agents. Each agent gets its own git worktree, branch, and PR. The dashboard is the operator's single pane of glass. - **Who it's for:** Developers running 10-30+ AI coding agents in parallel. From solo devs to engineering teams. - **Space/industry:** AI agent orchestration. Competitors: Conductor.build, T3 Code, OpenAI Codex app, Emdash. All are native Mac apps. Agent Orchestrator is the web-based alternative. - **Project type:** Web app (Next.js 15, React 19, Tailwind v4). Kanban board with 6 attention-priority columns. ## Aesthetic Direction - **Direction:** Industrial Precision - **Decoration level:** Intentional — subtle depth through surface hierarchy, ambient glow on active states, gradient surfaces in dark mode. No decorative blobs, no gratuitous gradients. - **Mood:** Trading terminal meets control room. Dense, scannable, utilitarian, with just enough warmth that developers want to live in it for 10 hours. "I'm running an operation" not "I'm organizing tasks." - **Reference sites:** Conductor.build, t3.codes, openai.com/codex, emdash.dev ## Typography - **Display/Hero:** Geist Sans, weight 680, letter-spacing -0.035em — same font as body but differentiated through weight and tracking. Tighter and heavier creates display hierarchy without a font swap. No cognitive gear-shifts on a scan-heavy dashboard. - **Body:** Geist Sans, weight 400, letter-spacing -0.011em — purpose-built for dense interfaces at 13px. Better digit alignment than IBM Plex Sans, designed for exactly this density level. - **UI/Labels:** Geist Sans, weight 600, letter-spacing 0.06em, uppercase, 10-11px — column headers, section labels, status indicators. - **Data/Tables:** JetBrains Mono, weight 400, 11-13px, tabular-nums — agent IDs, branch names, timestamps, commit hashes, diff stats, PR numbers. - **Code:** JetBrains Mono, weight 400 — terminal output, code blocks, inline code. - **Loading:** Google Fonts via next/font/google. CSS variables: `--font-sans` (Geist), `--font-mono` (JetBrains Mono). Display strategy: swap. - **Scale:** - xs: 10px (timestamps, metadata) - sm: 11px (secondary text, captions, labels) - base: 13px (body text, card content) - lg: 15px (section titles) - xl: 17px (page titles) - display: clamp(22px, 2.8vw, 32px) (hero headings) ## Color - **Approach:** Restrained with signal accents. Color is a priority channel, not decoration. - **Accent (cool):** #5B7EF8 — interactive elements, links, focus rings. Used sparingly. - **Accent hover:** #7a96ff - **Accent tint:** rgba(91, 126, 248, 0.12) - **Attention (warm):** #f1be64 — states requiring human input. Amber is universally "needs attention" without the panic of red. ### Surfaces (Dark Mode) | Token | Value | Usage | |-------|-------|-------| | bg-base | #0a0d12 | Page background | | bg-surface | #11161d | Card/column backgrounds | | bg-elevated | #171d26 | Modals, popovers, hover states | | bg-elevated-hover | #1c2430 | Hover on elevated surfaces | | bg-subtle | rgba(177, 206, 255, 0.05) | Subtle tints, pill backgrounds | ### Surfaces (Light Mode) | Token | Value | Usage | |-------|-------|-------| | bg-base | #f5f5f7 | Page background | | bg-surface | #ffffff | Card/column backgrounds | | bg-elevated | #ffffff | Modals, popovers | | bg-elevated-hover | #f7f7f8 | Hover states | | bg-subtle | #f0f0f2 | Subtle tints | ### Text (Dark Mode) | Token | Value | Usage | |-------|-------|-------| | text-primary | #eef3ff | Headings, card titles, body. Blue-white, not pure white. | | text-secondary | #a5afc4 | Descriptions, metadata. Readable in dense layouts. | | text-tertiary | #6f7c94 | Timestamps, placeholders, disabled states. | ### Text (Light Mode) | Token | Value | Usage | |-------|-------|-------| | text-primary | #1b1b1f | Headings, card titles, body. | | text-secondary | #5e5e66 | Descriptions, metadata. | | text-tertiary | #8e8e96 | Timestamps, placeholders. | ### Borders (Dark Mode) | Token | Value | Usage | |-------|-------|-------| | border-subtle | rgba(160, 190, 255, 0.08) | Dividers, section separators | | border-default | rgba(160, 190, 255, 0.14) | Card edges, input borders | | border-strong | rgba(185, 214, 255, 0.24) | Hover states, focus indicators | ### Status Colors | Status | Dark Mode | Light Mode | Usage | |--------|-----------|------------|-------| | Working | #22c55e | #16a34a | Agent actively coding. Green dot with pulse ring animation. | | Ready | #5B7EF8 | #5e6ad2 | Queued, awaiting start or CI pending. | | Respond | #f1be64 | #ca8a04 | Needs human input. Amber = attention without panic. | | Review | #06b6d4 | #0891b2 | Code ready for review. Cyan = "look when ready." | | Error | #ef4444 | #dc2626 | CI failed, agent crashed. Red = broken. | | Done | #3a4252 | #d0d7de | Completed. Fades to secondary text. Done items recede. | - **Dark mode strategy:** Blue-tinted graphite palette (not neutral gray). Reduce font weight by one step in dark mode (semibold becomes 500, bold becomes 600). Inset highlights on elevated surfaces: `inset 0 1px 0 rgba(255,255,255,0.04)`. Subtle radial gradients on body for ambient depth. ## Spacing - **Base unit:** 4px - **Density:** Comfortable — dense enough for 30+ cards, spacious enough for 10-hour sessions - **Scale:** 1(4) 2(8) 3(12) 4(16) 5(20) 6(24) 8(32) 10(40) 12(48) 16(64) ## Layout - **Approach:** Grid-disciplined - **Kanban grid:** 6 equal-width columns on desktop, 3 on tablet, stacked on mobile - **Mobile column order:** Respond > Review > Pending > Working (urgency-first) - **Max content width:** 1280px for settings/detail pages - **Border radius:** - base: 2px (cards, buttons, inputs — consistent, sharp, intentional) - sm: 4px (tooltips, small transient elements) - md: 6px (dropdowns, floating interactive elements) - lg: 8px (modals, large floating overlays) - full: 9999px (pills, badges, count indicators) - **Card inset highlight:** `inset 0 1px 0 rgba(255,255,255,0.04)` in dark mode - **Status accent:** 2px solid left border on session cards, colored by status ## Motion - **Approach:** Intentional — every animation has a clear purpose and passes the frequency test - **Easing:** - enter/exit: `cubic-bezier(0.16, 1, 0.3, 1)` (spring-like deceleration, feels responsive) - move/morph: `cubic-bezier(0.77, 0, 0.175, 1)` (natural acceleration/deceleration) - hover/color: `ease-out` - constant (spinner, marquee): `linear` - **Duration:** - micro: 100-160ms (button press, hover state) - short: 150-200ms (tooltips, popovers, card entrance) - medium: 200-300ms (modals, drawers, card expand) - long: 2s (status dot pulse, continuous indicators) - **Card entrance:** `translateY(8px)` + opacity, 0.2s with 40ms stagger between siblings - **Status pulse:** GPU-composited pseudo-element on Working dots. `transform: scale(0.8→1.3)` + `opacity: 0.5→0`, 2s ease-in-out infinite. Not box-shadow (triggers paint). - **Button press:** `transform: scale(0.97)` on `:active`, 160ms ease-out - **Rules:** - Never animate keyboard-initiated actions (command palette toggle, shortcuts) - One animation per element, one purpose per animation - CSS transitions for interruptible UI, keyframes for continuous indicators - All animations must respect `prefers-reduced-motion: reduce` - Use `contain: layout style paint` on session cards for performance with 30+ cards ## Performance Guidelines - Use `contain: layout style paint` and `content-visibility: auto` on session cards - Animate only `transform` and `opacity` (GPU-composited). Never animate `padding`, `margin`, `height`, `width`, `border`, or `box-shadow`. - Status dot pulse must use pseudo-element with `will-change: transform, opacity`, not box-shadow rings - Backdrop blur on nav capped at 12px (diminishing returns above 12) - Pause all non-essential animations when tab is hidden ## Anti-Patterns (Never Do) - Purple/violet gradients as default accent - 3-column feature grid with icons in colored circles - Centered everything with uniform spacing - Uniform bubbly border-radius (8-12px) on all elements - Gradient buttons as primary CTA pattern - `transition: all` — always specify exact properties - `scale(0)` entry animations — start from `scale(0.95)` with `opacity: 0` - `ease-in` on UI elements — use `ease-out` for responsiveness - Animations over 300ms on frequently-triggered UI elements ## Decisions Log | Date | Decision | Rationale | |------|----------|-----------| | 2026-03-28 | Initial design system created | Created by /design-consultation with competitive research (Conductor.build, T3 Code, OpenAI Codex, Emdash) + 4 design voices (primary, Codex CLI, Claude subagent, Emil Kowalski design eng) | | 2026-03-28 | Geist Sans + JetBrains Mono (2 fonts only) | Emil review: 4 fonts creates cognitive gear-shifts on scan-heavy dashboards. Two fonts, hierarchy through weight + tracking. | | 2026-03-28 | Accent #5B7EF8 instead of Tailwind blue-500 | Emil review: stock Tailwind blue reads "default" and undermines Industrial Precision identity. Existing token-reference blue is more sophisticated. | | 2026-03-28 | Dual accent (cool blue + warm amber) | All 3 outside voices independently proposed amber for attention states. Two accents with clear semantic roles beat a single color. | | 2026-03-28 | Fixed-width kanban columns (not variable) | Emil review: variable width breaks spatial memory. Encode urgency in column header dots instead. | | 2026-03-28 | 2px base border-radius | Full 0px risks looking unstyled. 2px reads as intentionally sharp while feeling designed. Consistent across cards, buttons, inputs. Distinct from competitors' 8-12px rounded corners. | | 2026-03-28 | Keep dot pulse, remove border heartbeat | Emil review: 4s border animation on 15+ cards is "decorative anxiety" with high perf cost. Existing 8px dot pulse is correct pattern — small surface, GPU-composited. | | 2026-03-28 | Simplify ready-to-merge to single animation | Emil review: 3 concurrent keyframe animations on merge-ready cards is over-engineered. One animation per element, one purpose. Keep dot pulse only. |