/* ── Nxt design tokens — THE Blazor palette (#2574) ─────────────────────────────────────────
   The one `:root` every Blazor host links. It is the CSS twin of
   Nxt.Presentation.Wpf/Themes/Default.xaml, and the two are compared BY VALUE, pair by pair,
   in DesignTokenVocabularyTests.

   Why it lives HERE, in Common. Until #2574 the definitions were spread over three files —
   Nxt.Devices.Presentation.Blazor/wwwroot/css/devices.css (53), the OperationTester's
   wwwroot/css/tester.css (36) and the DeviceTester's (7, all aliases). Adding an application shell
   would have made it four. It is not devices.css because an Application-layer shell taking its
   palette from a Drivers-area file is a layering inversion; the vocabulary belongs to the layer both
   the shell and the drivers sit on. Recorded in doc/Common/design-decisions.md.

   The rules, enforced rather than hoped for:
     · One value per token, one declaration per token. A custom property whose value is a colour or
       length LITERAL may occur only in this file — asserted repo-wide over every .css under src/.
     · Every token here either has a WPF twin in Themes/Default.xaml (MirroredTokens) or is declared
       Blazor-only with a reason (BlazorOnlyTokens). Both directions fail the build.
     · Light-only. One value per token; no @media (prefers-color-scheme) block. A dark value is a new
       decision and belongs in its own story.
     · Chrome and semantic are SEPARATE vocabularies. Nothing here may be named --nxt-semantic-* to
       express chrome: a pressed button and a failed operation are different kinds of thing. The
       semantic set is closed at the eight doc/Common/ui.md states plus the scenario tint, and that
       is asserted too.
   ────────────────────────────────────────────────────────────────────────────────────────────── */

/* ── The Nxt faces (#2962) ───────────────────────────────────────────────────────────────────
   Served by this library from wwwroot/fonts/<family>/, each beside its OFL.txt (SIL Open Font
   License 1.1). Variable fonts, so every weight a rule asks for is real rather than synthesised,
   and Newsreader's optical size follows the font size. Declared here, not in a sheet of their own,
   because every host already links this one. A src that 404s falls back silently;
   NxtBrandingTests asserts each file exists. */
@font-face {
  font-family: "Instrument Sans";
  src: url("../fonts/InstrumentSans/InstrumentSans-Variable.ttf") format("truetype");
  font-weight: 400 700;
  font-stretch: 75% 100%;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("../fonts/JetBrainsMono/JetBrainsMono-Variable.ttf") format("truetype");
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Newsreader";
  src: url("../fonts/Newsreader/Newsreader-Variable.ttf") format("truetype");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}

