/**
 * lbai-tokens.css — semantic colour token system for light and dark mode.
 *
 * ─────────────────────────────────────────────────────────────────────────────────────────────
 * WHY THIS FILE EXISTS
 * ─────────────────────────────────────────────────────────────────────────────────────────────
 * Measured inventory of the first-party components:
 *
 *   body.dark-mode rules   702 across 13 stylesheets, with NO shared vocabulary
 *   of which frozen        299  (single-listing-v2 113, dashboard-ui 86, core 42,
 *                                dashboard 30, header.php 28)
 *   hardcoded white ink    215 declarations
 *   hardcoded white bg     184 declarations
 *   plugin dark support    ZERO — listingpro-custom-features has 81 white inks, 37 white
 *                          backgrounds and not one dark-mode rule, and it renders booking
 *                          cards and status badges
 *
 * Thirteen stylesheets each invented their own dark palette, so "different components use
 * conflicting dark-mode rules" is literally true. This file introduces the one vocabulary
 * they can all agree on, and fixes the structural cause rather than the symptoms.
 *
 * ─────────────────────────────────────────────────────────────────────────────────────────────
 * THE STRUCTURAL CAUSE, AND THE ONE RULE THAT REPLACES IT
 * ─────────────────────────────────────────────────────────────────────────────────────────────
 * header.php prints, inline in <head>, a colour-only rule with !important:
 *
 *     body.dark-mode h1..h4, p, span, label, .ail-tab-btn, .ail-nav-item,
 *     .ail-quick-action-item { color: var(--text-primary) !important; }
 *
 * In dark mode --text-primary is near-white. The rule sets no background, so every one of
 * those elements sitting on a surface that stayed light becomes near-white on near-white —
 * and being !important, a component cannot opt out by restating its own ink. That single
 * declaration is the origin of the "white text on white surface" class of bug, the
 * unreadable status labels, and most of the invisible icons.
 *
 * header.php is FROZEN, so the rule cannot be removed. It is instead SUPERSEDED, once, by a
 * rule that is context-aware because it reads a token instead of naming a colour:
 *
 *     html body.dark-mode :is(h1..h4, p, span, label, …) { color: var(--lbai-text) !important; }
 *
 * That wins on SPECIFICITY, not source order: header.php's selector is (0,1,2) — one class,
 * two type selectors — and prefixing `html` makes this one (0,1,3). No source-order fight, no
 * dependence on enqueue timing.
 *
 * Because --lbai-text is a CUSTOM PROPERTY it INHERITS, so any component that declares
 * itself a pale surface re-points the token for its whole subtree in one line:
 *
 *     body.dark-mode .some-pale-chip { --lbai-text: var(--lbai-text-on-pale); }
 *
 * That is the difference between a token system and an override list: N components need N
 * one-line surface declarations, not N × M selector overrides for every text element inside
 * them. This is explicitly NOT `* { color: white !important }` — nothing here forces a colour,
 * it forces a *token*, and the token is decided by the surface the text actually sits on.
 *
 * ─────────────────────────────────────────────────────────────────────────────────────────────
 * SCOPE DISCIPLINE
 * ─────────────────────────────────────────────────────────────────────────────────────────────
 * Light mode is defined with the SAME semantic tokens but the values are the product's
 * existing ones, so light rendering is unchanged. Brand colours are reused, never redesigned.
 * No frozen file is modified. Status hues keep their meaning; only the foreground/background
 * pairing is corrected.
 *
 * @package listing-by-atul-ingale
 */

/* =====================================================================================
   1. LIGHT TOKENS — the product's existing values, given semantic names.
   =====================================================================================
   Values are taken from what the product already renders (style.css :root, core.css,
   dashboard-ui.css) so adopting the vocabulary changes nothing visually in light mode.
   ===================================================================================== */
:root {
    /* Surfaces, lightest to most elevated. */
    --lbai-bg: #f5f6fb;
    --lbai-surface: #ffffff;
    --lbai-surface-2: #f8fafc;
    --lbai-surface-3: #f1f5f9;

    /* Ink. --lbai-text is the inheritable default; -strong/-muted/-subtle are the ladder. */
    --lbai-text: #0f172a;
    --lbai-text-strong: #0b1220;
    --lbai-text-muted: #475569;
    --lbai-text-subtle: #64748b;

    /* The ink to use when text sits on a deliberately PALE surface in either mode. */
    --lbai-text-on-pale: #0f172a;
    /* The ink to use on a saturated brand/status fill. */
    --lbai-text-on-accent: #ffffff;

    --lbai-border: #e2e8f0;
    --lbai-border-strong: #cbd5e1;

    --lbai-link: #6d5efc;
    --lbai-link-hover: #574bd6;

    /* A FILL is not a link colour, and conflating the two was measurably wrong: using the
       dark-mode link tint as the active-pill background put white on a light purple at
       2.36:1. Accent tokens exist for saturated fills that carry white text. */
    --lbai-accent: #6d5efc;
    --lbai-accent-strong: #574bd6;

    --lbai-icon: #475569;
    --lbai-icon-muted: #94a3b8;

    --lbai-input-bg: #ffffff;
    --lbai-input-text: #0f172a;
    --lbai-input-border: #cbd5e1;
    --lbai-placeholder: #94a3b8;

    --lbai-focus: #6d5efc;
    --lbai-shadow: 0 1px 3px rgba(15, 23, 42, .08);

    /* Status: an ink + a surface that are guaranteed to pair. Hues are the product's own. */
    --lbai-success: #15803d;
    --lbai-success-bg: #dcfce7;
    --lbai-warning: #92400e;
    --lbai-warning-bg: #fef3c7;
    --lbai-danger: #b91c1c;
    --lbai-danger-bg: #fee2e2;
    --lbai-info: #1d4ed8;
    --lbai-info-bg: #dbeafe;
    --lbai-neutral: #475569;
    --lbai-neutral-bg: #f1f5f9;

    --lbai-disabled-bg: #f1f5f9;
    --lbai-disabled-text: #94a3b8;
}

/* =====================================================================================
   2. DARK TOKENS — a coherent palette, not an inversion.
   =====================================================================================
   Built on the dark values the product already approved (page #1a1a2e, card #16213e,
   raised #1f2a47, field #101a30, ink #f1f5f9) so this is a consolidation of existing
   decisions rather than a new theme. The admin-configurable emitter may override the first
   few at runtime; every value below is a fallback that is already AA-compliant.

   Status pairs are re-derived for dark: the HUE is preserved so meaning is unchanged, but
   the surface becomes a low-alpha tint of the hue and the ink becomes a light tint of it.
   That is what makes Confirmed / Pending / Rejected readable on a dark card instead of
   near-white on a pale pastel.
   ===================================================================================== */
body.dark-mode {
    --lbai-bg: #1a1a2e;
    --lbai-surface: #16213e;
    --lbai-surface-2: #1f2a47;
    --lbai-surface-3: #131c33;

    --lbai-text: #f1f5f9;
    --lbai-text-strong: #ffffff;
    --lbai-text-muted: #a5b4c8;
    --lbai-text-subtle: #8b9ab0;

    /* A pale surface still exists in dark mode (status chips, accent tiles). Text on it must
       go DARK, which is the opposite of what the forced rule in header.php would do. */
    --lbai-text-on-pale: #0f172a;
    --lbai-text-on-accent: #ffffff;

    --lbai-border: #24304d;
    --lbai-border-strong: #35446b;

    --lbai-link: #a99cff;
    --lbai-link-hover: #c4b5fd;

    /* The fill stays close to the brand but a shade deeper than the light-mode value, because
       white-on-fill must still clear AA: white on #6d5efc measures 4.49:1, white on #5b4bd8
       measures 6.1:1. Same hue family, no brand redesign. */
    --lbai-accent: #5b4bd8;
    --lbai-accent-strong: #4c3fbe;

    --lbai-icon: #cbd5e1;
    --lbai-icon-muted: #8b9ab0;

    --lbai-input-bg: #101a30;
    --lbai-input-text: #f1f5f9;
    --lbai-input-border: #35446b;
    --lbai-placeholder: #8b9ab0;

    --lbai-focus: #c4b5fd;
    --lbai-shadow: 0 1px 3px rgba(0, 0, 0, .5);

    --lbai-success: #6ee7a8;
    --lbai-success-bg: rgba(22, 163, 74, .22);
    --lbai-warning: #fcd34d;
    --lbai-warning-bg: rgba(245, 158, 11, .20);
    --lbai-danger: #fca5a5;
    --lbai-danger-bg: rgba(220, 38, 38, .22);
    --lbai-info: #93c5fd;
    --lbai-info-bg: rgba(59, 130, 246, .22);
    --lbai-neutral: #cbd5e1;
    --lbai-neutral-bg: rgba(255, 255, 255, .10);

    --lbai-disabled-bg: rgba(255, 255, 255, .06);
    /* #7c8aa5 measured 4.16:1 on the composited disabled surface — below AA. A disabled
       control must still be READ, so the ink is raised rather than the state being signalled
       by dimming alone. */
    --lbai-disabled-text: #94a3b8;
}

/* =====================================================================================
   3. THE SUPERSEDING INK RULE
   =====================================================================================
   One rule, token-driven, replacing header.php's literal near-white. `html` is present
   solely to raise specificity above (0,1,2) so this wins without depending on load order.

   Deliberately NOT applied to elements whose colour is legitimately owned by their own
   component: anything inside a saturated button, and anything that sets its own ink through
   a token below. Those cases re-point --lbai-text instead, which this rule then honours.
   ===================================================================================== */
/* Kept on ONE line deliberately: a newline between the compound and :is() is collapsed by
   formatters into `body.dark-mode:is(...)`, which asserts that <body> is itself a heading and
   therefore matches nothing. Do not reflow these two selectors. */
html body.dark-mode *:is(h1, h2, h3, h4, h5, h6, p, span, label, li, dt, dd, th, td, legend, strong, b, em, small, time, output, figcaption, caption, summary, blockquote, address, cite, .ail-tab-btn, .ail-nav-item, .ail-quick-action-item):not([style*="background"]) {
    color: var(--lbai-text) !important;
}

/* ── The inline-surface half. REWRITTEN from measured data, not from an assumption. ──
   The first version of this rule said "an inline background means a pale chip, so force dark
   ink". Enumerating every inline background literal actually emitted across the real rendered
   homepage and all eight dashboard tabs disproved that: of 41 distinct values, only 14 are pale
   opaque. The rest are DARK (#2563eb, #8224e3), MID (#ea580c, #ef4444, #3b82f6, #22c55e,
   #10b981) or translucent tints that composite DARK over a dark card — and those translucent
   ones are the most common of all (rgba(16,185,129,.1) alone appears 208 times).

   Forcing dark ink onto that majority is what produced the measured 1.31:1 on a "Completed"
   chip, 1.32:1 on "Pending" and 1.05:1 on the Coupon Manager heading icon. So the default for
   an inline-background element is now the ordinary LIGHT ink, and dark ink is applied only to
   the enumerated pale literals below. */
html body.dark-mode *:is(h1, h2, h3, h4, h5, h6, p, span, label, li, dt, dd, strong, b, em, small, time)[style*="background"] {
    color: var(--lbai-text) !important;
}

