/* ============================================================================
   Dark theme — token overrides only

   Kept out of qf-tokens.css so that file stays refreshable from the Qatar
   Foundation Design System, exactly like pue-chrome-overrides.css sits beside
   qf-chrome.css. Nothing here styles a component; it redefines what the tokens
   mean and lets every existing rule follow.

   WHY THE INK RAMP FLIPS

   74 rules across these stylesheets say `color: var(--qf-ink)` rather than
   `var(--text-body)`. Overriding only the semantic aliases would have left all
   74 as near-black text on a near-black page. --qf-ink is the *foreground* ink
   of the digital ramp, so inverting the ramp is both the smaller change and the
   more honest one: ink is what you write with, and on dark paper it is pale.

   The brand palette is NOT touched. Sidra green stays Sidra green — it is a
   Pantone reference, not a colour we get to reinterpret. Where it is used as
   text it is swapped for a lighter tint through --text-link and --text-brand,
   which is a legibility decision about a specific use rather than a claim about
   the colour.

   WHAT DELIBERATELY STAYS WHITE

   The plates behind a QR code and behind artwork (`background: #fff` in
   pue-tools.css and pue-edunation.css). A QR code needs its quiet zone on white
   to scan at all, and a designer judging artwork needs it on the paper it will
   be printed on. Both are correct in either theme and neither is a bug.

   THREE STATES, NOT TWO

   An explicit choice stamps data-theme on <html>. With no choice stamped, the
   media query follows the operating system. The :not([data-theme="light"])
   guard is what lets somebody on a dark OS force light and be obeyed.
   ============================================================================ */

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        /* Neutral ink ramp, inverted. */
        --qf-ink: #ECEDEC;
        --qf-ink-70: #B4B7B6;
        --qf-ink-50: #8C908F;
        --qf-ink-30: #616665;
        --qf-line: #2E3331;
        --qf-surface-tint: #1A1E1D;
        --qf-surface-tint-2: #151918;

        /* Semantic aliases that point at brand white, which must not follow. */
        --surface-page: #0F1211;
        --surface-card: #161A19;

        /* Sidra green is unreadable as text on a dark page; its 40% tint is not. */
        --text-brand: var(--qf-sidra-green-40);
        --text-link: var(--qf-sidra-green-40);
        --text-link-hover: var(--qf-orange-80);

        --border-subtle: #333937;
        --border-strong: var(--qf-ink-50);

        color-scheme: dark;
    }
}

:root[data-theme="dark"] {
    --qf-ink: #ECEDEC;
    --qf-ink-70: #B4B7B6;
    --qf-ink-50: #8C908F;
    --qf-ink-30: #616665;
    --qf-line: #2E3331;
    --qf-surface-tint: #1A1E1D;
    --qf-surface-tint-2: #151918;

    --surface-page: #0F1211;
    --surface-card: #161A19;

    --text-brand: var(--qf-sidra-green-40);
    --text-link: var(--qf-sidra-green-40);
    --text-link-hover: var(--qf-orange-80);

    --border-subtle: #333937;
    --border-strong: var(--qf-ink-50);

    color-scheme: dark;
}

/* ---- The one thing tokens cannot reach ----
   The page background is painted by the body, and several pages set their own
   surface. Stated explicitly so a page that never mentions a background does
   not inherit the browser's white. */
body.qf-page {
    background: var(--surface-page);
    color: var(--text-body);
}

/* ---- The switch ----

   A track with a knob that slides, rather than an icon that swaps. The swap
   version was honest but silent: nothing moved, so nothing confirmed the press,
   and on a page that repaints in the same instant the eye has nothing to follow.
   Here the knob travels, the sun leaves as the moon arrives, and the track warms
   or cools underneath — three cues on one gesture, all of them saying the same
   thing.

   Sized in px rather than tokens on purpose: this is a physical control whose
   proportions are the design, and a spacing scale change should not resize the
   knob into or out of its track. The TIMING is tokens, though — --ease-out and
   --duration-base, the design system's own decelerate curve.

   Deliberately not a spring. The first version overshot the knob and settled
   back, which is the house style of a different house: this design system is
   square-first and uses hairlines instead of shadow, and a knob that boings is
   at odds with everything around it. A thing that slides and stops is the
   version that still looks right on the hundredth press.

   Square-first, per the house style, softened only enough to read as a switch. */
