/**
 * ERP MASTER THEME — single source of truth for colour
 * ============================================================
 * Every colour the ERP is allowed to care about lives here, as an
 * `--erp-*` custom property. Components reference the token, never a
 * literal hex, so one change here (or one change in Settings → Appearance)
 * moves the whole product.
 *
 * WHY THE `--erp-` PREFIX
 * ~20 stylesheets already declare their own `:root` blocks using generic
 * names (--primary, --primary-color, --primary-blue, --accent) and they do
 * NOT all mean the same thing — in other-ledger-details-v2.css `--primary`
 * is the navy primary, elsewhere it is a bright blue. Claiming those names
 * globally would silently repaint half the app. The prefix keeps this file
 * additive: nothing breaks until a component is deliberately migrated.
 *
 * RUNTIME OVERRIDES
 * config/theme.php emits an inline block at higher specificity
 * (`:root:root:root`) so the admin's saved colours beat this file no matter
 * what order stylesheets happen to load in. Do not raise the specificity
 * here to match — this file is the floor, not the ceiling.
 *
 * DARK MODE
 * `[data-theme="dark"]` on <html> re-points the surface/text tokens only.
 * Primary and semantic hues stay put so a red error stays red.
 */

:root {
    /* ---- Primary ------------------------------------------------ */
    /* The software's identity. Everything navy traces back to these. */
    --erp-primary-start: #314677;
    --erp-primary-mid:   #0a1633;
    --erp-primary-end:   #04102d;
    --erp-on-primary:    #ffffff;

    /* The primary used as content, not as a surface: links, icons, an active
       pill. The surface stops above are tuned to sit behind white text and get
       deeper still in dark mode, so they cannot double as foreground colours.
       These are the static floor; config/theme.php recomputes them per theme. */
    --erp-primary-text:  #314677;
    --erp-primary-soft:  #eaedf1;
    --erp-primary-line:  #a2acc2;

    /* Prebuilt gradients — the three angles already used across the app.
       Components should use these rather than re-declaring a gradient, so
       a primary-colour change reaches every surface. */
    --erp-primary-gradient:        linear-gradient(180deg, var(--erp-primary-start) 0%, var(--erp-primary-mid) 55%, var(--erp-primary-end) 100%);
    --erp-primary-gradient-soft:   linear-gradient(180deg, var(--erp-primary-start) 0%, var(--erp-primary-end) 100%);
    --erp-primary-gradient-tilt:   linear-gradient(178deg, var(--erp-primary-start) 0%, var(--erp-primary-end) 100%);
    --erp-primary-gradient-across: linear-gradient(90deg,  var(--erp-primary-start) 0%, var(--erp-primary-end) 100%);
    --erp-primary-gradient-diag:   linear-gradient(135deg, var(--erp-primary-start) 0%, var(--erp-primary-end) 100%);

    /* ---- Accent / semantic hues --------------------------------- */
    --erp-accent:         #3b82f6;
    --erp-accent-dark:    #2563eb;
    --erp-accent-soft:    #eff6ff;
    --erp-accent-line: #a7c7fb;

    --erp-success:        #10b981;
    --erp-success-dark:   #059669;
    --erp-success-soft:   #ecfdf5;
    --erp-success-line: #93e0c6;

    --erp-warning:        #f59e0b;
    --erp-warning-dark:   #d97706;
    --erp-warning-soft:   #fffbeb;
    --erp-warning-line: #fad391;

    --erp-danger:         #ef4444;
    --erp-danger-dark:    #dc2626;
    --erp-danger-soft:    #fef2f2;
    --erp-danger-line: #f8abab;

    --erp-info:           #0ea5e9;
    --erp-info-dark:      #0284c7;
    --erp-info-soft:      #f0f9ff;
    --erp-info-line: #93d6f5;

    --erp-violet:         #8b5cf6;
    --erp-violet-dark:    #7c3aed;
    --erp-violet-soft:    #ede9fe;
    --erp-violet-line: #cbb6fb;

    /* ---- Extended hues ------------------------------------------ */
    /* Three more families, for categories the six above cannot tell apart: a
       legend with red, orange AND amber rows, a teal chip beside a green one.
       They are not in Settings -> Appearance, so nothing recomputes them at
       runtime; the shades here are derived the way config/theme.php derives
       the others (-dark 18% toward black, -soft 90% and -line 55% toward
       white), so all nine families sit at the same depths. */
    --erp-pink:           #ec4899;
    --erp-pink-dark:      #c23b7d;
    --erp-pink-soft:      #fdedf5;
    --erp-pink-line:      #f6add1;

    --erp-teal:           #14b8a6;
    --erp-teal-dark:      #109788;
    --erp-teal-soft:      #e8f8f6;
    --erp-teal-line:      #95dfd7;

    --erp-orange:         #f97316;
    --erp-orange-dark:    #cc5e12;
    --erp-orange-soft:    #fef1e8;
    --erp-orange-line:    #fcc096;

    /* ---- Hue as content ----------------------------------------- */
    /* Two more shades per family, for a hue used AS text, an icon or a figure
       rather than as a fill — the counterparts of --erp-primary-text.

       -on-dark  the hue lifted halfway to white: coloured text on a fill that
                 stays dark in both themes (a navy summary card, the sidebar).
       -text     coloured text on the card. In light mode that is the -dark
                 shade; on a dark card -dark is too dim to read comfortably,
                 so the dark block points it at -on-dark instead.

       Use these and a component needs no dark rule of its own. They are
       written with color-mix so an admin's change to the hue carries through,
       which also means canvas cannot be trusted to parse them: for Chart.js
       hand ErpTheme.color() the base or -dark token. */
    --erp-accent-on-dark:   color-mix(in srgb, var(--erp-accent) 50%, var(--erp-white));
    --erp-success-on-dark:  color-mix(in srgb, var(--erp-success) 50%, var(--erp-white));
    --erp-warning-on-dark:  color-mix(in srgb, var(--erp-warning) 50%, var(--erp-white));
    --erp-danger-on-dark:   color-mix(in srgb, var(--erp-danger) 50%, var(--erp-white));
    --erp-info-on-dark:     color-mix(in srgb, var(--erp-info) 50%, var(--erp-white));
    --erp-violet-on-dark:   color-mix(in srgb, var(--erp-violet) 50%, var(--erp-white));
    --erp-pink-on-dark:     color-mix(in srgb, var(--erp-pink) 50%, var(--erp-white));
    --erp-teal-on-dark:     color-mix(in srgb, var(--erp-teal) 50%, var(--erp-white));
    --erp-orange-on-dark:   color-mix(in srgb, var(--erp-orange) 50%, var(--erp-white));

    --erp-accent-text:      var(--erp-accent-dark);
    --erp-success-text:     var(--erp-success-dark);
    --erp-warning-text:     var(--erp-warning-dark);
    --erp-danger-text:      var(--erp-danger-dark);
    --erp-info-text:        var(--erp-info-dark);
    --erp-violet-text:      var(--erp-violet-dark);
    --erp-pink-text:        var(--erp-pink-dark);
    --erp-teal-text:        var(--erp-teal-dark);
    --erp-orange-text:      var(--erp-orange-dark);

    /* ---- Third-party marks -------------------------------------- */
    /* Somebody else's identity colour. Fixed on purpose: it must look like
       their mark whatever the admin picks for ours, in both themes. */
    --erp-whatsapp:       #25d366;
    --erp-whatsapp-dark:  #128c7e;

    /* ---- Neutral ramp ------------------------------------------- */
    /* The greys every surface, line and label is built from, lightest to
       darkest. Values are the slate family: the ERP uses slate ~1,970 times
       against gray ~1,690, and slate sits better beside the navy primary.
       Files still on the gray family shift by 1-2% per channel when they are
       migrated — imperceptible, and the point of having ONE ramp is that dark
       mode can invert it in a single place. */
    --erp-n-50:  #f8fafc;
    --erp-n-100: #f1f5f9;
    --erp-n-200: #e2e8f0;
    --erp-n-300: #cbd5e1;
    --erp-n-400: #94a3b8;
    --erp-n-500: #64748b;
    --erp-n-600: #475569;
    --erp-n-700: #334155;
    --erp-n-800: #1e293b;
    --erp-n-900: #0f172a;

    /* ---- Surfaces ----------------------------------------------- */
    /* The page behind everything.
       --erp-surface-page-seed is what Settings -> Appearance writes. It is a
       LIGHT-mode choice, so it is consumed here and deliberately ignored by
       the dark rule below; that keeps the admin's page colour out of a fight
       with dark mode. */
    --erp-surface-page:    var(--erp-surface-page-seed, var(--erp-n-50));
    --erp-surface-card:    #ffffff;  /* cards, modals, table bodies */
    --erp-surface-raised:  #ffffff;  /* anything floating above the page: modals, drawers, popovers */
    --erp-surface-sunken:  var(--erp-n-100);  /* wells, table headers, chips */
    --erp-surface-hover:   var(--erp-n-50);
    --erp-surface-rail:    var(--erp-primary-gradient);  /* sidebar rail */
    --erp-surface-panel:   #1c2b4d;  /* sidebar sliding panel */
    --erp-surface-panel-deep: #16233f;
    --erp-surface-panel-hover: #2d4785;

    /* ---- Lines --------------------------------------------------- */
    --erp-border:        var(--erp-n-200);
    --erp-border-strong: var(--erp-n-300);
    --erp-border-faint:  #f0f0f0;
    --erp-hairline:      rgba(255, 255, 255, 0.09);  /* on dark surfaces */

    /* ---- Text ---------------------------------------------------- */
    --erp-text:           var(--erp-n-800);
    --erp-text-secondary: var(--erp-n-500);
    --erp-text-muted:     var(--erp-n-400);
    --erp-text-inverse:   #ffffff;
    --erp-text-on-dark:       rgba(255, 255, 255, 0.88);
    --erp-text-on-dark-dim:   rgba(255, 255, 255, 0.55);
    /* The other way round: dark text on a fill that stays bright in both
       themes (a yellow badge, a white paper preview). --erp-text would turn
       pale there in dark mode and disappear. */
    --erp-text-on-light:      #0f172a;

    /* ---- Fixed --------------------------------------------------- */
    /* White and black that do NOT move with the theme: the knob on a coloured
       switch, a photo backdrop, a sheet of paper, the base of a translucent
       veil (color-mix(in srgb, var(--erp-black) 40%, transparent)).
       A surface or a run of text almost never wants these — use
       --erp-surface-* / --erp-text-*, which invert. */
    --erp-white:          #ffffff;
    --erp-black:          #000000;


    /* ---- Heatmap intensity scale --------------------------------- */
    /* A sequential 0-4 ramp (the activity heatmap's contribution grid).
       Kept as its own scale rather than reusing the success family: a
       sequential scale has to stay evenly spaced to be readable, which the
       base/-dark/-soft shades are not. Level 0 is "no activity" and rides the
       neutral ramp, so it darkens with the page. */
    --erp-heat-0: var(--erp-n-200);
    --erp-heat-1: #9be9a8;
    --erp-heat-2: #40c463;
    --erp-heat-3: #30a14e;
    --erp-heat-4: #216e39;

    /* ---- Chart series -------------------------------------------- */
    /* The order colours are dealt in when a chart's categories carry no
       meaning of their own (users, products, months). Neighbours are as far
       apart in hue as the families allow, and the second lap takes the -dark
       shades. A category that DOES mean something keeps its semantic token:
       a "Delivered" bar is --erp-success wherever it falls in the list.
       From JS: ErpTheme.series() returns these as real colour strings. */
    --erp-chart-1:  var(--erp-accent);
    --erp-chart-2:  var(--erp-warning);
    --erp-chart-3:  var(--erp-success);
    --erp-chart-4:  var(--erp-danger);
    --erp-chart-5:  var(--erp-violet);
    --erp-chart-6:  var(--erp-teal);
    --erp-chart-7:  var(--erp-orange);
    --erp-chart-8:  var(--erp-info);
    --erp-chart-9:  var(--erp-pink);
    --erp-chart-10: var(--erp-n-500);
    --erp-chart-11: var(--erp-accent-dark);
    --erp-chart-12: var(--erp-warning-dark);
    --erp-chart-13: var(--erp-success-dark);
    --erp-chart-14: var(--erp-danger-dark);
    --erp-chart-15: var(--erp-violet-dark);
    --erp-chart-16: var(--erp-teal-dark);
    --erp-chart-17: var(--erp-orange-dark);
    --erp-chart-18: var(--erp-info-dark);
    --erp-chart-19: var(--erp-pink-dark);
    --erp-chart-20: var(--erp-n-700);

    /* ---- Elevation ----------------------------------------------- */
    --erp-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
    --erp-shadow:    0 2px 8px rgba(0, 0, 0, 0.06);
    --erp-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.10);
    --erp-shadow-lg: 0 10px 25px rgba(0, 0, 0, 0.12);
    --erp-scrim:     rgba(2, 8, 30, 0.55);
}

