- Create frontend/colors.mjs as SSOT for all design colors - Create scripts/generate-css-vars.mjs to auto-generate CSS variables - Update tailwind.config.ts to import colors from colors.mjs - Update frontend/package.json: add 'generate-css-vars' script to build pipeline - Update start_servers.py: include CSS variable generation before npm build - All color changes now require only one edit in colors.mjs - Build process auto-syncs CSS variables and Tailwind colors Eliminates DRY violation where colors were duplicated in: - tailwind.config.ts (Tailwind utility classes) - globals.css (CSS custom properties) Single source of truth approach ensures: ✓ No inconsistency between Tailwind and CSS variables ✓ One place to update colors for all contexts ✓ Automated CSS variable generation on every build Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
355 lines
8.3 KiB
CSS
355 lines
8.3 KiB
CSS
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
|
|
|
|
@tailwind base;
|
|
@tailwind components;
|
|
@tailwind utilities;
|
|
|
|
@layer base {
|
|
:root {
|
|
/* Base colors from DESIGN.md - AUTO-GENERATED from colors.mjs */
|
|
|
|
/* Base colors from DESIGN.md */
|
|
--background: #131313;
|
|
--on-background: #e5e2e1;
|
|
--foreground: #e5e2e1;
|
|
|
|
/* Surface colors from DESIGN.md */
|
|
--surface-DEFAULT: #131313;
|
|
--surface-dim: #131313;
|
|
--surface-bright: #3a3939;
|
|
--surface-container-lowest: #0e0e0e;
|
|
--surface-container-low: #1c1b1b;
|
|
--surface-container: #201f1f;
|
|
--surface-container-high: #2a2a2a;
|
|
--surface-container-highest: #353534;
|
|
--surface-variant: #353534;
|
|
|
|
/* Primary colors from DESIGN.md */
|
|
--primary-DEFAULT: #ffb781;
|
|
--primary-foreground: #4e2600;
|
|
--primary-container: #f58618;
|
|
--primary-on-container: #5b2d00;
|
|
--primary-fixed: #ffdcc4;
|
|
--primary-fixed-dim: #ffb781;
|
|
--primary-on-fixed: #2f1400;
|
|
--primary-on-fixed-variant: #6f3800;
|
|
--primary-inverse: #924c00;
|
|
|
|
/* Secondary colors from DESIGN.md */
|
|
--secondary-DEFAULT: #c8c6c5;
|
|
--secondary-foreground: #303030;
|
|
--secondary-container: #474746;
|
|
--secondary-on-container: #b7b5b4;
|
|
--secondary-fixed: #e5e2e1;
|
|
--secondary-fixed-dim: #c8c6c5;
|
|
--secondary-on-fixed: #1b1c1c;
|
|
--secondary-on-fixed-variant: #474746;
|
|
|
|
/* Tertiary colors from DESIGN.md */
|
|
--tertiary-DEFAULT: #00e639;
|
|
--tertiary-foreground: #003907;
|
|
--tertiary-container: #00bd2d;
|
|
--tertiary-on-container: #00440a;
|
|
--tertiary-fixed: #72ff70;
|
|
--tertiary-fixed-dim: #00e639;
|
|
--tertiary-on-fixed: #002203;
|
|
--tertiary-on-fixed-variant: #00530e;
|
|
|
|
/* Error colors from DESIGN.md */
|
|
--error-DEFAULT: #ffb4ab;
|
|
--error-foreground: #690005;
|
|
--error-container: #93000a;
|
|
--error-on-container: #ffdad6;
|
|
|
|
/* Outline colors from DESIGN.md */
|
|
--outline: #a48c7c;
|
|
--outline-variant: #564335;
|
|
|
|
/* Inverse colors from DESIGN.md */
|
|
--inverse-surface: #e5e2e1;
|
|
--inverse-on-surface: #313030;
|
|
|
|
/* Semantic colors from DESIGN.md */
|
|
--border: #353534;
|
|
--muted: #9f9e9d;
|
|
--info: #64b5f6;
|
|
--success: #00e639;
|
|
--warning: #ffb781;
|
|
--alert: #ffb4ab;
|
|
|
|
/* Semantic spacing tokens */
|
|
--spacing-unit: 4px;
|
|
--spacing-stack-sm: 8px;
|
|
--spacing-stack-md: 16px;
|
|
--spacing-gutter: 16px;
|
|
--spacing-margin: 32px;
|
|
--spacing-container-gap: 24px;
|
|
}
|
|
|
|
|
|
|
|
* {
|
|
@apply border-border;
|
|
border-radius: 0 !important;
|
|
box-shadow: none !important;
|
|
}
|
|
|
|
body {
|
|
@apply bg-background text-foreground antialiased font-normal;
|
|
font-family: 'Space Grotesk', sans-serif;
|
|
letter-spacing: -0.01em;
|
|
}
|
|
|
|
/* Strict "NO BOLD" enforcement from AI_RULES.md - Hierarchy via size and color only */
|
|
*, *::before, *::after {
|
|
font-weight: 400 !important;
|
|
}
|
|
|
|
/* No uppercase/italics as per AI_RULES.md and GEMINI.md */
|
|
*, *::before, *::after {
|
|
text-transform: none !important;
|
|
font-style: normal !important;
|
|
}
|
|
|
|
/* Typography scale with proper letter-spacing per DESIGN.md */
|
|
h1 {
|
|
@apply text-5xl tracking-tighter;
|
|
letter-spacing: -0.02em;
|
|
}
|
|
|
|
h2 {
|
|
@apply text-4xl tracking-tight;
|
|
letter-spacing: -0.01em;
|
|
}
|
|
|
|
h3, h4, h5, h6 {
|
|
@apply tracking-tight;
|
|
}
|
|
|
|
/* Input Fields: Darker than the container background per DESIGN.md */
|
|
input, textarea, select {
|
|
background-color: var(--surface-container-lowest);
|
|
border: 1px solid var(--outline);
|
|
color: var(--foreground);
|
|
padding: 0.5rem 0.75rem;
|
|
border-radius: 0 !important;
|
|
transition: border-color 0.2s;
|
|
}
|
|
|
|
input:focus, textarea:focus, select:focus {
|
|
border-color: var(--primary);
|
|
outline: none;
|
|
}
|
|
}
|
|
|
|
@layer components {
|
|
/* Button Styles: Rectangular with no radius */
|
|
.btn-primary {
|
|
background-color: var(--primary);
|
|
color: var(--on-primary);
|
|
padding: 0.5rem 1rem;
|
|
@apply inline-flex items-center justify-center gap-2 transition-opacity hover:opacity-90;
|
|
border-radius: 0 !important;
|
|
}
|
|
|
|
.btn-secondary {
|
|
background-color: transparent;
|
|
border: 1px solid var(--secondary);
|
|
color: var(--secondary);
|
|
padding: 0.5rem 1rem;
|
|
@apply inline-flex items-center justify-center gap-2 transition-colors;
|
|
border-radius: 0 !important;
|
|
}
|
|
|
|
.btn-secondary:hover {
|
|
border-color: var(--foreground);
|
|
color: var(--foreground);
|
|
}
|
|
|
|
.level-0 {
|
|
background-color: var(--surface);
|
|
}
|
|
|
|
/* Level 1 (Cards/Panels): surface-container with 1px border of outline-variant */
|
|
.level-1 {
|
|
@apply border;
|
|
background-color: var(--surface-container);
|
|
border-color: var(--outline-variant);
|
|
}
|
|
|
|
/* Level 2 (Modals/Popovers): surface-container-high with 2px border of primary */
|
|
.level-2 {
|
|
background-color: var(--surface-container-high);
|
|
border: 2px solid var(--primary);
|
|
border-radius: 0 !important;
|
|
}
|
|
|
|
.input-field {
|
|
background-color: var(--surface-container-lowest);
|
|
border: 1px solid var(--outline);
|
|
color: var(--foreground);
|
|
padding: 0.75rem;
|
|
border-radius: 0 !important;
|
|
transition: border-color 0.2s;
|
|
}
|
|
|
|
.input-field:focus {
|
|
border-color: var(--primary);
|
|
outline: none;
|
|
}
|
|
|
|
/* Active State: 1px solid primary */
|
|
.active-border {
|
|
@apply border;
|
|
border-color: var(--primary);
|
|
}
|
|
|
|
/* High-contrast status blocks: No rounded corners */
|
|
.status-success {
|
|
background-color: var(--tertiary);
|
|
color: var(--on-tertiary);
|
|
padding: 0.125rem 0.5rem;
|
|
border-radius: 0 !important;
|
|
}
|
|
|
|
.status-alert {
|
|
background-color: var(--primary);
|
|
color: var(--on-primary);
|
|
padding: 0.125rem 0.5rem;
|
|
border-radius: 0 !important;
|
|
}
|
|
|
|
/* Data Tables: Header cells with a subtle background tint */
|
|
.table-header {
|
|
background-color: var(--surface-container-high);
|
|
border-bottom: 1px solid var(--outline);
|
|
padding: 0.5rem 1rem;
|
|
color: var(--secondary);
|
|
font-size: 0.875rem;
|
|
font-weight: normal;
|
|
}
|
|
|
|
/* Log Viewers: Background surface-container-lowest with outline border */
|
|
.log-viewer {
|
|
background-color: var(--surface-container-lowest);
|
|
border: 1px solid var(--outline);
|
|
padding: 1rem;
|
|
font-family: 'Space Grotesk', monospace;
|
|
font-variant-numeric: tabular-nums;
|
|
overflow-y: auto;
|
|
border-radius: 0 !important;
|
|
}
|
|
|
|
/* Typography utilities for DESIGN.md semantic sizing */
|
|
.headline-lg {
|
|
@apply text-5xl font-normal;
|
|
letter-spacing: -0.02em;
|
|
line-height: 1.1;
|
|
}
|
|
|
|
.headline-md {
|
|
@apply text-4xl font-normal;
|
|
letter-spacing: -0.01em;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.headline-sm {
|
|
@apply text-2xl font-normal;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.body-lg {
|
|
@apply text-lg font-normal;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.body-md {
|
|
@apply text-base font-normal;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.label-md {
|
|
@apply text-sm font-normal;
|
|
letter-spacing: 0.05em;
|
|
line-height: 1;
|
|
}
|
|
|
|
.mono-data {
|
|
@apply text-sm font-normal;
|
|
font-family: 'Space Grotesk', monospace;
|
|
letter-spacing: 0.02em;
|
|
line-height: 1;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
}
|
|
|
|
/* Custom Industrial Scrollbar Styling per DESIGN.md */
|
|
::-webkit-scrollbar {
|
|
width: 8px;
|
|
height: 8px;
|
|
}
|
|
|
|
::-webkit-scrollbar-track {
|
|
background: var(--surface);
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb {
|
|
background: var(--outline-variant);
|
|
border-radius: 0;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb:hover {
|
|
background: var(--primary);
|
|
}
|
|
|
|
@layer utilities {
|
|
.text-fluid-lg {
|
|
font-size: clamp(1.125rem, 3cqi, 1.5rem);
|
|
}
|
|
|
|
.text-fluid-xl {
|
|
font-size: clamp(1.5rem, 5cqi, 2.25rem);
|
|
}
|
|
|
|
.card-title {
|
|
@apply text-base font-normal tracking-tight;
|
|
}
|
|
|
|
.card-subtitle {
|
|
@apply text-xs font-normal tracking-tight;
|
|
color: var(--muted);
|
|
margin-top: 0.125rem;
|
|
}
|
|
|
|
.legacy-mono-data {
|
|
@apply font-normal tracking-normal;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
}
|
|
|
|
/* Safe Area Insets for Modern Mobile Devices */
|
|
.pb-safe {
|
|
padding-bottom: env(safe-area-inset-bottom);
|
|
}
|
|
|
|
.pt-safe {
|
|
padding-top: env(safe-area-inset-top);
|
|
}
|
|
|
|
/* Accessibility: Respect user's reduced motion preference */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
*,
|
|
*::before,
|
|
*::after {
|
|
animation-duration: 0.01ms !important;
|
|
animation-iteration-count: 1 !important;
|
|
transition-duration: 0.01ms !important;
|
|
}
|
|
|
|
.animate-scan-fast,
|
|
.animate-spin-slow,
|
|
.animate-pulse {
|
|
animation: none !important;
|
|
}
|
|
}
|