Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 48 additions & 23 deletions ui/overlay-styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,32 @@ export const OVERLAY_CSS = `
--lco-warn-bg: rgba(245, 158, 11, 0.09);

/* Dark mode (default on claude.ai) */
--lco-bg: rgba(30, 30, 32, 0.82);
--lco-bg-hover: rgba(38, 38, 42, 0.88);
--lco-bg: rgba(30, 30, 28, 0.92); /* was .82 — prevents muted text failing on light page content bleedthrough */
--lco-bg-hover: rgba(38, 38, 36, 0.95);
--lco-text: #d4d4d8;
--lco-muted: #71717a;
--lco-border: rgba(255, 255, 255, 0.06);
--lco-border-hover: rgba(255, 255, 255, 0.12);
--lco-muted: #8a8a93; /* was #71717a — bumped for WCAG AA headroom (~5.8:1 on dark surface) */
--lco-border: rgba(255, 255, 255, 0.12); /* was .06 — invisible on claude.ai dark panels */
Comment thread
DevanshuNEU marked this conversation as resolved.
--lco-border-hover: rgba(255, 255, 255, 0.18);

-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

@media (prefers-color-scheme: light) {
:host {
--lco-bg: rgba(244, 243, 238, 0.85);
--lco-bg-hover: rgba(238, 236, 230, 0.90);
--lco-bg: rgba(244, 243, 238, 0.92); /* matched to dark mode .92 floor */
--lco-bg-hover: rgba(238, 236, 230, 0.95);
--lco-text: #27272a;
--lco-muted: #a1a1aa;
--lco-muted: #6b7280; /* was #a1a1aa (~3.2:1 fail on warm cream) — gray-500 gives ~4.8:1 AA */
--lco-accent: #b35a34;
--lco-bar-fill: #b35a34;
--lco-bar-glow: rgba(179, 90, 52, 0.20);
--lco-bar-bg: rgba(179, 90, 52, 0.10);
--lco-warn-fill: #d97706;
--lco-warn-glow: rgba(217, 119, 6, 0.20);
--lco-warn-bg: rgba(217, 119, 6, 0.08);
--lco-border: rgba(0, 0, 0, 0.06);
--lco-border-hover: rgba(0, 0, 0, 0.12);
--lco-border: rgba(0, 0, 0, 0.08); /* was .06 — widget edge was missing in light mode */
--lco-border-hover: rgba(0, 0, 0, 0.14);
}
}

Expand All @@ -60,8 +60,8 @@ export const OVERLAY_CSS = `
}

@keyframes lco-dot-pulse {
0%, 100% { box-shadow: 0 0 4px rgba(248, 113, 113, 0.4); }
50% { box-shadow: 0 0 10px rgba(248, 113, 113, 0.7); }
0%, 100% { box-shadow: 0 0 4px rgba(239, 68, 68, 0.4); }
50% { box-shadow: 0 0 10px rgba(239, 68, 68, 0.7); }
}

@keyframes lco-nudge-in {
Expand Down Expand Up @@ -237,9 +237,9 @@ export const OVERLAY_CSS = `
Instant swap avoids a paint-layer transition on the main thread. */
}

.lco-health-dot--healthy { background: #4ade80; box-shadow: 0 0 4px rgba(74, 222, 128, 0.4); }
.lco-health-dot--degrading { background: #fbbf24; box-shadow: 0 0 4px rgba(251, 191, 36, 0.4); }
.lco-health-dot--critical { background: #f87171; animation: lco-dot-pulse 2s ease-in-out infinite; }
.lco-health-dot--healthy { background: #86efac; box-shadow: 0 0 4px rgba(134, 239, 172, 0.4); }
.lco-health-dot--degrading { background: #f59e0b; box-shadow: 0 0 4px rgba(245, 158, 11, 0.4); }
.lco-health-dot--critical { background: #ef4444; animation: lco-dot-pulse 2s ease-in-out infinite; }

.lco-health-label {
font-size: 10px;
Expand All @@ -248,9 +248,9 @@ export const OVERLAY_CSS = `
/* No transition: color is a paint property; health state changes snap instantly. */
}