/* ============================================================
   BASE
   The page needs a text colour of its own. Without one, anything that
   does not set `color` inherits the browser default — black — which is
   invisible on a dark card. This is the floor; any component that sets its
   own colour still wins.
   ============================================================ */
body {
    color: var(--erp-text);
}

/* Tell the browser which way the page leans. This is what repaints the parts
   we cannot style: the native <option> popup, scrollbars, spinners, date
   pickers and the default form-control chrome. Without it a dark page still
   drops a white dropdown list over itself. */
:root {
    color-scheme: light;
}

:root[data-theme="dark"] {
    color-scheme: dark;
}

/* Form controls do NOT inherit `color` from their parent — they use the
   browser's own default, which is near-black whatever the page is doing. The
   selects on the dashboard set a themed background but no colour, so in dark
   mode they were dark text on a dark field. */
select,
input,
textarea {
    color: var(--erp-text);
}

/* The popup list is rendered by the OS. color-scheme above does most of the
   work; these keep it right where a component has restyled the select. */
option,
optgroup {
    color: var(--erp-text);
    background-color: var(--erp-surface-card);
}

::placeholder {
    color: var(--erp-text-muted);
    opacity: 1;  /* Firefox dims placeholders again on top of the colour. */
}

/* ============================================================
   LEGACY ALIASES
   Generic names that predate this file. Only the unambiguous ones are
   listed: --text-secondary means the same thing everywhere it appears, so
   pointing it at a token is safe. Names like --primary and --accent are
   deliberately absent — they mean the navy in one stylesheet and a bright
   blue in another, and claiming them globally would repaint half the app.

   These are defined at plain `:root`, so a stylesheet that declares its own
   value still wins. That file keeps working exactly as before; it simply
   will not follow dark mode until it is migrated.
   ============================================================ */