/* ── INLINE PALE FILLS ARE REPAINTED, NOT RE-INKED. ──
   The earlier design kept these pale and forced a dark ink back over them. Measuring the real DOM
   showed why that cannot hold: THIS layer repaints many of the same elements dark through the
   surface contracts in sections 4 and 14, so two of our own rules ended up disagreeing about
   whether one element was pale or dark. The measured result was dark ink on a dark card —

     div.ail-vendor-listing-card   inline background:#fff  repainted #16213e, ink #0f172a  1.12:1
     div.lbai-ver-summary          inline background:#f0fdf4 repainted #16213e, ink #0f172a 1.12:1
     div.ail-empty-state p         inline background:#fff  repainted #131c33, ink #0f172a  1.06:1

   So the classification problem is removed instead of refined: every pale inline fill is REPAINTED
   to a dark equivalent that preserves its HUE, and the ink stays the ordinary light token. One
   consequence is worth stating plainly, because it is why this converges — once no surface behind
   text is pale, header.php's forced near-white becomes CORRECT everywhere rather than something
   every component has to fight.

   Enumerated from the 41 distinct inline background values actually emitted, not pattern-matched:
   a substring test like [style*="background:#f"] would also catch #f59e0b and #ef4444, which are
   mid-tone fills that must keep white ink.

   ORDER IS LOAD-BEARING. [style*="background:#fff"] is a substring of "#fff7ed" and "#ffffff", so
   the longer literals are declared AFTER the shorter one and win on source order at equal
   specificity. Do not sort these selectors. */
html body.dark-mode [style*="background:#fff"],
html body.dark-mode [style*="background:#f1f5f9"],
html body.dark-mode [style*="background:#f8fafc"],
html body.dark-mode [style*="background:rgba(241, 245, 249, 0.8)"] {
    background-color: var(--lbai-surface) !important;
    border-color: var(--lbai-border) !important;
    --lbai-text: #f1f5f9;
}

html body.dark-mode [style*="background:#e5e7eb"] {
    background-color: var(--lbai-surface-2) !important;
    --lbai-text: #f1f5f9;
}

/* Hued pastels keep their hue as a translucent tint of the same colour. */
html body.dark-mode [style*="background:#f3f1ff"] {
    background-color: rgba(109, 94, 252, .20) !important;
    --lbai-text: #f1f5f9;
}

html body.dark-mode [style*="background:#eff6ff"],
html body.dark-mode [style*="background:#eef4ff"] {
    background-color: rgba(59, 130, 246, .20) !important;
    --lbai-text: #f1f5f9;
}

html body.dark-mode [style*="background:#ecfdf3"],
html body.dark-mode [style*="background:#dcfce7"],
html body.dark-mode [style*="background:#f0fdf4"] {
    background-color: rgba(34, 197, 94, .18) !important;
    --lbai-text: #f1f5f9;
}

html body.dark-mode [style*="background:#fef2f2"] {
    background-color: rgba(239, 68, 68, .18) !important;
    --lbai-text: #f1f5f9;
}

html body.dark-mode [style*="background:#fef9c3"],
html body.dark-mode [style*="background:#fff7ed"] {
    background-color: rgba(245, 158, 11, .18) !important;
    --lbai-text: #f1f5f9;
}

/* Longest-match last: #ffffff must not be caught by the #fff bucket's border colour only. */
html body.dark-mode [style*="background:#ffffff"] {
    background-color: var(--lbai-surface) !important;
    --lbai-text: #f1f5f9;
}

/* With no pale surface left behind text, the ink for these subtrees is the ordinary light token.
   Inline `color:` on descendants still has to be beaten, which is what the !important is for. */
html body.dark-mode [style*="background:#f"] *:not(a):not(svg):not(path):not([class*="status"]):not([class*="badge"]),
html body.dark-mode [style*="background:#e5e7eb"] *:not(a):not(svg):not(path),
html body.dark-mode [style*="background:rgba(241, 245, 249, 0.8)"] *:not(a):not(svg):not(path) {
    color: var(--lbai-text) !important;
}

/* Saturated inline fills that legitimately carry white: the glyph tiles inside the expiry
   badges, and anything a component has explicitly marked as an accent surface. */
html body.dark-mode .lpcf-badge-icon>span[style*="background"],
html body.dark-mode .lbai-on-accent[style*="background"] {
    color: var(--lbai-text-on-accent) !important;
}

/* ── THE INLINE-BACKGROUND EXEMPTION, and why it is the important half ──
   `:not([style*="background"])` above is not a detail. Measurement showed that the templates
   and the plugin emit dozens of chips as inline-styled spans that pair their OWN pale
   background with their OWN dark ink — `style="background:#dcfce7;color:#15803d"` for a
   Confirmed badge, for example. Those pairs are already correct and internally consistent.
   header.php's forced rule broke exactly those, because it replaced the authored dark ink
   with near-white and left the pale background alone: measured 1.00:1 and 1.02:1 on the
   plugin's Confirmed and Pending badges.

   The general principle, applied once here instead of chased per component: AN ELEMENT THAT
   DECLARES ITS OWN SURFACE ALSO OWNS ITS OWN FOREGROUND. Excluding those elements repairs
   every inline chip in the product — including ones in files this layer never names, and ones
   added in future — without a single per-component override. Components that need their
   pairing changed for dark mode still get it below, by class, deliberately. */

/* =====================================================================================
   4. SURFACE CONTRACTS
   =====================================================================================
   Each entry declares "this element is a surface of type X", and the inherited ink follows
   automatically for its entire subtree. This is the whole mechanism: one line per surface.
   ===================================================================================== */

/* ── 4a. Genuinely DARK surfaces in dark mode: keep the light ink, fix the background. ── */
body.dark-mode .ail-vendor-listing-card,
body.dark-mode .ail-module-card,
body.dark-mode .ail-result-card,
body.dark-mode .ail-review-card,
body.dark-mode .ail-booking-card,
body.dark-mode .ail-noteworthy-card,
body.dark-mode .ail-autocomplete-dropdown,
body.dark-mode .ail-single-bottom-bar,
body.dark-mode .lbaid-staff__card,
body.dark-mode .lbaid-lead,
body.dark-mode .lbaid-bk,
body.dark-mode .lbaid-doc,
body.dark-mode .lbaid-rev__card,
body.dark-mode .lbaid-avail,
body.dark-mode .lpcf-vm-card,
body.dark-mode .lpcf-stat-card,
body.dark-mode .lbai-ver-card {
    background-color: var(--lbai-surface) !important;
    border-color: var(--lbai-border) !important;
    --lbai-text: #f1f5f9;
}

/* Elevated: modals, drawers, dropdowns, sheets. One step lighter than a card so depth reads. */
body.dark-mode .ail-drawer-menu,
body.dark-mode .lbaid-modal,
body.dark-mode .lbaid-cxl__panel,
body.dark-mode .lbaid-cxl__dialog,
body.dark-mode .lbaid-bke__dialog,
body.dark-mode .ail-booking-sheet,
body.dark-mode .ail-modal-content,
body.dark-mode .ail-sheet-content {
    background-color: var(--lbai-surface-2) !important;
    border-color: var(--lbai-border-strong) !important;
    --lbai-text: #f1f5f9;
}

/* Recessed: quote blocks, job rows, empty states, table zebra. */
body.dark-mode .lbaid-lead__msg,
body.dark-mode .lbaid-lead__reply,
body.dark-mode .lbaid-rev__reply,
body.dark-mode .lbaid-staff__job,
body.dark-mode .lbaid-avail__day,
body.dark-mode .lbaid-empty,
body.dark-mode .ail-empty-state,
body.dark-mode .lbaid-crm__col {
    background-color: var(--lbai-surface-3) !important;
    border-color: var(--lbai-border) !important;
    --lbai-text: #f1f5f9;
}

/* ── 4b. Deliberately PALE surfaces that SURVIVE into dark mode. ──
   These keep their pastel fill on purpose (accent tiles, chips whose hue carries meaning).
   The one line re-points the inherited ink to dark, which is what the forced rule would
   otherwise have got wrong. This is the fix for "status labels become unreadable". */
/* NOTE: .ail-booking-status and the .lpcf-badge-* family are deliberately ABSENT here.
   They are owned by the status families in section 5, which give them a translucent tint of
   their own hue plus a light ink of the same hue. Listing them here as well produced a
   measured self-conflict — dark ink forced onto a translucent tint over a dark card, 1.61:1. */
/* REVISED. These were previously classified "pale surface, dark ink". Measurement on the real DOM
   showed that sections 14 and 16 of this file repaint several of them dark, so the pale
   classification contradicted the actual surface and produced dark-on-dark:

     div.lbaid-sub__feat.on      #0f172a on #1e2946   1.24:1   "Call Button"
     span.lbaid-badge.blue       #0f172a on #1d3463   1.47:1   "Top Rated"
     span.lbaid-mini__tag        #0f172a on #1d3463   1.47:1   "New"
     span.lbaid-doc__badge.red   #0f172a on #3d273f   1.33:1   "Expired"

   They now take a neutral dark tint with light ink; the hue variants in section 16 override this
   for the ones whose colour carries meaning. .lbai-on-pale is retained as the explicit opt-in for
   any surface that genuinely must stay pale in dark mode. */
body.dark-mode .lbaid-lead__tag,
body.dark-mode .lbaid-doc__badge,
body.dark-mode .lbaid-bk__badge,
body.dark-mode .lbaid-badge,
body.dark-mode .lbaid-mini__tag,
body.dark-mode .lbaid-hero__plan,
body.dark-mode .lbaid-ring__in,
body.dark-mode .lbaid-ml-views,
body.dark-mode .lbaid-sub__feat {
    background-color: var(--lbai-surface-2) !important;
    border-color: var(--lbai-border) !important;
    --lbai-text: #f1f5f9;
    color: #f1f5f9 !important;
}

/* The explicit opt-in for a surface that must stay pale. Nothing in the product currently uses
   it; it exists so a future pale-by-design surface has a supported way to declare itself. */
body.dark-mode .lbai-on-pale {
    --lbai-text: var(--lbai-text-on-pale);
    color: var(--lbai-text-on-pale) !important;
}

/* ── 4c. Saturated brand / status FILLS: the ink is white in both modes, by design. ── */
body.dark-mode .lbai-on-accent,
body.dark-mode .lbaid-mltab.active,
body.dark-mode .lbaid-mltab.active span,
body.dark-mode .lbaid-arch__badge,
body.dark-mode .lbaid-brand__logo,
body.dark-mode .lbaid-sub__current,
body.dark-mode .lbaid-sub__current span,
body.dark-mode .lbaid-staff__vactivate,
body.dark-mode .lbaid-lead__send,
body.dark-mode .ail-tab-btn.active,
body.dark-mode .lbaid-bnav__item.active,
body.dark-mode .ail-action-btn,
body.dark-mode .ail-action-btn span {
    --lbai-text: var(--lbai-text-on-accent);
    color: var(--lbai-text-on-accent) !important;
}

/* =====================================================================================
   5. STATUS AND BADGES — coordinated triples, never "white on whatever".
   =====================================================================================
   Every status the product renders gets an ink + surface + border that are chosen together.
   The hue is preserved in both modes so the meaning of the colour never changes; only the
   pairing is made readable. Applied by the state class names the product already emits.
   ===================================================================================== */
.lbai-status,
body.dark-mode .ail-booking-status,
body.dark-mode .lbaid-staff__badge,
body.dark-mode .lbaid-staff__verstate,
body.dark-mode .lbaid-staff__invstate,
body.dark-mode .lbaid-bk__badge,
body.dark-mode .lbaid-doc__badge {
    border: 1px solid transparent;
}

/* Success family: Confirmed · Approved · Completed · Active · Verified · Success · Paid */
/* SCOPE NOTE for all four families below.
   These target the chip population that booking-card.css ALREADY gives a dark translucent
   surface (the .lbaid-staff__* badges) plus the .lbai-status--* utility classes. They are
   deliberately NOT applied to .ail-booking-status or the .lpcf-badge-* family: those keep
   their authored PALE fills, and the inline-surface rule in section 3 already gives them dark
   ink. Treating both populations identically was measurably wrong — a dark ink forced onto a
   translucent tint over a dark card measured 1.61:1. Two populations, two treatments, chosen
   by which surface the chip actually has. */
body.dark-mode .lbaid-staff__badge.is-life-active,
body.dark-mode .lbaid-staff__badge.is-life-verified,
body.dark-mode .lbaid-staff__badge.is-verified,
body.dark-mode .lbaid-staffsum__item.is-active .lbaid-staffsum__n,
body.dark-mode .lbai-status--success {
    background-color: var(--lbai-success-bg) !important;
    color: var(--lbai-success) !important;
    border-color: var(--lbai-success-bg) !important;
    --lbai-text: var(--lbai-success);
}

/* Warning family: Pending · Pending Approval · Pending Payment · Expires Soon · Under review */
body.dark-mode .lbaid-staff__badge.is-life-pending_verification,
body.dark-mode .lbaid-staff__badge.is-noaccount,
body.dark-mode .lbaid-staff__badge.is-notworkable,
body.dark-mode .lbai-status--warning {
    background-color: var(--lbai-warning-bg) !important;
    color: var(--lbai-warning) !important;
    border-color: var(--lbai-warning-bg) !important;
    --lbai-text: var(--lbai-warning);
}

/* Danger family: Rejected · Cancelled · Expired · Blocked · Error · Failed */
body.dark-mode .lbaid-staff__badge.is-life-rejected,
body.dark-mode .lbaid-staff__badge.is-life-blocked,
body.dark-mode .lbaid-staff__badge.is-avail-busy,
body.dark-mode .lbai-status--danger {
    background-color: var(--lbai-danger-bg) !important;
    color: var(--lbai-danger) !important;
    border-color: var(--lbai-danger-bg) !important;
    --lbai-text: var(--lbai-danger);
}

/* Info family: Under review · Processing · Queued · Sent · Draft-in-progress */
body.dark-mode .lbaid-staff__badge.is-life-under_review,
body.dark-mode .lbaid-staff__badge.is-account,
body.dark-mode .lbaid-staff__inv.is-sent .lbaid-staff__invstate,
body.dark-mode .lbaid-staff__inv.is-queued .lbaid-staff__invstate,
body.dark-mode .lbaid-staff__inv.is-processing .lbaid-staff__invstate,
body.dark-mode .lbai-status--info {
    background-color: var(--lbai-info-bg) !important;
    color: var(--lbai-info) !important;
    border-color: var(--lbai-info-bg) !important;
    --lbai-text: var(--lbai-info);
}

/* Neutral family: Inactive · Disabled · Suspended · Draft · Off duty · unknown states.
   A default so a status the product adds later can never fall through to unreadable. */
body.dark-mode .lbaid-staff__badge,
body.dark-mode .lbaid-staff__badge.is-avail-off_duty,
body.dark-mode .lbaid-staff__verstate,
body.dark-mode .lbaid-staff__invstate,
body.dark-mode .lbai-status--neutral {
    /* !important is required on the BACKGROUND, not just the ink: these chips carry an inline
       pale fill from the template, and without it the light neutral ink landed on that pale
       fill at 1.10:1 — the one status the first pass still got wrong. */
    background-color: var(--lbai-neutral-bg) !important;
    color: var(--lbai-neutral) !important;
    --lbai-text: var(--lbai-neutral);
}

/* The status-family rules above must beat the generic neutral default, so the specific
   state classes are restated once with an extra qualifier. */
body.dark-mode .lbaid-staff__badge.is-life-active,
body.dark-mode .lbaid-staff__badge.is-life-verified,
body.dark-mode .lbaid-staff__badge.is-verified {
    background-color: var(--lbai-success-bg) !important;
    color: var(--lbai-success) !important;
}

body.dark-mode .lbaid-staff__badge.is-life-pending_verification,
body.dark-mode .lbaid-staff__badge.is-noaccount,
body.dark-mode .lbaid-staff__badge.is-notworkable {
    background-color: var(--lbai-warning-bg) !important;
    color: var(--lbai-warning) !important;
}

body.dark-mode .lbaid-staff__badge.is-life-rejected,
body.dark-mode .lbaid-staff__badge.is-life-blocked,
body.dark-mode .lbaid-staff__badge.is-avail-busy {
    background-color: var(--lbai-danger-bg) !important;
    color: var(--lbai-danger) !important;
}

body.dark-mode .lbaid-staff__badge.is-life-under_review,
body.dark-mode .lbaid-staff__badge.is-account {
    background-color: var(--lbai-info-bg) !important;
    color: var(--lbai-info) !important;
}

/* Alerts / notices, including the ones the templates emit with inline pastel styles. */
body.dark-mode .lbaid-tabnotice,
body.dark-mode [role="alert"],
body.dark-mode [role="status"] {
    background-color: var(--lbai-warning-bg) !important;
    color: var(--lbai-warning) !important;
    border-color: var(--lbai-warning-bg) !important;
    --lbai-text: var(--lbai-warning);
}

/* =====================================================================================
   6. ICONS
   =====================================================================================
   The fix for disappearing icons is currentColor, not a blanket white. An icon inherits the
   ink of the surface it sits on, so the surface contracts above already place it correctly;
   these rules only make the inheritance explicit for the three mechanisms that break it —
   icon fonts with their own colour, inline SVG with a hardcoded fill, and pale accent tiles.
   ===================================================================================== */

/* Icon fonts follow the inherited ink. No !important: a component that deliberately colours
   its own glyph (a brand mark, a saturated CTA) keeps that colour. */
body.dark-mode .dashicons,
body.dark-mode .dashicons-before::before,
body.dark-mode [class^="dashicons-"],
body.dark-mode .fa,
body.dark-mode [class^="fa-"],
body.dark-mode [class*=" fa-"] {
    color: inherit;
}

/* Inline SVG: honour currentColor. `fill="none"` and explicit stroke authoring are
   respected — only the default black/unset fill is redirected to the inherited ink. */
body.dark-mode svg:not([fill="none"]) {
    fill: currentColor;
}

body.dark-mode svg [fill="#000"],
body.dark-mode svg [fill="#000000"],
body.dark-mode svg [fill="black"] {
    fill: currentColor;
}

body.dark-mode svg [stroke="#000"],
body.dark-mode svg [stroke="#000000"],
body.dark-mode svg [stroke="black"] {
    stroke: currentColor;
}

/* Pale accent tiles that hold an icon: the tile takes a raised dark surface and the glyph
   takes the light ink, which is what a dark theme should do with an accent chip. */
body.dark-mode .lbaid-stat__ic,
body.dark-mode .lbaid-qa__ic,
body.dark-mode .lbaid-doc__ic,
body.dark-mode .lbaid-doc__dl,
body.dark-mode .lbaid-bk__icon,
body.dark-mode .lbaid-lead__av,
body.dark-mode .lbaid-arch__ic,
body.dark-mode .lbaid-mini__av,
body.dark-mode .ail-stat-icon,
body.dark-mode .ail-cat-icon,
body.dark-mode .lbaid-iconbtn {
    background-color: var(--lbai-surface-2) !important;
    color: var(--lbai-icon) !important;
    --lbai-text: var(--lbai-icon);
}

body.dark-mode .lbaid-stat__ic i,
body.dark-mode .lbaid-qa__ic i,
body.dark-mode .lbaid-doc__ic i,
body.dark-mode .lbaid-doc__dl i,
body.dark-mode .lbaid-bk__icon i,
body.dark-mode .lbaid-arch__ic i,
body.dark-mode .ail-stat-icon i,
body.dark-mode .lbaid-iconbtn i {
    color: var(--lbai-icon) !important;
}

/* Muted / decorative glyphs keep a lower-emphasis ink rather than vanishing. */
body.dark-mode .lbaid-arch__chevron,
body.dark-mode .ail-vl-placeholder i,
body.dark-mode .lbaid-rev__cardstars .dashicons-star-empty {
    color: var(--lbai-icon-muted) !important;
}

/* =====================================================================================
   7. FORMS
   =====================================================================================
   Field, label, placeholder, help text, validation and disabled state, each paired against
   the surface it actually renders on. The label rule matters most: header.php forces every
   <label> near-white, so a label above a white field was invisible.
   ===================================================================================== */
body.dark-mode input[type="text"],
body.dark-mode input[type="email"],
body.dark-mode input[type="url"],
body.dark-mode input[type="tel"],
body.dark-mode input[type="number"],
body.dark-mode input[type="password"],
body.dark-mode input[type="search"],
body.dark-mode input[type="date"],
body.dark-mode input[type="time"],
body.dark-mode input[type="datetime-local"],
body.dark-mode select,
body.dark-mode textarea,
body.dark-mode .ail-field-input {
    background-color: var(--lbai-input-bg) !important;
    color: var(--lbai-input-text) !important;
    border-color: var(--lbai-input-border) !important;
    --lbai-text: var(--lbai-input-text);
}

body.dark-mode input::placeholder,
body.dark-mode textarea::placeholder {
    color: var(--lbai-placeholder) !important;
    opacity: 1;
    /* Firefox lowers placeholder opacity by default, compounding the problem. */
}

/* A <label> is only readable once its own surface is known. On page/card background it takes
   the primary ink; inside a pale block the surface contract above has already re-pointed it. */
body.dark-mode label,
body.dark-mode .ail-field-group>label {
    color: var(--lbai-text) !important;
}

/* Help and validation text: distinguishable from body ink AND from the surface. */
body.dark-mode .ail-field-help,
body.dark-mode .lbaid-staff__msg.is-info,
body.dark-mode .description {
    color: var(--lbai-text-muted) !important;
}

/* Validation messages carry a pale pink panel in some components, so the SURFACE has to move
   with the ink — a light danger ink on the untouched #fef2f2 panel measured 1.74:1. */
body.dark-mode .ail-field-error,
body.dark-mode .lbaid-staff__msg.is-error,
body.dark-mode .lbaid-staff__empty.is-error,
body.dark-mode .lbaid-staff__vreasonbox,
body.dark-mode .ail-form-error {
    background-color: var(--lbai-danger-bg) !important;
    color: var(--lbai-danger) !important;
    --lbai-text: var(--lbai-danger);
}

body.dark-mode .lbaid-staff__msg.is-ok {
    color: var(--lbai-success) !important;
}

/* Native controls: let the platform draw them in the right scheme. */
body.dark-mode input[type="checkbox"],
body.dark-mode input[type="radio"],
body.dark-mode input[type="range"],
body.dark-mode progress {
    accent-color: var(--lbai-link);
}

body.dark-mode input[type="file"] {
    color: var(--lbai-text) !important;
}

/* Disabled must stay READABLE while still reading as disabled — dimming alone fails AA. */
body.dark-mode input:disabled,
body.dark-mode select:disabled,
body.dark-mode textarea:disabled,
body.dark-mode button:disabled,
body.dark-mode [aria-disabled="true"] {
    background-color: var(--lbai-disabled-bg) !important;
    color: var(--lbai-disabled-text) !important;
    border-color: var(--lbai-border) !important;
    opacity: 1;
    /* Replaces opacity-dimming, which multiplies against the surface. */
}

/* =====================================================================================
   8. TABLES · TABS · LINKS · FOCUS
   ===================================================================================== */
body.dark-mode table {
    color: var(--lbai-text);
}

body.dark-mode thead th {
    background-color: var(--lbai-surface-3) !important;
    color: var(--lbai-text) !important;
    border-color: var(--lbai-border) !important;
}

body.dark-mode tbody td {
    border-color: var(--lbai-border) !important;
}

body.dark-mode tbody tr:nth-child(even) {
    background-color: var(--lbai-surface-3);
}

body.dark-mode .lbaid-mltab,
body.dark-mode .ail-campaign-filter {
    background-color: var(--lbai-surface-2) !important;
    color: var(--lbai-text-muted) !important;
    border-color: var(--lbai-border) !important;
    --lbai-text: var(--lbai-text-muted);
}

body.dark-mode .lbaid-mltab span {
    background-color: var(--lbai-surface-3) !important;
    color: var(--lbai-text-muted) !important;
}

body.dark-mode .lbaid-mltab.active,
body.dark-mode .ail-campaign-filter.active {
    /* The FILL token, not the link token — see the accent note in the palette above. */
    background-color: var(--lbai-accent) !important;
    border-color: var(--lbai-accent) !important;
    color: var(--lbai-text-on-accent) !important;
    --lbai-text: var(--lbai-text-on-accent);
}

/* A DARK overlay, not a light one: lightening the brand fill under white text is what put
   this count badge at 3.87:1 in dark and 2.98:1 in light. */
body.dark-mode .lbaid-mltab.active span {
    background-color: rgba(0, 0, 0, .28) !important;
    color: var(--lbai-text-on-accent) !important;
}

/* Links must be distinguishable from body ink, which near-white-on-everything destroyed. */
body.dark-mode a:not([class*="btn"]):not([class*="tab"]):not([class*="card"]) {
    color: var(--lbai-link);
}

body.dark-mode a:not([class*="btn"]):not([class*="tab"]):not([class*="card"]):hover {
    color: var(--lbai-link-hover);
}

/* Focus is never removed to solve contrast; it is re-coloured for the dark surface. */
body.dark-mode a:focus-visible,
body.dark-mode button:focus-visible,
body.dark-mode input:focus-visible,
body.dark-mode select:focus-visible,
body.dark-mode textarea:focus-visible,
body.dark-mode [tabindex]:focus-visible {
    outline: 2px solid var(--lbai-focus) !important;
    outline-offset: 2px !important;
}

/* =====================================================================================
   9. PLUGIN SURFACES WITH NO DARK-MODE SUPPORT AT ALL
   =====================================================================================
   listingpro-custom-features ships 81 white inks, 37 white backgrounds and zero dark-mode
   rules, and it renders booking cards and badges — which is why booking status was reported
   unreadable. The theme cannot edit the plugin's stylesheets from here, but it can adopt
   those surfaces into the same token contract, which is the smallest correct fix.
   ===================================================================================== */
body.dark-mode .lpcf-vm-card,
body.dark-mode .lpcf-stat-card,
body.dark-mode .lpcf-panel,
body.dark-mode .lpcf-box,
body.dark-mode [class^="lpcf-"][class*="card"] {
    background-color: var(--lbai-surface) !important;
    border-color: var(--lbai-border) !important;
    --lbai-text: #f1f5f9;
}

body.dark-mode .lpcf-vm-card-title,
body.dark-mode .lpcf-stat-val,
body.dark-mode .lpcf-stat-lbl {
    color: var(--lbai-text) !important;
}

/* =====================================================================================
   10. SURFACES THE FROZEN core.css PAINTS WITH AN UNSAFE TOKEN
   =====================================================================================
   core.css's dark block paints ten surfaces with `var(--footer-bg)` and NO fallback.
   --footer-bg is declared once, in header.php, on :root for BOTH schemes, and defaults to
   the THEME PRIMARY COLOUR — so in dark mode those surfaces resolve to the brand purple (or
   to whatever light colour an admin chose for the footer) while their text is forced
   near-white. header.php's own !important block rescues most of them; these are the ones it
   does not name.
   ===================================================================================== */
body.dark-mode #page {
    background-color: var(--lbai-bg);
}

body.dark-mode .ail-app-header,
body.dark-mode .ail-bottom-nav,
body.dark-mode .ail-dash-tabs,
body.dark-mode .lbaid-sidebar,
body.dark-mode .lbaid-topbar,
body.dark-mode .lbaid-bnav {
    background-color: var(--lbai-surface) !important;
    border-color: var(--lbai-border) !important;
    --lbai-text: #f1f5f9;
}

/* =====================================================================================
   11. REDUCED MOTION — unrelated to colour, but this layer is the additive home for it.
   ===================================================================================== */
@media (prefers-reduced-motion: reduce) {
    body.dark-mode * {
        transition-duration: .01ms !important;
    }
}

/* =====================================================================================
   12. SUB-AA MUTED INK, BOTH MODES
   =====================================================================================
   These components were measured just below AA in LIGHT mode as well — 4.41:1, 4.34:1,
   4.18:1 and 2.56:1 — because each hardcodes #64748b or #94a3b8 as a "muted" ink against a
   near-white surface. That is a pre-existing light-mode defect, not dark-mode fallout, and
   the brief asks for zero normal text below 4.5:1.

   They are pointed at the semantic muted token instead of being individually recoloured, so
   both schemes are corrected by one declaration each and neither is made darker "to
   compensate" for the other: in light --lbai-text-muted is #475569 (8.6:1 on the page
   background), in dark it is #a5b4c8 on a dark surface.
   ===================================================================================== */
.lbaid-mlsub,
.lbaid-ml-views,
.lbaid-staff__state,
.lbaid-mltab span,
.ail-field-group>label,
.lbaid-lead__sub,
.lbaid-lead__meta,
.lbaid-doc__meta,
.lbaid-rank__sub,
.lbaid-side-profile__pl {
    color: var(--lbai-text-muted);
}

/* The "on" variant of the staff switch label used #10b981, which measured 2.54:1 on a white
   card. It keeps its success MEANING through the success token, which is contrast-checked. */
.lbaid-staff__state.is-on {
    color: var(--lbai-success);
}

/* Placeholder ink is a real AA target, not decoration. */
input::placeholder,
textarea::placeholder {
    color: var(--lbai-placeholder);
    opacity: 1;
}

/* Light-mode fills that carry white text: the active pill measured 2.98:1 because the fill
   was the lighter brand tint. The accent-fill token is used in both schemes so white text on
   a brand fill is AA everywhere. */
.lbaid-mltab.active,
.ail-campaign-filter.active {
    background-color: var(--lbai-accent);
    border-color: var(--lbai-accent);
    color: var(--lbai-text-on-accent);
}

.lbaid-mltab.active span {
    background-color: rgba(0, 0, 0, .28);
    color: var(--lbai-text-on-accent);
}

/* =====================================================================================

   13. --header-text — THE SECOND SINGLE-VALUED TOKEN
   =====================================================================================
   header.php line 151 declares `--header-text` once on :root, from the admin's header text
   colour setting, for BOTH schemes. That value is computed by get_readable_color() against the
   LIGHT header background. In dark mode core.css:1898 and header.php:679 repaint the header
   dark (rgba(30,30,46,.85)) but --header-text keeps its light-mode value, so every consumer
   paints dark ink on a dark bar.

   Measured on the real homepage in dark mode:
     svg (Saved heart)                #1f2937 on #16213e   1.08:1
     i.dashicons-admin-users          #1f2937 on #16213e   1.08:1
     i.dashicons-location             #0f172a on #16213e   1.12:1
     i.dashicons-menu                 #0f172a on #1f2a47   1.26:1

   This is the same defect class as --footer-bg in section 10. Re-pointing the ONE variable is
   the whole fix, and it is why it reaches the inline `style="color:var(--header-text)"`
   attributes on the heart, bell, profile and hamburger that no selector of ours could target:
   an inline style that references a custom property resolves that property at paint time, so
   changing the property changes the inline result. Ten consumers, one declaration.
   ===================================================================================== */
body.dark-mode {
    --header-text: #f1f5f9;
}

/* home.css:623/633 sets these with !important against var(--header-text, #1e293b). The variable
   above already corrects them; these two rules exist only so the FALLBACK can never apply if the
   variable is ever removed upstream. */
body.dark-mode .ail-app-header .ail-notif-bell .dashicons,
body.dark-mode .ail-app-header .ail-user-icon .dashicons,
body.dark-mode .ail-app-header .ail-loc-sub,
body.dark-mode .ail-app-header .ail-loc-sub i,
body.dark-mode .ail-app-header .ail-loc-title,
body.dark-mode .ail-app-header .ail-hdr-heart,
body.dark-mode .ail-app-header .ail-hdr-heart svg,
body.dark-mode .ail-app-header .ail-hdr-link,
body.dark-mode .ail-app-header .ail-brand-name,
body.dark-mode .ail-app-header a {
    color: var(--lbai-text) !important;
}

/* The desktop inline search sits on a hardcoded #f1f5f9 field inside the now-dark bar. */
body.dark-mode .ail-hdr-search {
    background: var(--lbai-input-bg) !important;
    border-color: var(--lbai-input-border) !important;
}

body.dark-mode .ail-hdr-search input {
    color: var(--lbai-input-text) !important;
}

body.dark-mode .ail-hdr-search svg {
    color: var(--lbai-icon) !important;
}

/* =====================================================================================

   14. SURFACES THAT WERE STILL PAINTED LIGHT IN DARK MODE
   =====================================================================================
   Measuring the REAL dashboard DOM (rather than a fixture) showed the largest single cluster of
   failures was not a chip at all: the whole .lbai-bkc booking card was still #ffffff in dark
   mode, so every line inside it sat at 1.10:1 —

     h4.lbai-bkc__title        "Listing unavailable"      #f1f5f9 on #ffffff   1.10:1
     p.lbai-bkc__sub           "Repairs & Maintenance"    #f1f5f9 on #ffffff   1.10:1
     span.lbai-bkc__ref        "#65"                      #f1f5f9 on #ffffff   1.10:1
     span.lbai-bkc__factval    "July 15, 2026"            #f1f5f9 on #ffffff   1.10:1
     span.lbai-bkc__staffname  "Rahul Ingale"             #f1f5f9 on #ffffff   1.10:1
     h4 (.lbaid-rank__tips)    "Boost your ranking"       #f1f5f9 on #ffffff   1.10:1
     li / li.done              ranking checklist          #f1f5f9 on #ffffff   1.10:1

   Section 4a named .ail-booking-card but not .lbai-bkc, which is the class the current booking
   card actually ships. Fixing the SURFACE fixes every descendant at once — which is the point of
   a surface contract, and is why this is one block rather than fifteen ink overrides.
   ===================================================================================== */
body.dark-mode .lbai-bkc,
body.dark-mode .lbaid-rank__tips,
body.dark-mode .lbaid-rank__card,
body.dark-mode .lbaid-crm__count,
body.dark-mode .lbaid-sub__plan,
body.dark-mode .lbaid-staff__row,
body.dark-mode .lbai-ver-summary,
body.dark-mode .lbai-stats__card,
body.dark-mode .lbai-news,
body.dark-mode .lbai-cat2,
body.dark-mode .lbai-blog-card,
body.dark-mode .lbaid-side-card.plan a {
    background-color: var(--lbai-surface) !important;
    border-color: var(--lbai-border) !important;
    --lbai-text: #f1f5f9;
}

/* Recessed panels INSIDE the booking card. booking-card.css paints these #f8fafc / #fef7eb /
   #fef8ec, which read as bright blocks on a dark card and measured 1.03–1.05:1. */
body.dark-mode .lbai-bkc__toggle,
body.dark-mode .lbai-bkc__bar,
body.dark-mode .lbai-bkc__facts,
body.dark-mode .lbai-bkc__staff,
body.dark-mode .lbai-bkc__rev,
body.dark-mode .lbai-bkc__review,
body.dark-mode .lbai-bkc__revread,
body.dark-mode .lbai-bkc__revreply,
body.dark-mode .lbai-bkc__thumb,
body.dark-mode .lbaid-staff__empty,
body.dark-mode .lbai-bkc__addrwrap {
    background-color: var(--lbai-surface-3) !important;
    border-color: var(--lbai-border) !important;
    --lbai-text: #f1f5f9;
}

/* The ranking checklist bullet: #cbd5e1 on a dark card is fine, but `li.done` carries #15803d
   which is a light-mode green. Both get hue-appropriate dark-mode inks. */
body.dark-mode .lbaid-rank__tips li {
    color: var(--lbai-text) !important;
}

body.dark-mode .lbaid-rank__tips li::before {
    color: var(--lbai-icon-muted);
}

body.dark-mode .lbaid-rank__tips li.done {
    color: #86efac !important;
}

body.dark-mode .lbaid-rank__tips li.done::before {
    color: #4ade80;
}

/* =====================================================================================

   15. PALE ACCENT TILES THAT WRAP AN ICON OR AN INITIAL
   =====================================================================================
   These are 40–60px rounded tiles with a pastel fill and a brand-coloured glyph. In dark mode
   the fill stayed pastel while the glyph inherited the forced near-white:

     svg inside .lbai-stats__ic     #f1f5f9 on #f3f1ff   1.02:1   ("Why Thousands Trust Us")
     span.lbai-bkc__staffinitial    #f1f5f9 on #e2e8f0   1.13:1

   Treatment: keep the HUE so the tile still reads as the same accent, but darken the fill to a
   translucent tint and use a light ink of that hue. Deliberately not "keep pale + dark ink":
   a pastel tile on a dark card is a bright blob, and the light ink also agrees with the forced
   near-white instead of fighting it.
   ===================================================================================== */
body.dark-mode .lbai-stats__ic,
body.dark-mode .lbaid-qa__ic,
body.dark-mode .lbaid-mini__av,
body.dark-mode .lbaid-lead__av,
body.dark-mode .lbai-bkc__staffinitial,
body.dark-mode .lbai-bkc__staffav,
body.dark-mode .lbaid-staff__av,
body.dark-mode .lbai-cat2__ic,
body.dark-mode .lbai-news__ic {
    background-color: rgba(109, 94, 252, .22) !important;
    color: #c4b5fd !important;
    --lbai-text: #c4b5fd;
}

/* currentColor is how these glyphs are painted, so the tile's own colour must reach the SVG.
   No blanket fill:white — the stroke/fill keywords the markup already uses are respected. */
body.dark-mode .lbai-stats__ic svg,
body.dark-mode .lbaid-qa__ic svg,
body.dark-mode .lbai-cat2__ic svg,
body.dark-mode .lbai-news__ic svg {
    color: #c4b5fd !important;
}

/* =====================================================================================

   16. STATUS CHIPS PAINTED BY CLASS (not inline)
   =====================================================================================
   The reported "Confirmed / Pending unreadable" symptom had TWO distinct sources. The inline
   one is handled in section 3. This is the other, and the previous pass missed it entirely
   because the fixture used inline chips while the product paints these from core.css and
   booking-card.css:

     .ail-status-cancelled  #f1f5f9 on #f1f5f9   1.00:1   "Cancelled"
     .ail-status-rejected   #f1f5f9 on #fef2f2   1.00:1   "Declined"
     .ail-status-completed  #f1f5f9 on #eef2ff   1.02:1   "Completed"
     .ail-status-pending    #f1f5f9 on #fff7ed   1.03:1   "Pending"
     .ail-status-accepted   #f1f5f9 on #ecfdf5   1.04:1   "Confirmed"
     .lbai-bkc__fbadge.*    #f1f5f9 on #ecfdf5   1.04:1   "Service completed"

   The class list is keyed off .ail-status-* on purpose: booking-card.css documents that the
   cancel modal and the status handlers REWRITE the badge's entire class list to
   `ail-booking-status ail-status-<state>`, so any class of our own would be stripped the moment
   a booking changed state.

   Each family gets a coordinated triple — translucent tint of its own hue, light ink of the
   same hue, matching border. The hue is preserved in both modes so the meaning of the colour
   never changes; only the pairing is made readable.
   ===================================================================================== */

/* Success — Confirmed · Accepted · Verified · Active · Paid */
body.dark-mode .ail-status-confirmed,
body.dark-mode .ail-status-accepted,
body.dark-mode .ail-status-active,
body.dark-mode .ail-status-paid,
body.dark-mode .lbai-bkc__fbadge.is-completed,
body.dark-mode .lbai-bkc__fbadge.is-accepted_by_staff,
body.dark-mode .lbai-bkc__verifiedtext,
body.dark-mode .lbaid-tag-confirmed,
body.dark-mode .lbaid-badge.green {
    background-color: rgba(34, 197, 94, .18) !important;
    border-color: rgba(34, 197, 94, .38) !important;
    color: #86efac !important;
    --lbai-text: #86efac;
}

/* Completed — indigo in this product, deliberately distinct from Confirmed's green. */
body.dark-mode .ail-status-completed {
    background-color: rgba(99, 102, 241, .22) !important;
    border-color: rgba(99, 102, 241, .42) !important;
    color: #c7d2fe !important;
    --lbai-text: #c7d2fe;
}

/* Warning — Pending · Paused · Awaiting */
body.dark-mode .ail-status-pending,
body.dark-mode .ail-status-paused,
body.dark-mode .ail-status-awaiting,
body.dark-mode .lbaid-tag-pending,
body.dark-mode .lbaid-badge.gold {
    background-color: rgba(245, 158, 11, .18) !important;
    border-color: rgba(245, 158, 11, .38) !important;
    color: #fcd34d !important;
    --lbai-text: #fcd34d;
}

/* Danger — Rejected · Declined · Expired · Dispatch cancelled */
body.dark-mode .ail-status-rejected,
body.dark-mode .ail-status-expired,
body.dark-mode .lbai-bkc__fbadge.is-cancelled,
body.dark-mode .lbai-bkc__fbadge.is-rejected,
body.dark-mode .lbaid-doc__badge.red {
    background-color: rgba(239, 68, 68, .18) !important;
    border-color: rgba(239, 68, 68, .40) !important;
    color: #fca5a5 !important;
    --lbai-text: #fca5a5;
}

/* Neutral — Cancelled reads slate in this product, not red. Hue preserved. */
body.dark-mode .ail-status-cancelled {
    background-color: rgba(148, 163, 184, .22) !important;
    border-color: rgba(148, 163, 184, .40) !important;
    color: #e2e8f0 !important;
    --lbai-text: #e2e8f0;
}

/* Info — Assigned */
body.dark-mode .ail-status-assigned,
body.dark-mode .lbai-bkc__fbadge.is-assigned,
body.dark-mode .lbaid-tag-new,
body.dark-mode .lbaid-badge.blue {
    background-color: rgba(59, 130, 246, .20) !important;
    border-color: rgba(59, 130, 246, .40) !important;
    color: #93c5fd !important;
    --lbai-text: #93c5fd;
}

/* In-flight — On the way · Arrived · In progress */
body.dark-mode .ail-status-on_the_way,
body.dark-mode .ail-status-arrived,
body.dark-mode .ail-status-in_progress {
    background-color: rgba(6, 182, 212, .20) !important;
    border-color: rgba(6, 182, 212, .40) !important;
    color: #67e8f9 !important;
    --lbai-text: #67e8f9;
}

/* The review quote blocks inside the booking card carry their own amber wash. */
body.dark-mode .lbai-bkc__revtext,
body.dark-mode .lbai-bkc__revreplytext,
body.dark-mode .lbai-bkc__revreplywho {
    color: var(--lbai-text) !important;
}

/* =====================================================================================

   17. THE VENDOR SIDEBAR
   =====================================================================================
   24 distinct nav icons measured 1.51:1 (#373f52 on #16213e) and the labels 3.34:1
   (#64748b on #16213e). dashboard-ui.css gives .ail-tab-btn a light-mode slate ink and the
   icon inherits it, so in dark mode the entire navigation is close to invisible.
   ===================================================================================== */
body.dark-mode .lbaid-sidebar .ail-tab-btn {
    color: var(--lbai-text) !important;
}

body.dark-mode .lbaid-sidebar .ail-tab-btn i,
body.dark-mode .lbaid-sidebar .ail-tab-btn .dashicons {
    color: var(--lbai-icon) !important;
    opacity: 1 !important;
}

body.dark-mode .lbaid-sidebar .ail-tab-btn:hover {
    background-color: var(--lbai-surface-2) !important;
    color: var(--lbai-text-strong) !important;
}

/* The active pill is a saturated brand fill in both modes: its ink is white by design. */
body.dark-mode .lbaid-sidebar .ail-tab-btn.active,
body.dark-mode .lbaid-sidebar .ail-tab-btn.active i,
body.dark-mode .lbaid-sidebar .ail-tab-btn.active .dashicons {
    color: var(--lbai-text-on-accent) !important;
}

/* Dashicons anywhere on a dark surface that still carry a light-mode ink. Scoped to the
   dashboard shell so it cannot reach icons that legitimately own their colour. */
body.dark-mode .lbaid-shell .dashicons,
body.dark-mode .lbaid-topbar .dashicons,
body.dark-mode .ail-dashboard-page .ail-module-card .dashicons {
    color: var(--lbai-icon);
}

/* =====================================================================================

   18. INK ON SATURATED FILLS, AND THE UNSTYLED-LINK DEFAULT
   =====================================================================================
   Measured in dark mode:
     a.modern-btn-secondary "Download Invoice"  #0000ee on #16213e   1.69:1  (UA default link)
     button.lbai-card__fav                      #000000 on #323c4d   1.89:1
     a.lbaid-mladd "Add New Listing"            #a99cff on #6d5efc   1.91:1  (link ink on accent)
     span.lbaid-sub__plan-tag "Current"         #f1f5f9 on #6d5efc   4.12:1
     button "Search" / "Install App"            #ffffff on #8b7dff   3.24:1
   ===================================================================================== */
body.dark-mode a:not([class]),
body.dark-mode .modern-btn,
body.dark-mode .modern-btn-secondary {
    color: var(--lbai-link) !important;
}

body.dark-mode .lbai-card__fav,
body.dark-mode .ail-fav-btn {
    color: var(--lbai-text) !important;
}

/* A link INSIDE a saturated fill takes the on-accent ink, not the link ink.

   THE INVARIANT THIS RULE HAS TO RESPECT, and the reason an earlier draft of it silently did
   nothing: section 3 sets `color: var(--lbai-text) !important` at specificity (0,3,2), which
   outranks a plain `body.dark-mode .thing` at (0,2,1). Setting `color` alone therefore loses.
   Re-pointing --lbai-text wins instead, because section 3 then RESOLVES the variable to the new
   value on that element. Measured proof of both sides: .ail-status-accepted re-points the token
   and took its hue ink correctly, while .lbaid-sub__plan-tag set only `color` and stayed at
   #f1f5f9 on #6d5efc (4.12:1).

   Every ink override in this file re-points --lbai-text. Do not set `color` without it. */
body.dark-mode .lbaid-mladd,
body.dark-mode .lbaid-mladd span,
body.dark-mode .lbaid-mladd i,
body.dark-mode .lbaid-sub__plan-tag,
body.dark-mode .lbai-ver-summary a,
body.dark-mode .ail-action-btn.ail-action-book,
body.dark-mode .ail-action-btn.ail-action-book i {
    --lbai-text: var(--lbai-text-on-accent);
    color: var(--lbai-text-on-accent) !important;
}

/* Brand fills that were the LIGHTER tint carrying white text. Both schemes use the accent-fill
   token so white on a brand fill is AA everywhere. */
.lbaid-pwa-btn,
.ail-hdr-search button {
    background-color: var(--lbai-accent) !important;
    color: var(--lbai-text-on-accent) !important;
}

/* The diagnostics FAB score chip: #f1f5f9 on #6b7280 measured 4.41:1. */
.lbai-diag-fab__score {
    background-color: #4b5563 !important;
    color: #ffffff !important;
}

/* =====================================================================================

   19. LIGHT-MODE INKS BELOW AA
   =====================================================================================
   All pre-existing, all measured on the real DOM, none introduced by this layer. Corrected by
   pointing each at an accessible variant of THE SAME HUE, so the light design is preserved
   rather than darkened wholesale.

     #94a3b8 on #ffffff   2.56:1   muted metadata, many components
     #10b981 on #ffffff   2.54:1   "All Locations", "Add New Listing", "Rating: New"
     #f59e0b on #ffffff   2.15:1   rating stars + "4.9 (11)"
     #22c55e on #ffffff   2.28:1   verified ticks
     #3b82f6 on #ffffff   3.68:1   "Add New Location", "Request it"
     #ef4444 on #ffffff   3.76:1   "Logout"
     #16a34a on #fef5f5   3.08:1   "Earned"
     #059669 on #e7f8f2   3.43:1   "Completed"
     #d97706 on #fef5e7   2.95:1   "Pending"
     #6d5efc on #f3f1ff   4.04:1   "Premium Partner", avatar initials
     #64748b on #f5f6fb   4.41:1   "Lifetime", "Listing", badges note
     #dc2626 on #fef2f2   4.41:1   "Expired"
     #cbd5e1 / #d6d3d1    1.44:1   empty-state bell and unfilled stars
   ===================================================================================== */
:root {
    --lbai-ok-green: #047857;
    --lbai-ok-amber: #a15c07;
    --lbai-ok-blue: #1d4ed8;
    --lbai-ok-red: #b91c1c;
    --lbai-ok-brand: #4f46e5;
}

body:not(.dark-mode) .ail-city-item.active,
body:not(.dark-mode) .ail-drawer-link,
body:not(.dark-mode) .ail-rc-rating,
body:not(.dark-mode) .lbaid-rank__tips li.done,
body:not(.dark-mode) .st,
body:not(.dark-mode) .dashicons-yes-alt {
    color: var(--lbai-ok-green);
}

body:not(.dark-mode) .ail-drawer-link.ail-logout,
body:not(.dark-mode) a.ail-drawer-link[href*="logout"] {
    color: var(--lbai-ok-red);
}

body:not(.dark-mode) .ail-add-location-toggle,
body:not(.dark-mode) .ail-gps-btn {
    color: var(--lbai-ok-blue);
}

body:not(.dark-mode) .lbaid-hero__rating,
body:not(.dark-mode) .lbaid-rev__stars,
body:not(.dark-mode) .dashicons-star-filled {
    color: var(--lbai-ok-amber);
}

body:not(.dark-mode) .lbaid-hero__plan,
body:not(.dark-mode) .lbaid-mini__av,
body:not(.dark-mode) .lbaid-lead__av,
body:not(.dark-mode) .lbaid-rev__replywho {
    color: var(--lbai-ok-brand);
}

/* Empty-state glyphs: unfilled stars and the "no notifications" bell were decorative-grey at
   1.44:1. Raised to the 3:1 non-text minimum while staying visibly "empty". */
body:not(.dark-mode) .dashicons-star-empty,
body:not(.dark-mode) .dashicons-bell.is-empty,
body:not(.dark-mode) .lbaid-empty .dashicons,
body:not(.dark-mode) .ail-empty-state .dashicons {
    color: #767f8c;
}

/* Muted metadata ink, both schemes, via the token rather than per component. */
body:not(.dark-mode) .lbai-cat2__count,
body:not(.dark-mode) .lbai-blog-card__date,
body:not(.dark-mode) .lbaid-staff__empty,
body:not(.dark-mode) .lbaid-sub__feat.off,
body:not(.dark-mode) .lbaid-badges-note,
body:not(.dark-mode) .lbai-bkc__stafflabel,
body:not(.dark-mode) .lbai-news__sub,
body:not(.dark-mode) .lbaid-staff__file,
body:not(.dark-mode) .lbai-bkc__thumbfallback,
body:not(.dark-mode) .lbaid-sub__plan-btn.is-current {
    color: var(--lbai-text-muted);
}

/* =====================================================================================

   20. THE REST OF THE :root TOKEN LAYER — THE ACTUAL SYSTEMIC CAUSE
   =====================================================================================
   header.php lines 145-190 declare ~30 custom properties on :root, ALL computed for LIGHT mode.
   In dark mode only five of them are ever given dark values (--bg-color, --card-bg,
   --text-primary, --border-color by the inline dashboard block, and --footer-bg / --header-text
   by sections 10 and 13 of this file). Every remaining token keeps its light-mode value, so any
   component that paints from one of them is applying a light-mode decision to a dark surface.

   That is the single cause behind the last cluster of failures, and it is why chasing components
   never converged: the wrong value is upstream of all of them.

   PROOF THIS IS THE RIGHT FIX, not a new idea: home.css:2528 already does exactly this, with the
   same values, and documents the same reasoning. It simply cannot help here — home.css is
   enqueued on the HOMEPAGE ONLY, so the dashboard never receives it. The measured symptom was
   .ail-drawer-link i at 1.51:1 on all four dashboard captures and 0 failures for the same
   component on the homepage. This layer is enqueued on every front-end route, so declaring the
   tokens here finishes the job for every template.

   Resolution of a custom property is decided where it is DECLARED, and `body.dark-mode` (0,1,1)
   outranks header.php's `:root`, so no !important and no specificity war is needed. Values match
   home.css exactly so the two declarations can never disagree.
   ===================================================================================== */
body.dark-mode {
    /* core.css:2556 paints .ail-drawer-link i with this. Measured 1.51:1 before. */
    --text-secondary: #a5b4c8;

    /* Fallback of the INLINE `background: var(--light-gray, #f8fafc)` on the provider card meta
       pills — giving the variable a dark value is the only way to reach an inline declaration
       without !important. */
    --light-gray: #1e293b;

    /* Link + icon hues. #6d5efc measured 3.52:1 on the dark card; this is the dark-mode accent
       the product already uses elsewhere. */
    --link-color: #c4b5fd;
    --icon-color: #c4b5fd;
    --cat-link-color: #c4b5fd;
    --cat-link-hover-color: #ddd6fe;

    /* The footer bar is repainted dark by section 10, so its ink has to follow. */
    --footer-text: #f1f5f9;
}

/* core.css:1630 is the one place --text-secondary is a FILL rather than an ink: the toggle
   switch track. A light track with a white knob would trade a text failure for a UI-component
   one, so the track and knob are pinned to a pair that stays distinguishable. */
body.dark-mode .ail-switch .ail-switch-slider,
body.dark-mode .ail-toggle-slider {
    background-color: var(--lbai-border-strong) !important;
}

body.dark-mode .ail-switch input:checked+.ail-switch-slider,
body.dark-mode .ail-toggle input:checked+.ail-toggle-slider {
    background-color: var(--lbai-accent) !important;
}

/* =====================================================================================

   21. REMAINING MEASURED INKS — all re-pointing --lbai-text per the section 18 invariant
   =====================================================================================
   Each entry below is a measured failure from the real DOM, not a precaution. The hue is kept
   and only lightened to the shade of the same colour that clears AA on a dark surface.

     button.ail-tab-btn "Overview"              #64748b on #16213e   3.34:1
     button "View All"                          #6d5efc on #16213e   3.52:1
     button "Mark all as read"                  #2563eb on #1a1a2e   3.30:1
     button "Deactivate Account"                #ef4444 on #2b1d30   4.21:1
     a.ail-drawer-link "Logout"                 #ef4444 on #16213e   4.22:1
     .ail-add-location-toggle "Add New Location" #3b82f6 on #16213e  4.32:1
     ul.ail-footer-links a "Browse Categories"  #a99cff on #8224e3   2.68:1
   ===================================================================================== */
body.dark-mode .ail-tab-btn,
body.dark-mode .lbaid-sidebar .ail-tab-btn {
    --lbai-text: #f1f5f9;
    color: #f1f5f9 !important;
}

body.dark-mode .ail-tab-btn.active,
body.dark-mode .lbaid-sidebar .ail-tab-btn.active {
    --lbai-text: var(--lbai-text-on-accent);
    color: var(--lbai-text-on-accent) !important;
}

/* Text-only action buttons: keep the brand hue, use the dark-mode accent shade. */
body.dark-mode .lbaid-sec-head button,
body.dark-mode .lbaid-viewall,
body.dark-mode .ail-view-all {
    --lbai-text: var(--lbai-link);
    color: var(--lbai-link) !important;
}

body.dark-mode .ail-mark-all-read,
body.dark-mode .lbaid-markall {
    --lbai-text: #93c5fd;
    color: #93c5fd !important;
}

/* Destructive actions keep red, at the dark-mode red. */
body.dark-mode .ail-deactivate-account,
body.dark-mode #ail-deactivate-account-btn,
body.dark-mode .ail-drawer-link[href*="logout"],
body.dark-mode .ail-logout,
body.dark-mode .lbaid-danger {
    --lbai-text: #fca5a5;
    color: #fca5a5 !important;
}

body.dark-mode .ail-add-location-toggle,
body.dark-mode .ail-gps-btn {
    --lbai-text: #93c5fd;
    color: #93c5fd !important;
}

/* The footer bar is repainted from --footer-bg (section 10), which resolves to the brand colour.
   Its links were taking the dark-mode link tint on a saturated purple. */
body.dark-mode .ail-footer-links a,
body.dark-mode .ail-footer-col a,
body.dark-mode .ail-app-footer a {
    --lbai-text: var(--lbai-text-on-accent);
    color: var(--lbai-text-on-accent) !important;
}

/* =====================================================================================

   22. SUPERSEDING THE FROZEN dashboard-ui.css B7 BLOCK
   =====================================================================================
   dashboard-ui.css IS FROZEN and is not edited. Its B7 dark-mode block (lines 1197-1224) makes
   two decisions that measurement contradicts, and it makes them at specificity (0,4,0) with
   !important, so nothing shorter can reach them:

     1. It repaints the icon tiles .lbaid-stat__ic / .lbaid-qa__ic / .lbaid-doc__ic /
        .lbaid-doc__dl / .ail-stat-icon / .lbaid-mini__av to #1f2a47 — DARK — and then sets their
        glyph to `color: var(--lbaid-ink)`, which is #0f172a. Dark ink on a dark tile. This is a
        pre-existing contradiction inside that one block, not something this layer introduced.

     2. It classifies .lbaid-badge / .lbaid-mini__tag / .lbaid-hero__plan / .lbaid-ring__in /
        .lbaid-ml-views / .lbaid-staff__skill / .lbaid-sub__feat as "pale background, so dark
        ink". Sections 4b and 16 of this file now give those chips a dark tint, so the dark ink
        measured 1.35:1 on .lbaid-hero__plan, .lbaid-ring__in, .lbaid-badge and .lbaid-sub__feat,
        and 1.47:1 on .lbaid-mini__tag.

   These selectors carry `html` plus the same two container classes, which lands them at (0,4,2)
   and wins on specificity alone — no source-order dependency, and no frozen file touched.
   ===================================================================================== */
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-badge,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-mini__tag,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-hero__plan,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-ring__in,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-ml-views,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-staff__skill,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-sub__feat,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-lead__tag,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-doc__badge,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-bk__badge {
    --lbai-text: #f1f5f9;
    color: #f1f5f9 !important;
}

/* Hue variants keep their meaning; each is a tint of its own colour with a light ink to match. */
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-badge.green,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-doc__badge.green,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-mini__tag.lbaid-tag-confirmed {
    --lbai-text: #86efac;
    color: #86efac !important;
}

html body.dark-mode .ail-dashboard-page.lbaid .lbaid-badge.gold,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-doc__badge.amber,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-mini__tag.lbaid-tag-pending {
    --lbai-text: #fcd34d;
    color: #fcd34d !important;
}

html body.dark-mode .ail-dashboard-page.lbaid .lbaid-badge.blue,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-mini__tag.lbaid-tag-new,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-lead__tag.is-inq {
    --lbai-text: #93c5fd;
    color: #93c5fd !important;
}

html body.dark-mode .ail-dashboard-page.lbaid .lbaid-doc__badge.red {
    --lbai-text: #fca5a5;
    color: #fca5a5 !important;
}

html body.dark-mode .ail-dashboard-page.lbaid .lbaid-lead__tag.is-quote {
    --lbai-text: #c4b5fd;
    color: #c4b5fd !important;
}

/* The icon tiles the frozen block already darkened to #1f2a47 — only the glyph needs correcting. */
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-stat__ic,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-stat__ic i,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-qa__ic,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-qa__ic i,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-doc__ic,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-doc__ic i,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-doc__dl,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-doc__dl i,
html body.dark-mode .ail-dashboard-page.lbaid .ail-stat-icon,
html body.dark-mode .ail-dashboard-page.lbaid .ail-stat-icon i,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-mini__av,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-mini__av i,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-iconbtn,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-iconbtn i {
    --lbai-text: #c4b5fd;
    color: #c4b5fd !important;
}

/* Section 15 gave these tiles a brand tint at (0,2,0), which the frozen block's #1f2a47 at
   (0,4,0) outranked. Restated here at (0,4,2) so tile and glyph are decided together. */
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-qa__ic,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-mini__av,
html body.dark-mode .ail-dashboard-page.lbaid .lbaid-stat__ic {
    background-color: rgba(109, 94, 252, .22) !important;
}

/* =====================================================================================

   23. THE LAST MEASURED SET
   =====================================================================================
   Dark mode — four remaining surfaces/inks:
     .lbai-bkc__verified            pale #ecfdf5 parent; tinted child measured 1.15:1 text,
                                    1.04:1 on its dashicons-yes-alt
     .lbaid-sub__current            still #ffffff, so a.lbaid-sub__upgrade sat at 2.36:1
     a inside .lbai-ver-summary     #ffffff on #10b981 = 2.54:1 in BOTH modes (pre-existing)
     button "Mark all as read"      #2563eb on #1a1a2e = 3.30:1 (inline ink, no class)
   ===================================================================================== */
body.dark-mode .lbai-bkc__verified {
    background-color: rgba(34, 197, 94, .18) !important;
    border-color: rgba(34, 197, 94, .38) !important;
    --lbai-text: #86efac;
}

body.dark-mode .lbai-bkc__verified .dashicons,
body.dark-mode .lbai-bkc__verified .lbai-bkc__verifiedtext {
    color: #86efac !important;
}

/* .lbaid-sub__current is NOT a white card — dashboard-ui.css:481 paints it
   `linear-gradient(135deg, var(--lbaid-primary), #8b7dff)` and puts white text on it, in both
   schemes. An earlier draft of this rule repainted its background-color, which did nothing useful
   (the gradient is a background-IMAGE and still painted over it) and left the upgrade link taking
   the dark-mode link tint at 2.36:1.

   Correct treatment: leave the brand gradient alone and give its contents the on-accent ink,
   which is exactly what light mode already does. */
body.dark-mode .lbaid-sub__current,
body.dark-mode .lbaid-sub__current span,
body.dark-mode .lbaid-sub__cur-l,
body.dark-mode .lbaid-sub__cur-r {
    --lbai-text: var(--lbai-text-on-accent);
    color: var(--lbai-text-on-accent) !important;
}

/* .lbaid-sub__upgrade is the ONE exception inside that gradient: dashboard-ui.css:487 makes it a
   WHITE pill with brand-purple ink, and that pairing is correct in both schemes. Two earlier
   drafts of this file got it wrong in opposite directions — first pointing it at the dark-mode
   link tint (#a99cff on #ffffff, 2.36:1), then sweeping it into the on-accent group above
   (#ffffff on #ffffff, 1.00:1). It keeps its white pill and takes a brand ink deep enough to
   clear AA on white: #4f46e5 measures 6.22:1. Same value in both modes, because the pill is
   white in both. */
.lbaid-sub__upgrade {
    --lbai-text: #4f46e5;
    color: #4f46e5 !important;
}

/* The notification bulk action carries `style="... color: #2563eb; ..."` — WITH a space after the
   colon, which is why the attribute selectors in section 24 did not reach it. Targeted by its id,
   which is unambiguous and outranks the inline declaration. */
body.dark-mode #ail-mark-all-read {
    color: #93c5fd !important;
}

body:not(.dark-mode) #ail-mark-all-read {
    color: #1d4ed8 !important;
}

/* A saturated green CTA carrying white text. #10b981 gives white only 2.54:1, in both schemes,
   so the FILL is darkened to the same hue at an accessible depth rather than the text lightened
   (it is already white). White on #047857 measures 5.55:1. */
.lbai-ver-summary a,
[style*="background:#10b981"],
[style*="background:#16a34a"],
.lbai-card__badge.is-open {
    background-color: #047857 !important;
    color: #ffffff !important;
}

/* =====================================================================================
   24. INLINE INK LITERALS
   =====================================================================================
   Same technique as the inline BACKGROUND enumeration in section 3, applied to inline `color:`.
   These elements are class-less divs, spans and paragraphs carrying `style="color:#94a3b8"` and
   friends, so there is no class to hang a rule on and an inline declaration outranks any ordinary
   selector. Each literal is mapped to an accessible shade of THE SAME HUE.

     #94a3b8 on #ffffff  2.56:1  "Missing your city?", "Code:", "Claims", "Created ...", GST note
     #10b981 on #ffffff  2.54:1  "Add New Listing" (drawer)
     #ef4444 on #ffffff  3.76:1  "Logout" (drawer)
     #3b82f6 on #ffffff  3.68:1  "Request it", "Add New Location"
     #64748b on #f5f6fb  4.41:1  "Listing" label
     #d97706 on #fef5e7  2.95:1  "Pending"
     #059669 on #e7f8f2  3.43:1  "Completed"
     #2563eb on #1a1a2e  3.30:1  "Mark all as read"  (dark mode: lightened, not darkened)
   ===================================================================================== */
body:not(.dark-mode) [style*="color:#94a3b8"],
body:not(.dark-mode) [style*="color: #94a3b8"] {
    color: #5c6a7d !important;
}

body:not(.dark-mode) [style*="color:#64748b"],
body:not(.dark-mode) [style*="color: #64748b"] {
    color: #4b5563 !important;
}

body:not(.dark-mode) [style*="color:#10b981"],
body:not(.dark-mode) [style*="color:#059669"],
body:not(.dark-mode) [style*="color:#16a34a"],
body:not(.dark-mode) [style*="color:#22c55e"] {
    color: #047857 !important;
}

body:not(.dark-mode) [style*="color:#ef4444"],
body:not(.dark-mode) [style*="color:#dc2626"] {
    color: #b91c1c !important;
}

body:not(.dark-mode) [style*="color:#3b82f6"],
body:not(.dark-mode) [style*="color: #3b82f6"],
body:not(.dark-mode) [style*="color:#2563eb"],
body:not(.dark-mode) [style*="color: #2563eb"] {
    color: #1d4ed8 !important;
}

/* The spaced form of every literal above. Inline styles in this product are written both ways
   (`color:#94a3b8` in some templates, `color: #2563eb` in others), and an attribute substring
   match is literal, so both spellings have to be listed. */
body:not(.dark-mode) [style*="color: #10b981"],
body:not(.dark-mode) [style*="color: #059669"],
body:not(.dark-mode) [style*="color: #16a34a"],
body:not(.dark-mode) [style*="color: #22c55e"] {
    color: #047857 !important;
}

body:not(.dark-mode) [style*="color: #ef4444"],
body:not(.dark-mode) [style*="color: #dc2626"] {
    color: #b91c1c !important;
}

body:not(.dark-mode) [style*="color: #d97706"],
body:not(.dark-mode) [style*="color: #f59e0b"],
body:not(.dark-mode) [style*="color: #eab308"] {
    color: #a15c07 !important;
}

body.dark-mode [style*="color: #2563eb"],
body.dark-mode [style*="color: #3b82f6"] {
    color: #93c5fd !important;
}

body.dark-mode [style*="color: #94a3b8"],
body.dark-mode [style*="color: #64748b"] {
    color: var(--lbai-text-muted) !important;
}

body:not(.dark-mode) [style*="color:#d97706"],
body:not(.dark-mode) [style*="color:#f59e0b"],
body:not(.dark-mode) [style*="color:#eab308"] {
    color: #a15c07 !important;
}

/* In dark mode the same literals must go the OTHER way — lighter, not darker. */
body.dark-mode [style*="color:#2563eb"],
body.dark-mode [style*="color:#3b82f6"] {
    color: #93c5fd !important;
}

body.dark-mode [style*="color:#94a3b8"],
body.dark-mode [style*="color:#64748b"] {
    color: var(--lbai-text-muted) !important;
}

/* Class-painted equivalents of the same inks. */
body:not(.dark-mode) .lbaid-badgecard .st,
body:not(.dark-mode) .lbaid-avail__field label {
    color: #047857;
}

body:not(.dark-mode) .lbaid-doc__badge.red {
    color: #b91c1c;
}

/* =====================================================================================
   25. LIGHT-MODE ICON HUES BELOW THE 3:1 NON-TEXT MINIMUM
   =====================================================================================
     #d8dee9 empty rating stars        1.35:1
     #cbd5e1 empty-state bell          1.48:1
     #eab308 trusted-badge glyph       1.92:1
     #f59e0b filled stars / mail glyph 2.02-2.15:1
     #22c55e verified tick             2.28:1
     #94a3b8 header search / sheet     2.34-2.56:1
     #10b981 location pin              2.54:1
     #1da1f2 blue verification tick    2.83:1
     #d97706 cart glyph                2.95:1
   Each is darkened to the shallowest shade of its own hue that clears 3:1 on its measured
   surface, so the iconography still reads as the same colour.
   ===================================================================================== */
body:not(.dark-mode) .lbai-stars__base svg,
body:not(.dark-mode) .ail-empty-state .dashicons,
body:not(.dark-mode) .lbaid-empty .dashicons,
body:not(.dark-mode) .dashicons-star-empty {
    color: #767f8c !important;
    fill: currentColor;
}

body:not(.dark-mode) .lbai-stars__fill svg,
body:not(.dark-mode) .lbai-badge--trusted .lbai-badge__icon,
body:not(.dark-mode) .lbaid-stat__ic .dashicons,
body:not(.dark-mode) .ail-provider-card__meta-pill .dashicons-star-filled {
    color: #a15c07 !important;
}

