/* =============================================================================================
   WPI Design Template  ·  LAYER 1: TOKENS
   Framework-agnostic. This file is the product; everything else is a bridge to it.

   Two palette families x two modes = four skins:

       [data-palette]  signature (default) | brand   <- per system, set once, server-side
       [data-bs-theme] light | dark                  <- per user, resolved by js/wpi-theme.js

   Load order:
       wpi-tokens.css        (this file)      always
       wpi-tabler.css        Tabler/Bootstrap 5 apps, AFTER tabler.min.css
       wpi-components.css    always, last
       wpi-tailwind.css      Tailwind v4 apps, instead of wpi-tabler.css

   The attribute names keep the "data-bs-theme" spelling in the Tailwind stack too. It costs
   nothing there and means one theme resolver script serves both ecosystems.

   Every color here is contrast-gated. After editing any token run:
       python3 tools/contrast-check.py
   ============================================================================================= */


/* =============================================================================================
   Display serif: Instrument Serif (SIL OFL, see assets/fonts/OFL.txt).
   Single-weight display face. Use at >= ~28px ONLY: titles, stat numerals, pitch headings.
   Body copy stays on each system's existing sans (Inter in the portals).

   ONE deliberate exception: .wpi-wordmark sits at 24px, because the lockup has to line up
   beside a 1.35rem brand mark in a sidebar and 28px there is out of scale. It survives at 24px
   where body copy would not, being two fixed words that never reflow, never wrap and never
   carry information a user has to read carefully. Do not treat it as precedent.
   ============================================================================================= */
@font-face {
    font-family: "Instrument Serif";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../assets/fonts/instrument-serif-latin-v5.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "Instrument Serif";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../assets/fonts/instrument-serif-latin-ext-v5.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}


/* =============================================================================================
   LAYER 1: PALETTE BLOCKS

   Selectors are bare attribute selectors, NOT :root-anchored, so a skin can also be applied to
   a container (the showcase renders all four at once that way). In production both attributes
   live on <html>.

   Specificity ladder, deliberate:
       [data-bs-theme=dark]                     (0,1,0)  signature dark  <- default palette
       [data-bs-theme=dark][data-palette=brand] (0,2,0)  brand dark      <- wins, more specific
   ============================================================================================= */

/* ---------------------------------------------------------------------------------------------
   SIGNATURE DARK: the default look. Three distinct near-blacks (page / card / stripe) so table
   striping and hover depth survive on a black page. Metallic accents, black-on-gold buttons.
   Values are the production set these skins were derived from, with one correction noted below.
   --------------------------------------------------------------------------------------------- */