:root {
    --text-primary:   var(--erp-text);
    --text-secondary: var(--erp-text-secondary);
    --text-muted:     var(--erp-text-muted);
    --border-color:   var(--erp-border);
    --bg-light:       var(--erp-surface-sunken);
    --bg-white:       var(--erp-surface-card);
}

/* ============================================================
   DARK MODE
   Only surfaces, lines and text move. Primary and semantic hues are
   deliberately left alone — an error badge must not drift toward grey
   just because the page went dark.
   ============================================================ */
:root[data-theme="dark"] {
    /* The ramp inverts: --erp-n-50 still means "the lightest surface", it is
       just now a near-black. Anything built on the ramp needs no dark rule. */
    --erp-n-50:  #0b1220;
    --erp-n-100: #131c2e;
    --erp-n-200: #263149;
    --erp-n-300: #33415f;
    --erp-n-400: #7a869e;
    --erp-n-500: #a3adc2;
    --erp-n-600: #c2cad9;
    --erp-n-700: #d5dbe7;
    --erp-n-800: #e5e9f0;
    --erp-n-900: #f4f6fa;

    --erp-primary-text:  #a2acc2;
    --erp-primary-soft:  #172238;
    --erp-primary-line:  #212f4f;

    --erp-surface-page:    var(--erp-n-50);
    /* Keep ERP_DARK_CARD in config/theme.php in step with this value. */
    --erp-surface-card:    #131c2e;
    /* One step lighter than the card. In light mode a modal separates from the
       page by its shadow; on a dark page a shadow is invisible, so the surface
       itself has to lift. */
    --erp-surface-raised:  #1d2a47;
    /* "Sunken" has to invert its relationship to the card. In light mode a
       recessed well is darker than the white card, and --erp-n-100 gives that.
       In dark mode --erp-n-100 IS the card colour, so wells, table headers and
       search fields flattened into their surroundings. Recessed now means
       deeper than the card, not lighter. */
    --erp-surface-sunken:  #0d1522;
    --erp-surface-hover:   #1d2842;
    --erp-surface-panel:   #131c2e;
    --erp-surface-panel-deep: #0e1626;
    --erp-surface-panel-hover: #24324f;

    --erp-border-faint:  #1c2740;


    /* Soft tints are near-white in light mode; at 8% they read as a wash
       over a dark card instead of a glaring block. */
    --erp-accent-soft:  rgba(59, 130, 246, 0.14);
    --erp-success-soft: rgba(16, 185, 129, 0.14);
    --erp-warning-soft: rgba(245, 158, 11, 0.14);
    --erp-danger-soft:  rgba(239, 68, 68, 0.14);
    --erp-info-soft:    rgba(14, 165, 233, 0.14);
    --erp-violet-soft:  rgba(139, 92, 246, 0.16);

    /* The extended hues have no runtime override, so their dark shades are
       written out here, mixed the way config/theme.php mixes the others:
       -dark lifts 12% toward white, -soft and -line sink 86% / 55% into the
       dark card (ERP_DARK_CARD). */
    --erp-pink-dark:    #ee5ea5;
    --erp-pink-soft:    #31223d;
    --erp-pink-line:    #75305e;
    --erp-teal-dark:    #30c1b1;
    --erp-teal-soft:    #13323f;
    --erp-teal-line:    #136264;
    --erp-orange-dark:  #fa8432;
    --erp-orange-soft:  #33282b;
    --erp-orange-line:  #7a4323;

    /* Coloured text on a dark card is the same problem as coloured text on a
       dark fill, so it takes the same shade. */
    --erp-accent-text:   var(--erp-accent-on-dark);
    --erp-success-text:  var(--erp-success-on-dark);
    --erp-warning-text:  var(--erp-warning-on-dark);
    --erp-danger-text:   var(--erp-danger-on-dark);
    --erp-info-text:     var(--erp-info-on-dark);
    --erp-violet-text:   var(--erp-violet-on-dark);
    --erp-pink-text:     var(--erp-pink-on-dark);
    --erp-teal-text:     var(--erp-teal-on-dark);
    --erp-orange-text:   var(--erp-orange-on-dark);

    /* Inverted: on a dark ground the brightest green must mean the most
       activity, so the ramp climbs in lightness instead of falling. */
    --erp-heat-1: #0e4429;
    --erp-heat-2: #006d32;
    --erp-heat-3: #26a641;
    --erp-heat-4: #39d353;

    /* A black shadow on a near-black page cannot be seen, so every elevation
       step also carries a 1px ring in the border colour. The ring is what
       draws the edge of a card here; the blur underneath only adds depth.
       box-shadow, not border, so nothing shifts by a pixel. */
    --erp-shadow-sm: 0 0 0 1px var(--erp-border), 0 1px 2px rgba(0, 0, 0, 0.4);
    --erp-shadow:    0 0 0 1px var(--erp-border), 0 2px 8px rgba(0, 0, 0, 0.45);
    --erp-shadow-md: 0 0 0 1px var(--erp-border-strong), 0 4px 12px rgba(0, 0, 0, 0.5);
    --erp-shadow-lg: 0 0 0 1px var(--erp-border-strong), 0 10px 25px rgba(0, 0, 0, 0.55);

    /* ~20 stylesheets declare their own --shadow-* at plain :root with
       light-mode values. The names mean the same thing everywhere, so in dark
       mode they are re-pointed here; this selector outranks a plain :root, and
       light mode is left exactly as each file wrote it. */
    --shadow-sm: var(--erp-shadow-sm);
    --shadow:    var(--erp-shadow);
    --shadow-md: var(--erp-shadow-md);
    --shadow-lg: var(--erp-shadow-lg);
}

/* Suppress the transition flash when the theme flips. */
:root[data-theme-switching] * {
    transition: none !important;
}

/* ============================================================
   FLOATING SURFACES (dark mode)
   Modals, drawers and dialogs are written against --erp-surface-card like
   everything else, which on a dark page makes them the same colour as the
   cards underneath: dark on dark, with a shadow nobody can see.

   Rather than restyle each of the ~150 modals, re-point the card token for
   anything that is a modal. The box reads the new value for its own
   background, and so does every card-coloured child inside it, so the whole
   dialog lifts together while wells and inputs (sunken) stay recessed.

   `body` is excluded because Bootstrap puts `modal-open` on it while a modal
   is showing, which would otherwise lift the entire page.
   ============================================================ */
:root[data-theme="dark"] [class*="modal"]:not(body):not(html),
:root[data-theme="dark"] [class*="Modal"]:not(body):not(html),
:root[data-theme="dark"] [class*="drawer"]:not(body):not(html),
:root[data-theme="dark"] [class*="popover"]:not(body):not(html),
:root[data-theme="dark"] [class*="dialog"]:not(body):not(html),
:root[data-theme="dark"] [role="dialog"],
:root[data-theme="dark"] dialog,
:root[data-theme="dark"] .offcanvas,
:root[data-theme="dark"] .dropdown-menu,
:root[data-theme="dark"] .swal2-popup {
    --erp-surface-card:  var(--erp-surface-raised);
    /* Pages that route the card colour through their own variable resolve it
       once at :root, so re-pointing the token above never reaches them. The
       names below are every local alias of --erp-surface-card in the ERP. */
    --bg-white:           var(--erp-surface-raised);
    --card-bg:            var(--erp-surface-raised);
    --surface:            var(--erp-surface-raised);
    --um-surface:         var(--erp-surface-raised);
    --studio-surface:     var(--erp-surface-raised);
    --source-report-card: var(--erp-surface-raised);
    --report-surface:     var(--erp-surface-raised);
    --rep-card:           var(--erp-surface-raised);
    --pur-card:           var(--erp-surface-raised);
    --ps-surface:         var(--erp-surface-raised);
    --pl-card:            var(--erp-surface-raised);
    --ldb-surface:        var(--erp-surface-raised);
    --ed-surface:         var(--erp-surface-raised);
    --ed-card-bg:         var(--erp-surface-raised);
    --al-card:            var(--erp-surface-raised);
    --erp-surface-hover: #283758;
    --erp-border:        #33415f;
    /* The low end of the ramp is tuned against the page: --erp-n-50 is a
       near-black that sits just under a card. Under a raised surface the same
       value is three steps too deep, so a table header, zebra row or footer
       that is a faint tint in light mode became a black band across the
       dialog. Lift the tints with the surface so they stay one step below it,
       and move the two line colours up so they still show against it. */
    --erp-n-50:           #162037;
    --erp-n-100:          #1a2640;
    --erp-n-200:          #33415f;
    --erp-n-300:          #42517a;
    --erp-surface-sunken: #141e33;
    --bs-modal-bg:       var(--erp-surface-raised);
    --bs-body-bg:        var(--erp-surface-raised);
}

