// ============================================================================ // OpenClaw Control Center — M3 Tactical Dark Theme // ============================================================================ // Material Design 3 theming with custom dark palette per design spec. // Section 5.1: Color Palette, Section 5.2: Typography // ============================================================================ @use '@angular/material' as mat; // --------------------------------------------------------------------------- // M3 Theme Definition // --------------------------------------------------------------------------- // Using mat.define-theme() with custom color tokens to match the tactical // dark palette. Angular Material 19+ uses the new theming API. // --------------------------------------------------------------------------- $dark-theme: mat.define-theme(( color: ( theme-type: dark, primary: mat.$cyan-palette, tertiary: mat.$violet-palette, ), typography: ( brand-family: 'Inter, Roboto, sans-serif', plain-family: 'Inter, Roboto, sans-serif', bold-weight: 600, medium-weight: 500, regular-weight: 400, ), density: ( scale: 0, ), )); // --------------------------------------------------------------------------- // Apply theme to :root // --------------------------------------------------------------------------- html { height: 100%; @include mat.theme($dark-theme); color-scheme: dark; } // --------------------------------------------------------------------------- // Custom CSS Custom Properties — Status Colors // --------------------------------------------------------------------------- // Per spec Section 5.1 "Status Colors (Semantic — outside M3 tonal system)" // These are NOT part of the M3 tonal palette; they are semantic overrides. // --------------------------------------------------------------------------- :root { // --- Tactical Dark Mode color palette (CUB-47) --- --color-surface: #0F172A; --color-surface-light: #1E293B; --color-primary: #38BDF8; --color-secondary: #2DD4BF; --color-accent: #A78BFA; --color-danger: #F87171; --color-text-primary: #FFFFFF; --color-text-secondary: #94A3B8; --color-border: #334155; // --- Status colors --- --status-active: #38BDF8; --status-idle: #2DD4BF; --status-thinking: #A78BFA; --status-error: #F87171; --status-offline: #64748B; // --- Status background tints (12% opacity) --- --status-active-bg: rgba(56, 189, 248, 0.12); --status-idle-bg: rgba(45, 212, 191, 0.12); --status-thinking-bg: rgba(167, 139, 250, 0.12); --status-error-bg: rgba(248, 113, 113, 0.12); // --- Surface overrides (tactical dark palette) --- --cc-background: #0D0F12; --cc-surface: #13161A; --cc-surface-container: #1C2027; --cc-surface-container-high: #252B33; --cc-on-surface: #E2E8F0; --cc-on-surface-variant: #8A9BB0; --cc-outline: #2D3748; // --- Mono font stack --- --cc-font-mono: 'Roboto Mono', 'Cascadia Code', 'Fira Code', monospace; // --- Layout constants --- --cc-nav-rail-collapsed-width: 72px; --cc-nav-rail-expanded-width: 256px; --cc-header-height: 64px; --cc-bottom-nav-height: 80px; --cc-card-border-radius: 16px; --cc-card-min-width: 320px; --cc-card-gap: 16px; --cc-card-padding: 20px; --cc-section-padding: 24px; --cc-spacing-unit: 8px; } // --------------------------------------------------------------------------- // Global Body Styles // --------------------------------------------------------------------------- body { background-color: var(--color-surface); color: var(--cc-on-surface); font-family: 'Inter', 'Roboto', sans-serif; margin: 0; height: 100%; min-height: 100vh; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } // --------------------------------------------------------------------------- // M3 Surface Overrides // --------------------------------------------------------------------------- // Override M3 surface tokens to match our tactical dark palette // --------------------------------------------------------------------------- :root { // Override M3 system color tokens to match custom palette --mat-sys-surface: var(--cc-surface); --mat-sys-surface-container: var(--cc-surface-container); --mat-sys-surface-container-high: var(--cc-surface-container-high); --mat-sys-on-surface: var(--cc-on-surface); --mat-sys-on-surface-variant: var(--cc-on-surface-variant); --mat-sys-outline: var(--cc-outline); --mat-sys-background: var(--cc-background); } // --------------------------------------------------------------------------- // Typography Helpers // --------------------------------------------------------------------------- .text-mono { font-family: var(--cc-font-mono); font-size: 13px; font-weight: 400; letter-spacing: 0.02em; } // --------------------------------------------------------------------------- // Status Dot Pulse Animations // --------------------------------------------------------------------------- // Per spec Section 7.5: Animation Specs // --------------------------------------------------------------------------- @keyframes pulse-active { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.7; transform: scale(1.15); } } @keyframes pulse-error { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } } @keyframes pulse-thinking { 0%, 100% { opacity: 0.8; } 50% { opacity: 0.4; } } // --------------------------------------------------------------------------- // Utility Classes // --------------------------------------------------------------------------- .status-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; &--active { background-color: var(--status-active); animation: pulse-active 2s ease-in-out infinite; } &--idle { background-color: var(--status-idle); } &--thinking { background-color: var(--status-thinking); animation: pulse-thinking 3s ease-in-out infinite; } &--error { background-color: var(--status-error); animation: pulse-error 0.8s ease-in-out infinite; } &--offline { background-color: var(--status-offline); } } // --------------------------------------------------------------------------- // Accessibility: Reduced Motion // --------------------------------------------------------------------------- @media (prefers-reduced-motion: reduce) { .status-dot--active, .status-dot--error, .status-dot--thinking { animation: none; } } // --------------------------------------------------------------------------- // Scrollbar Styling (Tactical Dark) // --------------------------------------------------------------------------- ::-webkit-scrollbar { width: 6px; height: 6px; } ::-webkit-scrollbar-track { background: var(--cc-surface); } ::-webkit-scrollbar-thumb { background: var(--cc-outline); border-radius: 3px; &:hover { background: var(--cc-on-surface-variant); } }