/* ==========================================================================
   Catalis Core palette — snaketrax dark theme
   --------------------------------------------------------------------------
   Values come from the Catalis Core Design System handoff bundle,
   colors_and_type.css, specifically its [data-theme="dark"] block. The dark
   theme is kept deliberately: Catalis defines its own dark palette, so this is
   adopting that rather than trading the dark theme away for the light one.

   Loaded FIRST in index.html, ahead of bootstrap and style.css, so every later
   stylesheet can reference these. Custom properties on :root resolve at use
   time, so declaration order relative to the rules that consume them does not
   matter — only that this file is present.

   WHY THE -rgb TRIPLETS: the stylesheets use each brand colour at ten different
   alpha levels (rgba(158, 218, 41, 0.05) through 0.4 for the accent alone).
   A hex token cannot serve those, so each colour is declared once as channels
   and composed two ways. Change the triplet and both the solid and every
   translucent variant move together.
   ========================================================================== */

/* Roboto is not a system face on Windows or macOS, so without these the sans
   token would silently fall through to Helvetica/Arial and nothing would look
   any different. Both files are the variable builds shipped in the handoff
   bundle, served locally rather than from a font CDN — this is government admin
   software and the asset should not be a third-party request. */
@font-face {
    font-family: 'Roboto';
    src: url('../fonts/Roboto-VariableFont_wdth_wght.ttf') format('truetype-variations'),
         url('../fonts/Roboto-VariableFont_wdth_wght.ttf') format('truetype');
    font-weight: 100 900;
    font-stretch: 75% 100%;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Roboto';
    src: url('../fonts/Roboto-Italic-VariableFont_wdth_wght.ttf') format('truetype-variations'),
         url('../fonts/Roboto-Italic-VariableFont_wdth_wght.ttf') format('truetype');
    font-weight: 100 900;
    font-stretch: 75% 100%;
    font-style: italic;
    font-display: swap;
}


/* Black Ops One — the SnakeTrax wordmark only, not a UI face. Self-hosted so
   the navbar does not flash an unstyled wordmark on first paint. Google Fonts,
   SIL Open Font License: commercial use is fine and no attribution is required. */
