# Design System Migration Plan — Nexus UI → DESIGN.md (ClickHouse-inspired) Status: **DRAFT, awaiting review**. Do not touch UI files until this is approved. --- ## 1. Executive summary Migrate the Nexus UI from its current Tailwind v4 + Catppuccin (Mocha/Latte) + Tokyo Night setup to the new DESIGN.md aesthetic: **pure black canvas, Neon Volt (`#faff69`) as the sole chromatic accent, Forest Green (`#166534`) as secondary CTA, Inter/Basier/Inconsolata typography, sharp geometry, border-based depth**. **Scope in numbers (from codebase scan):** | Category | Count | How it migrates | |---|---|---| | CSS variables in `index.css` | 29 × 3 selectors | Rewrite `@theme inline` block (single file edit) | | Tailwind theme-token classes (`bg-background`, `text-muted-foreground`, `border-border`, …) | ~1,250 instances | Auto-migrate when CSS vars change — zero source edits | | Raw palette utilities (`bg-red-500`, `text-amber-600`, …) | ~274 instances across ~60 files | Manual remap to semantic tokens — per-file work | | Hardcoded hex fallbacks in TSX (e.g., `#6366f1`, `#64748b`) | ~65 files | Find-and-replace with token refs | | Status / priority / agent-role color maps (`lib/status-colors.ts`, `lib/agent-role-colors.ts`) | ~45 definitions | Rewrite against new palette | | hljs syntax highlighting blocks in `index.css` | 3 theme blocks (Mocha, Tokyo, Latte) | Delete, write one block matching DESIGN.md | | Theme switching machinery (`ThemeContext.tsx`, `Layout.tsx` toggle) | 2 files | Simplify — drop Catppuccin/Tokyo cycle, keep light/dark binary | | Font loading (Inter/Basier/Inconsolata) | 0 currently | Add font-face declarations (or CDN) — new work | **Effort estimate:** One careful pass, with the bulk of the mechanical work concentrated in ~3 files (`index.css`, `lib/status-colors.ts`, `lib/agent-role-colors.ts`) and a long tail in the ~60 files using raw palette utilities. The hardcoded hex cleanup is mostly in fallback expressions and is trivial once the token semantics are agreed. **Key design decisions the user must make before Phase 1:** 1. **Light mode strategy.** DESIGN.md explicitly says "no light/white backgrounds anywhere." I've drafted a light mode anyway (Section 5), but I'd like confirmation on the direction — or explicit permission to drop light mode entirely. 2. **Neon Volt on white is unreadable.** In light mode, volt either gets reserved for border/active states (primary chromatic accent rotates to Forest Green) or we pick a darker neon-adjacent hue. See Section 5. 3. **Tokyo Night removal.** The `.theme-tokyo-night.dark` selector is defined in CSS but never applied by the current ThemeContext (dead code). I propose deleting it — confirm. 4. **Font pipeline.** Inter/Basier/Inconsolata are not currently loaded. Options: Google Fonts CDN, self-hosted woff2, or `@fontsource` npm packages. I'd suggest self-hosted woff2 for LAN/offline reliability, but that's 6–10 MB of fonts in `public/`. Confirm preference. 5. **Font weight 900 for display.** DESIGN.md calls this out as core to the identity. Current Nexus has no 96px+ display type. Adopt for hero/landing moments or skip? --- ## 2. Current state vs. DESIGN.md (side by side) ### Color philosophy | Dimension | Current (Catppuccin Mocha) | Current (Tokyo Night) | DESIGN.md (ClickHouse) | |---|---|---|---| | Background | `#1e1e2e` (dark purple-gray) | `#1a1b26` (dark blue-gray) | `#000000` (pure black) | | Card | `#181825` | `#16161e` | `#141414` or transparent | | Primary | `#89b4fa` (blue) | `#7aa2f7` (blue) | `#faff69` (acid yellow-green) | | Destructive | `#f38ba8` (pink) | `#f7768e` (pink) | TBD — DESIGN.md omits red | | Border | `#313244` | `#24283b` | `rgba(65,65,65,0.8)` (charcoal) | | Accent scale | Smooth pastels | Smooth blues | Binary: volt or green, nothing else | | Overall vibe | Cozy, muted, rounded | Cozy, muted, rounded | Cockpit, sharp, maximum contrast | ### Typography | Role | Current | DESIGN.md | |---|---|---| | Font family | System stack (no explicit loads — Tailwind default) | Inter + Basier + Inconsolata | | Display weight | Up to 700 at 24–36px | **900 at 72–96px** | | Body weight | 400 / 500 | 400 / 500 / 600 / 700 | | Labels | Mixed case | **Uppercase + 1.4px tracking** | | Code | Monospace (system) | Inconsolata 600 | ### Geometry | | Current | DESIGN.md | |---|---|---| | Radius scale | `sm:2px md:4px lg:0 xl:0` (already sharpish) | Sharp 4px / comfortable 8px / pill 9999px — nothing else | | Border style | Solid 1px | Solid 1px, charcoal `rgba(65,65,65,0.8)` — single workhorse color | | Shadow | Subtle layered shadows | Border-based depth + inset "pressed" effect | ### Interaction | | Current | DESIGN.md | |---|---|---| | Link hover | Muted highlight | **Volt (`#faff69`) — universal** | | Active text | Opacity change | **Pale Yellow (`#f4f692`)** | | Button hover | Subtle bg shift | BG shifts to `#3a3a3a`, text to volt/pale | --- ## 3. Token mapping — old vars → new vars (DARK mode) The migration is primarily a rewrite of the `@theme inline` block in `/opt/nexus/ui/src/index.css`. Token **names** stay the same (so the ~1,250 Tailwind utility classes auto-migrate); only values change. | Token | Current (Mocha) | New (DESIGN.md dark) | Notes | |---|---|---|---| | `--background` | `#1e1e2e` | `#000000` | Pure black, no compromise | | `--foreground` | `#cdd6f4` | `#ffffff` | Pure white | | `--card` | `#181825` | `#141414` | "Near Black" from DESIGN.md §2 | | `--card-foreground` | `#cdd6f4` | `#ffffff` | — | | `--popover` | `#181825` | `#141414` | Match card | | `--popover-foreground` | `#cdd6f4` | `#ffffff` | — | | `--primary` | `#89b4fa` (blue) | `#faff69` (**volt**) | The brand inversion — single biggest visual change | | `--primary-foreground` | `#1e1e2e` | `#151515` | Near-black text on volt | | `--secondary` | `#313244` | `#166534` (**forest**) | Secondary CTA becomes green | | `--secondary-foreground` | `#cdd6f4` | `#ffffff` | — | | `--muted` | `#313244` | `#141414` | Muted surfaces stay near-black | | `--muted-foreground` | `#a6adc8` | `#a0a0a0` (**silver**) | DESIGN.md §2 "Silver" | | `--accent` | `#45475a` | `#141414` | Accent surface = muted surface in this system | | `--accent-foreground` | `#cdd6f4` | `#faff69` | Text on accent surfaces lights up volt | | `--destructive` | `#f38ba8` (pink) | `#ef4444` (muted red) | DESIGN.md doesn't specify — I picked a restrained red that doesn't compete with volt. Confirm. | | `--destructive-foreground` | `#1e1e2e` | `#ffffff` | — | | `--border` | `#313244` | `rgba(65,65,65,0.8)` (**charcoal**) | Workhorse — DESIGN.md §2 | | `--input` | `#313244` | `#141414` | Input fields use near-black fill, charcoal border | | `--ring` | `#89b4fa` | `#faff69` | Focus ring is volt | | `--chart-1` | `#89b4fa` | `#faff69` | Primary chart series = volt | | `--chart-2` | `#a6e3a1` | `#166534` | Secondary = forest | | `--chart-3` | `#cba6f7` | `#a0a0a0` | Tertiary = silver | | `--chart-4` | `#f9e2af` | `#f4f692` (pale yellow) | Active/pressed accent | | `--chart-5` | `#f38ba8` | `#ef4444` | Destructive (if needed for alerts) | | `--sidebar` | `#181825` | `#000000` | Sidebar = pure black, no surface differentiation | | `--sidebar-foreground` | `#cdd6f4` | `#a0a0a0` | Secondary silver — nav items dim, active is volt | | `--sidebar-primary` | `#89b4fa` | `#faff69` | — | | `--sidebar-primary-foreground` | `#1e1e2e` | `#151515` | — | | `--sidebar-accent` | `#313244` | `#141414` | — | | `--sidebar-accent-foreground` | `#cdd6f4` | `#ffffff` | — | | `--sidebar-border` | `#313244` | `rgba(65,65,65,0.8)` | — | | `--sidebar-ring` | `#89b4fa` | `#faff69` | — | **New tokens to add** (not in current system but needed for DESIGN.md fidelity): | New token | Value | Purpose | |---|---|---| | `--volt` | `#faff69` | Direct brand-accent reference (for code that needs the literal brand color, e.g. logo, chart emphasis) | | `--volt-pale` | `#f4f692` | Active/pressed text color per DESIGN.md §2 | | `--volt-border` | `#4f5100` | Dark olive ghost-button borders per DESIGN.md §2 | | `--forest` | `#166534` | Direct secondary-CTA reference | | `--forest-dark` | `#14572f` | Darker forest for border variant | | `--near-black` | `#141414` | Button backgrounds, elevated dark surfaces | | `--hover-gray` | `#3a3a3a` | Button hover background | | `--silver` | `#a0a0a0` | Secondary/muted text | | `--charcoal-border` | `rgba(65,65,65,0.8)` | Signature border | | `--charcoal-divider` | `#343434` | Subtler division | ### Radius DESIGN.md is strict: 4px, 8px, 9999px. Current `--radius-*` tokens are already close — audit and lock: | Token | Current | New | Notes | |---|---|---|---| | `--radius-sm` | `2px` | `4px` | Bump to 4 (DESIGN.md "sharp") | | `--radius-md` | `4px` | `4px` | Keep | | `--radius-lg` | `0px` | `8px` | DESIGN.md "comfortable" for cards | | `--radius-xl` | `0px` | `8px` | Alias to lg; audit xl usage and collapse | | `--radius-full` | `9999px` | `9999px` | Pill unchanged | **Audit task:** grep for `rounded-xl`, `rounded-2xl`, `rounded-3xl` — these violate the DESIGN.md scale and need to come down. --- ## 4. Typography migration ### Font loading Currently: no explicit font loads — Tailwind falls back to system stack. Proposed: self-hosted woff2 via `@font-face` in `index.css`, dropped into `ui/public/fonts/`. Rationale: LAN testing without internet; Nexus is meant to run offline-capable. ```css @font-face { font-family: "Inter"; src: url("/fonts/Inter-VariableFont_slnt,wght.woff2") format("woff2-variations"); font-weight: 100 900; font-display: swap; } @font-face { font-family: "Inconsolata"; src: url("/fonts/Inconsolata-VariableFont_wdth,wght.woff2") format("woff2-variations"); font-weight: 100 900; font-display: swap; } /* Basier: not free — likely fallback to Inter for feature headings, or purchase license */ ``` **Decision needed:** Basier is a paid font. Either: - (A) License Basier (one-time cost) — true to DESIGN.md - (B) Use Inter for both display and feature headings (skip Basier entirely) — simpler, free - (C) Sub in a free alternative (Manrope, Space Grotesk, Archivo) with similar character I recommend **(B)** for the migration — DESIGN.md's Inter/Basier split is subtle and the rest of the aesthetic carries the identity. Can upgrade to real Basier later. ### @theme additions ```css @theme inline { --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif; --font-mono: "Inconsolata", ui-monospace, "Courier New", monospace; --font-display: "Inter", ui-sans-serif, system-ui, sans-serif; /* weight 900 usage */ } ``` ### Tracking / weights Audit component library (shadcn-like `components/ui/`) for heading weights and letter-spacing. Specifically: - Button text: 600–700 weight - Section overlines: uppercase + `tracking-[0.1em]` (≈ 1.4px at 14px font) - Display heading: `text-6xl md:text-8xl font-black` (96px at weight 900) --- ## 5. Light mode derivation DESIGN.md is dark-only by policy ("Don't use light/white backgrounds anywhere"). But the user explicitly asked for a light mode. I propose treating light mode as a **legibility alternative**, not a brand statement — it preserves accessibility without claiming design parity with the dark mode. ### Design principles for the light variant 1. **Neon Volt is downranked.** On white, `#faff69` is invisible. In light mode, volt is reserved for **border highlights and active states** — never backgrounds, never text. The primary chromatic accent rotates to **Forest Green (`#166534`)**, which DESIGN.md already treats as a primary CTA color. 2. **Canvas is near-white, not pure white.** Pure `#ffffff` is harsh; `#fafafa` gives the eye something to hold. Matches "paper on desk" affordance. 3. **Charcoal inverts to silver.** Border/divider workhorse becomes `rgba(20,20,20,0.12)` — faint, functional, same role. 4. **Text hierarchy inverts.** Primary text `#0a0a0a`, secondary `#6b6b6b` (a light-mode counterpart to DESIGN.md's Silver `#a0a0a0`). 5. **Sharp geometry stays.** Radius, fonts, weights, borders — identical. Only hue flips. ### Light mode token values | Token | Value | Rationale | |---|---|---| | `--background` | `#fafafa` | Near-white canvas | | `--foreground` | `#0a0a0a` | Near-black text | | `--card` | `#ffffff` | Pure white cards sit above canvas | | `--card-foreground` | `#0a0a0a` | — | | `--popover` | `#ffffff` | — | | `--popover-foreground` | `#0a0a0a` | — | | `--primary` | `#166534` (**forest**) | In light mode, the CTA accent is forest green — volt is too unreadable | | `--primary-foreground` | `#ffffff` | White on forest | | `--secondary` | `#f1f5f1` | Very pale forest tint for secondary surfaces | | `--secondary-foreground` | `#0a0a0a` | — | | `--muted` | `#f4f4f5` | Pale gray for muted surfaces | | `--muted-foreground` | `#6b6b6b` | "Light silver" — readable but clearly subordinate | | `--accent` | `#fafff0` | Very faint volt tint for highlighted surfaces | | `--accent-foreground` | `#4f5100` | Dark olive text (volt-family) on the pale volt surface | | `--destructive` | `#dc2626` | Readable red on white | | `--destructive-foreground` | `#ffffff` | — | | `--border` | `rgba(20,20,20,0.12)` | Inverted charcoal — workhorse | | `--input` | `#ffffff` | — | | `--ring` | `#166534` | Focus ring matches primary (forest) | | `--volt` | `#4f5100` | **In light mode, `--volt` resolves to the dark olive** (DESIGN.md's "Border Olive") so any component that references it directly stays readable | | `--volt-pale` | `#8a8c00` | Mid-tone olive for active states | | `--volt-border` | `#4f5100` | Same as current DESIGN.md spec | | `--forest` | `#166534` | Unchanged — forest reads on both backgrounds | | `--forest-dark` | `#14572f` | Unchanged | | `--near-black` | `#0a0a0a` | Repurposed as the darkest text color | | `--hover-gray` | `#e4e4e7` | Light hover background | | `--silver` | `#6b6b6b` | Darker silver for light-mode legibility | | `--charcoal-border` | `rgba(20,20,20,0.12)` | Inverted | | `--charcoal-divider` | `rgba(20,20,20,0.08)` | Even fainter | | `--sidebar` | `#ffffff` | — | | `--sidebar-foreground` | `#6b6b6b` | Muted nav labels | | `--sidebar-primary` | `#166534` | Active nav = forest | | `--sidebar-primary-foreground` | `#ffffff` | — | | `--sidebar-accent` | `#f4f4f5` | Hover bg | | `--sidebar-accent-foreground` | `#0a0a0a` | — | | `--sidebar-border` | `rgba(20,20,20,0.12)` | — | | `--sidebar-ring` | `#166534` | — | ### Trade-offs of this approach - **Pro:** Preserves DESIGN.md's dual-accent system (volt + forest) by promoting forest when volt can't perform. - **Pro:** Sharp geometry and charcoal border identity carry across modes. - **Con:** Light mode is objectively weaker brand-wise than dark — the neon-on-black drama is gone. - **Con:** Components that rely on volt as their primary affordance (e.g., "click me, I'm the CTA") look different in light mode. - **Con:** If Nexus is meant to be a cockpit, a light mode fundamentally undermines the atmosphere. The honest answer might be: don't ship a light mode. **User decision required:** do I ship this light mode, drop light mode entirely, or iterate on the palette? --- ## 6. Raw Tailwind color utility remapping The scan found **~274 instances** of raw color utilities (`bg-red-500`, `text-amber-600`, etc.) that bypass the theme-token system. These need manual remapping. ### Semantic categories and their new homes | Use case | Current classes | New strategy | |---|---|---| | **Error / destructive** (`bg-red-*`, `text-red-*`) | 74 instances | → `bg-destructive`, `text-destructive` (theme tokens) | | **Warning / pending** (`bg-amber-*`, `text-amber-*`, `bg-yellow-*`) | 70 instances | → New token `--warning` (proposed: `#f59e0b` dark, `#b45309` light), then `bg-warning`, `text-warning` | | **Success / completed** (`bg-green-*`, `text-green-*`, `bg-emerald-*`) | 34 instances | → New token `--success` = `#166534` (matches forest); `bg-success` | | **Info / in-progress** (`bg-blue-*`, `text-blue-*`, `bg-cyan-*`, `bg-sky-*`) | 63 instances | → `text-muted-foreground` or a new `--info` token = `#a0a0a0` (silver) in dark mode | | **Role / agent hues** (violet, pink, teal, orange, indigo, rose) | ~14 instances | **These are the hardest**. In DESIGN.md's palette, everything non-volt/non-forest is neutral. Options: (a) collapse all role colors into silver/volt/forest variations, losing per-role distinction; (b) introduce a small "chart palette" of low-saturation grays and use pattern/icon differentiation instead of hue; (c) keep a small named-role palette as an exception. I lean toward **(a)** — use volt for the primary role, silver for the rest, rely on labels/icons for identity. | | **Status/neutral** (`bg-neutral-*`, `bg-zinc-*`, `bg-slate-*`, `bg-gray-*`) | 24 instances | → `bg-muted`, `text-muted-foreground` | **Impact on `lib/status-colors.ts` and `lib/agent-role-colors.ts`:** These files are the primary home for the ~100 palette mappings. They define the source-of-truth dictionaries that most raw-utility usage pulls from. Rewriting these two files gets us ~60% of the raw-utility work done. I'll draft the replacement dictionaries in Phase 2 (see Section 8) — that rewrite is the single biggest file-level change in the migration. --- ## 7. File-by-file scope ### Must change (foundation — Phase 1) | File | Lines of change | Why | |---|---|---| | `ui/src/index.css` | ~300 → ~250 (rewrite theme blocks, hljs, scrollbars) | All token values, all three theme variants → two modes, new hljs palette | | `ui/src/lib/status-colors.ts` | Full rewrite | ~30 status → color mappings need new palette | | `ui/src/lib/agent-role-colors.ts` | Full rewrite | ~15 role → color mappings | | `ui/src/context/ThemeContext.tsx` | Simplify | Drop `"custom"` theme type, drop Catppuccin/Tokyo cycle, keep light/dark binary | | `ui/src/components/Layout.tsx` | ~10 lines | Drop theme cycle map (lines 66–72), simplify toggle | ### Should change (sweep — Phase 2) Files with raw palette utilities, ordered by instance count (high-impact first). From the scan I'd need to enumerate these precisely in the execution phase, but the top offenders are predictable: - Any "status pill" / "priority badge" / "agent role avatar" component — where most of the 274 raw utilities live - `pages/OrgChart.tsx` — 6 hardcoded hex status colors + raw palette usage - `pages/Inbox.tsx` — `#64748b` fallback + raw classes - `pages/Routines.tsx` — `#64748b` fallback × 3 - `pages/CompanySettings.tsx`, `pages/ContentStudio.tsx` — brand color defaults - `components/NewIssueDialog.tsx` — `#6366f1` project color fallback × 2 - `components/MarkdownEditor.tsx` — `#64748b` fallback - `components/VoiceWaveform.tsx` — hardcoded `#89b4fa` (needs to become `var(--primary)` or `--volt`) - `components/ThemePreviewPanel.tsx` — 12 hardcoded hexes (this file IS the theme preview; needs full rewrite against new palette) - `components/ThemePaletteGrid.tsx` — Catppuccin green references **Complete file list to be produced during Phase 2 execution** via a precise `rg '(bg|text|border|ring)-(red|blue|green|amber|yellow|cyan|violet|pink|slate|zinc|neutral|sky|teal|emerald|indigo|rose|orange)-' ui/src` with per-file counts. ### May change (audit — Phase 3) - Typography usages: any `text-*xl`, `font-bold` etc. needing bump to `font-black` for display moments - Radius audits: `rounded-2xl`, `rounded-3xl` need to come down to `rounded-lg` (8px) or `rounded-sm` (4px) - Shadow audits: replace soft shadows with border-based elevation or inset "pressed" effects for active states ### Do NOT change - `.planning/`, `doc/`, `docs/`, test fixtures, snapshots - `packages/branding/` — has no colors, just vocabulary - Test files that assert current palette (note: `ThemePreviewPanel.test.tsx` has snapshot tests that will need updating, but snapshot updates are mechanical, not design work) --- ## 8. Migration sequence Ordered phases. Each phase is independently committable and reviewable. ### Phase 1 — Foundation (single commit) **What:** Rewrite `ui/src/index.css` `@theme` block and all three theme selectors. Load new fonts. Simplify `ThemeContext.tsx` + `Layout.tsx` theme cycle. **Goal:** After this phase, the app's ~1,250 theme-token class usages visually switch to the new palette with zero per-file edits. Raw utilities and hardcoded hexes will still look wrong — that's Phase 2. **Deliverables:** - New `ui/src/index.css` (rewritten theme blocks + font-face declarations) - Fonts in `ui/public/fonts/` (woff2 Inter + Inconsolata) - Simplified `ThemeContext.tsx` (binary light/dark, no Catppuccin/Tokyo) - Simplified `Layout.tsx` theme toggle button **Verification:** load any authenticated page, visually confirm black canvas + volt accents on borders and CTAs. Expect ugly patches where raw utilities still show their old colors — that's expected at this phase. ### Phase 2 — Status / role color rewrite (single commit) **What:** Rewrite `lib/status-colors.ts` and `lib/agent-role-colors.ts` against the new palette. This cleans up ~60% of the raw-utility usage because those two files are the source of truth for most status/priority/role dictionaries. **Deliverables:** - New color dictionaries - Any components that import from these files get their "wrongness" fixed automatically **Verification:** inbox, org chart, agent cards all show volt/forest/silver status indicators instead of red/blue/green. ### Phase 3 — Raw utility sweep (one commit per logical component group) **What:** Per-file cleanup of the remaining raw palette utilities and hardcoded hex fallbacks. Group by feature (dashboard, org chart, inbox, settings) so each commit is reviewable. **Deliverables:** - ~60 files touched, 274 utility instances replaced with theme tokens or new semantic tokens (`bg-warning`, `bg-success`, etc.) - ~65 hardcoded hex fallbacks replaced with `var(--token)` refs or `text-muted-foreground` equivalents **Verification:** grep for raw palette utilities — should be zero matches (or only well-justified exceptions). Visual regression via manual QA of each touched page. ### Phase 4 — Typography + radius audit (single commit) **What:** Bump heading weights to 900 for display moments, enforce radius scale (4px/8px/9999px only), replace soft shadows with border-based depth. **Deliverables:** - Hero/landing pages use display typography - `rounded-2xl`/`rounded-3xl` collapsed to `rounded-lg` or `rounded-sm` - Soft `shadow-md`/`shadow-lg` replaced with `border` + inset shadows for active states **Verification:** visual compliance with DESIGN.md §3-§6 on representative pages. ### Phase 5 — ThemePreviewPanel rewrite (single commit) **What:** The theme preview / palette grid components currently showcase Catppuccin. They need a complete rewrite to preview the new system. **Deliverables:** - `ThemePreviewPanel.tsx` showing new palette - `ThemePaletteGrid.tsx` or deprecation (if the grid no longer makes sense in a binary-mode system) ### Phase 6 — hljs syntax highlighting (single commit) **What:** Replace the three Catppuccin/Tokyo hljs rule sets in `index.css` with a single DESIGN.md-compliant rule set: neon and white on dark, terminal aesthetic per §4. **Deliverables:** - `.hljs-*` rules rewritten in `index.css` - Light mode hljs variant derived ### Phase 7 — Visual QA pass **What:** Walk every top-level route, compare against DESIGN.md principles, capture screenshots for before/after, file any remaining issues. No code changes unless issues found. --- ## 8b. Structural overhaul phases (8–16) — see layout spec Phases 1–7 above are a **visual repaint** of the existing structure. They do not change layout, navigation, information architecture, or what each page does. A separate, larger overhaul to the layout and IA was approved 2026-04-11 and is captured in **`docs/specs/2026-04-11-nexus-layout-overhaul.md`**. That spec defines phases 8–16, summarized here: | Phase | Title | Wave | |---|---|---| | 8 | Frame skeleton (56px icon rail, 48px top strip, kill ChatPanel/PropertiesPanel/sidebar) | 1 (alone, foundational) | | 9 | Assistant mode (full-bleed chat at `/assistant`, History/Memory slide-overs, conversational home state) | 2 (parallel) | | 10 | Studio mode (8-card workshop grid, fold ConvertPage in, freeform prompt) | 2 (parallel) | | 11 | Projects + Builder mode (hero-stat cards, 7-tab Builder strip, demote 9 global routes to per-project tabs) | 2 (parallel) | | 12 | Promote-to-project transition (700ms compress + rise animation with inset shadow ripple) | 3 (parallel) | | 13 | Settings consolidation (single-column, Skills + Routines sections, drop nested settings routes) | 3 (parallel) | | 14 | Voice + ⌘K globalization (mic in top header, voice queues to Assistant inbox, universal command palette) | 3 (parallel) | | 15 | Mobile parity (bottom tab bar, project sub-tab strip, mobile takeovers for slide-overs) | 3 (parallel) | | 16 | Cleanup pass (vocabulary sweep, dead-code removal, visual QA) | 4 (alone, sequential) | The dispatch pattern for phases 8–16 is documented in §11 below. **Phases 1–7 are independent of phases 8–16 and can ship first.** The overhaul does not block visual QA — and conversely, the visual repaint produces tokens that the overhaul phases consume. Phases 8–16 should not begin until phase 4 (typography + radius audit) is at minimum committed, because the new frame relies on the locked-in radius scale and font weights. --- ## 9. Risks and decisions ### Decisions required from you before Phase 1 1. **Light mode**: ship the derived palette (Section 5), drop it entirely, or iterate on my draft? 2. **Basier font**: license it, use Inter everywhere, or pick a free alternative? 3. **Destructive color**: DESIGN.md doesn't specify a red. I propose `#ef4444` (muted). Confirm or pick. 4. **Role hue collapse vs. preserve**: for agent roles / chart series, do we accept a silver-only palette with pattern differentiation, or keep a small named-role palette as a controlled exception? 5. **Display weight 900**: adopt for hero/landing moments, or skip the 96px Inter Black treatment? 6. **Theme toggle UX**: if we drop Tokyo Night, is the toggle still light ↔ dark, or do we simplify further (e.g., single dark mode, light is an accessibility fallback only)? 7. **Tokyo Night removal**: the `.theme-tokyo-night.dark` block in `index.css` is dead code (never applied by ThemeContext). Confirm I should delete it. ### Risks - **Visual regression**: ~1,250 token-using elements will all shift on Phase 1. Expect surprise — Catppuccin is cozy and Nexus users may not be ready for cockpit-level contrast. Worth previewing on a throwaway branch. - **Accessibility**: volt on black (`#faff69` on `#000000`) passes WCAG AAA for normal text, but volt on white fails for anything smaller than 18pt. That's why light mode downranks volt. - **Chart/viz readability**: with only 5 semantic chart colors (volt, forest, silver, pale, red), multi-series visualizations get crowded. Consider using the same hue with pattern/opacity differentiation, or accepting the "chart palette" as a documented exception. - **Catppuccin Mocha nostalgia**: if anyone on the team is attached to the Mocha look, DESIGN.md's aesthetic is going to feel jarring. Socialize early. - **Component-library components** (`components/ui/*`): these are shadcn-ish primitives. They use theme tokens heavily, which is good — they'll auto-migrate. But any that hardcode radius or shadow styles need individual audit. - **Onboarding wizard + InviteLanding**: just-touched files using the current palette. They'll shift visually in Phase 1 — worth a dedicated visual review since they're the first thing a new user sees. - **Font loading flash**: adding web fonts for the first time introduces FOUT/FOIT. Use `font-display: swap` and preload the most critical weights (Inter 400, 700, 900). ### Out of scope (for this migration) - Custom user themes (the current `"custom"` theme type is seldom used; I propose dropping it) - Per-company branding overrides (covered by separate `worktree-branding.ts` system — untouched) - Print styles - High-contrast accessibility mode beyond normal WCAG --- ## 10. Open questions for the user Answer these and I'll kick off Phase 1: 1. Light mode: **ship / drop / iterate**? 2. Fonts: **license Basier / Inter only / free alternative (name one)**? 3. Destructive red: **`#ef4444` / other (specify)**? 4. Role hues: **collapse to silver / keep small named palette / something else**? 5. Display 900: **adopt / skip**? 6. Theme toggle: **binary light/dark / dark only**? 7. Tokyo Night dead code: **delete / keep as future option**? Once answered, I'll update this file with the resolved decisions and begin Phase 1 on a separate branch. --- ## 11. Subagent dispatch pattern (binding for phases 8–16) **Directive from user 2026-04-11:** structural overhaul phases (8–16) MUST be implemented by dispatching subagents in parallel for any work that does not share files. Sequential implementation is wrong for work of this size. The implementation plan derived from `docs/specs/2026-04-11-nexus-layout-overhaul.md` will spell out the dispatch waves; this section is the standing rule. **Pattern:** 1. **Read the spec** before each wave. The spec (`docs/specs/2026-04-11-nexus-layout-overhaul.md`) is the source of truth for what to build. Don't infer from the code. 2. **Group phases into waves** based on file overlap. Phases that touch disjoint files run in parallel. Phases that share files (or where one builds on another's output) run sequentially. 3. **Dispatch one subagent per phase per wave**, in a single message with multiple Agent tool calls. Each subagent gets: - The phase number and title - The relevant section(s) of the spec verbatim - The specific files it owns (so two subagents in the same wave never touch the same file) - The atomic-commit requirement (one phase = one commit) 4. **After each wave**, verify all subagents committed cleanly before dispatching the next wave. If a wave produces conflicts on any file outside its declared ownership, stop and re-plan. 5. **Use the `superpowers:dispatching-parallel-agents` skill** for the actual dispatch. The skill enforces the message structure for parallel tool calls. **Anti-patterns explicitly forbidden by the user:** - Doing phases 8–16 sequentially in the main session - Doing one phase yourself "to get started" and then dispatching the rest - Dispatching subagents for phases that share files (will produce merge chaos) - Using subagents for phase 16 cleanup (sequential by design — touches everything) **Wave structure for the layout overhaul:** ``` Wave 1: [ Phase 8 ] # foundational, alone Wave 2: [ Phase 9 | Phase 10 | Phase 11 ] # 3 subagents, parallel Wave 3: [ Phase 12 | Phase 13 | Phase 14 | Phase 15 ] # 4 subagents, parallel Wave 4: [ Phase 16 ] # sequential cleanup, alone ``` This is captured here in MIGRATION-PLAN.md (rather than only in the spec) so that any future session opening this branch finds the directive even if it doesn't read the spec.