/* GENERATED FILE. DO NOT EDIT.
 *
 * Source: NB Admin repo, shared/nb-ui/tokens.css
 * Regenerate: cd "NB Admin" && npm run build && npm run sync:shared
 *
 * Edits here are overwritten by the next sync, and `npm run sync:shared -- --check` fails the
 * build (this repo's as well as the hub's) while they survive.
 */

/* NB design tokens.
 *
 * CANONICAL SOURCE. Edit here, then run `npm run sync:shared` from the NB Admin repo. The copies
 * under each app's vendor directory are generated and carry a banner saying so.
 *
 * ── The one rule ─────────────────────────────────────────────────────────────
 *
 * This is the ONLY file in the estate permitted to contain a colour literal. Conformance test C-1
 * greps every other stylesheet, template and inline <style> for hex, rgb() and hsl() and fails on a
 * hit. That is a blunt rule and it is blunt on purpose: the four surfaces already share a palette by
 * convention and it survived six months, but "by convention" is why Client Truth spent a while on a
 * blue #1f5eff, which made the one tool with the most numbers on screen the one that looked least
 * like the others. A grep is what makes the convention hold without anyone watching.
 *
 * ── Why every token is prefixed --nb- ────────────────────────────────────────
 *
 * These get dropped into pages that ALREADY define --bg, --panel, --text and --accent, with three
 * different meanings between them: the hub's --panel does not exist, Client Truth's is the hub's
 * --surface, SpendTracker's is the hub's --surface-sunken. An unprefixed token here would silently
 * inherit whichever the host happened to set, and the failure would be a subtly wrong background
 * rather than an error.
 *
 * The prefix is what makes nb-ui adoptable one page at a time instead of in a flag-day rewrite.
 * During migration a surface can load this file, convert one panel, and leave the rest on its old
 * variables with nothing colliding.
 *
 * See ../SCHEMA.md §1.1.
 */

