--- date: 2026-10-19 pr: pending feature: CYBER theme - chat chain restyled onto the single dark token set impact: Rendering-layer only. Every chat-chain style block is moved onto the CYBER dark tokens, all `.dark` override branches are deleted because dark is now the only theme, and two latent bugs are fixed as a side effect (Monaco loaded the light `vs` theme; four Arco RGB-triplet variables were used as colors and silently fell back). No chat store logic, no `/chat-run` payload, and no message rendering path is touched. --- # CYBER theme — chat chain The chat chain was restyled onto the token set in `packages/client/src/styles/variables.scss`. The theme is a single dark palette: `useTheme()` pins `isDark` to `true` and the brightness switcher was removed, so any `.dark` selector now always matches and any non-`.dark` branch is unreachable. ## Why chat-chain files changed Fifteen files under the chat chain were caught by the restyle. None of the changes touch logic. ### Deleting `.dark` branches Because `.dark` is unconditionally present, every `.dark &` block was an unconditional override sitting on top of a token-based base rule — and each one carried a hardcoded gray from the previous theme. The value was merged down into the base rule and the wrapper deleted. Fourteen blocks across ten files were affected, including three that pinned `background-color: #333333` (a neutral gray that fought the blue-black CYBER palette) and one that set the thinking-shimmer sweep band to white. ### `#999999` / `#cccccc` / `#f2f2f2` / `#1f1f1f` / `#2a2a2a` Fifteen hardcoded legacy grays in `MessageItem.vue`, `MessageList.vue`, `ChatInput.vue`, `GroupMessageItem.vue` and `VirtualMessageList.vue` were rewritten to `--text-faint`, `--text-secondary`, `--bg-card` and `rgba(var(--text-primary-rgb), …)`. ### Latent bugs fixed - **`files/FileEditor.vue`** picked the Monaco theme with `document.documentElement.classList.contains('dark')`. The `dark` class is bound on `.app-root` in `App.vue`, not on ``, so the check was always false and Monaco always loaded the **light** `vs` theme inside the dark editor surface. Pinned to `vs-dark`. - **Arco RGB triplets used as colors.** `CodexLoginModal.vue`, `CopilotLoginModal.vue` and `NousLoginModal.vue` wrote `border-color: var(--arcoblue-6, #165dff)` and `VoiceApiFormModal.vue` wrote `color: var(--primary-6, #18a058)`. Those variables hold bare triplets (`22,93,255`), not colors, so each declaration was invalid and silently discarded — the hover border and link color fell back to the stock Arco blue/green rather than the CYBER accent. Rewritten to `--accent-primary`. - **`JourneyView.vue`** drew the pinned-node ring in `rgba(255, 190, 90, 0.85)`, an amber left over from the previous palette. Now uses the cyan edge palette like every other stroke in that canvas. ## Verification `grep -rn "\.dark" packages/client/src` returns no style-block matches. A token-reference scan comparing every `var(--x)` against the definitions in `variables.scss`, `global.scss` and `arco.css` reports only locally-defined per-component variables. ## Behavior impact Rendering-layer only. No chat store logic, no `/chat-run` payload, and no message rendering path was touched. The voice overlay, transcript controls, and the thinking indicator keep their existing markup and event wiring; only their colors and shadows changed.