.qf-theme {
    position: relative;
    display: inline-flex;
    align-items: center;
    width: 46px;
    height: 24px;
    padding: 0;
    appearance: none;
    background: var(--surface-tint);
    border: 1px solid var(--border-default);
    border-radius: 999px;
    cursor: pointer;
    transition:
        background-color var(--duration-base) var(--ease-out),
        border-color var(--duration-base) var(--ease-out);
}
.qf-theme:hover { border-color: var(--border-strong); }
.qf-theme:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
}

/* The knob. transform rather than `left`, so it animates on the compositor and
   does not force layout on every frame. */
.qf-theme::before {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 18px;
    height: 18px;
    border-radius: 999px;
    background: var(--surface-page);
    border: 1px solid var(--border-default);
    transition:
        transform var(--duration-base) var(--ease-out),
        background-color var(--duration-base) var(--ease-out);
}

/* Both icons live in the track and cross-travel with the knob: the one leaving
   shrinks and rotates away, the one arriving unrolls into place. */
.qf-theme > span {
    position: absolute;
    top: 0;
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    pointer-events: none;
    transition:
        opacity var(--duration-fast) var(--ease-out),
        transform var(--duration-base) var(--ease-out);
}
.qf-theme .qf-theme-light { left: 22px; color: var(--text-subtle); }
.qf-theme .qf-theme-dark  { left: 2px;  color: var(--qf-yellow); }

/* The icon shows the DESTINATION, not the current state — it pairs with the
   "Switch to dark mode" label rather than contradicting it. So the visible icon
   always sits opposite the knob: knob left and a moon on the right in light
   mode, knob right and a sun on the left in dark. */
.qf-theme .qf-theme-dark  { opacity: 0; transform: rotate(-70deg) scale(.6); }
.qf-theme .qf-theme-light { opacity: 1; transform: none; }

/* The press itself, so a click that changes nothing still feels like a click. */
.qf-theme:active::before { transform: scale(.92); }

/* ---- Dark: the knob travels right, the track cools, the moon arrives ---- */
:root[data-theme="dark"] .qf-theme,
:root[data-theme="dark"] .qf-theme:hover {
    background: var(--qf-sidra-green-20);
    border-color: var(--qf-sidra-green-40);
}
:root[data-theme="dark"] .qf-theme::before { transform: translateX(22px); }
:root[data-theme="dark"] .qf-theme:active::before { transform: translateX(22px) scale(.92); }
:root[data-theme="dark"] .qf-theme .qf-theme-dark  { opacity: 1; transform: none; }
:root[data-theme="dark"] .qf-theme .qf-theme-light { opacity: 0; transform: rotate(70deg) scale(.6); }

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .qf-theme,
    :root:not([data-theme="light"]) .qf-theme:hover {
        background: var(--qf-sidra-green-20);
        border-color: var(--qf-sidra-green-40);
    }
    :root:not([data-theme="light"]) .qf-theme::before { transform: translateX(22px); }
    :root:not([data-theme="light"]) .qf-theme:active::before { transform: translateX(22px) scale(.92); }
    :root:not([data-theme="light"]) .qf-theme .qf-theme-dark  { opacity: 1; transform: none; }
    :root:not([data-theme="light"]) .qf-theme .qf-theme-light { opacity: 0; transform: rotate(70deg) scale(.6); }
}

/* Somebody who has asked for less motion gets the state change and none of the
   travel. The control still says which theme is on; it just stops performing. */
@media (prefers-reduced-motion: reduce) {
    .qf-theme,
    .qf-theme::before,
    .qf-theme > span { transition: none; }
    .qf-theme > span { transform: none; }
}