@font-face {
    font-family: 'Black Ops One';
    src: url('../fonts/black-ops-one-latin-400-normal.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

:root {
    /* ---------- Brand + status: channels ----------
       TINTED FOR A DARK GROUND, and this is a deliberate deviation worth reading.

       Catalis's [data-theme="dark"] block re-tints only two of these — error to
       #F2B3B3 and info to #1976D2 — and leaves secondary, success and warning at
       their light-canvas values. Those values do not survive here. Measured
       against #3d404c, the lightest ground snaketrax puts them on:

           mint    #00A876  3.37    success #039112  2.49
           info    #1976D2  2.24    warning #DC7D00  3.43

       All below the 4.5:1 AA threshold, and three of them WORSE than the colours
       snaketrax ships today. These buttons are translucent-fill with a coloured
       border and label (.btn-accent is rgba(...,.1) over border-color), so the
       token is doing the job of text and AA is the right bar.

       So each keeps its Catalis hue and saturation and is raised in lightness
       until it clears 4.5:1 — the same move Catalis itself makes for error.
       Ratios below are against #3d404c; every one is higher against the darker
       canvas and appbar grounds. */
    --ct-accent-rgb:  137, 206, 227;    /* #89CEE3  navy-400 -- see note below  */
    --ct-primary-rgb: 137, 206, 227;    /* #89CEE3  navy-400, as-is     5.89:1  */
    --ct-info-rgb:    120, 180, 239;    /* #78B4EF  info, L 46%->70%    4.70:1  */
    --ct-success-rgb: 4, 200, 25;       /* #04C819  success, L 29%->40% 4.56:1  */
    --ct-warning-rgb: 255, 145, 1;      /* #FF9101  warning, L 43%->50% 4.57:1  */
    --ct-danger-rgb:  242, 179, 179;    /* #F2B3B3  Catalis's OWN dark  5.83:1
                                           error tint — not derived, taken. */

    /* ---------- Brand + status: solid ---------- */
    --ct-accent:  rgb(var(--ct-accent-rgb));
    --ct-primary: rgb(var(--ct-primary-rgb));
    --ct-info:    rgb(var(--ct-info-rgb));
    --ct-success: rgb(var(--ct-success-rgb));
    --ct-warning: rgb(var(--ct-warning-rgb));
    --ct-danger:  rgb(var(--ct-danger-rgb));

    /* The saturated Catalis error, for the rare place that needs a solid red
       FILL with white on it rather than a border or a label. Never use it for
       text on these grounds — it measures 1.88:1 on #3d404c. */
    --ct-danger-solid: #D50000;         /* #D50000  --color-error (light)      */

    /* ---------- Solid fills ----------
       A brand colour needs two values on a dark theme, exactly as Catalis
       splits error into #D50000 (fill) and #F2B3B3 (text). The tokens above
       are tuned to be READ against a dark ground; used as a solid alert or
       badge background they are far too hot. These are the fill halves, each
       chosen to clear 4.5:1 against the white text those rules already set. */
    --ct-accent-fill:  #1F3C6E;         /* Catalis navy, Primary     10.88:1   */
    --ct-success-fill: #027c10;         /* white on it 5.39:1                  */
    --ct-warning-fill: #9e5a01;         /* white on it 5.36:1                  */
    --ct-danger-fill:  #D50000;         /* Catalis --color-error      5.48:1   */
    --ct-info-fill:    #01579B;         /* Catalis --color-info       7.40:1   */
    --ct-primary-fill: #1F3C6E;         /* Catalis navy, Primary     10.88:1   */
    /* ---------- Neutral ramp ----------
       snaketrax used 69 distinct greys, most of them drift rather than
       intent — pairs 1-2% apart doing the same job. They are snapped to 22
       steps named by lightness, each step taking the value of its most-used
       member so the common surfaces keep their exact appearance. Median
       shift is 0.8%; one colour of 69 moves more than 4%.

       This is what makes a light theme a single inverted block rather than
       408 separate decisions. */
    --ct-n-4  : #0b0d10;     /* 9 uses, 5 shades merged */
    --ct-n-8  : #101114;     /* 22 uses, 7 shades merged */
    --ct-n-12 : #191a1f;    /* 14 uses, 3 shades merged */
    --ct-n-16 : #24262d;    /* 31 uses, 6 shades merged */
    --ct-n-20 : #2d2f34;    /* 19 uses, 6 shades merged */
    --ct-n-24 : #35373d;    /* 5 uses, 2 shades merged */
    --ct-n-40 : #585d6e;    /* 46 uses, 4 shades merged */
    --ct-n-44 : #616779;    /* 15 uses, 4 shades merged */
    --ct-n-48 : #6f7780;    /* 8 uses, 3 shades merged */
    --ct-n-52 : #7a8090;    /* 2 uses, 2 shades merged */
    --ct-n-56 : #848c94;    /* 4 uses, 3 shades merged */
    --ct-n-60 : #949ba2;    /* 41 uses, 2 shades merged */
    --ct-n-64 : #9aa7b4;    /* 10 uses, 3 shades merged */
    --ct-n-68 : #9aa5b8;    /* 6 uses, 5 shades merged */
    --ct-n-72 : #adb5bd;    /* 2 uses, 2 shades merged */
    --ct-n-76 : #c0c4c8;    /* 5 uses, 1 shades merged */
    --ct-n-80 : #c4c9d4;    /* 21 uses, 2 shades merged */
    --ct-n-84 : #d7d7d7;    /* 7 uses, 3 shades merged */
    --ct-n-88 : #e0e0e0;    /* 21 uses, 2 shades merged */
    --ct-n-92 : #eeeeee;    /* 1 uses, 1 shades merged */
    --ct-n-96 : #f7f7f7;    /* 3 uses, 2 shades merged */
    --ct-n-100: #ffffff;   /* 59 uses, 1 shades merged */
    /* ---------- Surfaces ----------
       Moved onto the Catalis dark grounds. ANCHORED, not squeezed: snaketrax's
       surfaces spanned L 0-37% while Catalis names only L 7-16%, and mapping
       one range straight onto the other would have flattened every panel into
       a single tone. Instead the three grounds that correspond were pinned to
       their Catalis counterparts and the rest follow the line through them
       (slope 0.82), so adjacent panels stay distinguishable.

       Hue and saturation were left alone — snaketrax's greys are already cool
       (#3d404c is hue 228, Catalis's #23272e is 218), so only lightness moved. */
    --ct-bg-canvas:  #101114;           /* was #24262d · Catalis #101216       */
    --ct-bg-appbar:  #191a1f;           /* was #2f323b · Catalis #1a1d24       */
    --ct-bg-drawer:  #24262d;           /* was #3d404c · Catalis #23272e       */
    --ct-bg-panel:   #2d2f34;           /* was #494b54 · Catalis #1f2329       */

    /* ---------- Text ---------- */
    --ct-fg:         #949ba2;           /* Catalis --fg-secondary rgba(255,255,255,.70) */
    --ct-fg-muted:   #6f7780;           /* Catalis --fg-disabled  rgba(255,255,255,.50) */
    --ct-fg-strong:  #c0c4c8;           /* Catalis --fg-primary   rgba(255,255,255,.87) */

    /* ---------- Lines ---------- */
    --ct-line:       #616779;           /* Catalis --line-default rgba(255,255,255,.12) */

    /* ---------- Shade ramps ----------
       Each brand colour had hover, active and tint variants of its own that
       the first pass missed, which left base colours Catalis and every hover
       still snaketrax. Derived by mixing the base toward black and white --
       raising HSL lightness at fixed saturation sends a saturated green
       fluorescent. 50 is the base; lower is deeper, higher is lighter. */
    /* accent ramp — 50 is the base token above */
    --ct-accent-20: #55808d;
    --ct-accent-30: #679baa;
    --ct-accent-40: #79b5c8;
    --ct-accent-50: #89cee3;
    --ct-accent-60: #97d4e6;
    --ct-accent-70: #a5daea;
    --ct-accent-80: #b3e0ed;
    --ct-accent-90: #c2e6f0;

    /* success ramp — 50 is the base token above */
    --ct-success-20: #027c10;
    --ct-success-30: #039613;
    --ct-success-40: #04b016;
    --ct-success-50: #04c819;
    --ct-success-60: #22cf35;
    --ct-success-70: #40d550;
    --ct-success-80: #5edc6c;
    --ct-success-90: #7ce287;

    /* warning ramp — 50 is the base token above */
    --ct-warning-20: #9e5a01;
    --ct-warning-30: #bf6d01;
    --ct-warning-40: #e08001;
    --ct-warning-50: #ff9101;
    --ct-warning-60: #ff9e1f;
    --ct-warning-70: #ffab3e;
    --ct-warning-80: #ffb95c;
    --ct-warning-90: #ffc67b;

    /* danger ramp — 50 is the base token above */
    --ct-danger-20: #966f6f;
    --ct-danger-30: #b68686;
    --ct-danger-40: #d59e9e;
    --ct-danger-60: #f4bcbc;
    --ct-danger-70: #f5c5c5;
    --ct-danger-80: #f7cece;
    --ct-danger-90: #f8d7d7;

    /* primary ramp — 50 is the base token above */
    --ct-primary-20: #55808d;
    --ct-primary-30: #679baa;
    --ct-primary-40: #79b5c8;
    --ct-primary-50: #89cee3;
    --ct-primary-60: #97d4e6;
    --ct-primary-70: #a5daea;
    --ct-primary-80: #b3e0ed;
    --ct-primary-90: #c2e6f0;

    /* info ramp — 50 is the base token above */
    --ct-info-20: #4a7094;
    --ct-info-40: #6a9ed2;
    --ct-info-70: #98c6f3;
    --ct-info-90: #b9d8f7;

    /* ---------- Type ----------
       Roboto is the Catalis face and was already present in one rule here. The
       mono stack was already all but identical — 'Roboto Mono' is prepended for
       when the face lands; the handoff bundle ships no Roboto Mono file yet, so
       the fallback renders and nothing changes visually today. */
    --ct-font-sans: 'Roboto', 'Helvetica Neue', Helvetica, Arial, sans-serif;
    --ct-font-mono: 'Roboto Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

    /* The page gutter, and the one layout value here rather than a colour.
       .content takes it as its padding, and the navbar's search column takes it
       as padding-left so the search control starts on the same vertical line as
       the page content beneath it. Both read this token so they cannot drift:
       with the numbers written out separately the search bar sat 20px left of
       the content. Theme-independent, like the font stacks above. */
    --ct-content-gutter: 30px;

    /* Channel triplets for the same ramp. rgba() cannot take a hex token for
       its colour, and 133 places paint with a translucent grey — table
       striping, filled panels, the active nav tab. Without these they stay
       dark when the theme flips. */
    --ct-n-4-rgb:    11, 13, 16;
    --ct-n-8-rgb:    16, 17, 20;
    --ct-n-12-rgb:   25, 26, 31;
    --ct-n-16-rgb:   36, 38, 45;
    --ct-n-20-rgb:   45, 47, 52;
    --ct-n-24-rgb:   53, 55, 61;
    --ct-n-40-rgb:   88, 93, 110;
    --ct-n-44-rgb:   97, 103, 121;
    --ct-n-48-rgb:   111, 119, 128;
    --ct-n-52-rgb:   122, 128, 144;
    --ct-n-56-rgb:   132, 140, 148;
    --ct-n-60-rgb:   148, 155, 162;
    --ct-n-64-rgb:   154, 167, 180;
    --ct-n-68-rgb:   154, 165, 184;
    --ct-n-72-rgb:   173, 181, 189;
    --ct-n-76-rgb:   192, 196, 200;
    --ct-n-80-rgb:   196, 201, 212;
    --ct-n-84-rgb:   215, 215, 215;
    --ct-n-88-rgb:   224, 224, 224;
    --ct-n-92-rgb:   238, 238, 238;
    --ct-n-96-rgb:   247, 247, 247;
    --ct-n-100-rgb: 255, 255, 255;

    /* Purple -- an environment/queue tag colour with no semantic family. 4.63:1 on its own tint */
    --ct-purple:     #D661EA;
    --ct-purple-rgb: 214, 97, 234;
}
/* ==========================================================================
   LIGHT — Catalis Core light palette (L1)
   --------------------------------------------------------------------------
   Set data-theme="light" on <html>. Only tokens are redefined here; no rule
   in any stylesheet knows which theme is active.

   The neutral ramp is authored rather than inverted. In dark a divider sits
   ABOVE its surface in lightness (#585d6e on #101114, +32); in light it sits
   BELOW it (#e8e8e8 on white, -8). Mirroring the dark ramp turns every
   border into a heavy mid-grey slab, so the surface end is anchored on
   Catalis's own light grounds and the text end climbs to near-black.
   ========================================================================== */

[data-theme="light"] {
    /* ---------- Neutral ramp ---------- */
    --ct-n-4  : #ffffff;
    --ct-n-8  : #ffffff;
    --ct-n-12 : #f8fafd;
    --ct-n-16 : #eceef1;
    --ct-n-20 : #e4e7ec;
    --ct-n-24 : #dadfe6;
    --ct-n-40 : #96989f;
    --ct-n-44 : #898c94;
    --ct-n-48 : #797c85;
    --ct-n-52 : #6f727c;
    --ct-n-56 : #656873;
    --ct-n-60 : #585c67;
    --ct-n-64 : #4f535e;
    --ct-n-68 : #50545f;
    --ct-n-72 : #444855;
    --ct-n-76 : #393e4a;
    --ct-n-80 : #353a47;
    --ct-n-84 : #2b303e;
    --ct-n-88 : #252a38;
    --ct-n-92 : #1a202f;
    --ct-n-96 : #131828;
    --ct-n-100: #0b1120;

    /* ---------- Brand ----------
       Navy is the FOREGROUND here. That is the whole point of a light theme
       for this brand: #1F3C6E is unusable as text on charcoal, so dark mode
       substitutes navy-400 for it. On white it can finally be itself. */

    /* The base semantic tokens. Without these the light theme inherits the
       DARK ones -- which are chosen to sit on charcoal, so `var(--ct-primary)`
       came out as pale sky blue on white, about 1.8:1. Each value is its own
       -rgb triplet above, kept identical so the pair cannot drift apart. */
    --ct-accent:   #1F3C6E;   /* 10.88:1 on white */
    --ct-primary:  #1F3C6E;   /* 10.88:1 on white */
    --ct-info:     #01579B;   /* 7.40:1 on white */
    --ct-success:  #02700E;   /* 5.68:1 on white */
    --ct-warning:  #8F5201;   /* 5.57:1 on white */
    --ct-danger:   #BA0000;   /* 6.48:1 on white */

    --ct-accent-rgb:   31, 60, 110;
    --ct-primary-rgb:  31, 60, 110;
    --ct-info-rgb:     1, 87, 155;
    --ct-success-rgb:  2, 112, 14;
    --ct-warning-rgb:  143, 82, 1;
    --ct-danger-rgb:   186, 0, 0;

    --ct-accent-fill:   #1F3C6E;
    --ct-primary-fill:  #1F3C6E;
    --ct-info-fill:     #01579B;
    --ct-success-fill:  #038911;
    --ct-warning-fill:  #AF6300;
    --ct-danger-fill:   #D50000;

    /* ---------- Brand ramps ----------
       Same construction as dark, reversed: steps below the base mix toward
       white, steps above it toward black, so a hover still darkens against a
       light ground instead of washing out. */
    --ct-accent-20  : #697c9e;
    --ct-accent-30  : #50678e;
    --ct-accent-40  : #38517e;
    --ct-accent-50  : #1f3c6e;
    --ct-accent-60  : #1c3562;
    --ct-accent-70  : #182f56;
    --ct-accent-80  : #15284a;
    --ct-accent-90  : #11223e;

    --ct-success-20  : #55a75f;
    --ct-success-30  : #3a9945;
    --ct-success-40  : #1e8a2a;
    --ct-success-50  : #027c10;
    --ct-success-60  : #026e0e;
    --ct-success-70  : #02610c;
    --ct-success-80  : #01530b;
    --ct-success-90  : #014509;

    --ct-warning-20  : #be9055;
    --ct-warning-30  : #b37e39;
    --ct-warning-40  : #a96c1d;
    --ct-warning-50  : #9e5a01;
    --ct-warning-60  : #8d5001;
    --ct-warning-70  : #7b4601;
    --ct-warning-80  : #6a3c01;
    --ct-warning-90  : #583201;

    --ct-danger-20  : #d55454;
    --ct-danger-30  : #ce3838;
    --ct-danger-40  : #c71c1c;
    --ct-danger-60  : #ab0000;
    --ct-danger-70  : #960000;
    --ct-danger-80  : #810000;
    --ct-danger-90  : #6c0000;

    --ct-primary-20  : #697c9e;
    --ct-primary-30  : #50678e;
    --ct-primary-40  : #38517e;
    --ct-primary-50  : #1f3c6e;
    --ct-primary-60  : #1c3562;
    --ct-primary-70  : #182f56;
    --ct-primary-80  : #15284a;
    --ct-primary-90  : #11223e;

    --ct-info-20  : #558ebc;
    --ct-info-40  : #1d69a6;
    --ct-info-70  : #014479;
    --ct-info-90  : #013157;

    /* Error text on a light ground is the saturated red, not the pale tint the
       dark theme needs. Kept as a separate token so nothing has to guess. */
    --ct-danger-solid: #D50000;

    /* ---------- Semantic surfaces and text ----------
       These sit alongside the ramp rather than on it, and are what a rule
       reaches for when it means "the page" or "body copy". Leaving them out
       was why the first light build still painted a dark page. */
    --ct-bg-canvas: #ffffff;              /* Catalis --bg-canvas    */
    --ct-bg-appbar: #f8fafd;              /* Catalis --bg-appbar    */
    --ct-bg-drawer: #eceef1;              /* Catalis --bg-drawer    */
    --ct-bg-panel:  #e4e7ec;              /* one step down, raised  */

    --ct-fg:        rgba(0, 0, 0, 0.60);  /* Catalis --fg-secondary */
    --ct-fg-muted:  rgba(0, 0, 0, 0.38);  /* Catalis --fg-disabled  */
    --ct-fg-strong: rgba(0, 0, 0, 0.87);  /* Catalis --fg-primary   */

    --ct-line:      #e8e8e8;              /* Catalis --line-default */

    /* Channel triplets for the same ramp. rgba() cannot take a hex token for
       its colour, and 133 places paint with a translucent grey — table
       striping, filled panels, the active nav tab. Without these they stay
       dark when the theme flips. */
    --ct-n-4-rgb:    255, 255, 255;
    --ct-n-8-rgb:    255, 255, 255;
    --ct-n-12-rgb:   248, 250, 253;
    --ct-n-16-rgb:   236, 238, 241;
    --ct-n-20-rgb:   228, 231, 236;
    --ct-n-24-rgb:   218, 223, 230;
    --ct-n-40-rgb:   150, 152, 159;
    --ct-n-44-rgb:   137, 140, 148;
    --ct-n-48-rgb:   121, 124, 133;
    --ct-n-52-rgb:   111, 114, 124;
    --ct-n-56-rgb:   101, 104, 115;
    --ct-n-60-rgb:   88, 92, 103;
    --ct-n-64-rgb:   79, 83, 94;
    --ct-n-68-rgb:   80, 84, 95;
    --ct-n-72-rgb:   68, 72, 85;
    --ct-n-76-rgb:   57, 62, 74;
    --ct-n-80-rgb:   53, 58, 71;
    --ct-n-84-rgb:   43, 48, 62;
    --ct-n-88-rgb:   37, 42, 56;
    --ct-n-92-rgb:   26, 32, 47;
    --ct-n-96-rgb:   19, 24, 40;
    --ct-n-100-rgb: 11, 17, 32;

    /* Purple -- an environment/queue tag colour with no semantic family. 4.62:1 on its own tint */
    --ct-purple:     #9A27AE;
    --ct-purple-rgb: 154, 39, 174;
}
