/* Readable text on solid brand backgrounds.
 *
 * These rules exist because AdminKit paints card titles (--bs-card-title-color:
 * #939ba2) and muted text a mid grey that disappears on a solid .bg-* fill.
 *
 * They used to hardcode `color: #fff`, which assumed every brand colour is dark.
 * It isn't: white on the DEFAULT --bs-warning (#ffc107) measures 1.63:1, far
 * below the WCAG AA 4.5:1 floor, and a tenant who brands on yellow/mint/sky
 * broke every other fill too. The foreground now comes from --bs-on-*, emitted
 * per tenant by BusinessTheme#on_color_tokens, which picks white or #212529 by
 * measured contrast against that tenant's actual brand colour.
 *
 * The fallbacks matter: a layout that loads this file without the tenant theme
 * (layouts/ask_ai, layouts/sweep) never gets the inline <style id="custom-theme">
 * block, so each var() carries the label BusinessTheme.on_color picks for the
 * fill such a page actually paints — AdminKit's own default of that colour.
 * Primary (#3b7ddd) and success (#1cbb8c) take dark ink: white on them reads
 * 4.07:1 and 2.46:1, the label on_color picks 5.16:1 and 6.27:1 (Console #2289).
 * Secondary (#6c757d) and danger (#dc3545) take white; info (#17a2b8) and
 * warning (#fcb92c) take #212529. spec/assets/color_text_fix_css_spec.rb holds
 * every fallback to on_color, so a change to either side fails there.
 */

/* The brand as INK on a surface that stays light in BOTH themes — a fixed
 * near-white chip or tint (#eff6ff, #eef3f9, #d8e9fb) that no dark rule
 * repaints: the news feed's reaction chips and composer controls, and the
 * dashboard builder. (The wiki reader's tags and the phone menu now follow the
 * theme, so they take --bs-link-color / --bs-on-subtle-primary instead.)
 * Under a pale brand the raw colour read 1.69:1 there (#9ECBFF on white,
 * Console #6311). In the light theme this is --bs-link-color: the brand
 * clamped by the tenant theme to AA against its light surfaces. The dark
 * theme's --bs-link-color is clamped against DARK surfaces and would go
 * lighter still on these; there it is --bs-primary-band, the (lifted) brand
 * deepened until white on it clears AA — so it reads on a near-white chip
 * too, where the raw lifted brand read 4.04:1 (default) and ~1.5:1 (pale).
 * A surface that follows the theme takes --bs-link-color itself.
 * Both are clamped against WHITE, and these chips are tinted (#d8e9fb,
 * #e7eefb), so each is deepened 15% toward black: the band alone read 3.74:1
 * on #d8e9fb in dark (AdminKit's #3b7ddd), and every brand measured — default,
 * #0077be, pale #9ECBFF, green, purple, yellow — now clears 4.5:1 on all eight
 * chip fills in both themes, worst 4.86:1 (/code-review 2026-10-09). */