/* A hairline ring does what the shadow cannot on a dark page. box-shadow, not
   border, so no dialog shifts by a pixel. */
:root[data-theme="dark"] .modal-content,
:root[data-theme="dark"] .modal-container,
:root[data-theme="dark"] .modal-box,
:root[data-theme="dark"] .modal-card,
:root[data-theme="dark"] .modal-dialog-box,
:root[data-theme="dark"] dialog,
:root[data-theme="dark"] .swal2-popup {
    box-shadow: 0 0 0 1px var(--erp-border-strong), 0 24px 60px rgba(0, 0, 0, 0.6);
}

/* A field with no background of its own is painted by the browser, and with
   color-scheme: dark that default is a flat mid-grey that matches nothing.
   :where() keeps this at zero specificity, so any stylesheet that does set a
   background still wins; this only replaces the browser default. */
:where(:root[data-theme="dark"]) :where(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="image"]):not([type="submit"]):not([type="button"]):not([type="reset"]), select, textarea) {
    background-color: var(--erp-surface-sunken);
    border-color: var(--erp-border-strong);
}

/* ============================================================
   BOOTSTRAP BRIDGE (dark mode only)
   Around forty pages lean on Bootstrap's own classes, and Bootstrap paints
   from its own variables and a few hardcoded values — none of which know
   about the tokens above. Rather than restyle each page, point Bootstrap's
   variables at ours and patch the utilities that hardcode a colour.
   Scoped to dark so the light theme stays byte-for-byte what it was.
   ============================================================ */
