From e2a0bc68726c1b8dca179ee1f6826b88d8dd09f5 Mon Sep 17 00:00:00 2001 From: Clawd Date: Sat, 28 Feb 2026 18:46:20 -0800 Subject: Remove accidentally created .claude-flow/ directory --- .claude-flow/plan.md | 1090 -------------------------------------------------- 1 file changed, 1090 deletions(-) delete mode 100644 .claude-flow/plan.md (limited to '.claude-flow/plan.md') diff --git a/.claude-flow/plan.md b/.claude-flow/plan.md deleted file mode 100644 index bbcae6a..0000000 --- a/.claude-flow/plan.md +++ /dev/null @@ -1,1090 +0,0 @@ -# Implementation Plan - -## Goal -Restyle the Claude Flow Electron app with: -1. Fix the window/tab title from "minimal" → "Claude Flow" -2. Add a "CLAUDE FLOW" wordmark to the header -3. Apply a cipherpunk aesthetic (full monospace UI font, sharper geometry, electric-blue accent, uppercase meta labels, focus glow) -4. Add light/dark mode with a text toggle (`[dark]` / `[light]`) persisted to `localStorage` - -## Approach -Five files touched in order of dependency. No new npm packages. The CSS rewrite is the biggest change; the JS/TSX changes are small and surgical. - -**Order of changes:** -1. `renderer/index.html` — title fix (trivial, isolated) -2. `renderer/src/styles/globals.css` — full restyle (all visual work) -3. `renderer/src/App.tsx` — add theme state, wire it down -4. `renderer/src/components/Header.tsx` — wordmark + toggle button -5. `renderer/src/components/DocumentPane.tsx` — dynamic CodeMirror theme - ---- - -## Changes - -### 1. Fix Window Title -**File:** `renderer/index.html` -**What:** Change `minimal` to `Claude Flow` on line 10. - -```html - -minimal - - -Claude Flow -``` - ---- - -### 2. Restyle the CSS -**File:** `renderer/src/styles/globals.css` -**What:** Complete replacement of the file. Key changes from the original: -- `:root` dark-mode accent updated to `#60a5fa` / `#93c5fd` -- `body` font-family changed to full monospace stack -- New `html[data-theme="light"]` block added after `:root` -- `border-radius` reduced to 2px on all interactive controls (4px on chat bubbles) -- `text-transform: uppercase; letter-spacing: 0.07em` added to all meta/chrome labels -- Focus glow (`box-shadow`) added on inputs and focused buttons -- New `.app-wordmark` class added -- New `.theme-toggle` class added -- All existing selectors preserved; only values changed - -```css -* { - box-sizing: border-box; - margin: 0; - padding: 0; -} - -/* ── Dark theme (default) ────────────────────────────────────── */ -:root { - --bg-primary: #1a1a1a; - --bg-secondary: #252525; - --bg-tertiary: #333; - --border: #444; - --text-primary: #e0e0e0; - --text-secondary: #888; - --accent: #60a5fa; /* electric blue — brighter than original #3b82f6 */ - --accent-hover: #93c5fd; - --success: #10b981; - --warning: #f59e0b; - --danger: #ef4444; -} - -/* ── Light theme overrides ───────────────────────────────────── */ -html[data-theme="light"] { - --bg-primary: #f4f4f2; - --bg-secondary: #e8e8e5; - --bg-tertiary: #d8d8d4; - --border: #b4b4b0; - --text-primary: #1a1a18; - --text-secondary: #5a5a56; - --accent: #2563eb; - --accent-hover: #1d4ed8; - --success: #059669; - --warning: #d97706; - --danger: #dc2626; -} - -/* ── Base ────────────────────────────────────────────────────── */ -body { - font-family: "SF Mono", "Cascadia Code", "JetBrains Mono", "Fira Code", - Monaco, "Courier New", monospace; - background: var(--bg-primary); - color: var(--text-primary); - overflow: hidden; - font-size: 13px; -} - -.app { - display: flex; - flex-direction: column; - height: 100vh; -} - -/* ── Header ──────────────────────────────────────────────────── */ -.header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 10px 16px; - background: var(--bg-secondary); - border-bottom: 1px solid var(--border); - -webkit-app-region: drag; -} - -.header-left, -.header-right { - display: flex; - align-items: center; - gap: 8px; - -webkit-app-region: no-drag; -} - -/* App wordmark */ -.app-wordmark { - font-size: 12px; - font-weight: 700; - letter-spacing: 0.15em; - text-transform: uppercase; - color: var(--text-primary); - padding-right: 12px; - border-right: 1px solid var(--border); - margin-right: 4px; - user-select: none; - white-space: nowrap; -} - -.header select, -.header button { - padding: 5px 10px; - background: var(--bg-tertiary); - border: 1px solid var(--border); - border-radius: 2px; - color: var(--text-primary); - cursor: pointer; - font-size: 12px; - font-family: inherit; -} - -.header button:hover { - background: var(--border); -} - -.header button.btn-delete { - background: transparent; - border: 1px solid var(--border); - padding: 5px 8px; - font-size: 13px; -} - -.header button.btn-delete:hover { - background: var(--danger); - border-color: var(--danger); -} - -/* Theme toggle */ -.theme-toggle { - font-size: 11px; - letter-spacing: 0.08em; - text-transform: lowercase; - opacity: 0.7; - transition: opacity 0.15s; -} - -.theme-toggle:hover { - opacity: 1; - background: var(--bg-tertiary) !important; -} - -/* Phase indicator */ -.phase-indicator { - display: flex; - gap: 4px; -} - -.phase-step { - padding: 3px 10px; - font-size: 11px; - letter-spacing: 0.07em; - text-transform: uppercase; - border-radius: 2px; - background: var(--bg-tertiary); - color: var(--text-secondary); -} - -.phase-step.active { - background: var(--accent); - color: white; -} - -.phase-step.complete { - background: var(--success); - color: white; -} - -/* ── Main Content ─────────────────────────────────────────────── */ -.main-content { - flex: 1; - display: flex; - overflow: hidden; -} - -/* ── Document Pane ───────────────────────────────────────────── */ -.document-pane { - flex: 1; - display: flex; - flex-direction: column; - border-right: 1px solid var(--border); - min-width: 0; - overflow: hidden; -} - -.document-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 7px 16px; - background: var(--bg-secondary); - border-bottom: 1px solid var(--border); - font-size: 11px; - letter-spacing: 0.07em; - text-transform: uppercase; - color: var(--text-secondary); -} - -.document-header button { - padding: 3px 8px; - background: var(--bg-tertiary); - border: 1px solid var(--border); - border-radius: 2px; - color: var(--text-primary); - cursor: pointer; - font-size: 11px; - font-family: inherit; - letter-spacing: 0.05em; -} - -.document-header button:hover { - background: var(--border); -} - -.document-content { - flex: 1; - overflow-y: auto; - padding: 24px; -} - -.document-content.editing { - font-family: inherit; - font-size: 13px; - line-height: 1.6; - background: var(--bg-primary); - border: none; - resize: none; - color: var(--text-primary); -} - -.codemirror-editor { - flex: 1; - overflow: hidden; - min-height: 0; -} - -.codemirror-editor .cm-editor { - height: 100%; - max-width: 100%; -} - -.codemirror-editor .cm-scroller { - overflow: auto !important; -} - -.codemirror-editor .cm-gutters { - background: var(--bg-secondary); - border-right: 1px solid var(--border); -} - -.document-content.rendered { - line-height: 1.7; -} - -.document-content.rendered h1 { - font-size: 22px; - margin: 24px 0 16px; - letter-spacing: -0.01em; -} -.document-content.rendered h2 { - font-size: 17px; - margin: 20px 0 12px; - color: var(--text-secondary); - text-transform: uppercase; - letter-spacing: 0.05em; -} -.document-content.rendered h3 { - font-size: 14px; - margin: 16px 0 8px; -} -.document-content.rendered p { - margin: 8px 0; - line-height: 1.6; -} -.document-content.rendered code { - background: var(--bg-tertiary); - padding: 2px 6px; - border-radius: 2px; - font-size: 12px; - font-family: inherit; -} -.document-content.rendered pre { - background: var(--bg-tertiary); - padding: 16px; - border-radius: 2px; - overflow-x: auto; - margin: 16px 0; -} -.document-content.rendered pre code { - background: none; - padding: 0; -} -.document-content.rendered ul, -.document-content.rendered ol { - margin: 12px 0; - padding-left: 24px; -} -.document-content.rendered li { - margin-bottom: 6px; - line-height: 1.5; -} -.document-content.rendered ul.contains-task-list { - list-style: none; - padding-left: 0; -} -.document-content.rendered li.task-list-item { - display: flex; - align-items: flex-start; - gap: 8px; -} -.document-content.rendered li.task-list-item input[type="checkbox"] { - margin-top: 4px; -} -.document-content.rendered table { - width: 100%; - border-collapse: collapse; - margin: 16px 0; - font-size: 12px; -} -.document-content.rendered th, -.document-content.rendered td { - padding: 8px 12px; - text-align: left; - border: 1px solid var(--border); -} -.document-content.rendered th { - background: var(--bg-tertiary); - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.06em; - font-size: 11px; -} -.document-content.rendered tr:nth-child(even) td { - background: var(--bg-secondary); -} -.document-content.rendered blockquote { - border-left: 3px solid var(--accent); - margin: 16px 0; - padding-left: 16px; - color: var(--text-secondary); -} -.document-content.rendered hr { - border: none; - border-top: 1px solid var(--border); - margin: 24px 0; -} -.document-content.rendered a { - color: var(--accent); - text-decoration: none; -} -.document-content.rendered a:hover { - text-decoration: underline; -} -.document-content.rendered .empty { - color: var(--text-secondary); - font-style: italic; -} - -.badge { - background: var(--accent); - color: white; - padding: 2px 8px; - border-radius: 2px; - font-size: 10px; - letter-spacing: 0.08em; - text-transform: uppercase; -} - -/* ── Chat Pane ───────────────────────────────────────────────── */ -.chat-pane { - width: 380px; - display: flex; - flex-direction: column; - background: var(--bg-secondary); -} - -.chat-messages { - flex: 1; - overflow-y: auto; - padding: 16px; -} - -.message { - margin-bottom: 10px; - padding: 9px 13px; - border-radius: 4px; - max-width: 90%; - font-size: 13px; - line-height: 1.5; - white-space: pre-wrap; -} - -.message.user { - background: var(--accent); - margin-left: auto; - color: white; -} - -.message.assistant { - background: var(--bg-tertiary); -} - -.message.loading { - color: var(--text-secondary); - font-style: italic; -} - -.chat-input { - display: flex; - gap: 8px; - padding: 12px; - border-top: 1px solid var(--border); -} - -.chat-input input { - flex: 1; - padding: 9px 13px; - background: var(--bg-tertiary); - border: 1px solid var(--border); - border-radius: 2px; - color: var(--text-primary); - font-size: 13px; - font-family: inherit; - transition: border-color 0.15s, box-shadow 0.15s; -} - -.chat-input input:focus { - outline: none; - border-color: var(--accent); - box-shadow: 0 0 0 2px rgba(96, 165, 250, 0.2); -} - -html[data-theme="light"] .chat-input input:focus { - box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.2); -} - -.chat-input button { - padding: 9px 15px; - background: var(--accent); - border: none; - border-radius: 2px; - color: white; - cursor: pointer; - font-size: 12px; - font-family: inherit; - letter-spacing: 0.05em; - text-transform: uppercase; - transition: background 0.15s; -} - -.chat-input button:hover:not(:disabled) { - background: var(--accent-hover); -} - -.chat-input button:disabled { - opacity: 0.4; - cursor: not-allowed; -} - -/* ── Action Bar ──────────────────────────────────────────────── */ -.action-bar { - display: flex; - justify-content: space-between; - align-items: center; - padding: 10px 16px; - background: var(--bg-secondary); - border-top: 1px solid var(--border); -} - -.action-bar-left, -.action-bar-right { - display: flex; - align-items: center; - gap: 16px; -} - -.token-indicator { - display: flex; - align-items: center; - gap: 8px; -} - -.token-bar { - width: 100px; - height: 4px; - background: var(--bg-tertiary); - border-radius: 1px; - overflow: hidden; -} - -.token-fill { - height: 100%; - transition: width 0.3s ease; -} - -.token-label { - font-size: 10px; - letter-spacing: 0.08em; - text-transform: uppercase; - color: var(--text-secondary); -} - -.permission-toggle { - display: flex; - align-items: center; - gap: 6px; - font-size: 11px; - letter-spacing: 0.05em; - text-transform: uppercase; - color: var(--text-secondary); - cursor: pointer; -} - -.permission-toggle input { - cursor: pointer; -} - -.btn-secondary { - padding: 6px 14px; - background: var(--bg-tertiary); - border: 1px solid var(--border); - border-radius: 2px; - color: var(--text-primary); - cursor: pointer; - font-size: 12px; - font-family: inherit; - letter-spacing: 0.05em; - transition: background 0.15s; -} - -.btn-secondary:hover:not(:disabled) { - background: var(--border); -} - -.btn-secondary:disabled { - opacity: 0.4; - cursor: not-allowed; -} - -.btn-primary { - padding: 6px 18px; - background: var(--accent); - border: none; - border-radius: 2px; - color: white; - cursor: pointer; - font-weight: 600; - font-size: 12px; - font-family: inherit; - letter-spacing: 0.07em; - text-transform: uppercase; - transition: background 0.15s; -} - -.btn-primary:hover:not(:disabled) { - background: var(--accent-hover); -} - -.btn-primary:disabled { - opacity: 0.4; - cursor: not-allowed; -} - -.implementing-status { - color: var(--success); - font-size: 11px; - letter-spacing: 0.1em; - text-transform: uppercase; -} - -/* ── Error Bar ───────────────────────────────────────────────── */ -.error-bar { - display: flex; - justify-content: space-between; - align-items: center; - padding: 8px 16px; - background: var(--danger); - color: white; - font-size: 12px; - letter-spacing: 0.03em; -} - -.error-bar button { - background: none; - border: none; - color: white; - font-size: 16px; - cursor: pointer; - padding: 0 4px; -} - -.error-bar button:hover { - opacity: 0.8; -} - -/* ── Onboarding ──────────────────────────────────────────────── */ -.onboarding h1 { - font-size: 24px; - margin-bottom: 8px; - letter-spacing: 0.05em; - text-transform: uppercase; -} - -.onboarding h2 { - font-size: 13px; - margin-top: 28px; - margin-bottom: 12px; - color: var(--accent); - text-transform: uppercase; - letter-spacing: 0.1em; -} - -.onboarding p { - margin: 12px 0; - line-height: 1.6; -} - -.onboarding ol { - margin: 12px 0 12px 24px; -} - -.onboarding li { - margin: 8px 0; - line-height: 1.5; -} - -.onboarding pre { - background: var(--bg-tertiary); - padding: 12px 16px; - border-radius: 2px; - margin: 12px 0; -} - -.onboarding code { - font-family: inherit; - font-size: 12px; -} - -.onboarding a { - color: var(--accent); - text-decoration: none; -} - -.onboarding a:hover { - text-decoration: underline; -} - -.onboarding-tip { - margin-top: 28px; - padding: 16px; - background: var(--bg-tertiary); - border-left: 3px solid var(--accent); - border-radius: 0 2px 2px 0; -} -``` - ---- - -### 3. Add Theme State to App -**File:** `renderer/src/App.tsx` -**What:** Three additions to the existing file — no existing logic is touched. - -**3a. Add `Theme` type and `theme` state** — insert after the existing imports, before the `App` function: - -```typescript -// Add this type alias near the top, alongside other local types if any, -// or just before the App function: -type Theme = "dark" | "light"; -``` - -**3b. Add `theme` state and side-effects** — insert inside `App()`, after the existing `useState` declarations (after `const [error, setError] = useState(null)`): - -```typescript -const [theme, setTheme] = useState( - () => (localStorage.getItem("cf-theme") as Theme) ?? "dark" -); - -// Keep document.documentElement in sync, and persist to localStorage -useEffect(() => { - document.documentElement.setAttribute("data-theme", theme); - localStorage.setItem("cf-theme", theme); -}, [theme]); - -const handleToggleTheme = () => - setTheme((t) => (t === "dark" ? "light" : "dark")); -``` - -**3c. Pass new props to `Header` and `DocumentPane`** — update the JSX inside the `return`: - -```tsx -// Header — add two new props: -
- -// DocumentPane — add one new prop: - -``` - ---- - -### 4. Update Header Component -**File:** `renderer/src/components/Header.tsx` -**What:** Add `theme` and `onToggleTheme` to the props interface, insert wordmark element, add toggle button. - -**Complete updated file:** - -```tsx -import React from "react"; -import type { Project, Session, Phase } from "../types"; - -type Theme = "dark" | "light"; - -interface HeaderProps { - projects: Project[]; - sessions: Session[]; - selectedProject: Project | null; - selectedSession: Session | null; - onSelectProject: (project: Project | null) => void; - onSelectSession: (session: Session | null) => void; - onCreateProject: () => void; - onCreateSession: () => void; - onDeleteProject?: (id: string) => void; - onDeleteSession?: (id: string) => void; - theme: Theme; - onToggleTheme: () => void; -} - -const phaseLabels: Record = { - research: "Research", - plan: "Plan", - implement: "Implement", -}; - -const phases: Phase[] = ["research", "plan", "implement"]; - -export function Header({ - projects, - sessions, - selectedProject, - selectedSession, - onSelectProject, - onSelectSession, - onCreateProject, - onCreateSession, - onDeleteProject, - onDeleteSession, - theme, - onToggleTheme, -}: HeaderProps) { - const handleDeleteProject = () => { - if (!selectedProject || !onDeleteProject) return; - if (confirm(`Delete project "${selectedProject.name}"? This cannot be undone.`)) { - onDeleteProject(selectedProject.id); - } - }; - - const handleDeleteSession = () => { - if (!selectedSession || !onDeleteSession) return; - if (confirm(`Delete session "${selectedSession.name}"? This cannot be undone.`)) { - onDeleteSession(selectedSession.id); - } - }; - - return ( -
-
- {/* ── Wordmark ── */} - Claude Flow - - - - {selectedProject && onDeleteProject && ( - - )} - - {selectedProject && ( - <> - - - {selectedSession && onDeleteSession && ( - - )} - - )} -
- -
- {selectedSession && ( -
- {phases.map((phase) => { - const phaseIndex = phases.indexOf(phase); - const currentIndex = phases.indexOf(selectedSession.phase); - const isComplete = phaseIndex < currentIndex; - const isActive = phase === selectedSession.phase; - - return ( - - {phaseLabels[phase]} - - ); - })} -
- )} - - {/* ── Theme toggle ── */} - -
-
- ); -} -``` - ---- - -### 5. Dynamic CodeMirror Theme in DocumentPane -**File:** `renderer/src/components/DocumentPane.tsx` -**What:** Three surgical changes to `MarkdownEditor` — add `theme` prop, update imports, update `useEffect`. - -**5a. Update imports** — add `syntaxHighlighting` and `defaultHighlightStyle` to the `@codemirror/language` import: - -```typescript -// BEFORE: -import { markdown } from "@codemirror/lang-markdown"; -import { languages } from "@codemirror/language-data"; - -// AFTER: -import { markdown } from "@codemirror/lang-markdown"; -import { languages } from "@codemirror/language-data"; -import { syntaxHighlighting, defaultHighlightStyle } from "@codemirror/language"; -``` - -**5b. Update `MarkdownEditor` props interface** — add `theme`: - -```typescript -// BEFORE: -function MarkdownEditor({ - content, - onChange, - disabled, -}: { - content: string; - onChange: (content: string) => void; - disabled: boolean; -}) - -// AFTER: -function MarkdownEditor({ - content, - onChange, - disabled, - theme, -}: { - content: string; - onChange: (content: string) => void; - disabled: boolean; - theme: "dark" | "light"; -}) -``` - -**5c. Update the `useEffect` inside `MarkdownEditor`** — swap the theme extension and add `theme` to the dependency array: - -```typescript -// BEFORE (inside useEffect): -extensions: [ - lineNumbers(), - highlightActiveLine(), - drawSelection(), - history(), - keymap.of([...defaultKeymap, ...historyKeymap]), - markdown({ codeLanguages: languages }), - oneDark, // ← hardcoded - updateListener, - EditorView.editable.of(!disabled), - EditorView.lineWrapping, - EditorView.theme({ ... }), -], -// dependency array: -}, [disabled]); - -// AFTER: -extensions: [ - lineNumbers(), - highlightActiveLine(), - drawSelection(), - history(), - keymap.of([...defaultKeymap, ...historyKeymap]), - markdown({ codeLanguages: languages }), - theme === "dark" ? oneDark : syntaxHighlighting(defaultHighlightStyle), // ← dynamic - updateListener, - EditorView.editable.of(!disabled), - EditorView.lineWrapping, - EditorView.theme({ ... }), -], -// dependency array: -}, [disabled, theme]); // ← theme added -``` - -**5d. Update `DocumentPaneProps` interface and pass `theme` through** — add to the interface and forward to `MarkdownEditor`: - -```typescript -// BEFORE: -interface DocumentPaneProps { - content: string; - onChange: (content: string) => void; - phase: Phase; - disabled: boolean; - showOnboarding?: boolean; -} - -// AFTER: -interface DocumentPaneProps { - content: string; - onChange: (content: string) => void; - phase: Phase; - disabled: boolean; - showOnboarding?: boolean; - theme: "dark" | "light"; -} -``` - -And in the `DocumentPane` function body, destructure `theme` and pass it to `MarkdownEditor`: - -```tsx -// BEFORE: -export function DocumentPane({ - content, - onChange, - phase, - disabled, - showOnboarding, -}: DocumentPaneProps) - -// AFTER: -export function DocumentPane({ - content, - onChange, - phase, - disabled, - showOnboarding, - theme, -}: DocumentPaneProps) -``` - -```tsx -// BEFORE (in JSX): - - -// AFTER: - -``` - ---- - -## TODO -- [x] **1.** `renderer/index.html` — change `minimal` to `Claude Flow` -- [x] **2.** `renderer/src/styles/globals.css` — full replacement with new CSS (monospace body, electric accent, 2px radii, uppercase labels, light theme block, focus glow, `.app-wordmark`, `.theme-toggle`) -- [x] **3a.** `renderer/src/App.tsx` — add `type Theme` alias -- [x] **3b.** `renderer/src/App.tsx` — add `theme` state + `useEffect` + `handleToggleTheme` -- [x] **3c.** `renderer/src/App.tsx` — pass `theme`/`onToggleTheme` to `Header`, pass `theme` to `DocumentPane` -- [x] **4.** `renderer/src/components/Header.tsx` — full replacement (new props, wordmark, toggle button) -- [x] **5a.** `renderer/src/components/DocumentPane.tsx` — add `syntaxHighlighting, defaultHighlightStyle` import -- [x] **5b.** `renderer/src/components/DocumentPane.tsx` — add `theme` to `MarkdownEditor` props -- [x] **5c.** `renderer/src/components/DocumentPane.tsx` — dynamic theme extension + `theme` in dep array -- [x] **5d.** `renderer/src/components/DocumentPane.tsx` — add `theme` to `DocumentPaneProps`, destructure, forward to `MarkdownEditor` - ---- - -## Risks / Considerations - -**CodeMirror reinitialization on theme switch**: Adding `theme` to the `useEffect` dependency array means the entire editor is torn down and recreated when the theme changes. This is intentional and correct — CodeMirror extensions are baked into the `EditorState` at creation time and can't be hot-swapped. The existing `content` sync `useEffect` will immediately restore the document contents after reinit, so no text loss occurs. There is a brief visual flash on theme toggle; this is acceptable. - -**`data-theme` initial state and flash of wrong theme**: The `useState` initializer reads `localStorage` synchronously, and the `useEffect` sets `data-theme` on first render. Because this happens before paint (Electron loads the renderer in a hidden window and only shows it after load), there should be no flash of the wrong theme in production. In dev the Vite HMR setup may briefly show unstyled content; this is not a concern for shipping. - -**Monospace font rendering differences per OS**: "SF Mono" ships with macOS/Xcode; "Cascadia Code" ships with Windows Terminal; "JetBrains Mono" and "Fira Code" are user-installed. The fallback chain is safe — `Monaco` is widely available on macOS, and `"Courier New", monospace` are universal final fallbacks. No font files are bundled; this is system-font-only. - -**`Theme` type duplication**: The `type Theme = "dark" | "light"` alias is defined in both `App.tsx` and `Header.tsx`. This is a minor smell. If it grows to more places, move it into `renderer/src/types.ts`. For this task (2 files) the duplication is acceptable. - -**Light mode CodeMirror gutter background**: The `.codemirror-editor .cm-gutters` rule uses `var(--bg-secondary)` which will automatically pick up the light-mode value — no extra change needed there. - -**`select` element styling in light mode**: Native `