/* libli design tokens. @font-face first; then the palette derived via color-mix()
   from two raw institution-overridable inputs. See docs/design-language.md. */
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("../fonts/inter/Inter-Regular.da03732a27e1.woff2") format("woff2");
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("../fonts/inter/Inter-Medium.51205681a1ba.woff2") format("woff2");
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("../fonts/inter/Inter-SemiBold.2ede57db1a3a.woff2") format("woff2");
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("../fonts/inter/Inter-Bold.8ca0a5155296.woff2") format("woff2");
}

:root {
  /* raw institution-overridable inputs (defaults = warm teal / amber) */
  --brand-primary: #147E78;
  --brand-accent:  #C77B2A;

  /* derived brand families (light) */
  --primary:        var(--brand-primary);
  --primary-hover:  color-mix(in srgb, var(--brand-primary) 88%, black);
  --primary-active: color-mix(in srgb, var(--brand-primary) 78%, black);
  --primary-subtle: color-mix(in srgb, var(--brand-primary) 16%, var(--surface-raised));
  --accent:         var(--brand-accent);
  --accent-hover:   color-mix(in srgb, var(--brand-accent) 88%, black);
  --accent-subtle:  color-mix(in srgb, var(--brand-accent) 18%, var(--surface-raised));

  /* surfaces / text / borders — flat literals (design-language.md, light) */
  --surface-base: #F4F1EA; --surface-raised: #FFFFFF; --surface-sunken: #FAF8F3;
  --surface-overlay: rgba(30,28,24,0.45);
  /* Edge shading for a horizontally scrollable box (.scroll-x). A translucent
     shade rather than a fade to a surface colour: it sits over table cells whose
     own backgrounds vary (raised card, sunken header tint, zebra rows), so any
     opaque fade colour would be wrong against at least one of them. */
  --scroll-edge: rgba(30,28,24,0.16);
  /* Lightbox scrim for the click-to-enlarge overlay. Declared ONCE, here, and
     deliberately NOT repeated in the [data-theme="dark"] block below: that absence is
     the mechanism by which the overlay is identical in both themes (image viewers are
     conventionally dark). A source-level test enforces it, because every neighbouring
     surface token IS defined twice and the next routine edit here is the one that would
     silently break it. Near-opaque, unlike --surface-overlay: nothing of the page may
     show through. */
  --scrim-solid: rgba(12,11,10,0.97);
  --text-primary: #1E1C18; --text-secondary: #5A544A; --text-tertiary: #8A8477;
  --text-inverse: #FBF9F4;
  --border-subtle: #EDE8DE; --border-default: #E7E1D6; --border-strong: #D6CFC1;

  /* semantic */
  --success: #5A7D3C; --success-subtle: #E3ECD7;
  --warning: #B8811F; --warning-subtle: #F4E8CD;
  --danger:  #A8392E; --danger-subtle:  #F2D9D5;
  /* Author-selectable text colour. Independent of --danger/--success/--warning
     despite some dark values coinciding: those are UI accents and may move for
     UI reasons; these are body-text colours measured against ten surfaces
     (see tests/test_text_colour_css.py). Light red and --danger-subtle sit at a
     4.51:1 margin — neither moves without re-running that test. */
  --tc-red: #B2372A; --tc-blue: #1F61AD; --tc-green: #3F6B24; --tc-orange: #8A5514;

  /* radius / shadow / type / spacing */
  --radius-sm: 7px; --radius-md: 10px; --radius-lg: 12px; --radius-xl: 18px;
  --radius-full: 9999px;
  --shadow-xs: 0 1px 2px rgba(30,28,24,.06);
  --shadow-sm: 0 2px 6px rgba(30,28,24,.08);
  --shadow-md: 0 6px 16px rgba(30,28,24,.10);
  --shadow-lg: 0 16px 40px rgba(30,28,24,.14);
  --font-ui: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono: "SFMono-Regular", ui-monospace, "Cascadia Code", "Consolas", monospace;
  --heading-letter-spacing: -0.015em;
  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px;
  --space-5: 20px; --space-6: 24px; --space-8: 32px; --space-10: 40px;
}

[data-theme="dark"] {
  /* brand lift (dark) */
  --primary:        color-mix(in srgb, var(--brand-primary) 68%, white);
  --primary-hover:  color-mix(in srgb, var(--brand-primary) 78%, white);
  --primary-active: color-mix(in srgb, var(--brand-primary) 88%, white);
  --primary-subtle: color-mix(in srgb, var(--brand-primary) 24%, var(--surface-raised));
  --accent:         color-mix(in srgb, var(--brand-accent) 70%, white);
  --accent-hover:   color-mix(in srgb, var(--brand-accent) 80%, white);
  --accent-subtle:  color-mix(in srgb, var(--brand-accent) 26%, var(--surface-raised));

  /* surfaces / text / borders — flat literals (design-language.md, dark) */
  --surface-base: #1A1816; --surface-raised: #2C2925; --surface-sunken: #15130F;
  --surface-overlay: rgba(0,0,0,0.55);
  --scroll-edge: rgba(0,0,0,0.45);   /* deeper: dark surfaces swallow a light shade */
  --text-primary: #F2EFE9; --text-secondary: #BDB6A8; --text-tertiary: #8A8477;
  --text-inverse: #1E1C18;
  /* Cut against --surface-raised, NOT --surface-base. Raised (#2C2925) is the
     LIGHTER of the two in dark mode, so a ramp derived from the page background
     passes straight through it: the previous --border-default (#322E29) scored
     1.07:1 on a raised card and 1.04:1 on a callout's 6% tint, which is why a
     table's grid lines vanished inside a callout — and the ladder inverted there,
     "subtle" reading more strongly than "default". tests/test_border_contrast_css.py
     measures every rung on all eight grounds a neutral hairline is drawn on. */
  --border-subtle: #443B32; --border-default: #584C40; --border-strong: #706152;
  --success: #9FBF7B; --success-subtle: #2A3620;
  --warning: #E8B761; --warning-subtle: #3A2F18;
  --danger:  #E57373; --danger-subtle:  #3A1E1A;
  --tc-red: #EA8A82; --tc-blue: #8FBCE8; --tc-green: #9FBF7B; --tc-orange: #E8B761;
  --shadow-xs: 0 1px 2px rgba(0,0,0,.4);
  --shadow-sm: 0 2px 6px rgba(0,0,0,.45);
  --shadow-md: 0 6px 16px rgba(0,0,0,.5);
  --shadow-lg: 0 16px 40px rgba(0,0,0,.55);
}

/* ── Print: restore the light palette ──────────────────────────────────────
   A dark-theme student printing any page gets near-white text on white paper:
   browsers strip backgrounds by default, and --text-primary is #F2EFE9. This
   block restates EVERY token the [data-theme="dark"] block declares, using
   :root's declaration for each -- color-mix() formulas included, because dark
   mixes toward white and light toward black, so the formulas genuinely differ.

   Placement is load-bearing: :root and [data-theme="dark"] are both (0,1,0) and
   both match <html>, so this wins only by source order. Anywhere above the dark
   block (tokens.css:79) it is silently inert. Keep it last in the file.
   tests/test_print_tokens_css.py pins both the placement and every value. */
@media print {
  /* Light theme prints this element invisibly too -- see the --text-inverse note
     below. Fixing only the dark path would leave the same blank Next button on
     every light-theme printout. */
  :root { --text-inverse: #1E1C18; }

  [data-theme="dark"] {
    /* brand lift — :root mixes toward black, the dark block toward white */
    --primary:        var(--brand-primary);
    --primary-hover:  color-mix(in srgb, var(--brand-primary) 88%, black);
    --primary-active: color-mix(in srgb, var(--brand-primary) 78%, black);
    --primary-subtle: color-mix(in srgb, var(--brand-primary) 16%, var(--surface-raised));
    --accent:         var(--brand-accent);
    --accent-hover:   color-mix(in srgb, var(--brand-accent) 88%, black);
    --accent-subtle:  color-mix(in srgb, var(--brand-accent) 18%, var(--surface-raised));

    /* surfaces / text / borders */
    --surface-base: #F4F1EA; --surface-raised: #FFFFFF; --surface-sunken: #FAF8F3;
    --surface-overlay: rgba(30,28,24,0.45);
    --scroll-edge: rgba(30,28,24,0.16);
    --text-primary: #1E1C18; --text-secondary: #5A544A; --text-tertiary: #8A8477;
    /* The ONE deliberate divergence from :root. --text-inverse is only ever
       `color:` on a `background: var(--primary)` (app.css:39,53; the unit-footer
       Next link at courses.css:814). Print strips backgrounds, so the paint that
       justifies an "inverse" colour is gone: :root's #FBF9F4 would print at
       1.05:1 on white -- the exact defect this whole block exists to fix, and the
       dark theme's own #1E1C18 (17.01:1) was accidentally the safe one. Both
       themes get dark ink; the :root override below covers the light theme, which
       has been printing this element invisibly all along. */
    --text-inverse: #1E1C18;
    --border-subtle: #EDE8DE; --border-default: #E7E1D6; --border-strong: #D6CFC1;

    /* semantic */
    --success: #5A7D3C; --success-subtle: #E3ECD7;
    --warning: #B8811F; --warning-subtle: #F4E8CD;
    --danger:  #A8392E; --danger-subtle:  #F2D9D5;

    /* Author-selectable body-text colours. Easy to miss and the most visible
       omission: without these a lesson using coloured text still prints
       near-white-on-white, which is the exact defect this block exists to fix. */
    --tc-red: #B2372A; --tc-blue: #1F61AD; --tc-green: #3F6B24; --tc-orange: #8A5514;

    --shadow-xs: 0 1px 2px rgba(30,28,24,.06);
    --shadow-sm: 0 2px 6px rgba(30,28,24,.08);
    --shadow-md: 0 6px 16px rgba(30,28,24,.10);
    --shadow-lg: 0 16px 40px rgba(30,28,24,.14);
  }
}
