/* ==========================================================================
   design_system.css — the ONE owner of every restyle of a Bootstrap/AdminKit
   class. Created 2026-09-21 from the DS-alignment drafts (passes 2 and 3).

   THE CONTRACT (docs/design/archive/ds-alignment-2026-09/cascade.md §3)
   - Every selector is `body.mgx-restyle` + the selector it replaces, so the
     specificity band is (0,2,1), or (0,3,1) with a state or child. Extra
     context goes in :where() so it stays weightless.
   - NOT @layer: unlayered AdminKit would beat a layer, and layering AdminKit
     breaks the light/dark <link> swap.
   - This file READS theme variables and NEVER writes them. Colour belongs to
     the tenant theme, which is emitted after every stylesheet with !important.
     The 41 tenant-owned keys are never pinned here.
   - Load position: after the app's stylesheets, before theme_fonts and
     tenant_theme (application.html.erb). That is the whole design — after
     everything it must beat, before the theme it must not overwrite.

   WHERE EACH BLOCK CAME FROM
   Blocks 1-9 are pass 2 §3A (`overrides.DRAFT.css`), render-verified on a
   static specimen in light and dark. Blocks 10-12 are the owner options that
   won their decision on 2026-09-21 (`owner_options.DRAFT.css`). Block 5 is
   pass 3's C1 (`pass3/controls_overrides.DRAFT.css`), which SUPERSEDES pass 2's
   O5 — O5 themed the focus hue but kept a 55%-tint border at about 2:1 and
   never reached the picker engines. O5 is deliberately not in this file.

   DECISIONS THIS FILE IMPLEMENTS (src/docs/DESIGN_DECISIONS.md)
   6.3 control heights 30/38/48 · 6.4 bordered hairline cards ·
   6.15 underline tabs · 6.17 drawer actions pinned.
   6.8 (table header) chose SENTENCE CASE, which is today's behaviour, so the
   uppercase option is absent by design, not by omission.

   ADDED LATER THE SAME DAY: blocks 13-21 — C2-C6 (the picker engines, native
   file input, range track, segmented control, date pickers), the dark-mode
   scrim and side panels, the default wordmark in dark, readable rail labels,
   and the 768-991px overlay drawer. Each closes a row of the live-defect list.

   ADDED 2026-09-27: §22's dark branch and blocks 23-24 — the dark-theme
   contrast causes the Sites block census traced to the platform (Console
   #3997, #3999, #4034, #4036), fixed here once for every app. Their siblings
   live where each colour pairing is owned: #3998 and #4035 in
   color_text_fix.css, #4000 and #4001 in BusinessTheme.

   NOT YET HERE — each is tracked in the pass-3 work list, section 02:
   - The "one owner" extraction: the scattered overrides still in custom.css
     have NOT been moved here yet. They load before this file, so this file
     wins; the duplication is debt, not breakage. Locate them by CONTENT — the
     line numbers in the pass-2 plan have drifted (custom.css is 16,653 lines
     now, 16,626 when they were recorded).
   - 6.16's empty-state scale. The pass-2 note says "delete custom.css's Legacy
     empty states block", but that block's selector is `.card-body
     .text-center.py-5` — every card, not just widgets. The decision was "DS
     scale on PAGES, compact in WIDGETS", so the block must be NARROWED to
     widgets, not deleted. That needs a widget selector first.
   ========================================================================== */

/* ---------- 0 · Control tokens (pass 3) -----------------------------------
   Only the tokens the focus contract needs. --ctl-h is deliberately NOT set
   here: block 10 owns control height, per decision 6.3. */
