@import "tailwindcss"; @plugin 'tailwindcss-animate'; @custom-variant dark (&:is(.dark *)); /* ───────────────────────────────────────────────────────────── THEME ENGINE Theme is an attribute on (data-theme = dim · oled · light); accent is a second attribute (data-accent = one of eight hues). Surfaces, ink and borders derive from a handful of raw lightness vars per theme, so the live knobs (--border-boost, --glow) modulate every hairline and the page glow through calc(). The accent sets --brand everywhere and tints the ambient glow. :root carries the shared + computed tokens AND the Dim defaults, so a document with no data-theme renders Dim (the default theme). [data-theme="oled"] and [data-theme="light"] override from there. ───────────────────────────────────────────────────────────── */ :root { color-scheme: dark; /* Live knobs (overwritten on by the pre-paint script / useTheme) */ --border-boost: 0; /* signed offset added to every border L */ --glow: 0.16; /* ambient top-glow alpha */ --contrast: 0; /* master contrast: spreads page, ink and borders, signed by --ink-dir */ /* Accent default: cyan (overridden by [data-accent]) */ --accent-h: 196; --accent-c: 0.130; /* ---- Computed surfaces (flat neutral ladder per theme). The page tone spreads away from the cards as --contrast rises; clamp keeps it in gamut and always a hair below --card so page/card separation never collapses (matters at high contrast in Light, where --card is pure white). ---- */ --background: oklch(clamp(0, var(--bg) - var(--ink-dir) * var(--contrast) * 0.03, var(--card-l) - 0.012) 0 0); --card: oklch(var(--card-l) 0 0); --band: oklch(var(--band-l) 0 0); --well: oklch(var(--well-l) 0 0); /* ---- Computed popover / floating-panel fill. Mirrors --background's clamp + --ink-dir + contrast spread off a per-theme raw lightness + alpha, so every floating surface (sheets, dialogs, dropdowns, menus) tones with the active theme (incl. OLED true-black) and deepens with --contrast, instead of being a flat per-theme literal that stranded OLED at the Dim value. ---- */ --popover: oklch(clamp(0, var(--pop-l) - var(--ink-dir) * var(--contrast) * 0.03, 1) 0 0 / var(--pop-a)); /* Overlay scrim behind modals & sheets (theme-aware; softened in Light). */ --scrim: oklch(0 0 0 / 0.45); /* ---- Computed borders (opaque grey, directionally lit). --border-boost and --contrast both lift every hairline through one expression; clamp keeps them in gamut and below pure white so the lit edge never merges into a white card in Light at the low end of the knobs. ---- */ --card-border: oklch(clamp(0, var(--bb) + var(--border-dir) * (var(--border-boost) + var(--contrast) * 0.05), 0.97) 0 0); --card-border-top: oklch(clamp(0, var(--bt) + var(--border-dir) * (var(--border-boost) + var(--contrast) * 0.05), 0.97) 0 0); --card-border-hover: oklch(clamp(0, var(--bh) + var(--border-dir) * (var(--border-boost) + var(--contrast) * 0.05), 0.97) 0 0); --hairline: oklch(clamp(0, var(--hl) + var(--border-dir) * (var(--border-boost) + var(--contrast) * 0.05), 0.97) 0 0); --border: var(--card-border); --sidebar-border: var(--card-border); /* ---- Computed ink tiers. --contrast pushes each tier toward its extreme so secondary text crisps up as it rises; clamp keeps every tier in gamut. ---- */ --stat-value: oklch(clamp(0, var(--val) + var(--ink-dir) * var(--contrast) * 0.04, 1) 0 0); --stat-title: oklch(clamp(0, var(--title) + var(--ink-dir) * var(--contrast) * 0.055, 1) 0 0); --stat-subtitle: oklch(clamp(0, var(--sub) + var(--ink-dir) * var(--contrast) * 0.07, 1) 0 0); --stat-icon: oklch(clamp(0, var(--icon) + var(--ink-dir) * var(--contrast) * 0.06, 1) 0 0); /* ---- Computed brand (the accent is the one data color) ---- */ --brand: oklch(var(--accent-l) var(--accent-c) var(--accent-h)); --brand-foreground: var(--brand-fg); --brand-muted: oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.16); --ring: var(--brand); --sidebar-ring: var(--brand); /* Glass surface = the card tone; borders use the opaque hairline */ --glass: var(--card); /* Ambient glow tracks the accent hue so the whole page tints with it */ --glow-color: oklch(var(--glow-l) var(--glow-c) var(--accent-h) / var(--glow)); /* Charts: cyan leads as the primary data color, amber for peaks, rose for errors */ --chart-1: var(--brand); --chart-2: var(--warning); --chart-3: var(--destructive); /* Severity / chart palette (Signature default = today's saturated semantics). Colours only; per-palette fill/gradient/stroke live in JS (SecurityCharts). [data-chart-style="muted"|"heat"] override these; signature needs no rule. */ --sev-critical: var(--destructive); --sev-high: var(--warning); --sev-medium: color-mix(in oklch, var(--warning) 52%, var(--stat-icon)); --sev-low: color-mix(in oklch, var(--stat-icon) 72%, var(--well)); --sev-vuln: var(--brand); /* Sparkline / data-line styling (centralized) */ --data-line-width: 1.25px; --data-peak: var(--warning); /* Fleet Action card transformative chip (reuses the purple label hue) */ --action-transformative: var(--label-purple); /* ─────────────── Dim defaults (the default theme) ─────────────── */ /* Raw lightness vars */ --bg: 0.160; --card-l: 0.212; --band-l: 0.190; --well-l: 0.128; --bb: 0.320; --bt: 0.400; --bh: 0.460; --hl: 0.300; --border-dir: 1; --val: 0.970; --title: 0.800; --sub: 0.605; --icon: 0.480; --ink-dir: 1; --accent-l: 0.745; --brand-fg: oklch(0.15 0 0); --glow-l: 0.55; --glow-c: 0.085; --pop-l: 0.14; --pop-a: 0.82; /* Dark non-derivable tokens (shared by Dim & OLED) */ --foreground: oklch(0.94 0 0); --card-foreground: oklch(0.94 0 0); --popover-foreground: oklch(0.94 0 0); --primary: oklch(0.98 0 0); --primary-foreground: oklch(0.10 0 0); --secondary: oklch(var(--card-l) 0 0); --secondary-foreground: oklch(0.94 0 0); --muted: oklch(var(--card-l) 0 0); --muted-foreground: oklch(0.45 0 0); --accent: oklch(1 0 0 / 0.06); --accent-foreground: oklch(0.94 0 0); --destructive: oklch(0.72 0.18 20); --destructive-foreground: oklch(0.94 0 0); --destructive-muted: oklch(0.72 0.18 20 / 0.15); --input: oklch(var(--card-l) 0 0); /* Glass: solid surface system (no blur on static surfaces) */ --glass-border: var(--card-border); --glass-highlight: oklch(1 0 0 / 0.06); /* Semantic status colors (dark set) */ --success: oklch(0.78 0.16 155); --success-foreground: oklch(0.10 0 0); --success-muted: oklch(0.78 0.16 155 / 0.15); --warning: oklch(0.82 0.14 75); --warning-foreground: oklch(0.10 0 0); --warning-muted: oklch(0.82 0.14 75 / 0.15); /* --info: TOAST USE ONLY. Not part of the §17 five-slot working palette. */ --info: oklch(0.70 0.14 250); --info-foreground: oklch(0.10 0 0); --info-muted: oklch(0.70 0.14 250 / 0.15); --update: oklch(0.72 0.20 320); --update-foreground: oklch(0.10 0 0); --update-muted: oklch(0.72 0.20 320 / 0.15); /* Sidebar (tracks the page tone; borders use the shared hairline) */ --sidebar: oklch(var(--bg) 0 0 / 0.80); --sidebar-foreground: oklch(0.94 0 0); --sidebar-primary: oklch(0.98 0 0); --sidebar-primary-foreground: oklch(0.10 0 0); --sidebar-accent: oklch(1 0 0 / 0.07); --sidebar-accent-foreground: oklch(0.94 0 0); /* Label palette: ten raw hues preserved for existing assignments (dark) */ --label-teal: oklch(0.75 0.10 192); --label-teal-bg: oklch(0.75 0.10 192 / 0.15); --label-blue: oklch(0.72 0.12 250); --label-blue-bg: oklch(0.72 0.12 250 / 0.15); --label-purple: oklch(0.72 0.12 300); --label-purple-bg: oklch(0.72 0.12 300 / 0.15); --label-rose: oklch(0.72 0.14 10); --label-rose-bg: oklch(0.72 0.14 10 / 0.15); --label-amber: oklch(0.78 0.14 60); --label-amber-bg: oklch(0.78 0.14 60 / 0.15); --label-green: oklch(0.72 0.13 150); --label-green-bg: oklch(0.72 0.13 150 / 0.15); --label-orange: oklch(0.75 0.14 45); --label-orange-bg: oklch(0.75 0.14 45 / 0.15); --label-pink: oklch(0.75 0.14 340); --label-pink-bg: oklch(0.75 0.14 340 / 0.15); --label-cyan: oklch(0.75 0.10 210); --label-cyan-bg: oklch(0.75 0.10 210 / 0.15); --label-slate: oklch(0.65 0.01 250); --label-slate-bg: oklch(0.65 0.01 250 / 0.15); /* Semantic label roles: new labels should consume these */ --label-env: var(--label-teal); --label-env-bg: var(--label-teal-bg); --label-role: var(--label-blue); --label-role-bg: var(--label-blue-bg); --label-owner: var(--label-green); --label-owner-bg: var(--label-green-bg); --label-risk: var(--label-rose); --label-risk-bg: var(--label-rose-bg); --label-custom: var(--label-amber); --label-custom-bg: var(--label-amber-bg); /* Chart neutrals + grid/axis (dark) */ --chart-4: oklch(0.55 0 0); --chart-5: oklch(0.80 0 0); --chart-grid: oklch(1 0 0 / 0.05); --chart-tick: oklch(1 0 0 / 0.40); /* Material simulation: inherent depth (dark) */ --card-bevel: inset 0 1px 0 0 oklch(1 0 0 / 0.05); --button-inner-glow: inset 0 1px 0 0 oklch(1 0 0 / 0.06); --chrome-top-highlight: inset 0 1px 0 0 oklch(1 0 0 / 0.08); /* Shadows: near-zero, depth comes from surface tone (dark) */ --shadow-x: 0px; --shadow-y: 1px; --shadow-blur: 2px; --shadow-spread: 0px; --shadow-opacity: 0.15; --shadow-color: hsl(0 0% 0%); --shadow-2xs: 0 0 0 0 transparent; --shadow-xs: 0 0 0 0 transparent; --shadow-sm: 0px 1px 2px 0px hsl(0 0% 0% / 0.15); --shadow: 0px 1px 2px 0px hsl(0 0% 0% / 0.15); --shadow-md: 0px 2px 4px 0px hsl(0 0% 0% / 0.15); --shadow-lg: 0px 4px 6px -1px hsl(0 0% 0% / 0.15); --shadow-xl: 0px 8px 10px -1px hsl(0 0% 0% / 0.20); --shadow-2xl: 0px 12px 20px -2px hsl(0 0% 0% / 0.30); /* Terminal (recessed well, tracks the theme's well tone) */ --terminal-bg: oklch(var(--well-l) 0 0); --terminal-fg: oklch(0.85 0 0); --terminal-cursor: oklch(1 0 0); --terminal-cursor-accent: oklch(0 0 0); --terminal-selection: oklch(1 0 0 / 0.3); /* ─────────────── Shared (theme-independent) ─────────────── */ /* Typography. Display is the locked signature face; the interface (sans) and data (mono) faces are user-swappable via --ui-font / --mono-font, and --type-scale multiplies the root font-size (see the html rule below). */ --type-scale: 1; --ui-font: 'Geist'; --mono-font: 'Geist Mono'; --font-sans: var(--ui-font), system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; --font-mono: var(--mono-font), ui-monospace, monospace; --font-serif: 'Instrument Serif', Georgia, serif; --font-display: 'Instrument Serif', Georgia, serif; /* Operational heading family. Signature default = the display serif, italic; family + style ONLY so migrated headings keep their own weight/tracking and stay a true no-op in Signature. [data-headings="clean"] flips to the sans face and the Calm weight/tracking lift lands via the .font-heading rule. */ --font-heading: var(--font-display); --heading-style: italic; /* Shape */ --radius: 0.5rem; /* Height of the mobile bottom tab bar's interactive area (excludes the safe-area inset, which is added where needed). Fixed-position overlays (toasts, the deploy pill) offset above it on mobile so they never sit behind the tab bar. */ --sn-mobile-tabbar-h: 56px; /* Motion timing */ --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1); --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1); --duration-fast: 150ms; --duration-base: 220ms; --duration-slow: 350ms; --tracking-normal: 0em; --spacing: 0.25rem; /* Density: comfortable defaults. Overridden under .density-compact. */ --density-scale: 1; --density-row-y: 0.75rem; --density-row-x: 1.25rem; --density-cell-y: 0.5rem; --density-tile-y: 1rem; --density-gap: 1rem; } /* ───────────────────────────────────────────────────────────── ACCENTS (hue + chroma only; lightness comes from the theme) ───────────────────────────────────────────────────────────── */ /* A tighter, well-spaced wheel: every pair is >=40deg apart and pushed chromatic so the hues stay distinct at the accent lightness. Kept clear of success(155) / warning(75) / destructive(20). Steel is the near-neutral. */ [data-accent="cyan"] { --accent-h: 196; --accent-c: 0.130; } [data-accent="blue"] { --accent-h: 252; --accent-c: 0.165; } [data-accent="violet"] { --accent-h: 298; --accent-c: 0.190; } [data-accent="magenta"] { --accent-h: 344; --accent-c: 0.180; } [data-accent="orange"] { --accent-h: 42; --accent-c: 0.165; } [data-accent="amber"] { --accent-h: 88; --accent-c: 0.165; } [data-accent="lime"] { --accent-h: 132; --accent-c: 0.195; } [data-accent="steel"] { --accent-h: 250; --accent-c: 0.040; } /* ───────────────────────────────────────────────────────────── OLED: true black for power-saving panels. Only the raw surface, ink and glow vars change; the dark non-derivable tokens inherit from :root, and the opaque-grey borders keep cards from merging into the black the way 6%-white hairlines did. ───────────────────────────────────────────────────────────── */ [data-theme="oled"] { --bg: 0.035; --card-l: 0.105; --band-l: 0.072; --well-l: 0.020; --bb: 0.262; --bt: 0.345; --bh: 0.405; --hl: 0.235; --border-dir: 1; --val: 0.950; --title: 0.780; --sub: 0.575; --icon: 0.445; --ink-dir: 1; --accent-l: 0.745; --brand-fg: oklch(0.11 0 0); --glow-l: 0.46; --glow-c: 0.085; --pop-l: 0.06; --pop-a: 0.86; } /* ───────────────────────────────────────────────────────────── LIGHT: the existing light theme. Borders are opaque and directionally lit (the lit top edge is lighter, sides darker, so --border-dir flips to -1). ───────────────────────────────────────────────────────────── */ [data-theme="light"] { color-scheme: light; /* Raw lightness vars */ --bg: 0.965; --card-l: 1.000; --band-l: 0.972; --well-l: 0.945; --bb: 0.855; --bt: 0.910; --bh: 0.780; --hl: 0.885; --border-dir: -1; --val: 0.190; --title: 0.400; --sub: 0.500; --icon: 0.620; --ink-dir: -1; --accent-l: 0.525; --brand-fg: oklch(0.99 0 0); --glow-l: 0.90; --glow-c: 0.040; --pop-l: 1.0; --pop-a: 0.92; --scrim: oklch(0.22 0 0 / 0.32); /* Light non-derivable tokens */ --foreground: oklch(0.15 0 0); --card-foreground: oklch(0.15 0 0); --popover-foreground: oklch(0.15 0 0); --primary: oklch(0.15 0 0); --primary-foreground: oklch(1 0 0); --secondary: oklch(0 0 0 / 0.05); --secondary-foreground: oklch(0.15 0 0); --muted: oklch(0 0 0 / 0.04); --muted-foreground: oklch(0.50 0 0); --accent: oklch(0 0 0 / 0.06); --accent-foreground: oklch(0.15 0 0); --destructive: oklch(0.63 0.18 20); --destructive-foreground: oklch(1 0 0); --destructive-muted: oklch(0.63 0.18 20 / 0.12); --input: oklch(0.97 0 0); --glass-border: var(--card-border); --glass-highlight: oklch(0 0 0 / 0.06); --success: oklch(0.65 0.16 155); --success-foreground: oklch(1 0 0); --success-muted: oklch(0.65 0.16 155 / 0.12); --warning: oklch(0.75 0.14 75); --warning-foreground: oklch(0.20 0 0); --warning-muted: oklch(0.75 0.14 75 / 0.12); --info: oklch(0.62 0.14 250); --info-foreground: oklch(1 0 0); --info-muted: oklch(0.62 0.14 250 / 0.12); --update: oklch(0.62 0.22 320); --update-foreground: oklch(1 0 0); --update-muted: oklch(0.62 0.22 320 / 0.12); --sidebar: oklch(0.98 0 0 / 0.80); --sidebar-foreground: oklch(0.15 0 0); --sidebar-primary: oklch(0.15 0 0); --sidebar-primary-foreground: oklch(1 0 0); --sidebar-accent: oklch(0 0 0 / 0.06); --sidebar-accent-foreground: oklch(0.15 0 0); /* Label palette (light) */ --label-teal: oklch(0.55 0.12 192); --label-teal-bg: oklch(0.55 0.12 192 / 0.12); --label-blue: oklch(0.55 0.14 250); --label-blue-bg: oklch(0.55 0.14 250 / 0.12); --label-purple: oklch(0.55 0.14 300); --label-purple-bg: oklch(0.55 0.14 300 / 0.12); --label-rose: oklch(0.55 0.16 10); --label-rose-bg: oklch(0.55 0.16 10 / 0.12); --label-amber: oklch(0.60 0.16 60); --label-amber-bg: oklch(0.60 0.16 60 / 0.12); --label-green: oklch(0.55 0.15 150); --label-green-bg: oklch(0.55 0.15 150 / 0.12); --label-orange: oklch(0.58 0.16 45); --label-orange-bg: oklch(0.58 0.16 45 / 0.12); --label-pink: oklch(0.58 0.16 340); --label-pink-bg: oklch(0.58 0.16 340 / 0.12); --label-cyan: oklch(0.58 0.12 210); --label-cyan-bg: oklch(0.58 0.12 210 / 0.12); --label-slate: oklch(0.50 0.01 250); --label-slate-bg: oklch(0.50 0.01 250 / 0.12); /* Chart neutrals + grid/axis (light) */ --chart-4: oklch(0.70 0 0); --chart-5: oklch(0.45 0 0); --chart-grid: oklch(0 0 0 / 0.06); --chart-tick: oklch(0 0 0 / 0.45); /* Material simulation (light) */ --card-bevel: inset 0 1px 0 0 oklch(1 0 0 / 0.04), 0 1px 2px 0 oklch(0 0 0 / 0.05); --button-inner-glow: inset 0 1px 0 0 oklch(1 0 0 / 0.10), 0 1px 2px 0 oklch(0 0 0 / 0.06); --chrome-top-highlight: inset 0 1px 0 0 oklch(1 0 0 / 0.45); /* Shadows (light) */ --shadow-opacity: 0.10; --shadow-2xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.05); --shadow-xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.05); --shadow-sm: 0px 1px 2px 0px hsl(0 0% 0% / 0.08); --shadow: 0px 1px 2px 0px hsl(0 0% 0% / 0.08), 0px 1px 2px -1px hsl(0 0% 0% / 0.08); --shadow-md: 0px 1px 2px 0px hsl(0 0% 0% / 0.10), 0px 2px 4px -1px hsl(0 0% 0% / 0.10); --shadow-lg: 0px 1px 2px 0px hsl(0 0% 0% / 0.10), 0px 4px 6px -1px hsl(0 0% 0% / 0.10); --shadow-xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.10), 0px 8px 10px -1px hsl(0 0% 0% / 0.10); --shadow-2xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.25); /* Terminal stays a dark well even in the light theme */ --terminal-bg: oklch(0.12 0 0); } /* ───────────────────────────────────────────────────────────── CALM / READABILITY REFRESH Three appearance attributes on switch the heading family, the severity-chart palette, and material effects. Signature (the defaults in :root) needs no rule; Calm flips them. Placed after the theme blocks so the reduced-effects --card-bevel override wins in every theme. ───────────────────────────────────────────────────────────── */ /* Clean headings: the readability fix. Operational headings drop the display serif for the upright interface face. */ [data-headings="clean"] { --font-heading: var(--font-sans); --heading-style: normal; } /* Muted: desaturated severity semantics, no brand/destructive clash. */ [data-chart-style="muted"] { --sev-critical: oklch(0.605 0.105 28); --sev-high: oklch(0.715 0.085 70); --sev-medium: oklch(0.675 0.045 88); --sev-low: oklch(0.565 0.018 250); --sev-vuln: oklch(0.605 0.045 235); } /* Heat: a single warm sequential ramp with zero complementary vibration. */ [data-chart-style="heat"] { --sev-critical: oklch(0.565 0.135 30); --sev-high: oklch(0.675 0.115 48); --sev-medium: oklch(0.770 0.080 70); --sev-low: oklch(0.825 0.040 82); --sev-vuln: oklch(0.660 0.100 45); } /* Reduced effects: lower-overhead rendering path (Calm / Reduced effects / Readability). Flatten material, drop glass blur, and solidify translucent chrome so constrained GPUs are not forced to sample backdrop-filter. data-theme and data-effects both live on , so token overrides use combined selectors. Exceptions to the blur kill need a more-specific !important rule, not a normal opt-out class. Charts also read the reduced flag from the store. */ html[data-effects="reduced"] { --card-bevel: none; --pop-a: 1; /* Dim (default theme when data-theme is dim or unset on first paint) */ --sidebar: oklch(var(--bg) 0 0); } html[data-theme="oled"][data-effects="reduced"] { --sidebar: oklch(var(--bg) 0 0); } html[data-theme="light"][data-effects="reduced"] { --sidebar: oklch(0.98 0 0); } /* Both properties: Chromium uses backdrop-filter; the WebKit-prefixed form still appears in some engines. */ html[data-effects="reduced"] *, html[data-effects="reduced"] *::before, html[data-effects="reduced"] *::after { backdrop-filter: none !important; -webkit-backdrop-filter: none !important; } /* Direct-alpha glass surfaces (bg-popover/95, color-mix tab bar, etc.) stay translucent after --pop-a: 1. Mark them with data-sn-glass and solidify here. */ html[data-effects="reduced"] [data-sn-glass="panel"] { background-color: var(--popover); } html[data-effects="reduced"] [data-sn-glass="overlay"] { background-color: var(--background); } html[data-effects="reduced"] [data-sn-glass="mobile-tabbar"] { background-color: var(--card); } html[data-effects="reduced"] .animate-pulse { animation: none; } /* Decorative masthead rails: tied to reduced material effects (Calm, Readability, or manual Reduced effects), not to data-motion. Motion remains independently toggleable; turning Motion off does not restore these rails while effects are reduced. */ html[data-effects="reduced"] .masthead-rail-glow, html[data-effects="reduced"] .masthead-rail-shimmer { animation: none; } /* Heading utility: every operational title routes through this. Base sets only family + style (Signature parity); the Calm-only descendant rule lifts weight and tightens tracking for the sans face, beating any single tracking or weight utility on the element. */ .font-heading { font-family: var(--font-heading); font-style: var(--heading-style); } [data-headings="clean"] .font-heading { font-weight: 600; letter-spacing: -0.006em; } /* ───────────────────────────────────────────────────────────── TAILWIND THEME MAPPING ───────────────────────────────────────────────────────────── */ @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); --color-card: var(--card); --color-card-foreground: var(--card-foreground); --color-popover: var(--popover); --color-popover-foreground: var(--popover-foreground); --color-primary: var(--primary); --color-primary-foreground: var(--primary-foreground); --color-secondary: var(--secondary); --color-secondary-foreground: var(--secondary-foreground); --color-muted: var(--muted); --color-muted-foreground: var(--muted-foreground); --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); --color-destructive: var(--destructive); --color-destructive-foreground: var(--destructive-foreground); --color-border: var(--border); --color-input: var(--input); --color-ring: var(--ring); --color-brand: var(--brand); --color-brand-foreground: var(--brand-foreground); --color-brand-muted: var(--brand-muted); --color-chart-1: var(--chart-1); --color-chart-2: var(--chart-2); --color-chart-3: var(--chart-3); --color-chart-4: var(--chart-4); --color-chart-5: var(--chart-5); --color-sidebar: var(--sidebar); --color-sidebar-foreground: var(--sidebar-foreground); --color-sidebar-primary: var(--sidebar-primary); --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); --color-sidebar-accent: var(--sidebar-accent); --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-border: var(--sidebar-border); --color-sidebar-ring: var(--sidebar-ring); --color-glass: var(--glass); --color-glass-border: var(--glass-border); --color-glass-highlight: var(--glass-highlight); --color-stat-value: var(--stat-value); --color-stat-title: var(--stat-title); --color-stat-subtitle: var(--stat-subtitle); --color-stat-icon: var(--stat-icon); --color-card-border: var(--card-border); --color-card-border-top: var(--card-border-top); --color-card-border-hover: var(--card-border-hover); --color-band: var(--band); --color-well: var(--well); --color-hairline: var(--hairline); --color-chart-grid: var(--chart-grid); --color-chart-tick: var(--chart-tick); --color-success: var(--success); --color-success-foreground: var(--success-foreground); --color-success-muted: var(--success-muted); --color-warning: var(--warning); --color-warning-foreground: var(--warning-foreground); --color-warning-muted: var(--warning-muted); --color-info: var(--info); --color-info-foreground: var(--info-foreground); --color-info-muted: var(--info-muted); --color-update: var(--update); --color-update-foreground: var(--update-foreground); --color-update-muted: var(--update-muted); --color-destructive-muted: var(--destructive-muted); --color-action-transformative: var(--action-transformative); --font-sans: var(--font-sans); --font-mono: var(--font-mono); --font-serif: var(--font-serif); --font-display: var(--font-display); --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); --radius-xl: calc(var(--radius) + 4px); --shadow-2xs: var(--shadow-2xs); --shadow-xs: var(--shadow-xs); --shadow-sm: var(--shadow-sm); --shadow: var(--shadow); --shadow-md: var(--shadow-md); --shadow-lg: var(--shadow-lg); --shadow-xl: var(--shadow-xl); --shadow-2xl: var(--shadow-2xl); --shadow-card-bevel: var(--card-bevel); --shadow-btn-glow: var(--button-inner-glow); --shadow-chrome-top: var(--chrome-top-highlight); } /* ───────────────────────────────────────────────────────────── BASE STYLES ───────────────────────────────────────────────────────────── */ @layer base { * { @apply border-border outline-ring/50; } body { @apply text-foreground; /* Ambient top-center glow tracks the accent hue and the --glow knob. Shows on screens whose root is transparent (e.g. Login). Full-screen app shells that paint an opaque --background must use .app-canvas instead, or they occlude this. */ background: radial-gradient( ellipse 156% 106% at 50% -6%, var(--glow-color), transparent 70% ), var(--background); background-attachment: fixed; } } /* The page canvas: opaque --background base plus the ambient accent glow. Use on full-screen app shells (EditorLayout, the loading wrapper) that would otherwise paint a flat bg-background over the body glow and hide it entirely. */ .app-canvas { background: radial-gradient( ellipse 156% 106% at 50% -6%, var(--glow-color), transparent 70% ), var(--background); background-attachment: fixed; } /* Accent wash for floating panels (sheets & large dialogs). Layers the ambient accent glow as a background image over the panel's own --popover fill, so a portaled surface carries the same accent personality .app-canvas gives the page. Image-only (the popover color stays the base) to keep the glass translucency and backdrop blur; anchored to the panel top so the translucent header bands let it bleed through. */ .panel-glow { background-image: radial-gradient( ellipse 130% 42% at 50% 0%, var(--glow-color), transparent 64% ); } /* Density: compact mode compresses row/cell padding by ~50%. */ body.density-compact { --density-scale: 0.75; --density-row-y: 0.375rem; --density-row-x: 1rem; --density-cell-y: 0.25rem; --density-tile-y: 0.625rem; --density-gap: 0.75rem; } /* ───────────────────────────────────────────────────────────── TYPOGRAPHY & RENDERING ───────────────────────────────────────────────────────────── */ html, body, #root { height: 100%; width: 100%; overflow: hidden; } /* Text-size control: one root multiplier scales the whole rem-based type ramp. Layout px is untouched; only rem-sized text grows/shrinks. */ html { font-size: calc(16px * var(--type-scale)); } body { font-family: var(--font-sans), system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; line-height: 1.5; font-weight: 400; font-synthesis: none; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } /* ───────────────────────────────────────────────────────────── SCROLLBAR ───────────────────────────────────────────────────────────── */ ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background: oklch(0.40 0 0 / 0.5); border-radius: 4px; transition: background var(--duration-fast) ease; } ::-webkit-scrollbar-thumb:hover { background: oklch(0.55 0 0 / 0.7); } .dark ::-webkit-scrollbar-thumb { background: oklch(0.35 0 0 / 0.6); } .dark ::-webkit-scrollbar-thumb:hover { background: oklch(0.50 0 0 / 0.8); } /* ───────────────────────────────────────────────────────────── GLASS UTILITIES ───────────────────────────────────────────────────────────── */ .glass { background: var(--glass); border: 1px solid var(--glass-border); } .glass-strong { background: var(--glass); border: 1px solid var(--glass-border); } .glass-float { background: var(--popover); backdrop-filter: blur(10px) saturate(1.15); -webkit-backdrop-filter: blur(10px) saturate(1.15); border: 1px solid var(--glass-border); } /* ───────────────────────────────────────────────────────────── ANIMATION KEYFRAMES ───────────────────────────────────────────────────────────── */ @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } } @keyframes fade-up { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } } @keyframes fade-down { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: translateY(0); } } @keyframes slide-in-left { from { opacity: 0; transform: translateX(-12px); } to { opacity: 1; transform: translateX(0); } } @keyframes scale-in { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } @keyframes shimmer { 0% { transform: translateY(-100%); } 100% { transform: translateY(200%); } } @keyframes masthead-rail-glow { 0%, 100% { opacity: 0.15; } 50% { opacity: 0.55; } } /* ───────────────────────────────────────────────────────────── ANIMATION UTILITIES ───────────────────────────────────────────────────────────── */ .animate-fade-in { animation: fade-in var(--duration-base) var(--ease-out-expo) both; } .animate-fade-up { animation: fade-up var(--duration-base) var(--ease-out-expo) both; } .animate-fade-down { animation: fade-down var(--duration-base) var(--ease-out-expo) both; } .animate-slide-in-left { animation: slide-in-left var(--duration-base) var(--ease-out-expo) both; } .animate-scale-in { animation: scale-in var(--duration-fast) var(--ease-spring) both; } .animate-shimmer { animation: shimmer 4.5s ease-in-out infinite alternate; } .masthead-rail-shimmer { animation: shimmer 5s ease-in-out infinite alternate; } .masthead-rail-glow { animation: masthead-rail-glow 4s ease-in-out infinite alternate; } /* Stagger delay helpers */ .animate-delay-50 { animation-delay: 50ms; } .animate-delay-100 { animation-delay: 100ms; } .animate-delay-150 { animation-delay: 150ms; } .animate-delay-200 { animation-delay: 200ms; } .animate-delay-300 { animation-delay: 300ms; } /* ───────────────────────────────────────────────────────────── PREFERS REDUCED MOTION - zero-cost accessibility ───────────────────────────────────────────────────────────── */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } } /* The "Reduced motion" appearance setting (data-motion="reduced" on ) clamps CSS animations/transitions, mirroring the OS preference above. Sonner toasts animate via inline transform/opacity (React state), not CSS, so they are unaffected. framer-motion is handled separately by MotionConfig. */ [data-motion="reduced"] *, [data-motion="reduced"] *::before, [data-motion="reduced"] *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } /* ───────────────────────────────────────────────────────────── XTERM.JS ───────────────────────────────────────────────────────────── */ .xterm { padding: 0; }