:root[data-theme="dark"] {
    --bs-body-color:       var(--erp-text);
    --bs-body-bg:          var(--erp-surface-page);
    --bs-secondary-color:  var(--erp-text-secondary);
    --bs-tertiary-bg:      var(--erp-surface-sunken);
    --bs-border-color:     var(--erp-border);
    --bs-emphasis-color:   var(--erp-n-900);
    --bs-heading-color:    var(--erp-text);
}

:root[data-theme="dark"] .table {
    --bs-table-color:          var(--erp-text);
    --bs-table-bg:             transparent;
    --bs-table-border-color:   var(--erp-border);
    --bs-table-striped-color:  var(--erp-text);
    --bs-table-striped-bg:     rgba(255, 255, 255, 0.03);
    --bs-table-hover-color:    var(--erp-text);
    --bs-table-hover-bg:       rgba(255, 255, 255, 0.05);
    color: var(--erp-text);
    border-color: var(--erp-border);
}

:root[data-theme="dark"] .card,
:root[data-theme="dark"] .modal-content,
:root[data-theme="dark"] .dropdown-menu,
:root[data-theme="dark"] .list-group-item,
:root[data-theme="dark"] .accordion-item,
:root[data-theme="dark"] .accordion-button,
:root[data-theme="dark"] .offcanvas {
    background-color: var(--erp-surface-card);
    color: var(--erp-text);
    border-color: var(--erp-border);
}