:root {
  /* ── surfaces, furthest back to nearest front ───────────────────────────── */

  --nb-canvas: #edf5fc; /* the page: brand Ice */
  --nb-surface: #ffffff; /* panels, cards, menus, dialogs */
  --nb-surface-sunken: #f6f8fa; /* chips, code blocks, table headers, wells */

  /* ── ink ────────────────────────────────────────────────────────────────── */

  --nb-ink: #373a36; /* brand Charcoal */
  --nb-ink-muted: #57606a; /* labels, blurbs, secondary facts */
  --nb-ink-inverse: #ffffff; /* on brand or status fills */

  /* ── lines ──────────────────────────────────────────────────────────────── */

  --nb-line: #e1e4e8;
  --nb-line-strong: #d0d7de; /* dividers that need to read as structural */

  /* ── brand ──────────────────────────────────────────────────────────────── */

  /* Violet is RESERVED. It means New Breed, and on a page it means "the primary action" or "the
   * thing you are currently in": the header, the current tab, the current tool in the Tools menu.
   * It is not available as a status colour, a chart series, or a way to make something look
   * important. See --nb-pending below for the status hue that was previously taking violet's job.
   */
  --nb-brand: #733bf6;
  --nb-brand-dark: #5b2cd6;
  --nb-brand-wash: #f3ecfc; /* the "you are here" fill */
  --nb-brand-line: #d6c4f7;

  /* ── status ─────────────────────────────────────────────────────────────── */

  /* Each status has an ink and a wash. Ink for text, icons and left borders; wash for a row fill or
   * a block background. Never ink-on-wash below 4.5:1; the pairs here were picked to clear it.
   */
  /* Three values per status, not two.
   *
   * The `-line` tier was added when the hub was migrated: it had been hand-mixing a mid-tone border
   * for every status block (#f0c2c6 for danger, #e6d6a2 for warn, #b4dcc0 for ok) because ink-on-wash
   * is too strong for a 1px border and wash-on-wash is invisible. Every surface that draws a tinted
   * block needs that middle value, so it is a token rather than three ad-hoc mixes.
   */
  --nb-ok: #1a7f37;
  --nb-ok-wash: #e6f4ea;
  --nb-ok-line: #b4dcc0;
  --nb-warn: #9a6700;
  --nb-warn-wash: #fff6e5;
  --nb-warn-line: #e6d6a2;
  --nb-danger: #cf222e;
  --nb-danger-wash: #ffebe9;
  --nb-danger-line: #f0c2c6;
  --nb-info: #0969da;
  --nb-info-wash: #ddf4ff;
  --nb-info-line: #a9d6ff;

  /* Queued / in-flight / tasked. This is the OnOffboarder's --tasked: #6e40c9, kept at very nearly
   * its old value on purpose. It USED to be a violet close enough to the brand accent that a task
   * status and a navigational "you are here" were hard to tell apart. Moving it out of the brand
   * ramp fixes that; moving it further would have invalidated every existing screenshot and runbook
   * for no additional gain. */
  --nb-pending: #6e40c9;
  --nb-pending-wash: #f3ecfc;

  /* ── categorical (charts only) ─────────────────────────────────────────────
   * A fixed-order series palette for data viz, assigned by entity, NEVER by rank, never cycled
   * (a 9th series folds into cat-8, the neutral "Other"). Okabe-Ito-based, chosen for colorblind
   * separation. Deliberately distinct from the reserved brand violet and the status hues (§1.2):
   * those never carry a chart series, and a chart series never borrows them. */
  --nb-cat-1: #0072b2;  --nb-cat-2: #e69f00;  --nb-cat-3: #009e73;  --nb-cat-4: #cc79a7;
  --nb-cat-5: #56b4e9;  --nb-cat-6: #d55e00;  --nb-cat-7: #ca9a00;  --nb-cat-8: #6b7280;

  /* ── focus ──────────────────────────────────────────────────────────────── */

  /* Deliberately NOT the brand violet. A violet focus ring on a violet primary button is invisible,
   * and the primary button is the control most likely to be reached by keyboard. The shared header
   * overrides this to white, because its own background is the violet gradient. */
  --nb-focus: #0969da;

  /* ── type ───────────────────────────────────────────────────────────────── */

  /* Proxima Nova is the brand's primary typeface and is licensed. It is used when present on the client,
   * with a close sans fallback otherwise. Embedding it for everyone needs an Adobe Fonts kit plus a
   * CSP font-src allowance. That trade has now been evaluated and deferred four separate times
   * across four surfaces, independently reaching the same answer; it is deferred here too, once, so
   * the fifth surface does not have to rediscover it. */
  --nb-font: 'proxima-nova', 'Proxima Nova', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
    sans-serif;
  --nb-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* 14px base: three of the four web surfaces already use it and the shared header hardcodes it.
   * SpendTracker's in-progress app.css uses 15px and changes. */
  --nb-text-xs: 11px; /* chips, tags, footnotes */
  --nb-text-sm: 12px; /* labels, blurbs, table detail */
  --nb-text-base: 14px; /* body */
  --nb-text-lg: 18px; /* section heads, the header's h1 */
  --nb-text-xl: 20px; /* stat values */
  --nb-text-2xl: 26px; /* the one number a page is about, if it has one */
  --nb-leading: 1.5;

  /* ── space (a 4px scale) ────────────────────────────────────────────────── */

  /* Every margin, padding and gap in nb-ui resolves to one of these. The scale is short on purpose:
   * the four surfaces between them currently use 20 distinct spacing values, which is 20 chances
   * for two panels to sit 2px differently apart on two pages. */
  --nb-space-1: 4px;
  --nb-space-2: 8px;
  --nb-space-3: 12px;
  --nb-space-4: 16px;
  --nb-space-5: 24px;
  --nb-space-6: 32px;
  --nb-space-7: 48px;

  /* ── shape ──────────────────────────────────────────────────────────────── */

  --nb-radius-sm: 6px; /* buttons, inputs, chips-that-are-not-pills */
  --nb-radius-md: 10px; /* panels, dialogs, menus */
  --nb-radius-pill: 999px; /* chips, tags */
  --nb-shadow-pop: 0 8px 24px rgba(55, 58, 54, 0.24); /* menus and dialogs only */
  --nb-scrim: rgb(0 0 0 / 0.45); /* dialog backdrop */

  /* A card that lifts on hover. Distinct from --nb-shadow-pop, which is for things that float ABOVE
   * the page (menus, dialogs); this is for something still in the page that is merely interactive. */
  --nb-shadow-card: 0 2px 8px rgba(55, 58, 54, 0.08);
  /* The brand-tinted version, for a hover on something whose whole affordance is "this navigates".
   * The hub's tool cards use it and it is the one place a coloured shadow is warranted. */
  --nb-shadow-brand: 0 4px 16px rgba(115, 59, 246, 0.14);

  /* The idle-lock overlay.
   *
   * Nearly opaque, because it is doing a job: it blanks figures on an unattended screen. It is NOT a
   * security control: the numbers would still be in the DOM, and devtools removes an overlay in
   * seconds. That is why the hub's server also refuses to serve metrics while a session is locked.
   * The overlay is the courtesy; the server-side refusal is the control. */
  --nb-haze: rgba(233, 238, 246, 0.86);

  /* ── layout ─────────────────────────────────────────────────────────────── */

  --nb-content-max: 1180px;
}

