/* ============================================================
   RBI brand primitives — LAYER 1.

   This file is the SWAP FILE. It is the only place in the stack
   where a raw brand colour value is allowed to exist. Everything
   downstream reads these primitives through semantic tokens and
   never restates a value found here.

   CONTRACT (true for every consumer of this file):

   1. `:root` only. NEVER a `[data-theme]` selector — nor any other
      theme, media, or container condition. Primitives carry no
      theme; semantics do. This single rule is what makes a rebrand
      a one-file diff a human can eyeball.
   2. Primitives only. No product semantics: no `--color-*`,
      `--surface-*`, `--text-*`, `--space-*`, `--radius-*`. Every
      custom property here is namespaced `--rbi-*`.
   3. No repo-specific prose. This file is vendored byte-identically
      across repositories and hash-compared between copies. Every
      comment must be true everywhere it lands. Do not name an app,
      a component, a file, or a person in this file.
   4. Every primitive is tagged. `brand-truth` = a value the brand
      owner must supply; a rebrand cannot compute it. `derived` = a
      value computed or sampled from a brand-truth value; a rebrand
      may recompute it rather than be told it.
   5. Ordering is by lightness within a family, lightest first, so
      a replacement palette can be dropped in rung-for-rung.

   STATUS AT THIS REVISION: FIVE VALUES ARE BRAND-TRUTH, ACROSS FOUR
   COLOUR CORES. The navy, the blue, the green and the warm grey
   below were read off the brand owner's own artifacts — the vector
   logo and two independently-built production applications that
   agree with each other — and the navy is recorded TWICE, once as
   the application value and once as the value the vector mark is
   drawn with. They are not samples and not guesses. Every OTHER
   value in this file is a lightness derivation around one of those
   four cores, and a rebrand recomputes it rather than being told it.
   (The count was written as "four" for two revisions, counting the
   cores while the register downstream counted the values. Both were
   right about what they counted; neither said which. Stated as both
   numbers here so the next reader does not have to reconcile them.)

   THE FOUR RATIOS THAT CONSTRAIN EVERY DERIVATION IN THIS FILE.
   They follow from the WCAG contrast formula alone, so they hold for
   any palette dropped in here, and a re-derivation must respect them:

     - white ink clears 4.5:1 on a fill whose relative luminance
       is <= 0.1833;
     - the deepest ink rung (-900 below, luminance 0.0066) clears
       4.5:1 on a fill whose relative luminance is >= 0.2046;
     - therefore luminance 0.1833 .. 0.2046 is a DEAD BAND: no ink
       clears AA on a fill in it. Never place text on such a fill;
     - a fill clears 3:1 as a graphical object against a white
       canvas when its luminance is <= 0.30.

   The happy consequence, and the reason the categorical rungs below
   land where they do: any fill at or below 0.1833 satisfies BOTH the
   white-ink text rule AND the 3:1 object rule at once.
   ============================================================ */