/* ============================================================================
   Ink plates

   The token flip is not enough on its own, and this is where it stops.

   Ten rules across these stylesheets say `background: var(--qf-ink); color:
   var(--qf-white)` — an ink plate with white text: the primary button, a
   ticked checkbox, the arrow disc on a card, a selected scale segment. The
   background follows the ramp and flips pale. The white does not, because
   --qf-white is a brand colour and has to stay white for the plates that really
   are white. Left alone, the primary button is white text on a white button.

   So the pairs are named here. `--surface-page` rather than a literal: the text
   on an inverted plate is the colour of the paper it sits on, whatever that is.

   The list is exhaustive as of this commit. A new rule pairing --qf-ink with
   --qf-white needs a line here; grepping for that pair is how to find them.
   ============================================================================ */

:root[data-theme="dark"] .qf-btn--primary,
:root[data-theme="dark"] .qf-page a.qf-btn--primary,
:root[data-theme="dark"] .qf-btn--secondary:hover,
:root[data-theme="dark"] .qf-page a.qf-btn--secondary:hover,
:root[data-theme="dark"] .qf-iconbtn--solid,
:root[data-theme="dark"] .bk-btn--solid,
:root[data-theme="dark"] .sol-arrow .disc,
:root[data-theme="dark"] .qf-scale-seg:has(:checked),
:root[data-theme="dark"] .qf-scale-seg:has(:checked) {
    color: var(--surface-page);
}

/* Cool Gray 11 is a dark hover, which on a pale button leaves dark text on a
   dark plate. The ramp's own mid tone is the hover that works here. */
:root[data-theme="dark"] .qf-btn--primary:hover {
    background: var(--qf-ink-70);
    border-color: var(--qf-ink-70);
    color: var(--surface-page);
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .qf-btn--primary,
    :root:not([data-theme="light"]) .qf-page a.qf-btn--primary,
    :root:not([data-theme="light"]) .qf-btn--secondary:hover,
    :root:not([data-theme="light"]) .qf-page a.qf-btn--secondary:hover,
    :root:not([data-theme="light"]) .qf-iconbtn--solid,
    :root:not([data-theme="light"]) .bk-btn--solid,
    :root:not([data-theme="light"]) .sol-arrow .disc,
    :root:not([data-theme="light"]) .qf-scale-seg:has(:checked) {
        color: var(--surface-page);
    }

    :root:not([data-theme="light"]) .qf-btn--primary:hover {
        background: var(--qf-ink-70);
        border-color: var(--qf-ink-70);
        color: var(--surface-page);
    }
}

/* ---- The lockup ----
   The green and black artwork both disappear against a dark header, so the
   white one is used instead. Both images ship and CSS picks, rather than the
   server choosing a file: with no explicit choice stamped the server does not
   know which theme the visitor is in, and only the media query does. */
.qf-header-logo,
.pue-footer-home { position: relative; display: inline-flex; }
.qf-header-logo .qf-lockup-dark { display: none; }

:root[data-theme="dark"] .qf-header-logo .qf-lockup-dark { display: block; }
:root[data-theme="dark"] .qf-header-logo .qf-lockup-light { display: none; }

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .qf-header-logo .qf-lockup-dark { display: block; }
    :root:not([data-theme="light"]) .qf-header-logo .qf-lockup-light { display: none; }
}

/* ============================================================================
   Light plates that do not flip

   The mirror image of the ink plates above, and the same root cause. These pair
   a background from the BRAND palette — which is fixed, by design — with text
   from the ramp, which is not. Cool Gray 3 stays a pale grey in dark mode while
   its text turns pale with the ramp, so five badges become invisible.

   Fixed by inverting the chip rather than the text: a dark chip with light text
   is what a badge looks like on a dark page, where pale-grey-with-dark-text
   would be a light patch stapled to the design.

   The highlight marks and the selection colour go the other way. Mint and
   yellow are bright and stay bright, so those keep the plate and darken the
   text, which is also what they do on paper.
   ============================================================================ */

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .sol-badge,
    :root:not([data-theme="light"]) .sl-badge,
    :root:not([data-theme="light"]) .svy-badge,
    :root:not([data-theme="light"]) .edu-art-tag {
        background: var(--qf-line);
        color: var(--text-body);
    }

    :root:not([data-theme="light"]) .qf-file {
        background: var(--surface-card);
        color: var(--text-body);
    }

    :root:not([data-theme="light"]) .qf-page ::selection,
    :root:not([data-theme="light"]) .qf-mark-mint,
    :root:not([data-theme="light"]) .qf-mark-yellow,
    :root:not([data-theme="light"]) .qf-mark-orange {
        color: #0F1211;
    }
}

