/*
 * kampaign-theme.css
 * Kampaign OS — Shared Design System
 * Provides design tokens, form components, buttons, cards,
 * and accessibility utilities for use across all pages.
 *
 * Class prefix: kos-
 * All CSS variables: --kos-*
 *
 * ---------------------------------------------------------------------------
 * PALETTE RATIONALE — read before changing a colour.
 *
 * The brand guidebook gives six hues: navy #1b2451, blue #39b0e4, grey #eeeff0,
 * teal #1fbbaf, purple #6a55a4, mustard #fcb029. Three of them fail WCAG AA as
 * text or UI colours on white — blue is 2.47:1, teal 2.39:1, mustard 1.85:1.
 * This is an elections-monitoring product, so AA is the floor.
 *
 * So the system runs two tiers:
 *   - LIGHT mode uses lightness-darkened derivations. Hue and saturation are
 *     preserved exactly (blue 198°/76% -> #1677a1 at 5.01:1), so they read as
 *     the brand colour rather than a muddy approximation.
 *   - DARK mode uses the PURE brand hues, which all clear 5:1 against the dark
 *     card. That is the context the guidebook designed them for — the logo puts
 *     blue on navy, never blue on white.
 *
 * Danger and success are deliberately outside the guidebook: it supplies no red
 * and no green, and status colours must stay unambiguous for colourblind users.
 *
 * Every value here is asserted in tests/Unit/BrandContrastTest.php. Changing a
 * hue without running that test is how the palette silently regresses.
 * ---------------------------------------------------------------------------
 */


/* ══ 1. DESIGN TOKENS ════════════════════════════════════════════════════════ */

:root {
  /* Brand */
  --kos-brand:          #1B2451;   /* navy — headings and brand ink. FLIPS in dark mode. */
  --kos-brand-rgb:      27, 36, 81;
  --kos-brand-mid:      #2B376E;
  /* Navy as a SURFACE, for brand chrome that stays navy in both themes: the
     sidebar and the full-bleed auth canvas. Deliberately absent from the
     html.dark-style block — --kos-brand flips to light ink there (correct for
     headings), and a chrome surface reading that token would turn white. */
  --kos-chrome:         #1B2451;
  --kos-chrome-deep:    #131A3B;   /* layered panels on the chrome surface */
  --kos-chrome-deeper:  #0D1229;   /* silhouettes / deepest layer */
  --kos-on-chrome:      #FFFFFF;   /* 14.81:1 */
  /* State text ON the navy chrome. The light-mode --kos-error/--kos-success are
     tuned for white and drop to ~2:1 against navy, so the auth screens need
     lightened variants — same two-tier logic as dark mode. */
  --kos-on-chrome-error:   #F2B8B8;
  --kos-on-chrome-success: #8FE3B0;
  --kos-cta:            #1677A1;   /* brand blue darkened, 5.01:1 on white */
  --kos-cta-rgb:        22, 119, 161;
  --kos-cta-hover:      #115E7F;   /* 7.16:1 */
  --kos-accent:         #39B0E4;   /* pure brand blue — fills/accents on navy only */
  --kos-accent-rgb:     57, 176, 228;
  --kos-accent-hover:   #6BC5EB;

  /* Surface */
  --kos-bg:             #EEEFF0;   /* brand grey */
  --kos-surface:        #FFFFFF;
  /* Panels that sit ON TOP of a map canvas rather than on a card. The canvas
     never follows the theme, so these need their own tokens — a plain
     rgba(255,255,255,…) turns into a white flash in dark mode. */
  --kos-surface-float:  rgba(255, 255, 255, 0.94);   /* legends, floating chips */
  --kos-surface-scrim:  rgba(255, 255, 255, 0.7);    /* loading veil over a map */

  /* Text — a navy-cast neutral ramp, so ink stays on-brand without going indigo */
  --kos-text:           #141A36;   /* 17.06:1 on white */
  --kos-muted:          #444A6A;   /*  8.63:1 */
  --kos-subtle:         #5E6482;   /*  5.80:1 — still AA for small text */
  --kos-placeholder:    #7F849F;   /*  3.68:1 — placeholders only, never body copy */

  /* Readable ink for anything filled with --kos-cta (buttons, skip link).
     commonMaster recomputes both per tenant via a WCAG contrast check, so a
     light brand colour gets dark ink instead of unreadable white. */
  --kos-on-primary:       #FFFFFF;
  --kos-on-primary-hover: #FFFFFF;

  /* Borders */
  --kos-border:         #D6D8E0;
  --kos-border-focus:   #1677A1;

  /* States. *-accent is the vivid brand hue for decorative fills and chart
     marks; the base token is the AA-safe one and is what text must use. */
  --kos-error:            #D82323;   /* 5.02:1 */
  --kos-error-rgb:        216, 35, 35;
  --kos-success:          #12784A;   /* 5.51:1 */
  --kos-success-rgb:      18, 120, 74;
  --kos-warning:          #996302;   /* 5.07:1 */
  --kos-warning-rgb:      153, 99, 2;
  --kos-warning-accent:   #FCB029;   /* brand mustard — fills only, never text */
  --kos-info:             #147C74;   /* brand teal darkened, 5.04:1 */
  --kos-info-rgb:         20, 124, 116;
  --kos-info-accent:      #1FBBAF;   /* brand teal — fills only */
  --kos-purple:           #6A55A4;   /* brand purple, passes as-is at 6.09:1 */
  --kos-purple-rgb:       106, 85, 164;

  /* Focus rings */
  --kos-ring:           0 0 0 3px rgba(22, 119, 161, 0.35);
  --kos-ring-err:       0 0 0 3px rgba(216, 35, 35, 0.25);

  /* Typography */
  --kos-font-head:      'Nexa', 'Outfit', 'Space Grotesk', system-ui, -apple-system, sans-serif;
  --kos-font-body:      'Space Grotesk', system-ui, -apple-system, sans-serif;
  --kos-font-mono:      'SFMono-Regular', Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;

  /* Shape — one scale, shared with $border-radius* in the SCSS custom-variables */
  --kos-radius:         6px;
  --kos-radius-lg:      8px;

  /* Touch target */
  --kos-touch:          44px;

  /* Sidebar. Merged here from a second, orphaned :root that used to sit ~900
     lines below. Two bare :root blocks in one file is a landmine — the later one
     silently wins on equal specificity, so a token added to this block did
     nothing. Keep every token in this one place. */
  --kos-sidebar-bg:        var(--kos-chrome);
  /* The active pill uses the PURE brand blue, not the darkened CTA. On navy the
     derived #1677A1 is only 2.95:1 — the selected item barely reads as selected.
     #39B0E4 is 6.00:1 here, and blue-on-navy is exactly the pairing the logo
     uses, so the accessible choice is also the more on-brand one. */
  --kos-sidebar-active:    #39B0E4;
  --kos-sidebar-text:      rgba(255, 255, 255, 0.85);
  --kos-sidebar-text-dim:  rgba(255, 255, 255, 0.55);
  --kos-sidebar-hover:     rgba(255, 255, 255, 0.08);
  /* Foregrounds are tokens too, so tenant branding can swap them for dark
     ink when a tenant picks a light sidebar/active colour. */
  --kos-sidebar-active-fg: #0B1020;  /* dark ink — the active pill is now light blue */
  --kos-sidebar-hover-fg:  #FFFFFF;
  --kos-sidebar-heading:   rgba(255, 255, 255, 0.92);
}


/* ══ 1b. DARK MODE TOKEN OVERRIDES ═══════════════════════════════════════════ */
/* The template puts `dark-style` on <html> and swaps in Bootstrap's core-dark.css.
   Unlike the previous system, the state colours DO change here: the AA-safe light
   derivations are too dark to read on the dark card, while the pure brand hues —
   which fail on white — pass comfortably. Every ratio below is against the card
   colour #283144. Because the component rules further down consume these tokens,
   redefining them here cascades app-wide. */
html.dark-style {
  --kos-bg:             #232b3a;  /* table-light header, subtle fills — a touch lighter than card */
  --kos-surface:        #283144;  /* card-header/footer — matches Bootstrap dark card body */
  --kos-text:           #E0E2EB;  /* 10.07:1 */
  --kos-muted:          #ACB0C3;  /*  6.05:1 */
  --kos-subtle:         #9CA0B4;  /*  5.02:1 */
  --kos-placeholder:    #797E96;  /* 3.25:1 — placeholders are held to the 3:1 UI floor */
  --kos-border:         #3A4356;  /* light hairline for dark surfaces */
  --kos-surface-float:  rgba(40, 49, 68, 0.94);
  --kos-surface-scrim:  rgba(35, 43, 58, 0.7);

  /* Brand hues, unmodified — this is the context they were designed for */
  --kos-cta:            #39B0E4;  /* 5.27:1 */
  --kos-cta-rgb:        57, 176, 228;
  --kos-cta-hover:      #6BC5EB;
  --kos-brand:          #E0E2EB;  /* navy is invisible on a dark card; headings flip to ink */
  --kos-brand-rgb:      224, 226, 235;

  --kos-error:          #EB8484;  /* 5.06:1 — #D82323 is only 2.01:1 here */
  --kos-error-rgb:      235, 132, 132;
  --kos-success:        #19B954;  /* 5.03:1 */
  --kos-success-rgb:    25, 185, 84;
  --kos-warning:        #FCB029;  /* brand mustard, 7.06:1 */
  --kos-warning-rgb:    252, 176, 41;
  --kos-info:           #1FBBAF;  /* brand teal, 5.45:1 */
  --kos-info-rgb:       31, 187, 175;
  --kos-purple:         #A79ACA;  /* 5.03:1 — #6A55A4 is 2.14:1 here */
  --kos-purple-rgb:     167, 154, 202;

  --kos-border-focus:   #39B0E4;
  --kos-ring:           0 0 0 3px rgba(57, 176, 228, 0.35);
  --kos-ring-err:       0 0 0 3px rgba(235, 132, 132, 0.25);

  /* The sidebar stays navy in dark mode — it is brand chrome, not a surface */
  --kos-sidebar-active: #39B0E4;
  --kos-sidebar-active-fg: #0B1020;
}


/* ══ 1c. PRIMARY BRIDGE ══════════════════════════════════════════════════════
   Bootstrap's compiled CSS hard-codes the primary colour into ~40 component and
   utility rules; it does not read var(--bs-primary). Every one of those rules
   used to be REGENERATED IN PHP ON EVERY REQUEST inside a <style> block in
   commonMaster.blade.php — about 150 uncacheable lines per response, all marked
   !important, and with no way to express a dark-mode variant (the old block
   emitted identical values for .light-style and .dark-style, which is why
   tenant colours never adapted in dark mode).

   Writing them once here, against the tokens, means:
     - the per-request payload drops to a ~15-line token assignment,
     - dark mode works, because --kos-cta is already redefined under
       html.dark-style and these rules simply follow it,
     - the rules are unscoped, so blankLayout (auth + open/, which renders its
       content with no .content-wrapper at all) finally gets them too.

   Tenant branding now only reassigns --kos-cta and friends; it no longer needs
   to restate any of this. --kos-on-primary is contrast-checked per tenant by
   App\Support\BrandPalette, so a pale brand gets dark ink automatically.
   ══════════════════════════════════════════════════════════════════════════ */

.bg-primary                  { background-color: var(--kos-cta) !important; }
.text-primary                { color: var(--kos-cta) !important; }
.border-primary              { border-color: var(--kos-cta) !important; }
.text-primary i, .fw-primary { color: var(--kos-cta) !important; }

.bg-label-primary,
.badge.bg-label-primary {
  background-color: rgb(var(--kos-cta-rgb) / 16%) !important;
  color: var(--kos-cta) !important;
}
.badge.bg-primary { color: var(--kos-on-primary); }
.alert-primary {
  background-color: rgb(var(--kos-cta-rgb) / 10%) !important;
  border-color: rgb(var(--kos-cta-rgb) / 28%) !important;
  color: var(--kos-cta) !important;
}

.btn-primary {
  --bs-btn-bg: var(--kos-cta);
  --bs-btn-border-color: var(--kos-cta);
  --bs-btn-hover-bg: var(--kos-cta-hover);
  --bs-btn-hover-border-color: var(--kos-cta-hover);
  --bs-btn-active-bg: var(--kos-cta-hover);
  --bs-btn-active-border-color: var(--kos-cta-hover);
  --bs-btn-disabled-bg: var(--kos-cta);
  --bs-btn-disabled-border-color: var(--kos-cta);
  --bs-btn-color: var(--kos-on-primary);
  --bs-btn-hover-color: var(--kos-on-primary-hover);
  --bs-btn-active-color: var(--kos-on-primary-hover);
}
.btn-outline-primary {
  --bs-btn-color: var(--kos-cta);
  --bs-btn-border-color: var(--kos-cta);
  --bs-btn-hover-bg: var(--kos-cta);
  --bs-btn-hover-border-color: var(--kos-cta);
  --bs-btn-hover-color: var(--kos-on-primary);
  --bs-btn-active-bg: var(--kos-cta);
  --bs-btn-active-border-color: var(--kos-cta);
  --bs-btn-active-color: var(--kos-on-primary);
}
.btn-label-primary {
  background-color: rgb(var(--kos-cta-rgb) / 16%) !important;
  color: var(--kos-cta) !important;
  border-color: transparent !important;
}

/* Links. `.kos-btn` is excluded alongside `.btn`: a link styled as a button
   paints its own background from --kos-cta, so recolouring its text to the same
   value would make the label invisible. */
a:not(.btn):not(.kos-btn):not(.menu-link):not(.nav-link):not(.dropdown-item):not(.page-link) { color: var(--kos-cta); }
a:not(.btn):not(.kos-btn):not(.menu-link):not(.nav-link):not(.dropdown-item):not(.page-link):hover { color: var(--kos-cta-hover); }

.form-control:focus, .form-select:focus, .form-check-input:focus {
  border-color: var(--kos-border-focus) !important;
  box-shadow: 0 0 0 0.15rem rgb(var(--kos-cta-rgb) / 25%) !important;
}
.form-check-input:checked {
  background-color: var(--kos-cta) !important;
  border-color: var(--kos-cta) !important;
}