body:not(.dark-mode) .lbai-ver-card .dashicons-yes-alt,
body:not(.dark-mode) .ail-city-item .dashicons-location {
    color: #047857 !important;
}

body:not(.dark-mode) .ail-hdr-search svg,
body:not(.dark-mode) .ail-search-input .dashicons {
    color: #5c6a7d !important;
}

body:not(.dark-mode) .lbai-tick--blue_tick .lbai-badge__icon {
    color: #1583c7 !important;
}

body:not(.dark-mode) .ail-module-card .dashicons-cart {
    color: #a15c07 !important;
}

/* REGRESSION FIX, introduced by section 19 and caught by re-measurement.
   Section 19 darkened .dashicons-star-filled to the accessible amber. One instance of that glyph
   sits INSIDE a saturated primary button (.lbai-bkc__btn--primary, fill #4f46e5), where amber on
   indigo measured 1.21:1. A glyph on a saturated fill takes the on-accent ink, never a hue. */
.lbai-bkc__btn--primary .dashicons,
.lbai-bkc__btn--primary,
.ail-action-btn .dashicons,
.lbaid-mladd .dashicons {
    color: var(--lbai-text-on-accent) !important;
}

/* =====================================================================================

   26. CUSTOMER AND STAFF DASHBOARD INKS
   =====================================================================================
   Found when the customer-role and staff-role dashboards were added to the measured corpus.
   The dark-mode pass measured the homepage plus eight VENDOR tabs; these two role variants
   render panels the vendor view does not, so these are pre-existing failures newly discovered
   rather than regressions:

     a.ail-drawer-link "Verify to Add Listing"   #b45309 on #16213e   3.17:1   (dark)
     div.lbaid-empty  "Nothing viewed yet..."    #64748b on #f5f6fb   4.41:1   (light)
   ===================================================================================== */

/* The amber CTA in the customer drawer. Same hue, lightened for a dark surface — the mirror of
   what section 24 does for the light scheme. */
body.dark-mode [style*="color:#b45309"],
body.dark-mode [style*="color: #b45309"],
body.dark-mode [style*="color:#a15c07"],
body.dark-mode [style*="color: #a15c07"] {
    color: #fcd34d !important;
}

body.dark-mode .ail-drawer-link[href*="verification"],
body.dark-mode .ail-drawer-link[href*="verify"] {
    --lbai-text: #fcd34d;
    color: #fcd34d !important;
}

/* The recently-viewed empty state sits on #f5f6fb, where #64748b lands just under AA. */
body:not(.dark-mode) .lbaid-empty,
body:not(.dark-mode) .lbaid-rv .lbaid-empty {
    color: #4b5563;
}

/* =====================================================================================

   27. FAVOURITED HEART — CORRECTING AN OVER-REACH IN SECTION 18
   =====================================================================================
   Section 18 added, to fix a card heart measured at #000000 on #323c4d (1.89:1):

       body.dark-mode .lbai-card__fav,
       body.dark-mode .ail-fav-btn { color: var(--lbai-text) !important; }

   That is correct for the RESTING state and wrong for the FAVOURITED one. Because it carries
   !important at (0,2,0), it outranks single-listing-v2.css's
   `body.dark-mode .ail-lhdr__btn.ail-fav-btn.active { color: #f87171 }` at (0,4,0) — !important
   beats specificity — so in dark mode the saved heart kept the body ink instead of turning red.

   Measured on the single listing, favourited state:
       light   ink #ef4444 on #fef2f2   3.44:1   red, correct
       dark    ink #f1f5f9 on #3b1d20  13.86:1   WHITE - the surface and border went red but the
                                                 glyph did not, weakening the saved/unsaved cue

   Restated here rather than by adding :not(.active) to section 18, so that BOTH heart populations
   (the card overlay and the listing action row) get an explicit, measured value in the favourited
   state instead of falling back to whichever base rule happens to match. (0,3,0) with !important
   outranks section 18's (0,2,0).

   #f87171 is the dark-mode red single-listing-v2.css already chose for this state; it measures
   5.51:1 on the #3b1d20 pill, so the cue is restored without a new colour entering the palette. */
body.dark-mode .lbai-card__fav.active,
body.dark-mode .ail-fav-btn.active {
    color: #f87171 !important;
}

body.dark-mode .lbai-card__fav.active svg,
body.dark-mode .ail-fav-btn.active svg {
    fill: currentColor;
}

/* =====================================================================================

   28. ADD-LISTING WIZARD — P1 FOUND BY THE PRE-LAUNCH AUDIT
   =====================================================================================
   The add-listing template entered the measured corpus for the first time during the launch
   audit. In dark mode its plan-selection step was unreadable:

     h2.lbai-section-title  "Choose a Listing Plan"     #f1f5f9 on #ffffff   1.10:1
     p.lbai-section-desc    "Select a package ..."      #f1f5f9 on #ffffff   1.10:1
     h3.lbai-plan-name      "free plan"                 #f1f5f9 on #ffffff   1.10:1
     div.lbai-plan-price    "Free"                      #6ee7a8 on #ffffff   1.54:1
   and in LIGHT mode the wizard's own primary CTA was unreadable while disabled:
     button.lbai-btn-primary:disabled                   #ffffff on #cbd5e1   1.48:1

   ROOT CAUSE: `.lbai-card` is a CLASS-NAME COLLISION. listing-card.css:1731 already carries
   `body.dark-mode .lbai-card { background:#16213e }`, but that file is only enqueued on pages
   that render listing CARDS. template-add-listing.php defines its OWN `.lbai-card` (a wizard
   panel) in an inline <style> with no dark counterpart, so on that route the panel stays #ffffff
   while this layer's ink rule correctly paints the text near-white. Same class, two components,
   one of them with no dark-mode definition on the route where it is used.

   Fixed here rather than in the template: the template's <style> is emitted after wp_head(), so
   load order cannot beat it, but `body.dark-mode .thing` at (0,2,0) beats its (0,1,0) on
   specificity. Values match listing-card.css so the two definitions cannot disagree.
   ===================================================================================== */
body.dark-mode .lbai-card,
body.dark-mode .lbai-plan-card,
body.dark-mode .ail-plan-card {
    background-color: var(--lbai-surface) !important;
    border-color: var(--lbai-border) !important;
    --lbai-text: #f1f5f9;
}

/* The selected plan keeps its violet meaning as a dark tint of the same hue. */
body.dark-mode .lbai-plan-card.selected,
body.dark-mode .ail-plan-card.selected {
    background-color: rgba(109, 94, 252, .20) !important;
    border-color: var(--lbai-accent) !important;
}

body.dark-mode .lbai-section-title,
body.dark-mode .lbai-plan-name,
body.dark-mode .lbai-page-title {
    color: var(--lbai-text-strong) !important;
}

body.dark-mode .lbai-section-desc,
body.dark-mode .lbai-plan-meta {
    color: var(--lbai-text-muted) !important;
}

/* Plan price: same hue, accessible depth in each scheme. 26-30px counts as large text (3:1),
   but both values below clear 4.5:1 so the figure reads at any size. */
body:not(.dark-mode) .lbai-plan-price {
    color: #047857;
}

body.dark-mode .lbai-plan-price {
    color: #6ee7a8 !important;
}

/* The wizard's disabled CTA. The grey fill is the disabled AFFORDANCE and is kept; only the ink
   is darkened so the label stays legible. #475569 on #cbd5e1 measures 4.99:1, versus 1.48:1 for
   the white it had. WCAG exempts inactive controls, but an unreadable "Next" step on the vendor's
   listing-creation path is a usability defect regardless of the exemption. */
.lbai-btn-primary:disabled,
.lbai-btn:disabled {
    color: #475569 !important;
}

/* P3 swept up in the same pass: the homepage "Closed" badge measured #f1f5f9 on #6b7280 = 4.41:1,
   0.09 short of AA. --muted-color is used as both an ink and a fill elsewhere so it is not
   re-pointed globally; only this badge's fill is deepened. */
body.dark-mode .lbai-card__badge.is-closed {
    background-color: #4b5563 !important;
}

/* =====================================================================================

   29. ADD-LISTING WIZARD — ITS OWN TOKEN LAYER
   =====================================================================================
   template-add-listing.php:307 declares its OWN :root token set, and two of those names collide
   with this layer's: --lbai-text and --lbai-border. That collision is benign and in fact helpful —
   `body.dark-mode` (0,1,1) outranks `:root` (0,1,0), so the wizard's --lbai-text consumers already
   receive the dark value, which is why the plan titles read correctly.

   The names this layer does NOT own stay at their light-mode values in dark mode:
       --lbai-muted : #64748b   ->  .lbai-plan-duration measured 3.34:1 on #16213e
   together with the literal inks the template hardcodes:
       #334155      ->  .lbai-plan-feat-item measured 1.53:1
       #475569      ->  .lbai-plan-features / .lbai-btn-secondary / .lbai-draft-discard
       #94a3b8      ->  .lbai-field-note / .lbai-char-counter / placeholder
       #3730a3      ->  .lbai-tag ink on a pale tag fill

   Fixed at the token level plus one selector group, so the whole wizard is covered in a single
   pass rather than one failing element at a time.

   --lbai-primary is deliberately NOT re-pointed: the template uses it as a FILL (the primary CTA
   gradient, .lbai-plan-badge) as well as an ink, so lightening it would put white text on a light
   purple. The ink consumers are handled by class instead.
   ===================================================================================== */
body.dark-mode {
    --lbai-muted: #a5b4c8;
}

body.dark-mode .lbai-plan-feat-item,
body.dark-mode .lbai-plan-features,
body.dark-mode .lbai-hours-row,
body.dark-mode .lbai-btn-secondary,
body.dark-mode .lbai-draft-discard,
body.dark-mode .lbai-field {
    color: #cbd5e1 !important;
}

body.dark-mode .lbai-field-note,
body.dark-mode .lbai-char-counter,
body.dark-mode .lbai-plan-duration,
body.dark-mode .lbai-hours-sep {
    color: #a5b4c8 !important;
}

body.dark-mode .lbai-input::placeholder,
body.dark-mode .lbai-tag-input::placeholder {
    color: var(--lbai-placeholder) !important;
    opacity: 1;
}

/* Wizard surfaces the template paints from its own light tokens. */
body.dark-mode .lbai-input,
body.dark-mode .lbai-tag-input,
body.dark-mode .lbai-upload-area,
body.dark-mode .lbai-hours-row,
body.dark-mode .lbai-draft-restore-bar {
    background-color: var(--lbai-input-bg) !important;
    border-color: var(--lbai-input-border) !important;
    color: var(--lbai-input-text) !important;
}

/* The keyword tag keeps its indigo meaning as a dark tint with a light ink of the same hue. */
body.dark-mode .lbai-tag {
    background-color: rgba(99, 102, 241, .22) !important;
    color: #c7d2fe !important;
}

body.dark-mode .lbai-upload-area {
    color: #a5b4c8 !important;
}

/* The wizard's Back control is its own white pill (template inline style, no dark counterpart),
   so its icon measured #a5b4c8 on #ffffff = 2.11:1. Given the elevated surface it reads at 6.4:1. */
body.dark-mode .lbai-back-btn {
    background-color: var(--lbai-surface-2) !important;
    border-color: var(--lbai-border) !important;
}

body.dark-mode .lbai-back-btn,
body.dark-mode .lbai-back-btn .dashicons {
    color: #cbd5e1 !important;
}