/* Amproteq Studio design tokens.
 *
 * Every variable NAME here matches the forked component stylesheets, so the
 * panels, cards, badges and grade chips inherited from the sibling platform
 * re-skin by loading this file instead of theirs. Only the values change.
 *
 * Values are sampled from the live Amproteq marketing site (assets/site.css) so
 * the platform and the site are visibly one product: a customer who clicks
 * "model my site" should not feel they have left.
 *
 * The site is dark only and has no light mode. A theme toggle is therefore NOT
 * provided — a half-built light theme reads worse than none.
 */

:root {
  /* ── Surfaces ─────────────────────────────────────────────────────────── */
  --bg-deep: #05070c;
  --bg-surface: #080c14;
  --bg-surface-2: #0c121c;
  --bg-surface-3: #111925;
  --bg-elevated: #16202e;

  /* ── Brand ────────────────────────────────────────────────────────────────
   * Cyan is the accent; azure is its deep end. The site's signature is the
   * gradient between them, not either colour alone. */
  --cyan: #3cccfc;
  --cyan-lt: #7fe2fe;
  --azure: #1898fc;
  --deep: #0b6fd6;
  --grad: linear-gradient(100deg, #7fe2fe 0%, #3cccfc 42%, #1898fc 100%);
  --grad-r: linear-gradient(100deg, #3cccfc, #1898fc);

  /* The forked stylesheets call the primary accent "plasma". Kept as an alias
   * so their rules work untouched; new code should use --cyan. */
  --plasma: var(--cyan);
  --plasma-dim: var(--azure);
  --plasma-glow: rgba(60, 204, 252, 0.2);
  --plasma-wash: rgba(60, 204, 252, 0.08);

  /* Secondary series colour. In the sibling platform this was a muted rose;
   * Amproteq has no rose, so it maps to the site's violet data-series colour. */
  --wire: #9c8cff;
  --wire-dim: #6f62c4;
  --wire-glow: rgba(156, 140, 255, 0.2);
  --wire-wash: rgba(156, 140, 255, 0.08);

  /* ── Status ────────────────────────────────────────────────────────────── */
  /* `--signal` WAS #5fd69a, a green, kept on the argument that a 6px status dot
   * is not a brand surface. Build contract V5 §5 closes that loophole: "No
   * green in the palette. Green is another brand." It is now the brand cyan.
   * The NAME is kept because `.badge-good` and three other stylesheets
   * reference it; only the value changed, so nothing breaks and no green is
   * rendered anywhere in the product. */
  --signal: #3cccfc;
  --signal-dim: #1898fc;
  --signal-glow: rgba(60, 204, 252, 0.2);
  --amber: #ffb63d;
  --amber-glow: rgba(255, 182, 61, 0.2);
  --red: #ff6b6b;
  --red-glow: rgba(255, 107, 107, 0.2);
  --yellow: #ffd166;

  /* ── Semantic colour: the meanings that must not drift ─────────────────────
   * Contract V5 §3: "Peak / standard / off-peak must be the same three colours
   * everywhere in the product. Import and export never share a hue. A loss is
   * warm, a gain is cool."
   *
   * These are the one definition. charts.js resolves them at build time (a
   * canvas cannot read a CSS custom property) and exports them as named
   * constants so a chart in any stream reaches for the same value a panel's
   * legend swatch does.
   *
   * TIME OF USE. Ordered by cost, so the ramp itself carries the meaning:
   * expensive is hot amber, cheap is deep azure, and the middle is neutral
   * violet. Deliberately NOT three tints of cyan — three tints of one hue are
   * indistinguishable in a 4px band, which is exactly how a TOU underlay has
   * to work. */
  --tou-peak: #ffb63d;
  --tou-standard: #9c8cff;
  --tou-offpeak: #1f6ea8;
  --tou-peak-wash: rgba(255, 182, 61, 0.14);
  --tou-standard-wash: rgba(156, 140, 255, 0.11);
  --tou-offpeak-wash: rgba(31, 110, 168, 0.16);

  /* POWER DIRECTION. Import is what you pay for and export is what you send
   * back; they never share a hue, so a stacked dispatch chart reads without a
   * legend. Charge and discharge follow the same logic one level down. */
  --flow-import: #ff8a5c;
  --flow-export: #3cccfc;
  --flow-charge: #1898fc;
  --flow-discharge: #7fe2fe;
  --flow-load: #c4d2e4;
  --flow-solar: #ffd166;

  /* LOSS AND GAIN. Warm loses, cool gains — the same pair a waterfall, a
   * delta tag and a tooltip all use. */
  --loss: #ff8a5c;
  --gain: #3cccfc;
  --loss-wash: rgba(255, 138, 92, 0.13);
  --gain-wash: rgba(60, 204, 252, 0.12);

  /* NOT MODELLED. The third state every series needs: a stage the engine
   * DECLINED to compute. It draws grey with its reason in the tooltip, never
   * as a zero — a silent zero and a modelled zero look identical, and only one
   * of them is honest. Matches `quantity().is-null` so a null figure and a
   * null bar are visibly the same claim. */
  --not-modelled: #46566d;
  --not-modelled-wash: rgba(70, 86, 109, 0.22);

  /* The sequential ramp for a heat map, perceptually ordered from the surface
   * colour through azure and cyan to amber. No green stop. */
  --heat-0: #0c121c;
  --heat-1: #143a58;
  --heat-2: #1b74b8;
  --heat-3: #3cccfc;
  --heat-4: #ffb63d;

  /* ── Text ─────────────────────────────────────────────────────────────── */
  --text: #eef3fa;
  --text-dim: #c4d2e4;
  --text-secondary: #8595b2;
  --text-muted: #8595b2;
  /* The quietest text still has to be READ: WCAG AA wants 4,5:1. #3a4759 was
   * 2,1:1 on the page and 1,9:1 on a card, and it carried hints, the optional
   * rail steps and the privacy line under the bill door. #7788a1 clears 4,5:1
   * on every surface up to --bg-elevated (5,6:1 on the page, 4,9:1 on a
   * card's top edge), and stays a step below --text-secondary (6,7:1). */
  --text-faint: #7788a1;

  /* ── Borders ───────────────────────────────────────────────────────────────
   * Blue-tinted alpha whites, never neutral grey: on a near-black navy ground a
   * grey rule reads brown. */
  --border: rgba(150, 190, 255, 0.2);
  --border-soft: rgba(150, 190, 255, 0.1);
  --border-neon: rgba(150, 190, 255, 0.36);

  /* ── Type ──────────────────────────────────────────────────────────────────
   * Jost for display, Inter for body, JetBrains Mono for micro-labels and every
   * number. Mono is the one family shared with the sibling platform. */
  --font-heading: 'Jost', system-ui, sans-serif;
  --font-display: 'Jost', system-ui, sans-serif;
  --font-body: 'Inter', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, monospace;

  --fs-xs: 11px;
  --fs-sm: 12px;
  --fs-base: 13px;
  --fs-md: 14px;
  --fs-lg: 16px;
  --fs-xl: 20px;
  --fs-2xl: 28px;
  --fs-3xl: 40px;
  --fs-hero: 64px;

  /* Display type, clamped against viewport HEIGHT rather than width. In an
   * application that never scrolls, height is the scarce axis: a headline
   * sized off `vw` is what pushes the last row of a 1280x720 screen out of
   * sight while looking perfectly reasonable at 1440x900.
   *
   * 11px is the floor for a mono micro-label and 12.5px for prose — below
   * that the contract says redesign, not shrink. */
  --fs-display: clamp(30px, 5.4vh, 50px);
  --fs-display-sm: clamp(21px, 3.1vh, 30px);
  --fs-micro: 11px;      /* mono micro-label: the floor, never go under it */
  --fs-prose: 12.5px;    /* prose floor */

  /* ── The figure scale ──────────────────────────────────────────────────────
   * Contract V5 §3, in the customer's words: "the numbers are too big … it
   * looks really unprofessional." `R 2 490 163` was rendering at ~40px tall
   * and ~380px wide in letter-spaced gradient display type — the least
   * informative thing on the screen and by far the largest.
   *
   * THE CAP IS --fs-figure. Nothing that prints a number may exceed it, and
   * the ceiling is 26px. Three steps, all mono, all tabular, none of them
   * letter-spaced:
   *
   *   --fs-figure     a screen's headline figure, and only one per screen
   *   --fs-figure-md  a metric card, a stat strip cell
   *   --fs-figure-sm  a dense definition row, a table cell
   *
   * The remedy for a screen that looks empty is never a larger font. It is
   * more information, in more columns, at the same size. */
  --fs-figure: clamp(19px, 2.6vh, 26px);
  --fs-figure-md: clamp(16px, 2vh, 19px);
  --fs-figure-sm: 14px;

  /* Tabular figures never track. Letter spacing belongs to eyebrows and
   * micro-labels, which is what --ls-wider is for. A figure that needs 380px
   * of width is a figure nobody can compare against the one beside it. */
  --ls-figure: 0;

  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;

  /* Display leading, and the trim that makes it legal.
   *
   * MEASURED, in this browser, against the three families we ship: Jost's
   * glyph box is ~1.37em, JetBrains Mono's ~1.25em, Inter's ~1.12em. A line
   * box shorter than the glyph box means the text really does overflow its
   * own element — invisibly, with nothing clipped and no scrollbar — and
   * contract §1's self-check flags exactly that. The old --lh-tight of 1.15
   * failed it on every Jost heading on every screen in the product.
   *
   * The fix is not to loosen the leading to 1.37 and lose the display voice.
   * It is to keep the tight line box and absorb the glyph overhang in
   * padding: `line-height: var(--lh-tight); padding-block: var(--lh-trim)`.
   * 1.08 + 2 x 0.16 = 1.40em of box against 1.37em of glyph — it passes at
   * every size, because both terms are in em and the check's tolerance is
   * the only thing that is absolute. For a heading of three 48px lines this
   * is 171px where loosening the leading would cost 197px.
   *
   * Applied to h1-h4 in app.css and to the numeric classes in
   * components.css. Anything else that sets a line-height below ~1.4 on Jost
   * or below ~1.28 on mono must pair it with the same padding — the
   * `.lh-trim` utility in components.css exists for that.
   *
   * SETTING `padding` ON A HEADING REMOVES THE TRIM and the overflow comes
   * back. Use padding-inline, or re-apply padding-block: var(--lh-trim). */
  --lh-tight: 1.08;
  --lh-trim: 0.16em;
  --lh-normal: 1.45;
  --lh-relaxed: 1.62;

  /* SINGLE-LINE leading. `line-height: 1` on a micro-label is the same bug as
   * --lh-tight on a heading, just two pixels smaller: an 11px mono label has
   * an 11px line box and a 13.75px glyph box, so it overflows itself and the
   * self-check flags it — nine times over in the rail alone.
   *
   * For a label that is always one line, a containing line-height and the
   * padding trim produce exactly the same box height, so use these: they are
   * one declaration instead of two, and unlike padding they cannot be
   * clobbered by a later `padding:` shorthand. Reach for --lh-trim only where
   * the text can wrap and the tight stack is worth keeping. */
  --lh-mono: 1.30;   /* JetBrains Mono's glyph box is ~1.25em */
  --lh-jost: 1.42;   /* Jost's is ~1.37em */

  /* Display type tightens as it grows — the site's signature. Eyebrows and
   * micro-labels track the other way, wide and uppercase. */
  --ls-tight: -0.018em;
  --ls-normal: 0;
  --ls-wide: 0.04em;
  --ls-wider: 0.18em;

  /* ── Space and radii ──────────────────────────────────────────────────── */
  --sp-0: 0;
  --sp-1: 2px;
  --sp-2: 4px;
  --sp-3: 8px;
  --sp-4: 12px;
  --sp-5: 16px;
  --sp-6: 24px;
  --sp-7: 32px;
  --sp-8: 48px;
  --sp-9: 64px;

  --r-0: 0;
  --r-1: 2px;
  --r-2: 4px;
  --r-3: 6px;
  --r-4: 8px;
  --r-5: 12px;
  --r-6: 16px;
  --r-full: 999px;

  /* ── Elevation ────────────────────────────────────────────────────────── */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.45);
  --shadow-lg: 0 14px 40px -12px rgba(0, 0, 0, 0.6);
  --shadow-neon: 0 8px 28px -10px rgba(24, 152, 252, 0.62);

  /* ── Motion ────────────────────────────────────────────────────────────────
   * The site's expo-out ease, and its slower durations. An instrument panel
   * wants faster transitions than a scroll story, so the fast step is kept
   * short and only the slow step carries the site's character. */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0.05, 0.36, 1);
  --dur-fast: 140ms;
  --dur: 260ms;
  --dur-slow: 520ms;

  /* ── Stacking ─────────────────────────────────────────────────────────── */
  --z-base: 1;
  --z-map: 10;
  --z-overlay: 100;
  --z-panel: 200;
  --z-dock: 300;
  --z-modal: 500;
  --z-palette: 600;
  --z-toast: 700;
  --z-onboarding: 800;

  /* ── Layout ────────────────────────────────────────────────────────────────
   * The header was two rows and 112px tall. It is now ONE dense row: the
   * lockup, the state chips, the KPI strip and the actions, side by side.
   * Every pixel spent here is a pixel the stage does not have, and the stage
   * is the only part of this product anybody came to look at. */
  --h-header: clamp(50px, 6.6vh, 60px);
  --h-dock: 200px;
  --w-rail: 84px;   /* V7: sentence-case labels ("Business case") need the room */
  --w-left: clamp(280px, 23vw, 340px);
  --w-right: clamp(320px, 27vw, 420px);
  --maxw: 1380px;
  --gut: clamp(20px, 5vw, 80px);

  /* Vertical rhythm for a viewport-locked screen. Anything laid out down the
   * page uses these rather than the fixed --sp scale, so a screen that fits
   * at 900px tall also fits at 720px instead of merely clipping. */
  --stage-pad-y: clamp(14px, 3.4vh, 38px);
  --stage-pad-x: clamp(18px, 3.2vw, 56px);
  --row-gap: clamp(8px, 1.6vh, 20px);

  /* ── Density ───────────────────────────────────────────────────────────────
   * Contract V5 §3: "A screen that is more than a third empty at 1600×950 is
   * unfinished." These are the measurements that make a dense grid possible
   * without every stream inventing its own.
   *
   * --col-metric is the width at which a metric card still reads — below it
   * a seven-digit rand figure wraps. --col-def is the width of a definition
   * column, chosen so twelve rows stack in a 420px column with room for the
   * label. */
  --col-metric: 178px;
  --col-def: 260px;
  --grid-gap: clamp(8px, 0.9vw, 14px);

  /* Chart hosts. A chart NEVER takes its height from a fractional grid row —
   * `minmax(0, 1fr)` resolves to ZERO when the content exceeds the container,
   * and ECharts paints nothing at all in a zero-height box, silently. The
   * floor is a real pixel minimum; the working height is set in JS from the
   * declared aspect ratio. See kit.chartFrame(). */
  --chart-h-sm: 120px;
  --chart-h: 200px;
  --chart-h-lg: 300px;
}

/* Respect a reduced-motion preference everywhere at once, rather than leaving
 * it to each surface to remember. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-fast: 0ms;
    --dur: 0ms;
    --dur-slow: 0ms;
  }
}
