/* SPDX-License-Identifier: (MIT OR Apache-2.0) */

/* The one place site colours and type live. Landing page, book theme and
   playground all pull from here — the build copies this to the site root as
   /tokens.css, so the book's theme can reach it across directories.

   Every colour is written once, as a `--paper-*` or `--night-*` value. The
   blocks near the bottom only decide which of the two sets the live names point
   at, so changing a colour is one edit and the two palettes can't drift apart.
   The triggers are the reader's system preference and mdBook's theme classes
   (light/rust are its light themes, coal/navy/ayu its dark ones). */

:root {
    /* ---- paper: warm off-white, warm near-black, the logo's green -------- */

    --paper-bg: #fbfaf6;
    --paper-bg-sunken: #f3f0e9;
    --paper-surface: #ffffff;
    --paper-ink: #1a1815;
    --paper-ink-soft: #55504a;
    --paper-ink-faint: #837c73;
    --paper-rule: #e4dfd4;

    /* The logo's green, used two ways. As text it needs contrast against the
       page; as a fill it needs contrast against the label sitting on it. On
       paper one colour does both jobs. */
    --paper-accent: #0b5c38;
    --paper-accent-fill: #0b5c38;
    --paper-accent-hover: #084227;
    --paper-accent-on-fill: #fbfaf6;

    /* ---- night: dark and near-neutral, so the brand green has a ground --- */

    /* The old site's mistake, diagnosed: #0b5c38 reads fine on GitHub's
       near-black and badly on Nord's #2e3440, because #2e3440 is a *mid*
       blue-grey. A dark green needs a dark, barely-tinted ground — then it
       survives as itself instead of needing to be replaced by a mint.

       Tinted warm, on the same neutral axis as the paper (~40°). These were
       green-tinted (90-100°) while the paper was yellow-warm (48°), which is
       two different neutrals wearing one name — the themes read as unrelated
       before any coloured thing was placed on them. */
    --night-bg: #121110;
    --night-bg-sunken: #0d0c0b;
    --night-surface: #1c1b19;
    --night-ink: #ece8e0;
    --night-ink-soft: #aba59b;
    --night-ink-faint: #8e887e;
    --night-rule: #2c2a27;

    /* So the split earns its keep here. The fill stays the brand green, barely
       opened up until its edge clears 3:1 against the page — a green button is
       still a green button. Only the text form has to climb, and it climbs by
       lightness while keeping the hue and the saturation: 153°, and saturated,
       not the washed-out mint that lifting-by-desaturation produced. */
    --night-accent: #2eaf74;
    --night-accent-fill: #0d6b41;
    --night-accent-hover: #48c98c;
    --night-accent-on-fill: #f2f6f3;

    /* ---- code: its own surface per theme -------------------------------- */

    /* A third surface, distinct from both the page and the sunken wells, in
       each theme's own key. Light code on light paper, dark code at night —
       a dark slab dropped into a pale page reads as a foreign object. */
    --paper-code-bg: #f2efe4;
    --paper-code-chrome: #eae6d8;
    --paper-code-rule: #ded8c7;
    --paper-code-fg: #221f1a;

    --night-code-bg: #191817;
    --night-code-chrome: #201f1d;
    --night-code-rule: #2c2a27;
    --night-code-fg: #e4e0d6;

    /* Syntax: one hue and one saturation per role, written once. Only the
       lightness changes between themes — the same rule that fixed the accent
       green, for the same reason.

       Picking the two sets separately is what went wrong first: `ty` came out
       a 145° mint on dark and a 162° teal on light, and every light colour
       landed ~20 saturation points hotter than its dark twin, so the two sets
       were two schemes rather than one scheme in two keys. Comments were worse
       — 43% lightness in both, so they never flipped at all. */
    --syn-kw:  30 68%;    /* amber — keywords */
    --syn-ty:  152 46%;   /* the brand's own hue — types */
    --syn-fn:  45 55%;    /* gold — functions */
    --syn-str: 87 38%;    /* olive — strings */
    --syn-cmt: 40 9%;     /* the neutral axis, barely tinted — comments */
    --syn-bad: 6 68%;     /* rust — errors */

    /* Lightness pairs. Warmer hues read brighter at equal lightness, so gold
       and amber sit a step apart from the green rather than all on one number. */
    --night-c-kw: hsl(var(--syn-kw) 64%);
    --night-c-ty: hsl(var(--syn-ty) 66%);
    --night-c-fn: hsl(var(--syn-fn) 70%);
    --night-c-str: hsl(var(--syn-str) 65%);
    --night-c-cmt: hsl(var(--syn-cmt) 46%);
    --night-c-bad: hsl(var(--syn-bad) 70%);

    /* Paper's lightnesses are pulled ~3 points darker than the number that
       would be right on white, because the code block is not white. #f2efe4
       costs every colour on it about 13% of the contrast it would have had
       against #ffffff, so the same hex reads a shade weaker there. These are
       solved rather than nudged: each is the lightness whose contrast against
       #f2efe4 equals what that hue and saturation had against white.

       The mirror-image correction for night — matching pure black — is not
       applied, and that is a judgement, not an oversight. It computes to +5 to
       +9.5 points, which would push dark code to 9.7-12.6:1 and make it glare.
       Two reasons it overstates: WCAG's ratio carries a +0.05 flare constant
       that dominates at the dark end, and nobody's eye holds "on pure black" as
       the reference for a dark theme the way it holds white for a light one.
       There, the ground is the reference. */
    --paper-c-kw: hsl(var(--syn-kw) 27%);
    --paper-c-ty: hsl(var(--syn-ty) 25%);
    --paper-c-fn: hsl(var(--syn-fn) 27%);
    --paper-c-str: hsl(var(--syn-str) 27%);
    --paper-c-cmt: hsl(var(--syn-cmt) 40%);
    --paper-c-bad: hsl(var(--syn-bad) 34%);

    /* ---- type ----------------------------------------------------------- */

    --font-display: "Newsreader", Georgia, "Times New Roman", serif;
    --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

    --measure: 68ch;
    --page: 1120px;
}