:root {
  --bs-primary-ink-on-light: color-mix(in srgb, var(--bs-link-color, var(--bs-primary)) 85%, #000);
}
:root[data-theme="dark"] {
  --bs-primary-ink-on-light: color-mix(in srgb, var(--bs-primary-band, var(--bs-primary)) 85%, #000);
}

/* Primary background */
.bg-primary,
.card.bg-primary {
  color: var(--bs-on-primary, #000) !important;
}

.bg-primary h1,
.bg-primary h2,
.bg-primary h3,
.bg-primary h4,
.bg-primary h5,
.bg-primary h6,
.card.bg-primary h1,
.card.bg-primary h2,
.card.bg-primary h3,
.card.bg-primary h4,
.card.bg-primary h5,
.card.bg-primary h6,
.bg-primary .card-title,
.bg-primary .card-subtitle,
.card.bg-primary .card-title,
.card.bg-primary .card-subtitle {
  color: var(--bs-on-primary, #000) !important;
}

/* Success background */
.bg-success,
.card.bg-success {
  color: var(--bs-on-success, #212529) !important;
}

.bg-success h1,
.bg-success h2,
.bg-success h3,
.bg-success h4,
.bg-success h5,
.bg-success h6,
.card.bg-success h1,
.card.bg-success h2,
.card.bg-success h3,
.card.bg-success h4,
.card.bg-success h5,
.card.bg-success h6,
.bg-success .card-title,
.bg-success .card-subtitle,
.card.bg-success .card-title,
.card.bg-success .card-subtitle {
  color: var(--bs-on-success, #212529) !important;
}

/* Danger background */
.bg-danger,
.card.bg-danger {
  color: var(--bs-on-danger, #fff) !important;
}

.bg-danger h1,
.bg-danger h2,
.bg-danger h3,
.bg-danger h4,
.bg-danger h5,
.bg-danger h6,
.card.bg-danger h1,
.card.bg-danger h2,
.card.bg-danger h3,
.card.bg-danger h4,
.card.bg-danger h5,
.card.bg-danger h6,
.bg-danger .card-title,
.bg-danger .card-subtitle,
.card.bg-danger .card-title,
.card.bg-danger .card-subtitle {
  color: var(--bs-on-danger, #fff) !important;
}

/* Warning background — Bootstrap's own default (#ffc107) needs DARK text, which
   is why the fallback here differs from every other fill in this file. */
.bg-warning,
.card.bg-warning {
  color: var(--bs-on-warning, #212529) !important;
}

.bg-warning h1,
.bg-warning h2,
.bg-warning h3,
.bg-warning h4,
.bg-warning h5,
.bg-warning h6,
.card.bg-warning h1,
.card.bg-warning h2,
.card.bg-warning h3,
.card.bg-warning h4,
.card.bg-warning h5,
.card.bg-warning h6,
.bg-warning .card-title,
.bg-warning .card-subtitle,
.card.bg-warning .card-title,
.card.bg-warning .card-subtitle {
  color: var(--bs-on-warning, #212529) !important;
}

/* Info background — Bootstrap's default (#0dcaf0) is also a light cyan. */
.bg-info,
.card.bg-info {
  color: var(--bs-on-info, #212529) !important;
}

.bg-info h1,
.bg-info h2,
.bg-info h3,
.bg-info h4,
.bg-info h5,
.bg-info h6,
.card.bg-info h1,
.card.bg-info h2,
.card.bg-info h3,
.card.bg-info h4,
.card.bg-info h5,
.card.bg-info h6,
.bg-info .card-title,
.bg-info .card-subtitle,
.card.bg-info .card-title,
.card.bg-info .card-subtitle {
  color: var(--bs-on-info, #212529) !important;
}

/* Secondary background */
.bg-secondary,
.card.bg-secondary {
  color: var(--bs-on-secondary, #fff) !important;
}

.bg-secondary h1,
.bg-secondary h2,
.bg-secondary h3,
.bg-secondary h4,
.bg-secondary h5,
.bg-secondary h6,
.card.bg-secondary h1,
.card.bg-secondary h2,
.card.bg-secondary h3,
.card.bg-secondary h4,
.card.bg-secondary h5,
.card.bg-secondary h6,
.bg-secondary .card-title,
.bg-secondary .card-subtitle,
.card.bg-secondary .card-title,
.card.bg-secondary .card-subtitle {
  color: var(--bs-on-secondary, #fff) !important;
}

/* Dark background — --bs-dark isn't tenant-themable, and AdminKit's dark sheet
   flips it from #212529 to a near-white #e9eaec (and --bs-black to white). This
   block used to follow the flip with a dark label (--bs-on-dark #212529), which
   answered a bare `.bg-dark` and left every `bg-dark text-white` / `bg-black
   text-white` at 1.2:1 and 1.0:1 — and every author of those classes meant a
   dark surface: a video frame, an image lightbox, a code block, a tile or badge
   with white text (Digital Signage, Training's video fields, EPMS goal
   priorities, the news feed's GIF badge; Console #4035). So in the dark theme
   the fill keeps its meaning, at its own --bs-bg-opacity, and the label is white
   in both themes. Fill and label live together here because a label without
   its fill is the 1.2:1 this replaces; this file travels with shared/_head
   (the app shell, the Sites reader, the lesson player, Ask AI), while the
   marketing, customer-portal and Console layouts load neither it nor a dark
   theme. `btn-dark` is a button variant with its own palette
   (design_system.css block 24), not this utility.
   A 10% or 25% wash is not a dark surface: `badge bg-dark bg-opacity-10
   text-dark` is a faint neutral chip (Mango IQ's competitor and theme tags).
   It keeps the ink its author named and, in the dark theme, AdminKit's own
   light wash — the solid label drew white on the light theme's #e9e9ea chip
   at 1.21:1, and the dark fill sank the chip into the card at 1.02:1
   (/pre-merge, 2026-09-27). */
:root {
  --bs-on-dark: #ffffff;
}

:root[data-theme="dark"] .bg-dark:not(:where(.bg-opacity-10, .bg-opacity-25)) {
  background-color: rgba(33, 37, 41, var(--bs-bg-opacity, 1)) !important;
}

:root[data-theme="dark"] .bg-black:not(:where(.bg-opacity-10, .bg-opacity-25)) {
  background-color: rgba(0, 0, 0, var(--bs-bg-opacity, 1)) !important;
}

.bg-dark:not(:where(.bg-opacity-10, .bg-opacity-25)),
.card.bg-dark:not(:where(.bg-opacity-10, .bg-opacity-25)) {
  color: var(--bs-on-dark, #fff) !important;
}

.bg-dark h1,
.bg-dark h2,
.bg-dark h3,
.bg-dark h4,
.bg-dark h5,
.bg-dark h6,
.card.bg-dark h1,
.card.bg-dark h2,
.card.bg-dark h3,
.card.bg-dark h4,
.card.bg-dark h5,
.card.bg-dark h6,
.bg-dark .card-title,
.bg-dark .card-subtitle,
.card.bg-dark .card-title,
.card.bg-dark .card-subtitle {
  color: var(--bs-on-dark, #fff) !important;
}

/* Payroll / summary cards: figures inside a solid fill inherit the fill's
   foreground. Listed by class rather than swept with `*` — see the note on the
   descendant rules below. */
.bg-primary .total,
.bg-primary .payroll,
.bg-primary .hours,
.bg-primary .overtime {
  color: var(--bs-on-primary, #000) !important;
}

.bg-success .total,
.bg-success .payroll,
.bg-success .hours,
.bg-success .overtime {
  color: var(--bs-on-success, #212529) !important;
}

.bg-info .total,
.bg-info .payroll,
.bg-info .hours,
.bg-info .overtime {
  color: var(--bs-on-info, #212529) !important;
}

.bg-warning .total,
.bg-warning .payroll,
.bg-warning .hours,
.bg-warning .overtime {
  color: var(--bs-on-warning, #212529) !important;
}

.bg-danger .total,
.bg-danger .payroll,
.bg-danger .hours,
.bg-danger .overtime {
  color: var(--bs-on-danger, #fff) !important;
}

.bg-secondary .total {
  color: var(--bs-on-secondary, #fff) !important;
}

.bg-dark .total {
  color: var(--bs-on-dark, #fff) !important;
}

/* Descendant sweep for solid cards.
 *
 * This was `.card.bg-primary *`, which forced white onto EVERY descendant —
 * including children that carry their own background and therefore their own
 * correct foreground. A `.badge.bg-light` inside a `.bg-primary` card rendered
 * white-on-#f5f7fb at 1.06:1: invisible. The exclusion list below skips any
 * child that paints its own surface or states its own text colour, so those
 * components keep the contrast they were designed with. Layout utilities
 * (.text-center, .text-truncate) are deliberately NOT excluded — matching
 * `[class*="text-"]` would have dropped them out of the sweep as well.
 *
 * Excluding a component is not enough on its own: the sweep reached its
 * DESCENDANTS, so the glyph inside a `btn-light` on a solid card took the fill's
 * white at 1.07:1 while its label stayed dark, and every row of a dropdown
 * menu, list group, form field or nested white card drew white on white
 * (Console #4130, measured 2026-10-08; in the dark theme the dark label of a
 * light fill landed on the dark menu and list rows at 1.22:1). The trailing
 * `:where()` skips what sits inside a component that paints its own OPAQUE
 * surface — a solid button, a badge, a menu, a list row, a nested plain card,
 * a modal — so it keeps the ink that component sets (a glyph in a `badge
 * bg-light` read 1.22:1 in white). `:where()` adds no weight, so the rule wins
 * exactly where it did before.
 * Light surfaces (`bg-white`, `bg-light`, the subtle and pastel fills) and
 * form fields are skipped too: both themes paint them opaque, and a field's
 * typed text drew white on white here, or dark on the dark field at 1.09:1.
 * Only what is opaque is listed. An outline or link button, an alert and a
 * translucent wash let the fill show through, so their text still needs
 * the fill's label.
 */
.card.bg-primary *:not(.badge):not(.btn):not(.alert):not(.card):not([class*="bg-"]):not(.text-white):not(.text-dark):not(.text-black):not(.text-body):not(.text-muted):not(.text-primary):not(.text-secondary):not(.text-success):not(.text-danger):not(.text-warning):not(.text-info):not(:where(.dropdown-menu, .list-group-item, :is(.card.bg-primary, .card.bg-success, .card.bg-info, .card.bg-warning, .card.bg-danger, .card.bg-secondary, .card.bg-dark) :is(.btn:not([class*="btn-outline"], .btn-link), .badge, .dropdown-menu, .list-group-item, .modal, .offcanvas, .toast, .card:not([class*="bg-"])) *, .card :is(.form-control, .form-select), :is(.card.bg-primary, .card.bg-success, .card.bg-info, .card.bg-warning, .card.bg-danger, .card.bg-secondary, .card.bg-dark) :is(.bg-white, .bg-light, .bg-body, .bg-body-secondary, .bg-body-tertiary, .bg-primary-subtle, .bg-secondary-subtle, .bg-success-subtle, .bg-danger-subtle, .bg-warning-subtle, .bg-info-subtle, .bg-light-subtle, .bg-primary-light, .bg-secondary-light, .bg-success-light, .bg-danger-light, .bg-warning-light, .bg-info-light):not([class*="bg-opacity-"]) *)) {
  color: var(--bs-on-primary, #000) !important;
}

.card.bg-success *:not(.badge):not(.btn):not(.alert):not(.card):not([class*="bg-"]):not(.text-white):not(.text-dark):not(.text-black):not(.text-body):not(.text-muted):not(.text-primary):not(.text-secondary):not(.text-success):not(.text-danger):not(.text-warning):not(.text-info):not(:where(.dropdown-menu, .list-group-item, :is(.card.bg-primary, .card.bg-success, .card.bg-info, .card.bg-warning, .card.bg-danger, .card.bg-secondary, .card.bg-dark) :is(.btn:not([class*="btn-outline"], .btn-link), .badge, .dropdown-menu, .list-group-item, .modal, .offcanvas, .toast, .card:not([class*="bg-"])) *, .card :is(.form-control, .form-select), :is(.card.bg-primary, .card.bg-success, .card.bg-info, .card.bg-warning, .card.bg-danger, .card.bg-secondary, .card.bg-dark) :is(.bg-white, .bg-light, .bg-body, .bg-body-secondary, .bg-body-tertiary, .bg-primary-subtle, .bg-secondary-subtle, .bg-success-subtle, .bg-danger-subtle, .bg-warning-subtle, .bg-info-subtle, .bg-light-subtle, .bg-primary-light, .bg-secondary-light, .bg-success-light, .bg-danger-light, .bg-warning-light, .bg-info-light):not([class*="bg-opacity-"]) *)) {
  color: var(--bs-on-success, #212529) !important;
}

.card.bg-info *:not(.badge):not(.btn):not(.alert):not(.card):not([class*="bg-"]):not(.text-white):not(.text-dark):not(.text-black):not(.text-body):not(.text-muted):not(.text-primary):not(.text-secondary):not(.text-success):not(.text-danger):not(.text-warning):not(.text-info):not(:where(.dropdown-menu, .list-group-item, :is(.card.bg-primary, .card.bg-success, .card.bg-info, .card.bg-warning, .card.bg-danger, .card.bg-secondary, .card.bg-dark) :is(.btn:not([class*="btn-outline"], .btn-link), .badge, .dropdown-menu, .list-group-item, .modal, .offcanvas, .toast, .card:not([class*="bg-"])) *, .card :is(.form-control, .form-select), :is(.card.bg-primary, .card.bg-success, .card.bg-info, .card.bg-warning, .card.bg-danger, .card.bg-secondary, .card.bg-dark) :is(.bg-white, .bg-light, .bg-body, .bg-body-secondary, .bg-body-tertiary, .bg-primary-subtle, .bg-secondary-subtle, .bg-success-subtle, .bg-danger-subtle, .bg-warning-subtle, .bg-info-subtle, .bg-light-subtle, .bg-primary-light, .bg-secondary-light, .bg-success-light, .bg-danger-light, .bg-warning-light, .bg-info-light):not([class*="bg-opacity-"]) *)) {
  color: var(--bs-on-info, #212529) !important;
}

.card.bg-warning *:not(.badge):not(.btn):not(.alert):not(.card):not([class*="bg-"]):not(.text-white):not(.text-dark):not(.text-black):not(.text-body):not(.text-muted):not(.text-primary):not(.text-secondary):not(.text-success):not(.text-danger):not(.text-warning):not(.text-info):not(:where(.dropdown-menu, .list-group-item, :is(.card.bg-primary, .card.bg-success, .card.bg-info, .card.bg-warning, .card.bg-danger, .card.bg-secondary, .card.bg-dark) :is(.btn:not([class*="btn-outline"], .btn-link), .badge, .dropdown-menu, .list-group-item, .modal, .offcanvas, .toast, .card:not([class*="bg-"])) *, .card :is(.form-control, .form-select), :is(.card.bg-primary, .card.bg-success, .card.bg-info, .card.bg-warning, .card.bg-danger, .card.bg-secondary, .card.bg-dark) :is(.bg-white, .bg-light, .bg-body, .bg-body-secondary, .bg-body-tertiary, .bg-primary-subtle, .bg-secondary-subtle, .bg-success-subtle, .bg-danger-subtle, .bg-warning-subtle, .bg-info-subtle, .bg-light-subtle, .bg-primary-light, .bg-secondary-light, .bg-success-light, .bg-danger-light, .bg-warning-light, .bg-info-light):not([class*="bg-opacity-"]) *)) {
  color: var(--bs-on-warning, #212529) !important;
}

.card.bg-danger *:not(.badge):not(.btn):not(.alert):not(.card):not([class*="bg-"]):not(.text-white):not(.text-dark):not(.text-black):not(.text-body):not(.text-muted):not(.text-primary):not(.text-secondary):not(.text-success):not(.text-danger):not(.text-warning):not(.text-info):not(:where(.dropdown-menu, .list-group-item, :is(.card.bg-primary, .card.bg-success, .card.bg-info, .card.bg-warning, .card.bg-danger, .card.bg-secondary, .card.bg-dark) :is(.btn:not([class*="btn-outline"], .btn-link), .badge, .dropdown-menu, .list-group-item, .modal, .offcanvas, .toast, .card:not([class*="bg-"])) *, .card :is(.form-control, .form-select), :is(.card.bg-primary, .card.bg-success, .card.bg-info, .card.bg-warning, .card.bg-danger, .card.bg-secondary, .card.bg-dark) :is(.bg-white, .bg-light, .bg-body, .bg-body-secondary, .bg-body-tertiary, .bg-primary-subtle, .bg-secondary-subtle, .bg-success-subtle, .bg-danger-subtle, .bg-warning-subtle, .bg-info-subtle, .bg-light-subtle, .bg-primary-light, .bg-secondary-light, .bg-success-light, .bg-danger-light, .bg-warning-light, .bg-info-light):not([class*="bg-opacity-"]) *)) {
  color: var(--bs-on-danger, #fff) !important;
}

.card.bg-secondary *:not(.badge):not(.btn):not(.alert):not(.card):not([class*="bg-"]):not(.text-white):not(.text-dark):not(.text-black):not(.text-body):not(.text-muted):not(.text-primary):not(.text-secondary):not(.text-success):not(.text-danger):not(.text-warning):not(.text-info):not(:where(.dropdown-menu, .list-group-item, :is(.card.bg-primary, .card.bg-success, .card.bg-info, .card.bg-warning, .card.bg-danger, .card.bg-secondary, .card.bg-dark) :is(.btn:not([class*="btn-outline"], .btn-link), .badge, .dropdown-menu, .list-group-item, .modal, .offcanvas, .toast, .card:not([class*="bg-"])) *, .card :is(.form-control, .form-select), :is(.card.bg-primary, .card.bg-success, .card.bg-info, .card.bg-warning, .card.bg-danger, .card.bg-secondary, .card.bg-dark) :is(.bg-white, .bg-light, .bg-body, .bg-body-secondary, .bg-body-tertiary, .bg-primary-subtle, .bg-secondary-subtle, .bg-success-subtle, .bg-danger-subtle, .bg-warning-subtle, .bg-info-subtle, .bg-light-subtle, .bg-primary-light, .bg-secondary-light, .bg-success-light, .bg-danger-light, .bg-warning-light, .bg-info-light):not([class*="bg-opacity-"]) *)) {
  color: var(--bs-on-secondary, #fff) !important;
}

.card.bg-dark *:not(.badge):not(.btn):not(.alert):not(.card):not([class*="bg-"]):not(.text-white):not(.text-dark):not(.text-black):not(.text-body):not(.text-muted):not(.text-primary):not(.text-secondary):not(.text-success):not(.text-danger):not(.text-warning):not(.text-info):not(:where(.dropdown-menu, .list-group-item, :is(.card.bg-primary, .card.bg-success, .card.bg-info, .card.bg-warning, .card.bg-danger, .card.bg-secondary, .card.bg-dark) :is(.btn:not([class*="btn-outline"], .btn-link), .badge, .dropdown-menu, .list-group-item, .modal, .offcanvas, .toast, .card:not([class*="bg-"])) *, .card :is(.form-control, .form-select), :is(.card.bg-primary, .card.bg-success, .card.bg-info, .card.bg-warning, .card.bg-danger, .card.bg-secondary, .card.bg-dark) :is(.bg-white, .bg-light, .bg-body, .bg-body-secondary, .bg-body-tertiary, .bg-primary-subtle, .bg-secondary-subtle, .bg-success-subtle, .bg-danger-subtle, .bg-warning-subtle, .bg-info-subtle, .bg-light-subtle, .bg-primary-light, .bg-secondary-light, .bg-success-light, .bg-danger-light, .bg-warning-light, .bg-info-light):not([class*="bg-opacity-"]) *)) {
  color: var(--bs-on-dark, #fff) !important;
}

/* …and such a light surface that names no ink of its own reads like the page
 * it imitates: body ink, not the card's label it would otherwise inherit —
 * a `bg-white` box of text on a solid primary card drew white on white
 * (1.00:1, #4130's twin). Badges keep their own rules; an authored `text-*`
 * colour utility still wins. A layout utility (`text-center`, `text-truncate`,
 * `text-uppercase`…) is not an ink, so it does not opt a box out — matching
 * every `text-` class had left a `bg-white text-center` box white on white.
 * A `bg-white bg-opacity-25` is a translucent wash over the fill, not a light
 * box, so it keeps the fill's label (here and in the sweep's skip list above).
 * AdminKit's `bg-*-light` pastels stay pale in BOTH of its sheets (#dee9f9 in
 * dark.css too), so they take dark ink in both themes, not the dark theme's
 * light body ink. */
:is(.card.bg-primary, .card.bg-success, .card.bg-info, .card.bg-warning, .card.bg-danger, .card.bg-secondary, .card.bg-dark) :is(.bg-white, .bg-light, .bg-body, .bg-body-secondary, .bg-body-tertiary, .bg-primary-subtle, .bg-secondary-subtle, .bg-success-subtle, .bg-danger-subtle, .bg-warning-subtle, .bg-info-subtle, .bg-light-subtle):not(.badge, :is([class^="text-"], [class*=" text-"]):not(:where(.text-center, .text-start, .text-end, .text-truncate, .text-nowrap, .text-wrap, .text-break, .text-uppercase, .text-lowercase, .text-capitalize, [class*="text-decoration-"], [class*="text-sm-"], [class*="text-md-"], [class*="text-lg-"], [class*="text-xl-"], [class*="text-xxl-"])), [class*="bg-opacity-"]) {
  color: var(--bs-body-color);
}
:is(.card.bg-primary, .card.bg-success, .card.bg-info, .card.bg-warning, .card.bg-danger, .card.bg-secondary, .card.bg-dark) :is(.bg-primary-light, .bg-secondary-light, .bg-success-light, .bg-danger-light, .bg-warning-light, .bg-info-light):not(.badge, :is([class^="text-"], [class*=" text-"]):not(:where(.text-center, .text-start, .text-end, .text-truncate, .text-nowrap, .text-wrap, .text-break, .text-uppercase, .text-lowercase, .text-capitalize, [class*="text-decoration-"], [class*="text-sm-"], [class*="text-md-"], [class*="text-lg-"], [class*="text-xl-"], [class*="text-xxl-"])), [class*="bg-opacity-"]) {
  color: #212529;
}

/* NOTE — two rules were deleted here rather than fixed, because CSS cannot make
 * them correct:
 *
 *   [style*="background-color: #"]     { color: #fff !important; }
 *   .card[style*="background-color"]   { color: #fff !important; }
 *
 * A substring match on the style attribute cannot know how light the colour is.
 * The escape hatch that followed tested the FIRST HEX DIGIT (f/e/d/c), which is
 * not a lightness test: #c00000 (dark red) was read as light and got dark text,
 * while #a1e6ff (near-white) was read as dark and got white text at 1.4:1. Both
 * failure directions were live. Worse, the colours flowing into these rules are
 * admin-picked (leave-type colours, workspace card colours) and so can be any
 * lightness at all.
 *
 * Elements with an inline background now state their own foreground, computed by
 * the `contrast_color` helper in application_helper.rb — the pattern the leave
 * and password-manager badges already used. Do not reintroduce a blanket
 * attribute selector here; fix the view instead.
 */

/* Text within badges on a solid fill: badges carry their own background, so this
   only covers the ones that don't (.badge with no bg-* class inherits the card). */
.bg-primary .badge:not([class*="bg-"]) {
  color: var(--bs-on-primary, #000) !important;
}

.bg-success .badge:not([class*="bg-"]) {
  color: var(--bs-on-success, #212529) !important;
}

.bg-danger .badge:not([class*="bg-"]) {
  color: var(--bs-on-danger, #fff) !important;
}

.bg-warning .badge:not([class*="bg-"]) {
  color: var(--bs-on-warning, #212529) !important;
}

.bg-info .badge:not([class*="bg-"]) {
  color: var(--bs-on-info, #212529) !important;
}

.bg-secondary .badge:not([class*="bg-"]) {
  color: var(--bs-on-secondary, #fff) !important;
}

.bg-dark .badge:not([class*="bg-"]) {
  color: var(--bs-on-dark, #fff) !important;
}

/* AdminKit's pastel `.bg-*-light` fills — the third background family, and the
 * only one that had no foreground paired with it.
 *
 * AdminKit declares `.badge { color: #fff }` unconditionally and then declares
 * `.bg-success-light { background: #a5f1db }` (and siblings) with no colour at
 * all. A `<span class="badge bg-success-light">` therefore paints white on a
 * near-white pastel: measured on /apps/tasks/analytics, every status tag landed
 * between 1.06:1 (bg-warning-light) and 1.49:1 (bg-secondary-light), against a
 * WCAG AA floor of 4.5:1. `opacity` is 1 the whole time — the text just has
 * almost no contrast, which reads to users as a greyed-out, inactive tag.
 *
 * The pairing is Bootstrap's own `--bs-*-text-emphasis`, not the tenant
 * `--bs-on-subtle-*` used for `.bg-opacity-10` above: these pastels are FIXED
 * hex values that do not follow the tenant's brand, so a foreground computed
 * against a tenant-blended tint would be measured against the wrong background.
 * AdminKit ships the same pastels AND the same six emphasis values in both
 * light.css and dark.css, so one declaration is correct in both modes
 * (7.8:1–10.5:1 measured across the six).
 *
 * The values are AdminKit's emphasis inks as LITERALS (X1, 2026-09-27): the
 * dark theme now re-points `--bs-*-text-emphasis` at :root to the light ink
 * measured for its dark subtle washes (custom.css), which would put a light
 * ink on these light pastels. They pair with the pastel, not with the variable.
 *
 * Deliberately NOT `!important`: `.badge.bg-*-light` (0,2,0) already outranks
 * AdminKit's `.badge` (0,1,0), while Bootstrap's `.text-*` utilities carry
 * `!important` and keep winning — so the views that already state their own
 * foreground (`badge bg-success-light text-success`) are left exactly as they
 * were. `-light`/`-dark` are omitted: no view pairs them with `.badge`, and
 * unlike the six they are the one family whose pastel flips between modes.
 */
.badge.bg-primary-light {
  color: #183258;
}

.badge.bg-secondary-light {
  color: #2b2f32;
}

.badge.bg-success-light {
  color: #0b4b38;
}

.badge.bg-info-light {
  color: #09414a;
}

.badge.bg-warning-light {
  color: #654a12;
}

.badge.bg-danger-light {
  color: #58151c;
}

/* ── X1 (cross-app contrast, 2026-09-27): a tone's ink ON its pastel ─────────
   Half the pastel badges also name their tone (`badge bg-success-light
   text-success`, 51 in views), and the tone utility is the theme's ink clamped
   for the card, not for the pastel: 4.1:1 on #a5f1db in light, and the dark
   theme's light ink on the same fixed pastel 1.59:1 (a leave request's
   "Approved"). The pastel is the same in both themes, so the ink is the same
   emphasis literal as above; `:root` lifts the weight over the theme's
   `[data-theme="dark"] .text-{tone}` (0,2,0, !important). */
:root .bg-primary-light.text-primary,
:root .bg-primary-light .text-primary { color: #183258 !important; }
:root .bg-secondary-light.text-secondary,
:root .bg-secondary-light .text-secondary { color: #2b2f32 !important; }
:root .bg-success-light.text-success,
:root .bg-success-light .text-success { color: #0b4b38 !important; }
:root .bg-info-light.text-info,
:root .bg-info-light .text-info { color: #09414a !important; }
:root .bg-warning-light.text-warning,
:root .bg-warning-light .text-warning { color: #654a12 !important; }
:root .bg-danger-light.text-danger,
:root .bg-danger-light .text-danger { color: #58151c !important; }
/* ── end X1 ── */

/* For dark mode compatibility: AdminKit's dark sheet re-points --bs-white-rgb to
 * navy, so `.text-white` would paint #222e3c. Not on a solid tone fill, though:
 * there the fill's own measured label (`.bg-{tone}` above, --bs-on-{tone}) is the
 * answer, and this rule used to outrank it (0,2,0 over 0,1,0). The dark theme
 * lifts every brand colour 20% toward white, so a pale fill under a hard-coded
 * `text-white` drew white on the lifted accent: initial discs and kanban headers
 * 1.94:1 on bg-secondary, 2.45:1 on bg-success, 1.66:1 on bg-warning, 1.75:1 on
 * bg-info (Console #3998). `:where()` keeps this rule's weight where it was. */
[data-bs-theme="dark"] .text-white:not(:where(.bg-primary, .bg-secondary, .bg-success, .bg-danger, .bg-warning, .bg-info)),
[data-theme="dark"] .text-white:not(:where(.bg-primary, .bg-secondary, .bg-success, .bg-danger, .bg-warning, .bg-info)) {
  color: #fff !important;
}

/* …and a HEADING on a solid tone fill keeps the fill's label too. The tenant
 * theme's dark heading rule (`[data-theme="dark"] .h6 { color: … !important }`,
 * BusinessTheme#generate_dark_css_from_config) outranks the `.bg-{tone} h1…h6`
 * rules at the top of this file (0,2,0 over 0,1,1), so Tasks' kanban column
 * headers wrote the theme's heading grey on the lifted fills: 1.38:1 on
 * bg-warning, 1.45:1 on bg-info, 2.04:1 on bg-success (#3998's twin).
 * SOLID fills only: a `bg-{tone} bg-opacity-*` wash is not the fill the label
 * was measured for, and its headings keep the ink they had (`.bg-{tone}.bg-
 * opacity-10 *` below, a `text-{tone}` on the heading). Unscoped, this drew
 * #212529 on Talent Hub's translucent pipeline headers in the dark theme —
 * 1.19:1 "Qualified", 1.26:1 the warning column (/pre-merge, 2026-09-27).
 * `:where()` keeps the weight at 0,4,0. */
:root[data-theme="dark"] .bg-primary:not(:where([class*="bg-opacity-"])) :is(h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6) { color: var(--bs-on-primary, #000) !important; }
:root[data-theme="dark"] .bg-secondary:not(:where([class*="bg-opacity-"])) :is(h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6) { color: var(--bs-on-secondary, #fff) !important; }
:root[data-theme="dark"] .bg-success:not(:where([class*="bg-opacity-"])) :is(h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6) { color: var(--bs-on-success, #212529) !important; }
:root[data-theme="dark"] .bg-danger:not(:where([class*="bg-opacity-"])) :is(h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6) { color: var(--bs-on-danger, #fff) !important; }
:root[data-theme="dark"] .bg-warning:not(:where([class*="bg-opacity-"])) :is(h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6) { color: var(--bs-on-warning, #212529) !important; }
:root[data-theme="dark"] .bg-info:not(:where([class*="bg-opacity-"])) :is(h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6) { color: var(--bs-on-info, #212529) !important; }

/* A filled outline button's label is the one measured for its fill — the twin
 * of design_system.css block 23 (Console #4034) for the layouts that load this
 * file but not design_system.css, whose block is scoped to the app shell's
 * body.mgx-restyle: the Sites reader's expanded view and public share link
 * (layouts/site_reader), the lesson player, Ask AI, the sweep. AdminKit paints
 * the hovered or pressed label a literal white at 0,4,0 over the
 * --bs-btn-hover-color / --bs-btn-active-color the tenant theme measured; on
 * the expanded reader the reactions bar's "React" (outline-secondary, the pale
 * accent #f7931e) went white at 2.3:1 under the pointer (/pre-merge,
 * 2026-09-27). Same weight as AdminKit's rule, later in the cascade. */
:where(body:not(.mgx-restyle)) :is(.btn-outline-primary, .btn-outline-secondary, .btn-outline-success, .btn-outline-info, .btn-outline-warning, .btn-outline-danger, .btn-outline-dark, .btn-outline-light):is(:hover, .hover):not(:disabled):not(.disabled) {
  color: var(--bs-btn-hover-color);
}
:where(body:not(.mgx-restyle)) :is(.btn-outline-primary, .btn-outline-secondary, .btn-outline-success, .btn-outline-info, .btn-outline-warning, .btn-outline-danger, .btn-outline-dark, .btn-outline-light):not(:disabled):not(.disabled):is(:active, .active) {
  color: var(--bs-btn-active-color);
}

/* ── X1 (cross-app contrast, 2026-09-27): `btn-light` has an edge ──────────
   The twin of design_system.css block 25 (Console #4107) for the layouts that
   load this file but not design_system.css: the button's border is the
   control boundary instead of its own fill, which floated it at 1.07:1 on a
   white card and 1.06:1 on the dark one. --ctl-border lives on
   body.mgx-restyle, so these layouts take its values directly: custom.css's
   --control-border-color (#868e96) light, #767e86 dark (/pre-merge xr). */
:where(body:not(.mgx-restyle)) .btn-light {
  --bs-btn-border-color: var(--control-border-color, #868e96);
  --bs-btn-hover-border-color: var(--control-border-color, #868e96);
  --bs-btn-active-border-color: var(--control-border-color, #868e96);
  --bs-btn-disabled-border-color: var(--control-border-color, #868e96);
}
:where(:root[data-theme="dark"] body:not(.mgx-restyle)) .btn-light {
  --bs-btn-border-color: #767e86;
  --bs-btn-hover-border-color: #767e86;
  --bs-btn-active-border-color: #767e86;
  --bs-btn-disabled-border-color: #767e86;
}
/* …and design_system.css block 26's twin: a card title outside a header
   inherits its card's ink instead of AdminKit's light #939ba2 (2.81:1). */
:where(:root:not([data-theme="dark"]) body:not(.mgx-restyle)) .card-title { color: inherit; }
/* ── end X1 ── */

/* Fix for chart containers to prevent scrolling issues */
.chart-container {
  overflow: visible;
  position: relative;
}

.chart-container canvas {
  max-height: 100%;
}

/* Fix for payroll chart specifically */
#payrollChart {
  height: 100%;
  width: 100%;
  max-height: none;
  max-width: none;
}

/* Ensure chart container cards have proper padding */
.card-body.d-flex.align-items-center.justify-content-center {
  padding: 1rem;
  overflow: hidden;
}

/* Chart container styling - updated for better dimensions */
.chart-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 280px;
  position: relative;
  padding: 1rem;
  overflow: visible;
}

.chart-center-container {
  position: relative;
  height: 230px;
  width: auto;
  aspect-ratio: 1/1;
  margin: 0 auto;
}

/* Fix pie chart legend and layout */
#payrollChart {
  margin: 0 auto;
}

/* Component Style Text Color Fixes */
/* Override the global white text rules for subtle (10% opacity) backgrounds */
/* These need colored text, not white text, for proper contrast.
 *
 * The colour is --bs-on-subtle-* rather than the raw --bs-* it used to be. A
 * 10% tint of a colour is a poor background FOR that same colour: the raw brand
 * on its own tint measured 2.93:1 with the default blue on a dark card, and on a
 * pale brand it disappears outright. BusinessTheme#subtle_on_color_tokens
 * already computes the readable variant against the actual blended tint and
 * emits it at :root in both modes — this just consumes it. The raw brand stays
 * as the var() fallback for surfaces that render without a theme block.
 *
 * A solid button inside the wash is skipped (`:not(:where(…))`, no added
 * weight): it paints its own fill, and the sweep handed it the header's ink — a
 * `btn-primary` in a `card-header bg-primary bg-opacity-10` drew dark ink on
 * the brand at 2.47:1, and a `btn-light` in the dark theme 1.12:1 (Console
 * #4130's twin, 2026-10-08). Its glyph and label inherit from the button; the
 * rules that paint a tone's ink skip the glyph too, or it would take that ink.
 * An outline or link button has no fill of its own and keeps the wash's ink.
 */

.bg-primary.bg-opacity-10,
.bg-primary.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.card-header.bg-primary.bg-opacity-10,
.card-header.bg-primary.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.modal-header.bg-primary.bg-opacity-10,
.modal-header.bg-primary.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.modal-footer.bg-primary.bg-opacity-10,
.modal-footer.bg-primary.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))) {
  color: inherit !important;
}

.bg-primary.bg-opacity-10.text-primary,
.bg-primary.bg-opacity-10.text-primary *:not(:where(.btn:not([class*="btn-outline"], .btn-link), .btn:not([class*="btn-outline"], .btn-link) *)),
.card-header.bg-primary.bg-opacity-10.text-primary h1,
.card-header.bg-primary.bg-opacity-10.text-primary h2,
.card-header.bg-primary.bg-opacity-10.text-primary h3,
.card-header.bg-primary.bg-opacity-10.text-primary h4,
.card-header.bg-primary.bg-opacity-10.text-primary h5,
.card-header.bg-primary.bg-opacity-10.text-primary h6 {
  color: var(--bs-on-subtle-primary, var(--bs-primary)) !important;
}

.bg-secondary.bg-opacity-10,
.bg-secondary.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.card-header.bg-secondary.bg-opacity-10,
.card-header.bg-secondary.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.modal-header.bg-secondary.bg-opacity-10,
.modal-header.bg-secondary.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.modal-footer.bg-secondary.bg-opacity-10,
.modal-footer.bg-secondary.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))) {
  color: inherit !important;
}

.bg-secondary.bg-opacity-10.text-secondary,
.bg-secondary.bg-opacity-10.text-secondary *:not(:where(.btn:not([class*="btn-outline"], .btn-link), .btn:not([class*="btn-outline"], .btn-link) *)),
.card-header.bg-secondary.bg-opacity-10.text-secondary h1,
.card-header.bg-secondary.bg-opacity-10.text-secondary h2,
.card-header.bg-secondary.bg-opacity-10.text-secondary h3,
.card-header.bg-secondary.bg-opacity-10.text-secondary h4,
.card-header.bg-secondary.bg-opacity-10.text-secondary h5,
.card-header.bg-secondary.bg-opacity-10.text-secondary h6 {
  color: var(--bs-on-subtle-secondary, var(--bs-secondary)) !important;
}

.bg-success.bg-opacity-10,
.bg-success.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.card-header.bg-success.bg-opacity-10,
.card-header.bg-success.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.modal-header.bg-success.bg-opacity-10,
.modal-header.bg-success.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.modal-footer.bg-success.bg-opacity-10,
.modal-footer.bg-success.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))) {
  color: inherit !important;
}

.bg-success.bg-opacity-10.text-success,
.bg-success.bg-opacity-10.text-success *:not(:where(.btn:not([class*="btn-outline"], .btn-link), .btn:not([class*="btn-outline"], .btn-link) *)),
.card-header.bg-success.bg-opacity-10.text-success h1,
.card-header.bg-success.bg-opacity-10.text-success h2,
.card-header.bg-success.bg-opacity-10.text-success h3,
.card-header.bg-success.bg-opacity-10.text-success h4,
.card-header.bg-success.bg-opacity-10.text-success h5,
.card-header.bg-success.bg-opacity-10.text-success h6 {
  color: var(--bs-on-subtle-success, var(--bs-success)) !important;
}

.bg-info.bg-opacity-10,
.bg-info.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.card-header.bg-info.bg-opacity-10,
.card-header.bg-info.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.modal-header.bg-info.bg-opacity-10,
.modal-header.bg-info.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.modal-footer.bg-info.bg-opacity-10,
.modal-footer.bg-info.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))) {
  color: inherit !important;
}

.bg-info.bg-opacity-10.text-info,
.bg-info.bg-opacity-10.text-info *:not(:where(.btn:not([class*="btn-outline"], .btn-link), .btn:not([class*="btn-outline"], .btn-link) *)),
.card-header.bg-info.bg-opacity-10.text-info h1,
.card-header.bg-info.bg-opacity-10.text-info h2,
.card-header.bg-info.bg-opacity-10.text-info h3,
.card-header.bg-info.bg-opacity-10.text-info h4,
.card-header.bg-info.bg-opacity-10.text-info h5,
.card-header.bg-info.bg-opacity-10.text-info h6 {
  color: var(--bs-on-subtle-info, var(--bs-info)) !important;
}

.bg-warning.bg-opacity-10,
.bg-warning.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.card-header.bg-warning.bg-opacity-10,
.card-header.bg-warning.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.modal-header.bg-warning.bg-opacity-10,
.modal-header.bg-warning.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.modal-footer.bg-warning.bg-opacity-10,
.modal-footer.bg-warning.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))) {
  color: inherit !important;
}

.bg-warning.bg-opacity-10.text-dark,
.bg-warning.bg-opacity-10.text-dark *:not(:where(.btn:not([class*="btn-outline"], .btn-link), .btn:not([class*="btn-outline"], .btn-link) *)),
.card-header.bg-warning.bg-opacity-10.text-dark h1,
.card-header.bg-warning.bg-opacity-10.text-dark h2,
.card-header.bg-warning.bg-opacity-10.text-dark h3,
.card-header.bg-warning.bg-opacity-10.text-dark h4,
.card-header.bg-warning.bg-opacity-10.text-dark h5,
.card-header.bg-warning.bg-opacity-10.text-dark h6 {
  color: var(--bs-dark) !important;
}

.bg-danger.bg-opacity-10,
.bg-danger.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.card-header.bg-danger.bg-opacity-10,
.card-header.bg-danger.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.modal-header.bg-danger.bg-opacity-10,
.modal-header.bg-danger.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))),
.modal-footer.bg-danger.bg-opacity-10,
.modal-footer.bg-danger.bg-opacity-10 *:not(:where(.btn:not([class*="btn-outline"], .btn-link))) {
  color: inherit !important;
}

.bg-danger.bg-opacity-10.text-danger,
.bg-danger.bg-opacity-10.text-danger *:not(:where(.btn:not([class*="btn-outline"], .btn-link), .btn:not([class*="btn-outline"], .btn-link) *)),
.card-header.bg-danger.bg-opacity-10.text-danger h1,
.card-header.bg-danger.bg-opacity-10.text-danger h2,
.card-header.bg-danger.bg-opacity-10.text-danger h3,
.card-header.bg-danger.bg-opacity-10.text-danger h4,
.card-header.bg-danger.bg-opacity-10.text-danger h5,
.card-header.bg-danger.bg-opacity-10.text-danger h6 {
  color: var(--bs-on-subtle-danger, var(--bs-danger)) !important;
}

/* `text-white` INSIDE a solid tone fill — the glyph in a `rounded-circle bg-warning`
 * disc, a label in a `bg-info` strip, an icon in a `btn-warning`. The same element
 * is answered by `.bg-{tone}` above; a CHILD carrying `text-white` was excluded from
 * every rule in this file, so it painted white on the tenant's tone whatever that
 * tone is — 1.72:1 on the default warning and 1.96:1 on info in the light theme,
 * 1.56:1 / 1.75:1 in the dark one (measured 2026-10-05, defect class
 * colour-pair-fails-contrast). It takes the fill's measured label, like the fill's
 * own text. A child or grandchild only; never one that paints its own fill (a
 * nested bg-*, a badge, a button), and never under a translucent bg-opacity wash.
 * (0,3,0)+ with !important, so it also outranks the dark `.text-white` rule above. */
:is(.bg-primary, .btn-primary):not([class*="bg-opacity-"]) > .text-white:not([class*="bg-"], .badge, .btn),
:is(.bg-primary, .btn-primary):not([class*="bg-opacity-"]) > :not([class*="bg-"], .badge, .btn, .card, .dropdown-menu) > .text-white:not([class*="bg-"], .badge, .btn) {
  color: var(--bs-on-primary, #000) !important;
}
:is(.bg-secondary, .btn-secondary):not([class*="bg-opacity-"]) > .text-white:not([class*="bg-"], .badge, .btn),
:is(.bg-secondary, .btn-secondary):not([class*="bg-opacity-"]) > :not([class*="bg-"], .badge, .btn, .card, .dropdown-menu) > .text-white:not([class*="bg-"], .badge, .btn) {
  color: var(--bs-on-secondary, #fff) !important;
}
:is(.bg-success, .btn-success):not([class*="bg-opacity-"]) > .text-white:not([class*="bg-"], .badge, .btn),
:is(.bg-success, .btn-success):not([class*="bg-opacity-"]) > :not([class*="bg-"], .badge, .btn, .card, .dropdown-menu) > .text-white:not([class*="bg-"], .badge, .btn) {
  color: var(--bs-on-success, #212529) !important;
}
:is(.bg-danger, .btn-danger):not([class*="bg-opacity-"]) > .text-white:not([class*="bg-"], .badge, .btn),
:is(.bg-danger, .btn-danger):not([class*="bg-opacity-"]) > :not([class*="bg-"], .badge, .btn, .card, .dropdown-menu) > .text-white:not([class*="bg-"], .badge, .btn) {
  color: var(--bs-on-danger, #fff) !important;
}
:is(.bg-warning, .btn-warning):not([class*="bg-opacity-"]) > .text-white:not([class*="bg-"], .badge, .btn),
:is(.bg-warning, .btn-warning):not([class*="bg-opacity-"]) > :not([class*="bg-"], .badge, .btn, .card, .dropdown-menu) > .text-white:not([class*="bg-"], .badge, .btn) {
  color: var(--bs-on-warning, #212529) !important;
}
:is(.bg-info, .btn-info):not([class*="bg-opacity-"]) > .text-white:not([class*="bg-"], .badge, .btn),
:is(.bg-info, .btn-info):not([class*="bg-opacity-"]) > :not([class*="bg-"], .badge, .btn, .card, .dropdown-menu) > .text-white:not([class*="bg-"], .badge, .btn) {
  color: var(--bs-on-info, #212529) !important;
}
/* …except inside a status badge the app shell re-skins as a soft chip
 * (design_system.css block 22: `body.mgx-restyle .badge.bg-{tone}` that is not a
 * pill or a corner dot). Its fill is the tone's pale tint (a translucent wash in
 * dark), not the solid tone the rules above measure for, so `--bs-on-<tone>` drew
 * dark ink on the dark chip (1.9:1) and the old white drew 1.3:1 on the light one —
 * the "×" that clears a filter chip. A text-white child takes the chip's own ink.
 * (0,5,1)+, so it outranks the (0,5,0) rules above. */
body.mgx-restyle .badge:is(.bg-primary, .bg-secondary, .bg-success, .bg-danger, .bg-warning, .bg-info):not(.rounded-pill, .position-absolute) > .text-white:not([class*="bg-"], .badge, .btn),
body.mgx-restyle .badge:is(.bg-primary, .bg-secondary, .bg-success, .bg-danger, .bg-warning, .bg-info):not(.rounded-pill, .position-absolute) > :not([class*="bg-"], .badge, .btn) > .text-white:not([class*="bg-"], .badge, .btn) {
  color: inherit !important;
}