:root {

  /* --- Achromatic anchors -----------------------------------
     Universal, not brand-owned. Present so that scrims, veils, and
     shadows can be expressed as a color-mix() of a primitive rather
     than as a raw rgba() triplet. Never retune these. */
  --rbi-white: #FFFFFF;   /* derived (universal) */
  --rbi-black: #000000;   /* derived (universal) */

  /* --- Navy: the brand core ---------------------------------
     -700 is the authoritative brand navy, taken from the brand
     owner's own production applications.

     This family is deliberately LONG — ten rungs — because it is
     asked to do three jobs at once: it is the brand fill, it is the
     single-hue sequential scale, and it is the ordered progression
     scale. One family serving all three is what guarantees they can
     never drift apart from each other, and it is why no separate
     monochrome ladder is declared anywhere in this file.

     Rungs are spaced by LUMINANCE, not by even hex steps, so that
     every consecutive pair is a visible step and the ink crossover
     falls between -400 and -500. Recorded luminance, lightest
     first: .872 .753 .568 .356 .231 .101 .050 .029 .014 .007 */
  --rbi-navy-050: #EEF0F7;  /* derived  — lightest tint; scale floor */
  --rbi-navy-100: #DDE1EC;  /* derived  — very light tint */
  --rbi-navy-200: #C0C6DC;  /* derived  — light tint */
  --rbi-navy-300: #97A0C1;  /* derived  — muted ink for dark canvases */
  --rbi-navy-400: #7683AE;  /* derived  — lightest rung that still clears
                                          3:1 on a white canvas (3.73:1) */
  --rbi-navy-500: #4A5788;  /* derived  — muted fill */
  --rbi-navy-600: #2E3C70;  /* derived  — brand fill for dark canvases */
  --rbi-navy-700: #222D59;  /* BRAND-TRUTH — the authoritative brand navy */
  --rbi-navy-800: #161D3A;  /* derived  — one step deeper than -700 */
  --rbi-navy-900: #0D1226;  /* derived  — deepest navy; scrims, and the
                                          standard ink for light fills */

  /* --- Navy, as drawn ---------------------------------------
     The vector logo fills its mark with a navy one step off the
     application navy above. Both are authentic; they differ by less
     than a perceptible step and only one can be the token core.
     Recorded here so a future rebrand knows the difference exists
     and is not a transcription error. NOT consumed by anything —
     it is a provenance record.

     ON UNCONSUMED PRIMITIVES GENERALLY, since this is not the only
     one: a primitive with no consumer is normally a defect in this
     file, and there are exactly two exceptions. A PROVENANCE RECORD
     like this one, which exists to stop a future reader "correcting"
     two authentic values into one. And a BRAND-TRUTH CORE whose
     derived rungs carry the family downstream while the core itself
     is reached by nothing — an unconsumed core is still the thing
     every rung is derived FROM, which is a different standing from
     an unconsumed leaf. Delete a leaf; keep both of these. */
  --rbi-navy-700-mark: #232E59;  /* BRAND-TRUTH — vector mark fill */

  /* --- Blue: the supporting accent ---------------------------
     -500 is brand-truth, read off the brand owner's applications.
     It is dark enough to be legible as text on a light canvas
     (7.70:1) AND saturated enough to read as an accent fill, so a
     light canvas needs no separate ink rung — the accent fill and
     the accent ink are the same value playing two roles. The two
     lighter rungs exist only because a dark canvas DOES need the
     split. */
  --rbi-blue-300: #9DAEE8;  /* derived  — accent ink for dark canvases */
  --rbi-blue-400: #6C82CE;  /* derived  — accent fill for dark canvases */
  --rbi-blue-500: #374E9B;  /* BRAND-TRUTH — the authoritative brand blue */

  /* --- Green: the confirmation colour ------------------------
     -500 is brand-truth. READ THIS BEFORE USING IT: at luminance
     .289 it is 3.10:1 on white and 2.89:1 on an off-white canvas,
     so it can never carry text on a light canvas, in any role, in
     any theme. Any role here that carries text on a light canvas
     reaches for -700 or -800.

     THE ONE SANCTIONED EXCEPTION, AND WHY IT IS NOT A DEFECT TO
     REPAIR. Where the brand owner's own live platforms use -500
     unmodified as a filled confirm control, a consumer may match
     them exactly and take white on it at 3.10:1 — an SC 1.4.3
     failure entered knowingly, in exchange for reading as the same
     product family as the platforms beside it. That decision is
     recorded downstream with its number and its reason. DO NOT
     "correct" such a consumer to a passing rung from this file: the
     failing ratio is the price of a consistency somebody chose, and
     substituting -700 buys 5.42:1 by throwing away the thing that
     was bought. If it is ever reversed it is reversed downstream, in
     one line, not here.

     On a dark canvas -500 clears 3:1 as an object comfortably
     (5.14:1 against a near-black surface), which is why the same
     control needs no theme variant. Where a dark canvas needs a
     saturated affirmative fill that is NOT that control, it takes
     -300 — both so the two stay distinguishable and because -300
     measures better against a dark canvas (8.93:1).

     The lighter and darker rungs are lightness derivations of -500
     and hold its hue, so the family reads as one green. */
  --rbi-green-050: #E6F5E7;  /* derived  — pale tint for light canvases */
  --rbi-green-300: #6FD877;  /* derived  — ink AND saturated affirmative
                                           fill for dark canvases */
  --rbi-green-500: #2FA837;  /* BRAND-TRUTH — the authoritative brand green.
                                NEVER legible as text on a light canvas;
                                see the sanctioned exception above. */
  --rbi-green-700: #1F7A28;  /* derived  — fill for light canvases (5.42:1) */
  --rbi-green-800: #1A6A22;  /* derived  — ink for light canvases (6.71:1) */
  --rbi-green-950: #12331A;  /* derived  — deep tint for dark canvases */

  /* --- Warm grey: the wordmark neutral ------------------------
     -500 is brand-truth, taken from the wordmark fill. It is the
     one warm value the brand owns, and it is 3.66:1 on white:
     legible as a MARK, never as text. Do not promote it to a text
     role in any theme. The two derived rungs move it to where it
     can carry text on their respective canvases.

     The CORE has no direct consumer and is kept under the
     brand-truth-core exception stated above; the two derived rungs
     ARE consumed, by the near-neutral categorical position, and as
     of this revision they are consumed by REFERENCE. They were
     duplicated literals until now, which made the claim "the core
     carries the family downstream" false at the moment it was
     written. */
  --rbi-warm-400: #B0ABA8;  /* derived  — for dark canvases */
  --rbi-warm-500: #888584;  /* BRAND-TRUTH — wordmark neutral. MARKS ONLY. */
  --rbi-warm-700: #6B6664;  /* derived  — for light canvases */

  /* --- Categorical palette ----------------------------------
     Six positions, each in two lightness variants: `-deep` reads on
     a light canvas, `-bright` reads on a dark canvas. Names carry
     luminance, never a theme.

     This series is PURPOSE-BUILT and only position 1 anchors to the
     brand. The reason is a measurement-integrity one: these encode
     NOMINAL membership, and a set built by walking one hue down a
     lightness ladder reads as an ORDERED scale. Encoding unordered
     things in an ordered-looking scale is a measurement error, so
     the series spends hue rather than lightness wherever it can.

     Where it cannot, it spends CHROMA. Position 5 is near-neutral
     by design: with four saturated status hues already spoken for,
     the hue circle does not hold six well-separated positions, and
     a near-neutral is the one escape left.

     CORRECTED BY MEASUREMENT: this comment used to say a
     near-neutral "collides with nothing". That is only true against
     members that STAY saturated under a colour-vision deficiency. A
     hue that desaturates toward grey lands on the deliberate grey,
     and position 4 did exactly that — measured dE00 3.8 against
     position 5 under light deuteranopia. The near-neutral escape is
     real but conditional, and the condition is now written down.

     Position 6 is the second brand-hue position, separated from
     position 1 by luminance rather than hue (3.54:1 apart) —
     deliberately, because luminance is the ONLY channel that
     survives every colour-vision deficiency intact, whereas hue
     separation degrades. THIS ONE MEASURED OUT: 1-vs-6 is the
     strongest pair of the set in all four simulated conditions
     (dE00 29.9-30.3). Spending the hardest slot on the most robust
     channel is the right trade; the open question was only which
     slot was hardest, and the measurements said 4, not 6.

     SIX-WAY SEPARABILITY IS NOT ACHIEVABLE HERE, AND THAT IS
     ARITHMETIC RATHER THAN AN OPINION. Read this before retuning
     any rung in the hope of fixing it.

       - Under dichromacy the perceived hue circle collapses to a
         blue-vs-yellow axis. Yellow is spoken for by the watch
         status colour. So every saturated member of this set falls
         into ONE post-collapse class (blue-chromatic) and only the
         near-neutral is achromatic. There are three classes and one
         of them is unavailable.
       - Within one class the residual channel is luminance, and the
         luminance budget is bounded at both ends. On a dark canvas
         every rung must clear the deepest-ink 4.5:1 floor (Y >=
         0.2046, above) and stay under the glare ceiling the ordered
         ramp already uses (Y ~0.753). That window is 3.15:1 across
         FIVE gaps: 1.26:1 per gap at best.
       - Simulation brackets the threshold: pairs sitting 1.35:1
         apart in luminance measured dE00 7.7 and read as separate;
         the pair sitting 1.20:1 apart measured 2.2 and collapsed.
         1.26:1 is below what a six-position set would need.

     THEREFORE THE PROMISE DOWNSTREAM IS NARROWED RATHER THAN THE
     RUNGS BEING CHASED: three positions — 1, 5 and 6 — are the
     robust triple (two luminance-separated brand blues plus the
     achromatic neutral; adjacent luminance ratios 2.34:1 / 1.51:1
     on light and 1.78:1 / 1.74:1 on dark). Positions 2, 3 and 4
     are legitimate nominal encodings that are NOT
     deficiency-guaranteed, and a consumer rendering more than the
     triple at once carries a NON-COLOUR key alongside. Nothing in
     this file can supply that key; it is a component contract.

     WHAT DID MOVE: position 4's deep rung, once, to the max-min
     point between its two neighbours rather than to the point that
     fixes one pair. Sitting between the anchor (Y .0294) and the
     near-neutral (Y .1356) it now holds 1.53:1 against the first
     and 1.52:1 against the second, where before it held 1.98:1 and
     1.18:1. The objective is the MINIMUM over the set, not a named
     pair — a member weak against two partners cannot be nudged
     against one of them. Its bright rung did NOT move: on that
     canvas the anchor sits barely above the ink floor, so every
     direction position 4 could travel trades one collapse for two.

     THE ALIASED POSITIONS ARE NOW REFERENCES, NOT COPIES. Six of
     the twelve rungs below are the same value as a rung declared
     earlier in this file, and they were duplicated LITERALS carrying
     an `= --rbi-…` comment that nothing enforced. A rebrand that
     replaced a core moved every semantic role that read it and left
     these behind, silently breaking the rule that position 1 is the
     brand anchor. They are var() references now. Zero pixel change;
     the guarantee is the point. */
  --rbi-cat-1-deep:   var(--rbi-navy-700);  /* derived — the brand anchor */
  --rbi-cat-1-bright: var(--rbi-navy-400);  /* derived */
  --rbi-cat-2-deep:   #0B6E7A;  /* derived */
  --rbi-cat-2-bright: #3FBACB;  /* derived */
  --rbi-cat-3-deep:   #5C3A9E;  /* derived */
  --rbi-cat-3-bright: #9B7FE0;  /* derived */
  --rbi-cat-4-deep:   #882457;  /* derived — luminance Y .0718. Retuned from a
                                   lighter rung (Y .1071) to the max-min point
                                   between the anchor and the near-neutral.
                                   White ink 8.62:1; object 8.62 on white,
                                   8.03 on an off-white canvas. Under the
                                   .1833 white-ink ceiling, so it satisfies
                                   the text rule and the 3:1 object rule at
                                   once. */
  --rbi-cat-4-bright: #E06AA3;  /* derived — deliberately unmoved; see above */
  --rbi-cat-5-deep:   var(--rbi-warm-700);  /* derived — near-neutral */
  --rbi-cat-5-bright: var(--rbi-warm-400);  /* derived — near-neutral */
  --rbi-cat-6-deep:   var(--rbi-navy-400);  /* derived */
  --rbi-cat-6-bright: var(--rbi-navy-100);  /* derived */

  /* --- Typefaces --------------------------------------------
     The brand ships one self-hosted face; everything after it in
     each stack is a platform fallback, so the page still renders
     offline and during the swap period.
     The @font-face block that backs the first family sits directly
     BELOW this rule — it is the only rule type other than `:root`
     this file may contain.

     `"Inter var"` is the variable file; the bare `"Inter"` behind it
     catches a static Inter already installed on the reader's
     machine, so a blocked or failed download degrades to the same
     typeface rather than to a different one. The platform stacks
     behind both are the last resort.

     PROVENANCE: still tagged `derived`, and the tag is correct.
     `derived` does not mean "computed" — it means "a rebrand may
     recompute or re-choose this rather than be told it", and that
     is exactly the standing of this face. The brand owner's own
     applications do not settle a typeface, and the face the brand's
     print identity uses is licensed in a way that does not extend
     here. This is therefore a SELECTION made downstream, on the same
     footing as any other derivation: legitimate, defensible, and
     replaceable the moment the owner names a face. If they do, that
     value becomes brand-truth and the tag changes with it. */
  --rbi-font-sans: "Inter var", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;  /* derived */
  /* The monospace stack no longer sets numerals — the sans face
     carries tabular figures, so digits align without changing
     typeface. What is left is genuinely code-shaped text, which is
     why the primitive is named for that role rather than for its
     metrics. */
  --rbi-font-code: ui-monospace, "SF Mono", "Segoe UI Mono", "Roboto Mono", Menlo, Consolas, monospace;         /* derived */
}

/* ============================================================
   SELF-HOSTED BRAND FACE.

   One variable file, roman only. The weight axis is declared as a
   RANGE (100 900), which is what tells the engine the file is
   variable and lets any weight in between resolve without a
   synthetic bold.

   The `src` url is RELATIVE ON PURPOSE. A url in a stylesheet
   resolves against the STYLESHEET, not the document, so this brand
   package stays self-contained: drop the folder anywhere in a host
   app's tree and the face still resolves. Making it absolute would
   couple the swap file to one app's directory layout, which is the
   one thing this file may never do.

   The filename carries a content hash. That is what makes an
   immutable cache header safe to set on this directory: a new cut
   of the face is a new filename, so a cached copy can never go
   stale. If the face is re-cut, re-hash it and change the name —
   never overwrite the bytes behind the same url.

   `font-display: swap` renders fallback text immediately and
   restyles when the face arrives, so a slow or blocked font never
   costs a reader the content.

   Licence text ships beside the binary in the same folder.
   ============================================================ */
@font-face {
  font-family: "Inter var";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/InterVariable.693b77d4.woff2") format("woff2");
}
