fix(skins): keep tinted badges readable on light skins, pin OG modals

The light skins themed the app chrome, but a class of status badges and
accent-tinted pills still hardcode pale light-on-dark ink (#cdddff,
#9dc0ff, #ffc107, #fff) over a low-alpha tint. Measured on a rendered
page, that lands at 1.0 to 1.9:1 under all four light skins: the search
filter chips (Sessions / Events / Files) render as empty blue pills.
Re-point the ink at each skin's own dark tokens and keep the tint as the
category signal, which moves the same components to 3.2 to 14:1.

Also pin --floating-bg on the OG skin. The new :root default is slate
rgba(31,38,48,.96), which suits the Daylight palettes (their glass
header is already rgba(31,38,48,.85)) but repaints OG's modals, command
palette and floating windows away from the neutral near-black that skin
is built on.

Verified against a live instance across all seven skins, plus a real
shell session for terminal ANSI output. Full suite green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer
2026-07-28 00:56:15 +02:00
parent 541d9c8131
commit 84f47e8ee0
2 changed files with 49 additions and 2 deletions
+8 -2
View File
@@ -1,5 +1,11 @@
---
"aicodeman": patch
'aicodeman': patch
---
Add four light UI and terminal skins—Paper Gray, Solarized Light, Catppuccin Latte, and Rosé Pine Dawn—with readable native controls, xterm palettes, and stateful mobile/response-viewer surfaces.
Add four light UI and terminal skins: Paper Gray, Solarized Light, Catppuccin Latte, and Rosé Pine Dawn. The Skin picker now groups Light and Dark options, and each light skin ships a matching xterm ANSI palette plus `color-scheme: light` so native selects, date pickers and scrollbars stop rendering as dark OS widgets on a light page. Terminals set `minimumContrastRatio: 4.5` under a light skin (main terminal and teammate terminals both), which keeps CLI output that assumes a dark background readable, and `applyTerminalSkin()` now refreshes the zero-lag input overlay so typed-but-unflushed text does not keep the previous theme's colors.
Elevated surfaces (modals, command palette, dropdowns, subagent and ultracode windows, file preview, attachment tray, mobile sheets) now resolve through shared `--floating-bg` / `--control-*` / `--banner-bg-*` / `--modal-backdrop` / `--elevated-shadow` tokens instead of hardcoded near-black rgba, so they follow whichever skin is active. On the Daylight skins this lifts modals slightly off the page background; OG Codeman pins its own near-black value to keep that palette neutral.
Also defines twelve CSS compatibility aliases (`--bg-primary`, `--bg-secondary`, `--bg-tertiary`, `--text-primary`, `--text-secondary`, `--border-color`, `--accent-color`, `--success`, `--error`, `--danger`, `--font-mono`, `--shadow-lg`) that panels and overlays already referenced in about 79 places but which were never actually declared, so those rules silently resolved to nothing. Status badges and accent-tinted pills (search filter chips and result badges, session tab mode pills, respawn state, Ralph priority and circuit-breaker badges, tunnel and voice status, mobile case picker) no longer keep their pale light-on-dark ink under a light skin, where it measured 1.0 to 1.9:1 and made the search filter chips invisible.
New static regression `test/skin-themes.test.ts` guards the four-way parity between the CSS token block, the xterm palette, the pre-paint allowlist and the Settings picker.
+41
View File
@@ -159,6 +159,10 @@ html[data-skin="og"] {
--term-bg: #0d0d0d;
--green: #22c55e; --yellow: #eab308; --red: #ef4444;
--glass-bg: rgba(19, 19, 22, 0.85); --glass-border: rgba(255, 255, 255, 0.06);
/* OG is a neutral near-black palette with no blue in it. Without this the
:root slate default would repaint every modal/palette/floating window
rgba(31,38,48,.96) and quietly break the skin's identity. */
--floating-bg: rgba(19, 19, 22, 0.96);
/* daylight-only extras left at sane neutral defaults (unused — override block does not apply to og) */
--accent-d: #3b82f6; --emerald: #3b82f6; --teal: #2563eb;
--accent-soft: #22c55e; --accent-ink: #0b1220;
@@ -315,6 +319,43 @@ html:is([data-skin="paper-gray"], [data-skin="solarized-light"], [data-skin="cat
border-color: var(--control-border-hover);
}
/* Status badges and accent-tinted pills bake in pale light-on-dark ink
(#cdddff, #9dc0ff, #ffc107, #fff, …) over a low-alpha tint. That reads at
1.0–1.9:1 once the tint sits on a light surface — the search filter chips
literally vanish. Re-point the ink at each skin's own dark tokens and keep
the tint as the category signal. */
html:is([data-skin="paper-gray"], [data-skin="solarized-light"], [data-skin="catppuccin-latte"], [data-skin="rose-pine-dawn"]) :is(
.search-filter-chip.active,
.search-badge-session,
.history-view-all-btn,
.session-tab .tab-mode.gemini
) {
color: var(--accent-d);
}
html:is([data-skin="paper-gray"], [data-skin="solarized-light"], [data-skin="catppuccin-latte"], [data-skin="rose-pine-dawn"]) :is(
.search-badge-file,
.tunnel-panel-btn.btn-start,
.voice-provider-status.active
) {
color: var(--green);
}
html:is([data-skin="paper-gray"], [data-skin="solarized-light"], [data-skin="catppuccin-latte"], [data-skin="rose-pine-dawn"]) :is(
.ralph-task-priority.priority-p1,
.ralph-circuit-breaker.half-open
) {
color: var(--yellow);
}
html:is([data-skin="paper-gray"], [data-skin="solarized-light"], [data-skin="catppuccin-latte"], [data-skin="rose-pine-dawn"]) :is(
.search-badge-event,
.respawn-state,
.history-detail-path,
.mobile-case-item,
.mobile-case-picker-header h3,
.btn-toolbar.btn-case-mobile:hover
) {
color: var(--text);
}
* { box-sizing: border-box; margin: 0; padding: 0; }
/* ========== Accessibility: Focus Styles ========== */