/* ── dark ──────────────────────────────────────────────────────────────────── */

/* Client Truth was the only surface with a dark mode, and the recorded reason the other three were
 * light-only was sound: a hub that flipped to dark while the tool you clicked into stayed light
 * would look broken rather than considerate.
 *
 * This removes the premise rather than the dark mode. Every surface loads this file, so every
 * surface gets both schemes and switching tools no longer switches scheme.
 *
 * `prefers-color-scheme` only: no toggle, no stored preference, no data-theme attribute. A toggle
 * means persisting a preference across four independent session stores, which is four places to get
 * it wrong in exchange for a setting the operating system already has.
 *
 * The header bar does NOT participate: it carries the fixed violet gradient in both schemes on all
 * surfaces, because a shared component that changes appearance per host is not a shared component.
 * The gradient was checked against both canvases rather than assumed.
 */
@media (prefers-color-scheme: dark) {
  :root {
    --nb-canvas: #14171c;
    --nb-surface: #1c2128;
    --nb-surface-sunken: #262d36;

    --nb-ink: #e8ecf2;
    --nb-ink-muted: #9aa4b2;
    /* --nb-ink-inverse stays white: it sits on brand and status FILLS, which stay dark-on-light
       enough to need it in both schemes. */

    --nb-line: #2c333d;
    --nb-line-strong: #3a434f;

    /* Lifted toward the light so violet stays legible on a dark canvas. Text on --nb-brand still
       uses --nb-ink-inverse; the ratio was checked. */
    --nb-brand: #a785f9;
    --nb-brand-dark: #8b63f5;
    --nb-brand-wash: #241c38;
    --nb-brand-line: #4a3a6b;

    /* Status washes invert to dark tints of their hue rather than staying pale. A pale wash on a
       dark row reads as a highlight, which is the opposite of what a danger row means. */
    --nb-ok: #6cc99a;
    --nb-ok-wash: #16281f;
    --nb-ok-line: #2c5340;
    --nb-warn: #e0a458;
    --nb-warn-wash: #2e2415;
    --nb-warn-line: #5c4a2a;
    --nb-danger: #f2857c;
    --nb-danger-wash: #2e1a1a;
    --nb-danger-line: #5e3330;
    --nb-info: #6cb6ff;
    --nb-info-wash: #12283d;
    --nb-info-line: #2a4a6b;
    --nb-pending: #b394f0;
    --nb-pending-wash: #241c38;

    /* categorical, lightened for the dark surface, same fixed order */
    --nb-cat-1: #56a3d9;  --nb-cat-2: #f0b942;  --nb-cat-3: #40c79a;  --nb-cat-4: #e39ac4;
    --nb-cat-5: #8fd0f5;  --nb-cat-6: #f58152;  --nb-cat-7: #e0c04a;  --nb-cat-8: #9aa4b2;

    --nb-focus: #6cb6ff;

    --nb-shadow-pop: 0 8px 24px rgba(0, 0, 0, 0.55);
    /* Heavier than on light: a 0.45 scrim over a dark canvas barely separates the dialog from the
       page behind it, which is the one job a scrim has. */
    --nb-scrim: rgb(0 0 0 / 0.65);
    --nb-shadow-card: 0 2px 8px rgba(0, 0, 0, 0.4);
    --nb-shadow-brand: 0 4px 16px rgba(167, 133, 249, 0.22);
    /* Dark equivalent of the lock overlay: near-opaque canvas rather than a pale wash, or the
       figures underneath stay legible, which defeats the point. */
    --nb-haze: rgba(20, 23, 28, 0.9);
  }
}

/* ── reduced motion ────────────────────────────────────────────────────────── */

/* nb-ui has exactly two animations, both in nb-spinner/nb-progress, and both are pure indicators.
 * Nothing is communicated only by their movement. So they can be stopped outright rather than
 * shortened. A stopped spinner still marks the place something is loading.
 *
 * Defaults FIRST, override second. Both blocks are plain `:root`, so specificity is equal and the
 * later rule wins, as a media query does not add weight. Written the other way round, the override
 * would be silently dead and the only symptom would be a spinner that keeps spinning for the people
 * who asked it not to. */
:root {
  --nb-anim-spin: nb-spin 0.8s linear infinite;
  --nb-anim-sweep: nb-sweep 1.1s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --nb-anim-spin: none;
    --nb-anim-sweep: none;
  }
}