:root[data-theme="dark"] .card-header,
:root[data-theme="dark"] .card-footer,
:root[data-theme="dark"] .modal-header,
:root[data-theme="dark"] .modal-footer {
    border-color: var(--erp-border);
}

:root[data-theme="dark"] .form-control,
:root[data-theme="dark"] .form-select,
:root[data-theme="dark"] .input-group-text {
    background-color: var(--erp-surface-card);
    color: var(--erp-text);
    border-color: var(--erp-border-strong);
}

:root[data-theme="dark"] .form-control:disabled,
:root[data-theme="dark"] .form-control[readonly],
:root[data-theme="dark"] .form-select:disabled {
    background-color: var(--erp-surface-sunken);
}

:root[data-theme="dark"] .dropdown-item { color: var(--erp-text); }
:root[data-theme="dark"] .dropdown-item:hover,
:root[data-theme="dark"] .dropdown-item:focus {
    background-color: var(--erp-surface-hover);
    color: var(--erp-text);
}

:root[data-theme="dark"] .nav-tabs { border-color: var(--erp-border); }
:root[data-theme="dark"] .nav-tabs .nav-link.active {
    background-color: var(--erp-surface-card);
    color: var(--erp-text);
    border-color: var(--erp-border) var(--erp-border) var(--erp-surface-card);
}

:root[data-theme="dark"] .bg-white  { background-color: var(--erp-surface-card) !important; }
:root[data-theme="dark"] .bg-light  { background-color: var(--erp-surface-sunken) !important; }
:root[data-theme="dark"] .text-dark,
:root[data-theme="dark"] .text-body { color: var(--erp-text) !important; }
:root[data-theme="dark"] .text-muted,
:root[data-theme="dark"] .form-text { color: var(--erp-text-secondary) !important; }
:root[data-theme="dark"] .border,
:root[data-theme="dark"] .border-top,
:root[data-theme="dark"] .border-bottom { border-color: var(--erp-border) !important; }
:root[data-theme="dark"] .btn-close { filter: invert(1) grayscale(100%) brightness(200%); }
:root[data-theme="dark"] .btn-light,
:root[data-theme="dark"] .btn-outline-secondary {
    background-color: var(--erp-surface-sunken);
    color: var(--erp-text);
    border-color: var(--erp-border-strong);
}

:root[data-theme="dark"] .btn-outline-dark {
    --bs-btn-color:        var(--erp-text);
    --bs-btn-border-color: var(--erp-border-strong);
    --bs-btn-hover-bg:     var(--erp-surface-hover);
    --bs-btn-hover-color:  var(--erp-text);
    --bs-btn-hover-border-color: var(--erp-border-strong);
    --bs-btn-active-bg:    var(--erp-surface-hover);
    --bs-btn-active-color: var(--erp-text);
    --bs-btn-disabled-color: var(--erp-text-muted);
    color: var(--erp-text);
    border-color: var(--erp-border-strong);
}
:root[data-theme="dark"] .btn-dark {
    --bs-btn-bg:           var(--erp-surface-panel-hover);
    --bs-btn-border-color: var(--erp-border-strong);
    --bs-btn-hover-bg:     var(--erp-surface-hover);
}
:root[data-theme="dark"] .text-black,
:root[data-theme="dark"] .link-dark { color: var(--erp-text) !important; }
:root[data-theme="dark"] .bg-body,
:root[data-theme="dark"] .bg-body-tertiary { background-color: var(--erp-surface-sunken) !important; }
:root[data-theme="dark"] .table-light,
:root[data-theme="dark"] .table > thead.table-light > tr > th {
    --bs-table-bg:    var(--erp-surface-sunken);
    --bs-table-color: var(--erp-text);
    background-color: var(--erp-surface-sunken);
    color: var(--erp-text);
}
:root[data-theme="dark"] .alert-info    { background-color: var(--erp-info-soft);    color: var(--erp-text); border-color: var(--erp-info-line); }
:root[data-theme="dark"] .alert-warning { background-color: var(--erp-warning-soft); color: var(--erp-text); border-color: var(--erp-warning-line); }
:root[data-theme="dark"] .alert-success { background-color: var(--erp-success-soft); color: var(--erp-text); border-color: var(--erp-success-line); }
:root[data-theme="dark"] .alert-danger  { background-color: var(--erp-danger-soft);  color: var(--erp-text); border-color: var(--erp-danger-line); }
:root[data-theme="dark"] .alert-secondary,
:root[data-theme="dark"] .alert-light   { background-color: var(--erp-surface-sunken); color: var(--erp-text); border-color: var(--erp-border); }
:root[data-theme="dark"] .bg-warning-subtle { background-color: var(--erp-warning-soft) !important; }
:root[data-theme="dark"] .bg-success-subtle { background-color: var(--erp-success-soft) !important; }
:root[data-theme="dark"] .bg-danger-subtle  { background-color: var(--erp-danger-soft) !important; }
:root[data-theme="dark"] .bg-info-subtle,
:root[data-theme="dark"] .bg-primary-subtle { background-color: var(--erp-accent-soft) !important; }