.lco-health-label--healthy { color: #4ade80; }
.lco-health-label--degrading { color: #fbbf24; }
.lco-health-label--critical { color: #f87171; }
.lco-health-label--healthy { color: #86efac; }
.lco-health-label--degrading { color: #f59e0b; }
.lco-health-label--critical { color: #ef4444; }
Comment thread
DevanshuNEU marked this conversation as resolved.

.lco-coaching {
font-size: 9px;
Expand Down Expand Up @@ -292,6 +292,30 @@ export const OVERLAY_CSS = `
outline-offset: 2px;
}

/* Critical state: filled button — more urgent than the outline used at degrading */
.lco-start-fresh--critical {
background: #c15f3c;
color: rgba(255, 255, 255, 0.92);
border-color: transparent;
box-shadow: 0 2px 10px rgba(193, 95, 60, 0.35);
}

.lco-start-fresh--critical:hover {
background: #a8522f;
box-shadow: 0 4px 14px rgba(193, 95, 60, 0.45);
}

.lco-start-fresh--critical:active {
background: #944829;
transform: scale(0.97);
box-shadow: 0 1px 6px rgba(193, 95, 60, 0.3);
Comment thread
DevanshuNEU marked this conversation as resolved.
}

.lco-start-fresh--critical:focus-visible {
outline: 2px solid #c15f3c;
outline-offset: 2px;
}

/* ── Progress bars ── */

.lco-bar-row {
Expand Down Expand Up @@ -331,9 +355,9 @@ export const OVERLAY_CSS = `
box-shadow: 0 0 6px var(--lco-warn-glow);
}

.lco-bar-fill--healthy { background: #4ade80; box-shadow: 0 0 6px rgba(74, 222, 128, 0.3); }
.lco-bar-fill--degrading { background: #fbbf24; box-shadow: 0 0 6px rgba(251, 191, 36, 0.3); }
.lco-bar-fill--critical { background: #f87171; box-shadow: 0 0 6px rgba(248, 113, 113, 0.3); }
.lco-bar-fill--healthy { background: #86efac; box-shadow: 0 0 6px rgba(134, 239, 172, 0.3); }
.lco-bar-fill--degrading { background: #f59e0b; box-shadow: 0 0 6px rgba(245, 158, 11, 0.3); }
.lco-bar-fill--critical { background: #ef4444; box-shadow: 0 0 6px rgba(239, 68, 68, 0.3); }

.lco-bar-fill.lco-streaming {
animation: lco-bar-pulse 1.2s ease-in-out infinite;
Expand Down Expand Up @@ -364,7 +388,7 @@ export const OVERLAY_CSS = `
animation: lco-nudge-in 0.2s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

.lco-nudge--info { background: rgba(99, 179, 237, 0.09); border-left: 2px solid #63b3ed; }
.lco-nudge--info { background: rgba(107, 140, 174, 0.09); border-left: 2px solid #6b8cae; } /* desaturated steel from terracotta undertones — no pure blue in palette */
.lco-nudge--warning { background: rgba(245, 158, 11, 0.11); border-left: 2px solid #f59e0b; }
.lco-nudge--critical { background: rgba(239, 68, 68, 0.11); border-left: 2px solid #ef4444; }

Expand Down Expand Up @@ -415,7 +439,8 @@ export const OVERLAY_CSS = `
.lco-bar-fill { transition: none; }
.lco-bar-fill.lco-streaming { animation: none; }
.lco-health-dot--critical { animation: none; }
.lco-start-fresh { transition: none; }
.lco-start-fresh,
.lco-start-fresh--critical { transition: none; }
.lco-nudge,
.lco-nudge--exiting { animation: none; }
.lco-nudge-dismiss { transition: none; }
Expand Down
23 changes: 21 additions & 2 deletions ui/overlay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export function createOverlay(): OverlayHandle {
let elNudgeDismiss: HTMLButtonElement | null = null;
let elHealth: HTMLElement | null = null;
let elCostMini: HTMLElement | null = null;
let elHealthDotMini: HTMLElement | null = null;
let nudgeHideTimer: ReturnType<typeof setTimeout> | null = null;
let elDraftRow: HTMLElement | null = null;
let elDraftValue: HTMLElement | null = null;
Expand Down Expand Up @@ -80,8 +81,15 @@ export function createOverlay(): OverlayHandle {
costMini.style.display = 'none'; // shown only when collapsed
elCostMini = costMini;

// Health dot shown in collapsed pill — sole health signal when minimized.
Comment thread
DevanshuNEU marked this conversation as resolved.
const healthDotMini = document.createElement('span');
healthDotMini.className = 'lco-health-dot';
healthDotMini.style.display = 'none';
elHealthDotMini = healthDotMini;

header.appendChild(title);
header.appendChild(costMini);
header.appendChild(healthDotMini);
widget.appendChild(header);

// Body — collapsible
Expand Down Expand Up @@ -259,6 +267,7 @@ export function createOverlay(): OverlayHandle {
collapsed = !collapsed;
body.classList.toggle('lco-body--collapsed', collapsed);
costMini.style.display = collapsed ? '' : 'none';
healthDotMini.style.display = collapsed ? '' : 'none';
widget.classList.toggle('lco-collapsed', collapsed);
});
}
Expand Down Expand Up @@ -359,9 +368,11 @@ export function createOverlay(): OverlayHandle {
}

// "Start fresh" button: visible when Degrading or Critical.
// Critical gets a filled variant; degrading keeps the outline.
if (elStartFresh) {
const showFresh = state.health !== null && state.health.level !== 'healthy';
elStartFresh.style.display = showFresh ? '' : 'none';
elStartFresh.classList.toggle('lco-start-fresh--critical', state.health?.level === 'critical');
}

if (elLimitRow && elLimitFill && elLimitLabel) {
Expand Down Expand Up @@ -393,8 +404,16 @@ export function createOverlay(): OverlayHandle {
}
}

if (elCostMini && state.lastRequest) {
elCostMini.textContent = fmtCost(state.lastRequest.cost);
// Collapsed pill: show session total (not last reply cost).
// Cost color stays terra cotta regardless of health state — dot is the sole health signal.
if (elCostMini && state.session.requestCount > 0) {
elCostMini.textContent = fmtCost(state.session.totalCost);
}
Comment thread
DevanshuNEU marked this conversation as resolved.

// Collapsed health dot: mirrors the expanded dot color.
if (elHealthDotMini) {
const level = state.health?.level ?? 'healthy';
elHealthDotMini.className = `lco-health-dot lco-health-dot--${level}`;
}
}

Expand Down
Loading