/* ⛔⛔ §3.597.1 — THIS FILE NO LONGER TRIGGERS ON `html.light`.
   That class is a PREFERENCE, not a description of the pixels: the admin
   dashboard renders `html.light` while `admin-glass.css` paints it navy, and
   keying off it inverted an already-dark page (Mo's screenshot, 2026-09-09).
   `force-dark.js` now MEASURES the page's real background in CIELAB and sets
   `data-force-dark` only when L* > 50 — which is exactly what Chromium does:
   auto-dark is skipped on pages that are already dark. The decision is half the
   mechanism, and it is the half that was missing. */

/* =============================================================================
   force-dark.css — §3.597
   Edge's "Auto Dark Mode for Web Contents" (#enable-force-dark), baked in.

   Mo, 2026-09-09: *"use the same mechanism [Edge] uses ... change the new dark
   (originally was the light) to the exact reverse of bgs and cards and text
   (spare the buttons and svgs and lottie animations)."*

   ─────────────────────────────────────────────────────────────────────────────
   WHY A PAINT FILTER AND NOT A REWRITTEN PALETTE — the measurement that decided it

     html[data-force-dark] rules that exist today ...  2 (frontend) + 13 (backend)
     html.dark  rules that exist today ...  28 (glass-ui) + 12 (admin-glass)
     the base vendor CSS ..................  50,749 lines, 1,436 hard-coded hex

   ⭐ **THE LIGHT THEME HAS NO TOKEN LAYER.** It is not a palette that can be
   re-pointed; it IS the vendor's raw stylesheet, with the navy/gold system
   layered over it only under `html.dark`. There is nothing to swap. That is the
   same wall Chromium hit, and the reason force-dark is a COMPOSITOR filter
   rather than a stylesheet rewrite — you cannot re-point colours you do not own.

   ─────────────────────────────────────────────────────────────────────────────
   WHAT EDGE ACTUALLY DOES (read from Blink, 2026-09-09, not from memory)

     dark_mode_color_filter.cc
        DarkModeColorFilter::Create() -> LABColorFilter        // the default
        AdjustColorByLightness():  lab.x = min(110.0f - lab.x, 100.0f);
     dark_mode_lab_color_space.h
        L = 116*fy - 16 · a = 500*(fx-fy) · b = 200*(fy-fz), sigma 6/29, D65

   ⛔ It is **110 − L, not 100 − L**. White (L=100) lands on L=10 — a soft
      near-black, never pure black — while black (L=0) clamps to 100, pure white.
      The scale is deliberately asymmetric; 100−L gives a harsher, flatter page.
   ⛔ **Only L moves. a and b are untouched**, which is why hue and chroma
      survive and a gold heading stays gold.

   ⚠ CSS cannot do LAB. `invert(1) hue-rotate(180deg)` is the closest primitive:
   invert flips RGB (which also rotates hue 180°), and the hue-rotate puts the
   hue back — net effect is a lightness flip that preserves hue, which is Edge's
   intent. Measured against the real filter (`scripts/force-dark.mjs`) it is a
   good approximation, NOT a reproduction: the true LAB curve is perceptually
   even, this one is not.

   ─────────────────────────────────────────────────────────────────────────────
   ⚠⚠ THE ONE REAL SIDE EFFECT, STATED PLAINLY

   `filter` on an element makes it the CONTAINING BLOCK for every
   `position: fixed` descendant. Sticky headers, modals, drawers and the glass
   sheets stop being viewport-anchored and anchor to <body> instead. This
   platform uses fixed chrome and `backdrop-filter` glass in several places, so
   THIS NEEDS EYES ON IT before it is trusted — it cannot be proven by reading.

   ⛔ KILL SWITCH: delete the `<link>` to this file, or change `html[data-force-dark]`
   below to `html.__disabled`. Nothing else depends on it, and `html.dark`
   (the navy/gold system) is untouched by this file entirely.
   ============================================================================= */

/* The ground behind the filtered body. Set on <html>, which is NOT filtered, so
   over-scroll and the area behind short pages match instead of flashing white.
   #1b1b1b is what Blink's own filter returns for #ffffff — measured, not picked. */
html[data-force-dark] {
    background-color: #1b1b1b;
}

html[data-force-dark] body {
    /* Edge's lightness inversion, in the only primitive CSS gives us. */
    filter: invert(1) hue-rotate(180deg);
    /* Filtering a transparent body would show the html ground THROUGH the
       filter and double-invert it. An explicit white here inverts to the same
       #1b1b1b as the line above. */
    background-color: #ffffff;
}

/* ─────────────────────────────────────────────────────────────────────────────
   SPARED, exactly as Mo asked: "spare the buttons and svgs and lottie
   animations". A second, identical filter cancels the first — invert twice and
   hue-rotate 360° is the identity — so these paint with their real colours.
   ⚠ This is why the rule below must MATCH the body filter exactly; any drift
   between the two leaves these elements subtly wrong rather than untouched. */
html[data-force-dark] img,
html[data-force-dark] svg,
html[data-force-dark] video,
html[data-force-dark] canvas,
html[data-force-dark] iframe,
html[data-force-dark] lottie-player,
html[data-force-dark] dotlottie-player,
html[data-force-dark] [class*="lottie"],
html[data-force-dark] .mgx-lottie,
/* buttons and anything the vendor themes as one */
html[data-force-dark] button,
html[data-force-dark] .btn,
html[data-force-dark] [class*="btn-"],
html[data-force-dark] input[type="button"],
html[data-force-dark] input[type="submit"],
html[data-force-dark] input[type="reset"],
/* the brand marks — a logo must never be re-coloured */
html[data-force-dark] .logo img,
html[data-force-dark] [class*="logo"] img,
html[data-force-dark] .avatar img {
    filter: invert(1) hue-rotate(180deg);
}

/* A button that CONTAINS an icon would otherwise be un-inverted twice (once by
   the button rule, once by the svg/img rule) and come out inverted again.
   Cancel the inner one — the button already restored it. */
html[data-force-dark] button img,
html[data-force-dark] button svg,
html[data-force-dark] .btn img,
html[data-force-dark] .btn svg,
html[data-force-dark] [class*="btn-"] img,
html[data-force-dark] [class*="btn-"] svg {
    filter: none;
}

/* Backgrounds painted as IMAGES are photographs, not surfaces. Chromium's own
   DarkModeImageClassifier leaves photographs alone for the same reason: an
   inverted photo reads as a negative, not as a dark theme. */
html[data-force-dark] [style*="background-image"],
html[data-force-dark] [class*="hero"][style*="url("] {
    filter: invert(1) hue-rotate(180deg);
}

/* Form fields keep their own inverted surface but must not fight the browser's
   native widget colours, which are already dark-aware. */
html[data-force-dark] input,
html[data-force-dark] textarea,
html[data-force-dark] select {
    color-scheme: light; /* inverted -> reads as dark to the user */
}