/* Paper is white. A dark page must not send a dark sheet to the printer. */
@media print {
    /* Quadrupled so it also outranks the dark block config/theme.php emits. */
    :root:root:root:root[data-theme="dark"] {
        color-scheme: light;
        --erp-n-50:  #f8fafc; --erp-n-100: #f1f5f9; --erp-n-200: #e2e8f0;
        --erp-n-300: #cbd5e1; --erp-n-400: #94a3b8; --erp-n-500: #64748b;
        --erp-n-600: #475569; --erp-n-700: #334155; --erp-n-800: #1e293b;
        --erp-n-900: #0f172a;
        --erp-surface-page:   #ffffff;
        --erp-surface-card:   #ffffff;
        --erp-surface-sunken: #f1f5f9;
        --erp-border-faint:   #f0f0f0;
        --erp-primary-text:   #314677;
        --erp-pink-dark:   #c23b7d; --erp-pink-soft:   #fdedf5; --erp-pink-line:   #f6add1;
        --erp-teal-dark:   #109788; --erp-teal-soft:   #e8f8f6; --erp-teal-line:   #95dfd7;
        --erp-orange-dark: #cc5e12; --erp-orange-soft: #fef1e8; --erp-orange-line: #fcc096;
        --erp-accent-text: var(--erp-accent-dark); --erp-success-text: var(--erp-success-dark); --erp-warning-text: var(--erp-warning-dark);
        --erp-danger-text: var(--erp-danger-dark); --erp-info-text: var(--erp-info-dark); --erp-violet-text: var(--erp-violet-dark);
        --erp-pink-text: var(--erp-pink-dark); --erp-teal-text: var(--erp-teal-dark); --erp-orange-text: var(--erp-orange-dark);
    }
}

/* Maps. The tiles are imagery, so they cannot be re-coloured from tokens;
   inverting them and rotating the hue back gives a dark basemap that keeps
   water blue and parks green. The zoom buttons and attribution take the same
   filter, which is why they are NOT restyled below — a dark background there
   would be inverted straight back to light. Markers, shapes and popups sit in
   other panes and keep their real colours. */
:root[data-theme="dark"] .leaflet-layer,
:root[data-theme="dark"] .leaflet-control-zoom-in,
:root[data-theme="dark"] .leaflet-control-zoom-out,
:root[data-theme="dark"] .leaflet-control-attribution {
    filter: invert(100%) hue-rotate(180deg) brightness(95%) contrast(90%);
}
:root[data-theme="dark"] .leaflet-container {
    background: var(--erp-surface-sunken);
}

/* Popups and the layer switcher are drawn white with Leaflet's own dark
   text; page text inside them is themed, so the box has to follow. */
:root[data-theme="dark"] .leaflet-popup-content-wrapper,
:root[data-theme="dark"] .leaflet-popup-tip,
:root[data-theme="dark"] .leaflet-control-layers {
    background-color: var(--erp-surface-card);
    color: var(--erp-text);
    border-color: var(--erp-border);
}
:root[data-theme="dark"] .leaflet-container a.leaflet-popup-close-button {
    color: var(--erp-text-secondary);
}
