/* Copyright (c) 2025-2026, RTE (https://www.rte-france.com) This Source Code Form is subject to the terms of the Mozilla Public License, version 2.0. If a copy of the Mozilla Public License, version 2.0 was not distributed with this file, you can obtain one at http://mozilla.org/MPL/2.0/. SPDX-License-Identifier: MPL-2.0 Design tokens — single source of truth for color, spacing, type, radius. Why this file exists: docs/proposals/ui-design-critique.md flagged 273 hex literals across 24 files (three competing palettes: Flat UI, Bootstrap, Tailwind). All blues consolidate onto the Tailwind blue ramp (closest fit to existing values — #1e40af and #dbeafe are already on it). How to consume: - Inside .css files: color: var(--color-brand); - Inside inline styles: color: 'var(--color-brand)' (or import { colors } from 'styles/tokens') How to extend: add a NEW token here before introducing a new hex in a component. The check_code_quality.py gate ratchets down the remaining hex-literal count after each migration. */ :root { /* ----- Color: surfaces ----- */ --color-surface: #ffffff; --color-surface-muted: #f8f9fa; --color-surface-raised: #fcfcfc; /* Backdrop behind the pypowsybl NAD/SLD diagram. White in light mode; flipped dark by [data-theme="dark"] below. The diagram SVG itself is transparent, so this token IS the diagram background. */ --color-diagram-surface: #ffffff; /* Semi-opaque veil painted over the diagram while a new one loads (dims the stale diagram). Translucent so the old SVG shows through. */ --color-diagram-veil: rgba(255, 255, 255, 0.85); /* ----- Color: borders ----- */ --color-border: #cccccc; --color-border-subtle: #eeeeee; --color-border-strong: #999999; /* ----- Color: text ----- */ --color-text-primary: #1f2937; --color-text-secondary: #555555; --color-text-tertiary: #888888; --color-text-on-brand: #ffffff; /* Dark ink for text sitting on a bright, solid fill (warning yellow, notice badge, etc.). Stays dark in BOTH themes because those fills are bright in both — unlike the *-text tokens which are tuned for the matching *-soft background and flip light in dark mode. */ --color-text-on-bright: #1f2937; /* ----- Color: brand (Tailwind blue ramp) ----- */ --color-brand: #1e40af; /* blue-800 — primary links + active CTAs */ --color-brand-strong: #1d4ed8; /* blue-700 — hover / pressed */ --color-brand-soft: #dbeafe; /* blue-100 — selection bg, hint pills */ --color-brand-mid: #3b82f6; /* blue-500 — fills (slider, range bar) */ /* ----- Color: state — success ----- */ --color-success: #28a745; --color-success-strong: #2e7d32; --color-success-soft: #d1fae5; --color-success-text: #065f46; /* ----- Color: state — warning ----- */ --color-warning: #ffc107; --color-warning-strong: #f0ad4e; --color-warning-soft: #fff3cd; --color-warning-border: #ffeeba; --color-warning-text: #856404; /* ----- Color: state — danger ----- */ --color-danger: #dc3545; --color-danger-strong: #b91c1c; --color-danger-soft: #f8d7da; --color-danger-text: #c62828; /* ----- Color: accent + chrome ----- */ --color-accent: #8e44ad; /* save/secondary action */ --color-accent-soft: #f3e8ff; /* PST tap-edit row bg */ --color-accent-border: #c084fc; /* PST tap-edit row border */ --color-accent-text: #6b21a8; /* PST tap-edit row text */ --color-chrome: #2c3e50; /* header / dark backgrounds */ --color-chrome-soft: #7f8c8d; /* settings cog, neutral chrome */ --color-disabled: #95a5a6; /* disabled buttons */ /* ----- Color: info (cyan — distinct from brand blue) ----- Used by curtailment edit rows and metric badges where the intent is "informational" rather than "primary action". */ --color-info: #0284c7; --color-info-soft: #e0f2fe; --color-info-border: #7dd3fc; --color-info-text: #075985; /* ----- Spacing (4 / 8 grid) ----- */ --space-0: 0; --space-half: 2px; /* tight cases (badge padding, inline gaps) */ --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 20px; --space-6: 24px; --space-7: 32px; /* ----- Type sizes ----- */ --text-xs: 11px; --text-sm: 12px; --text-md: 14px; --text-lg: 16px; --text-xl: 20px; --text-xxl: 24px; /* ----- Radii ----- */ --radius-sm: 4px; --radius-md: 6px; --radius-lg: 8px; /* ----- Diagram-signal colors (domain-specific, not semantic state) ----- Used by NAD/SLD highlight CSS in App.css. These are visual signals for grid concepts (contingency, action target, overload, breaker) and intentionally bright/saturated to read on top of the diagram. */ --signal-overload: #ff8c00; --signal-contingency: #ffe033; --signal-action-target: #ff4081; --signal-action-target-strong: #ec407a; --signal-action-target-darker: #ad1457; --signal-action-target-soft: #fce4ec; --signal-breaker: #ce93d8; --signal-delta-positive: #ff9800; --signal-delta-negative: #2196f3; --signal-delta-neutral: #999999; /* ----- SLD interactive topology-edit highlight ----- The interactive SLD-edit feature (useSldTopologyEdit + SldEditPanel) stages switch toggles + injection (load / generator) active-power retunes in the frontend and visually marks the pending element. Distinct hues from action / contingency / overload so a toggled switch on an overloaded line still reads as both. */ --signal-edit-open: #d81b60; --signal-edit-closed: #1976d2; --signal-edit-injection: #00897b; /* ----- Action-overview pin palette ----- Severity buckets for Remedial Action overview pins (utils/svg/actionPin{Data,Render}.ts + ActionOverviewDiagram.tsx). Three triplets per bucket: base, dimmed (rejected / filtered-out), highlighted (selected on hover). The TS mirror in tokens.ts is the runtime source of truth because pin fills are written to raw SVG `fill="…"` attributes via setAttribute, which doesn't reliably resolve var() across older browsers. CSS variables here are kept in sync for any future CSS-only consumers. */ --pin-green: #28a745; --pin-orange: #f0ad4e; --pin-red: #dc3545; --pin-grey: #9ca3af; --pin-green-dimmed: #a3c9ab; --pin-orange-dimmed: #dcd0b8; --pin-red-dimmed: #d4a5ab; --pin-grey-dimmed: #c8cdd2; --pin-green-highlighted: #1e9e3a; --pin-orange-highlighted: #e89e20; --pin-red-highlighted: #c82333; --pin-grey-highlighted: #7b8a96; --pin-glyph-bg: #ffffff; /* white inner circle behind label */ --pin-glyph-text: #1f2937; /* label text (= text-primary) */ --pin-stroke-neutral: #6b7280; /* unsimulated pin outline */ --pin-gold: #eab308; /* selected-pin star fill + outline */ --pin-gold-dark: #a16207; /* selected-pin star stroke */ --pin-cross-fill: #ef4444; /* rejected-pin cross fill */ --pin-cross-stroke: #b91c1c; /* rejected-pin cross stroke */ /* Vite template carryover — visible only during the first paint before body { background-color: var(--color-surface) } takes over. Kept as a token so the dark-mode initial-paint color has a name. */ --color-surface-dark: #242424; } /* ===== Dark theme ===== Engaged via ``, set by useTheme + the pre-mount script in index.html. Only chrome tokens flip — domain signals (overload / contingency / action-target / pin palette) stay identical because pypowsybl SVGs render on a light backdrop and the colors encode semantic state. The diagram container keeps `colors.surface` here = light grey-blue so flow arrows / delta colors keep their meaning. */ [data-theme="dark"] { /* Surfaces — app shell is dark; the diagram backdrop goes near-black (see --color-diagram-surface) so voltage-coded lines pop. */ --color-surface: #1b1f24; /* base app background */ --color-surface-muted: #232830; /* sidebar / cards */ --color-surface-raised: #2a3038; /* hover / raised tiles */ --color-diagram-surface: #0c0f13; /* near-black diagram backdrop */ --color-diagram-veil: rgba(12, 15, 19, 0.78); /* Borders */ --color-border: #3a4049; --color-border-subtle: #2d333b; --color-border-strong: #555c66; /* Text — high-contrast on the dark surfaces above. */ --color-text-primary: #e6e8eb; --color-text-secondary: #b5bac1; --color-text-tertiary: #8b9098; --color-text-on-brand: #ffffff; /* Brand — lift the Tailwind blue one step so it stays vivid on dark. */ --color-brand: #3b82f6; /* blue-500 — primary CTAs */ --color-brand-strong: #60a5fa; /* blue-400 — hover */ --color-brand-soft: #1e3a8a; /* blue-900 — selection bg */ --color-brand-mid: #60a5fa; /* slider / range fills */ /* Success / Warning / Danger / Info — keep hue, deepen the soft backgrounds so badge text stays readable on dark cards. */ --color-success: #22c55e; --color-success-strong: #16a34a; --color-success-soft: #14532d; --color-success-text: #bbf7d0; --color-warning: #facc15; --color-warning-strong: #eab308; --color-warning-soft: #422006; --color-warning-border: #713f12; --color-warning-text: #fde68a; --color-danger: #ef4444; --color-danger-strong: #dc2626; --color-danger-soft: #4c1d1d; --color-danger-text: #fecaca; --color-accent: #c084fc; /* save/secondary action */ --color-accent-soft: #3b1f5c; --color-accent-border: #7e22ce; --color-accent-text: #e9d5ff; --color-chrome: #0f1419; /* header background */ --color-chrome-soft: #4a5159; /* settings cog */ --color-disabled: #4b5563; --color-info: #38bdf8; --color-info-soft: #0c3445; --color-info-border: #075985; --color-info-text: #bae6fd; }