diff --git a/apps/desktop/src/app/contrib/surfaces.tsx b/apps/desktop/src/app/contrib/surfaces.tsx index 2e40092ffc..750248fbfe 100644 --- a/apps/desktop/src/app/contrib/surfaces.tsx +++ b/apps/desktop/src/app/contrib/surfaces.tsx @@ -56,7 +56,7 @@ export const SidebarSurface = memo(function SidebarSurface({ export const TerminalSurface = memo(function TerminalSurface() { return ( -
+
) diff --git a/apps/desktop/src/app/right-sidebar/terminal/instance.tsx b/apps/desktop/src/app/right-sidebar/terminal/instance.tsx index 933916b640..9d81495642 100644 --- a/apps/desktop/src/app/right-sidebar/terminal/instance.tsx +++ b/apps/desktop/src/app/right-sidebar/terminal/instance.tsx @@ -12,7 +12,13 @@ import { useTerminalSession } from './use-terminal-session' // Absolute-stacked so inactive tabs keep layout size (a display:none host goes // 0×0 and renders garbled on re-show); visibility toggles which one is seen. -const INSTANCE_CLASS = 'absolute inset-0 flex flex-col bg-(--ui-editor-surface-background) px-2 pb-2 pt-0' +const INSTANCE_CLASS = 'absolute inset-0 flex flex-col bg-(--ui-terminal-surface-background) px-2 pb-2 pt-0' + +// xterm host. The screen/viewport overrides matter for the DOM renderer (the +// WebGL fast-path paints the canvas from ITheme.background instead) — both +// resolve to the same token, so the two renderers can't disagree. +const HOST_CLASS = + 'h-full min-h-0 overflow-hidden text-(--ui-text-secondary) [&_.xterm]:h-full [&_.xterm-screen]:bg-(--ui-terminal-surface-background)! [&_.xterm-viewport]:bg-(--ui-terminal-surface-background)!' interface TerminalInstanceProps { id: string @@ -81,10 +87,7 @@ export function TerminalInstance({ )} {/* Outer div paints the terminal inset; inner div is the xterm host so the canvas sizes to the content area and p-2 stays as terminal padding. */} -
+
) } @@ -107,10 +110,7 @@ export function AgentTerminalInstance({ active, id, procId }: AgentTerminalInsta // routes ⌘W here and closes the focused agent tab (not a preview). data-terminal="" > -
+
) } diff --git a/apps/desktop/src/app/right-sidebar/terminal/persistent.tsx b/apps/desktop/src/app/right-sidebar/terminal/persistent.tsx index 3fe2edb04a..b5e75978b0 100644 --- a/apps/desktop/src/app/right-sidebar/terminal/persistent.tsx +++ b/apps/desktop/src/app/right-sidebar/terminal/persistent.tsx @@ -207,7 +207,7 @@ export function PersistentTerminal({ onAddSelectionToChat }: PersistentTerminalP zIndex: 4, // Match the live skin surface so the header strip (transparent) and body // read as one cohesive pane instead of revealing a near-black slab behind. - backgroundColor: 'var(--ui-editor-surface-background)', + backgroundColor: 'var(--ui-terminal-surface-background)', contain: 'layout size paint' } diff --git a/apps/desktop/src/app/right-sidebar/terminal/rail.tsx b/apps/desktop/src/app/right-sidebar/terminal/rail.tsx index ced1675032..7b5aee0ffa 100644 --- a/apps/desktop/src/app/right-sidebar/terminal/rail.tsx +++ b/apps/desktop/src/app/right-sidebar/terminal/rail.tsx @@ -44,7 +44,7 @@ export function TerminalRail() { return (
{ const ansi = renderedMode === 'dark' ? (theme.darkTerminal ?? theme.terminal) : theme.terminal - const surface = resolveSurfaceColor('#ffffff') + const base = terminalTheme(renderedMode, ansi) + // Fall back to the palette's own background, not white — a hardcoded + // '#ffffff' flashes a white slab in dark mode whenever the probe can't read + // the token (pre-paint mount). Same contract as the user terminal. + const surface = resolveSurfaceColor(base.background ?? '#ffffff') - return { ...terminalTheme(renderedMode, ansi), background: surface, cursorAccent: surface } + return { ...base, background: surface, cursorAccent: surface } } // eslint-disable-next-line no-restricted-syntax -- legitimate non-atom ref write (see eslint rule comment) diff --git a/apps/desktop/src/styles.css b/apps/desktop/src/styles.css index 4017644307..065f5bd562 100644 --- a/apps/desktop/src/styles.css +++ b/apps/desktop/src/styles.css @@ -327,6 +327,12 @@ --ui-sidebar-surface-background: var(--ui-bg-sidebar); --ui-chat-surface-background: var(--ui-bg-chrome); --ui-editor-surface-background: var(--ui-bg-chrome); + /* The integrated terminal wears the transcript's background, not the + editor's — it reads as part of the conversation surface. Its own token so + the two can diverge without dragging the terminal along, and so a skin + gets one knob for it. xterm's canvas can't use a var, so the probe in + terminal/selection.ts resolves this same name to a concrete rgb. */ + --ui-terminal-surface-background: var(--ui-chat-surface-background); /* Inline chat widgets (clarify, artifact card) — the card fill in light mode, nudged down in dark so a widget settles into the transcript instead of glowing above it (see the `.dark` override). */