/* ---- the live names, paper by default ----------------------------------- */

:root {
    --bg: var(--paper-bg);
    --bg-sunken: var(--paper-bg-sunken);
    --surface: var(--paper-surface);
    --ink: var(--paper-ink);
    --ink-soft: var(--paper-ink-soft);
    --ink-faint: var(--paper-ink-faint);
    --rule: var(--paper-rule);
    --accent: var(--paper-accent);
    --accent-fill: var(--paper-accent-fill);
    --accent-hover: var(--paper-accent-hover);
    --accent-on-fill: var(--paper-accent-on-fill);

    --code-bg: var(--paper-code-bg);
    --code-chrome: var(--paper-code-chrome);
    --code-rule: var(--paper-code-rule);
    --code-fg: var(--paper-code-fg);
    --c-cmt: var(--paper-c-cmt);
    --c-kw: var(--paper-c-kw);
    --c-ty: var(--paper-c-ty);
    --c-fn: var(--paper-c-fn);
    --c-str: var(--paper-c-str);
    --c-bad: var(--paper-c-bad);

    /* Mixed from the accent rather than picked by hand, which is how the old
       one ended up a grey-green nobody chose. Small UI states only — a search
       hit, a hovered menu row. It is not a panel fill. */
    --accent-wash: color-mix(in srgb, var(--accent) 10%, var(--bg));
}

@media (prefers-color-scheme: dark) {
    :root:not(.light):not(.rust) {
        --bg: var(--night-bg);
        --bg-sunken: var(--night-bg-sunken);
        --surface: var(--night-surface);
        --ink: var(--night-ink);
        --ink-soft: var(--night-ink-soft);
        --ink-faint: var(--night-ink-faint);
        --rule: var(--night-rule);
        --accent: var(--night-accent);
        --accent-fill: var(--night-accent-fill);
        --accent-hover: var(--night-accent-hover);
        --accent-on-fill: var(--night-accent-on-fill);

        --code-bg: var(--night-code-bg);
        --code-chrome: var(--night-code-chrome);
        --code-rule: var(--night-code-rule);
        --code-fg: var(--night-code-fg);
        --c-cmt: var(--night-c-cmt);
        --c-kw: var(--night-c-kw);
        --c-ty: var(--night-c-ty);
        --c-fn: var(--night-c-fn);
        --c-str: var(--night-c-str);
        --c-bad: var(--night-c-bad);
    }
}

/* mdBook's dark themes, chosen explicitly — these beat the system preference. */
:root.coal, :root.navy, :root.ayu {
    --bg: var(--night-bg);
    --bg-sunken: var(--night-bg-sunken);
    --surface: var(--night-surface);
    --ink: var(--night-ink);
    --ink-soft: var(--night-ink-soft);
    --ink-faint: var(--night-ink-faint);
    --rule: var(--night-rule);
    --accent: var(--night-accent);
    --accent-fill: var(--night-accent-fill);
    --accent-hover: var(--night-accent-hover);
    --accent-on-fill: var(--night-accent-on-fill);

    --code-bg: var(--night-code-bg);
    --code-chrome: var(--night-code-chrome);
    --code-rule: var(--night-code-rule);
    --code-fg: var(--night-code-fg);
    --c-cmt: var(--night-c-cmt);
    --c-kw: var(--night-c-kw);
    --c-ty: var(--night-c-ty);
    --c-fn: var(--night-c-fn);
    --c-str: var(--night-c-str);
    --c-bad: var(--night-c-bad);
}

/* And its light ones, which have to beat a dark system preference. */
:root.light, :root.rust {
    --bg: var(--paper-bg);
    --bg-sunken: var(--paper-bg-sunken);
    --surface: var(--paper-surface);
    --ink: var(--paper-ink);
    --ink-soft: var(--paper-ink-soft);
    --ink-faint: var(--paper-ink-faint);
    --rule: var(--paper-rule);
    --accent: var(--paper-accent);
    --accent-fill: var(--paper-accent-fill);
    --accent-hover: var(--paper-accent-hover);
    --accent-on-fill: var(--paper-accent-on-fill);

    --code-bg: var(--paper-code-bg);
    --code-chrome: var(--paper-code-chrome);
    --code-rule: var(--paper-code-rule);
    --code-fg: var(--paper-code-fg);
    --c-cmt: var(--paper-c-cmt);
    --c-kw: var(--paper-c-kw);
    --c-ty: var(--paper-c-ty);
    --c-fn: var(--paper-c-fn);
    --c-str: var(--paper-c-str);
    --c-bad: var(--paper-c-bad);
}