:root[data-theme="dark"] .sol-badge,
:root[data-theme="dark"] .sl-badge,
:root[data-theme="dark"] .svy-badge,
:root[data-theme="dark"] .edu-art-tag {
    background: var(--qf-line);
    color: var(--text-body);
}

:root[data-theme="dark"] .qf-file {
    background: var(--surface-card);
    color: var(--text-body);
}

:root[data-theme="dark"] .qf-page ::selection,
:root[data-theme="dark"] .qf-mark-mint,
:root[data-theme="dark"] .qf-mark-yellow,
:root[data-theme="dark"] .qf-mark-orange {
    color: #0F1211;
}

/* ---- The last few, found by grepping the two pairings above ---- */

:root[data-theme="dark"] .svy-arrow .disc { color: var(--surface-page); }

/* The tick is a white SVG baked into a data URI, so on a pale plate it
   disappears. Same mark, dark, rather than a different control. */
:root[data-theme="dark"] .qf-checkbox:checked {
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%230F1211' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 7'/%3E%3C/svg%3E");
}

:root[data-theme="dark"] .qf-file::file-selector-button:hover { color: var(--surface-page); }

/* A photo letterbox, not a surface: it stays dark so an image with an odd
   aspect ratio is framed rather than glowing. */
:root[data-theme="dark"] .edu-crop-viewport { background: #0F1211; }

:root[data-theme="dark"] .bk-names li:has(a):hover { background: var(--qf-line); }

@media (prefers-color-scheme: dark) {

    /* ---- The last few, found by grepping the two pairings above ---- */

:root:not([data-theme="light"]) .svy-arrow .disc { color: var(--surface-page); }

    /* The tick is a white SVG baked into a data URI, so on a pale plate it
   disappears. Same mark, dark, rather than a different control. */
:root:not([data-theme="light"]) .qf-checkbox:checked {
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%230F1211' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 7'/%3E%3C/svg%3E");
}

:root:not([data-theme="light"]) .qf-file::file-selector-button:hover { color: var(--surface-page); }

    /* A photo letterbox, not a surface: it stays dark so an image with an odd
   aspect ratio is framed rather than glowing. */
:root:not([data-theme="light"]) .edu-crop-viewport { background: #0F1211; }

:root:not([data-theme="light"]) .bk-names li:has(a):hover { background: var(--qf-line); }
}

/* ============================================================================
   Card icons

   The /solutions icon set is flat Sidra green artwork (#034638) loaded through
   <img>, so no CSS colour reaches inside it and there is no currentColor to
   inherit. On a dark page that is dark green line art on near-black: present,
   and effectively invisible.

   brightness(0) turns the artwork black whatever colour it started as; invert(1)
   turns that white. Two filters rather than a hand-picked value, because the set
   is not perfectly uniform — some files carry their fill in a <style> block and
   some as an attribute — and this does not care which.

   Not `mask-image` with a background colour, which is the technically nicer
   answer: it needs the <img> to become an element with no src, and that would
   drop the onerror fallback in solutions.blade.php that swaps in the tool's
   initial when an icon is missing. A missing icon is a real state here.

   Slightly under full white, so the icons sit a shade below the headings rather
   than competing with them.
   ============================================================================ */

:root[data-theme="dark"] .sol-card-media img {
    filter: brightness(0) invert(1);
    opacity: .92;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .sol-card-media img {
        filter: brightness(0) invert(1);
        opacity: .92;
    }
}

/* The select caret is drawn by us, as a data URI with the stroke baked in at
   #111111. Every other part of the control follows the tokens; this one cannot,
   so the same caret ships in the ramp's ink colour. Background-image only: the
   position and size rules still come from qf-forms.css. */
:root[data-theme="dark"] .qf-select {
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23ECEDEC' stroke-width='1.25' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}

@media (prefers-color-scheme: dark) {

/* The select caret is drawn by us, as a data URI with the stroke baked in at
   #111111. Every other part of the control follows the tokens; this one cannot,
   so the same caret ships in the ramp's ink colour. Background-image only: the
   position and size rules still come from qf-forms.css. */
    :root:not([data-theme="light"]) .qf-select {
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23ECEDEC' stroke-width='1.25' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
}

/* ============================================================================
   Brand green as an indicator

   Sidra green is a Pantone reference and never flips, which is right where it
   is a FILL — the footer, a brand button, a swatch. It is wrong where it marks
   a state: a #034638 border on a near-black card is invisible, so "this one is
   selected" stops being said at all. That is a functional loss rather than a
   cosmetic one.

   Text already went through --text-link, which resolves to the 40% tint here.
   These are the same decision for the borders, the accents and the one flash
   rule, named individually because each reaches past the semantic layer for the
   raw token.
   ============================================================================ */

:root[data-theme="dark"] .tool-size:has(.qf-radio:checked) {
    border-color: var(--qf-sidra-green-40);
    box-shadow: inset 0 0 0 1px var(--qf-sidra-green-40);
}
:root[data-theme="dark"] .tool-size:has(.qf-radio:focus-visible) { border-color: var(--qf-sidra-green-40); }
:root[data-theme="dark"] .edu-art-cell.is-cover img { border-color: var(--qf-sidra-green-40); }
:root[data-theme="dark"] .qf-flash--success { border-inline-start-color: var(--qf-sidra-green-40); }
:root[data-theme="dark"] .qf-flash--success .qf-flash-icon { color: var(--qf-sidra-green-40); }

/* accent-color paints the browser's own checkbox and range controls, which have
   no other hook: dark green on a dark field reads as an unchecked box. */
:root[data-theme="dark"] .qf-check input,
:root[data-theme="dark"] .edu-crop-zoom input[type="range"],
:root[data-theme="dark"] input[type="range"] { accent-color: var(--qf-sidra-green-40); }

@media (prefers-color-scheme: dark) {

/* ============================================================================
   Brand green as an indicator

   Sidra green is a Pantone reference and never flips, which is right where it
   is a FILL — the footer, a brand button, a swatch. It is wrong where it marks
   a state: a #034638 border on a near-black card is invisible, so "this one is
   selected" stops being said at all. That is a functional loss rather than a
   cosmetic one.

   Text already went through --text-link, which resolves to the 40% tint here.
   These are the same decision for the borders, the accents and the one flash
   rule, named individually because each reaches past the semantic layer for the
   raw token.
   ============================================================================ */

    :root:not([data-theme="light"]) .tool-size:has(.qf-radio:checked) {
    border-color: var(--qf-sidra-green-40);
    box-shadow: inset 0 0 0 1px var(--qf-sidra-green-40);
}
    :root:not([data-theme="light"]) .tool-size:has(.qf-radio:focus-visible) { border-color: var(--qf-sidra-green-40); }
    :root:not([data-theme="light"]) .edu-art-cell.is-cover img { border-color: var(--qf-sidra-green-40); }
    :root:not([data-theme="light"]) .qf-flash--success { border-inline-start-color: var(--qf-sidra-green-40); }
    :root:not([data-theme="light"]) .qf-flash--success .qf-flash-icon { color: var(--qf-sidra-green-40); }

/* accent-color paints the browser's own checkbox and range controls, which have
   no other hook: dark green on a dark field reads as an unchecked box. */
    :root:not([data-theme="light"]) .qf-check input,
    :root:not([data-theme="light"]) .edu-crop-zoom input[type="range"],
    :root:not([data-theme="light"]) input[type="range"] { accent-color: var(--qf-sidra-green-40); }
}
