From b1d9e90bec60fd89dd566b3c7bf897a7ce27507c Mon Sep 17 00:00:00 2001 From: Sean Yang Date: Sun, 12 Apr 2026 11:49:32 -0400 Subject: [PATCH 1/5] feat: add green color theme Add a new "Green" forest-green color theme alongside the existing Light, Dark Navy, and Dark Black themes. Covers the full surface area: CSS variables, Monaco editor, Monaco diff viewer, terminal sessions, and all dark-mode guards updated to use `effectiveTheme !== 'light'` so future dark themes don't need per-file changes. Co-Authored-By: Claude Opus 4.6 --- src/main/settings.ts | 4 +- src/renderer/components/AgentLogo.tsx | 2 +- src/renderer/components/ChatInterface.tsx | 34 ++++++++------- src/renderer/components/EditorMode.tsx | 4 +- src/renderer/components/HomeView.tsx | 10 ++--- src/renderer/components/IntegrationsCard.tsx | 2 +- src/renderer/components/MultiAgentTask.tsx | 18 +++++--- src/renderer/components/TaskTerminalPanel.tsx | 41 ++++++++++--------- src/renderer/components/ThemeCard.tsx | 3 +- src/renderer/components/ThemeProvider.tsx | 17 ++++++-- .../components/diff-viewer/FileDiffView.tsx | 2 +- src/renderer/components/mcp/McpServerCard.tsx | 2 +- .../components/skills/SkillDetailModal.tsx | 2 +- .../components/skills/SkillIconRenderer.tsx | 2 +- .../components/ui/markdown-renderer.tsx | 2 +- .../hooks/useEditorDiffDecorations.ts | 2 +- src/renderer/index.css | 37 +++++++++++++++++ src/renderer/lib/monaco-themes.ts | 16 ++++++++ src/renderer/lib/monacoDiffColors.ts | 7 ++++ src/renderer/lib/monacoDiffThemes.ts | 16 ++++++++ 20 files changed, 159 insertions(+), 64 deletions(-) diff --git a/src/main/settings.ts b/src/main/settings.ts index 82cd0cc3d..896020bc1 100644 --- a/src/main/settings.ts +++ b/src/main/settings.ts @@ -68,7 +68,7 @@ export interface KeyboardSettings { export interface InterfaceSettings { autoRightSidebarBehavior?: boolean; showResourceMonitor?: boolean; - theme?: 'light' | 'dark' | 'dark-black' | 'system'; + theme?: 'light' | 'dark' | 'dark-black' | 'green' | 'system'; taskHoverAction?: 'delete' | 'archive'; } @@ -545,7 +545,7 @@ export function normalizeSettings(input: AppSettings): AppSettings { showResourceMonitor: Boolean( iface?.showResourceMonitor ?? DEFAULT_SETTINGS.interface!.showResourceMonitor ), - theme: ['light', 'dark', 'dark-black', 'system'].includes(iface?.theme) + theme: ['light', 'dark', 'dark-black', 'green', 'system'].includes(iface?.theme) ? iface.theme : DEFAULT_SETTINGS.interface!.theme, taskHoverAction: iface?.taskHoverAction === 'archive' ? 'archive' : 'delete', diff --git a/src/renderer/components/AgentLogo.tsx b/src/renderer/components/AgentLogo.tsx index 9cb253db0..4ac005b1b 100644 --- a/src/renderer/components/AgentLogo.tsx +++ b/src/renderer/components/AgentLogo.tsx @@ -20,7 +20,7 @@ const AgentLogo: React.FC = ({ grayscale, }) => { const { effectiveTheme } = useTheme(); - const isDark = effectiveTheme === 'dark' || effectiveTheme === 'dark-black'; + const isDark = effectiveTheme !== 'light'; const resolvedIsSvg = isSvg ?? logo.trimStart().startsWith(' = ({ ? 'bg-card' : 'bg-white' : agent === 'mistral' - ? effectiveTheme === 'dark' || effectiveTheme === 'dark-black' + ? effectiveTheme !== 'light' ? effectiveTheme === 'dark-black' ? 'bg-[#141820]' : 'bg-[#202938]' @@ -1313,18 +1313,18 @@ const ChatInterface: React.FC = ({ markActiveReviewPromptSent(); } }} - variant={ - effectiveTheme === 'dark' || effectiveTheme === 'dark-black' ? 'dark' : 'light' - } + variant={effectiveTheme !== 'light' ? 'dark' : 'light'} themeOverride={ agent === 'charm' ? { background: effectiveTheme === 'dark-black' ? '#0a0a0a' - : effectiveTheme === 'dark' - ? '#1f2937' - : '#ffffff', + : effectiveTheme === 'green' + ? '#365A3C' + : effectiveTheme === 'dark' + ? '#1f2937' + : '#ffffff', selectionBackground: 'rgba(96, 165, 250, 0.35)', selectionForeground: effectiveTheme === 'light' ? '#0f172a' : '#f9fafb', } @@ -1333,9 +1333,11 @@ const ChatInterface: React.FC = ({ background: effectiveTheme === 'dark-black' ? '#141820' - : effectiveTheme === 'dark' - ? '#202938' - : '#ffffff', + : effectiveTheme === 'green' + ? '#365A3C' + : effectiveTheme === 'dark' + ? '#202938' + : '#ffffff', selectionBackground: 'rgba(96, 165, 250, 0.35)', selectionForeground: effectiveTheme === 'light' ? '#0f172a' : '#f9fafb', } @@ -1345,12 +1347,16 @@ const ChatInterface: React.FC = ({ selectionBackground: 'rgba(96, 165, 250, 0.35)', selectionForeground: '#f9fafb', } - : undefined + : effectiveTheme === 'green' + ? { + background: '#2E5234', + selectionBackground: 'rgba(96, 165, 250, 0.35)', + selectionForeground: '#f9fafb', + } + : undefined } contentFilter={ - agent === 'charm' && - effectiveTheme !== 'dark' && - effectiveTheme !== 'dark-black' + agent === 'charm' && effectiveTheme === 'light' ? 'invert(1) hue-rotate(180deg) brightness(1.1) contrast(1.05)' : undefined } diff --git a/src/renderer/components/EditorMode.tsx b/src/renderer/components/EditorMode.tsx index 9fed79831..c8dfff8b1 100644 --- a/src/renderer/components/EditorMode.tsx +++ b/src/renderer/components/EditorMode.tsx @@ -555,9 +555,7 @@ export default function EditorMode({ taskPath, taskName, onClose }: EditorModePr value={fileContent} onChange={(value) => setFileContent(value || '')} onMount={handleEditorMount} - theme={ - effectiveTheme === 'dark' || effectiveTheme === 'dark-black' ? 'vs-dark' : 'vs' - } + theme={effectiveTheme !== 'light' ? 'vs-dark' : 'vs'} options={{ minimap: { enabled: true }, fontSize: 13, diff --git a/src/renderer/components/HomeView.tsx b/src/renderer/components/HomeView.tsx index 82fdd5505..7682b2fea 100644 --- a/src/renderer/components/HomeView.tsx +++ b/src/renderer/components/HomeView.tsx @@ -28,11 +28,7 @@ const HomeView: React.FC = ({
Emdash @@ -40,8 +36,8 @@ const HomeView: React.FC = ({ className="logo-shimmer-overlay" aria-hidden="true" style={{ - WebkitMaskImage: `url(${effectiveTheme === 'dark' || effectiveTheme === 'dark-black' ? emdashLogoWhite : emdashLogo})`, - maskImage: `url(${effectiveTheme === 'dark' || effectiveTheme === 'dark-black' ? emdashLogoWhite : emdashLogo})`, + WebkitMaskImage: `url(${effectiveTheme !== 'light' ? emdashLogoWhite : emdashLogo})`, + maskImage: `url(${effectiveTheme !== 'light' ? emdashLogoWhite : emdashLogo})`, WebkitMaskRepeat: 'no-repeat', maskRepeat: 'no-repeat', WebkitMaskSize: 'contain', diff --git a/src/renderer/components/IntegrationsCard.tsx b/src/renderer/components/IntegrationsCard.tsx index e4e02839a..fa2833624 100644 --- a/src/renderer/components/IntegrationsCard.tsx +++ b/src/renderer/components/IntegrationsCard.tsx @@ -31,7 +31,7 @@ import { INTEGRATION_REGISTRY, type IntegrationId } from './integrations/registr /** Light mode: original SVG colors. Dark / dark-black: primary colour. */ const SvgLogo = ({ raw }: { raw: string }) => { const { effectiveTheme } = useTheme(); - const isDark = effectiveTheme === 'dark' || effectiveTheme === 'dark-black'; + const isDark = effectiveTheme !== 'light'; const processed = isDark ? raw diff --git a/src/renderer/components/MultiAgentTask.tsx b/src/renderer/components/MultiAgentTask.tsx index a4d9372fb..25f0589fa 100644 --- a/src/renderer/components/MultiAgentTask.tsx +++ b/src/renderer/components/MultiAgentTask.tsx @@ -562,7 +562,7 @@ const MultiAgentTask: React.FC = ({
{variants.map((v, idx) => { - const isDark = effectiveTheme === 'dark' || effectiveTheme === 'dark-black'; + const isDark = effectiveTheme !== 'light'; const isActive = idx === activeTabIndex; return (
= ({ background: effectiveTheme === 'dark-black' ? '#141820' - : isDark - ? '#202938' - : '#ffffff', + : effectiveTheme === 'green' + ? '#365A3C' + : isDark + ? '#202938' + : '#ffffff', selectionBackground: 'rgba(96, 165, 250, 0.35)', selectionForeground: isDark ? '#f9fafb' : '#0f172a', } @@ -689,7 +691,13 @@ const MultiAgentTask: React.FC = ({ selectionBackground: 'rgba(96, 165, 250, 0.35)', selectionForeground: '#f9fafb', } - : undefined + : effectiveTheme === 'green' + ? { + background: '#2E5234', + selectionBackground: 'rgba(96, 165, 250, 0.35)', + selectionForeground: '#f9fafb', + } + : undefined } className="h-full w-full" onStartSuccess={() => { diff --git a/src/renderer/components/TaskTerminalPanel.tsx b/src/renderer/components/TaskTerminalPanel.tsx index cf673594c..8244926e3 100644 --- a/src/renderer/components/TaskTerminalPanel.tsx +++ b/src/renderer/components/TaskTerminalPanel.tsx @@ -439,13 +439,24 @@ const TaskTerminalPanelComponent: React.FC = ({ const isMistral = agent === 'mistral'; const darkBackground = isMistral ? '#202938' : '#1e1e1e'; const blackBackground = isMistral ? '#141820' : '#000000'; + const greenBackground = '#2E5234'; - return effectiveTheme === 'dark' || effectiveTheme === 'dark-black' + return effectiveTheme !== 'light' ? { - background: effectiveTheme === 'dark-black' ? blackBackground : darkBackground, - foreground: '#d4d4d4', - cursor: '#aeafad', - cursorAccent: effectiveTheme === 'dark-black' ? blackBackground : darkBackground, + background: + effectiveTheme === 'dark-black' + ? blackBackground + : effectiveTheme === 'green' + ? greenBackground + : darkBackground, + foreground: effectiveTheme === 'green' ? '#dde6dd' : '#d4d4d4', + cursor: effectiveTheme === 'green' ? '#dde6dd' : '#aeafad', + cursorAccent: + effectiveTheme === 'dark-black' + ? blackBackground + : effectiveTheme === 'green' + ? greenBackground + : darkBackground, selectionBackground: 'rgba(96, 165, 250, 0.35)', selectionForeground: '#f9fafb', black: '#000000', @@ -741,9 +752,7 @@ const TaskTerminalPanelComponent: React.FC = ({ @@ -752,7 +761,7 @@ const TaskTerminalPanelComponent: React.FC = ({
= ({ remote?.connectionId ? { connectionId: remote.connectionId } : undefined } env={taskEnv} - variant={ - effectiveTheme === 'dark' || effectiveTheme === 'dark-black' - ? 'dark' - : 'light' - } + variant={effectiveTheme !== 'light' ? 'dark' : 'light'} themeOverride={themeOverride} className="h-full w-full" keepAlive @@ -828,11 +833,7 @@ const TaskTerminalPanelComponent: React.FC = ({ remote={ remote?.connectionId ? { connectionId: remote.connectionId } : undefined } - variant={ - effectiveTheme === 'dark' || effectiveTheme === 'dark-black' - ? 'dark' - : 'light' - } + variant={effectiveTheme !== 'light' ? 'dark' : 'light'} themeOverride={themeOverride} className="h-full w-full" keepAlive @@ -861,7 +862,7 @@ const TaskTerminalPanelComponent: React.FC = ({ : 'Terminal' } onClose={handleCloseExpandedTerminal} - variant={effectiveTheme === 'dark' || effectiveTheme === 'dark-black' ? 'dark' : 'light'} + variant={effectiveTheme !== 'light' ? 'dark' : 'light'} /> )}
diff --git a/src/renderer/components/ThemeCard.tsx b/src/renderer/components/ThemeCard.tsx index 1d07aaa76..95cef0f72 100644 --- a/src/renderer/components/ThemeCard.tsx +++ b/src/renderer/components/ThemeCard.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { useTheme } from '../hooks/useTheme'; -import { Sun, Moon, Monitor, Circle } from 'lucide-react'; +import { Sun, Moon, Monitor, Circle, TreePine } from 'lucide-react'; const ThemeCard: React.FC = () => { const { theme, setTheme } = useTheme(); @@ -9,6 +9,7 @@ const ThemeCard: React.FC = () => { { value: 'light' as const, label: 'Light', icon: Sun }, { value: 'dark' as const, label: 'Dark Navy', icon: Moon }, { value: 'dark-black' as const, label: 'Dark Black', icon: Circle }, + { value: 'green' as const, label: 'Green', icon: TreePine }, { value: 'system' as const, label: 'System', icon: Monitor }, ]; diff --git a/src/renderer/components/ThemeProvider.tsx b/src/renderer/components/ThemeProvider.tsx index d63899cd4..2c14f8e69 100644 --- a/src/renderer/components/ThemeProvider.tsx +++ b/src/renderer/components/ThemeProvider.tsx @@ -1,8 +1,8 @@ import { useAppSettings } from '@/contexts/AppSettingsProvider'; import { createContext, useEffect, useState, type ReactNode } from 'react'; -type Theme = 'light' | 'dark' | 'dark-black' | 'system'; -type EffectiveTheme = 'light' | 'dark' | 'dark-black'; +type Theme = 'light' | 'dark' | 'dark-black' | 'green' | 'system'; +type EffectiveTheme = 'light' | 'dark' | 'dark-black' | 'green'; function getSystemTheme(): EffectiveTheme { if (typeof window === 'undefined') return 'light'; @@ -15,12 +15,14 @@ function applyTheme(theme: Theme, systemTheme: EffectiveTheme) { const root = document.documentElement; const effectiveTheme = theme === 'system' ? systemTheme : theme; - root.classList.remove('dark', 'dark-black'); + root.classList.remove('dark', 'dark-black', 'green'); if (effectiveTheme === 'dark') { root.classList.add('dark'); } else if (effectiveTheme === 'dark-black') { root.classList.add('dark', 'dark-black'); + } else if (effectiveTheme === 'green') { + root.classList.add('dark', 'green'); } } @@ -59,7 +61,14 @@ export function ThemeProvider({ children }: { children: ReactNode }) { const toggleTheme = () => { const base = theme === 'system' ? effectiveTheme : theme; - const next: Theme = base === 'light' ? 'dark' : base === 'dark' ? 'dark-black' : 'light'; + const next: Theme = + base === 'light' + ? 'dark' + : base === 'dark' + ? 'dark-black' + : base === 'dark-black' + ? 'green' + : 'light'; setTheme(next); }; diff --git a/src/renderer/components/diff-viewer/FileDiffView.tsx b/src/renderer/components/diff-viewer/FileDiffView.tsx index cdf145775..6b0ba990e 100644 --- a/src/renderer/components/diff-viewer/FileDiffView.tsx +++ b/src/renderer/components/diff-viewer/FileDiffView.tsx @@ -42,7 +42,7 @@ export const FileDiffView: React.FC = ({ baseRef, }) => { const { effectiveTheme } = useTheme(); - const isDark = effectiveTheme === 'dark' || effectiveTheme === 'dark-black'; + const isDark = effectiveTheme !== 'light'; const [fileData, setFileData] = useState<{ original: string; diff --git a/src/renderer/components/mcp/McpServerCard.tsx b/src/renderer/components/mcp/McpServerCard.tsx index 8401a1589..c6e655906 100644 --- a/src/renderer/components/mcp/McpServerCard.tsx +++ b/src/renderer/components/mcp/McpServerCard.tsx @@ -17,7 +17,7 @@ interface McpServerCardProps { const McpIcon: React.FC<{ name: string; catalogKey?: string }> = ({ name, catalogKey }) => { const { effectiveTheme } = useTheme(); - const isDark = effectiveTheme === 'dark' || effectiveTheme === 'dark-black'; + const isDark = effectiveTheme !== 'light'; const iconDef = catalogKey ? mcpIconMap[catalogKey] : undefined; if (iconDef && iconDef.type === 'svg' && iconDef.data) { diff --git a/src/renderer/components/skills/SkillDetailModal.tsx b/src/renderer/components/skills/SkillDetailModal.tsx index 1def3c1b0..c700d6f0b 100644 --- a/src/renderer/components/skills/SkillDetailModal.tsx +++ b/src/renderer/components/skills/SkillDetailModal.tsx @@ -93,7 +93,7 @@ const SkillDetailModal: React.FC = ({ const [isProcessing, setIsProcessing] = useState(false); const [justInstalled, setJustInstalled] = useState(false); const { effectiveTheme } = useTheme(); - const isDark = effectiveTheme === 'dark' || effectiveTheme === 'dark-black'; + const isDark = effectiveTheme !== 'light'; useEffect(() => { if (isOpen) setJustInstalled(false); diff --git a/src/renderer/components/skills/SkillIconRenderer.tsx b/src/renderer/components/skills/SkillIconRenderer.tsx index 3dec331b2..c87d22ac8 100644 --- a/src/renderer/components/skills/SkillIconRenderer.tsx +++ b/src/renderer/components/skills/SkillIconRenderer.tsx @@ -28,7 +28,7 @@ const SkillIconRenderer: React.FC = ({ skill, size = 'sm const [iconUrlError, setIconUrlError] = useState(false); const [avatarError, setAvatarError] = useState(false); const { effectiveTheme } = useTheme(); - const isDark = effectiveTheme === 'dark' || effectiveTheme === 'dark-black'; + const isDark = effectiveTheme !== 'light'; const iconDef = resolveSkillIcon(skill.id, skill.source); const remoteUrl = !iconDef ? skill.iconUrl : undefined; diff --git a/src/renderer/components/ui/markdown-renderer.tsx b/src/renderer/components/ui/markdown-renderer.tsx index 067ace0de..333a657dd 100644 --- a/src/renderer/components/ui/markdown-renderer.tsx +++ b/src/renderer/components/ui/markdown-renderer.tsx @@ -262,7 +262,7 @@ export const MarkdownRenderer: React.FC = ({ fileDir, }) => { const { effectiveTheme } = useTheme(); - const isDark = effectiveTheme === 'dark' || effectiveTheme === 'dark-black'; + const isDark = effectiveTheme !== 'light'; const fullComponents = useFullComponents(isDark, rootPath, fileDir); const compactComponents = useCompactComponents(); diff --git a/src/renderer/hooks/useEditorDiffDecorations.ts b/src/renderer/hooks/useEditorDiffDecorations.ts index cd6d3e87a..72e710e0c 100644 --- a/src/renderer/hooks/useEditorDiffDecorations.ts +++ b/src/renderer/hooks/useEditorDiffDecorations.ts @@ -147,7 +147,7 @@ export function useEditorDiffDecorations({ return; } - const isDark = effectiveTheme === 'dark' || effectiveTheme === 'dark-black'; + const isDark = effectiveTheme !== 'light'; const newDecorations: any[] = []; for (const diff of diffLines) { diff --git a/src/renderer/index.css b/src/renderer/index.css index 0b419cff9..6fb2fd627 100644 --- a/src/renderer/index.css +++ b/src/renderer/index.css @@ -103,6 +103,35 @@ --selection: 217 92% 70%; --selection-foreground: 0 0% 95%; } + + .green { + --background: 130 28% 25%; /* forest green #2E5234 */ + --foreground: 120 12% 90%; /* light sage #dde6dd */ + --card: 130 28% 25%; /* same as background */ + --card-foreground: 120 12% 90%; + --popover: 130 24% 28%; /* slightly lighter for dropdowns */ + --popover-foreground: 120 12% 90%; + --primary: 120 12% 90%; + --primary-foreground: 130 28% 25%; + --secondary: 130 20% 30%; + --secondary-foreground: 120 12% 90%; + --muted: 130 18% 32%; + --muted-foreground: 120 8% 65%; + --accent: 130 20% 30%; + --accent-foreground: 120 12% 90%; + --destructive: 0 62.8% 50%; + --destructive-foreground: 0 0% 98%; + --border: 130 14% 37%; + --input: 130 14% 37%; + --ring: 120 8% 65%; + --chart-1: 140 70% 40%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; + --selection: 120 60% 50%; + --selection-foreground: 130 28% 25%; + } } @layer base { @@ -164,6 +193,14 @@ .dark-black *::-webkit-scrollbar-thumb:hover { background-color: hsl(var(--muted-foreground) / 0.4); } + + .green *::-webkit-scrollbar-thumb { + background-color: hsl(var(--border)); + } + + .green *::-webkit-scrollbar-thumb:hover { + background-color: hsl(var(--muted-foreground) / 0.4); + } } @layer components { diff --git a/src/renderer/lib/monaco-themes.ts b/src/renderer/lib/monaco-themes.ts index ab6fdc012..dbf6668aa 100644 --- a/src/renderer/lib/monaco-themes.ts +++ b/src/renderer/lib/monaco-themes.ts @@ -43,6 +43,20 @@ export function defineMonacoThemes(monaco: Monaco): void { }, }); + // Green terminal theme + monaco.editor.defineTheme('custom-green', { + base: 'vs-dark', + inherit: true, + rules: [], + colors: { + 'editor.background': '#2E5234', + 'editor.foreground': '#dde6dd', + 'editor.lineHighlightBackground': '#3D6343', + 'editorLineNumber.foreground': '#7a9a7e', + 'editorGutter.background': '#2E5234', + }, + }); + // Light theme matching app's light mode monaco.editor.defineTheme('custom-light', { base: 'vs', @@ -67,6 +81,8 @@ export function getMonacoTheme(effectiveTheme: string): string { switch (effectiveTheme) { case 'dark-black': return 'custom-black'; + case 'green': + return 'custom-green'; case 'dark': return 'custom-dark'; case 'light': diff --git a/src/renderer/lib/monacoDiffColors.ts b/src/renderer/lib/monacoDiffColors.ts index fbbb0c8cc..9fc610cb7 100644 --- a/src/renderer/lib/monacoDiffColors.ts +++ b/src/renderer/lib/monacoDiffColors.ts @@ -23,6 +23,13 @@ export const MONACO_DIFF_COLORS = { removedTextBackground: '#8813375C', // rose-900 with slightly higher opacity for black bg removedLineBackground: '#88133773', // rose-900 with 45% opacity for lines }, + green: { + editorBackground: '#2E5234', // forest green + insertedTextBackground: '#064e3b5C', // emerald-900 with higher opacity for green bg + insertedLineBackground: '#064e3b73', // emerald-900 with 45% opacity for lines + removedTextBackground: '#8813375C', // rose-900 with higher opacity for green bg + removedLineBackground: '#88133773', // rose-900 with 45% opacity for lines + }, light: { editorBackground: '#f8fafc', // slate-50 - light grey/white background // Emerald (green) for additions - emerald-50 diff --git a/src/renderer/lib/monacoDiffThemes.ts b/src/renderer/lib/monacoDiffThemes.ts index 4975b5dad..84289884b 100644 --- a/src/renderer/lib/monacoDiffThemes.ts +++ b/src/renderer/lib/monacoDiffThemes.ts @@ -38,6 +38,21 @@ export async function registerDiffThemes(): Promise { }, }); + monacoInstance.editor.defineTheme('custom-diff-green', { + base: 'vs-dark', + inherit: true, + rules: [], + colors: { + 'editor.background': MONACO_DIFF_COLORS.green.editorBackground, + 'editorGutter.background': MONACO_DIFF_COLORS.green.editorBackground, + 'diffEditor.insertedTextBackground': MONACO_DIFF_COLORS.green.insertedTextBackground, + 'diffEditor.insertedLineBackground': MONACO_DIFF_COLORS.green.insertedLineBackground, + 'diffEditor.removedTextBackground': MONACO_DIFF_COLORS.green.removedTextBackground, + 'diffEditor.removedLineBackground': MONACO_DIFF_COLORS.green.removedLineBackground, + 'diffEditor.unchangedRegionBackground': '#264830', + }, + }); + monacoInstance.editor.defineTheme('custom-diff-light', { base: 'vs', inherit: true, @@ -56,6 +71,7 @@ export async function registerDiffThemes(): Promise { export function getDiffThemeName(effectiveTheme: string): string { if (effectiveTheme === 'dark-black') return 'custom-diff-black'; + if (effectiveTheme === 'green') return 'custom-diff-green'; if (effectiveTheme === 'light') return 'custom-diff-light'; return 'custom-diff-dark'; } From 6c7ffa04543d5d22a4682b2caaca3cf7bca414e3 Mon Sep 17 00:00:00 2001 From: Sean Yang Date: Sun, 12 Apr 2026 11:57:59 -0400 Subject: [PATCH 2/5] refactor: centralize terminal theme colors and extract helpers - Create terminalThemeColors.ts with shared constants (GREEN_COLORS, TERMINAL_BACKGROUNDS, MISTRAL_BACKGROUNDS, TERMINAL_SELECTION) and helpers (getTerminalThemeOverride, getTerminalContainerClass) - Replace 40+ lines of nested ternaries in ChatInterface and MultiAgentTask with single function calls - Fix charm agent bg-white bug on green theme (was falling through) - Fix green-on-green diff contrast by using blue tint for insertions - Merge duplicate scrollbar CSS selectors for dark-black and green - Use GREEN_COLORS constants in Monaco theme files Co-Authored-By: Claude Opus 4.6 --- src/renderer/components/ChatInterface.tsx | 59 +--------- src/renderer/components/MultiAgentTask.tsx | 40 +------ src/renderer/components/TaskTerminalPanel.tsx | 41 +++---- src/renderer/index.css | 10 +- src/renderer/lib/monaco-themes.ts | 11 +- src/renderer/lib/monacoDiffColors.ts | 8 +- src/renderer/lib/monacoDiffThemes.ts | 3 +- src/renderer/lib/terminalThemeColors.ts | 107 ++++++++++++++++++ 8 files changed, 143 insertions(+), 136 deletions(-) create mode 100644 src/renderer/lib/terminalThemeColors.ts diff --git a/src/renderer/components/ChatInterface.tsx b/src/renderer/components/ChatInterface.tsx index 72d302ec4..7df1eb3af 100644 --- a/src/renderer/components/ChatInterface.tsx +++ b/src/renderer/components/ChatInterface.tsx @@ -37,6 +37,7 @@ import { useWorkspaceConnection } from '../hooks/useWorkspaceConnection'; import { useTerminalSearch } from '../hooks/useTerminalSearch'; import { TerminalSearchOverlay } from './TerminalSearchOverlay'; import { getReviewConversationMetadata, parseConversationMetadata } from '@shared/reviewPreset'; +import { getTerminalThemeOverride, getTerminalContainerClass } from '../lib/terminalThemeColors'; import { getConversationTabLabel, planConversationTitleUpdates, @@ -1249,21 +1250,7 @@ const ChatInterface: React.FC = ({ >
= ({ } }} variant={effectiveTheme !== 'light' ? 'dark' : 'light'} - themeOverride={ - agent === 'charm' - ? { - background: - effectiveTheme === 'dark-black' - ? '#0a0a0a' - : effectiveTheme === 'green' - ? '#365A3C' - : effectiveTheme === 'dark' - ? '#1f2937' - : '#ffffff', - selectionBackground: 'rgba(96, 165, 250, 0.35)', - selectionForeground: effectiveTheme === 'light' ? '#0f172a' : '#f9fafb', - } - : agent === 'mistral' - ? { - background: - effectiveTheme === 'dark-black' - ? '#141820' - : effectiveTheme === 'green' - ? '#365A3C' - : effectiveTheme === 'dark' - ? '#202938' - : '#ffffff', - selectionBackground: 'rgba(96, 165, 250, 0.35)', - selectionForeground: effectiveTheme === 'light' ? '#0f172a' : '#f9fafb', - } - : effectiveTheme === 'dark-black' - ? { - background: '#000000', - selectionBackground: 'rgba(96, 165, 250, 0.35)', - selectionForeground: '#f9fafb', - } - : effectiveTheme === 'green' - ? { - background: '#2E5234', - selectionBackground: 'rgba(96, 165, 250, 0.35)', - selectionForeground: '#f9fafb', - } - : undefined - } + themeOverride={getTerminalThemeOverride(effectiveTheme, agent)} contentFilter={ agent === 'charm' && effectiveTheme === 'light' ? 'invert(1) hue-rotate(180deg) brightness(1.1) contrast(1.05)' diff --git a/src/renderer/components/MultiAgentTask.tsx b/src/renderer/components/MultiAgentTask.tsx index 25f0589fa..578db3dc2 100644 --- a/src/renderer/components/MultiAgentTask.tsx +++ b/src/renderer/components/MultiAgentTask.tsx @@ -28,6 +28,7 @@ import { formatCommentsForAgent } from '@/lib/formatCommentsForAgent'; import { buildPromptInjectionPayload } from '@/lib/terminalInjection'; import { TaskScopeProvider } from './TaskScopeContext'; import TaskContextBadges from './TaskContextBadges'; +import { getTerminalThemeOverride, getTerminalContainerClass } from '../lib/terminalThemeColors'; interface Props { task: Task; @@ -637,15 +638,7 @@ const MultiAgentTask: React.FC = ({ onWheelCapture={handleTerminalViewportWheelForwarding} >
= ({ keepAlive mapShiftEnterToCtrlJ variant={isDark ? 'dark' : 'light'} - themeOverride={ - v.agent === 'mistral' - ? { - background: - effectiveTheme === 'dark-black' - ? '#141820' - : effectiveTheme === 'green' - ? '#365A3C' - : isDark - ? '#202938' - : '#ffffff', - selectionBackground: 'rgba(96, 165, 250, 0.35)', - selectionForeground: isDark ? '#f9fafb' : '#0f172a', - } - : effectiveTheme === 'dark-black' - ? { - background: '#000000', - selectionBackground: 'rgba(96, 165, 250, 0.35)', - selectionForeground: '#f9fafb', - } - : effectiveTheme === 'green' - ? { - background: '#2E5234', - selectionBackground: 'rgba(96, 165, 250, 0.35)', - selectionForeground: '#f9fafb', - } - : undefined - } + themeOverride={getTerminalThemeOverride(effectiveTheme, v.agent)} className="h-full w-full" onStartSuccess={() => { if ( diff --git a/src/renderer/components/TaskTerminalPanel.tsx b/src/renderer/components/TaskTerminalPanel.tsx index 8244926e3..965df2d2e 100644 --- a/src/renderer/components/TaskTerminalPanel.tsx +++ b/src/renderer/components/TaskTerminalPanel.tsx @@ -30,6 +30,13 @@ import { } from '@shared/lifecycle'; import { shouldDisablePlay } from '../lib/lifecycleUi'; import ExpandedTerminalModal from './ExpandedTerminalModal'; +import { + GREEN_COLORS, + TERMINAL_BACKGROUNDS, + MISTRAL_BACKGROUNDS, + TERMINAL_SELECTION, + getTerminalContainerClass, +} from '../lib/terminalThemeColors'; interface Task { id: string; @@ -437,28 +444,16 @@ const TaskTerminalPanelComponent: React.FC = ({ const defaultTheme = useMemo(() => { const isMistral = agent === 'mistral'; - const darkBackground = isMistral ? '#202938' : '#1e1e1e'; - const blackBackground = isMistral ? '#141820' : '#000000'; - const greenBackground = '#2E5234'; + const backgrounds = isMistral ? MISTRAL_BACKGROUNDS : TERMINAL_BACKGROUNDS; + const bg = backgrounds[effectiveTheme] ?? backgrounds.dark; return effectiveTheme !== 'light' ? { - background: - effectiveTheme === 'dark-black' - ? blackBackground - : effectiveTheme === 'green' - ? greenBackground - : darkBackground, - foreground: effectiveTheme === 'green' ? '#dde6dd' : '#d4d4d4', - cursor: effectiveTheme === 'green' ? '#dde6dd' : '#aeafad', - cursorAccent: - effectiveTheme === 'dark-black' - ? blackBackground - : effectiveTheme === 'green' - ? greenBackground - : darkBackground, - selectionBackground: 'rgba(96, 165, 250, 0.35)', - selectionForeground: '#f9fafb', + background: bg, + foreground: effectiveTheme === 'green' ? GREEN_COLORS.foreground : '#d4d4d4', + cursor: effectiveTheme === 'green' ? GREEN_COLORS.foreground : '#aeafad', + cursorAccent: bg, + ...TERMINAL_SELECTION.dark, black: '#000000', red: '#cd3131', green: '#0dbc79', @@ -761,13 +756,7 @@ const TaskTerminalPanelComponent: React.FC = ({
(); @@ -49,11 +50,11 @@ export function defineMonacoThemes(monaco: Monaco): void { inherit: true, rules: [], colors: { - 'editor.background': '#2E5234', - 'editor.foreground': '#dde6dd', - 'editor.lineHighlightBackground': '#3D6343', - 'editorLineNumber.foreground': '#7a9a7e', - 'editorGutter.background': '#2E5234', + 'editor.background': GREEN_COLORS.background, + 'editor.foreground': GREEN_COLORS.foreground, + 'editor.lineHighlightBackground': GREEN_COLORS.lineHighlight, + 'editorLineNumber.foreground': GREEN_COLORS.lineNumber, + 'editorGutter.background': GREEN_COLORS.gutter, }, }); diff --git a/src/renderer/lib/monacoDiffColors.ts b/src/renderer/lib/monacoDiffColors.ts index 9fc610cb7..112c82879 100644 --- a/src/renderer/lib/monacoDiffColors.ts +++ b/src/renderer/lib/monacoDiffColors.ts @@ -3,6 +3,7 @@ * Shared Monaco Editor diff color constants used by DiffViewer and other diff views * Colors are defined here for maintainability and consistency */ +import { GREEN_COLORS } from './terminalThemeColors'; export const MONACO_DIFF_COLORS = { dark: { @@ -24,9 +25,10 @@ export const MONACO_DIFF_COLORS = { removedLineBackground: '#88133773', // rose-900 with 45% opacity for lines }, green: { - editorBackground: '#2E5234', // forest green - insertedTextBackground: '#064e3b5C', // emerald-900 with higher opacity for green bg - insertedLineBackground: '#064e3b73', // emerald-900 with 45% opacity for lines + editorBackground: GREEN_COLORS.background, + // Use blue/teal tint for insertions to avoid green-on-green low contrast + insertedTextBackground: '#0369a14D', // blue-700 with 30% opacity + insertedLineBackground: '#0369a166', // blue-700 with 40% opacity for lines removedTextBackground: '#8813375C', // rose-900 with higher opacity for green bg removedLineBackground: '#88133773', // rose-900 with 45% opacity for lines }, diff --git a/src/renderer/lib/monacoDiffThemes.ts b/src/renderer/lib/monacoDiffThemes.ts index 84289884b..b094571d6 100644 --- a/src/renderer/lib/monacoDiffThemes.ts +++ b/src/renderer/lib/monacoDiffThemes.ts @@ -1,5 +1,6 @@ import { loader } from '@monaco-editor/react'; import { MONACO_DIFF_COLORS } from './monacoDiffColors'; +import { GREEN_COLORS } from './terminalThemeColors'; let themesRegistered = false; @@ -49,7 +50,7 @@ export async function registerDiffThemes(): Promise { 'diffEditor.insertedLineBackground': MONACO_DIFF_COLORS.green.insertedLineBackground, 'diffEditor.removedTextBackground': MONACO_DIFF_COLORS.green.removedTextBackground, 'diffEditor.removedLineBackground': MONACO_DIFF_COLORS.green.removedLineBackground, - 'diffEditor.unchangedRegionBackground': '#264830', + 'diffEditor.unchangedRegionBackground': GREEN_COLORS.unchangedRegion, }, }); diff --git a/src/renderer/lib/terminalThemeColors.ts b/src/renderer/lib/terminalThemeColors.ts new file mode 100644 index 000000000..4cd9634a5 --- /dev/null +++ b/src/renderer/lib/terminalThemeColors.ts @@ -0,0 +1,107 @@ +/** + * Centralized terminal theme color constants. + * Used by ChatInterface, MultiAgentTask, TaskTerminalPanel, and Monaco theme files. + */ + +export const TERMINAL_SELECTION = { + dark: { + selectionBackground: 'rgba(96, 165, 250, 0.35)', + selectionForeground: '#f9fafb', + }, + light: { + selectionBackground: 'rgba(59, 130, 246, 0.35)', + selectionForeground: '#0f172a', + }, +} as const; + +export const GREEN_COLORS = { + background: '#2E5234', + card: '#365A3C', + foreground: '#dde6dd', + lineHighlight: '#3D6343', + lineNumber: '#7a9a7e', + gutter: '#2E5234', + unchangedRegion: '#264830', +} as const; + +/** Per-theme base terminal backgrounds (non-agent-specific). */ +export const TERMINAL_BACKGROUNDS = { + light: '#ffffff', + dark: '#1e1e1e', + 'dark-black': '#000000', + green: GREEN_COLORS.background, +} as const; + +/** Per-theme terminal backgrounds for the mistral agent. */ +export const MISTRAL_BACKGROUNDS = { + light: '#ffffff', + dark: '#202938', + 'dark-black': '#141820', + green: GREEN_COLORS.card, +} as const; + +type EffectiveTheme = 'light' | 'dark' | 'dark-black' | 'green'; + +/** + * Build the themeOverride object for a terminal pane. + * Returns undefined when no override is needed (standard dark theme). + */ +export function getTerminalThemeOverride( + effectiveTheme: EffectiveTheme, + agent?: string +): Record | undefined { + const selection = effectiveTheme === 'light' ? TERMINAL_SELECTION.light : TERMINAL_SELECTION.dark; + + if (agent === 'charm') { + return { + background: + effectiveTheme === 'dark-black' + ? '#0a0a0a' + : effectiveTheme === 'green' + ? GREEN_COLORS.card + : effectiveTheme === 'dark' + ? '#1f2937' + : '#ffffff', + ...selection, + }; + } + + if (agent === 'mistral') { + return { + background: MISTRAL_BACKGROUNDS[effectiveTheme], + ...selection, + }; + } + + // Non-agent-specific: only override for themes that differ from the dark default + if (effectiveTheme === 'dark-black') { + return { background: '#000000', ...selection }; + } + if (effectiveTheme === 'green') { + return { background: GREEN_COLORS.background, ...selection }; + } + + return undefined; +} + +/** + * Get the Tailwind bg class for the terminal container wrapper. + */ +export function getTerminalContainerClass(effectiveTheme: EffectiveTheme, agent?: string): string { + if (agent === 'charm') { + if (effectiveTheme === 'dark-black') return 'bg-black'; + if (effectiveTheme === 'green') return 'bg-card'; + if (effectiveTheme !== 'light') return 'bg-card'; + return 'bg-white'; + } + + if (agent === 'mistral') { + if (effectiveTheme === 'dark-black') return 'bg-[#141820]'; + if (effectiveTheme === 'green') return `bg-[${GREEN_COLORS.card}]`; + if (effectiveTheme !== 'light') return 'bg-[#202938]'; + return 'bg-white'; + } + + if (effectiveTheme !== 'light') return 'bg-card'; + return 'bg-white'; +} From 37db7b5c596ea0534da80f93166373b79c0431a1 Mon Sep 17 00:00:00 2001 From: Sean Yang Date: Sun, 12 Apr 2026 17:38:21 -0400 Subject: [PATCH 3/5] fix: address PR review comments - Use getMonacoTheme() in EditorMode so green theme gets custom-green instead of vs-dark - Use literal Tailwind class string instead of template interpolation so the content scanner can generate the CSS Co-Authored-By: Claude Opus 4.6 --- src/renderer/components/EditorMode.tsx | 3 ++- src/renderer/lib/terminalThemeColors.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/renderer/components/EditorMode.tsx b/src/renderer/components/EditorMode.tsx index c8dfff8b1..87ad5e3da 100644 --- a/src/renderer/components/EditorMode.tsx +++ b/src/renderer/components/EditorMode.tsx @@ -17,6 +17,7 @@ import { getMonacoLanguageId } from '@/lib/diffUtils'; import { buildMonacoModelPath } from '@/lib/monacoModelPath'; import { registerActiveCodeEditor } from '@/lib/activeCodeEditor'; import { addMonacoKeyboardShortcuts } from '@/lib/monaco-config'; +import { getMonacoTheme } from '@/lib/monaco-themes'; import { useTheme } from '@/hooks/useTheme'; import { useRightSidebar } from './ui/right-sidebar'; @@ -555,7 +556,7 @@ export default function EditorMode({ taskPath, taskName, onClose }: EditorModePr value={fileContent} onChange={(value) => setFileContent(value || '')} onMount={handleEditorMount} - theme={effectiveTheme !== 'light' ? 'vs-dark' : 'vs'} + theme={getMonacoTheme(effectiveTheme)} options={{ minimap: { enabled: true }, fontSize: 13, diff --git a/src/renderer/lib/terminalThemeColors.ts b/src/renderer/lib/terminalThemeColors.ts index 4cd9634a5..817ce5f1e 100644 --- a/src/renderer/lib/terminalThemeColors.ts +++ b/src/renderer/lib/terminalThemeColors.ts @@ -97,7 +97,7 @@ export function getTerminalContainerClass(effectiveTheme: EffectiveTheme, agent? if (agent === 'mistral') { if (effectiveTheme === 'dark-black') return 'bg-[#141820]'; - if (effectiveTheme === 'green') return `bg-[${GREEN_COLORS.card}]`; + if (effectiveTheme === 'green') return 'bg-[#365A3C]'; if (effectiveTheme !== 'light') return 'bg-[#202938]'; return 'bg-white'; } From d01b935e348981d97adb4983a3be7cf9ef953a16 Mon Sep 17 00:00:00 2001 From: Sean Yang Date: Sun, 12 Apr 2026 17:49:16 -0400 Subject: [PATCH 4/5] fix: use exact terminal RGB values (33,70,46) for green theme Updated base green from #2E5234 to #21462E to match the user's macOS terminal background exactly. All derived colors shifted proportionally. Co-Authored-By: Claude Opus 4.6 --- src/renderer/index.css | 20 ++++++++++---------- src/renderer/lib/terminalThemeColors.ts | 14 +++++++------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/renderer/index.css b/src/renderer/index.css index a0597880b..abf71164f 100644 --- a/src/renderer/index.css +++ b/src/renderer/index.css @@ -105,24 +105,24 @@ } .green { - --background: 130 28% 25%; /* forest green #2E5234 */ + --background: 141 36% 20%; /* forest green #21462E */ --foreground: 120 12% 90%; /* light sage #dde6dd */ - --card: 130 28% 25%; /* same as background */ + --card: 141 36% 20%; /* same as background */ --card-foreground: 120 12% 90%; - --popover: 130 24% 28%; /* slightly lighter for dropdowns */ + --popover: 141 32% 23%; /* slightly lighter for dropdowns */ --popover-foreground: 120 12% 90%; --primary: 120 12% 90%; - --primary-foreground: 130 28% 25%; - --secondary: 130 20% 30%; + --primary-foreground: 141 36% 20%; + --secondary: 141 28% 25%; --secondary-foreground: 120 12% 90%; - --muted: 130 18% 32%; + --muted: 141 26% 27%; --muted-foreground: 120 8% 65%; - --accent: 130 20% 30%; + --accent: 141 28% 25%; --accent-foreground: 120 12% 90%; --destructive: 0 62.8% 50%; --destructive-foreground: 0 0% 98%; - --border: 130 14% 37%; - --input: 130 14% 37%; + --border: 141 22% 32%; + --input: 141 22% 32%; --ring: 120 8% 65%; --chart-1: 140 70% 40%; --chart-2: 160 60% 45%; @@ -130,7 +130,7 @@ --chart-4: 280 65% 60%; --chart-5: 340 75% 55%; --selection: 120 60% 50%; - --selection-foreground: 130 28% 25%; + --selection-foreground: 141 36% 20%; } } diff --git a/src/renderer/lib/terminalThemeColors.ts b/src/renderer/lib/terminalThemeColors.ts index 817ce5f1e..46dac32e4 100644 --- a/src/renderer/lib/terminalThemeColors.ts +++ b/src/renderer/lib/terminalThemeColors.ts @@ -15,13 +15,13 @@ export const TERMINAL_SELECTION = { } as const; export const GREEN_COLORS = { - background: '#2E5234', - card: '#365A3C', + background: '#21462E', + card: '#294E36', foreground: '#dde6dd', - lineHighlight: '#3D6343', - lineNumber: '#7a9a7e', - gutter: '#2E5234', - unchangedRegion: '#264830', + lineHighlight: '#30573D', + lineNumber: '#6D8E78', + gutter: '#21462E', + unchangedRegion: '#193C2A', } as const; /** Per-theme base terminal backgrounds (non-agent-specific). */ @@ -97,7 +97,7 @@ export function getTerminalContainerClass(effectiveTheme: EffectiveTheme, agent? if (agent === 'mistral') { if (effectiveTheme === 'dark-black') return 'bg-[#141820]'; - if (effectiveTheme === 'green') return 'bg-[#365A3C]'; + if (effectiveTheme === 'green') return 'bg-[#294E36]'; if (effectiveTheme !== 'light') return 'bg-[#202938]'; return 'bg-white'; } From 75df0e607872e9e99faf8cd9476bf617534c53e5 Mon Sep 17 00:00:00 2001 From: Sean Yang Date: Sun, 12 Apr 2026 18:09:47 -0400 Subject: [PATCH 5/5] fix: compensate for Electron color management in green theme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumped saturation (36→42%) and lightness (20→22%) so the rendered color matches the target terminal RGB (33, 70, 46) after Electron's color pipeline. Co-Authored-By: Claude Opus 4.6 --- src/renderer/index.css | 20 ++++++++++---------- src/renderer/lib/terminalThemeColors.ts | 12 ++++++------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/renderer/index.css b/src/renderer/index.css index abf71164f..0b8e2d27b 100644 --- a/src/renderer/index.css +++ b/src/renderer/index.css @@ -105,24 +105,24 @@ } .green { - --background: 141 36% 20%; /* forest green #21462E */ + --background: 141 42% 22%; /* forest green #215031 */ --foreground: 120 12% 90%; /* light sage #dde6dd */ - --card: 141 36% 20%; /* same as background */ + --card: 141 42% 22%; /* same as background */ --card-foreground: 120 12% 90%; - --popover: 141 32% 23%; /* slightly lighter for dropdowns */ + --popover: 141 38% 25%; /* slightly lighter for dropdowns */ --popover-foreground: 120 12% 90%; --primary: 120 12% 90%; - --primary-foreground: 141 36% 20%; - --secondary: 141 28% 25%; + --primary-foreground: 141 42% 22%; + --secondary: 141 34% 27%; --secondary-foreground: 120 12% 90%; - --muted: 141 26% 27%; + --muted: 141 32% 29%; --muted-foreground: 120 8% 65%; - --accent: 141 28% 25%; + --accent: 141 34% 27%; --accent-foreground: 120 12% 90%; --destructive: 0 62.8% 50%; --destructive-foreground: 0 0% 98%; - --border: 141 22% 32%; - --input: 141 22% 32%; + --border: 141 28% 34%; + --input: 141 28% 34%; --ring: 120 8% 65%; --chart-1: 140 70% 40%; --chart-2: 160 60% 45%; @@ -130,7 +130,7 @@ --chart-4: 280 65% 60%; --chart-5: 340 75% 55%; --selection: 120 60% 50%; - --selection-foreground: 141 36% 20%; + --selection-foreground: 141 42% 22%; } } diff --git a/src/renderer/lib/terminalThemeColors.ts b/src/renderer/lib/terminalThemeColors.ts index 46dac32e4..79681b9d7 100644 --- a/src/renderer/lib/terminalThemeColors.ts +++ b/src/renderer/lib/terminalThemeColors.ts @@ -15,13 +15,13 @@ export const TERMINAL_SELECTION = { } as const; export const GREEN_COLORS = { - background: '#21462E', - card: '#294E36', + background: '#215031', + card: '#295839', foreground: '#dde6dd', - lineHighlight: '#30573D', + lineHighlight: '#306140', lineNumber: '#6D8E78', - gutter: '#21462E', - unchangedRegion: '#193C2A', + gutter: '#215031', + unchangedRegion: '#19462D', } as const; /** Per-theme base terminal backgrounds (non-agent-specific). */ @@ -97,7 +97,7 @@ export function getTerminalContainerClass(effectiveTheme: EffectiveTheme, agent? if (agent === 'mistral') { if (effectiveTheme === 'dark-black') return 'bg-[#141820]'; - if (effectiveTheme === 'green') return 'bg-[#294E36]'; + if (effectiveTheme === 'green') return 'bg-[#295839]'; if (effectiveTheme !== 'light') return 'bg-[#202938]'; return 'bg-white'; }