/* Electric Cherry — design tokens. This file is the single source of truth for color, type, spacing, motion, and elevation. It's organized in three layers: 1. RAW RAMPS — the actual color/type/space values. Never referenced directly by components. 2. SEMANTIC ALIASES — what components should reference (--surface, --text-primary, --state-online, --space-4, etc.). Swapping the palette or spacing rhythm later is a single-file edit. 3. LEGACY ALIASES — old names (--bg-page, --accent, --ink-300, --pad-card…) mapped onto new semantic values. Kept alive so existing components render during the phased redesign; each page rewrite removes its usage, and this block shrinks over time. Design principles this file encodes: · One accent (blue). Cyan/amber/red/green mean state only. · Depth by light, not lines. One ambient shadow + subtle translucency. · One typeface (Inter). Mono for data. Display face lives inside BrandMark. · Motion tokens standardize easings + durations across the product. */ :root { /* ---------- 1. RAW RAMPS ---------- */ /* Blue — one hue, five stops. Brand primary + focus/link. */ --blue-950: #060b16; --blue-900: #0d1826; --blue-700: #1c3d6b; --blue-500: #4da3e6; --blue-300: #7cc0f5; /* Neutral gray — cool-tinted, distinct from the blue ramp so surfaces stop being tinted-blue on tinted-blue. */ --gray-975: #08090c; --gray-950: #0d0f14; --gray-925: #12151c; --gray-900: #171b24; --gray-850: #1f242f; --gray-800: #262c39; --gray-700: #363d4d; --gray-500: #6b7488; --gray-400: #8892a5; --gray-300: #a8b2c4; --gray-200: #c5cddc; --gray-100: #dfe4ee; --gray-050: #eef2f8; /* State — reserved for actual state, never decoration. */ --state-online: #7cd4ff; --state-warning: #ffb020; --state-danger: #ff5670; --state-restarting: #7cc0f5; /* ---------- 2. SEMANTIC ALIASES ---------- */ /* Surfaces — three tiers of depth, all near-black cool gray. */ --surface-sunken: var(--gray-975); --surface: var(--gray-925); --surface-raised: var(--gray-850); --surface-overlay: var(--gray-800); /* Text — four steps of hierarchy on dark. */ --text-primary: var(--gray-050); --text-secondary: var(--gray-300); --text-tertiary: #98a4b8; --text-quaternary: var(--gray-400); --text-on-accent: #08111f; /* Border — hairlines, no more. */ --border-subtle: rgba(255, 255, 255, 0.06); --border-strong: rgba(255, 255, 255, 0.12); --border-focus: var(--blue-500); --border-control: #576176; --border-control-hover: #78869f; /* Accent — one color, one voice. */ --accent-primary: var(--blue-500); --accent-primary-hover: var(--blue-300); --accent-primary-active: #398fcf; /* Typography — Inter everywhere, mono for data. Display face lives inside BrandMark; no global --font-display token. */ --font-body: 'Inter', system-ui, -apple-system, sans-serif; --font-numeric: 'Inter', system-ui, -apple-system, sans-serif; --font-mono: 'JetBrains Mono', ui-monospace, monospace; /* Type scale — cleaner ramp anchored at 15px body. */ --text-xs: 12px; --text-sm: 13px; --text-base: 15px; --text-md: 17px; --text-lg: 20px; --text-xl: 24px; --text-2xl: 32px; --text-3xl: 44px; --leading-tight: 1.15; --leading-body: 1.55; --leading-mono: 1.5; --tracking-tight: -0.01em; --tracking-normal: 0; --tracking-wide: 0.02em; --tracking-label: 0.08em; /* Weight scale — one variable at each rung so intent is legible. */ --weight-regular: 400; --weight-medium: 500; --weight-semibold: 600; --weight-bold: 700; /* Spacing — strict 8pt grid (with 4pt half-step). */ --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 20px; --space-6: 24px; --space-8: 32px; --space-10: 40px; --space-12: 48px; --space-16: 64px; --space-24: 96px; /* Radii — three steps + pill. Softer than the old 4/8/12. */ --radius-sm: 6px; --radius-md: 10px; --radius-lg: 16px; --radius-pill: 999px; /* Elevation — two shadows only, ambient + raised. No glow rings. */ --shadow-ambient: 0 1px 2px rgba(0, 0, 0, 0.35), 0 4px 12px rgba(0, 0, 0, 0.22); --shadow-raised: 0 2px 4px rgba(0, 0, 0, 0.4), 0 12px 28px rgba(0, 0, 0, 0.32); /* Motion — standardized easings + durations. Apple-esque out-quart. */ --ease-standard: cubic-bezier(0.22, 1, 0.36, 1); --ease-emphasized: cubic-bezier(0.16, 1, 0.3, 1); --ease-linear: linear; --dur-instant: 80ms; --dur-fast: 160ms; --dur-base: 240ms; --dur-slow: 360ms; --dur-slower: 560ms; /* Focus ring — 2px accent, 2px offset, everywhere. */ --focus-ring: 0 0 0 2px var(--surface), 0 0 0 4px var(--accent-primary); /* ---------- 3. LEGACY ALIASES ---------- Old token names, mapped onto new semantic values so components that haven't been rewritten yet keep rendering. Delete entries as pages migrate; the block should be empty at the end of Phase 8. */ /* Old blue ramp names */ --blue-975: var(--gray-975); --blue-925: var(--gray-950); --blue-875: var(--gray-925); --blue-825: var(--gray-850); --blue-600: #256cae; --blue-400: var(--blue-300); /* Old spark/cherry/amber names */ --spark-500: var(--state-online); --spark-400: #a8e5ff; --spark-glow: 0 0 8px rgba(124, 212, 255, 0.45); --spark-glow-lg: 0 0 14px rgba(124, 212, 255, 0.35); --cherry-500: var(--state-danger); --cherry-400: #ff7590; --cherry-300: #ff9db0; --amber-500: var(--state-warning); --amber-glow: 0 0 8px rgba(255, 176, 32, 0.32); --danger-500: var(--state-danger); --success-500: #4ade80; /* Old neutral names */ --cream: var(--text-primary); --cream-dim: var(--gray-200); --ink-100: var(--text-primary); --ink-300: var(--text-secondary); --ink-500: var(--text-tertiary); --ink-700: var(--text-quaternary); /* Old surface/border/accent aliases */ --bg-page: var(--surface-sunken); --bg-nav: var(--surface); --bg-card: var(--surface); --bg-card-hi: var(--surface-raised); --border: var(--border-subtle); --border-hi: var(--border-strong); --accent: var(--accent-primary); --accent-hi: var(--accent-primary-hover); --accent-glow: 0 0 0 1px rgba(46, 134, 209, 0.35); --accent-glow-lg: 0 0 0 1px rgba(46, 134, 209, 0.28); /* Old typography names */ --font-display: 'Alfa Slab One', 'Georgia', serif; --text-mono: 13px; --text-mono-sm: 12px; --tracking-display: 0.12em; --tracking-nav: 0.03em; /* Old spacing/radii names */ --pad-card: var(--space-5); --pad-panel: var(--space-6); --pad-nav-y: var(--space-4); --pad-nav-x: var(--space-8); --gap-section: var(--space-8); --gap-cards: var(--space-4); --r-sm: var(--radius-sm); --r-md: var(--radius-md); --r-lg: var(--radius-lg); --shadow-card: var(--shadow-ambient); --shadow-panel: var(--shadow-raised); } /* Keyframes — pared down. Legacy names kept so existing components animate; the new StatusPip uses `pip-breathe` (opacity-only, GPU-cheap). */ @keyframes pip-breathe { 0%, 100% { opacity: 0.35; transform: scale(1); } 50% { opacity: 0.9; transform: scale(1.4); } } @keyframes shimmer { from { background-position: -200% 0; } to { background-position: 200% 0; } } /* Legacy — retained until ServerCard/BrandMark/StatusDot are replaced. */ @keyframes electric-pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(124, 212, 255, 0.5); } 50% { box-shadow: 0 0 0 5px rgba(124, 212, 255, 0); } } @keyframes cherry-fizz { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-1px); } } @keyframes spark-slide { from { background-position: -100% 0; } to { background-position: 200% 0; } } /* Reduced motion — neutralize all animation. Components that respect this token get calm behavior for free; the media query below handles the ones that don't. */ @media (prefers-reduced-motion: reduce) { :root { --dur-instant: 0.01ms; --dur-fast: 0.01ms; --dur-base: 0.01ms; --dur-slow: 0.01ms; --dur-slower: 0.01ms; } *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } }