/* =====================================================================
 * wwl-theme.css — the platform color palette, light and dark.  [#1728]
 *
 * ONE palette for the whole app. Before this file there were three
 * half-systems: `loginpage.css` (.loginreg[data-theme] + the
 * localStorage key `wwl-theme`), `dashboard_grid.css` (:root tokens whose
 * only consumer hardcoded data-theme="dark"), and a bare
 * prefers-color-scheme block in `winfocus-ai.css` that no toggle could
 * reach. This is the second of those generalised, not a fourth system.
 *
 * THE THREE-STATE PATTERN — the same one `tools/qa-bench/template.html`
 * uses, and the reason it is worth the duplication below:
 *
 *   1. bare :root                                  -> light, the default
 *   2. @media (prefers-color-scheme: dark)
 *        guarded by :root:not([data-theme="light"]) -> follow the OS
 *   3. :root[data-theme="dark"]                    -> an explicit choice
 *
 * Block 2 MUST carry the :not([data-theme="light"]) guard. Without it,
 * choosing light on a dark-OS machine leaves parts of the page dark —
 * which is exactly what winfocus-ai.css did until this shipped.
 *
 * Blocks 2 and 3 are byte-identical by design and
 * `tools/ui-checks/check-contrast.mjs` asserts that they stay so,
 * along with asserting every foreground/background PAIR below clears
 * WCAG AA in BOTH themes. Run it after any change here:
 *
 *   node tools/ui-checks/check-contrast.mjs
 *
 * That check is a script rather than a comment on purpose. The recurring
 * complaint this file answers is button text with too little contrast,
 * and a palette rule that only ever gets re-read is a rule that fails
 * silently the first time someone nudges a hex value.
 * ===================================================================== */

/* ── Light (default) ─────────────────────────────────────────────── */
:root {
  /* Surfaces */
  --wwl-bg: #f8fafc;
  --wwl-surface: #ffffff;
  --wwl-surface-2: #f1f5f9;
  --wwl-surface-3: #e2e8f0;

  /* Text */
  --wwl-text: #0f172a;
  --wwl-text-muted: #475569;
  --wwl-text-faint: #64748b;

  /* Lines. --wwl-border is decorative; --wwl-border-strong is for the
     edge of an actual control and is held to 3:1 against its surface. */
  --wwl-border: #e2e8f0;
  --wwl-border-strong: #64748b;

  /* Brand accent, and the text that sits ON it */
  --wwl-accent: #7c3aed;
  --wwl-accent-hover: #6d28d9;
  --wwl-accent-text: #ffffff;
  --wwl-accent-soft: #f5f3ff;
  --wwl-accent-soft-text: #5b21b6;

  /* Links */
  --wwl-link: #6d28d9;
  --wwl-link-hover: #5b21b6;

  /* Status. Each has an -on token: the text color that goes on top. */
  --wwl-danger: #dc2626;
  --wwl-danger-on: #ffffff;
  --wwl-danger-soft: #fef2f2;
  --wwl-danger-soft-text: #991b1b;
  --wwl-success: #15803d;
  --wwl-success-on: #ffffff;
  --wwl-success-soft: #f0fdf4;
  --wwl-success-soft-text: #14532d;
  --wwl-warn: #b45309;
  --wwl-warn-on: #ffffff;
  --wwl-warn-soft: #fffbeb;
  --wwl-warn-soft-text: #92400e;

  /* Header / nav chrome */
  --wwl-nav-bg: #ffffff;
  --wwl-nav-text: #1f1f1f;
  --wwl-nav-border: #eeeeee;

  /* Form controls */
  --wwl-input-bg: #ffffff;
  --wwl-input-text: #0f172a;
  --wwl-input-placeholder: #64748b;

  /* Elevation */
  --wwl-shadow: 0 4px 16px rgba(15, 23, 42, 0.08);
  --wwl-shadow-lg: 0 8px 28px rgba(15, 23, 42, 0.14);
  --wwl-overlay: rgba(15, 23, 42, 0.45);

  /* The gamification accents, which used to be inline hex in nav.php.
     Both are read as text on --wwl-surface, so both are checked. */
  --wwl-streak: #dc2626;
  --wwl-points: #b45309;
  --wwl-focus: #4f46e5;
  --wwl-guide: #0e7490;

  color-scheme: light;
}

/* ── Dark, following the OS ──────────────────────────────────────── */
/* The :not([data-theme="light"]) guard is load-bearing: it is what lets an
   explicit light choice win on a dark-OS machine. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --wwl-bg: #0f172a;
    --wwl-surface: #1e293b;
    --wwl-surface-2: #273449;
    --wwl-surface-3: #334155;

    --wwl-text: #f1f5f9;
    --wwl-text-muted: #94a3b8;
    --wwl-text-faint: #94a3b8;

    --wwl-border: #334155;
    --wwl-border-strong: #64748b;

    --wwl-accent: #7c3aed;
    --wwl-accent-hover: #9333ea;
    --wwl-accent-text: #ffffff;
    --wwl-accent-soft: #2e1065;
    --wwl-accent-soft-text: #ddd6fe;

    --wwl-link: #c4b5fd;
    --wwl-link-hover: #ddd6fe;

    --wwl-danger: #b91c1c;
    --wwl-danger-on: #ffffff;
    --wwl-danger-soft: #450a0a;
    --wwl-danger-soft-text: #fecaca;
    --wwl-success: #15803d;
    --wwl-success-on: #ffffff;
    --wwl-success-soft: #052e16;
    --wwl-success-soft-text: #bbf7d0;
    --wwl-warn: #b45309;
    --wwl-warn-on: #ffffff;
    --wwl-warn-soft: #451a03;
    --wwl-warn-soft-text: #fde68a;

    --wwl-nav-bg: #1e293b;
    --wwl-nav-text: #e2e8f0;
    --wwl-nav-border: #334155;

    --wwl-input-bg: #0f172a;
    --wwl-input-text: #f1f5f9;
    --wwl-input-placeholder: #94a3b8;

    --wwl-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
    --wwl-shadow-lg: 0 8px 28px rgba(0, 0, 0, 0.6);
    --wwl-overlay: rgba(0, 0, 0, 0.6);

    --wwl-streak: #f87171;
    --wwl-points: #fbbf24;
    --wwl-focus: #a5b4fc;
    --wwl-guide: #67e8f9;

    color-scheme: dark;
  }
}

/* ── Dark, chosen explicitly ─────────────────────────────────────── */
/* Byte-identical to the block above; check-contrast.mjs enforces that. */
:root[data-theme="dark"] {
  --wwl-bg: #0f172a;
  --wwl-surface: #1e293b;
  --wwl-surface-2: #273449;
  --wwl-surface-3: #334155;

  --wwl-text: #f1f5f9;
  --wwl-text-muted: #94a3b8;
  --wwl-text-faint: #94a3b8;

  --wwl-border: #334155;
  --wwl-border-strong: #64748b;

  --wwl-accent: #7c3aed;
  --wwl-accent-hover: #9333ea;
  --wwl-accent-text: #ffffff;
  --wwl-accent-soft: #2e1065;
  --wwl-accent-soft-text: #ddd6fe;

  --wwl-link: #c4b5fd;
  --wwl-link-hover: #ddd6fe;

  --wwl-danger: #b91c1c;
  --wwl-danger-on: #ffffff;
  --wwl-danger-soft: #450a0a;
  --wwl-danger-soft-text: #fecaca;
  --wwl-success: #15803d;
  --wwl-success-on: #ffffff;
  --wwl-success-soft: #052e16;
  --wwl-success-soft-text: #bbf7d0;
  --wwl-warn: #b45309;
  --wwl-warn-on: #ffffff;
  --wwl-warn-soft: #451a03;
  --wwl-warn-soft-text: #fde68a;

  --wwl-nav-bg: #1e293b;
  --wwl-nav-text: #e2e8f0;
  --wwl-nav-border: #334155;

  --wwl-input-bg: #0f172a;
  --wwl-input-text: #f1f5f9;
  --wwl-input-placeholder: #94a3b8;

  --wwl-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
  --wwl-shadow-lg: 0 8px 28px rgba(0, 0, 0, 0.6);
  --wwl-overlay: rgba(0, 0, 0, 0.6);

  --wwl-streak: #f87171;
  --wwl-points: #fbbf24;
  --wwl-focus: #a5b4fc;
  --wwl-guide: #67e8f9;

  color-scheme: dark;
}

/* =====================================================================
 * Applied layer — the global chrome, painted from the tokens above.
 *
 * DARK ONLY, and deliberately so. Every rule below is additive: light
 * mode renders exactly as it did before this file existed, because none
 * of these selectors match. Repainting light mode from tokens would be
 * the more principled shape, but `style.css` alone is 220KB of hardcoded
 * light values and "improve dark mode" is not a license to shift the
 * theme every user is already looking at.
 *
 * The single selector is `:root[data-theme="dark"]`, not the pair of
 * states the tokens use, because the bootstrap in layouts/meta_tags.php
 * always RESOLVES the theme and writes an explicit `light` or `dark`
 * before first paint. So by the time these rules are evaluated there is
 * always an explicit attribute, and this list does not need writing
 * twice — which matters, because it is ~200 lines and a second copy is
 * a second thing to forget.
 *
 * With JavaScript off there is no attribute, so a dark-OS machine gets
 * the dark *tokens* (block 2) but the light chrome. Nothing reads those
 * tokens in that state, so the page is simply light — the same thing it
 * was before, rather than a half-painted mixture.
 * ===================================================================== */

:root[data-theme="dark"] body {
  background-color: var(--wwl-bg);
  color: var(--wwl-text);
}

:root[data-theme="dark"] .navbar,
:root[data-theme="dark"] #main-nav {
  background-color: var(--wwl-nav-bg);
  border-bottom-color: var(--wwl-nav-border);
}

:root[data-theme="dark"] nav li a,
:root[data-theme="dark"] #main-nav .nav-link,
:root[data-theme="dark"] .navbar-brand {
  color: var(--wwl-nav-text) !important;
}

:root[data-theme="dark"] #main-nav .navbar-collapse {
  background: var(--wwl-nav-bg);
}

:root[data-theme="dark"] .navbar-toggler-icon {
  filter: invert(1) brightness(1.4);
}

:root[data-theme="dark"] #main-nav .dropdown-menu,
:root[data-theme="dark"] .dropdown-menu {
  background-color: var(--wwl-surface);
  border-color: var(--wwl-border);
  box-shadow: var(--wwl-shadow-lg);
}

:root[data-theme="dark"] .dropdown-item,
:root[data-theme="dark"] nav .dropdown-menu li a {
  color: var(--wwl-text) !important;
}

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

:root[data-theme="dark"] .dropdown-divider {
  border-top-color: var(--wwl-border);
}

/* Content surfaces */
:root[data-theme="dark"] .card,
:root[data-theme="dark"] .panel,
:root[data-theme="dark"] .modal-content,
:root[data-theme="dark"] .list-group-item,
:root[data-theme="dark"] .notification-panel #notification-panel {
  background-color: var(--wwl-surface);
  border-color: var(--wwl-border);
  color: var(--wwl-text);
}

:root[data-theme="dark"] .modal-header,
:root[data-theme="dark"] .modal-footer,
:root[data-theme="dark"] .card-header,
:root[data-theme="dark"] .card-footer,
:root[data-theme="dark"] .panel-heading {
  background-color: var(--wwl-surface-2);
  border-color: var(--wwl-border);
  color: var(--wwl-text);
}

:root[data-theme="dark"] .modal-backdrop.show {
  opacity: 1;
  background-color: var(--wwl-overlay);
}

:root[data-theme="dark"] .close {
  color: var(--wwl-text);
  text-shadow: none;
  opacity: .8;
}

/* Type.
   These are wrapped in :where() so they weigh what a bare element selector
   weighs -- (0,0,1) -- instead of (0,2,1). Without it, `:root[data-theme] a`
   outranks a two-class rule, and it did: it repainted
   `.wf-nav__link.is-active`, whose own rule sets `color:#fff` on a filled
   accent background, to the light-purple link color, giving light purple on
   light purple. A blanket rule that beats every considered one is not a
   default, it is an override. This way anything that names its own color
   keeps it, and only the unstyled remainder falls through to the token. */
:where(:root[data-theme="dark"]) h1,
:where(:root[data-theme="dark"]) h2,
:where(:root[data-theme="dark"]) h3,
:where(:root[data-theme="dark"]) h4,
:where(:root[data-theme="dark"]) h5,
:where(:root[data-theme="dark"]) h6 {
  color: var(--wwl-text);
}

:root[data-theme="dark"] .text-muted,
:root[data-theme="dark"] small {
  color: var(--wwl-text-muted) !important;
}

:where(:root[data-theme="dark"]) a {
  color: var(--wwl-link);
}

:where(:root[data-theme="dark"]) a:hover,
:where(:root[data-theme="dark"]) a:focus {
  color: var(--wwl-link-hover);
}

:root[data-theme="dark"] hr {
  border-top-color: var(--wwl-border);
}

/* Form controls — the operator's headline complaint. An input whose text
   color is inherited but whose background is a hardcoded white is the
   single most common way a dark theme produces unreadable text, so these
   are set as a pair rather than leaving either to inherit. */
:root[data-theme="dark"] .form-control,
:root[data-theme="dark"] input[type="text"],
:root[data-theme="dark"] input[type="email"],
:root[data-theme="dark"] input[type="password"],
:root[data-theme="dark"] input[type="number"],
:root[data-theme="dark"] input[type="search"],
:root[data-theme="dark"] input[type="url"],
:root[data-theme="dark"] input[type="tel"],
:root[data-theme="dark"] input[type="date"],
:root[data-theme="dark"] textarea,
:root[data-theme="dark"] select {
  background-color: var(--wwl-input-bg);
  color: var(--wwl-input-text);
  border-color: var(--wwl-border-strong);
}

:root[data-theme="dark"] .form-control:focus,
:root[data-theme="dark"] input:focus,
:root[data-theme="dark"] textarea:focus,
:root[data-theme="dark"] select:focus {
  background-color: var(--wwl-input-bg);
  color: var(--wwl-input-text);
  border-color: var(--wwl-accent);
  box-shadow: 0 0 0 .2rem rgba(124, 58, 237, .3);
}

:root[data-theme="dark"] .form-control::placeholder,
:root[data-theme="dark"] input::placeholder,
:root[data-theme="dark"] textarea::placeholder {
  color: var(--wwl-input-placeholder);
  opacity: 1;
}

:root[data-theme="dark"] label,
:root[data-theme="dark"] legend {
  color: var(--wwl-text);
}

:root[data-theme="dark"] .input-group-text {
  background-color: var(--wwl-surface-2);
  border-color: var(--wwl-border-strong);
  color: var(--wwl-text-muted);
}

/* Buttons. Bootstrap's default .btn inherits its color from body, which
   in dark mode turns a light-background button's label near-white on
   near-white. Each variant therefore names both halves of its pair. */
:root[data-theme="dark"] .btn-primary {
  background-color: var(--wwl-accent);
  border-color: var(--wwl-accent);
  color: var(--wwl-accent-text);
}

:root[data-theme="dark"] .btn-primary:hover,
:root[data-theme="dark"] .btn-primary:focus {
  background-color: var(--wwl-accent-hover);
  border-color: var(--wwl-accent-hover);
  color: var(--wwl-accent-text);
}

:root[data-theme="dark"] .btn-secondary,
:root[data-theme="dark"] .btn-light,
:root[data-theme="dark"] .btn-default {
  background-color: var(--wwl-surface-3);
  border-color: var(--wwl-border-strong);
  color: var(--wwl-text);
}

:root[data-theme="dark"] .btn-outline-primary {
  border-color: var(--wwl-accent);
  color: var(--wwl-link);
  background-color: transparent;
}

:root[data-theme="dark"] .btn-outline-primary:hover {
  background-color: var(--wwl-accent);
  color: var(--wwl-accent-text);
}

:root[data-theme="dark"] .btn-danger {
  background-color: var(--wwl-danger);
  border-color: var(--wwl-danger);
  color: var(--wwl-danger-on);
}

:root[data-theme="dark"] .btn-success {
  background-color: var(--wwl-success);
  border-color: var(--wwl-success);
  color: var(--wwl-success-on);
}

:root[data-theme="dark"] .btn-warning {
  background-color: var(--wwl-warn);
  border-color: var(--wwl-warn);
  color: var(--wwl-warn-on);
}

/* Tables */
:root[data-theme="dark"] table,
:root[data-theme="dark"] .table {
  color: var(--wwl-text);
  border-color: var(--wwl-border);
}

:root[data-theme="dark"] .table thead th {
  background-color: var(--wwl-surface-2);
  color: var(--wwl-text);
  border-color: var(--wwl-border);
}

:root[data-theme="dark"] .table td,
:root[data-theme="dark"] .table th {
  border-color: var(--wwl-border);
}

:root[data-theme="dark"] .table-striped tbody tr:nth-of-type(odd) {
  background-color: var(--wwl-surface);
}

:root[data-theme="dark"] .table-hover tbody tr:hover {
  background-color: var(--wwl-surface-2);
  color: var(--wwl-text);
}

/* Alerts / badges */
:root[data-theme="dark"] .alert-danger {
  background-color: var(--wwl-danger-soft);
  border-color: var(--wwl-danger);
  color: var(--wwl-danger-soft-text);
}

:root[data-theme="dark"] .alert-success {
  background-color: var(--wwl-success-soft);
  border-color: var(--wwl-success);
  color: var(--wwl-success-soft-text);
}

:root[data-theme="dark"] .alert-warning {
  background-color: var(--wwl-warn-soft);
  border-color: var(--wwl-warn);
  color: var(--wwl-warn-soft-text);
}

:root[data-theme="dark"] .alert-info,
:root[data-theme="dark"] .alert-primary {
  background-color: var(--wwl-accent-soft);
  border-color: var(--wwl-accent);
  color: var(--wwl-accent-soft-text);
}

/* Footer */
:root[data-theme="dark"] footer,
:root[data-theme="dark"] .footer {
  background-color: var(--wwl-surface);
  color: var(--wwl-text-muted);
  border-top: 1px solid var(--wwl-border);
}

:root[data-theme="dark"] footer a,
:root[data-theme="dark"] .footer a {
  color: var(--wwl-link);
}

/* `footer` is a bare ELEMENT selector, and both quote carousels mark their
   attribution up as a semantic <footer> inside a card. So the page-footer
   background above was painting a slab behind "— Greg Reid". Each of those
   rules already sets `background: transparent` to beat `footer{background:#1f1f1f}`
   in style.css -- winfocus.css even carries a comment saying so -- but a
   one-class rule cannot outrank `:root[data-theme="dark"] footer`.

   Worth stating rather than just patching: a blanket element selector in the
   applied layer is a standing hazard, because it claims every future use of
   that element too. `footer` and `a` are the two here; `a` is defused with
   :where(), and this is the same defusing done by hand for the one element
   that cannot take it -- a background has no :where() equivalent when the
   thing being overridden is another background. [#1728] */
:root[data-theme="dark"] .login-quotes__attr,
:root[data-theme="dark"] .wf-quote__attr {
  background: transparent;
}

/* Breadcrumb */
:root[data-theme="dark"] .breadcrumb {
  background-color: var(--wwl-surface-2);
  color: var(--wwl-text-muted);
}

/* Focus timer chip + panel, which carry their own hardcoded light values
   in winfocus-gamification.css */
:root[data-theme="dark"] .wf-timer-chip--idle {
  color: var(--wwl-text-muted);
  border-color: var(--wwl-border);
  background: var(--wwl-surface-2);
}

:root[data-theme="dark"] .wf-timer-panel,
:root[data-theme="dark"] .wf-gam-nav-popup {
  background: var(--wwl-surface);
  border-color: var(--wwl-border);
  color: var(--wwl-text);
}

:root[data-theme="dark"] .wf-timer-panel__task,
:root[data-theme="dark"] .wf-timer-time {
  background: var(--wwl-input-bg);
  border-color: var(--wwl-border-strong);
  color: var(--wwl-input-text);
}

:root[data-theme="dark"] .wf-timer-panel__display {
  color: var(--wwl-text);
}

/* ---------------------------------------------------------------------
   Surfaces that carry their own palette, remapped rather than chased.

   Everything above this point assumes a light surface can be darkened by
   naming its properties. These four cannot: they set their own colors,
   sometimes inline, and a partial dark theme that recolors the TEXT on a
   surface it did not also darken is worse than no dark theme at all --
   which is exactly what the first pass here did to the winfocus nav
   (light-purple links left sitting on a still-white bar, 1.74:1).

   Found by measuring, not by looking: tools/ui-checks/check-dark-contrast.mjs
   walks the rendered page and reports every visible string under WCAG AA.
   --------------------------------------------------------------------- */

/* The winfocus app shell declares six tokens of its own (winfocus.css:9).
   Remapping those themes ~2600 lines of rules in one block. Declared twice
   because .wf-shell sets them locally -- an inherited :root value would lose
   to that -- and .wf-header sits outside the shell and needs the inherited
   copy. */
:root[data-theme="dark"],
:root[data-theme="dark"] .wf-shell {
  --wf-bg: #0f172a;
  --wf-card: #1e293b;
  --wf-border: #334155;
  --wf-ink: #f1f5f9;
  --wf-muted: #94a3b8;
  --wf-accent: #c4b5fd;
}

/* Card headings. These carry an inline `color:#111827` in several views --
   1.21:1 on a dark card, the worst reading on the whole page -- and an inline
   style is beatable only by !important. Bounded to headings inside a card, so
   a heading that is deliberately colored elsewhere is untouched. */
:root[data-theme="dark"] .card-title,
:root[data-theme="dark"] .card-body h1,
:root[data-theme="dark"] .card-body h2,
:root[data-theme="dark"] .card-body h3,
:root[data-theme="dark"] .card-body h4,
:root[data-theme="dark"] .card-body h5,
:root[data-theme="dark"] .card-body h6 {
  color: var(--wwl-text) !important;
}

/* Badges. Bootstrap's light-background variants keep dark text, and several
   views set the pair inline. Each variant names both halves. */
:root[data-theme="dark"] .badge-secondary,
:root[data-theme="dark"] .badge-light {
  background-color: var(--wwl-surface-3) !important;
  color: var(--wwl-text) !important;
}

:root[data-theme="dark"] .badge-success {
  background-color: var(--wwl-success) !important;
  color: var(--wwl-success-on) !important;
}

:root[data-theme="dark"] .badge-danger {
  background-color: var(--wwl-danger) !important;
  color: var(--wwl-danger-on) !important;
}

:root[data-theme="dark"] .badge-warning {
  background-color: var(--wwl-warn) !important;
  color: var(--wwl-warn-on) !important;
}

:root[data-theme="dark"] .badge-primary,
:root[data-theme="dark"] .badge-info {
  background-color: var(--wwl-accent) !important;
  color: var(--wwl-accent-text) !important;
}

/* Pagination */
:root[data-theme="dark"] .page-link {
  background-color: var(--wwl-surface);
  border-color: var(--wwl-border);
  color: var(--wwl-link);
}

:root[data-theme="dark"] .page-link:hover {
  background-color: var(--wwl-surface-2);
  color: var(--wwl-link-hover);
}

:root[data-theme="dark"] .page-item.active .page-link {
  background-color: var(--wwl-accent);
  border-color: var(--wwl-accent);
  color: var(--wwl-accent-text);
}

:root[data-theme="dark"] .page-item.disabled .page-link {
  background-color: var(--wwl-surface-2);
  color: var(--wwl-text-muted);
}

/* Light surfaces with a hardcoded background and no token of their own.
   Each of these was found by check-dark-contrast.mjs as a REGRESSION: text
   readable in light, unreadable in dark, because the surface stayed light
   while the text followed the theme. They are listed individually rather than
   swept with a wildcard so that adding one is a deliberate act with a
   measurement behind it. */
:root[data-theme="dark"] .wf-capture-drawer,     /* #eef2ff */
:root[data-theme="dark"] .wf-rw-reward-card,     /* #ffffff */
:root[data-theme="dark"] .wf-rw-flow__step,      /* #f9fafb */
:root[data-theme="dark"] .faqFilterBanner {      /* #ffffff */
  background: var(--wwl-surface);
  border-color: var(--wwl-border);
  color: var(--wwl-text);
}

/* Bootstrap's .bg-light utility carries !important, so this has to as well. */
:root[data-theme="dark"] .bg-light {
  background-color: var(--wwl-surface-2) !important;
  color: var(--wwl-text);
}

/* .bg-white and .text-dark, the two utilities .bg-light's rule should always
   have been written beside. The landing page leans on them heavily -- a
   1.7-million-px2 `section.bg-white` was the largest light slab anywhere in the
   app -- and `.text-dark` is Bootstrap's #343a40, which is not a color any dark
   surface can carry. Both carry !important upstream, so both do here. */
:root[data-theme="dark"] .bg-white {
  background-color: var(--wwl-surface) !important;
  color: var(--wwl-text);
}

:root[data-theme="dark"] .text-dark {
  color: var(--wwl-text) !important;
}

/* Card titles inside the surfaces darkened above -- each hardcodes a near-black
   that lands within a point of the new card color (#1f2937 on #1e293b reads
   1:1). Darkening a surface always means checking what was written on it. */
:root[data-theme="dark"] .wf-rw-reward-card__title,
:root[data-theme="dark"] .wf-rw-flow__step-title {
  color: var(--wwl-text);
}

/* Four places use --wf-accent as a FILL with `color:#fff` on top, while
   everything else uses it as text. Those two jobs want opposite lightnesses on
   a dark background: text has to be light to be read, a fill has to be dark
   enough for white to sit on it. The remap above chose the text reading
   (#c4b5fd), which left white-on-light-purple at 1.85:1 on the active nav
   link. Rather than compromise the token, the four fills name the platform
   accent, which is checked as a pair. Found by measurement; the full list is
   `grep -rn "background: var(--wf-accent)" app/assets/css/`. */
:root[data-theme="dark"] .wf-nav__link.is-active,
:root[data-theme="dark"] .wf-picker-add:hover:not(:disabled),
:root[data-theme="dark"] .wf-journal-nav-badge {
  background: var(--wwl-accent);
  color: var(--wwl-accent-text);
  border-color: var(--wwl-accent);
}

/* The four remaining light slabs, and the text written on them.
   These read fine in dark mode -- dark text on a light panel is legible, so
   the contrast check passes them -- but they are large pale rectangles on an
   otherwise dark page, which is the thing the operator asked for dark mode to
   stop. Each names its own text colors, so the panel and its type are
   converted together; converting only the background is what produced every
   regression above. */
:root[data-theme="dark"] .wf-insight {
  background: var(--wwl-surface-2);
  border-color: var(--wwl-border);
}

:root[data-theme="dark"] .wf-insight__hd,
:root[data-theme="dark"] .wf-insight__body strong {
  color: var(--wwl-link);
}

:root[data-theme="dark"] .wf-insight__body {
  color: var(--wwl-text);
}

:root[data-theme="dark"] .wf-research-banner,
:root[data-theme="dark"] .wf-quotes-carousel {
  background: var(--wwl-surface-2);
  border-color: var(--wwl-border);
  color: var(--wwl-text);
}

/* A gradient, so the contrast check skips it on purpose -- it cannot know
   which color sits under a given glyph. Converted by eye and by the same
   token pair the rest of the palette uses. */
:root[data-theme="dark"] .wf-rw-level-hero {
  background: linear-gradient(135deg, #1e1b4b, #172554);
  border-color: var(--wwl-border);
}

:root[data-theme="dark"] .wf-rw-level-hero__title,
:root[data-theme="dark"] .wf-rw-level-hero__points {
  color: var(--wwl-text);
}

/* ---------------------------------------------------------------------
   The dashboard's own card system.

   Reported by the operator: "the dashboard's dark mode does not look very
   dark". It was right -- the container darkened but every .cp-card on it
   stayed #fff, so the most-used page in the app read as white panels on a
   dark ground. The styles are an inline <style> block in
   views/dashboard/dashboard_customizer.php with hardcoded hexes and no
   tokens of its own, so unlike .wf-shell there is nothing to remap and the
   surfaces have to be named.

   The purple chips (#ede9fe fill, #7c3aed text) are the ones worth care:
   keeping their light fill would leave lilac confetti scattered over a dark
   card, so they take the accent-soft pair, which is contrast-checked.
   --------------------------------------------------------------------- */
:root[data-theme="dark"] .cp-card {
  background: var(--wwl-surface);
  border-color: var(--wwl-border);
  color: var(--wwl-text);
}

:root[data-theme="dark"] .cp-card__title,
:root[data-theme="dark"] .cp-feed-item__time {
  color: var(--wwl-text-muted);
}

:root[data-theme="dark"] .cp-goal.is-open {
  background: var(--wwl-surface-2);
  border-color: var(--wwl-accent);
}

:root[data-theme="dark"] .cp-goal__why {
  background: var(--wwl-accent-soft);
  color: var(--wwl-accent-soft-text);
}

:root[data-theme="dark"] .cp-goal__num,
:root[data-theme="dark"] .cp-action__pts,
:root[data-theme="dark"] .cp-goal-map-btn {
  background: var(--wwl-accent-soft);
  color: var(--wwl-accent-soft-text);
  border-color: var(--wwl-border);
}

:root[data-theme="dark"] .cp-goal-map-btn:hover,
:root[data-theme="dark"] .cp-goal__edit:hover,
:root[data-theme="dark"] .cp-action--link:hover,
:root[data-theme="dark"] .cp-service:hover {
  background: var(--wwl-surface-3);
  color: var(--wwl-text);
}

:root[data-theme="dark"] .cp-lb-you {
  background: var(--wwl-surface-3);
}

:root[data-theme="dark"] .cp-checkin-btn--done {
  background: var(--wwl-success-soft);
  color: var(--wwl-success-soft-text);
  border-color: var(--wwl-success);
}

:root[data-theme="dark"] .cp-goal__edit {
  color: var(--wwl-text-muted);
}

/* Bootstrap's contextual table rows: pale fills carrying dark text, which
   survive into dark mode as bright bands. Same treatment as the alerts. */
:root[data-theme="dark"] .table-info,
:root[data-theme="dark"] .table-info > td,
:root[data-theme="dark"] .table-info > th {
  background-color: var(--wwl-accent-soft) !important;
  color: var(--wwl-accent-soft-text) !important;
}

:root[data-theme="dark"] .table-warning,
:root[data-theme="dark"] .table-warning > td,
:root[data-theme="dark"] .table-warning > th {
  background-color: var(--wwl-warn-soft) !important;
  color: var(--wwl-warn-soft-text) !important;
}

:root[data-theme="dark"] .table-danger,
:root[data-theme="dark"] .table-danger > td,
:root[data-theme="dark"] .table-danger > th {
  background-color: var(--wwl-danger-soft) !important;
  color: var(--wwl-danger-soft-text) !important;
}

:root[data-theme="dark"] .table-success,
:root[data-theme="dark"] .table-success > td,
:root[data-theme="dark"] .table-success > th {
  background-color: var(--wwl-success-soft) !important;
  color: var(--wwl-success-soft-text) !important;
}

/* The text written on those cards.
   Darkening .cp-card is only half the job -- the rule this file keeps
   restating. Its contents carry mid-tone colors that were chosen against
   white: greys for labels, and accent/status colors for numbers.

   The inline ones are matched on the hex in the style attribute itself.
   That is unusual enough to justify: these values live in inline styles
   inside PHP-generated markup, which no stylesheet rule can reach without
   !important, and matching the literal value keeps each override pinned to
   exactly the elements that carry it rather than to every element of that
   tag. It fails safe -- change the hex in the view and the rule stops
   matching, which check-dark-contrast.mjs reports on the next run rather
   than leaving a silent mismatch. The durable fix is tokens in the view;
   that is a dashboard change, not a palette one. */
:root[data-theme="dark"] .cp-card .cp-action__text,
:root[data-theme="dark"] .cp-card .cp-count,
:root[data-theme="dark"] .cp-card strong {
  color: var(--wwl-text);
}

:root[data-theme="dark"] .cp-card [style*="color:#6b7280"],
:root[data-theme="dark"] .cp-card [style*="color: #6b7280"] {
  color: var(--wwl-text-muted) !important;
}

:root[data-theme="dark"] .cp-card [style*="color:#7c3aed"],
:root[data-theme="dark"] .cp-card [style*="color: #7c3aed"] {
  color: var(--wwl-link) !important;
}

:root[data-theme="dark"] .cp-card [style*="color:#dc2626"],
:root[data-theme="dark"] .cp-card [style*="color: #dc2626"] {
  color: var(--wwl-streak) !important;
}

:root[data-theme="dark"] .cp-card [style*="color:#16a34a"],
:root[data-theme="dark"] .cp-card [style*="color: #16a34a"] {
  color: var(--wwl-success-soft-text) !important;
}

:root[data-theme="dark"] .cp-card [style*="color:#d97706"],
:root[data-theme="dark"] .cp-card [style*="color: #d97706"] {
  color: var(--wwl-points) !important;
}

/* The stat tiles inside those cards set their own light fills inline, so
   the .cp-card background above never reached them. Recoloring their
   labels without this left gray-on-pale-green at 2.45:1 -- this file's own
   rule broken by this file, and caught by check-dark-contrast.mjs on the
   next run rather than by anyone looking. Surface and text, together. */
:root[data-theme="dark"] .cp-card [style*="background:#f0fdf4"] {
  background: var(--wwl-success-soft) !important;
}

:root[data-theme="dark"] .cp-card [style*="background:#fef3c7"] {
  background: var(--wwl-warn-soft) !important;
}

:root[data-theme="dark"] .cp-card [style*="background:#ede9fe"] {
  background: var(--wwl-accent-soft) !important;
}

/* The two the operator spotted after the first dashboard pass: the goal rows
   in Legacy Goals and the pills in Platform Services. Both sit on #f9fafb
   with dark text, so they stay perfectly READABLE in dark mode and the
   contrast check has nothing to report -- they are simply white slabs on a
   dark page. That is the gap the light-surface sweep in
   check-dark-contrast.mjs now closes, so the next one of these is found by a
   run rather than by someone looking at a screenshot. */
:root[data-theme="dark"] .cp-goal {
  background: var(--wwl-surface-2);
  border-color: var(--wwl-border);
}

:root[data-theme="dark"] .cp-goal:hover {
  border-color: var(--wwl-accent);
}

:root[data-theme="dark"] .cp-goal__title {
  color: var(--wwl-text);
}

:root[data-theme="dark"] .cp-goal__why-empty {
  color: var(--wwl-text-muted);
}

:root[data-theme="dark"] .cp-service {
  background: var(--wwl-surface-2);
  border-color: var(--wwl-border);
  color: var(--wwl-text);
}

:root[data-theme="dark"] .cp-service i {
  color: var(--wwl-text-muted);
}

:root[data-theme="dark"] .cp-service:hover {
  background: var(--wwl-surface-3);
  border-color: var(--wwl-accent);
  color: var(--wwl-link);
}

:root[data-theme="dark"] .cp-service:hover i {
  color: var(--wwl-link);
}

/* Selectize, the dropdown widget loaded from a CDN on /faq, /profile,
   /fundraisers, /admin and the game forms. Its stylesheet is not ours to
   edit, so it is themed from here. Found by the light-surface sweep rather
   than by anyone reporting it -- 25,600px2 of #f9f9f9 sitting on a dark
   page. The dropdown and the selected-item chips need naming too: the field
   is the part you notice, and the menu is the part you then cannot read. */
:root[data-theme="dark"] .selectize-input,
:root[data-theme="dark"] .selectize-input.focus,
:root[data-theme="dark"] .selectize-control.single .selectize-input,
:root[data-theme="dark"] .selectize-control.multi .selectize-input {
  background: var(--wwl-input-bg) !important;
  color: var(--wwl-input-text) !important;
  border-color: var(--wwl-border-strong) !important;
  box-shadow: none !important;
}

:root[data-theme="dark"] .selectize-input input,
:root[data-theme="dark"] .selectize-input > input {
  color: var(--wwl-input-text) !important;
}

:root[data-theme="dark"] .selectize-input.has-items > div,
:root[data-theme="dark"] .selectize-control.multi .selectize-input > div {
  background: var(--wwl-accent-soft) !important;
  color: var(--wwl-accent-soft-text) !important;
  border-color: var(--wwl-accent) !important;
}

:root[data-theme="dark"] .selectize-dropdown,
:root[data-theme="dark"] .selectize-dropdown-content {
  background: var(--wwl-surface) !important;
  color: var(--wwl-text) !important;
  border-color: var(--wwl-border) !important;
}

:root[data-theme="dark"] .selectize-dropdown .option,
:root[data-theme="dark"] .selectize-dropdown .optgroup-header {
  color: var(--wwl-text) !important;
}

:root[data-theme="dark"] .selectize-dropdown .active {
  background: var(--wwl-surface-2) !important;
  color: var(--wwl-text) !important;
}

:root[data-theme="dark"] .selectize-control.single .selectize-input:after {
  border-top-color: var(--wwl-text-muted) !important;
}

/* The notification bell, and any other bare icon in the header.
   `.ringBell` computes to #1f1f1f in BOTH themes -- it inherits from
   `nav li a { color: #1f1f1f !important }` and is not inside an anchor, so
   the nav-text rule above never reached it. On the dark bar that is roughly
   1.05:1: the bell was there and could not be seen.

   Missed by every check until now for an instructive reason: the rendered
   contrast pass only inspects elements that have TEXT, and an icon's glyph
   lives in a ::before pseudo-element. Icons are content. The pass now
   includes them. */
:root[data-theme="dark"] #main-nav .ringBell,
:root[data-theme="dark"] #main-nav .fa:not(.wf-hub__btn *),
:root[data-theme="dark"] #main-nav .fas:not(.wf-hub__btn *),
:root[data-theme="dark"] #main-nav .far:not(.wf-hub__btn *) {
  color: var(--wwl-nav-text);
}

/* The hub keeps the brand accent -- it is the one control meant to draw the
   eye, and the accent clears AA on the nav background. */
:root[data-theme="dark"] .wf-hub__btn i {
  color: var(--wwl-accent-soft-text);
}

/* Icons found by the sweep once it started looking at them.
   Two causes, both worth naming. Section titles set their own dark gray and
   so outrank the :where()-weighted heading rule above -- which is the rule
   working as intended, since :where() exists precisely so a considered color
   wins, but this one was considered against a white page. And the streak and
   points glyphs set a color of their own instead of inheriting the amber and
   red their labels already use, which are contrast-checked tokens. */
:root[data-theme="dark"] .wf-rw-section__title,
:root[data-theme="dark"] .wf-rw-section__title i {
  color: var(--wwl-text);
}

:root[data-theme="dark"] .wf-gam-points i,
:root[data-theme="dark"] .wf-gam-streak i,
:root[data-theme="dark"] .wf-hub__summary i {
  color: inherit;
}

/* =====================================================================
 * Round two — the surfaces the first QA pass reached and this one did not.
 *
 * Every block below answers a specific defect the operator found by looking
 * at a page nobody had checked. The pattern in all of them is the one this
 * file keeps restating and keeps getting caught by: a surface that declares
 * its own light background, with text that follows the theme. The palette
 * darkened the text and left the panel, which is strictly worse than not
 * theming the page at all.
 *
 * The durable change is not this list. It is that
 * `check-dark-contrast.mjs` now visits these routes and OPENS the two
 * modals, so the next one of these is a failing run rather than a
 * screenshot. Adding a page to that list is how a surface gets promoted
 * into what the palette claims to cover.
 * ===================================================================== */

/* ── The public landing page ──────────────────────────────────────────
   Reported as "some sections of the main page are still white". Two shapes:
   Bootstrap's .bg-white (handled with the utilities above) and three card
   systems that hardcode `background: white` in the view's own <style>. The
   studio section is the interesting one -- it is a PALE GRADIENT, so it is
   invisible to both checks: the contrast sweep skips gradients because it
   cannot know which color sits under a glyph, and the light-surface sweep
   only reads background-COLOR. It rendered near-white headings on a pale
   blue-gray wash. A gradient has to be converted by eye, and this is the
   argument for the operator's pass existing at all. */
:root[data-theme="dark"] .wwl-service-card,
:root[data-theme="dark"] .wwl-engage-card {
  background: var(--wwl-surface);
  border-color: var(--wwl-border);
  color: var(--wwl-text);
}

:root[data-theme="dark"] .wwl-service-card:hover,
:root[data-theme="dark"] .wwl-engage-card:hover {
  border-color: var(--wwl-accent);
}

:root[data-theme="dark"] .wwl-venture-studio {
  background: linear-gradient(135deg, #111827 0%, #1e293b 100%);
}

:root[data-theme="dark"] .wwl-highlight-item p,
:root[data-theme="dark"] .wwl-engage-card li {
  color: var(--wwl-text-muted);
}

/* The pipeline step numbers are white discs carrying #667eea. On a dark
   section that reads as confetti rather than as a numbered list. */
:root[data-theme="dark"] .wwl-pipeline__number {
  background: var(--wwl-accent-soft);
  color: var(--wwl-accent-soft-text);
}

/* ── winFocus: Today, the board, and Goals ────────────────────────────
   "Several pages need dark mode applied more evenly (today, kanban, goals)."
   These views declare their palettes inside the PHP file rather than in
   winfocus.css, so the --wf-* remap above never reached them. */
:root[data-theme="dark"] .tf-plan,
:root[data-theme="dark"] .tf-avoid {
  background: var(--wwl-surface);
  border-color: var(--wwl-border);
  color: var(--wwl-text);
}

:root[data-theme="dark"] .tf-plan-item,
:root[data-theme="dark"] .cp-feed-item {
  border-bottom-color: var(--wwl-border);
}

:root[data-theme="dark"] .tf-plan-item__text {
  color: var(--wwl-text);
}

:root[data-theme="dark"] .tf-plan__title,
:root[data-theme="dark"] .tf-plan__cap,
:root[data-theme="dark"] .tf-plan__empty {
  color: var(--wwl-text-muted);
}

/* The freeform "add a task" box: a dashed input on #fafafa. Set as a pair --
   the border is dashed and decorative, the background and text are not. */
:root[data-theme="dark"] .tf-plan-freeform input {
  background: var(--wwl-input-bg);
  color: var(--wwl-input-text);
  border-color: var(--wwl-border-strong);
}

/* The board's onboarding screen, which is what an empty board shows. Its
   headline carries an inline color, so it needs !important -- the same
   reason .card-title above does. */
:root[data-theme="dark"] .wf-onboard__headline,
:root[data-theme="dark"] .wf-onboard__step-title {
  color: var(--wwl-text) !important;
}

:root[data-theme="dark"] .wf-onboard__sub,
:root[data-theme="dark"] .wf-onboard__step-desc {
  color: var(--wwl-text-muted);
}

:root[data-theme="dark"] .wf-onboard__step {
  border-bottom-color: var(--wwl-border);
}

:root[data-theme="dark"] .wf-onboard__step-num,
:root[data-theme="dark"] .wf-onboard__step-action {
  background: var(--wwl-accent-soft);
  color: var(--wwl-accent-soft-text);
  border-color: var(--wwl-accent);
}

:root[data-theme="dark"] .wf-onboard__step-action:hover {
  background: var(--wwl-surface-3);
  color: var(--wwl-text);
}

/* The quotes carousel on Goals. `.wf-quotes-carousel` was already darkened
   above; its contents were not, which is the half-job this file exists to
   catch. 36 quote strings at 1.22:1. */
:root[data-theme="dark"] .wf-quote__text {
  color: var(--wwl-text);
}

:root[data-theme="dark"] .wf-quote__attr {
  color: var(--wwl-text-muted);
}

:root[data-theme="dark"] .wf-quotes-carousel__arrow {
  color: var(--wwl-text-muted);
  border-color: var(--wwl-border-strong);
}

/* The research banner's emphasis runs. The banner takes --wwl-surface-2 from
   the block above and its body text follows, but <strong> and <em> inside it
   name near-black colors of their own. */
:root[data-theme="dark"] .wf-research-banner strong,
:root[data-theme="dark"] .wf-research-banner em,
:root[data-theme="dark"] .wf-research-banner p {
  color: var(--wwl-text);
}

/* ── The admin bar ────────────────────────────────────────────────────
   "In Admin, the Events page does not show this row correctly." A textbook
   instance of the failure this file warns about: the palette recolored
   `nav li a` to near-white and #adminbar kept `background-color:#f7f7f7
   !important`, so the whole submenu row rendered at 1.15:1 -- present, and
   unreadable. It is an ID with !important, so this needs both to win. */
:root[data-theme="dark"] #adminbar {
  background-color: var(--wwl-surface-2) !important;
  border-bottom: 1px solid var(--wwl-border);
}

/* ── The game detail page ─────────────────────────────────────────────
   "The 'Share' word is barely seen, and the tabs are still bright white."
   Two different causes worth separating. Share is a <button>: buttons do
   not inherit color from body the way the anchors beside them do, so it
   kept the UA's near-black while its neighbors followed the theme -- which
   is why one control in a row of three was the one that disappeared. The
   tabs simply hardcode #eee and white. */
:root[data-theme="dark"] .share-btn-class {
  color: var(--wwl-text) !important;
  border-color: var(--wwl-border-strong) !important;
}

:root[data-theme="dark"] #chartTabs .nav-link,
:root[data-theme="dark"] #playerChartTabs .nav-link,
:root[data-theme="dark"] #prizeChartTabs .nav-link,
:root[data-theme="dark"] #aboutgame .nav-link {
  background-color: var(--wwl-surface-2);
  color: var(--wwl-text-muted);
  border-color: var(--wwl-border);
}

/* The active tab is meant to read as continuous with the panel below it,
   which is what its white bottom border does in light mode. Same trick,
   painted with the surface it now sits on. */
:root[data-theme="dark"] #chartTabs .nav-link.active,
:root[data-theme="dark"] #playerChartTabs .nav-link.active,
:root[data-theme="dark"] #prizeChartTabs .nav-link.active,
:root[data-theme="dark"] #aboutgame .nav-link.active {
  background-color: var(--wwl-surface);
  color: var(--wwl-text);
  border-color: var(--wwl-border);
  border-bottom-color: var(--wwl-surface);
}

/* flexslider ships a white frame around every gallery. Its stylesheet is
   vendor code, so it is themed from here like selectize. */
:root[data-theme="dark"] .flexslider {
  background: var(--wwl-surface);
  border-color: var(--wwl-surface);
}

/* ── The winFocus modals, the daily journal among them ────────────────
   "In dark mode the Journal looks bad." One line causes all of it:
   `.wf-modal__card` hardcodes `background:#fff` instead of the --wf-card
   token every other winFocus surface uses. Its contents were already
   correct -- the labels take --wf-ink, which the remap sets to near-white --
   so the whole modal was near-white type on a white card. Naming the token
   here fixes every wf modal at once rather than the journal alone, which is
   the point of the remap. */
:root[data-theme="dark"] .wf-modal__card {
  background: var(--wf-card);
  color: var(--wf-ink);
}

:root[data-theme="dark"] .wf-journal-mood__btn {
  background: var(--wwl-surface-2);
  border-color: var(--wwl-border);
}

:root[data-theme="dark"] .wf-journal-mood__btn:hover,
:root[data-theme="dark"] .wf-journal-mood__btn.active {
  background: var(--wwl-surface-3);
  border-color: var(--wwl-accent);
}

/* The border carries !important in winfocus-journal.css, so this must too. */
:root[data-theme="dark"] .wf-journal-textarea {
  background: var(--wwl-input-bg);
  color: var(--wwl-input-text);
  border-color: var(--wwl-border-strong) !important;
}

/* ── Help Us Improve ──────────────────────────────────────────────────
   "The modal does not look like dark mode was applied." It is a
   self-contained light design in the view's own <style> -- white body, pale
   grey footer, #f9fafb score cells and category chips. The gradient header
   and the submit button are already dark-safe and are deliberately left
   alone. Every selector here is one class deeper than the rule it beats, so
   none of them need !important. */
:root[data-theme="dark"] .feedbackClass .modal-body {
  background: var(--wwl-surface);
  color: var(--wwl-text);
}

:root[data-theme="dark"] .feedbackClass .modal-body p,
:root[data-theme="dark"] .feedbackClass .modal-body label {
  color: var(--wwl-text);
}

:root[data-theme="dark"] .feedbackClass .modal-footer {
  background: var(--wwl-surface-2);
  border-top-color: var(--wwl-border);
}

:root[data-theme="dark"] .feedbackClass .tab-bg {
  background: var(--wwl-surface-2);
  border-color: var(--wwl-border);
}

:root[data-theme="dark"] .feedbackClass .select-off td,
:root[data-theme="dark"] .feedbackClass .nav-td {
  background: var(--wwl-surface-2);
  border-color: var(--wwl-border);
  color: var(--wwl-text-muted);
}

:root[data-theme="dark"] .feedbackClass .select-off td:hover,
:root[data-theme="dark"] .feedbackClass .nav-td:hover,
:root[data-theme="dark"] .feedbackClass .nav-td.active {
  background: var(--wwl-accent-soft);
  color: var(--wwl-accent-soft-text);
}

:root[data-theme="dark"] .feedbackClass .heading,
:root[data-theme="dark"] .feedbackClass .other-heading,
:root[data-theme="dark"] .feedbackClass .feedback-sub-div a {
  color: var(--wwl-link);
}

:root[data-theme="dark"] .feedbackClass .feedback-text {
  background: var(--wwl-input-bg);
  color: var(--wwl-input-text);
  border-color: var(--wwl-border-strong);
}

:root[data-theme="dark"] .feedbackClass .feedBackImageBlock {
  background: var(--wwl-surface-2);
  border-color: var(--wwl-border-strong);
  color: var(--wwl-text-muted);
}

:root[data-theme="dark"] .feedbackClass .cancel-btn {
  border-color: var(--wwl-border-strong) !important;
  color: var(--wwl-text) !important;
}

:root[data-theme="dark"] .feedbackClass .cancel-btn:hover {
  background: var(--wwl-surface-3) !important;
  color: var(--wwl-text) !important;
}

/* ── The dashboard's applications and activity feed ───────────────────
   "The titles of the applications and the Progressions are too hard to
   read." Both were MISSED BY THE CHECK rather than missed by the palette,
   and the reason is worth recording: the check signs in as a test account
   with no applications and no recent activity, so neither block was in the
   DOM it swept. A rendered check only sees what the account it uses can
   see. That is the standing limit of every measurement in this issue.

   `.cp-action__text` already had a rule here. It lost to the inline
   `color:#374151` the view writes on the same element -- a rule that is
   correct and outranked reads exactly like a rule that was never written,
   which is why the hex is matched directly below. */
:root[data-theme="dark"] .cp-card .cp-action__text,
:root[data-theme="dark"] .cp-feed-item__action {
  color: var(--wwl-text) !important;
}

:root[data-theme="dark"] .cp-card [style*="color:#374151"],
:root[data-theme="dark"] .cp-card [style*="color: #374151"] {
  color: var(--wwl-text) !important;
}

:root[data-theme="dark"] .cp-card [style*="color:#9ca3af"],
:root[data-theme="dark"] .cp-card [style*="color: #9ca3af"] {
  color: var(--wwl-text-muted) !important;
}

/* The application rows draw their own hairline border on #eef0f3. */
:root[data-theme="dark"] .cp-card [style*="border:1px solid #eef0f3"] {
  border-color: var(--wwl-border) !important;
}

/* ── The last few, each found by the second run rather than by looking ──
   Kept together because they share one lesson: darkening a surface is what
   EXPOSES the text on it. Every entry below reads perfectly in light mode
   and became unreadable the moment the panel behind it went dark, which is
   why the fix and the surface always ship in the same commit. */

/* Service and engagement cards carry bare <h5> headings that inherit a
   near-black from style.css, and that beats the :where()-weighted heading
   rule by design. Darkening the card is what made them a problem. */
:root[data-theme="dark"] .wwl-service-card h5,
:root[data-theme="dark"] .wwl-engage-card h4,
:root[data-theme="dark"] .wwl-engage-card h5 {
  color: var(--wwl-text);
}

/* The winFocus nav pill's hover fill: #eef1f5, with the link text following
   the theme to near-white. Hovering a nav item made it vanish. */
:root[data-theme="dark"] .wf-nav__link:hover {
  background: var(--wwl-surface-2);
  color: var(--wwl-text);
}

/* Two links that name the light-mode brand purple directly. #7c3aed is a
   FILL color in this palette, not a text color -- it reads 3.13:1 on the
   page background, which is why --wwl-link exists as a separate token. */
:root[data-theme="dark"] .tf-empty-goal a,
:root[data-theme="dark"] .tf-avoid a[style*="color:#7c3aed"] {
  color: var(--wwl-link) !important;
}

/* The blue note inside Help Us Improve sets its fill and border inline. */
:root[data-theme="dark"] .feedbackClass .alert-light[style*="background:#f0f4ff"] {
  background: var(--wwl-accent-soft) !important;
  border-color: var(--wwl-accent) !important;
  color: var(--wwl-accent-soft-text);
}

/* The game page's raised-amount readout and the beneficiary name: #276EF1
   on the dark page is 3.9:1, just under the 4.5 a body-size string needs.
   Under, not far under -- which is the case for measuring rather than
   eyeballing, because 3.9 looks fine to anyone who already knows what the
   words say. */
:root[data-theme="dark"] .progamtdisplay,
:root[data-theme="dark"] .detailtitle strong {
  color: var(--wwl-link);
}

/* The goals empty state writes its headline and body color inline. Matched
   on the literal hex for the reason given further up this file: an inline
   style is unreachable without !important, and pinning to the value keeps
   the override on exactly the elements that carry it. */
:root[data-theme="dark"] [style*="color:#0f0a2e"] {
  color: var(--wwl-text) !important;
}

:root[data-theme="dark"] [style*="color:#6b7280"] {
  color: var(--wwl-text-muted) !important;
}

/* Same, for the indigo the feedback modal writes on its points note. */
:root[data-theme="dark"] .feedbackClass [style*="color:#4F46E5"] {
  color: var(--wwl-accent-soft-text) !important;
}

/* Icons inside the wishlist and share controls. The controls themselves are
   handled above; an icon is a child element and inherits nothing when the
   rule it would inherit from was outranked. */
:root[data-theme="dark"] .share-btn-class i {
  color: inherit !important;
}