[data-bs-theme="dark"] {
    --wpi-page: #000000;
    --wpi-surface: #0d0d0d;
    --wpi-surface-alt: #141414;

    --wpi-ink: #efe7d5;
    --wpi-ink-2: #b3a88e;
    /* Was #7d745e when shipped: 3.98:1 on the stripe surface, below small-text AA. Lifted to
       #867d65 (4.50:1 worst case). This token drives footers, hints and micro-labels. */
    --wpi-ink-3: #867d65;

    --wpi-accent: #c8a55c;
    --wpi-accent-hover: #a8894a;
    --wpi-accent-ink: #14100a;      /* black on gold is 8.11:1; white on gold is 2.34:1, never */

    --wpi-link: #d9bc82;
    --wpi-link-hover: #e8cfa0;

    --wpi-hairline: rgba(200, 165, 92, 0.28);   /* decorative card edge, not a control boundary */
    --wpi-hairline-soft: rgba(200, 165, 92, 0.13);
    --wpi-form-border: #685d47;                 /* a control boundary: gated at 3:1, see below */

    --wpi-pos: #8fae7a;
    --wpi-warn: #e08a3c;
    --wpi-neg: #c98470;

    --wpi-badge-a-bg: rgba(200, 165, 92, 0.14);
    --wpi-badge-a-ink: #d9bc82;
    --wpi-badge-b-bg: rgba(200, 165, 92, 0.08);
    --wpi-badge-b-ink: #a89468;

    --wpi-num-grad: linear-gradient(115deg, #8a6d3a 0%, #e8cfa0 45%, #b28a4a 80%, #f0ddb8 100%);
    --wpi-brand-grad: linear-gradient(115deg, #9a7a40, #d9bc82 55%, #8a6d3a);
    --wpi-shine: rgba(232, 207, 160, 0.55);
    --wpi-print-ink: #221b0e;

    color-scheme: dark;

    /* Tabler's gray scale, regraded warm. Without this, transitively-resolved grays (pagination,
       disabled states, focused input borders) leak Tabler's cool blue-grays onto a warm page. */
    --tblr-gray-950: #000000;
    --tblr-gray-900: #000000;
    --tblr-gray-800: #0d0d0d;
    --tblr-gray-700: #26221a;
    --tblr-gray-600: #4a4335;
    --tblr-gray-500: #7d745e;
    --tblr-gray-400: #b3a88e;
    --tblr-gray-300: #cfc6ad;
    --tblr-gray-200: #e3dcc8;
    --tblr-gray-100: #efe7d5;
    --tblr-gray-50:  #f6f0e2;
    --tblr-disabled-color: #4a4335;   /* stock routes via gray-700: invisible on #0d0d0d */
}

/* ---------------------------------------------------------------------------------------------
   SIGNATURE LIGHT: the same language on warm paper, equal care. Bronze accents, because gold on
   white fails contrast outright. This is what light-OS users get by default.
   --------------------------------------------------------------------------------------------- */
[data-bs-theme="light"] {
    --wpi-page: #f6f1e6;
    --wpi-surface: #fffdf6;
    --wpi-surface-alt: #f1ebdc;

    --wpi-ink: #221b0e;
    --wpi-ink-2: #5f5540;
    /* Was #8a7f66 when shipped: 3.33:1 on the stripe surface. Deepened to #736a55 (4.50:1). */
    --wpi-ink-3: #736a55;

    --wpi-accent: #8f6b2e;
    --wpi-accent-hover: #6e5222;
    --wpi-accent-ink: #fffdf6;       /* white on bronze is 4.79:1 */

    /* #8f6b2e is 4.33:1 on the page paper and fails small-text AA, so links run deeper than
       the accent. This is the single most-repeated mistake in this palette. */
    --wpi-link: #7a5c27;
    --wpi-link-hover: #6e5222;

    --wpi-hairline: rgba(143, 107, 46, 0.32);
    --wpi-hairline-soft: rgba(143, 107, 46, 0.15);
    --wpi-form-border: #9c8449;

    --wpi-pos: #4e7337;
    --wpi-warn: #a5550f;
    --wpi-neg: #a04f38;

    --wpi-badge-a-bg: rgba(143, 107, 46, 0.12);
    --wpi-badge-a-ink: #6e5222;
    --wpi-badge-b-bg: rgba(143, 107, 46, 0.07);
    --wpi-badge-b-ink: #7a6534;

    /* All stops at or beyond #8f6b2e depth. The Checkpoint A mock carries a lighter set with a
       #b28a4a stop; that is the PRE-AUDIT version and must not be copied back in. */
    --wpi-num-grad: linear-gradient(115deg, #5d451c 0%, #8f6b2e 45%, #6e5222 80%, #7a5c27 100%);
    --wpi-brand-grad: linear-gradient(115deg, #7a5c27, #8f6b2e 55%, #5d451c);
    --wpi-shine: rgba(178, 138, 74, 0.45);
    --wpi-print-ink: #221b0e;

    color-scheme: light;

    --tblr-gray-950: #16110a;
    --tblr-gray-900: #221b0e;
    --tblr-gray-800: #3a362b;
    --tblr-gray-700: #55503f;
    --tblr-gray-600: #6b6250;
    --tblr-gray-500: #8a7f66;
    --tblr-gray-400: #b3a488;
    --tblr-gray-300: #d4c8a8;
    --tblr-gray-200: #e6dcc4;
    --tblr-gray-100: #f1ebdc;
    --tblr-gray-50:  #faf6ec;
    --tblr-disabled-color: #b3a488;
}

/* ---------------------------------------------------------------------------------------------
   WPI BRAND DARK: the same premium treatment built from the company's own identity.

   Colours are the OFFICIAL SPEC, from "Logo Guide.pdf" page 9, in
   /Users/dharm/Important Docs/WPI Logo_s/. Two gradient pairs:

       #07B6E6 cyan  ->  #7AF19E mint
       #077AE8 blue  ->  #74DF6F green

   The brand book is the authority, on the brand owner's instruction. All four clear AA on these
   dark surfaces untouched, so the dark skin is the book exactly: the green accent is 11.91:1
   against dark button ink and the cyan link 8.00:1 on the card.

   THE TWO GREENS ARE BOTH CORRECT, AND THEY HAVE DIFFERENT JOBS.

   The book holds the ORIGINAL brand colours. A darker logo was produced later, because the
   bright green did not hold up on some materials and backgrounds, and the book was never updated
   to include it. So the March 2025 artwork is not a mistake and the book is not wrong; the book
   is simply out of date on that one point.

   The brand owner's rule, and the reason this file splits them:

       the FULL LOGO uses the darker green      -> --wpi-brand-grad, which fills .wpi-mark
       GRAPHS and the interface use the lighter -> --wpi-accent, --wpi-link, --wpi-num-grad,
                                                   and the chart series ramp

   That is why --wpi-brand-grad below is #2ab3d6 to #4da985, the darker artwork, while everything
   around it runs the book's brighter values. The mark then matches the real lockup sitting beside
   it in the sidebar, and the charts stay bright enough to read. Getting this backwards makes the
   reconstructed mark disagree with the actual logo file on the same screen.

   STILL OPEN: which exact shade of green is used going forward. That is with the brand owner and
   John Koh. When it lands, the value to change is the green stop in --wpi-brand-grad here, plus
   --wpi-accent if the interface green moves too.
   --------------------------------------------------------------------------------------------- */
[data-bs-theme="dark"][data-palette="brand"] {
    --wpi-page: #06090c;
    --wpi-surface: #0b1116;
    --wpi-surface-alt: #101820;

    --wpi-ink: #e8eef1;
    --wpi-ink-2: #9fb0ba;
    /* Mock value #6e7e88 was 4.26:1 on the stripe surface. Lifted to #72828d (4.51:1). */
    --wpi-ink-3: #72828d;

    --wpi-accent: #74df6f;           /* book green, unmodified: 11.91:1 with dark button ink */
    --wpi-accent-hover: #5db259;
    --wpi-accent-ink: #06090c;

    --wpi-link: #07b6e6;             /* book cyan, unmodified: 8.00:1 on the card */
    --wpi-link-hover: #51ccee;

    --wpi-hairline: rgba(116, 223, 111, 0.26);
    --wpi-hairline-soft: rgba(116, 223, 111, 0.12);
    --wpi-form-border: #40647a;

    --wpi-pos: #6fbf8f;
    --wpi-warn: #f0a23a;
    --wpi-neg: #c97c70;

    --wpi-badge-a-bg: rgba(7, 182, 230, 0.16);
    --wpi-badge-a-ink: #07b6e6;
    --wpi-badge-b-bg: rgba(116, 223, 111, 0.14);
    --wpi-badge-b-ink: #7af19e;

    /* Both gradient pairs from the book, run end to end: blue into cyan into green into mint.
       This is the book's own sweep, not an interpretation of it. */
    --wpi-num-grad: linear-gradient(115deg, #077ae8 0%, #07b6e6 38%, #74df6f 74%, #7af19e 100%);
    --wpi-brand-grad: linear-gradient(115deg, #2ab3d6, #4da985);  /* the DARKER logo, see below */
    --wpi-shine: rgba(81, 204, 238, 0.5);
    --wpi-print-ink: #19191a;

    color-scheme: dark;

    /* Cool regrade, mirroring the warm one above. */
    --tblr-gray-950: #06090c;
    --tblr-gray-900: #06090c;
    --tblr-gray-800: #0b1116;
    --tblr-gray-700: #1b2a33;
    --tblr-gray-600: #3a4c57;
    --tblr-gray-500: #6e7e88;
    --tblr-gray-400: #9fb0ba;
    --tblr-gray-300: #c3d0d7;
    --tblr-gray-200: #d9e3e8;
    --tblr-gray-100: #e8eef1;
    --tblr-gray-50:  #f2f6f8;
    --tblr-disabled-color: #3a4c57;
}

/* ---------------------------------------------------------------------------------------------
   WPI BRAND LIGHT: the skin where the book cannot be used raw. On white the four spec colours
   measure 2.37:1 (cyan), 4.24:1 (blue), 1.41:1 (mint) and 1.68:1 (green). Every one fails
   small-text AA, and the two greens fail it by a wide margin.

   So they stay DISPLAY colours here, on the mark and the numerals where 3:1 governs, and every
   text and control role runs a deepened version of the same hue: #0775df for the accent so
   white button text clears 4.5:1, #066ed1 for links so they clear on the striped surface.

   That is the honest cost of a bright cyan-and-mint identity on paper, and it is worth saying
   out loud: this identity costs nothing in dark mode and a great deal on white. Deepening
   preserves the hue, so the page still reads as the brand.
   --------------------------------------------------------------------------------------------- */
[data-bs-theme="light"][data-palette="brand"] {
    --wpi-page: #f4f8f9;
    --wpi-surface: #ffffff;
    --wpi-surface-alt: #edf3f5;

    --wpi-ink: #181818;              /* the wordmark's own near-black, from the artwork */
    --wpi-ink-2: #4c5a63;
    /* Mock value #7d8b94 was 3.13:1 on the stripe surface. Deepened to #637079 (4.54:1). */
    --wpi-ink-3: #637079;

    --wpi-accent: #0775df;           /* book blue, deepened until white text clears 4.5:1 */
    --wpi-accent-hover: #0660b7;
    --wpi-accent-ink: #ffffff;       /* white on #0775df is 4.55:1 */

    --wpi-link: #066ed1;             /* 4.51:1 on the stripe, 5.05:1 on the card */
    --wpi-link-hover: #0558a7;

    --wpi-hairline: rgba(7, 182, 230, 0.32);
    --wpi-hairline-soft: rgba(7, 182, 230, 0.15);
    --wpi-form-border: #5a8fb0;

    --wpi-pos: #407b3d;
    --wpi-warn: #a65b06;
    --wpi-neg: #a04f38;

    --wpi-badge-a-bg: rgba(7, 182, 230, 0.15);
    --wpi-badge-a-ink: #057696;
    --wpi-badge-b-bg: rgba(116, 223, 111, 0.15);
    --wpi-badge-b-ink: #417d3e;

    /* Numerals are display type, so 3:1 governs, not 4.5:1. The raw logo green is 2.87:1 on the
       card and just misses, so the green stops sit at #4ba481 (3.03:1). The brand gradient below
       is the one place in this skin the logo colours appear exactly as drawn: the mark is a
       graphic, not text. */
    --wpi-num-grad: linear-gradient(115deg, #077ae8 0%, #069bc4 38%, #529e4f 74%, #519f68 100%);
    --wpi-brand-grad: linear-gradient(115deg, #2ab3d6, #4da985);
    --wpi-shine: rgba(7, 182, 230, 0.40);
    --wpi-print-ink: #19191a;

    color-scheme: light;

    --tblr-gray-950: #0d1114;
    --tblr-gray-900: #19191a;
    --tblr-gray-800: #2c3840;
    --tblr-gray-700: #3d4c56;
    --tblr-gray-600: #4c5a63;
    --tblr-gray-500: #637079;
    --tblr-gray-400: #9aa8b0;
    --tblr-gray-300: #c3d0d7;
    --tblr-gray-200: #dde6ea;
    --tblr-gray-100: #edf3f5;
    --tblr-gray-50:  #f7fafb;
    --tblr-disabled-color: #9aa8b0;
}

/* ---------------------------------------------------------------------------------------------
   No-JS / theme-script-failure fallback. Without a data-bs-theme attribute Tabler serves its
   stock light theme, and the ornament tokens must still resolve or every gradient-clipped
   heading renders transparent (invisible).

   Scoped :root:not([data-bs-theme]) on purpose. A bare :root block here would TIE the theme
   blocks on specificity (both land on <html>) and, being later in source order, silently
   clobber the dark tokens. That bug shipped once and was caught in a re-audit.
   --------------------------------------------------------------------------------------------- */
:root:not([data-bs-theme]) {
    --wpi-page: #f6f1e6;
    --wpi-surface: #fffdf6;
    --wpi-surface-alt: #f1ebdc;
    --wpi-ink: #221b0e;
    --wpi-ink-2: #5f5540;
    --wpi-ink-3: #736a55;
    --wpi-accent: #8f6b2e;
    --wpi-accent-hover: #6e5222;
    --wpi-accent-ink: #fffdf6;
    --wpi-link: #7a5c27;
    --wpi-link-hover: #6e5222;
    --wpi-hairline: rgba(143, 107, 46, 0.32);
    --wpi-hairline-soft: rgba(143, 107, 46, 0.15);
    --wpi-form-border: #9c8449;
    --wpi-pos: #4e7337;
    --wpi-warn: #a5550f;
    --wpi-neg: #a04f38;
    --wpi-badge-a-bg: rgba(143, 107, 46, 0.12);
    --wpi-badge-a-ink: #6e5222;
    --wpi-badge-b-bg: rgba(143, 107, 46, 0.07);
    --wpi-badge-b-ink: #7a6534;
    --wpi-num-grad: linear-gradient(115deg, #5d451c 0%, #8f6b2e 45%, #6e5222 80%, #7a5c27 100%);
    --wpi-brand-grad: linear-gradient(115deg, #7a5c27, #8f6b2e 55%, #5d451c);
    --wpi-shine: rgba(178, 138, 74, 0.45);
    --wpi-print-ink: #221b0e;
}
:root:not([data-bs-theme])[data-palette="brand"] {
    --wpi-page: #f4f8f9;
    --wpi-surface: #ffffff;
    --wpi-surface-alt: #edf3f5;
    --wpi-ink: #181818;              /* the wordmark's own near-black, from the artwork */
    --wpi-ink-2: #4c5a63;
    --wpi-ink-3: #637079;
    --wpi-accent: #0775df;           /* book blue, deepened until white text clears 4.5:1 */
    --wpi-accent-hover: #0660b7;
    --wpi-accent-ink: #ffffff;
    --wpi-link: #066ed1;             /* 4.51:1 on the stripe, 5.05:1 on the card */
    --wpi-link-hover: #0558a7;
    --wpi-hairline: rgba(7, 182, 230, 0.32);
    --wpi-hairline-soft: rgba(7, 182, 230, 0.15);
    --wpi-form-border: #5a8fb0;
    --wpi-pos: #407b3d;
    --wpi-warn: #a65b06;
    --wpi-neg: #a04f38;
    --wpi-badge-a-bg: rgba(7, 182, 230, 0.15);
    --wpi-badge-a-ink: #057696;
    --wpi-badge-b-bg: rgba(116, 223, 111, 0.15);
    --wpi-badge-b-ink: #417d3e;
    --wpi-num-grad: linear-gradient(115deg, #077ae8 0%, #069bc4 38%, #529e4f 74%, #519f68 100%);
    --wpi-brand-grad: linear-gradient(115deg, #2ab3d6, #4da985);
    --wpi-shine: rgba(7, 182, 230, 0.40);
    --wpi-print-ink: #19191a;
}
