// ============================================================================ // OpenClaw Control Center — M3 Tactical Dark Theme // ============================================================================ // Main global stylesheet. Imports the design system token modules and // applies the M3 dark theme. All tokens are defined once in // styles/_tokens.scss — SCSS variables and mixins // styles/_css-properties.scss — CSS custom property output // styles/_utilities.scss — utility mixins for components // // Components should @use these modules rather than hardcoding values. // ============================================================================ @use 'styles/tokens' as tokens; @use 'styles/css-properties' as css-props; @use 'styles/utilities' as utils; @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: tokens.$font-family-brand, plain-family: tokens.$font-family-body, bold-weight: tokens.$font-weight-bold, medium-weight: tokens.$font-weight-medium, regular-weight: tokens.$font-weight-regular, ), density: ( scale: 0, ), )); // --------------------------------------------------------------------------- // Apply theme to :root // --------------------------------------------------------------------------- html { height: 100%; @include mat.theme($dark-theme); color-scheme: dark; } // --------------------------------------------------------------------------- // Emit Design System CSS Custom Properties // --------------------------------------------------------------------------- @include css-props.emit-custom-properties; // --------------------------------------------------------------------------- // Global Body Styles // --------------------------------------------------------------------------- body { background-color: var(--cc-surface-darkest); color: var(--cc-on-surface); font-family: var(--cc-font-body); margin: 0; height: 100%; min-height: 100vh; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } // --------------------------------------------------------------------------- // Typography Helpers // --------------------------------------------------------------------------- .text-mono { font-family: var(--cc-font-mono); font-size: tokens.$font-size-body-medium; font-weight: tokens.$font-weight-regular; letter-spacing: tokens.$letter-spacing-mono; } .text-display-large { font-size: tokens.$font-size-display-large; font-weight: tokens.$font-weight-heavy; line-height: tokens.$line-height-tight; letter-spacing: tokens.$letter-spacing-tight; } .text-headline-medium { font-size: tokens.$font-size-headline-medium; font-weight: tokens.$font-weight-bold; line-height: tokens.$line-height-tight; } .text-title-large { font-size: tokens.$font-size-title-large; font-weight: tokens.$font-weight-bold; } .text-title-medium { font-size: tokens.$font-size-title-medium; font-weight: tokens.$font-weight-medium; } .text-body-large { font-size: tokens.$font-size-body-large; font-weight: tokens.$font-weight-regular; line-height: tokens.$line-height-normal; } .text-body-medium { font-size: tokens.$font-size-body-medium; font-weight: tokens.$font-weight-regular; line-height: tokens.$line-height-normal; } .text-label-medium { font-size: tokens.$font-size-label-medium; font-weight: tokens.$font-weight-medium; letter-spacing: tokens.$letter-spacing-wide; } // --------------------------------------------------------------------------- // Status Dot Pulse Animations // --------------------------------------------------------------------------- @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; } } // --------------------------------------------------------------------------- // Status Dot Utility Classes // --------------------------------------------------------------------------- .status-dot { width: tokens.$status-dot-size; height: tokens.$status-dot-size; border-radius: tokens.$radius-full; display: inline-block; &--active { background-color: var(--cc-status-active); animation: pulse-active tokens.$duration-standard tokens.$easing-standard infinite; } &--idle { background-color: var(--cc-status-idle); } &--thinking { background-color: var(--cc-status-thinking); animation: pulse-thinking 3s tokens.$easing-standard infinite; } &--error { background-color: var(--cc-status-error); animation: pulse-error tokens.$duration-fast tokens.$easing-standard infinite; } &--offline { background-color: var(--cc-status-offline); } } // --------------------------------------------------------------------------- // Accessibility: Reduced Motion // --------------------------------------------------------------------------- @media (prefers-reduced-motion: reduce) { .status-dot--active, .status-dot--error, .status-dot--thinking { animation: none; } } // --------------------------------------------------------------------------- // Screen-reader-only utility // --------------------------------------------------------------------------- .sr-only { @include tokens.sr-only; } // --------------------------------------------------------------------------- // Truncate utility // --------------------------------------------------------------------------- .truncate { @include tokens.truncate; } // --------------------------------------------------------------------------- // Focus ring utility // --------------------------------------------------------------------------- .focus-ring { @include tokens.focus-ring; } // --------------------------------------------------------------------------- // Scrollbar Styling (Tactical Dark) // --------------------------------------------------------------------------- ::-webkit-scrollbar { width: 6px; height: 6px; } ::-webkit-scrollbar-track { background: var(--cc-surface-dark); } ::-webkit-scrollbar-thumb { background: var(--cc-surface-lighter); border-radius: 3px; &:hover { background: var(--cc-on-surface-variant); } }