/* GLACIER FLARE - owner pick 2026-08-29. Contrast audited (WCAG):
   dark on #0d1013 / #14181d / #1b2129: ink 16.93/15.82/14.38, mut 7.84/7.33/6.66,
   acc #a8d8f0 12.49/11.67/10.60, pass 12.57, fail 7.89, warn 10.82,
   test(flare) #ff8b3d 8.19/7.65/6.95; btn ink-on-acc 12.49, ink-on-flare 8.19.
   light on #f2f6f9: ink 15.80, mut 5.79, acc #0b6a99 5.47, pass 4.66,
   fail 5.21, warn 5.45, test #b45309 4.62. All text pairs clear AA 4.5:1. */
@font-face {
  font-family: "ELMono";
  src: url("/assets/fonts/JetBrainsMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "ELMono";
  src: url("/assets/fonts/JetBrainsMono-Bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "ELSans";
  src: url("/assets/fonts/InterVariable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* Space Grotesk 2.0.0, variable weight axis 300-700, SIL OFL 1.1.
   Licence text ships beside it at SpaceGrotesk-LICENSE.txt. */
@font-face {
  font-family: "ELDisplay";
  src: url("/assets/fonts/SpaceGrotesk-Variable.woff2") format("woff2");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

:root {
  --bg: #0d1013;
  --panel: #14181d;
  --panel-2: #1b2129;
  --ink: #edf2f6;
  --mut: #9aa8b4;
  --line: #28313c;
  --acc: #a8d8f0;
  --acc-soft: rgba(255, 144, 102, 0.12);

  /* Semantic quartet. --pass is the counterpoint mint. */
  --pass: #8ce68f;
  --fail: #ff8271;
  --warn: #ffb454;
  --test: #ff8b3d;

  --term-bg: #0b0f14;
  --shadow: 0 40px 90px rgba(0, 0, 0, 0.55);

  /* Console chrome - the bits of .editor/.term/.assert/.receipts/.rail-dock
     that are not part of the semantic quartet (bars, tabs, panel depth,
     borders, syntax token colors, line numbers). Dark defaults here are the
     values these elements have always painted; light mode redefines them
     below so the console inverts instead of staying a dark island - see the
     light block for the audited contrast table. */
  --con-bg2: #11161d;
  --con-panel: #0a0d12;
  --con-border: #1e2733;
  --con-border-2: #161d26;
  --con-dot-off: #2c3240;
  --con-ln: #46525f;
  --con-where: #93a3b5;
  --con-tag: #8494a6;
  --con-k: #ff9066;
  --con-s: #ffc76b;
  --con-f: #7fdcd2;
  --con-n: #d29ae8;
  --con-pass: #8ce68f;

  --mono: "ELMono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  --sans: "ELSans", system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --disp: "ELDisplay", "ELSans", system-ui, Helvetica, Arial, sans-serif;

  /* Fluid type scale, base 1rem, ~1.25 ratio at desktop. */
  --step--1: clamp(0.83rem, 0.8rem + 0.15vw, 0.9rem);
  --step-0: clamp(1rem, 0.95rem + 0.2vw, 1.06rem);
  --step-1: clamp(1.15rem, 1.05rem + 0.4vw, 1.32rem);
  --step-2: clamp(1.4rem, 1.15rem + 1vw, 1.9rem);
  --step-3: clamp(1.75rem, 1.3rem + 2vw, 2.9rem);
  --step-4: clamp(2.2rem, 1.4rem + 3.4vw, 4rem);

  /* Display scale - the headline sizes. These are the design.
     Floors are set for a true 320px viewport: mobile-first pass 2026-08-29
     lowered them so the display type scales all the way down to phones
     without breaking words - the vw term still carries the growth up to
     the same desktop maximum. */
  --disp-1: clamp(2.3rem, 1rem + 9.4vw, 9.5rem);
  --disp-2: clamp(1.9rem, 1rem + 6.4vw, 6.5rem);
  --disp-3: clamp(1.6rem, 1.1rem + 4vw, 4rem);

  /* Space scale. */
  --s1: 0.25rem;
  --s2: 0.5rem;
  --s3: 1rem;
  --s4: 1.5rem;
  --s5: 2.5rem;
  /* fluid rhythm: the fixed 4/7rem stack was tuned for 1440px and gaped at
     every smaller width - three independent gap audits (320/390/768) traced
     8 of the top-10 vertical gaps to a non-responsive --s7 (2026-08-29) */
  --s6: clamp(2.5rem, 1.8rem + 2.4vw, 4rem);
  --s7: clamp(3.5rem, 2.4rem + 4.8vw, 7rem);

  --radius: 10px;

  /* Page frame: a 12 column grid, not a narrow centred column. */
  --maxw: 1560px;
  --pad: clamp(1rem, 4vw, 4.5rem);
}

body[data-product="java"] { --acc: #ffb454; --acc-soft: rgba(255, 199, 107, 0.12); }
body[data-product="python"] { --acc: #8ce68f; --acc-soft: rgba(95, 242, 176, 0.12); }
body[data-product="c"] { --acc: #a8d8f0; --acc-soft: rgba(255, 144, 102, 0.12); }
body[data-product="frontend"] { --acc: #d29ae8; --acc-soft: rgba(210, 154, 232, 0.12); }
body[data-product="php"] { --acc: #a8b0e0; --acc-soft: rgba(168, 176, 224, 0.12); }
body[data-product="devops"] { --acc: #7fdcd2; --acc-soft: rgba(127, 220, 210, 0.12); }

/* The IntelliJ design study (jetbrains-study.njk) is always a Java scene,
   regardless of which page's product context it is embedded in (it lives
   on /upcoming/, which carries no body[data-product]) - so it always
   carries the Java accent, reusing the same audited value as
   body[data-product="java"] above rather than inventing a new one. */
.jb-ide { --acc: #ffb454; --acc-soft: rgba(255, 199, 107, 0.12); }

/* Light theme: redefine only what differs. Every dark hue above is far too
   light to sit on paper, so the whole semantic set is restated darker.
   Measured on --bg #f2f6f9 (and, in brackets, --panel #ffffff):
     ink   #161c22 -> 15.49 (16.43)
     mut   #526270 ->  6.53 ( 6.93)
     acc   #b8380a ->  5.29 ( 5.61)
     pass  #0d7f47 ->  6.18 ( 6.56)
     fail  #c22b3d ->  5.94 ( 6.30)
     warn  #8a5a00 ->  6.22 ( 6.60)
     test  #b45309 ->  5.67 ( 6.02)
   Solid buttons paint #ffffff on --acc #b8380a -> 5.82:1.
   Per-product light accents, on --bg #f2f6f9 / white-on-accent:
     java     #8a5a00 -> 6.22 / 6.85
     python   #0d7f47 -> 6.18 / 6.81
     c        #b8380a -> 5.29 / 5.82
     frontend #8a2ec0 -> 5.90 / 6.50
     php      #4d55a0 -> 6.11 / 6.73
     devops   #0c6f7c -> 5.33 / 5.87

   Console inversion (owner ruling 2026-08-30): in light mode --term-bg
   flips to white so .editor/.term/.assert/.receipts/.rail-dock read as
   light panels, dark ink, instead of staying a dark island - the prior
   dark-pinned island left the rail-dock's product names (var(--ink) on
   var(--term-bg)) rendering near-black-on-near-black. --ink/--mut/--acc/
   --pass/--fail/--warn/--test above are reused unchanged (already audited
   on --panel #ffffff, the bracketed figures above); the console-only
   chrome tokens (bars, tabs, panel depth, borders, syntax highlight,
   line numbers) get their own light values here. Measured on --term-bg
   #ffffff (and, in brackets, --con-bg2 #eef1f4, the bar/tab/panel depth
   tint):
     ink        #161c22 -> 17.17 (15.14)
     mut        #526270 ->  6.29 ( 5.55)
     acc        #0b6a99 ->  5.94 ( 5.24)
     pass       #0d7f47 ->  5.07
     fail       #c22b3d ->  5.67
     warn       #8a5a00 ->  5.93
     test/con-s #8f4508 ->  6.95
     con-ln     #6b7885 ->  4.52
     con-where  #5a6773 ->  5.80 ( 5.11)
     con-tag    #5a6773 ->  5.80 ( 5.11)
     con-k      #b8380a ->  5.82
     con-f      #0c6f7c ->  5.87
     con-n      #8a2ec0 ->  6.50
     con-pass   #0a6b3c ->  6.60 ( 5.82); 5.18 on the active-row tint
                #eae2e1. The console green: --pass #0d7f47 is audited on
                --bg/--panel and measures 4.47 on --con-bg2 #eef1f4, under
                AA, so the small chrome chips inside a console (FREE chips,
                PASSED verdicts) paint this darker green instead.
   Per-product accents (already listed above) all clear 4.5:1 on white
   (min 5.07, python); every console text/bg pair is AA or better. */
@media (prefers-color-scheme: light) {
  :root {
    --bg: #f2f6f9;
    --panel: #ffffff;
    --panel-2: #e8eef3;
    --ink: #161c22;
    --mut: #526270;
    --line: #e2d2be;
    --acc: #0b6a99;
    --acc-soft: rgba(184, 56, 10, 0.08);
    --pass: #0d7f47;
    --fail: #c22b3d;
    --warn: #8a5a00;
    --test: #8f4508; /* 5.99:1 on the chip tint #f3edea */
    --term-bg: #ffffff;
    --shadow: 0 30px 70px rgba(120, 70, 30, 0.18);
    --con-bg2: #eef1f4;
    --con-panel: #eef1f4;
    --con-border: #c9d3db;
    --con-border-2: #d7dee4;
    --con-dot-off: #c7d0d8;
    --con-ln: #6b7885;
    --con-where: #5a6773;
    --con-tag: #5a6773;
    --con-k: #b8380a;
    --con-s: #8f4508;
    --con-f: #0c6f7c;
    --con-n: #8a2ec0;
    --con-pass: #0a6b3c;
  }
  body[data-product="java"] { --acc: #8a5a00; --acc-soft: rgba(122, 83, 6, 0.08); }
  body[data-product="python"] { --acc: #0d7f47; --acc-soft: rgba(4, 104, 74, 0.08); }
  body[data-product="c"] { --acc: #0b6a99; --acc-soft: rgba(184, 56, 10, 0.08); }
  body[data-product="frontend"] { --acc: #8a2ec0; --acc-soft: rgba(138, 46, 192, 0.08); }
  body[data-product="php"] { --acc: #4d55a0; --acc-soft: rgba(77, 85, 160, 0.08); }
  body[data-product="devops"] { --acc: #0c6f7c; --acc-soft: rgba(12, 111, 124, 0.08); }
  .jb-ide { --acc: #8a5a00; --acc-soft: rgba(122, 83, 6, 0.08); }
}

/* Explicit theme override, set by the header toggle (theme-boot.js stamps
   data-theme on <html> before paint; site.js keeps it in sync after a
   click). Selector targets :root because data-theme is set on <html>, not
   <body>. These blocks must OUTRANK prefers-color-scheme unconditionally -
   a user who explicitly chose light while their OS is set to dark must get
   the light palette, and vice versa - so both are plain (non-@media)
   :root[data-theme=...] rules; cascade order after the media query above is
   enough since a plain selector always wins a tie against one nested in a
   media query at equal specificity, and unlike the query these are never
   conditionally inert. Values are verbatim restatements of the bare :root
   (dark) and the prefers-color-scheme:light block above - see those two
   blocks for the audited contrast ratios; nothing here is a new color. */
:root[data-theme="dark"] {
  --bg: #0d1013;
  --panel: #14181d;
  --panel-2: #1b2129;
  --ink: #edf2f6;
  --mut: #9aa8b4;
  --line: #28313c;
  --acc: #a8d8f0;
  --acc-soft: rgba(255, 144, 102, 0.12);
  --pass: #8ce68f;
  --fail: #ff8271;
  --warn: #ffb454;
  --test: #ff8b3d;
  --term-bg: #0b0f14;
  --shadow: 0 40px 90px rgba(0, 0, 0, 0.55);
  --con-bg2: #11161d;
  --con-panel: #0a0d12;
  --con-border: #1e2733;
  --con-border-2: #161d26;
  --con-dot-off: #2c3240;
  --con-ln: #46525f;
  --con-where: #93a3b5;
  --con-tag: #8494a6;
  --con-k: #ff9066;
  --con-s: #ffc76b;
  --con-f: #7fdcd2;
  --con-n: #d29ae8;
  --con-pass: #8ce68f;
}
:root[data-theme="dark"] body[data-product="java"] { --acc: #ffb454; --acc-soft: rgba(255, 199, 107, 0.12); }
:root[data-theme="dark"] body[data-product="python"] { --acc: #8ce68f; --acc-soft: rgba(95, 242, 176, 0.12); }
:root[data-theme="dark"] body[data-product="c"] { --acc: #a8d8f0; --acc-soft: rgba(255, 144, 102, 0.12); }
:root[data-theme="dark"] body[data-product="frontend"] { --acc: #d29ae8; --acc-soft: rgba(210, 154, 232, 0.12); }
:root[data-theme="dark"] body[data-product="php"] { --acc: #a8b0e0; --acc-soft: rgba(168, 176, 224, 0.12); }
:root[data-theme="dark"] body[data-product="devops"] { --acc: #7fdcd2; --acc-soft: rgba(127, 220, 210, 0.12); }
:root[data-theme="dark"] .jb-ide { --acc: #ffb454; --acc-soft: rgba(255, 199, 107, 0.12); }

:root[data-theme="light"] {
  --bg: #f2f6f9;
  --panel: #ffffff;
  --panel-2: #e8eef3;
  --ink: #161c22;
  --mut: #526270;
  --line: #e2d2be;
  --acc: #0b6a99;
  --acc-soft: rgba(184, 56, 10, 0.08);
  --pass: #0d7f47;
  --fail: #c22b3d;
  --warn: #8a5a00;
  --test: #8f4508;
  --term-bg: #ffffff;
  --shadow: 0 30px 70px rgba(120, 70, 30, 0.18);
  --con-bg2: #eef1f4;
  --con-panel: #eef1f4;
  --con-border: #c9d3db;
  --con-border-2: #d7dee4;
  --con-dot-off: #c7d0d8;
  --con-ln: #6b7885;
  --con-where: #5a6773;
  --con-tag: #5a6773;
  --con-k: #b8380a;
  --con-s: #8f4508;
  --con-f: #0c6f7c;
  --con-n: #8a2ec0;
  --con-pass: #0a6b3c;
}
:root[data-theme="light"] body[data-product="java"] { --acc: #8a5a00; --acc-soft: rgba(122, 83, 6, 0.08); }
:root[data-theme="light"] body[data-product="python"] { --acc: #0d7f47; --acc-soft: rgba(4, 104, 74, 0.08); }
:root[data-theme="light"] body[data-product="c"] { --acc: #0b6a99; --acc-soft: rgba(184, 56, 10, 0.08); }
:root[data-theme="light"] body[data-product="frontend"] { --acc: #8a2ec0; --acc-soft: rgba(138, 46, 192, 0.08); }
:root[data-theme="light"] body[data-product="php"] { --acc: #4d55a0; --acc-soft: rgba(77, 85, 160, 0.08); }
:root[data-theme="light"] body[data-product="devops"] { --acc: #0c6f7c; --acc-soft: rgba(12, 111, 124, 0.08); }
:root[data-theme="light"] .jb-ide { --acc: #8a5a00; --acc-soft: rgba(122, 83, 6, 0.08); }

/* Console surfaces used to be pinned dark in BOTH themes (a dark island
   inside a light page). Owner ruling 2026-08-30, with screenshot evidence:
   that left broken spots - the homepage status rail's product names
   (.rail-name, var(--ink)) rendered near-black on the pinned-dark
   --term-bg, and the mixed dark-in-light look jarred everywhere else
   (.editor/.term/.assert/.receipts/.rail-dock). The fix is the opposite of
   the old approach: --term-bg and the --con-* chrome tokens above are now
   THEMED (dark values in the dark blocks, light values in the light
   blocks) instead of pinned, so a console surface inverts to a light panel
   with dark ink in light mode, same as every other panel, and stays
   exactly as before in dark mode since the dark-block values are
   unchanged. No per-selector override is needed here any more: --ink/
   --mut/--acc/--pass/--fail/--warn/--test already carry the theme's
   audited value by inheritance, and .assert/.receipts/.editor/.term paint
   var(--term-bg) - see the light @media block above for the full light
   console contrast table (all pairs AA or better) and the two
   :root[data-theme=...] blocks above for the per-theme --con-* chrome
   values consumed by src/assets/css/v2.css (.ed-bar, .ed-tab, .ed-panel,
   .ed-strip, .ed-code syntax classes, .term-bar, .receipts, .rail-dock).
   This also covers the ignition trigger words (.grn/.amb/.tst/.hardpass/
   .hl), which each derive --ig from these same properties. */