:root {
  /* ── Backgrounds ── */
  --nxt-bg-base:           #F3F3F3;   /* Nxt.Background.Base */
  --nxt-bg-panel:          #FFFFFF;   /* Nxt.Background.Panel */
  --nxt-bg-deep:           #ECEDED;   /* Nxt.Background.Deep */
  --nxt-bg-black:          #0D0D0D;   /* Nxt.Background.Black (#1340 — Connect toggle) */
  --nxt-bg-secondary:      #E7E8E9;   /* Nxt.Background.Secondary */
  --nxt-bg-sidebar:        #F3F3F3;   /* Nxt.Background.Sidebar */
  --nxt-bg-tab-inactive:   #F3F3F3;   /* Nxt.Background.Tab.Inactive */
  --nxt-bg-tab-active:     #FFFFFF;   /* Nxt.Background.Tab.Active */
  /* #1354 — the STANDARD operation-execution surface (framework chrome: state header, phase rail,
     progress, prompt-shell chrome, results grid, export bar). A light grey so the operation's OWN
     content — which stays on the white panel/card surface — visibly stands out against the
     framework. Moved here from the OperationTester's tester.css by #2574; it was never
     OperationTester-specific, only OperationTester-defined. */
  --nxt-surface-standard:  #EDEEF0;   /* Nxt.Surface.Standard */

  /* ── Borders ── */
  --nxt-border-primary:    #CFD1D3;   /* Nxt.Border.Primary */
  --nxt-border-secondary:  #C7C9CA;   /* Nxt.Border.Secondary */

  /* ── Text ── */
  --nxt-text-primary:      #343434;   /* Nxt.Text.Primary */
  --nxt-text-secondary:    #7E8184;   /* Nxt.Text.Secondary */
  --nxt-text-label:        #7E8184;   /* Nxt.Text.Label */
  --nxt-text-muted:        #A0A3A6;   /* Nxt.Text.Muted */
  --nxt-text-hint:         #A0A3A6;   /* Nxt.Text.Hint */
  --nxt-text-on-accent:    #FFFFFF;   /* Nxt.Text.OnAccent */
  --nxt-text-heading:      #0D0D0D;   /* Nxt.Text.Heading (#2951) */

  /* ── Typefaces (#2962): the face, then the fallback. Published through NxtUiTypography. ── */
  --nxt-font-ui:           "Instrument Sans", Arial, sans-serif;   /* Nxt.Font.Ui */
  --nxt-font-mono:         "JetBrains Mono", Consolas, monospace;   /* Nxt.Font.Mono */
  --nxt-font-figure:       "Newsreader", Georgia, serif;           /* Nxt.Font.Figure */

  /* ── Accent ── */
  --nxt-accent-primary:    #437BB5;   /* Nxt.Accent.Primary */
  --nxt-accent-secondary:  #0066CC;   /* Nxt.Accent.Secondary */
  --nxt-accent-secondary-soft:    #F2F7FC;   /* Nxt.Accent.SecondarySoft (#2951) */
  --nxt-accent-secondary-hover:   #0057AD;   /* Nxt.Accent.SecondaryHover (#2951) */
  --nxt-accent-secondary-pressed: #04478A;   /* Nxt.Accent.SecondaryPressed (#2951) */

  /* ── Chart pulse colours — distinct hues so Strong vs Weak read apart (#1183: strong=orange, weak=blue) ── */
  --nxt-chart-pulse-strong: #D98C00;  /* Nxt.Chart.PulseStrong (orange) */
  --nxt-chart-pulse-weak:   #2A78D6;  /* Nxt.Chart.PulseWeak (blue)  */
  --nxt-chart-pulse-none:   #B4B2A9;  /* Nxt.Chart.PulseNone (grey, unclassified #1191) */

  /* ── Semantic (ADR colour semantics — Nxt.Semantic.*) ──
     The CLOSED set: eight states plus the scenario tint. Adding a ninth is a recorded decision in
     doc/Common/design-decisions.md, not a reflex — and SemanticColourUsageTests asserts this set
     against the eight names doc/Common/ui.md publishes, in both renderers. */
  --nxt-semantic-error:      #D83B01;   /* Nxt.Semantic.Error */
  --nxt-semantic-inprogress: #FFB900;   /* Nxt.Semantic.InProgress */
  --nxt-semantic-active:     #50C878;   /* Nxt.Semantic.Active */
  --nxt-semantic-inactive:   #A0A3A6;   /* Nxt.Semantic.Inactive */
  --nxt-semantic-waiting:    #5B9BD5;   /* Nxt.Semantic.Waiting */

  /* #1511 (epic #1510, FR-002/003) — two ADDITIONS to the semantic vocabulary, for the execution
     footer's Scenario button. Mirrors the WPF Themes/Default.xaml keys byte-for-byte (WPF is leading).
     Both are deliberately NOT one of the five above — a safety argument, not taste
     (doc/Common/design-decisions.md):
       recording — a red for "capturing this run", kept SEPARATE from --nxt-semantic-error so the
                   recording red can never drift with the failure red as the palette is tuned.
       scenario  — a violet for "replaying a loaded scenario", because green already means Passed in
                   the header state circle in the SAME view, and a green "replaying" dot on a failed
                   run is the live-vs-replay confusion Repeatability exists to prevent. */
  --nxt-semantic-recording:  #E01B24;   /* Nxt.Semantic.Recording */
  --nxt-semantic-scenario:   #7C4DBE;   /* Nxt.Semantic.Scenario */

  /* #1593 — an EIGHTH key: warning, "caution about a consequence that has NOT happened yet". The
     vocabulary could say a failure occurred (error, past) and work is underway (inprogress, present)
     but had no future tense, so caution affordances borrowed a neighbour — #1581's confirm-before-flash
     strip took error, painting "about to do something irreversible" in the colour of "it already broke".
     Dark amber separates from inprogress (#FFB900) by LIGHTNESS and from error (#D83B01) by HUE, so it
     survives being adjacent to either. Mirrors the WPF Nxt.Semantic.Warning key byte-for-byte
     (WPF is leading) and is pinned by WarningSemanticTokenParityTests. */
  --nxt-semantic-warning:    #C77700;   /* Nxt.Semantic.Warning */

  /* #2951 — tones of four existing states, not new states: a notice is a -soft ground with -strong text.
     Opaque, unlike the -tint washes below, which composite over whatever is behind them. */
  --nxt-semantic-error-soft:      #F6E2D8;   /* Nxt.Semantic.ErrorSoft */
  --nxt-semantic-error-strong:    #A32C00;   /* Nxt.Semantic.ErrorStrong */
  --nxt-semantic-warning-soft:    #FCEFCF;   /* Nxt.Semantic.WarningSoft */
  --nxt-semantic-warning-strong:  #95590A;   /* Nxt.Semantic.WarningStrong */
  --nxt-semantic-active-soft:     #DCF3E5;   /* Nxt.Semantic.ActiveSoft */
  --nxt-semantic-active-strong:   #2C7A4B;   /* Nxt.Semantic.ActiveStrong */
  --nxt-semantic-waiting-soft:    #DFEAF6;   /* Nxt.Semantic.WaitingSoft */
  --nxt-semantic-waiting-strong:  #2F6899;   /* Nxt.Semantic.WaitingStrong */

  /* ── Overlay scrim (semi-transparent black for dimming behind overlays/modals) ── */
  --nxt-overlay-scrim:       rgba(0, 0, 0, 0.35);  /* Nxt.Overlay.Scrim (#59000000) */

  /* ── Buttons ── */
  --nxt-btn-hover:           #F4F5F6;   /* Nxt.Button.Hover */
  --nxt-btn-pressed:         #DEDEDE;   /* Nxt.Button.Pressed */
  --nxt-btn-primary-start:   #5499CD;   /* Nxt.Button.Primary.Start */
  --nxt-btn-primary-mid:     #3D85BE;   /* Nxt.Button.Primary.Mid */
  --nxt-btn-primary-end:     #2670AF;   /* Nxt.Button.Primary.End */
  --nxt-btn-primary-border:  #2267A2;   /* Nxt.Button.Primary.Border */

  /* ── Pills (Nxt.Pill.*) ── */
  --nxt-pill-active-bg:      #437BB5;   /* Nxt.Pill.Active.Background */
  --nxt-pill-spec-bg:        #10B981;   /* Nxt.Pill.Spec.Background */

  /* ── Banners ── */
  --nxt-banner-warn-bg:      #FEF3C7;   /* Nxt.Banner.Warning.Background */
  --nxt-banner-warn-text:    #92400E;   /* Nxt.Banner.Warning.Text */
  --nxt-banner-warn-border:  #FCD34D;   /* warning callout border (.nxt-banner-warn) */
  --nxt-banner-warn-accent:  #F59E0B;   /* warning callout left-accent bar */
  --nxt-banner-error-bg:     #FEE2E2;   /* Nxt.Banner.Error.Background */
  --nxt-banner-error-text:   #991B1B;   /* Nxt.Banner.Error.Text */
  --nxt-banner-error-border: #FCA5A5;   /* error callout border (.nxt-banner-error) */
  --nxt-banner-error-accent: #EF4444;   /* error callout left-accent bar */

  /* ── Shadows (#799 FR-004 — single source; no box-shadow literal at any call site) ── */
  --nxt-shadow-popup:         0 4px 12px rgba(0, 0, 0, 0.12);  /* floating popups (action-bar / readout / thumb / key) */
  --nxt-shadow-popup-overlay: 0 4px 12px rgba(0, 0, 0, 0.15);  /* connection-settings overlay (.nxt-popup-overlay) */
  --nxt-shadow-modal:         0 8px 24px rgba(0, 0, 0, 0.18);  /* centred scan-error modal (.dt-modal) */

  /* ── Derived tints (#799 FR-004 — color-mix keeps these a single derivation of the semantic
        token, so a palette change flows through automatically; no rgba literal at the call site) ── */
  --nxt-semantic-inprogress-tint: color-mix(in srgb, var(--nxt-semantic-inprogress) 8%, transparent);  /* busy underlay */
  /* #2574: 8%, the devices.css value. The OperationTester's own palette carried 12% and, loading after
     devices.css on the same :root, won there — an undocumented divergence rather than a decision. One
     palette holds one value, and 8% is the shared one. Error underlays on the OperationTester's Blazor
     host are correspondingly lighter; that is the ONE deliberate appearance change in #2574. */
  --nxt-semantic-error-tint:      color-mix(in srgb, var(--nxt-semantic-error) 8%, transparent);        /* error underlay */
  --nxt-semantic-active-tint:     color-mix(in srgb, var(--nxt-semantic-active) 12%, transparent);      /* passed underlay */
  --nxt-semantic-waiting-tint:    color-mix(in srgb, var(--nxt-semantic-waiting) 12%, transparent);     /* awaiting-operator underlay */
  /* #1511 (FR-002): the violet WASH behind a scenario-loaded Scenario button (its border + text use the
     full-strength token). Derived, so a palette change flows through — no rgba literal at the call site. */
  --nxt-semantic-scenario-tint:   color-mix(in srgb, var(--nxt-semantic-scenario) 10%, transparent);
  --nxt-text-on-accent-muted:     color-mix(in srgb, var(--nxt-text-on-accent) 75%, transparent);       /* unit suffix on an active pill */
  --nxt-accent-focus-ring:        color-mix(in srgb, var(--nxt-accent-primary) 25%, transparent);       /* focus OUTLINE colour */

  /* ══ Chrome: the control-face gradient stops (#2574) ═══════════════════════════════════════════
     The vocabulary the shell's control templates paint their FACES with, so #2575 maps named values
     instead of picking colours off a screenshot. A gradient ships as its STOPS, matching how
     --nxt-btn-primary-start/mid/end already work; the recipes are in doc/Common/ui.md.
     A stop that already has a token is not restated: the control face is #FFFFFF ->
     --nxt-bg-secondary -> #FFFFFF, and the accent face's middle stop is --nxt-btn-primary-end. */
  --nxt-chrome-shell-start:       #959FA5;   /* Nxt.Chrome.Shell.Start */
  --nxt-chrome-shell-end:         #BFC2C6;   /* Nxt.Chrome.Shell.End */
  --nxt-chrome-toolbar-end:       #EEEEEE;   /* Nxt.Chrome.Toolbar.End */
  --nxt-chrome-accent-face-start: #68BDFE;   /* Nxt.Chrome.AccentFace.Start */
  --nxt-chrome-accent-face-end:   #4294CE;   /* Nxt.Chrome.AccentFace.End */
  --nxt-chrome-dark-action-start: #B6BABC;   /* Nxt.Chrome.DarkAction.Start */
  --nxt-chrome-dark-action-mid:   #6D6D6A;   /* Nxt.Chrome.DarkAction.Mid */
  --nxt-chrome-dark-action-end:   #9C9EA1;   /* Nxt.Chrome.DarkAction.End */
  --nxt-chrome-tab-inactive-end:  #D5D6D7;   /* Nxt.Chrome.TabInactive.End */

  /* ══ Chrome: state colours (#2574) ═════════════════════════════════════════════════════════════
     The disabled BORDER and the focus-ring colour are deliberately absent: they are
     --nxt-border-secondary (#C7C9CA) and --nxt-accent-primary (#437BB5), which already carry those
     exact values. */
  --nxt-text-disabled:            #9A9A9A;   /* Nxt.Text.Disabled */
  --nxt-bg-selected:              #ADD8F9;   /* Nxt.Background.Selected */
  --nxt-border-row:               #A5A9AD;   /* Nxt.Border.Row */

  /* ══ Chrome: the four values #2575 needed and #2574 did not name ═══════════════════════════════
     --nxt-border-control is NOT --nxt-border-primary: #CFD1D3 is the hairline around a PANEL,
     #8F9295 is the outline of an interactive CONTROL, and the reference draws them two shades apart
     so a control reads as touchable against the panel it sits on.
     --nxt-border-list carries the same value as --nxt-text-muted and is still its own token, for the
     reason --nxt-semantic-recording is not --nxt-semantic-error: they mean unrelated things, and one
     token would couple them forever.
     --nxt-chrome-ink is ONE token for two uses (a list row's text, a check/radio's stroke) because
     the reference draws them in one value; it is named for the thing, not for either use. */
  --nxt-border-control:           #8F9295;   /* Nxt.Border.Control */
  --nxt-border-list:              #A0A3A6;   /* Nxt.Border.List */
  --nxt-chrome-ink:               #5D5D5D;   /* Nxt.Chrome.Ink */
  --nxt-icon-disabled:            #AEAEAE;   /* Nxt.Icon.Disabled */

  /* The focus GLOW. Its WPF twin is a DropShadowEffect, and a DropShadowEffect and a box-shadow are
     not the same construction, so the pair is declared exempt from value comparison — with the
     reason — in DesignTokenVocabularyTests.ValueExemptPairs, exactly as --nxt-shadow-popup is. */
  --nxt-shadow-focus-ring:        0 0 4px #437BB5;   /* Nxt.Shadow.FocusRing */
  /* #2575: the same glow in the failure colour, for an input whose value was refused. Exempt from the
     value comparison for the same construction reason as the focus ring above. */
  --nxt-shadow-error-ring:        0 0 4px #D83B01;   /* Nxt.Shadow.ErrorRing */

  /* ══ Chrome: metrics (#2574) ═══════════════════════════════════════════════════════════════════
     Each carries its unit here and is a bare number in XAML; the parity gate compares the numbers.
     The gradient mid-offset is unitless on both sides. There is no list-row min-height token: it is
     26, the same value as --nxt-control-height, and a second name for one value is how a palette
     starts meaning two things. */
  --nxt-control-height:           26px;      /* Nxt.ControlHeight */
  --nxt-text-button-min-width:    80px;      /* Nxt.TextButtonMinWidth */
  --nxt-chrome-gradient-mid-offset: 0.7;     /* Nxt.ChromeGradientMidOffset */
  --nxt-corner-radius:            4px;       /* Nxt.CornerRadius */
  --nxt-border-thickness:         1px;       /* Nxt.BorderThickness */
  --nxt-content-inset:            10px;      /* Nxt.ContentInset */
  --nxt-list-row-inset:           12px;      /* Nxt.ListRowInset */

  /* ══ Chrome: the metrics #2575 needed (#2575) ══════════════════════════════════════════════════
     Three radii, because the reference draws three shapes: a control is 4, a toolbar icon button is
     3, a list box is 2, and a toolbar chip is asymmetric. The chip's four corners are one token, so
     the parity gate compares "5px 0 5px 0" against the WPF CornerRadius "5,0,5,0" as one number list.
     The font family is a token too: --nxt-font-ui, under Typefaces above (#2962). */
  --nxt-corner-radius-toolbar:    3px;       /* Nxt.CornerRadius.Toolbar */
  --nxt-corner-radius-list:       2px;       /* Nxt.CornerRadius.List */
  --nxt-corner-radius-chip:       5px 0 5px 0;  /* Nxt.CornerRadius.Chip */
  --nxt-list-row-rule-thickness:  0 0 0 2px; /* Nxt.ListRowRuleThickness — the rule UNDER a list row */
  --nxt-font-size:                14px;      /* Nxt.FontSize */
  --nxt-font-size-small:          12px;      /* Nxt.FontSize.Small */
  --nxt-checkbox-size:            18px;      /* Nxt.CheckBoxSize */
  --nxt-radio-dot-size:           8px;       /* Nxt.RadioDotSize */

  /* ══ Tabs (#2954) ══════════════════════════════════════════════════════════════════════════════
     AssemblyLab's tab; each value's source line is in doc/Common/design-decisions.md (2026-10-01).
     The WPF side also carries Thickness keys built from these (it cannot negate or mask a number);
     controls.css composes the same scalars with calc(). */
  --nxt-tab-height:               29px;      /* Nxt.Tab.Height */
  --nxt-tab-slope-width:          30px;      /* Nxt.Tab.SlopeWidth */
  --nxt-tab-lead-width:           10px;      /* Nxt.Tab.LeadWidth */
  --nxt-tab-overlap:              10px;      /* Nxt.Tab.Overlap */
  --nxt-tab-header-inset:         10px;      /* Nxt.Tab.HeaderInset */
  --nxt-tab-slope-stroke:         0.5px;     /* Nxt.Tab.SlopeStroke */
  --nxt-tab-content-inset:        14px;      /* Nxt.Tab.ContentInset */
  --nxt-corner-radius-tab:        5px 0 0 0; /* Nxt.CornerRadius.Tab */
  --nxt-corner-radius-tab-panel:  0 0 5px 5px; /* Nxt.CornerRadius.TabPanel */

  /* ══ Chrome: the input inset shadow (#2574) ════════════════════════════════════════════════════
     Three stacked lines inside the top edge of a text input, fading downward. Shipped as the three
     OPACITIES rather than as one box-shadow token, because WPF has no single resource expressing
     three stacked inset lines — so a shadow pair would have had to be exempted from the value gate,
     while three numbers are compared. CSS composes them into one inset box-shadow at the call site. */
  --nxt-input-inset-outer-opacity:  0.1;     /* Nxt.InputInset.OuterOpacity */
  --nxt-input-inset-middle-opacity: 0.06;    /* Nxt.InputInset.MiddleOpacity */
  --nxt-input-inset-inner-opacity:  0.03;    /* Nxt.InputInset.InnerOpacity */
  /* #2575: the colour those three opacities are applied to. #2574 shipped the opacities and no
     colour. Not --nxt-overlay-scrim: that one bakes 35% alpha in, and these three carry their own. */
  --nxt-chrome-inset-shadow:        #000000; /* Nxt.Chrome.InsetShadow */
}
