| name | design-system |
| description | Dotbot CRT/retro-futuristic design system: tokens, components, patterns, and anti-patterns for the control panel UI. |
Dotbot Design System
Design system for dotbot's retro-futuristic CRT control panel UI. Use this alongside the global frontend-design skill, which provides creative principles. This skill provides the project-specific constraints.
Identity
The UI is a vintage hardware control panel with phosphor CRT displays. Signature elements:
- Phosphor glow — text-shadow on key values and status indicators
- Scanline overlay — 2px repeating gradient on body::after, always present
- Grid backgrounds — dual-scale (10px + 50px) on module screens
- LED indicators — 8px glowing circles for status
- Deep blacks — backgrounds from rgb(5,5,8) to rgb(13,14,20)
- Amber phosphor — default primary color with warm glow
Architecture
CSS load order (each file has a specific responsibility):
theme.css — Color system source of truth (CSS custom properties, RGB components, opacity variants, semantic data attributes)
base.css — Font imports, reset, body, scrollbar, toast notifications, loading states
layout.css — Page grid, header/footer, tabs, LED indicators
sidebar.css — Left/right sidebar panels, navigation
modules.css — Reusable components (stat cards, task lists, module panels, buttons)
views.css — Tab-specific styles (pipeline, product, workflow)
modal.css — Dialogs, task detail, forms
crt.css — CRT effects, oscilloscope, panic button
processes.css — Process/decision rows, interview UI
responsive.css — Breakpoint overrides
Source of truth: core/ui/static/
Runtime copy: .bot/core/ui/static/ (generated by dotbot init)
Theme system: theme-config.json defines 6 presets as RGB arrays. theme.js reads the config and sets CSS custom properties at runtime. theme.css provides defaults and computes opacity variants.
Design Tokens
Colors
Reference: core/ui/static/css/theme.css
Semantic roles (all via CSS custom properties, never raw values):
| Role | Variable | Default RGB | Purpose |
|---|
| Primary | --color-primary | 232 160 48 | Main text, actions, focus |
| Primary dim | --color-primary-dim | 184 120 32 | Secondary text, muted primary |
| Secondary | --color-secondary | 95 179 179 | Interactions, highlights, links |
| Tertiary | --color-tertiary | 170 136 255 | Tags, metadata, decorative |
| Success | --color-success | 0 255 136 | Completion, positive states |
| Error | --color-error | 209 105 105 | Danger, failures |
| Warning | --color-warning | 232 160 48 | Caution, attention |
| Info | --color-info | 68 136 255 | Information, utility |
| Muted | --color-muted | 136 136 153 | Labels, tertiary text |
Background depth ladder (darkest to lightest):
| Variable | Default RGB | Use |
|---|
--bg-deep | 5 5 8 | Page background |
--bg-panel | 10 11 15 | Panels, modals, toasts |
--bg-module | 13 14 20 | Module/card backgrounds |
--bg-screen | 7 10 8 | Screen content areas (greenish tint) |
UI chrome: --bezel-edge, --bezel-light (70% bezel + 30% black), --bezel-dark (45% bezel + 55% black)
Opacity variants: Use --primary-{n} where n = 05, 08, 10, 12, 15, 20, 25, 30, 40, 50. For new code, prefer the core steps: 05, 10, 15, 20, 30, 50. Other colors have fewer steps (see theme.css).
Glow variants: --primary-glow, --success-glow, --secondary-glow, --error-glow (all 50% opacity, for text-shadow and box-shadow).
Semantic data attributes: Use data-status="todo|in-progress|done" and data-type="primary|secondary|success|warning|error" to automatically set --status-color/--type-color variables.
Typography
Reference: core/ui/static/css/base.css
Font stacks:
--font-mono: JetBrains Mono, Consolas, monospace — for data, values, code, controls, body text
--font-ui: Inter, system sans-serif — for labels, descriptions, readable prose
Body default: font-family: var(--font-mono); font-size: 13px; line-height: 1.5
Type scale (use these sizes for new code):
| Token | Size | Use |
|---|
| xs | 9px | Micro labels, badges, timestamps |
| sm | 10px | Section headers, tab labels, uppercase UI text |
| base | 11px | Body content, list items, buttons |
| md | 12px | Card descriptions, toast text |
| lg | 14px | CRT loading text, subsection headers |
| xl | 16px | Logo, major section headers |
| display | 28px | Stat card values (with phosphor glow) |
| hero | 42px | Decorative glyphs (workflow-launch icon) |
Weight conventions: 400 body, 500 labels, 600 buttons/headers, 700 stat values
Letter-spacing: 0.05em (tight labels), 0.08em (tabs), 0.1em (section headers), 0.15em (display/logo)
Text-transform: uppercase on all UI labels, badges, buttons, section headers
Spacing
4px base unit. Use these values:
| Value | Use |
|---|
| 4px | Tight gaps (between badge and text) |
| 6px | Small gaps (list item internal) |
| 8px | Element gaps (between items in a group) |
| 12px | Component internal padding (task rows) |
| 16px | Section gaps, module margins |
| 20px | Large padding (header/footer, modals) |
| 24px | Major section separation |
| 32px | Hero/CTA padding |
Border Radius
| Value | Use |
|---|
| 0 | Progress bar fills, sharp edges |
| 2px | Loading bar, scrollbar thumb |
| 3px | Buttons, badges, small controls |
| 4px | Cards, modules, panels, toasts, inputs |
| 6px | Modals, large containers |
| 50% | LEDs and circular indicators only |
Rule: Never exceed 6px on rectangular containers. Exception: CRT bezel (10-20px) for the oscilloscope display only.
Animation Timing
| Duration | Easing | Use |
|---|
| 0.15s | ease | Hover/focus states, color transitions |
| 0.2s | ease | Tab transitions, button interactions |
| 0.25s | ease-out | Toast slide-in, panel reveals |
| 0.3s | ease | Sidebar open/close |
| 1-1.5s | ease-in-out | Loading dots, progress bar, LED pulse |
| 2-3s | ease-in-out | Ambient pulse (workflow-launch glyph, decorative) |
Dead zone: Avoid durations between 0.3s and 1s. Nothing should feel "not quite snappy, not quite ambient."
Component Patterns
Module Panel
Structure: .module > .module-header + .module-screen
- Header:
--bezel-dark bg, 10px uppercase Inter label, optional .module-badge and .count-badge
- Screen:
--bg-screen with dual-scale grid background (10px + 50px lines)
- Reference:
modules.css
Stat Card
7-column grid (responsive to 4/3/2). Each card:
--bg-screen with grid overlay, 4px radius, 14px 16px padding
.stat-value: 28px mono bold, phosphor glow text-shadow: 0 0 10px var(--primary-glow)
.stat-label: 9px Inter uppercase
- Color via
data-status attribute
- Reference:
modules.css
Task/Process Row
- Left border: 3px solid status color (amber=todo, cyan=active, green=done, red=error)
border-radius: 0 3px 3px 0 (flat left edge for border accent)
- 10px 12px padding, 11px font
- Hover:
--primary-08 background
- Reference:
modules.css, processes.css
Buttons
Three sizes, all mono font, uppercase, letter-spacing 0.05em:
| Class | Padding | Font | Use |
|---|
.ctrl-btn | 10px 14px | 11px/600 | Standard actions |
.ctrl-btn-sm | 8px 10px | 10px/600 | Compact actions |
.ctrl-btn-xs | 3px 8px | 9px/600 | Micro actions |
Variants: .danger (error border/color), .primary (primary bg emphasis)
Hover: --bezel-light bg. Active: translateY(1px) pressed effect.
Reference: modules.css, layout.css
LED Indicator
- 8px circle,
border-radius: 50%
- Active: colored fill +
box-shadow: 0 0 8px glow
- Off:
#333 fill, no shadow
.pulse: 2s ease-in-out infinite opacity animation
- Reference:
layout.css
Toast Notification
- Fixed top-right, slide-in from right (0.25s ease-out)
--bg-panel background, 1px solid --bezel-edge border
- Left border: 3px solid, colored by
data-type (error=red, success=green, etc.)
- 11px mono text
- Reference:
base.css
Modal
- Overlay:
rgba(0,0,0,0.8)
- Container:
--bg-panel, 6px radius, 1px solid --bezel-edge
- Header:
--bezel-dark bg, 14px 18px padding
- Standard: max-width 600px. Detail: max-width 900px.
- Reference:
modal.css
Layout
Reference: layout.css, responsive.css
Page grid: .main-layout = CSS Grid, 280px sidebar + 1fr content
Header: --bezel-dark bg, 60px height, flex layout
Footer: --bezel-dark bg, 36px height, 10px text
Responsive breakpoints:
- 1200px: sidebar narrows to 260px, stat grid 4-col
- 900px: sidebar hides (hamburger toggle), stat grid 3-col, stack layouts
- 600px: stat grid 2-col, hide labels (LEDs only), compact padding
Anti-Patterns
- No bright white backgrounds — even "Clean White" preset uses dark backgrounds
- No border-radius > 6px on panels, cards, or modules (CRT bezel is the only exception)
- No sans-serif for data — JetBrains Mono for values/code/labels; Inter only for descriptions
- No raw color values — always use CSS custom properties from theme.css
- No hardcoded rgba — use opacity variants (
--primary-15) not inline rgba(232,160,48,0.15)
- No scale() on hover — use
translateY(-1px) max for buttons; scale only for ambient animations
- No ungridded screen areas — module screens use the dual-scale grid background
- No missing phosphor glow — stat values and key status text need
text-shadow: 0 0 10px var(--*-glow)
- No 0.3-1s animation timing — use either micro (0.15-0.3s) or ambient (1-3s)
- No legacy aliases in new code — use
--color-primary not --phosphor-amber, --primary-10 not --amber-10
Theme Compatibility
- Use semantic variables (
--color-primary, --color-success) not preset-specific values
- Use RGB component vars (
--color-primary-rgb) when building custom opacity: rgb(var(--color-primary-rgb) / 0.15)
- Test in at least amber (default) and one monochrome preset (green or cyan)
- "Clean White" is NOT a light theme — it still has dark backgrounds
- Monochrome presets (amber, green, cyan, blue, purple) map most colors to the primary hue — secondary, tertiary, error, warning all collapse to shades of the primary
Checklist
Before submitting UI work, verify: