refactor: consolidate color definitions into single source of truth

- 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>
This commit is contained in:
2026-04-25 17:31:25 +03:00
parent de1708a754
commit e715afd814
11 changed files with 281 additions and 264 deletions

View File

@@ -1,4 +1,6 @@
import type { Config } from "tailwindcss";
// @ts-ignore - colors.mjs uses ESM exports, TypeScript may warn but it works at runtime
import { colors as colorsDefinition } from "./colors.mjs";
const config: Config = {
content: [
@@ -38,90 +40,7 @@ const config: Config = {
fontFamily: {
sans: ["'Space Grotesk'", "sans-serif"],
},
colors: {
// Base colors from DESIGN.md
background: "#131313",
"on-background": "#e5e2e1",
foreground: "#e5e2e1",
// Surface tones from DESIGN.md
surface: {
DEFAULT: "#131313",
dim: "#131313",
bright: "#3a3939",
"container-lowest": "#0e0e0e",
"container-low": "#1c1b1b",
container: "#201f1f",
"container-high": "#2a2a2a",
"container-highest": "#353534",
variant: "#353534",
},
// Primary colors from DESIGN.md
primary: {
DEFAULT: "#ffb781",
foreground: "#4e2600",
container: "#f58618",
"on-container": "#5b2d00",
fixed: "#ffdcc4",
"fixed-dim": "#ffb781",
"on-fixed": "#2f1400",
"on-fixed-variant": "#6f3800",
inverse: "#924c00",
},
// Secondary colors from DESIGN.md
secondary: {
DEFAULT: "#c8c6c5",
foreground: "#303030",
container: "#474746",
"on-container": "#b7b5b4",
fixed: "#e5e2e1",
"fixed-dim": "#c8c6c5",
"on-fixed": "#1b1c1c",
"on-fixed-variant": "#474746",
},
// Tertiary colors from DESIGN.md
tertiary: {
DEFAULT: "#00e639",
foreground: "#003907",
container: "#00bd2d",
"on-container": "#00440a",
fixed: "#72ff70",
"fixed-dim": "#00e639",
"on-fixed": "#002203",
"on-fixed-variant": "#00530e",
},
// Error colors from DESIGN.md
error: {
DEFAULT: "#ffb4ab",
foreground: "#690005",
container: "#93000a",
"on-container": "#ffdad6",
},
// Outline colors from DESIGN.md
outline: "#a48c7c",
"outline-variant": "#564335",
// Semantic surface colors (for compatibility)
muted: {
DEFAULT: "#474746",
foreground: "#a48c7c",
},
border: {
DEFAULT: "#353534",
strong: "#ffb781",
},
success: {
DEFAULT: "#00e639",
foreground: "#003907",
},
warning: "#ffb781",
info: "#c8c6c5",
},
colors: colorsDefinition,
keyframes: {
scan: {
'0%, 100%': { top: '0%' },