From 478ef8a28e477cdb0a87905a3364ec30346c93f5 Mon Sep 17 00:00:00 2001 From: Hephaestus Date: Sat, 23 May 2026 10:31:24 +0200 Subject: [PATCH] =?UTF-8?q?fix(dashboard):=20complete=20CSS=20variable=20m?= =?UTF-8?q?igration=20=E2=80=94=20remaining=20color=20families?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Round 2 of the design token migration covering all remaining raw Tailwind color families: emerald/green, rose/red, amber, blue, purple. Adds 5 new semantic glow tokens to the dark theme: - --color-success-glow (emerald-400 for text on dark surfaces) - --color-danger-glow (red-300 for text on dark surfaces) - --color-warning-glow (amber-300 for text on dark surfaces) - --color-info-glow (blue-300 for text on dark surfaces) - --color-accent-purple-glow (purple-300 for text on dark surfaces) Plus corresponding light-mode variants for theme switching. 33 files changed — zero raw Tailwind color classes remaining in dashboard production code (pages, components, types). --- dashboard/src/components/ConfirmDialog.tsx | 2 +- .../src/components/CreateSessionModal.tsx | 2 +- dashboard/src/components/Layout.tsx | 4 +- .../src/components/agents/AgentBadge.tsx | 10 +-- .../approvals/ApprovalNotification.tsx | 2 +- .../components/overview/HomeStatusPanel.tsx | 12 ++-- .../src/components/overview/MetricCards.tsx | 6 +- .../src/components/overview/RealtimeBadge.tsx | 2 +- .../components/overview/SessionMobileCard.tsx | 6 +- .../src/components/overview/SessionTable.tsx | 6 +- .../overview/VirtualizedSessionList.tsx | 4 +- .../pipeline/PipelineStatusBadge.tsx | 2 +- .../components/session/AcpApprovalModal.tsx | 2 +- .../components/session/AuditTrailPanel.tsx | 6 +- .../components/session/ContextWindowMeter.tsx | 4 +- .../src/components/session/DiffViewer.tsx | 6 +- .../components/session/DriverControlBar.tsx | 2 +- .../components/session/PauseControlBar.tsx | 2 +- .../session/SessionTimelineView.tsx | 2 +- .../src/components/shared/EmptyState.tsx | 2 +- .../src/components/shared/ErrorBoundary.tsx | 4 +- .../shared/LastUpdatedIndicator.tsx | 6 +- .../components/shared/LiveStatusIndicator.tsx | 6 +- .../src/components/shared/StaleDataBanner.tsx | 2 +- .../src/components/tour/FirstRunTour.tsx | 6 +- dashboard/src/index.css | 70 +++++++++++-------- dashboard/src/pages/AnalyticsPage.tsx | 6 +- dashboard/src/pages/AuditPage.tsx | 34 ++++----- dashboard/src/pages/AuthKeysPage.tsx | 10 +-- dashboard/src/pages/CostPage.tsx | 4 +- dashboard/src/pages/MetricsPage.tsx | 4 +- dashboard/src/pages/SessionHistoryPage.tsx | 8 +-- dashboard/src/pages/SettingsPage.tsx | 2 +- dashboard/src/pages/TemplatesPage.tsx | 4 +- dashboard/src/types/acp-approval.ts | 6 +- dashboard/src/types/acp-driver-observer.ts | 6 +- 36 files changed, 136 insertions(+), 126 deletions(-) diff --git a/dashboard/src/components/ConfirmDialog.tsx b/dashboard/src/components/ConfirmDialog.tsx index 0d8f03ed0..cd92e2dad 100644 --- a/dashboard/src/components/ConfirmDialog.tsx +++ b/dashboard/src/components/ConfirmDialog.tsx @@ -19,7 +19,7 @@ interface ConfirmDialogProps { const VARIANT_STYLES = { danger: { confirm: - 'bg-[var(--color-danger)]/10 hover:bg-[var(--color-danger)]/20 text-red-300 border border-[var(--color-danger)]/30', + 'bg-[var(--color-danger)]/10 hover:bg-[var(--color-danger)]/20 text-[var(--color-danger-glow)] border border-[var(--color-danger)]/30', }, warning: { confirm: diff --git a/dashboard/src/components/CreateSessionModal.tsx b/dashboard/src/components/CreateSessionModal.tsx index ee3f4b7cd..f1276ddde 100644 --- a/dashboard/src/components/CreateSessionModal.tsx +++ b/dashboard/src/components/CreateSessionModal.tsx @@ -629,7 +629,7 @@ export default function CreateSessionModal({ open, onClose }: CreateSessionModal
{batchResult.created > 0 && ( - + {batchResult.created} created )} diff --git a/dashboard/src/components/Layout.tsx b/dashboard/src/components/Layout.tsx index 52b6982d3..ad1a74955 100644 --- a/dashboard/src/components/Layout.tsx +++ b/dashboard/src/components/Layout.tsx @@ -559,7 +559,7 @@ export default function Layout() {
{/* PREVIEW badge — hidden on very small screens */} - + PREVIEW @@ -632,7 +632,7 @@ export default function Layout() { )} {updateCheckError && ( -
+
Update check failed
)} diff --git a/dashboard/src/components/agents/AgentBadge.tsx b/dashboard/src/components/agents/AgentBadge.tsx index f231dd646..7a08cac33 100644 --- a/dashboard/src/components/agents/AgentBadge.tsx +++ b/dashboard/src/components/agents/AgentBadge.tsx @@ -12,12 +12,12 @@ import { getAgentMeta } from "./agent-registry"; /** Tailwind color → dark-theme badge classes. */ const COLOR_CLASSES: Record = { - purple: "bg-purple-500/15 text-purple-400 border-purple-500/25", - green: "bg-emerald-500/15 text-emerald-400 border-emerald-500/25", - blue: "bg-blue-500/15 text-blue-400 border-blue-500/25", - amber: "bg-[var(--color-warning)]/15 text-amber-400 border-[var(--color-warning)]/25", + purple: "bg-[var(--color-accent-purple)]/15 text-[var(--color-accent-purple-glow)] border-[var(--color-accent-purple)]/25", + green: "bg-[var(--color-success)]/15 text-[var(--color-success-glow)] border-[var(--color-success)]/25", + blue: "bg-[var(--color-info)]/15 text-[var(--color-info-glow)] border-[var(--color-info)]/25", + amber: "bg-[var(--color-warning)]/15 text-[var(--color-warning-glow)] border-[var(--color-warning)]/25", cyan: "bg-[var(--color-accent-cyan)]/15 text-[var(--color-accent-cyan-glow)] border-[var(--color-accent-cyan)]/25", - rose: "bg-rose-500/15 text-rose-400 border-rose-500/25", + rose: "bg-[var(--color-danger)]/15 text-[var(--color-danger-glow)] border-[var(--color-danger)]/25", gray: "bg-gray-500/15 text-gray-400 border-gray-500/25", }; diff --git a/dashboard/src/components/approvals/ApprovalNotification.tsx b/dashboard/src/components/approvals/ApprovalNotification.tsx index df12d79d1..542a8ab2a 100644 --- a/dashboard/src/components/approvals/ApprovalNotification.tsx +++ b/dashboard/src/components/approvals/ApprovalNotification.tsx @@ -68,7 +68,7 @@ export function ApprovalBadge() { return ( 1 ? "s" : ""}`} title={`${count} session${count > 1 ? "s" : ""} awaiting approval`} > diff --git a/dashboard/src/components/overview/HomeStatusPanel.tsx b/dashboard/src/components/overview/HomeStatusPanel.tsx index ed5226556..3f96517bc 100644 --- a/dashboard/src/components/overview/HomeStatusPanel.tsx +++ b/dashboard/src/components/overview/HomeStatusPanel.tsx @@ -42,19 +42,19 @@ function StatusCard({ label, value, detail, tone, icon, actionButton }: StatusCa value: 'text-[var(--color-accent-cyan-glow)]', }, green: { - border: 'border-emerald-500/20', - icon: 'text-emerald-400', - value: 'text-emerald-300', + border: 'border-[var(--color-success)]/20', + icon: 'text-[var(--color-success-glow)]', + value: 'text-[var(--color-success-glow)]', }, amber: { border: 'border-[var(--color-warning)]/20', icon: 'text-[var(--color-warning)]', - value: 'text-amber-300', + value: 'text-[var(--color-warning-glow)]', }, red: { border: 'border-[var(--color-danger)]/40 bg-[var(--color-danger)]/10 shadow-[0_0_20px_rgba(239,68,68,0.15),0_20px_40px_-15px_rgba(0,0,0,0.8)] ring-1 ring-inset ring-[var(--color-danger)]/20', icon: 'text-[var(--color-danger)]', - value: 'text-red-300', + value: 'text-[var(--color-danger-glow)]', }, }; @@ -89,7 +89,7 @@ function StatusCard({ label, value, detail, tone, icon, actionButton }: StatusCa type="button" onClick={actionButton.onClick} className={`ml-11 sm:ml-14 inline-flex items-center gap-1.5 text-[10px] font-bold uppercase tracking-widest transition-colors ${ - tone === 'red' ? 'text-[var(--color-danger)] hover:text-red-300' : 'text-[var(--color-warning)] hover:text-amber-300' + tone === 'red' ? 'text-[var(--color-danger)] hover:text-[var(--color-danger-glow)]' : 'text-[var(--color-warning)] hover:text-[var(--color-warning-glow)]' }`} > diff --git a/dashboard/src/components/overview/MetricCards.tsx b/dashboard/src/components/overview/MetricCards.tsx index a283508a9..8cab05d2d 100644 --- a/dashboard/src/components/overview/MetricCards.tsx +++ b/dashboard/src/components/overview/MetricCards.tsx @@ -86,7 +86,7 @@ export default function MetricCards() { if (loadError && !metrics && !health) { return ( -
+
{loadError}
); @@ -157,7 +157,7 @@ export default function MetricCards() {

{failedSessions}

View Error Logs @@ -190,7 +190,7 @@ export default function MetricCards() {
{promptsDelivered > 0 && (
-

{promptsDelivered}

+

{promptsDelivered}

Delivered

)} diff --git a/dashboard/src/components/overview/RealtimeBadge.tsx b/dashboard/src/components/overview/RealtimeBadge.tsx index 0231b509c..904fc800f 100644 --- a/dashboard/src/components/overview/RealtimeBadge.tsx +++ b/dashboard/src/components/overview/RealtimeBadge.tsx @@ -11,7 +11,7 @@ const LABELS: Record = { export default function RealtimeBadge({ mode, message }: RealtimeBadgeProps) { return ( {LABELS[mode]} diff --git a/dashboard/src/components/overview/SessionMobileCard.tsx b/dashboard/src/components/overview/SessionMobileCard.tsx index 2382ffc0a..a640d17d6 100644 --- a/dashboard/src/components/overview/SessionMobileCard.tsx +++ b/dashboard/src/components/overview/SessionMobileCard.tsx @@ -65,7 +65,7 @@ export const SessionMobileCard = memo(function SessionMobileCard({ onClick={(e) => onApprove(e, session.id)} disabled={currentAction === 'approve'} aria-label={`Approve session ${formatSessionName(session.displayName, session.id.slice(0, 8))}`} - className="flex min-h-[44px] min-w-[44px] items-center justify-center rounded-md bg-green-900/30 p-2 text-[var(--color-success)] transition-colors hover:bg-green-900/50 disabled:pointer-events-none disabled:opacity-40" + className="flex min-h-[44px] min-w-[44px] items-center justify-center rounded-md bg-[var(--color-success)]/15 p-2 text-[var(--color-success)] transition-colors hover:bg-[var(--color-success)]/25 disabled:pointer-events-none disabled:opacity-40" title="Approve" > @@ -84,7 +84,7 @@ export const SessionMobileCard = memo(function SessionMobileCard({ onClick={(e) => onKill(e, session.id)} disabled={currentAction === 'kill'} aria-label={`Kill session ${formatSessionName(session.displayName, session.id.slice(0, 8))}`} - className="flex min-h-[44px] min-w-[44px] items-center justify-center rounded-md bg-red-900/30 p-2 text-[var(--color-danger)] transition-colors hover:bg-red-900/50 disabled:pointer-events-none disabled:opacity-40" + className="flex min-h-[44px] min-w-[44px] items-center justify-center rounded-md bg-[var(--color-danger)]/15 p-2 text-[var(--color-danger)] transition-colors hover:bg-[var(--color-danger)]/25 disabled:pointer-events-none disabled:opacity-40" title="Kill" > @@ -101,7 +101,7 @@ export const SessionMobileCard = memo(function SessionMobileCard({ )} {session.permissionMode && session.permissionMode !== 'default' ? ( - + {session.permissionMode} ) : ( diff --git a/dashboard/src/components/overview/SessionTable.tsx b/dashboard/src/components/overview/SessionTable.tsx index 2c9e3504e..a49750aac 100644 --- a/dashboard/src/components/overview/SessionTable.tsx +++ b/dashboard/src/components/overview/SessionTable.tsx @@ -478,7 +478,7 @@ export default function SessionTable({ maxRows }: SessionTableProps = {}) { return (
-

{loadError}

+

{loadError}

@@ -652,7 +652,7 @@ export default function SessionTable({ maxRows }: SessionTableProps = {}) { onClick={() => runBulkAction('kill')} disabled={bulkAction !== null} aria-label={`Kill ${selectedIds.length} selected session${selectedIds.length === 1 ? '' : 's'}`} - className="min-h-[44px] rounded-md bg-red-900/30 px-3 py-2 text-sm font-medium text-red-300 transition-colors hover:bg-red-900/50 disabled:pointer-events-none disabled:opacity-40" + className="min-h-[44px] rounded-md bg-[var(--color-danger)]/15 px-3 py-2 text-sm font-medium text-[var(--color-danger-glow)] transition-colors hover:bg-[var(--color-danger)]/25 disabled:pointer-events-none disabled:opacity-40" > Kill Selected diff --git a/dashboard/src/components/overview/VirtualizedSessionList.tsx b/dashboard/src/components/overview/VirtualizedSessionList.tsx index b58f27528..60e9803c9 100644 --- a/dashboard/src/components/overview/VirtualizedSessionList.tsx +++ b/dashboard/src/components/overview/VirtualizedSessionList.tsx @@ -119,7 +119,7 @@ function ApproveButton({ onClick={(e) => onApprove(e, session.id)} disabled={currentAction === 'approve'} aria-label={`Approve session ${formatSessionName(session.displayName, session.id.slice(0, 8))}`} - className="flex min-h-[44px] min-w-[44px] items-center justify-center rounded-md bg-green-900/30 text-xs font-medium text-[var(--color-success)] transition-colors hover:bg-green-900/50 disabled:pointer-events-none disabled:opacity-40" + className="flex min-h-[44px] min-w-[44px] items-center justify-center rounded-md bg-[var(--color-success)]/15 text-xs font-medium text-[var(--color-success)] transition-colors hover:bg-[var(--color-success)]/25 disabled:pointer-events-none disabled:opacity-40" title="Approve" > @@ -219,7 +219,7 @@ function VirtualizedRow(props: {
{session.permissionMode && session.permissionMode !== 'default' ? ( - + {session.permissionMode} diff --git a/dashboard/src/components/pipeline/PipelineStatusBadge.tsx b/dashboard/src/components/pipeline/PipelineStatusBadge.tsx index 64b15f9f8..7885d9bd6 100644 --- a/dashboard/src/components/pipeline/PipelineStatusBadge.tsx +++ b/dashboard/src/components/pipeline/PipelineStatusBadge.tsx @@ -8,7 +8,7 @@ interface PipelineStatusBadgeProps { const STATUS_STYLES: Record = { running: 'bg-[var(--color-cta-bg)]/10 text-[var(--color-accent-cyan)] border-[var(--color-accent-cyan)]/30', - completed: 'bg-emerald-400/10 text-emerald-400 border-emerald-400/30', + completed: 'bg-[var(--color-success)]/10 text-[var(--color-success-glow)] border-[var(--color-success)]/30', failed: 'bg-[var(--color-danger)]/10 text-[var(--color-danger)] border-[var(--color-danger)]/30', pending: 'bg-[var(--color-void-lighter)] text-[var(--color-text-muted)] border-[var(--color-void-lighter)]', }; diff --git a/dashboard/src/components/session/AcpApprovalModal.tsx b/dashboard/src/components/session/AcpApprovalModal.tsx index a809eeee5..660c88193 100644 --- a/dashboard/src/components/session/AcpApprovalModal.tsx +++ b/dashboard/src/components/session/AcpApprovalModal.tsx @@ -160,7 +160,7 @@ export function AcpApprovalModal({
{error} {onClearError && ( - )} diff --git a/dashboard/src/components/session/AuditTrailPanel.tsx b/dashboard/src/components/session/AuditTrailPanel.tsx index ee3fd081d..787eb829a 100644 --- a/dashboard/src/components/session/AuditTrailPanel.tsx +++ b/dashboard/src/components/session/AuditTrailPanel.tsx @@ -60,9 +60,9 @@ function actionColor(action: string): string { function actionBg(action: string): string { const a = action.toLowerCase(); if (a.includes('approve') || a.includes('permission_granted')) - return 'bg-green-950/30 border-green-900/30'; + return 'bg-[var(--color-success)]/10 border-[var(--color-success)]/20'; if (a.includes('reject') || a.includes('deny') || a.includes('permission_denied')) - return 'bg-red-950/30 border-red-900/30'; + return 'bg-[var(--color-danger)]/10 border-[var(--color-danger)]/20'; if (a.includes('prompt') || a.includes('request')) return 'bg-[var(--color-warning)]/30 border-[var(--color-warning)]/30'; return 'bg-[var(--color-surface-strong)] border-[var(--color-border)]'; @@ -83,7 +83,7 @@ export function AuditTrailPanel({ records, loading, error }: AuditTrailPanelProp if (error) { return ( -
+
Failed to load audit trail: {error}
); diff --git a/dashboard/src/components/session/ContextWindowMeter.tsx b/dashboard/src/components/session/ContextWindowMeter.tsx index a2de91a11..5891bce42 100644 --- a/dashboard/src/components/session/ContextWindowMeter.tsx +++ b/dashboard/src/components/session/ContextWindowMeter.tsx @@ -38,14 +38,14 @@ function formatTokens(n: number): string { } function getUsageColor(percentage: number): string { - if (percentage < 0.5) return 'bg-emerald-500'; + if (percentage < 0.5) return 'bg-[var(--color-success)]'; if (percentage < 0.75) return 'bg-[var(--color-warning)]'; if (percentage < 0.9) return 'bg-[var(--color-warning)]'; return 'bg-[var(--color-danger)]'; } function getUsageTextColor(percentage: number): string { - if (percentage < 0.5) return 'text-emerald-400'; + if (percentage < 0.5) return 'text-[var(--color-success-glow)]'; if (percentage < 0.75) return 'text-[var(--color-warning)]'; if (percentage < 0.9) return 'text-[var(--color-warning)]'; return 'text-[var(--color-danger)]'; diff --git a/dashboard/src/components/session/DiffViewer.tsx b/dashboard/src/components/session/DiffViewer.tsx index fd5258bfa..010dee7cf 100644 --- a/dashboard/src/components/session/DiffViewer.tsx +++ b/dashboard/src/components/session/DiffViewer.tsx @@ -198,7 +198,7 @@ export function DiffViewer({ entries, isLoading }: DiffViewerProps) { {selectedChange.type === 'edit' ? 'modified' : 'created'} @@ -223,7 +223,7 @@ function DiffContent({ change }: { change: FileChange }) { key={i} className={`flex ${ line.type === 'add' - ? 'bg-emerald-500/10' + ? 'bg-[var(--color-success)]/10' : line.type === 'remove' ? 'bg-[var(--color-danger)]/10' : '' @@ -234,7 +234,7 @@ function DiffContent({ change }: { change: FileChange }) { ✕ diff --git a/dashboard/src/components/session/PauseControlBar.tsx b/dashboard/src/components/session/PauseControlBar.tsx index 0cd78f9f2..b68045bc7 100644 --- a/dashboard/src/components/session/PauseControlBar.tsx +++ b/dashboard/src/components/session/PauseControlBar.tsx @@ -91,7 +91,7 @@ export function PauseControlBar({ {onClearError && (
-

+

Something went wrong

@@ -56,7 +56,7 @@ export class ErrorBoundary extends Component {

@@ -229,7 +229,7 @@ export function FirstRunTour({ onComplete }: FirstRunTourProps) { complete: { title: 'Tour complete!', description: 'You now know the basics: create sessions, handle permissions, and manage cleanup. Happy orchestrating!', - icon: , + icon: , }, }; @@ -286,7 +286,7 @@ export function FirstRunTour({ onComplete }: FirstRunTourProps) {

{error && ( -
+
{error}
)} diff --git a/dashboard/src/index.css b/dashboard/src/index.css index bc4609ed2..361cb0b08 100644 --- a/dashboard/src/index.css +++ b/dashboard/src/index.css @@ -87,6 +87,11 @@ --color-metrics-purple: #8b5cf6; --color-success-bg: #064e3b; --color-error-bg: #4c1d1f; + --color-success-glow: #4ade80; /* emerald-400 — text on dark surfaces */ + --color-danger-glow: #fca5a5; /* red-300 — text on dark surfaces */ + --color-warning-glow: #fcd34d; /* amber-300 — text on dark surfaces */ + --color-info-glow: #93c5fd; /* blue-300 — text on dark surfaces */ + --color-accent-purple-glow: #c4b5fd; /* purple-300 — text on dark surfaces */ /* ------------------------------------------------------------------ */ /* Motion tokens (mirror of dashboard/src/design/tokens.ts). */ @@ -205,6 +210,11 @@ --color-success: #047857; /* emerald-700 on white ≈ 6.3:1 */ --color-warning: #92400e; /* amber-800 on tinted light surfaces clears AA */ --color-danger: #dc2626; /* red-600 on white ≈ 4.8:1 */ + --color-success-glow: #059669; /* emerald-600 on white */ + --color-danger-glow: #b91c1c; /* red-700 on white */ + --color-warning-glow: #92400e; /* amber-800 on white */ + --color-info-glow: #2563eb; /* blue-600 on white */ + --color-accent-purple-glow: #7c3aed; /* purple-600 on white */ /* Primary CTA: emerald-600 on white ≈ 4.6:1 (AA normal). */ --color-cta-bg: #059669; @@ -615,23 +625,23 @@ body::before { [data-theme="light-aaa"] .text-cyan-400 { color: var(--color-accent-cyan) !important; } -[data-theme="light"] .text-emerald-300, -[data-theme="light"] .text-emerald-400, +[data-theme="light"] .text-[var(--color-success-glow)], +[data-theme="light"] .text-[var(--color-success-glow)], [data-theme="light"] .text-green-400, -[data-theme="light-paper"] .text-emerald-300, -[data-theme="light-paper"] .text-emerald-400, +[data-theme="light-paper"] .text-[var(--color-success-glow)], +[data-theme="light-paper"] .text-[var(--color-success-glow)], [data-theme="light-paper"] .text-green-400, -[data-theme="light-aaa"] .text-emerald-300, -[data-theme="light-aaa"] .text-emerald-400, +[data-theme="light-aaa"] .text-[var(--color-success-glow)], +[data-theme="light-aaa"] .text-[var(--color-success-glow)], [data-theme="light-aaa"] .text-green-400 { color: var(--color-success) !important; } -[data-theme="light"] .text-amber-300, -[data-theme="light"] .text-amber-400, -[data-theme="light-paper"] .text-amber-300, -[data-theme="light-paper"] .text-amber-400, -[data-theme="light-aaa"] .text-amber-300, -[data-theme="light-aaa"] .text-amber-400 { +[data-theme="light"] .text-[var(--color-warning-glow)], +[data-theme="light"] .text-[var(--color-warning-glow)], +[data-theme="light-paper"] .text-[var(--color-warning-glow)], +[data-theme="light-paper"] .text-[var(--color-warning-glow)], +[data-theme="light-aaa"] .text-[var(--color-warning-glow)], +[data-theme="light-aaa"] .text-[var(--color-warning-glow)] { color: var(--color-warning) !important; } /* ------------------------------------------------------------------ @@ -640,14 +650,14 @@ body::before { * amber-200 (#fde68a) has ~1.4:1 contrast on white — fails WCAG AA. * bg-white/5 and border-white/5 are invisible on light backgrounds. * ------------------------------------------------------------------ */ -[data-theme="light"] .text-amber-200, -[data-theme="light-paper"] .text-amber-200, -[data-theme="light-aaa"] .text-amber-200 { +[data-theme="light"] .text-[var(--color-warning-glow)], +[data-theme="light-paper"] .text-[var(--color-warning-glow)], +[data-theme="light-aaa"] .text-[var(--color-warning-glow)] { color: var(--color-warning) !important; } -[data-theme="light"] .text-amber-200\/80, -[data-theme="light-paper"] .text-amber-200\/80, -[data-theme="light-aaa"] .text-amber-200\/80 { +[data-theme="light"] .text-[var(--color-warning-glow)]\/80, +[data-theme="light-paper"] .text-[var(--color-warning-glow)]\/80, +[data-theme="light-aaa"] .text-[var(--color-warning-glow)]\/80 { color: var(--color-warning) !important; } [data-theme="light"] .border-amber-500\/20, @@ -799,22 +809,22 @@ body::before { * fail WCAG contrast on light backgrounds. * Placed AFTER body::before closes so rules are top-level. * ------------------------------------------------------------------ */ -[data-theme="light"] .text-rose-300, -[data-theme="light"] .text-rose-400, -[data-theme="light-paper"] .text-rose-300, -[data-theme="light-paper"] .text-rose-400, -[data-theme="light-aaa"] .text-rose-300, -[data-theme="light-aaa"] .text-rose-400 { +[data-theme="light"] .text-[var(--color-danger-glow)], +[data-theme="light"] .text-[var(--color-danger-glow)], +[data-theme="light-paper"] .text-[var(--color-danger-glow)], +[data-theme="light-paper"] .text-[var(--color-danger-glow)], +[data-theme="light-aaa"] .text-[var(--color-danger-glow)], +[data-theme="light-aaa"] .text-[var(--color-danger-glow)] { color: var(--color-danger) !important; } -[data-theme="light"] .text-red-300, -[data-theme="light"] .text-red-400, +[data-theme="light"] .text-[var(--color-danger-glow)], +[data-theme="light"] .text-[var(--color-danger-glow)], [data-theme="light"] .text-red-500, -[data-theme="light-paper"] .text-red-300, -[data-theme="light-paper"] .text-red-400, +[data-theme="light-paper"] .text-[var(--color-danger-glow)], +[data-theme="light-paper"] .text-[var(--color-danger-glow)], [data-theme="light-paper"] .text-red-500, -[data-theme="light-aaa"] .text-red-300, -[data-theme="light-aaa"] .text-red-400, +[data-theme="light-aaa"] .text-[var(--color-danger-glow)], +[data-theme="light-aaa"] .text-[var(--color-danger-glow)], [data-theme="light-aaa"] .text-red-500 { color: var(--color-danger) !important; } diff --git a/dashboard/src/pages/AnalyticsPage.tsx b/dashboard/src/pages/AnalyticsPage.tsx index 2ecb865ae..a2e0e0824 100644 --- a/dashboard/src/pages/AnalyticsPage.tsx +++ b/dashboard/src/pages/AnalyticsPage.tsx @@ -221,7 +221,7 @@ export default function AnalyticsPage() {
@@ -533,8 +533,8 @@ function MetricBox({ label, value }: { label: string; value: string }) { function RateBar({ label, value, detail, color }: { label: string; value: number; detail: string; color: 'red' | 'green' }) { const pct = Math.min(value * 100, 100); - const barColor = color === 'red' ? 'bg-[var(--color-danger)]' : 'bg-emerald-500'; - const textColor = color === 'red' ? 'text-[var(--color-danger)]' : 'text-emerald-400'; + const barColor = color === 'red' ? 'bg-[var(--color-danger)]' : 'bg-[var(--color-success)]'; + const textColor = color === 'red' ? 'text-[var(--color-danger)]' : 'text-[var(--color-success-glow)]'; return (
diff --git a/dashboard/src/pages/AuditPage.tsx b/dashboard/src/pages/AuditPage.tsx index 4beddd6a0..c9cc3d3d7 100644 --- a/dashboard/src/pages/AuditPage.tsx +++ b/dashboard/src/pages/AuditPage.tsx @@ -131,13 +131,13 @@ function hasActiveFilters(filters: AuditFilterState): boolean { function actionBadgeClass(action: string): string { if (action.includes('deny') || action.includes('kill')) { - return 'border border-rose-500/30 bg-rose-500/10 text-rose-300'; + return 'border border-[var(--color-danger)]/30 bg-[var(--color-danger)]/10 text-[var(--color-danger-glow)]'; } if (action.includes('reject')) { - return 'border border-[var(--color-warning)]/30 bg-[var(--color-warning)]/10 text-amber-300'; + return 'border border-[var(--color-warning)]/30 bg-[var(--color-warning)]/10 text-[var(--color-warning-glow)]'; } if (action.includes('approve') || action.includes('allowed')) { - return 'border border-emerald-500/30 bg-emerald-500/10 text-emerald-300'; + return 'border border-[var(--color-success)]/30 bg-[var(--color-success)]/10 text-[var(--color-success-glow)]'; } if (action.includes('create') || action.includes('authenticated')) { return 'border border-[var(--color-accent-cyan)]/30 bg-[var(--color-accent-cyan)]/10 text-[var(--color-accent-cyan-glow)]'; @@ -222,8 +222,8 @@ function MetadataField({ function ExportMetadataCard({ result }: { result: AuditExportResult }) { const t = useT(); const integrityTone = result.integrity?.valid - ? 'border-emerald-500/30 bg-emerald-500/10 text-emerald-300' - : 'border-rose-500/30 bg-rose-500/10 text-rose-300'; + ? 'border-[var(--color-success)]/30 bg-[var(--color-success)]/10 text-[var(--color-success-glow)]' + : 'border-[var(--color-danger)]/30 bg-[var(--color-danger)]/10 text-[var(--color-danger-glow)]'; const integrityLabel = result.integrity?.valid ? 'Integrity verified' : 'Integrity check failed'; return ( @@ -259,7 +259,7 @@ function ExportMetadataCard({ result }: { result: AuditExportResult }) {
{result.integrity && result.integrity.brokenAt !== undefined ? ( -

+

Chain verification failed at line {result.integrity.brokenAt}.

) : null} @@ -281,7 +281,7 @@ function ChainIntegrityBadge({ state }: { state: IntegrityState }) { return (
- Integrity check failed: {state.error} + Integrity check failed: {state.error}
); } @@ -297,11 +297,11 @@ function ChainIntegrityBadge({ state }: { state: IntegrityState }) { if (state.integrity && !state.integrity.valid) { return ( -
- - Chain broken +
+ + Chain broken {state.integrity.brokenAt !== undefined && ( - (at seq {state.integrity.brokenAt}) + (at seq {state.integrity.brokenAt}) )}
); @@ -309,9 +309,9 @@ function ChainIntegrityBadge({ state }: { state: IntegrityState }) { if (state.chain) { return ( -
- - +
+ + Chain verified ({state.chain.count} records)
@@ -662,7 +662,7 @@ export default function AuditPage() { disabled={page !== 1} className={`flex min-h-[44px] items-center gap-1.5 rounded border px-3 py-2 text-xs font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50 ${ liveTail - ? 'border-emerald-500/30 bg-emerald-500/10 text-emerald-300 hover:bg-emerald-500/20' + ? 'border-[var(--color-success)]/30 bg-[var(--color-success)]/10 text-[var(--color-success-glow)] hover:bg-[var(--color-success)]/20' : 'border-[var(--color-void-lighter)] bg-[var(--color-void-light)] text-[var(--color-text-primary)] hover:bg-[var(--color-void-lighter)]' }`} aria-label={liveTail ? 'Pause live tail' : 'Start live tail'} @@ -797,10 +797,10 @@ export default function AuditPage() {
{filterError ? ( -

{filterError}

+

{filterError}

) : null} {exportError ? ( -

{exportError}

+

{exportError}

) : null}
diff --git a/dashboard/src/pages/AuthKeysPage.tsx b/dashboard/src/pages/AuthKeysPage.tsx index c7fc36402..ae141097a 100644 --- a/dashboard/src/pages/AuthKeysPage.tsx +++ b/dashboard/src/pages/AuthKeysPage.tsx @@ -285,11 +285,11 @@ export default function AuthKeysPage() { {createdKey ? ( -
+
-

{t('authKeys.storeKeyNow')}

-

+

{t('authKeys.storeKeyNow')}

+

{t('authKeys.secretShownOnce')}

@@ -299,7 +299,7 @@ export default function AuthKeysPage() { setCreatedKey(null); setSecretVisible(false); }} - className="text-xs font-medium text-emerald-200/80 transition-colors hover:text-emerald-200" + className="text-xs font-medium text-[var(--color-success-glow)]/80 transition-colors hover:text-[var(--color-success-glow)]" aria-label={t('authKeys.dismiss')} > {t('authKeys.dismiss')} @@ -401,7 +401,7 @@ export default function AuthKeysPage() { onClick={() => void handleRevoke(key.id, key.name)} disabled={revokingId === key.id} aria-label={`Revoke auth key ${key.name}`} - className="flex min-h-[40px] items-center justify-center gap-2 rounded border border-[var(--color-danger)]/20 bg-[var(--color-danger)]/05 px-3 py-2 text-xs font-medium text-[var(--color-danger)] dark:text-red-300 transition-colors hover:bg-[var(--color-danger)]/10 disabled:cursor-not-allowed disabled:opacity-60" + className="flex min-h-[40px] items-center justify-center gap-2 rounded border border-[var(--color-danger)]/20 bg-[var(--color-danger)]/05 px-3 py-2 text-xs font-medium text-[var(--color-danger)] dark:text-[var(--color-danger-glow)] transition-colors hover:bg-[var(--color-danger)]/10 disabled:cursor-not-allowed disabled:opacity-60" > {revokingId === key.id ? t('authKeys.revoking') : t('authKeys.revoke')} diff --git a/dashboard/src/pages/CostPage.tsx b/dashboard/src/pages/CostPage.tsx index 0009ebbd2..75b47f083 100644 --- a/dashboard/src/pages/CostPage.tsx +++ b/dashboard/src/pages/CostPage.tsx @@ -120,13 +120,13 @@ function BudgetOverview({ dailyData, budgetSettings, navigateToSettings }: Budge
-

{t('cost.budgetAlertSection.title')}

+

{t('cost.budgetAlertSection.title')}

{t('cost.budgetAlertSection.description')}{' '} diff --git a/dashboard/src/pages/MetricsPage.tsx b/dashboard/src/pages/MetricsPage.tsx index 6c516acbc..7fa3b1ee8 100644 --- a/dashboard/src/pages/MetricsPage.tsx +++ b/dashboard/src/pages/MetricsPage.tsx @@ -254,7 +254,7 @@ export default function MetricsPage() {

-

+

Anomalous Sessions ({data.anomalies?.length})

@@ -263,7 +263,7 @@ export default function MetricsPage() {

{data.anomalies.map((a) => (
- + {a.sessionId.slice(0, 12)} diff --git a/dashboard/src/pages/SessionHistoryPage.tsx b/dashboard/src/pages/SessionHistoryPage.tsx index 207cc150d..481c408ce 100644 --- a/dashboard/src/pages/SessionHistoryPage.tsx +++ b/dashboard/src/pages/SessionHistoryPage.tsx @@ -48,8 +48,8 @@ function formatTimestamp(ts?: number): string { } function statusClass(status: SessionHistoryRecord['finalStatus']): string { - if (status === 'active') return 'text-emerald-300 bg-emerald-500/10 border-emerald-500/25'; - if (status === 'killed') return 'text-rose-300 bg-rose-500/10 border-rose-500/25'; + if (status === 'active') return 'text-[var(--color-success-glow)] bg-[var(--color-success)]/10 border-[var(--color-success)]/25'; + if (status === 'killed') return 'text-[var(--color-danger-glow)] bg-[var(--color-danger)]/10 border-[var(--color-danger)]/25'; return 'text-[var(--color-text-muted)] dark:text-[var(--color-text-primary)] bg-[var(--color-void-lighter)]/40 border-[var(--color-void-lighter)]'; } @@ -613,7 +613,7 @@ export default function SessionHistoryPage() { diff --git a/dashboard/src/pages/SettingsPage.tsx b/dashboard/src/pages/SettingsPage.tsx index cb9854444..3ff119d97 100644 --- a/dashboard/src/pages/SettingsPage.tsx +++ b/dashboard/src/pages/SettingsPage.tsx @@ -102,7 +102,7 @@ function SettingsSwitch({ checked, label, onClick }: SettingsSwitchProps) {
) : error ? ( -
+

{t('templates.loadErrorTitle')}

{error}