.nav-pills .nav-link.active  { background-color: var(--kos-cta) !important; color: var(--kos-on-primary) !important; }
.nav-tabs .nav-link.active   { color: var(--kos-cta) !important; border-bottom-color: var(--kos-cta) !important; }
.page-link                   { color: var(--kos-cta); }
.page-item.active .page-link { background-color: var(--kos-cta) !important; border-color: var(--kos-cta) !important; color: var(--kos-on-primary) !important; }
.list-group-item.active      { background-color: var(--kos-cta) !important; border-color: var(--kos-cta) !important; color: var(--kos-on-primary) !important; }
.dropdown-item.active,
.dropdown-item:active        { background-color: var(--kos-cta) !important; color: var(--kos-on-primary) !important; }
.progress-bar                { background-color: var(--kos-cta) !important; }

/* Sidebar chrome follows the tokens rather than the compiled theme. */
#layout-menu.bg-menu-theme, .bg-menu-theme { background-color: var(--kos-sidebar-bg) !important; }


/* ══ 2. ACCESSIBILITY ════════════════════════════════════════════════════════ */

/* Skip to main content — keyboard only */
.kos-skip {
  position: absolute;
  top: -999px;
  left: 1rem;
  z-index: 9999;
  padding: 0.5rem 1.25rem;
  background: var(--kos-cta);
  color: var(--kos-on-primary);
  font-size: 0.875rem;
  font-weight: 600;
  border-radius: 0 0 var(--kos-radius) var(--kos-radius);
  text-decoration: none;
}
.kos-skip:focus { top: 0; }


/* ══ 3. TYPOGRAPHY ═══════════════════════════════════════════════════════════ */

.kos-font-head { font-family: var(--kos-font-head); }
.kos-font-body { font-family: var(--kos-font-body); }

.kos-heading {
  font-family: var(--kos-font-head);
  font-size: 1.75rem;
  font-weight: 600;
  color: var(--kos-text);
  line-height: 1.25;
}

.kos-subheading {
  font-size: 0.875rem;
  color: var(--kos-muted);
  line-height: 1.6;
}

.kos-label-caps {
  display: block;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--kos-text);
}

/* Colour utilities */
.kos-text-brand  { color: var(--kos-brand)  !important; }
.kos-text-cta    { color: var(--kos-cta)    !important; }
.kos-text-muted  { color: var(--kos-muted)  !important; }
.kos-text-subtle { color: var(--kos-subtle) !important; }
.kos-text-error  { color: var(--kos-error)  !important; }


/* ══ 4. LAYOUT PRIMITIVES ════════════════════════════════════════════════════ */

/* Flex/grid children refuse to shrink below their content's intrinsic width,
   because min-width defaults to `auto`. That is why `text-truncate` inside a
   flex child does nothing until min-width is zeroed — the ellipsis never gets a
   chance because the box never gets narrower than the text.

   This class is used in 31 views across the app (including the shared
   kos-stat-strip KPI tiles and the System Health cards) but was never defined:
   Bootstrap 5.1 ships min-vw-100/min-vh-100 and no min-width scale, and the
   utility was presumably assumed from a later version or from Tailwind. Every
   one of those truncations has been silently inert. Defining it here fixes them
   all at once.

   !important matches Bootstrap's utility convention, so it wins against the
   component rules it is applied alongside. */
.min-w-0 { min-width: 0 !important; }

.kos-divider {
  border: none;
  border-top: 1px solid var(--kos-border);
  margin-top: 0;
  margin-bottom: 0;
}

/* White surface card */
.kos-card {
  background: var(--kos-surface);
  border: 1px solid var(--kos-border);
  border-radius: var(--kos-radius-lg);
  padding: 2rem 2.25rem 1.75rem;
}

@media (max-width: 575.98px) {
  .kos-card {
    border: none;
    background: transparent;
    padding: 0;
  }
}


/* ══ 5. FORM COMPONENTS ══════════════════════════════════════════════════════ */

/* Field wrapper */
.kos-field { margin-bottom: 1.1rem; }

/* Label */
.kos-label {
  display: block;
  font-family: var(--kos-font-body);
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--kos-text);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 0.4rem;
}

/* Input */
.kos-input {
  display: block;
  width: 100%;
  min-height: var(--kos-touch);
  padding: 0.55rem 0.875rem;
  font-family: var(--kos-font-body);
  font-size: 0.9rem;
  color: var(--kos-text);
  background: var(--kos-surface);
  border: 1.5px solid var(--kos-border);
  border-radius: var(--kos-radius);
  outline: none;
  line-height: 1.5;
}
.kos-input::placeholder          { color: var(--kos-placeholder); }
.kos-input:focus                  { border-color: var(--kos-border-focus); box-shadow: var(--kos-ring); }
.kos-input.is-invalid             { border-color: var(--kos-error); }
.kos-input.is-invalid:focus       { box-shadow: var(--kos-ring-err); }

/* Password visibility wrapper */
.kos-pw-wrap          { position: relative; }
.kos-pw-wrap .kos-input { padding-right: 2.75rem; }

.kos-pw-btn {
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: var(--kos-touch);
  background: none;
  border: none;
  cursor: pointer;
  color: var(--kos-placeholder);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 0 var(--kos-radius) var(--kos-radius) 0;
}
.kos-pw-btn:hover         { color: var(--kos-muted); }
.kos-pw-btn:focus-visible { outline: none; box-shadow: var(--kos-ring); }

/* Inline error message (use role="alert") */
.kos-field-error {
  display: flex;
  align-items: flex-start;
  gap: 0.35rem;
  font-family: var(--kos-font-body);
  font-size: 0.775rem;
  color: var(--kos-error);
  margin-top: 0.35rem;
  line-height: 1.4;
}
.kos-field-error > svg { flex-shrink: 0; margin-top: 1px; }

/* Remember / checkbox row */
.kos-remember {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.kos-check {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  cursor: pointer;
  accent-color: var(--kos-cta);
  border-radius: 2px;
}
.kos-check-label {
  font-family: var(--kos-font-body);
  font-size: 0.82rem;
  color: var(--kos-muted);
  cursor: pointer;
  user-select: none;
  line-height: 1;
}


/* ══ 6. BUTTON ═══════════════════════════════════════════════════════════════ */

.kos-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: var(--kos-touch);
  padding: 0.6rem 1.25rem;
  font-family: var(--kos-font-body);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border-radius: var(--kos-radius);
  border: 1.5px solid transparent;
  cursor: pointer;
  text-decoration: none;
  line-height: 1.4;
}
.kos-btn:focus-visible { outline: none; box-shadow: var(--kos-ring); }
.kos-btn:disabled      { opacity: 0.6; cursor: not-allowed; }

/* Filled — primary action */
.kos-btn-primary {
  background: var(--kos-cta);
  color: var(--kos-on-primary);
  border-color: var(--kos-cta);
  width: 100%;
}
.kos-btn-primary:hover,
.kos-btn-primary:focus,
.kos-btn-primary:active {
  background: var(--kos-cta-hover);
  border-color: var(--kos-cta-hover);
  color: var(--kos-on-primary-hover);
}
/* Links styled as buttons: keep the button ink whatever the surrounding
   link styling (template defaults, tenant brand rules) tries to apply. */
a.kos-btn-primary,
a.kos-btn-primary:hover,
a.kos-btn-primary:focus,
a.kos-btn-primary:visited { text-decoration: none; }
/* Disabled: dim the fill, not the whole element. A blanket opacity fades the
   label along with the background and drops it under 3:1 — the submit button
   spends its whole "Activating…" state here. */
.kos-btn-primary:disabled,
.kos-btn-primary[disabled] {
  opacity: 1;
  background: var(--kos-cta);
  border-color: var(--kos-cta);
  color: var(--kos-on-primary);
  filter: grayscale(0.4) brightness(0.92);
}

/* Outline — secondary action */
.kos-btn-outline {
  background: transparent;
  color: var(--kos-cta);
  border-color: var(--kos-cta);
}
.kos-btn-outline:hover { background: var(--kos-cta); color: var(--kos-on-primary); }

/* Ghost — tertiary / text-link action */
.kos-btn-ghost {
  background: transparent;
  color: var(--kos-cta);
  border-color: transparent;
  padding-left: 0;
  padding-right: 0;
  min-height: auto;
  font-size: 0.82rem;
  letter-spacing: 0;
  text-transform: none;
  font-weight: 400;
}
.kos-btn-ghost:hover { color: var(--kos-cta-hover); text-decoration: underline; }


/* ══ 7. TRUST / STATUS BADGE ═════════════════════════════════════════════════ */

.kos-trust-list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  width: 100%;
}

.kos-trust-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.65rem 1rem;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.09);
  border-radius: var(--kos-radius);
}

.kos-trust-item--light {
  background: var(--kos-bg);
  border-color: var(--kos-border);
}

.kos-trust-icon {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  color: var(--kos-accent);
}

.kos-trust-item--light .kos-trust-icon { color: var(--kos-cta); }

.kos-trust-text {
  font-family: var(--kos-font-body);
  font-size: 0.72rem;
  font-weight: 400;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.65);
  line-height: 1.3;
}

.kos-trust-item--light .kos-trust-text { color: var(--kos-muted); }


/* ══ 8. SECURITY NOTE ════════════════════════════════════════════════════════ */

.kos-security-note {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  font-family: var(--kos-font-body);
  font-size: 0.72rem;
  color: var(--kos-subtle);
  letter-spacing: 0.02em;
  line-height: 1.5;
}
.kos-security-note svg { flex-shrink: 0; color: var(--kos-subtle); }


/* ══ 9. INLINE ALERT BANNER ══════════════════════════════════════════════════ */

.kos-alert {
  display: flex;
  gap: 0.65rem;
  padding: 0.75rem 1rem;
  border-radius: var(--kos-radius);
  font-family: var(--kos-font-body);
  font-size: 0.84rem;
  line-height: 1.5;
  border: 1px solid transparent;
}
.kos-alert svg          { flex-shrink: 0; margin-top: 2px; }
/* Token-derived, so these follow light/dark with no duplicate block. */
.kos-alert-error        { background: rgb(var(--kos-error-rgb) / 10%);   border-color: rgb(var(--kos-error-rgb) / 28%);   color: var(--kos-error); }
.kos-alert-success      { background: rgb(var(--kos-success-rgb) / 10%); border-color: rgb(var(--kos-success-rgb) / 28%); color: var(--kos-success); }
.kos-alert-warning      { background: rgb(var(--kos-warning-rgb) / 10%); border-color: rgb(var(--kos-warning-rgb) / 28%); color: var(--kos-warning); }
.kos-alert-info         { background: rgb(var(--kos-info-rgb) / 10%);    border-color: rgb(var(--kos-info-rgb) / 28%);    color: var(--kos-info); }


/* ══ 10. REDUCED MOTION ═══════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}


/* ══ 11. DASHBOARD — BOOTSTRAP OVERRIDES ═════════════════════════════════════
 * Scoped to .content-wrapper so the sidebar, navbar, and vendor UI are
 * unaffected. Every Bootstrap component inside the content area picks up
 * the Kampaign OS brand tokens automatically — no blade file changes required.
 ******************************************************************************/

/* ── Page header banner ─────────────────────────────── */
.kos-page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.5rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--kos-border);
}
.kos-page-header-left { flex: 1 1 0; min-width: 0; }
.kos-page-title {
  font-family: var(--kos-font-head);
  font-size: 1.6rem;
  font-weight: 600;
  color: var(--kos-text);
  line-height: 1.25;
  margin: 0 0 0.2rem;
  /* Organization names are free text up to 255 chars. Break one that has no
     spaces rather than letting it push the header wider than the viewport. */
  overflow-wrap: break-word;
}
.kos-page-subtitle {
  font-size: 0.82rem;
  color: var(--kos-subtle);
  margin: 0;
  line-height: 1.5;
  overflow-wrap: break-word;
}
.kos-page-header-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
  /* Wrap, because these headers carry more than a single button: the tenant
     analytics header holds a four-chip range selector, an export dropdown, a
     refresh form and a link. Without this they sit on one unshrinkable row and
     overflow the page at every width between 576px and roughly 1100px — the
     column switch below only rescues phones. */
  flex-wrap: wrap;
  justify-content: flex-end;
}
@media (max-width: 575.98px) {
  .kos-page-header { flex-direction: column; }
  .kos-page-header-actions { width: 100%; justify-content: flex-start; }
}

/* ── Card: consistent border, left accent, headings ──── */
.content-wrapper .card,
.authentication-wrapper .card {
  border-color: var(--kos-border);
  border-radius: var(--kos-radius-lg);
}
.content-wrapper .card-header,
.authentication-wrapper .card-header {
  background: var(--kos-surface);
  border-bottom-color: var(--kos-border);
  border-left: 3px solid var(--kos-cta);
  padding-left: calc(1.25rem - 3px);
}
.content-wrapper .card-footer,
.authentication-wrapper .card-footer {
  background: var(--kos-surface);
  border-top-color: var(--kos-border);
}

/* The core theme zeroes `.card-header + .card-body` top padding, which reads
   right for its own borderless header. Where a header opts into a visible
   divider with .border-bottom, that leaves the body flush against the rule —
   give the body its top padding back so it matches the other three sides. */
.content-wrapper .card-header.border-bottom + .card-body,
.authentication-wrapper .card-header.border-bottom + .card-body {
  padding-top: 1.375rem;
}
.content-wrapper .card-title,
.authentication-wrapper .card-title,
.content-wrapper h5.card-title,
.authentication-wrapper h5.card-title,
.content-wrapper h6.card-title,
.authentication-wrapper h6.card-title,
.content-wrapper .card-header > h4,
.authentication-wrapper .card-header > h4,
.content-wrapper .card-header > h5,
.authentication-wrapper .card-header > h5,
.content-wrapper .card-header > h6,
.authentication-wrapper .card-header > h6 {
  font-family: var(--kos-font-head);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--kos-text);
  letter-spacing: 0.01em;
}

/* Stat card numbers */
.content-wrapper .card-body > h4,
.authentication-wrapper .card-body > h4,
.content-wrapper .card-body > h5,
.authentication-wrapper .card-body > h5 {
  font-family: var(--kos-font-head);
  color: var(--kos-text);
}

/* ── Form labels ─────────────────────────────────────── */
.content-wrapper .form-label,
.authentication-wrapper .form-label {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--kos-text);
  margin-bottom: 0.4rem;
}

/* ── Form controls & selects ─────────────────────────── */
.content-wrapper .form-control,
.authentication-wrapper .form-control,
.content-wrapper .form-select,
.authentication-wrapper .form-select {
  border-color: var(--kos-border);
  color: var(--kos-text);
  min-height: var(--kos-touch);
  font-size: 0.9rem;
}
.content-wrapper .form-control::placeholder,
.authentication-wrapper .form-control::placeholder { color: var(--kos-placeholder); }
.content-wrapper .form-control:focus,
.authentication-wrapper .form-control:focus,
.content-wrapper .form-select:focus,
.authentication-wrapper .form-select:focus {
  border-color: var(--kos-border-focus);
  box-shadow: var(--kos-ring);
}
.content-wrapper .form-control.is-invalid:focus,
.authentication-wrapper .form-control.is-invalid:focus,
.content-wrapper .form-select.is-invalid:focus,
.authentication-wrapper .form-select.is-invalid:focus { box-shadow: var(--kos-ring-err); }

/* sm size variants stay compact */
.content-wrapper .form-control-sm,
.authentication-wrapper .form-control-sm,
.content-wrapper .form-select-sm,
.authentication-wrapper .form-select-sm { font-size: 0.85rem; min-height: 36px; }

/* ── Alerts ──────────────────────────────────────────── */
.content-wrapper .alert,
.authentication-wrapper .alert {
  border-radius: var(--kos-radius);
  font-size: 0.875rem;
  border-width: 1px;
}
/* Tints are derived from the state tokens rather than hard-coded. Because the
   *-rgb tokens are themselves redefined under html.dark-style, one rule now
   serves both modes — which is why the dark-mode duplicate block that used to
   sit here is gone. Don't reintroduce literal washes: they were the reason
   dark mode showed bright light-theme chips punched out of a dark card. */
.content-wrapper .alert-success,
.authentication-wrapper .alert-success {
  background: rgb(var(--kos-success-rgb) / 10%); border-color: rgb(var(--kos-success-rgb) / 28%); color: var(--kos-success);
}
.content-wrapper .alert-danger,
.authentication-wrapper .alert-danger {
  background: rgb(var(--kos-error-rgb) / 10%); border-color: rgb(var(--kos-error-rgb) / 28%); color: var(--kos-error);
}
.content-wrapper .alert-warning,
.authentication-wrapper .alert-warning {
  background: rgb(var(--kos-warning-rgb) / 10%); border-color: rgb(var(--kos-warning-rgb) / 28%); color: var(--kos-warning);
}
.content-wrapper .alert-info,
.authentication-wrapper .alert-info {
  background: rgb(var(--kos-info-rgb) / 10%); border-color: rgb(var(--kos-info-rgb) / 28%); color: var(--kos-info);
}

/* ── btn-primary ─────────────────────────────────────── */
.content-wrapper .btn-primary,
.authentication-wrapper .btn-primary {
  background-color: var(--kos-cta) !important;
  border-color: var(--kos-cta) !important;
  color: #ffffff !important;
}
.content-wrapper .btn-primary:hover,
.authentication-wrapper .btn-primary:hover,
.content-wrapper .btn-primary:active,
.authentication-wrapper .btn-primary:active {
  background-color: var(--kos-cta-hover) !important;
  border-color: var(--kos-cta-hover) !important;
}
.content-wrapper .btn-primary:focus-visible,
.authentication-wrapper .btn-primary:focus-visible { box-shadow: var(--kos-ring) !important; }

/* ── btn-outline-primary ─────────────────────────────── */
.content-wrapper .btn-outline-primary,
.authentication-wrapper .btn-outline-primary {
  color: var(--kos-cta) !important;
  border-color: var(--kos-cta) !important;
}
.content-wrapper .btn-outline-primary:hover,
.authentication-wrapper .btn-outline-primary:hover {
  background-color: var(--kos-cta) !important;
  color: #fff !important;
}

/* ── Icon buttons (edit/delete) ─────────────────────── */
.content-wrapper .btn-icon.text-primary,
.authentication-wrapper .btn-icon.text-primary { color: var(--kos-cta) !important; }

/* ── Table headers ───────────────────────────────────── */
.content-wrapper .table > thead th,
.authentication-wrapper .table > thead th,
.content-wrapper .table > thead > tr > th,
.authentication-wrapper .table > thead > tr > th {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--kos-muted);
  border-bottom-color: var(--kos-border);
}
.content-wrapper .table-light,
.authentication-wrapper .table-light,
.content-wrapper thead.table-light > tr > th,
.authentication-wrapper thead.table-light > tr > th {
  --bs-table-bg: var(--kos-bg);
  background-color: var(--kos-bg) !important;
}
.content-wrapper .table-hover > tbody > tr:hover > *,
.authentication-wrapper .table-hover > tbody > tr:hover > * {
  background-color: rgba(3, 105, 161, 0.04);
  color: inherit;
}

/* ── Pagination ──────────────────────────────────────── */
.content-wrapper .page-link,
.authentication-wrapper .page-link {
  color: var(--kos-cta);
  border-color: var(--kos-border);
}
.content-wrapper .page-link:hover,
.authentication-wrapper .page-link:hover {
  background: var(--kos-bg);
  border-color: var(--kos-border-focus);
  color: var(--kos-cta-hover);
}
.content-wrapper .page-item.active .page-link,
.authentication-wrapper .page-item.active .page-link {
  background-color: var(--kos-cta);
  border-color: var(--kos-cta);
  color: #fff;
}
.content-wrapper .page-item.disabled .page-link,
.authentication-wrapper .page-item.disabled .page-link { color: var(--kos-subtle); }

/* ── Modal: keep card-header accent bar out of modals ── */
.modal .card-header { border-left: none !important; }

/* ── Section group headings (h6 used as dividers in forms) */
.content-wrapper .text-muted.mb-1,
.authentication-wrapper .text-muted.mb-1,
.content-wrapper h6.text-muted,
.authentication-wrapper h6.text-muted {
  font-family: var(--kos-font-body);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--kos-subtle) !important;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--kos-border);
  margin-bottom: 0.75rem !important;
}

/* ── Badge bg-label-primary pull to brand colour ─────── */
.content-wrapper .bg-label-primary,
.authentication-wrapper .bg-label-primary {
  background-color: rgba(3, 105, 161, 0.12) !important;
  color: var(--kos-cta) !important;
}


/* ══ 12. LIST PAGES — ICON BADGE, BREADCRUMB, STATS STRIP, PILLS, TABLE ══════ */

/* Page header icon badge */
.kos-page-icon {
  flex-shrink: 0;
  width: 46px;
  height: 46px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  background: rgba(3, 105, 161, 0.1);
  color: var(--kos-cta);
  font-size: 1.45rem;
}

/* Breadcrumb (page header, right side) */
.content-wrapper .breadcrumb,
.authentication-wrapper .breadcrumb { margin: 0; font-size: 0.8rem; }
.content-wrapper .breadcrumb-item a,
.authentication-wrapper .breadcrumb-item a { color: var(--kos-subtle); text-decoration: none; }
.content-wrapper .breadcrumb-item a:hover,
.authentication-wrapper .breadcrumb-item a:hover { color: var(--kos-cta); }
.content-wrapper .breadcrumb-item.active,
.authentication-wrapper .breadcrumb-item.active { color: var(--kos-text); font-weight: 500; }

/* Stats strip — row of key counts above a list table */
.kos-stat {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  min-width: 0;
}
@media (min-width: 1200px) {
  /* Card tiles carry their own border, so they skip the divider. */
  .kos-stats-strip > [class*="col"] + [class*="col"] .kos-stat:not(.kos-stat--card) {
    border-left: 1px solid var(--kos-border);
    padding-left: 1.5rem;
  }
}

/* Card variant — a self-contained tile. Used where a stat is also a control
   (clickable status filters) or where tiles wrap onto several rows. */
.kos-stat--card {
  display: block;
  background: var(--kos-surface);
  border: 1px solid var(--kos-border);
  border-radius: var(--kos-radius-lg);
  padding: 0.8rem 0.9rem;
  color: inherit;
  transition: box-shadow 0.15s ease, transform 0.15s ease, border-color 0.15s ease;
  /* Nothing may escape a tile. The icon is flex-shrink:0, so if the text column
     ever fails to shrink the icon is pushed past the card edge and paints over
     the neighbouring tile's label — which is precisely what happened while the
     min-w-0 utility below was undefined. This is the belt to that braces. */
  overflow: hidden;
}
/* The text column, restated here rather than trusted to the min-w-0 class in
   the markup: that class went undefined for a long time and the failure was
   silent and ugly. A tile must degrade by ellipsising its own caption, never by
   spilling into its neighbour. */
.kos-stat--card > div > .min-w-0,
.kos-stat > .min-w-0 { min-width: 0; }
a.kos-stat--card:hover {
  box-shadow: 0 0.35rem 0.9rem rgba(0, 0, 0, 0.07);
  transform: translateY(-2px);
}
.kos-stat--card .kos-stat-label { font-size: 0.68rem; letter-spacing: 0.04em; font-weight: 600; }
.kos-stat--card .kos-stat-value { font-size: 1.35rem; margin-top: 0.1rem; }
.kos-stat-icon {
  flex-shrink: 0;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.3rem;
}
.kos-stat-icon--primary { background: rgba(3, 105, 161, 0.12);  color: var(--kos-cta); }
.kos-stat-icon--success { background: rgba(21, 128, 61, 0.12);  color: var(--kos-success); }
.kos-stat-icon--warning { background: rgba(180, 83, 9, 0.12);   color: var(--kos-warning); }
.kos-stat-icon--purple  { background: rgb(var(--kos-purple-rgb) / 12%); color: var(--kos-purple); }
.kos-stat-icon--secondary { background: var(--kos-bg); color: var(--kos-subtle); }
.kos-stat-icon--danger  { background: rgba(220, 38, 38, 0.12);  color: var(--kos-error); }

.kos-stat-label { font-size: 0.75rem; color: var(--kos-subtle); line-height: 1.3; }
.kos-stat-value {
  font-family: var(--kos-font-head);
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--kos-text);
  line-height: 1.25;
  /* A grouped figure like 12,345,678 has no natural break opportunity, and the
     six-across strip leaves each tile ~140px at 1200px. Break rather than
     spill into the neighbouring tile. */
  overflow-wrap: break-word;
}
.kos-stat-sub { font-size: 0.72rem; color: var(--kos-subtle); line-height: 1.3; }
.kos-stat-pct--success { color: var(--kos-success); font-weight: 600; }
.kos-stat-pct--warning { color: var(--kos-warning); font-weight: 600; }
.kos-stat-pct--purple  { color: var(--kos-purple); font-weight: 600; }

/* Status pills — dot + label */
/* .kos-pill was retired during the Kampaign OS rebrand. It duplicated
   `badge bg-label-*` (9 files vs 132), hard-coded six light washes with no
   dark counterpart, was never reached by tenant branding, and caused real
   drift — agent status rendered as a pill on the index and a badge on the
   show page. bg-label-* is mixin-generated from $theme-colors, so it
   re-skins with the palette for free. Do not reintroduce a second badge
   system; extend .badge instead. */

/* ── Workflow stepper ───────────────────────────────────
   A linear "where is this record in its lifecycle" indicator: numbered nodes
   joined by a rail, each done / active / upcoming.

   This exists because the campaign detail page drew its own with hardcoded hex
   values (#71dd37, #696cff, #e8e8e8, #aaa) baked into inline styles. Those are
   Sneat's light-theme colours, so on html.dark-style the rail and the upcoming
   nodes rendered as near-white blocks on a dark card and the muted labels fell
   below any readable contrast. Tokens fix that for free, and the component is
   reusable by any other multi-step record (bulk imports, member batches).
   ------------------------------------------------------ */
.kos-steps {
  display: flex;
  align-items: flex-start;
  gap: 0;
}
.kos-step {
  display: flex;
  align-items: flex-start;
  flex: 1 1 0;
  min-width: 0;
}
.kos-step:last-child { flex: 0 0 auto; }
.kos-step-node {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  flex-shrink: 0;
  width: 5.5rem;
}
.kos-step-dot {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.8rem;
  font-weight: 700;
  line-height: 1;
  background: var(--kos-bg);
  color: var(--kos-placeholder);
  border: 1px solid var(--kos-border);
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.kos-step-label {
  font-size: 0.72rem;
  color: var(--kos-subtle);
  text-align: center;
  line-height: 1.2;
  /* The labels sit under fixed-width nodes; a long one must wrap inside its
     own column rather than widening the node and skewing the rail. */
  overflow-wrap: break-word;
}
/* The connecting rail. margin-top centres it against the 32px dot. */
.kos-step-rail {
  flex: 1 1 auto;
  height: 2px;
  margin-top: 15px;
  background: var(--kos-border);
  border-radius: 1px;
  min-width: 0.75rem;
}

.kos-step--done .kos-step-dot {
  background: var(--kos-success);
  border-color: var(--kos-success);
  color: #fff;
}
.kos-step--done .kos-step-label { color: var(--kos-success); }
.kos-step--done .kos-step-rail  { background: var(--kos-success); }

.kos-step--active .kos-step-dot {
  background: var(--kos-cta);
  border-color: var(--kos-cta);
  color: #fff;
  /* Ring rather than a scale transform: the row is a fixed rail, and growing
     the dot would nudge every label after it. */
  box-shadow: 0 0 0 3px rgba(3, 105, 161, 0.18);
}
.kos-step--active .kos-step-label { color: var(--kos-cta); font-weight: 600; }

@media (max-width: 575.98px) {
  .kos-step-node { width: 4.25rem; }
  .kos-step-label { font-size: 0.66rem; }
}

/* Next-action strip under the stepper — the one thing to do next. */
.kos-next-action {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-top: 0.85rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--kos-border);
  font-size: 0.82rem;
  color: var(--kos-muted);
}

/* DataTables footer — "Showing X to Y of Z" + per-page select + pager */
.content-wrapper .kos-dt-footer,
.authentication-wrapper .kos-dt-footer { border-top: 1px solid var(--kos-border); }
.content-wrapper .dataTables_info,
.authentication-wrapper .dataTables_info {
  padding: 0 !important;
  font-size: 0.8rem;
  color: var(--kos-subtle);
}
.content-wrapper .dataTables_length label,
.authentication-wrapper .dataTables_length label { margin: 0; }
.content-wrapper .dataTables_length .form-select,
.authentication-wrapper .dataTables_length .form-select,
.content-wrapper .dataTables_length select,
.authentication-wrapper .dataTables_length select {
  min-height: 36px;
  font-size: 0.85rem;
  width: auto;
  padding-right: 2rem;
}
.content-wrapper .dataTables_paginate .pagination,
.authentication-wrapper .dataTables_paginate .pagination { margin: 0; }
.content-wrapper .dataTables_paginate .page-link,
.authentication-wrapper .dataTables_paginate .page-link { font-size: 0.82rem; }

/* =============================================================
   Sidebar theme — brand navy.
   The --kos-sidebar-* tokens that used to be declared here now live in the
   single :root at the top of this file; see the note there for why.
   ============================================================= */

#layout-menu.bg-menu-theme {
  background-color: var(--kos-sidebar-bg) !important;
  color: var(--kos-sidebar-text);
}

#layout-menu.bg-menu-theme .menu-divider {
  border-color: rgba(255, 255, 255, 0.12) !important;
}

#layout-menu.bg-menu-theme .app-brand-text {
  color: var(--kos-sidebar-text) !important;
}

#layout-menu.bg-menu-theme .menu-inner-shadow {
  background: linear-gradient(var(--kos-sidebar-bg) 41%, rgba(6, 71, 123, 0.11) 95%, rgba(6, 71, 123, 0)) !important;
}

/* Section headers — bright, bold, uppercase */
#layout-menu.bg-menu-theme .menu-inner > .menu-header {
  color: var(--kos-sidebar-heading);
}
#layout-menu.bg-menu-theme .menu-inner > .menu-header .menu-header-text {
  color: var(--kos-sidebar-heading);
  font-weight: 700;
  letter-spacing: 0.06em;
}
#layout-menu.bg-menu-theme .menu-inner > .menu-header::before {
  background-color: var(--kos-sidebar-text-dim) !important;
}

/* Links + icons */
#layout-menu.bg-menu-theme .menu-link,
#layout-menu.bg-menu-theme .menu-horizontal-prev,
#layout-menu.bg-menu-theme .menu-horizontal-next {
  color: var(--kos-sidebar-text) !important;
}
#layout-menu.bg-menu-theme .menu-link .menu-icon,
#layout-menu.bg-menu-theme .menu-item > .menu-link i {
  color: var(--kos-sidebar-text) !important;
}

/* Hover / focus */
#layout-menu.bg-menu-theme .menu-item .menu-link:hover,
#layout-menu.bg-menu-theme .menu-item .menu-link:focus,
#layout-menu.bg-menu-theme .menu-item.open:not(.menu-item-closing) > .menu-toggle {
  background-color: var(--kos-sidebar-hover) !important;
  color: var(--kos-sidebar-hover-fg) !important;
}
#layout-menu.bg-menu-theme .menu-item .menu-link:hover i,
#layout-menu.bg-menu-theme .menu-item.open:not(.menu-item-closing) > .menu-toggle i {
  color: var(--kos-sidebar-hover-fg) !important;
}

/* Active item — solid bright blue pill */
#layout-menu.bg-menu-theme .menu-item.active > .menu-link {
  background: var(--kos-sidebar-active) !important;
  box-shadow: none !important;
  color: var(--kos-sidebar-active-fg) !important;
}
#layout-menu.bg-menu-theme .menu-item.active > .menu-link i {
  color: var(--kos-sidebar-active-fg) !important;
}

/* Expanded (open) parent group: keep transparent so the branded blue shows
   through. The stock theme paints this group grey (#eceded light /
   #252b37 !important dark), which clashes with the sidebar — most visibly in
   dark mode where a grey block appears behind the open submenu. */
#layout-menu.bg-menu-theme .menu-inner > .menu-item.open,
#layout-menu.bg-menu-theme .menu-inner > .menu-item.active,
#layout-menu.bg-menu-theme .menu-sub {
  background: transparent !important;
}

/* Submenu */
#layout-menu.bg-menu-theme .menu-sub .menu-link {
  color: var(--kos-sidebar-text) !important;
  background: transparent !important;
}
#layout-menu.bg-menu-theme .menu-sub .menu-link::before {
  color: var(--kos-sidebar-text-dim) !important;
}
#layout-menu.bg-menu-theme .menu-sub .menu-item.active > .menu-link {
  background: var(--kos-sidebar-active) !important;
  color: var(--kos-sidebar-active-fg) !important;
}
#layout-menu.bg-menu-theme .menu-sub .menu-item.active > .menu-link::before {
  color: var(--kos-sidebar-active-fg) !important;
}

/* Collapse / toggle chrome */
#layout-menu.bg-menu-theme .layout-menu-toggle {
  color: var(--kos-sidebar-text) !important;
}
#layout-menu.bg-menu-theme .menu-toggle::after {
  color: var(--kos-sidebar-text) !important;
}

/* Scrollbar */
#layout-menu.bg-menu-theme .ps__thumb-y {
  background-color: rgba(255, 255, 255, 0.35) !important;
}


/* ── Avatar icon centering fix ─────────────────────────────────────
   Sneat/Vuexy's .avatar only centers its content when the glyph is
   wrapped in .avatar-initial. Many stat cards across the app place a
   bare <i> directly inside .avatar (e.g. <div class="avatar avatar-md
   bg-label-primary rounded"><i class="bx ..."></i></div>), which left
   the icon stuck in the top-left corner of the coloured box. Center
   bare direct-child icons; .avatar-initial markup is unaffected. */
.avatar > i {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

/* ─────────────────────────────────────────────────────────────────────────
   Severity rows — a finding with a level, a count and a link to its source.
   Lifted out of the system-overview page so the election integrity pages,
   the overview teaser and the declaration queue share one appearance.
   ───────────────────────────────────────────────────────────────────────── */
.kos-alert-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--kos-border);
  border-radius: var(--kos-radius-lg);
  background: var(--kos-surface);
  color: var(--kos-text);
  font-size: 0.85rem;
  transition: box-shadow 0.15s ease, border-color 0.15s ease;
}
a.kos-alert-row:hover { box-shadow: 0 0.2rem 0.6rem rgba(0, 0, 0, 0.07); border-color: var(--kos-cta); }
.kos-alert-icon {
  width: 28px; height: 28px; border-radius: 6px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--kos-bg); color: var(--kos-subtle); font-size: 1rem;
}
.kos-alert-title { font-weight: 500; }
.kos-alert-count { font-weight: 700; font-variant-numeric: tabular-nums; min-width: 2.5rem; text-align: right; }

.kos-sev {
  font-size: 0.68rem; font-weight: 700; text-transform: uppercase;
  border-radius: 5px; padding: 0.1rem 0.4rem; letter-spacing: 0.02em;
}
.kos-sev.high   { background: rgb(var(--kos-error-rgb) / 12%);   color: var(--kos-error); }
.kos-sev.medium { background: rgb(var(--kos-warning-rgb) / 14%); color: var(--kos-warning); }
.kos-sev.low    { background: var(--kos-bg);                     color: var(--kos-subtle); }

.kos-alert-row.high   .kos-alert-icon { background: rgb(var(--kos-error-rgb) / 12%);   color: var(--kos-error); }
.kos-alert-row.medium .kos-alert-icon { background: rgb(var(--kos-warning-rgb) / 14%); color: var(--kos-warning); }

/* Coverage cell — badge over a thin bar, the 80/50 convention. */
.kos-progress-cell { min-width: 130px; }


/* The election map panels were light-only; keep them legible in dark mode. */
html.dark-style #eo-map-legend,
html.dark-style #er-map-legend {
  background: rgba(40, 49, 68, 0.94);
  color: var(--kos-text);
}
html.dark-style #eo-map-loading,
html.dark-style #er-map-loading { background: rgba(35, 43, 58, 0.7); }


/* ══ 13. LOCALE CODE CHIP ════════════════════════════════════════════════════
   Replaces the flag-icons glyphs in the navbar language switcher. A flag names
   a country, not a language, and dropping the dependency removed a whole
   icon-font from every page load. */
.kos-locale-code {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2rem;
  height: 1.5rem;
  padding: 0 0.35rem;
  border: 1px solid var(--kos-border);
  border-radius: var(--kos-radius);
  background: var(--kos-bg);
  color: var(--kos-muted);
  font-family: var(--kos-font-body);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1;
}
.dropdown-item.active .kos-locale-code,
.dropdown-item:active .kos-locale-code {
  border-color: transparent;
  background: rgba(var(--kos-cta-rgb), 0.16);
  color: var(--kos-cta);
}


/* ══ 14. COMPONENT POLISH ════════════════════════════════════════════════════
   Extends the token system to the Bootstrap components §11 never reached.

   These are written as CSS against the compiled Bootstrap classes rather than as
   Blade components on purpose. There are 3,955 raw `card` usages and 284 views;
   migrating them to <x-...> is a multi-week rewrite, and the app already has a
   working reuse convention (_partials/). Restyling the classes reaches every
   view at once and touches no markup.

   What that CANNOT fix, stated so nobody assumes otherwise: structural
   divergence. The three KPI-card dialects will now LOOK like one system but
   still carry different DOM, so they can differ at odd breakpoints. Only a
   component migration fixes that.

   Unscoped deliberately — blankLayout has no .content-wrapper, and auth needs
   these too.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Badges ─────────────────────────────────────────────────────────────────
   The surviving badge system (see the .kos-pill retirement note above). */
.badge {
  font-family: var(--kos-font-body);
  font-weight: 600;
  letter-spacing: 0.01em;
  border-radius: var(--kos-radius-sm, 4px);
}

/* ── Buttons ────────────────────────────────────────────────────────────────
   Shape and type only; colour comes from $theme-colors at build time and, for
   primary, from the bridge in §1c. */
.btn {
  font-family: var(--kos-font-body);
  font-weight: 600;
  border-radius: var(--kos-radius);
}
.btn:focus-visible { box-shadow: var(--kos-ring) !important; }
.btn-sm { border-radius: var(--kos-radius); }

/* ── Modals ─────────────────────────────────────────────────────────────────
   50 usages across 27 views, none previously styled by this file. */
.modal-content {
  border: 1px solid var(--kos-border);
  border-radius: var(--kos-radius-lg);
  background: var(--kos-surface);
}
.modal-header {
  border-bottom-color: var(--kos-border);
  background: var(--kos-surface);
}
.modal-title {
  font-family: var(--kos-font-head);
  font-weight: 600;
  color: var(--kos-text);
}
.modal-footer { border-top-color: var(--kos-border); }

/* ── Tabs and pills ─────────────────────────────────────────────────────────
   The active states are coloured by the bridge; this is shape and inactive ink. */
.nav-tabs { border-bottom-color: var(--kos-border); }
.nav-tabs .nav-link,
.nav-pills .nav-link {
  font-family: var(--kos-font-body);
  font-weight: 600;
  color: var(--kos-muted);
}
.nav-tabs .nav-link:hover:not(.active) { color: var(--kos-text); }

/* ── Dropdowns ──────────────────────────────────────────────────────────────*/
.dropdown-menu {
  border: 1px solid var(--kos-border);
  border-radius: var(--kos-radius-lg);
  background: var(--kos-surface);
}
.dropdown-item { color: var(--kos-muted); }
.dropdown-item:hover:not(.active):not(:active) {
  background: var(--kos-bg);
  color: var(--kos-text);
}
.dropdown-divider { border-top-color: var(--kos-border); }
.dropdown-header {
  color: var(--kos-subtle);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* ── List groups, input groups, checks ──────────────────────────────────────*/
.list-group-item {
  border-color: var(--kos-border);
  background: var(--kos-surface);
  color: var(--kos-muted);
}
.input-group-text {
  border-color: var(--kos-border);
  background: var(--kos-bg);
  color: var(--kos-subtle);
}
.form-check-input { border-color: var(--kos-border); }
.form-check-label { color: var(--kos-muted); }

/* ── Toasts ─────────────────────────────────────────────────────────────────
   _partials/flash-toasts uses .bg-{success|danger|warning|info|primary}, which
   the recompiled palette already covers; this is the shell. */
.toast {
  border: 1px solid var(--kos-border);
  border-radius: var(--kos-radius-lg);
  background: var(--kos-surface);
}
.toast-header {
  border-bottom-color: var(--kos-border);
  background: var(--kos-surface);
  color: var(--kos-text);
}

/* ── Accordion / offcanvas ──────────────────────────────────────────────────*/
.accordion-item {
  border-color: var(--kos-border);
  background: var(--kos-surface);
}
.accordion-button {
  font-family: var(--kos-font-body);
  font-weight: 600;
  color: var(--kos-text);
  background: var(--kos-surface);
}
.accordion-button:not(.collapsed) {
  color: var(--kos-cta);
  background: rgb(var(--kos-cta-rgb) / 8%);
  box-shadow: none;
}
.accordion-button:focus { box-shadow: var(--kos-ring); }
.offcanvas {
  background: var(--kos-surface);
  color: var(--kos-text);
}
.offcanvas-header { border-bottom: 1px solid var(--kos-border); }

/* ── Typography ─────────────────────────────────────────────────────────────
   Bare headings compiled to Rubik/Times before the rebrand; $headings-font-family
   now fixes that at build time. This pins the display face for anything that
   reads the token layer instead. */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
  font-family: var(--kos-font-head);
}
code, kbd, pre, samp, .font-monospace { font-family: var(--kos-font-mono); }

/* Tabular figures wherever numbers are compared down a column — counts drifting
   left and right as digits change makes a table markedly harder to scan. */
.table td, .table th,
.kos-stat-value, .kos-alert-count { font-variant-numeric: tabular-nums; }

/* ── Icons ──────────────────────────────────────────────────────────────────
   `bx-sm` is used 296 times as an ad-hoc size modifier; pin it once so icon
   sizing is consistent rather than per-call-site. */
.bx { vertical-align: middle; line-height: 1; }
.bx-sm { font-size: 1.15rem; }
.bx-md { font-size: 1.5rem; }