body.mgx-restyle {
  --ctl-border: var(--control-border-color, #868e96);
  --ctl-bg: #fff;
  --ctl-ink: #495057;
  /* Focus colour: the brand in light (5.9:1 on white). In dark, the theme's
     readable brand tint — the dark --bs-primary is only 2.87:1. */
  --ctl-focus-rgb: var(--bs-primary-rgb);
  --ctl-focus-ring: 0 0 0 1px rgb(var(--ctl-focus-rgb)), 0 0 0 .25rem rgba(var(--ctl-focus-rgb), .2);
  --choice-focus-outline: 2px solid rgb(var(--ctl-focus-rgb));
}
:root[data-theme="dark"] body.mgx-restyle {
  --ctl-border: #767e86;          /* 3.07:1 on the #333 card, 3.4:1 on the control fill below; AdminKit's #4b4b4b is 1.58:1.
                                     Was #6f7780 until /pre-merge xr 2026-09-27: 2.78:1 on the card a control sits on. */
  /* The field is an INSET of the theme's own surfaces — the card mixed toward
     the page, the recess `.bg-light` / `.table-light` already take in dark
     (custom.css, "the surfaces AdminKit inverts") — a step darker than the card
     it sits in, the way a dark field reads. It was AdminKit's navy #222e3c: a
     second hue in a neutral palette, on every form in the product
     (Console #2831, decided 2026-10-02). Same luminance as the navy, so every
     ink and the boundary keep their measured contrast. */
  --ctl-bg: color-mix(in srgb, var(--bs-card-bg, #333) 40%, var(--bs-body-bg, #252526));
  --ctl-ink: #bdc0c5;
  --ctl-focus-rgb: var(--bs-link-color-rgb, 161, 180, 211);
}
/* Dark: native controls get the same 3:1 boundary. AdminKit dark ships #4b4b4b. */
:root[data-theme="dark"] body.mgx-restyle :is(.form-control, .form-select, .input-group-text, .form-check-input:not(:checked)) {
  border-color: var(--ctl-border);
}
/* Dark: the native controls take that fill too — the picker engines (block 14)
   already read it. AdminKit paints each one a navy literal: the field and its
   focus state #222e3c, a disabled field #4e5863, the addon and the file button
   its --bs-tertiary-bg #384350. A disabled field is the theme's secondary
   ground (the light theme's grey-out); an addon is the card itself, a step off
   the field as #f8f9fa is beside white. The scope is `:where()` so each rule
   weighs what AdminKit's does and wins on load order alone: an app rule that
   makes ITS field transparent (a composer, a search in a bar) still wins. */
:where(:root[data-theme="dark"] body.mgx-restyle) :is(.form-control, .form-select),
:where(:root[data-theme="dark"] body.mgx-restyle) :is(.form-control, .form-select):focus {
  background-color: var(--ctl-bg);
}
/* The floating label's backing strip — AdminKit's rule is (0,3,2), so this one
   keeps its scope's weight. */
:root[data-theme="dark"] body.mgx-restyle .form-floating > :is(.form-control, .form-control-plaintext, .form-select) ~ label::after {
  background-color: var(--ctl-bg);
}
:where(:root[data-theme="dark"] body.mgx-restyle) :is(.form-control, .form-select):disabled {
  background-color: var(--bs-secondary-bg);
}
:where(:root[data-theme="dark"] body.mgx-restyle) .form-check-input { --bs-form-check-bg: var(--ctl-bg); }
/* The header's search capsule (shared/_navbar) sits on the NAVBAR, not a card:
   AdminKit fills it #222e3c in dark (#f3f6fa, a breath off the white bar, in
   light). In dark it is the theme's navbar colour lifted a step — the same
   breath off the bar, in the bar's own hue, whatever the tenant paints it. */
:where(:root[data-theme="dark"] body.mgx-restyle) .input-group-navbar :is(.btn, .form-control),
:where(:root[data-theme="dark"] body.mgx-restyle) .input-group-navbar :is(.btn, .form-control):focus {
  background: color-mix(in srgb, var(--navbar-bg, #262626) 92%, #fff);
}
:where(:root[data-theme="dark"] body.mgx-restyle) .input-group-text,
:where(:root[data-theme="dark"] body.mgx-restyle) .form-control::file-selector-button {
  background-color: var(--bs-card-bg, #333);
}

/* ---------- 1 · Card inset — the header aligns with the body ---------------
   The adapter's `.card > .card-header { padding: 14px 18px }` puts every card
   title 4px left of the body text under it (measured: title x=19, body x=23).
   Flush tables follow the same inset. */
body.mgx-restyle .card > .card-header {
  /* --mgx-card-cap-py: the theme's card density (EXP-3c) — unset is 14px. */
  padding: var(--mgx-card-cap-py, 14px) var(--bs-card-cap-padding-x, 1.25rem);
}
body.mgx-restyle :is(.card-body.p-0, .card) > .table > * > tr > :first-child,
body.mgx-restyle :is(.card-body.p-0, .card) > .table-responsive > .table > * > tr > :first-child {
  padding-left: var(--bs-card-cap-padding-x, 1.25rem);
}
body.mgx-restyle :is(.card-body.p-0, .card) > .table > * > tr > :last-child,
body.mgx-restyle :is(.card-body.p-0, .card) > .table-responsive > .table > * > tr > :last-child {
  padding-right: var(--bs-card-cap-padding-x, 1.25rem);
}

/* ---------- 2 · The approved type scale, second pass ----------------------
   PAGE_COMPOSITION_STANDARDS §5A, owner-approved 2026-09-19. Controls take the
   tenant's body size (font_size_base), never a pinned 15px. */
body.mgx-restyle :where(.btn:not(.btn-sm, .btn-lg, .btn-group-sm > .btn, .btn-group-lg > .btn)),
body.mgx-restyle :where(.form-control:not(.form-control-sm, .form-control-lg), .form-select:not(.form-select-sm, .form-select-lg)),
body.mgx-restyle :where(.input-group:not(.input-group-sm, .input-group-lg) > .input-group-text) {
  font-size: var(--bs-body-font-size);
}
body.mgx-restyle .form-control-sm,
body.mgx-restyle .form-select-sm,
body.mgx-restyle .input-group-sm > :is(.form-control, .form-select, .input-group-text) {
  font-size: var(--type-small);
}
/* A searchable (Tom Select) small select draws its text in the inner
   .ts-control, which custom.css sizes in rem — 15.4px beside the 13px native
   .form-select-sm next to it (measured on the Power Tables rule editor,
   2026-10-03). Same token as the native control. */
body.mgx-restyle :is(.ts-wrapper.form-select-sm, .ts-wrapper.form-control-sm) .ts-control {
  font-size: var(--type-small);
}
body.mgx-restyle .dropdown-menu { --bs-dropdown-font-size: var(--bs-body-font-size); }
body.mgx-restyle .pagination:not(.pagination-sm):not(.pagination-lg) { --bs-pagination-font-size: var(--bs-body-font-size); }
@media (min-width: 576.02px) {
  body.mgx-restyle .breadcrumb { font-size: var(--bs-body-font-size); }
}
/* A badge is never larger than the text it sits beside (decision 6.21, owner
   2026-10-01): 0.85 of its context, between the type floor (12) and the small
   step (13) — 13 beside 15–16px text, 12 in a dense 14px row or a table. Pinned
   at 13 it read bigger than the meta lines, table cells and dense rows it
   annotates: bold and padded, at a larger size than the words around it. */
body.mgx-restyle .badge { --bs-badge-font-size: clamp(var(--type-caption), 0.85em, var(--type-small)); }
/* Weights are 400/500/600 — the UA's bold `th` (700) is off the scale. */
body.mgx-restyle .table th { font-weight: 600; }
/* Stat value (shared/_dashboard_stat_card): the display step, 28/600. */
body.mgx-restyle .stat-card-text > .h2 { font-size: var(--type-display); font-weight: 600; }
/* The same step as a variable: the narrow-tile rule (custom.css,
   `@container dashboard-stat-card`) scales the value DOWN from it. */
body.mgx-restyle .stat-card-text { --stat-value-size: var(--type-display); }
/* Modal and drawer titles are titles: 16/600 (modal was 15.4/400, drawer 15.4/600). */
body.mgx-restyle :is(.modal-title, .offcanvas-title) { font-size: var(--type-title); font-weight: 600; }

/* ---------- 3 · Underline tabs — decision 6.15 ----------------------------
   Restyles `.nav-tabs` (127 files + 46 card-header-tabs + enhanced-tabs) to the
   values the product's own underline tabs render. Markup unchanged.
   The rule and the bar are INSET SHADOWS, not borders with a -1px overhang: a
   strip that scrolls sideways must not overflow vertically. The !importants
   answer custom.css's "selected tab white" rule. */
body.mgx-restyle .nav-tabs {
  gap: 1.5rem;
  border-bottom: 0;
  box-shadow: inset 0 -1px 0 var(--bs-border-color);
}
body.mgx-restyle .nav-tabs .nav-link {
  margin-bottom: 0;
  padding: .5rem 0;
  font-size: var(--bs-body-font-size);
  color: var(--bs-secondary-color);
  background-color: transparent;
  border: 0;
  border-radius: 0;
}
body.mgx-restyle .nav-tabs .nav-link:hover {
  color: var(--bs-body-color);
  box-shadow: inset 0 -2px 0 var(--bs-border-color);
}
body.mgx-restyle .nav-tabs .nav-link.active,
body.mgx-restyle .nav-tabs .nav-item.show .nav-link {
  color: var(--bs-link-color, var(--bs-primary));
  font-weight: 600;
  background-color: transparent !important;
  border-color: transparent !important;
  box-shadow: inset 0 -2px 0 currentColor;
}
/* In a card header the tabs sit on the header's own rule, at the header's inset. */
body.mgx-restyle .card-header > .nav-tabs.card-header-tabs {
  margin: 0 0 -15px;
  box-shadow: none;
}

/* ---------- 4 · Input-group addon: boundary colour and control radius ------
   The addon kept #dee2e6 / 8px while the input beside it is #868e96 / 6px. */
:where(:root:not([data-theme="dark"])) body.mgx-restyle .input-group-text {
  border-color: var(--control-border-color);
}
body.mgx-restyle .input-group-text { border-radius: var(--mgx-ctl-radius); }

/* ---------- 5 · ONE focus indicator (pass 3, C1) --------------------------
   Supersedes pass 2's O5. Fourteen focus treatments across 31 focusable
   controls become two: text entry gets a brand edge plus a soft halo; a
   button-like choice gets a 2px outline with a 2px gap. Measured on the
   specimen: ring edge 1.36-1.90:1 -> 5.91:1 light, 6.55:1 dark.
   The !importants answer custom.css:1102-1111, which sets #80bdff !important.
   The engine selectors are included so the picker engines stop drawing their
   own rings even before their geometry rules (C2) land. */
body.mgx-restyle :is(.form-control, .form-select):focus,
body.mgx-restyle .ts-wrapper.focus,
body.mgx-restyle .select2-container--focus .select2-selection,
body.mgx-restyle .select2-container--open .select2-selection,
body.mgx-restyle .choices.is-focused .choices__inner,
body.mgx-restyle .choices.is-open .choices__inner {
  border-color: rgb(var(--ctl-focus-rgb)) !important;
  box-shadow: var(--ctl-focus-ring) !important;
  outline: 0;
}
body.mgx-restyle .ts-wrapper.focus .ts-control { box-shadow: none; border-color: transparent; }
/* Invalid keeps its own colour — this sits after the rule above on purpose. */
body.mgx-restyle .form-control.is-invalid:focus,
body.mgx-restyle .form-select.is-invalid:focus {
  border-color: var(--bs-form-invalid-border-color) !important;
  box-shadow: 0 0 0 1px var(--bs-form-invalid-border-color), 0 0 0 .25rem rgba(var(--bs-danger-rgb), .2) !important;
}
body.mgx-restyle .btn-check:focus-visible + .btn,
body.mgx-restyle .input-group > .btn:focus-visible,
body.mgx-restyle .star-rating [role="radio"]:focus-visible,
body.mgx-restyle .star-radio:focus-visible + .star-icon,
body.mgx-restyle .form-check-input:focus-visible {
  outline: var(--choice-focus-outline) !important;
  outline-offset: 2px;
  box-shadow: none !important;
  z-index: 5;
}

/* ---------- 6 · Status-badge fills derive from the tenant's colours --------
   Bootstrap 5.3's own rule: the tone mixed 20% into white. AdminKit compiled
   these from its own palette, so a tenant's brand never reached the fill while
   the theme DID recolour the ink. Inks stay the theme's contrast-checked
   on-subtle values. Light only; dark keeps custom.css's rgba tints. */
:root:not([data-theme="dark"]) body.mgx-restyle {
  --bs-primary-bg-subtle: color-mix(in srgb, var(--bs-primary) 20%, #fff);
  --bs-secondary-bg-subtle: color-mix(in srgb, var(--bs-secondary) 20%, #fff);
  --bs-success-bg-subtle: color-mix(in srgb, var(--bs-success) 20%, #fff);
  --bs-info-bg-subtle: color-mix(in srgb, var(--bs-info) 20%, #fff);
  --bs-warning-bg-subtle: color-mix(in srgb, var(--bs-warning) 20%, #fff);
  --bs-danger-bg-subtle: color-mix(in srgb, var(--bs-danger) 20%, #fff);
}
/* The neutral status badge painted the PAGE colour — invisible on the page,
   1.07:1 on a card; 284 files hand-add `border` to see it. Bootstrap's
   `text-bg-light` is the same tag spelled the other way (~110 sites), and takes
   the same fill (2026-10-02). Fill only — the tag's ink is whatever it already
   carries (`text-dark`, `text-muted`, …). */
:root:not([data-theme="dark"]) body.mgx-restyle .badge:is(.bg-light, .text-bg-light) {
  background-color: var(--bs-secondary-bg-subtle) !important;
}
/* …and that fill is a secondary TINT, so its ink is the one the theme measures
   for a secondary tint. The tone utilities are clamped against the card and the
   page only, and over 300 badges in the views pair it with them: "AI mode: Off"
   (`text-muted`) read 4.34:1 on the default theme and 3.69:1 on Midnight
   Purple, `text-secondary` 3.96–4.40:1 on five presets, `text-primary` 4.30:1
   on Sunset (preset sweep, 2026-10-02). */
:root:not([data-theme="dark"]) body.mgx-restyle .badge.bg-light:is(.text-muted, .text-secondary) {
  color: var(--bs-on-subtle-secondary, var(--bs-secondary-text-emphasis)) !important;
}
:root:not([data-theme="dark"]) body.mgx-restyle .badge.bg-light.text-primary {
  color: var(--bs-on-subtle-primary, var(--bs-primary-text-emphasis)) !important;
}
/* Dark: AdminKit fills it navy (#2d3846 — a second hue among the theme's
   neutral greys, Console #2831, decided 2026-10-02). It is the CARD lifted one
   step toward white: a raised neutral chip off the card, as the tone chips
   (block 22) are tone washes over it. Not the secondary wash light uses: that
   carries the tenant's secondary hue, and is light enough that a `text-muted`
   tag fell to 4.43:1 on it (the lifted card keeps it at 5:1). */
:root[data-theme="dark"] body.mgx-restyle .badge:is(.bg-light, .text-bg-light) {
  background-color: color-mix(in srgb, var(--bs-card-bg, #333) 94%, #fff) !important;
}

/* ---------- 7 · Menus float ------------------------------------------------
   AdminKit defines --bs-dropdown-box-shadow but never paints it. */
body.mgx-restyle .dropdown-menu { box-shadow: var(--mgx-menu-shadow); }

/* ---------- 8 · The overflow toggle is square at its height ----------------
   shared/_row_actions is icon-only fa-ellipsis-v: 23x29 -> 29x29 in a row.
   min-width, so a labelled button is never squeezed. */
body.mgx-restyle .btn:has(> .fa-ellipsis-v:only-child) {
  min-width: calc(1.5em + 2 * var(--bs-btn-padding-y) + 2 * var(--bs-btn-border-width));
}

/* ---------- 9 · Tenant page colour reaches the canvas and the modal body ---
   AdminKit paints `.main` with a literal (#f5f7fb light, #19222c navy dark), so
   page_bg was inert in the content area and dark mode showed the theme's #333
   cards on AdminKit navy. The modal-body tint was the same literal. */
body.mgx-restyle .main { background: var(--bs-body-bg); }
:root:not([data-theme="dark"]) body.mgx-restyle .modal-body { background-color: var(--bs-body-bg) !important; }

/* ---------- 10 · Control heights 30 / 38 / 48 — decision 6.3 ---------------
   Reached with PADDING, not a fixed height, so a wrapped label still grows
   instead of clipping. This block owns --ctl-h. */
body.mgx-restyle :where(.btn, .form-control, .form-select, .page-link, .input-group-text) { --ctl-h: 38px; }
body.mgx-restyle :where(.btn-sm, .btn-group-sm > .btn, .form-control-sm, .form-select-sm, .input-group-sm > *) { --ctl-h: 30px; }
body.mgx-restyle :where(.btn-lg, .btn-group-lg > .btn, .form-control-lg, .form-select-lg, .input-group-lg > *) { --ctl-h: 48px; }
/* A picker engine (block 14) draws its box as the select's NEXT SIBLING, which
   inherits nothing from it: a Select2 on a small select took 38px beside 30px
   inputs and lifted its label above its neighbours' (Lone Worker's alerts filter,
   /design-pass 2026-10-02). The box takes its select's size. */
body.mgx-restyle :where(.form-select-sm, .form-control-sm) + .select2-container { --ctl-h: 30px; }
body.mgx-restyle :where(.form-select-lg, .form-control-lg) + .select2-container { --ctl-h: 48px; }
body.mgx-restyle .btn { --bs-btn-padding-y: calc((var(--ctl-h) - 2px - 1.5em) / 2); }
body.mgx-restyle :is(.form-control, .form-select, .input-group-text):not(textarea) {
  padding-top: calc((var(--ctl-h) - 2px - 1.5em) / 2);
  padding-bottom: calc((var(--ctl-h) - 2px - 1.5em) / 2);
  min-height: 0;
}
body.mgx-restyle .pagination { --bs-pagination-padding-y: calc((var(--ctl-h, 38px) - 2px - 1.5em) / 2); }

/* ---------- 11 · Bordered hairline cards — decision 6.4 -------------------
   `.border-0` is an !important utility that 1,724 files opt out with, so this
   is the one place the layer answers a utility with !important. The repo rules
   that currently mandate `border-0 shadow-sm` change with this. */
body.mgx-restyle .card.border-0 { border: 1px solid var(--mgx-card-edge, var(--mgx-card-border)) !important; }

/* ---------- 12 · Drawer actions pinned to the bottom edge — decision 6.17 --
   Left-flowing order was already settled; the pinning is what was decided.

   z-index, added for ISS-20260922-601-25E845: the bar pinned with `z-index:
   auto`, which paints in the SAME layer as ordinary drawer content and LOSES
   to any positioned element in the body carrying a positive z-index. A drawer
   body is a scroll container, so anything a form pins to its floor lands in
   this bar's band — Live Boards' sticky "Live preview" card (z-index: 3) sat
   on top of Save and Cancel and swallowed the clicks at every scroll position
   but the very last. The bar owns the drawer floor: it is the only way out of
   the form, so it outranks whatever the form pins beside it. Kept well under
   the Bootstrap overlay bands (dropdown 1000, modal 1055) — those open ABOVE
   the bar and still must. */
body.mgx-restyle .offcanvas-body .form-actions {
  position: sticky;
  bottom: calc(-1 * var(--bs-offcanvas-padding-y));
  z-index: 5;
  margin: 1rem calc(-1 * var(--bs-offcanvas-padding-x)) calc(-1 * var(--bs-offcanvas-padding-y));
  padding: .75rem var(--bs-offcanvas-padding-x);
  background: var(--bs-offcanvas-bg);
  border-top: 1px solid var(--bs-border-color);
}

/* ==========================================================================
   Blocks 13-19 — added 2026-09-21 to close the live-defect list. Same
   contract as above: body.mgx-restyle + the selector it replaces, theme
   variables read never written, dark twins on :root[data-theme="dark"].
   ========================================================================== */

/* ---------- 13 · Picker-engine tokens (pass 3, C2-C6) ------------------
   The engines paint their own chevrons, so the form-select glyph is restated
   here scoped to them. --ctl-h is owned by block 10. */
body.mgx-restyle {
  --token-bg: rgba(var(--bs-primary-rgb), .12);
  --token-ink: var(--bs-on-subtle-primary, #2959a1);
  --ctl-chevron: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3E%3C/svg%3E");
}
:root[data-theme="dark"] body.mgx-restyle {
  --token-bg: rgba(var(--bs-primary-rgb), .28);
  --token-ink: #e4ebf5;
  --ctl-chevron: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23bdc0c5' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3E%3C/svg%3E");
}

/* ---------- 14 · C2: every picker engine takes the control's geometry ---
   select2.min.css is appended by application.js AFTER every stylesheet, so
   equal-specificity rules lose to it on order alone; the !importants here
   answer legacy !importants in custom.css:1036-1227 and win on weight. In
   dark mode these engines painted WHITE boxes with light ink (1.06-1.73:1,
   ~210 files). */
body.mgx-restyle .select2-container--default .select2-selection--single,
body.mgx-restyle .user-searchable-select + .select2-container--default .select2-selection--single {
  height: var(--ctl-h, 38px) !important;
  border: 1px solid var(--ctl-border) !important;
  border-radius: var(--mgx-ctl-radius, 6px) !important;
  background-color: var(--ctl-bg);
  font-size: var(--bs-body-font-size, 15px);
}
body.mgx-restyle .select2-container--default .select2-selection--single .select2-selection__rendered,
body.mgx-restyle .user-searchable-select + .select2-container--default .select2-selection--single .select2-selection__rendered {
  line-height: calc(var(--ctl-h, 38px) - 2px) !important;
  color: var(--ctl-ink) !important;
  padding-left: .85rem !important;
}
body.mgx-restyle .select2-container--default .select2-selection--single .select2-selection__arrow { height: calc(var(--ctl-h, 38px) - 2px) !important; }
body.mgx-restyle .select2-container--default .select2-selection--multiple {
  min-height: var(--ctl-h, 38px);
  border: 1px solid var(--ctl-border) !important;
  border-radius: var(--mgx-ctl-radius, 6px);
  background-color: var(--ctl-bg);
}
body.mgx-restyle .select2-container--default .select2-selection--multiple .select2-selection__choice {
  background-color: var(--token-bg); color: var(--token-ink); border: 0; border-radius: calc(var(--mgx-ctl-radius, 6px) - 2px);
}
body.mgx-restyle .select2-dropdown { background-color: var(--ctl-bg); color: var(--ctl-ink); border-color: var(--ctl-border); border-radius: var(--mgx-ctl-radius, 6px); }
body.mgx-restyle .select2-container--default .select2-results__option--highlighted[aria-selected],
body.mgx-restyle .select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
  background-color: rgb(var(--bs-primary-rgb)); color: var(--bs-on-primary, #fff);
}
body.mgx-restyle .select2-container--default.select2-container--focus .select2-selection,
body.mgx-restyle .select2-container--default.select2-container--open .select2-selection,
body.mgx-restyle .user-searchable-select + .select2-container--default.select2-container--focus .select2-selection--single,
body.mgx-restyle .user-searchable-select + .select2-container--default.select2-container--open .select2-selection--single {
  border-color: rgb(var(--ctl-focus-rgb)) !important;
  box-shadow: var(--ctl-focus-ring) !important;
}
body.mgx-restyle .select2-container--default .select2-search--dropdown .select2-search__field { border-color: var(--ctl-border); background: var(--ctl-bg); color: var(--ctl-ink); }

body.mgx-restyle .choices__inner {
  min-height: var(--ctl-h, 38px);
  border: 1px solid var(--ctl-border);
  border-radius: var(--mgx-ctl-radius, 6px);
  background-color: var(--ctl-bg);
  color: var(--ctl-ink);
  font-size: var(--bs-body-font-size, 15px);
  line-height: 1.5;
  padding: calc((var(--ctl-h, 38px) - 2px - 1.5em) / 2) .85rem;
}
body.mgx-restyle .choices[data-type*=select-one] .choices__inner { padding-bottom: calc((var(--ctl-h, 38px) - 2px - 1.5em) / 2); }
body.mgx-restyle .choices__list--single { padding: 0 1.75rem 0 0; }
body.mgx-restyle .choices[data-type*=select-one]::after {
  border: 0; width: 16px; height: 12px; margin-top: -6px; right: .75rem;
  background: var(--ctl-chevron) no-repeat center / 16px 12px;
}
body.mgx-restyle .choices__list--multiple .choices__item {
  background-color: var(--token-bg); color: var(--token-ink); border: 0; border-radius: calc(var(--mgx-ctl-radius, 6px) - 2px);
  font-size: .8125rem; font-weight: 500;
}
body.mgx-restyle .choices[data-type*=select-multiple] .choices__button { filter: invert(.55); border-left-color: rgba(0,0,0,.25); }
:root[data-theme="dark"] body.mgx-restyle .choices[data-type*=select-multiple] .choices__button { filter: none; border-left-color: rgba(255,255,255,.3); }
body.mgx-restyle .choices__list--dropdown, body.mgx-restyle .choices__list[aria-expanded] { background-color: var(--ctl-bg); color: var(--ctl-ink); border-color: var(--ctl-border); }
body.mgx-restyle .choices__input { background-color: transparent; color: var(--ctl-ink); }

body.mgx-restyle .ts-wrapper.multi .ts-control > div { background: var(--token-bg); color: var(--token-ink); border-radius: calc(var(--mgx-ctl-radius, 6px) - 2px); }
:root[data-theme="dark"] body.mgx-restyle .ts-dropdown { background: var(--ctl-bg); color: var(--ctl-ink); border-color: var(--ctl-border); }

/* colour swatch in an input-group: a fixed square at control height (was 120x38) */
body.mgx-restyle .input-group > .form-control-color {
  flex: 0 0 var(--ctl-h, 38px); width: var(--ctl-h, 38px); height: var(--ctl-h, 38px); padding: .25rem; border-color: var(--ctl-border);
}

/* ---------- 15 · C3: the native file input is a control, not a drop zone -
   enhanced_field_types.css:123-140 drew it as a 40.3px dashed box on #f8f9fa
   that dark mode never recoloured (1.73:1). */
body.mgx-restyle .form-control[type="file"] {
  border: 1px solid var(--ctl-border);
  background-color: var(--ctl-bg);
  color: var(--ctl-ink);
  padding: .3rem .85rem;
}
body.mgx-restyle .form-control[type="file"]:hover:not(:focus) { background-color: var(--ctl-bg); border-color: var(--ctl-border); }
/* ...and when it is invalid, it says so. The two rules above sit at (0,3,1)/(0,4,1)
   and outranked Bootstrap's `.form-control.is-invalid` border, so EVERY invalid file
   input on the platform stayed grey while its text-field siblings turned red — the
   error summary was the only visible signal (found on the Sites asset upload,
   2026-09-23). The hover twin, because the hover rule above resets border-color. */
body.mgx-restyle .form-control[type="file"].is-invalid,
body.mgx-restyle .form-control[type="file"].is-invalid:hover:not(:focus) { border-color: var(--bs-form-invalid-border-color); }

/* ---------- 16 · C4: a range track you can see (was 1.02-1.05:1) --------
   The disabled-thumb fix is in BusinessTheme (:enabled on the emitter). */
body.mgx-restyle .form-range::-webkit-slider-runnable-track { height: .3rem; background-color: var(--ctl-border); }
body.mgx-restyle .form-range::-moz-range-track { height: .3rem; background-color: var(--ctl-border); }
body.mgx-restyle .form-range::-moz-range-progress { height: .3rem; background-color: rgb(var(--bs-primary-rgb)); }
body.mgx-restyle .form-range::-webkit-slider-thumb { width: 1.125rem; height: 1.125rem; margin-top: -.4125rem; border: 2px solid var(--bs-card-bg, #fff); }
body.mgx-restyle .form-range:focus::-webkit-slider-thumb { box-shadow: none; }
body.mgx-restyle .form-range:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 2px var(--bs-card-bg, #fff), 0 0 0 4px rgb(var(--ctl-focus-rgb)); }
body.mgx-restyle .form-range:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 2px var(--bs-card-bg, #fff), 0 0 0 4px rgb(var(--ctl-focus-rgb)); }

/* ---------- 17 · C5: one selected look for the segmented control ---------
   shared/_segmented_control painted :radio mode grey (#6c757d) and :link mode
   brand — same partial, two looks. */
body.mgx-restyle .btn-group > .btn-check:checked + :is(.btn-outline-secondary, .btn-outline-primary),
body.mgx-restyle .btn-group > .btn-outline-secondary[aria-current="page"],
body.mgx-restyle .btn-group > .btn-primary[aria-current="page"] {
  background-color: rgb(var(--bs-primary-rgb)); border-color: rgb(var(--bs-primary-rgb)); color: var(--bs-on-primary, #fff);
}

/* ---------- 18 · C6: pickers that paint their own blues take the brand ---
   flatpickr #3b7ddd, daterangepicker #08c/#357ebd, repainted #0d6efd. */
body.mgx-restyle .flatpickr-day.selected, body.mgx-restyle .flatpickr-day.selected:hover,
body.mgx-restyle .flatpickr-day.startRange, body.mgx-restyle .flatpickr-day.endRange {
  background: rgb(var(--bs-primary-rgb)); border-color: rgb(var(--bs-primary-rgb)); color: var(--bs-on-primary, #fff);
}
body.mgx-restyle .flatpickr-day.today:not(.selected) { border-color: rgb(var(--bs-primary-rgb)); }
body.mgx-restyle .daterangepicker .ranges li.active,
body.mgx-restyle .daterangepicker td.active, body.mgx-restyle .daterangepicker td.active:hover {
  background-color: rgb(var(--bs-primary-rgb)); color: var(--bs-on-primary, #fff);
}
body.mgx-restyle .daterangepicker td.in-range:not(.active) { background-color: var(--token-bg); color: inherit; }
:root[data-theme="dark"] body.mgx-restyle .daterangepicker { background-color: var(--bs-card-bg, #333); border-color: var(--ctl-border); color: var(--ctl-ink); }
:root[data-theme="dark"] body.mgx-restyle .daterangepicker .calendar-table { background-color: transparent; border-color: transparent; }
:root[data-theme="dark"] body.mgx-restyle .daterangepicker td.off { background-color: transparent; color: #6c757d; }
:root[data-theme="dark"] body.mgx-restyle .daterangepicker td.available:hover,
:root[data-theme="dark"] body.mgx-restyle .daterangepicker .ranges li:hover { background-color: rgba(255, 255, 255, .08); }
:root[data-theme="dark"] body.mgx-restyle .daterangepicker select { background: var(--ctl-bg); color: var(--ctl-ink); border: 1px solid var(--ctl-border); }
:root[data-theme="dark"] body.mgx-restyle .daterangepicker::after { border-bottom-color: var(--bs-card-bg, #333); }

/* ---------- 19 · Dark mode: the scrim, the two side panels, the wordmark -
   AdminKit dark.css sets --bs-backdrop-bg:#fff, so every modal and drawer
   dimmed the page WHITE in dark mode. help_sidepanel.css and the profile
   panel's inline style carry no [data-theme] rule at all (1.15-1.34:1). */
:root[data-theme="dark"] body.mgx-restyle :is(.modal-backdrop, .offcanvas-backdrop) {
  --bs-backdrop-bg: #0b0d10;
  --bs-backdrop-opacity: .6;
}
:root[data-theme="dark"] body.mgx-restyle .help-sidepanel {
  --ai-assistant-bg-color: var(--bs-card-bg, #333);
  --ai-assistant-header-bg: var(--bs-tertiary-bg, #2b2b2b);
  color: var(--bs-body-color);
}
:root[data-theme="dark"] body.mgx-restyle .profile-sidepanel-container { background-color: var(--bs-card-bg, #333); color: var(--bs-body-color); }
:root[data-theme="dark"] body.mgx-restyle .profile-sidepanel-header { background-color: var(--bs-tertiary-bg, #2b2b2b); border-bottom-color: var(--bs-border-color); }
:root[data-theme="dark"] body.mgx-restyle .profile-sidepanel-job-title { color: var(--bs-secondary-color); }
/* The DEFAULT MangoApps wordmark is dark ink on a transparent PNG; on the dark
   navbar it vanished. This lifts only that asset — a tenant's own logo never
   carries .navbar-default-logo and is never filtered. */
:root[data-theme="dark"] body.mgx-restyle .navbar-default-logo { filter: brightness(0) invert(1); }

/* ---------- 20 · Rail labels you can read (pass 3, J5) -------------------
   custom.css:2649-2668 set 0.5625rem (9.9px) and 0.4375rem (7.7px); axe
   flagged all 11 as serious. 11px/500, two lines max. The colour half of the
   fix is BusinessTheme's sidebar_rail_text default (#d8ebe1 -> #ffffff).
   A label wraps first. A word too long for one line at 11px was clipped mid-
   word, so rail_label_fit_controller.js now steps that label down (inline
   font-size, floor 7px) until the whole word fits and marks it
   .rail-label-sm. Only a word that still does not fit at the floor breaks
   across lines (.rail-label-break) — every letter visible beats half a word.
   Every rail link has a tooltip with its full name (.rail-label-tooltip). */
body.mgx-restyle .sidebar-rail-label {
  font-size: 11px;
  font-weight: 500;
  line-height: 1.2;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
body.mgx-restyle .sidebar-rail-label.rail-label-break { overflow-wrap: anywhere; }
/* One line: the 200px default wrapped "Compensation Management" in two. */
.tooltip.rail-label-tooltip { --bs-tooltip-font-size: 0.875rem; --bs-tooltip-max-width: none; white-space: nowrap; }
/* The tenant's rail colours, a shade deeper, not Bootstrap's black — set on
   :root by rail_label_fit_controller.js from whatever the rail is painted with,
   held to 4.5:1 text contrast. */
.tooltip.rail-label-tooltip {
  --bs-tooltip-bg: var(--rail-tip-bg, var(--bs-emphasis-color));
  --bs-tooltip-color: var(--rail-tip-ink, var(--bs-body-bg));
  --bs-tooltip-opacity: 1;
}
.tooltip.rail-label-tooltip .tooltip-inner { box-shadow: 0 2px 8px rgba(11, 13, 16, .18); }

/* ---------- 21 · Navigation at 768-991px (pass 3, J1) --------------------
   custom.css:3397-3409 forces the sidebar wrapper to width 0 below 992 while
   the phone drawer is d-md-none, so in this band there was NO app or admin
   navigation. The panel becomes an overlay drawer beside the rail, opened by
   the hamburger or the rail's Apps/Admin buttons (modules/sidebar.js and
   sidebar_rail_controller add body.sidebar-overlay-open only in this band).
   The offsets are the shell's own: 56px navbar, 96px with the trial strip. */
@media (min-width: 768px) and (max-width: 991.98px) {
  body.mgx-restyle.sidebar-overlay-open .sidebar-rail ~ #sidebar-wrapper {
    position: fixed;
    top: 56px;
    bottom: 0;
    left: 64px;
    width: 220px !important;
    min-width: 220px !important;
    z-index: 1031;
    overflow-y: auto;
    background: var(--bs-body-bg);
    box-shadow: 0 8px 24px rgba(11, 13, 16, .26);
  }
  body.mgx-restyle.sidebar-overlay-open.has-trial-strip .sidebar-rail ~ #sidebar-wrapper { top: 96px; }
  body.mgx-restyle.sidebar-overlay-open .sidebar-rail ~ #sidebar-wrapper .sidebar {
    width: 220px !important;
    min-width: 220px !important;
    max-width: none !important;
    overflow: visible;
  }
  body.mgx-restyle.sidebar-overlay-open::after {
    content: "";
    position: fixed;
    inset: 56px 0 0 0;
    background: rgba(11, 13, 16, .36);
    z-index: 1000;
  }
  body.mgx-restyle.sidebar-overlay-open.has-trial-strip::after { top: 96px; }
}

/* ---------- 22 · Soft status badges (decision 6.14) ------------------------
   The majority markup, `badge bg-{tone}` (about 3,000 files, helpers and JS
   included), renders the settled soft look with no markup change: the tone's
   subtle fill, tenant-derived in light (block 6) and re-tinted in dark
   (custom.css), under `--bs-on-subtle-{tone}` — the ink BusinessTheme clamps
   for contrast against exactly those fills, in both modes. The settled form
   `shared/_status_badge` writes (`bg-{tone}-subtle text-{tone}-emphasis`) takes
   the same ink, so a helper-made badge and a hand-written one are identical.
   Stays solid: counters (`rounded-pill`), positioned notification dots
   (`position-absolute`), `bg-dark`, and Bootstrap's explicit `text-bg-{tone}`.
   !important because `.bg-{tone}` and `.text-dark` are !important utilities and
   color_text_fix.css re-inks solid fills with !important. Never a bare
   `.bg-{tone}` — always compounded with `.badge`. The modern skin (decision S0)
   comes after this and changes the badge's shape, not its colours. */
body.mgx-restyle .badge.bg-primary:not(.rounded-pill, .position-absolute),
body.mgx-restyle .badge.bg-primary-subtle {
  background-color: var(--bs-primary-bg-subtle) !important;
  color: var(--bs-on-subtle-primary, var(--bs-primary-text-emphasis)) !important;
}
body.mgx-restyle .badge.bg-secondary:not(.rounded-pill, .position-absolute),
body.mgx-restyle .badge.bg-secondary-subtle {
  background-color: var(--bs-secondary-bg-subtle) !important;
  color: var(--bs-on-subtle-secondary, var(--bs-secondary-text-emphasis)) !important;
}
body.mgx-restyle .badge.bg-success:not(.rounded-pill, .position-absolute),
body.mgx-restyle .badge.bg-success-subtle {
  background-color: var(--bs-success-bg-subtle) !important;
  color: var(--bs-on-subtle-success, var(--bs-success-text-emphasis)) !important;
}
body.mgx-restyle .badge.bg-danger:not(.rounded-pill, .position-absolute),
body.mgx-restyle .badge.bg-danger-subtle {
  background-color: var(--bs-danger-bg-subtle) !important;
  color: var(--bs-on-subtle-danger, var(--bs-danger-text-emphasis)) !important;
}
body.mgx-restyle .badge.bg-warning:not(.rounded-pill, .position-absolute),
body.mgx-restyle .badge.bg-warning-subtle {
  background-color: var(--bs-warning-bg-subtle) !important;
  color: var(--bs-on-subtle-warning, var(--bs-warning-text-emphasis)) !important;
}
body.mgx-restyle .badge.bg-info:not(.rounded-pill, .position-absolute),
body.mgx-restyle .badge.bg-info-subtle {
  background-color: var(--bs-info-bg-subtle) !important;
  color: var(--bs-on-subtle-info, var(--bs-info-text-emphasis)) !important;
}
/* In the dark theme each tone's subtle fill is an 18% TRANSLUCENT wash
   (custom.css, "Re-tint the Bootstrap subtle tokens"), while the ink above,
   --bs-on-subtle-{tone}, is measured against that wash over the CARD
   (BusinessTheme#subtle_on_color_tokens). A translucent chip takes on whatever
   is behind it, so a badge in an alert, on a card header or on a secondary
   panel sat on a wash over a wash: 3.6-4.4:1 across Policy Hub, Recognition,
   Forms, Scheduling, Tasks, the dashboard, the app marketplace and chat
   mentions (Console #3999). So the chip is laid over the card surface its ink
   was measured on, and reads the same wherever it sits. `dark` is the seventh
   tone and the one AdminKit's dark palette gets wrong outright: it fills
   `bg-dark-subtle` with an OPAQUE mid grey (#7a828a) under
   `text-dark-emphasis` (#bdc0c5), 2.14:1 (#4036). It becomes the same wash,
   of the dark theme's own `dark` (#e9eaec), inked with that tone the way the
   other tones are (6.3:1). Light is untouched: there the fills are opaque
   (block 6) and AdminKit's light `dark` pair reads 7:1. */
:root[data-theme="dark"] body.mgx-restyle .badge:is(.bg-primary:not(.rounded-pill, .position-absolute), .bg-primary-subtle) { --mgx-chip-wash: var(--bs-primary-bg-subtle); }
:root[data-theme="dark"] body.mgx-restyle .badge:is(.bg-secondary:not(.rounded-pill, .position-absolute), .bg-secondary-subtle) { --mgx-chip-wash: var(--bs-secondary-bg-subtle); }
:root[data-theme="dark"] body.mgx-restyle .badge:is(.bg-success:not(.rounded-pill, .position-absolute), .bg-success-subtle) { --mgx-chip-wash: var(--bs-success-bg-subtle); }
:root[data-theme="dark"] body.mgx-restyle .badge:is(.bg-danger:not(.rounded-pill, .position-absolute), .bg-danger-subtle) { --mgx-chip-wash: var(--bs-danger-bg-subtle); }
:root[data-theme="dark"] body.mgx-restyle .badge:is(.bg-warning:not(.rounded-pill, .position-absolute), .bg-warning-subtle) { --mgx-chip-wash: var(--bs-warning-bg-subtle); }
:root[data-theme="dark"] body.mgx-restyle .badge:is(.bg-info:not(.rounded-pill, .position-absolute), .bg-info-subtle) { --mgx-chip-wash: var(--bs-info-bg-subtle); }
:root[data-theme="dark"] body.mgx-restyle .badge.bg-dark-subtle {
  --mgx-chip-wash: rgba(233, 234, 236, .18);
  color: #e9eaec !important;
}
:root[data-theme="dark"] body.mgx-restyle .badge:is(.bg-primary, .bg-secondary, .bg-success, .bg-danger, .bg-warning, .bg-info):not(.rounded-pill, .position-absolute),
:root[data-theme="dark"] body.mgx-restyle .badge:is(.bg-primary-subtle, .bg-secondary-subtle, .bg-success-subtle, .bg-danger-subtle, .bg-warning-subtle, .bg-info-subtle, .bg-dark-subtle) {
  background: linear-gradient(var(--mgx-chip-wash), var(--mgx-chip-wash)), var(--bs-card-bg, #333) !important;
}

/* ---------- 23 · A filled outline button's label is the one measured for it
   AdminKit's light.css AND dark.css paint every hovered or pressed outline
   button's label a LITERAL white (`.btn-outline-*:hover:not(:disabled):not(.disabled)`,
   `…:active`, `….active`, 0,4,0) over the `--bs-btn-hover-color` /
   `--bs-btn-active-color` the tenant theme measured for each fill
   (BusinessTheme#component_scope_overrides: on_color of the fill). Wherever
   the fill is light the label vanished: the "Not now" button on every page and
   the List/Board view toggles in Tasks and Workspace (outline-secondary on the
   tenant's pale accent) 2.3:1 light / 1.94:1 dark, outline-warning 1.89:1 /
   1.66:1, outline-dark 1.2:1 in dark (Console #4034). Bootstrap's own `.btn`
   rules read the variable; this puts that back at AdminKit's own weight
   (0,4,0 — `:where()` keeps the body scope weightless) and wins on load order,
   so every rule that already beat AdminKit on purpose (a coloured card header,
   BusinessTheme#component_style_css; the chat composer's paperclip) still wins. */
:where(body.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.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);
}

/* ---------- 24 · Dark: `btn-dark` takes AdminKit's own dark label ----------
   AdminKit's dark palette inverts `.btn-dark` into a light grey (#e9eaec) and
   declares its label dark (--bs-btn-color #222e3c), but its combined solid
   rule (`.btn-danger, …, .btn-dark… { color: #fff }`) paints the label a
   literal white over it: 1.2:1 on Service Desk's "Close request", Guest Pass's
   badge and every other btn-dark (Console #3997). The label reads the
   variables again, 11.4:1. `btn-light` keeps AdminKit's fills and labels — a
   dark slate with a light label (8:1), the dark twin of the light theme's
   #f5f7fb button — and takes an edge in block 25. The `bg-dark` / `bg-black` UTILITIES are a
   different question with a different answer: they stay dark
   (color_text_fix.css, "Dark background"). */
:root[data-theme="dark"] body.mgx-restyle .btn-dark { color: var(--bs-btn-color); }
:root[data-theme="dark"] body.mgx-restyle .btn-dark:is(:hover, .hover, :focus-visible):not(:disabled):not(.disabled) { color: var(--bs-btn-hover-color); }
:root[data-theme="dark"] body.mgx-restyle .btn-dark:is(:active, .active, .show),
:root[data-theme="dark"] body.mgx-restyle .show > .btn-dark.dropdown-toggle { color: var(--bs-btn-active-color); }

/* ---------- 25 · `btn-light` has an edge (Console #4107) -----------------
   X1 (cross-app contrast, 2026-09-27; owner decision the same day). AdminKit
   draws `btn-light` with its fill as its border in both sheets (#f5f7fb light,
   #2d3846 dark), so on a white card it was a floating word at 1.07:1 and on the
   dark #333 card 1.06:1. It takes the CONTROL boundary, --ctl-border (block 0) —
   the edge a text input already draws, 3.32:1 on white / 3.1:1 on the #f5f7fb
   shell light, 3.07:1 on the #333 card dark — in every state and both themes
   (owner decision 2026-09-27, /pre-merge xr). The theme hairline it took first
   (--bs-border-color) is a decorative divider, 1.3:1 light / 1.45:1 dark, and
   AdminKit's light hover/pressed borders (#c4c6c9 / #b8b9bc) are 1.71 / 1.96:1.
   Variables only, at AdminKit's own weight (`:where()` keeps the scope
   weightless) — every button rule reads them. The twin for the layouts that
   load color_text_fix.css but not this file is there. */
:where(body.mgx-restyle) .btn-light {
  --bs-btn-border-color: var(--ctl-border);
  --bs-btn-hover-border-color: var(--ctl-border);
  --bs-btn-active-border-color: var(--ctl-border);
  --bs-btn-disabled-border-color: var(--ctl-border);
}

/* ---------- 26 · A card title outside a header takes its card's ink --------
   X1 (cross-app contrast, 2026-09-27). AdminKit's light sheet paints every
   `.card-title` a literal #939ba2 (after its own var() rule, so the variable
   cannot reach it): 2.81:1 on a white card. A heading title is rescued by the
   theme's `h1…h6` rule and a header title by the mgx header rule, but a
   `span` / `div` / `p` title in a card body kept the grey — Company Store's
   product names (Console #4086). It inherits instead: the card's ink, or a
   solid fill's measured label (color_text_fix.css), whichever it sits in.
   Light only — AdminKit's dark title (#d3d5d8) reads 9:1. Weight 0,1,0 (the
   scope is `:where()`), so every rule that already colours a title still wins. */
:where(:root:not([data-theme="dark"]) body.mgx-restyle) .card-title { color: inherit; }

/* ---------- 27 · The nav panel has an edge --------------------------------
   The 220px panel beside the rail had no edge in the product, while Theme
   Settings' preview (admin/theme_settings/_preview_frame) and the design
   system's navigation shell (design-system/preview/navigation.html) both draw
   a 1px hairline in the theme's border_color. A white panel on a tinted
   page_bg read as unfinished. Logical, so it lands on the page side in RTL.
   The panel collapses to width 0 (Home zone, hamburger, AdminKit's
   margin-left collapse, and every width below 992px unless block 21's overlay
   is open; custom.css's rail block) without leaving the box, so those states
   drop the edge, or a 1px line stays beside the rail. Same weight as the edge
   rule (the extra context is `:where()`), later wins. */
body.mgx-restyle .sidebar-rail ~ #sidebar-wrapper .sidebar {
  border-inline-end: 1px solid var(--bs-border-color, #dee2e6);
}
body.mgx-restyle:where(.sidebar-toggled) .sidebar-rail ~ #sidebar-wrapper .sidebar,
body.mgx-restyle .sidebar-rail ~ #sidebar-wrapper:where([data-sidebar-zone="home"]) .sidebar,
body.mgx-restyle .sidebar-rail ~ #sidebar-wrapper .sidebar:where(.collapsed, [style*="margin-left"]) {
  border-inline-end: 0;
}
@media (max-width: 991.98px) {
  body.mgx-restyle:where(:not(.sidebar-overlay-open)) .sidebar-rail ~ #sidebar-wrapper .sidebar {
    border-inline-end: 0;
  }
}
