2026-04-25 19:02:57 +00:00
|
|
|
// ============================================================================
|
|
|
|
|
// OpenClaw Control Center — M3 Tactical Dark Theme
|
|
|
|
|
// ============================================================================
|
2026-04-28 07:52:16 -04:00
|
|
|
// 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.
|
2026-04-25 19:02:57 +00:00
|
|
|
// ============================================================================
|
|
|
|
|
|
2026-04-28 07:52:16 -04:00
|
|
|
@use 'styles/tokens' as tokens;
|
|
|
|
|
@use 'styles/css-properties' as css-props;
|
|
|
|
|
@use 'styles/utilities' as utils;
|
2026-04-25 19:02:57 +00:00
|
|
|
@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: (
|
2026-04-28 07:52:16 -04:00
|
|
|
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,
|
2026-04-25 19:02:57 +00:00
|
|
|
),
|
|
|
|
|
density: (
|
|
|
|
|
scale: 0,
|
|
|
|
|
),
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// Apply theme to :root
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
html {
|
|
|
|
|
height: 100%;
|
|
|
|
|
@include mat.theme($dark-theme);
|
|
|
|
|
color-scheme: dark;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
2026-04-28 07:52:16 -04:00
|
|
|
// Emit Design System CSS Custom Properties
|
2026-04-25 19:02:57 +00:00
|
|
|
// ---------------------------------------------------------------------------
|
2026-04-28 07:52:16 -04:00
|
|
|
@include css-props.emit-custom-properties;
|
2026-04-25 19:02:57 +00:00
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// Global Body Styles
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
body {
|
2026-04-28 07:52:16 -04:00
|
|
|
background-color: var(--cc-surface-darkest);
|
2026-04-25 19:02:57 +00:00
|
|
|
color: var(--cc-on-surface);
|
2026-04-28 07:52:16 -04:00
|
|
|
font-family: var(--cc-font-body);
|
2026-04-25 19:02:57 +00:00
|
|
|
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);
|
2026-04-28 07:52:16 -04:00
|
|
|
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;
|
2026-04-25 19:02:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// 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; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
2026-04-28 07:52:16 -04:00
|
|
|
// Status Dot Utility Classes
|
2026-04-25 19:02:57 +00:00
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
.status-dot {
|
2026-04-28 07:52:16 -04:00
|
|
|
width: tokens.$status-dot-size;
|
|
|
|
|
height: tokens.$status-dot-size;
|
|
|
|
|
border-radius: tokens.$radius-full;
|
2026-04-25 19:02:57 +00:00
|
|
|
display: inline-block;
|
|
|
|
|
|
|
|
|
|
&--active {
|
2026-04-28 07:52:16 -04:00
|
|
|
background-color: var(--cc-status-active);
|
|
|
|
|
animation: pulse-active tokens.$duration-standard tokens.$easing-standard infinite;
|
2026-04-25 19:02:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&--idle {
|
2026-04-28 07:52:16 -04:00
|
|
|
background-color: var(--cc-status-idle);
|
2026-04-25 19:02:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&--thinking {
|
2026-04-28 07:52:16 -04:00
|
|
|
background-color: var(--cc-status-thinking);
|
|
|
|
|
animation: pulse-thinking 3s tokens.$easing-standard infinite;
|
2026-04-25 19:02:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&--error {
|
2026-04-28 07:52:16 -04:00
|
|
|
background-color: var(--cc-status-error);
|
|
|
|
|
animation: pulse-error tokens.$duration-fast tokens.$easing-standard infinite;
|
2026-04-25 19:02:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&--offline {
|
2026-04-28 07:52:16 -04:00
|
|
|
background-color: var(--cc-status-offline);
|
2026-04-25 19:02:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// Accessibility: Reduced Motion
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
|
|
|
.status-dot--active,
|
|
|
|
|
.status-dot--error,
|
|
|
|
|
.status-dot--thinking {
|
|
|
|
|
animation: none;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-28 07:52:16 -04:00
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// 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;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-25 19:02:57 +00:00
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// Scrollbar Styling (Tactical Dark)
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
::-webkit-scrollbar {
|
|
|
|
|
width: 6px;
|
|
|
|
|
height: 6px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
::-webkit-scrollbar-track {
|
2026-04-28 07:52:16 -04:00
|
|
|
background: var(--cc-surface-dark);
|
2026-04-25 19:02:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
::-webkit-scrollbar-thumb {
|
2026-04-28 07:52:16 -04:00
|
|
|
background: var(--cc-surface-lighter);
|
2026-04-25 19:02:57 +00:00
|
|
|
border-radius: 3px;
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
background: var(--cc-on-surface-variant);
|
|
|
|
|
}
|
|
|
|
|
}
|