/* =====================================================================================
   ACE-FUELS BATTERY ACADEMY NAIJA — DESIGN SYSTEM  ·  ban.css
   -------------------------------------------------------------------------------------
   Owner:   ACE-FUELS, Federal University of Technology Owerri (FUTO)
   Purpose: the single public stylesheet. Loaded after bootstrap.min.css, it redefines
            Bootstrap 5.3 through its CSS custom properties so that no Bootstrap default
            colour, radius, shadow or font ever reaches a rendered element.
   Method:  normal CSS only. No Sass, no post-processor, no build step.
   Structure:
      01 TOKENS           colour, type, space, radius, shadow, motion
      02 BOOTSTRAP OVERRIDE  --bs-* variable mapping (the theming seam)
      03 BASE             reset, elements, links, focus, selection, scrollbar
      04 LAYOUT           containers, sections, grids, rhythm, dividers
      05 COMPONENTS       header · navbar · hero · zone strip · cards · buttons · badges
                          alerts · forms · tables · breadcrumbs · pagination · filter bar
                          verification · kobo embed · audio · empty/placeholder states
                          · footer · skip link · timeline · metadata rows
      06 UTILITIES        a small, deliberately limited helper set
      07 RESPONSIVE       mobile-first refinements per breakpoint
      08 PREFERENCES      dark mode, reduced motion, print, forced colours
   Accessibility: every colour pair used for text is verified at WCAG 2.1 AA or better —
            see docs/08-design-phase.md §F for the measured contrast table.
   ===================================================================================== */


/* =====================================================================================
   01 · TOKENS
   ===================================================================================== */

:root {
  /* ---- Approved brand palette (fixed — do not add new hues) --------------------- */
  --ban-ink:          #13261F;   /* primary text, dark surfaces, footer               */
  --ban-green:        #0E6B47;   /* primary action, links, active states, verified    */
  --ban-amber:        #E59A1F;   /* accent, focus ring, attention, "next wave"        */
  --ban-bg:           #F3F5F4;   /* page background                                   */

  /* ---- Derived neutrals (green-tinged, so they always sit with the palette) ---- */
  --ban-white:        #FFFFFF;
  --ban-surface:      #FFFFFF;   /* card and panel surfaces                           */
  --ban-surface-alt:  #FAFBFA;   /* zebra rows, inset panels                          */
  --ban-border:       #D9E1DD;   /* hairlines, card borders, table rules              */
  --ban-border-strong:#788A82;   /* input borders, emphasised dividers — 3.7:1 on white */
  --ban-ink-700:      #3A4943;   /* secondary text — 9.0:1 on background             */
  --ban-ink-500:      #55655E;   /* muted text, captions — 6.1:1 on background       */
  --ban-ink-300:      #7E8E86;   /* disabled text, decorative rules — 3.4:1 on white  */

  /* ---- Fixed tokens: these NEVER flip between themes. Anything that must stay
     dark (footer, dark sections, header strip) or must stay dark-on-light (button
     labels sitting on amber/green) uses these, so dark mode cannot invert them. ---- */
  --ban-deep:         #13261F;   /* dark panel + footer surface                       */
  --ban-deep-alt:     #0E1F19;   /* header utility strip (deeper)                     */
  --ban-on-deep:      #D5DEDA;   /* body text on --ban-deep            (11.5:1)       */
  --ban-on-deep-muted:#A9BAB3;   /* muted text on --ban-deep            (7.8:1)       */
  --ban-on-deep-soft: #9FB2AB;   /* strapline text on --ban-deep        (7.1:1)       */
  --ban-on-deep-accent:#E59A1F;  /* links on --ban-deep                 (6.8:1)       */
  --ban-ink-fixed:    #13261F;   /* label colour on amber accents, both themes        */
  --ban-focus:        #8A5A05;   /* focus ring on light surfaces — 5.9:1 (amber family) */
  --ban-on-green:     #FFFFFF;   /* primary button label — light theme (6.5:1)        */
  --ban-on-amber:     #13261F;   /* accent button label — both themes   (6.8:1)       */

  /* ---- Green ramp ------------------------------------------------------------- */
  --ban-green-900:    #08402A;   /* hover/active for solid green buttons              */
  --ban-green-700:    #0B5A3B;   /* pressed state                                     */
  --ban-green-100:    #D8E9E0;   /* tinted panel                                      */
  --ban-green-050:    #EAF3EF;   /* faint section background                          */

  /* ---- Amber ramp ------------------------------------------------------------- */
  --ban-amber-800:    #8A5A05;   /* amber used as TEXT on light (5.6:1)              */
  --ban-amber-100:    #FBEBCF;   /* amber tinted panel                                */
  --ban-amber-050:    #FDF6E9;   /* faint amber section background                    */

  /* ---- Status colours (all derived from green/amber/ink — no new hues) -------- */
  --ban-success-bg:   #E4F0EA;  --ban-success-fg: #0B5A3B;  --ban-success-br: #B9D8C8;
  --ban-warning-bg:   #FDF3E2;  --ban-warning-fg: #8A5A05;  --ban-warning-br: #F0D8A8;
  --ban-info-bg:      #EAF3EF;  --ban-info-fg:    #13261F;  --ban-info-br:    #CBDDD4;
  --ban-danger-bg:    #F3E7E4;  --ban-danger-fg:  #7A2E1B;  --ban-danger-br:  #DFC2B8;
  --ban-neutral-bg:   #EDF1EF;  --ban-neutral-fg: #3A4943;  --ban-neutral-br: #D3DCD8;

  /* ---- Typography ------------------------------------------------------------- */
  --ban-font-head: "Archivo", "Segoe UI", system-ui, -apple-system, Roboto, Arial, sans-serif;
  --ban-font-body: "Source Sans 3", "Segoe UI", system-ui, -apple-system, Roboto, Arial, sans-serif;
  --ban-font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --ban-fs-h1:   clamp(2.25rem, 1.35rem + 3.6vw, 3.5rem);
  --ban-fs-h2:   clamp(1.625rem, 1.2rem + 1.7vw, 2.25rem);
  --ban-fs-h3:   clamp(1.25rem, 1.1rem + .6vw, 1.5rem);
  --ban-fs-h4:   1.0625rem;
  --ban-fs-lead: clamp(1.0625rem, 1rem + .45vw, 1.25rem);
  --ban-fs-body: 1.0625rem;
  --ban-fs-sm:   .9375rem;
  --ban-fs-xs:   .8125rem;

  --ban-lh-tight: 1.15;
  --ban-lh-head:  1.25;
  --ban-lh-body:  1.62;
  --ban-measure:  68ch;

  /* ---- Spacing (4px base, geometric) ----------------------------------------- */
  --ban-1: .25rem;  --ban-2: .5rem;   --ban-3: .75rem;  --ban-4: 1rem;
  --ban-5: 1.5rem;  --ban-6: 2rem;    --ban-7: 2.5rem;  --ban-8: 3rem;
  --ban-9: 4rem;    --ban-10: 5rem;   --ban-11: 6.5rem;

  /* ---- Radius ----------------------------------------------------------------- */
  --ban-radius-sm: 6px;
  --ban-radius-md: 10px;
  --ban-radius-lg: 16px;
  --ban-radius-pill: 999px;

  /* ---- Elevation (used sparingly; the identity is flat) ---------------------- */
  --ban-shadow-sm: 0 1px 2px rgba(19, 38, 31, .06), 0 2px 8px rgba(19, 38, 31, .05);
  --ban-shadow-md: 0 8px 24px rgba(19, 38, 31, .10);
  --ban-shadow-lg: 0 18px 48px rgba(19, 38, 31, .14);

  /* ---- Layout ----------------------------------------------------------------- */
  --ban-container: 75rem;        /* 1200px — grid and wide sections                 */
  --ban-container-narrow: 47rem; /*  752px — reading column (articles, docs)        */
  --ban-header-h: 4.5rem;
  --ban-control-h: 3rem;         /* 48px minimum touch target for controls          */
  --ban-header-h-sm: 3.75rem;

  /* ---- Motion ----------------------------------------------------------------- */
  --ban-t-fast: 120ms;
  --ban-t-med: 200ms;
  --ban-t-slow: 320ms;
  --ban-ease: cubic-bezier(.22, .61, .36, 1);
}


/* =====================================================================================
   02 · BOOTSTRAP 5.3 OVERRIDE
   Map every Bootstrap theme variable onto a brand token. This is what stops Bootstrap's
   defaults (#0d6efd blue, 0.375rem radius, system font stack, blue focus ring) from
   ever being painted. Nothing here needs !important.
   ===================================================================================== */

:root, [data-bs-theme="light"] {
  /* palette */
  --bs-blue: var(--ban-green);  --bs-primary: var(--ban-green);
  --bs-primary-rgb: 14, 107, 71;
  --bs-secondary: var(--ban-ink-700);
  --bs-secondary-rgb: 58, 73, 67;
  --bs-success: var(--ban-green);  --bs-success-rgb: 14, 107, 71;
  --bs-warning: var(--ban-amber);  --bs-warning-rgb: 229, 154, 31;
  --bs-danger: #7A2E1B;            --bs-danger-rgb: 122, 46, 27;
  --bs-info: var(--ban-green);     --bs-info-rgb: 14, 107, 71;
  --bs-light: var(--ban-bg);       --bs-dark: var(--ban-ink);
  --bs-body-color: var(--ban-ink);
  --bs-body-color-rgb: 19, 38, 31;
  --bs-body-bg: var(--ban-bg);
  --bs-emphasis-color: var(--ban-ink);
  --bs-secondary-color: var(--ban-ink-700);
  --bs-tertiary-color: var(--ban-ink-500);
  --bs-border-color: var(--ban-border);
  --bs-border-color-translucent: rgba(19, 38, 31, .12);
  --bs-heading-color: var(--ban-ink);
  --bs-link-color: var(--ban-green);
  --bs-link-color-rgb: 14, 107, 71;
  --bs-link-hover-color: var(--ban-green-900);
  --bs-link-decoration: underline;
  --bs-highlight-bg: var(--ban-amber-100);

  /* typography */
  --bs-font-sans-serif: var(--ban-font-body);
  --bs-body-font-family: var(--ban-font-body);
  --bs-body-font-size: var(--ban-fs-body);
  --bs-body-font-weight: 400;
  --bs-body-line-height: var(--ban-lh-body);
  --bs-headings-font-weight: 700;
  --bs-h1-font-size: var(--ban-fs-h1); --bs-h2-font-size: var(--ban-fs-h2);
  --bs-h3-font-size: var(--ban-fs-h3); --bs-h4-font-size: var(--ban-fs-h4);
  --bs-lead-font-size: var(--ban-fs-lead);

  /* geometry */
  --bs-border-width: 1px;
  --bs-border-radius: var(--ban-radius-md);
  --bs-border-radius-sm: var(--ban-radius-sm);
  --bs-border-radius-lg: var(--ban-radius-lg);
  --bs-border-radius-xl: var(--ban-radius-lg);
  --bs-border-radius-pill: var(--ban-radius-pill);
  --bs-border-radius-xxl: var(--ban-radius-lg);
  --bs-border-radius-2xl: var(--ban-radius-lg);

  /* elevation */
  --bs-box-shadow-sm: var(--ban-shadow-sm);
  --bs-box-shadow: var(--ban-shadow-md);
  --bs-box-shadow-lg: var(--ban-shadow-lg);

  /* focus ring — amber, carried over from the existing site */
  --bs-focus-ring-color: rgba(229, 154, 31, .55);
  --bs-focus-ring-width: 3px;
  --bs-focus-ring-offset: 2px;

  /* components */
  --bs-btn-border-radius: var(--ban-radius-pill);
  --bs-btn-padding-y: .75rem;   --bs-btn-padding-x: 1.35rem;
  --bs-btn-font-size: var(--ban-fs-body);  --bs-btn-font-weight: 600;
  --bs-btn-focus-box-shadow: 0 0 0 3px rgba(229, 154, 31, .55);
  --bs-card-border-color: var(--ban-border);
  --bs-card-border-radius: var(--ban-radius-lg);
  --bs-card-inner-border-radius: calc(var(--ban-radius-lg) - 1px);
  --bs-card-cap-bg: transparent;  --bs-card-bg: var(--ban-surface);
  --bs-card-spacer-y: var(--ban-5); --bs-card-spacer-x: var(--ban-5);
  --bs-dropdown-border-radius: var(--ban-radius-md);
  --bs-dropdown-border-color: var(--ban-border);
  --bs-dropdown-link-active-bg: var(--ban-green-050);
  --bs-dropdown-link-active-color: var(--ban-green-900);
  --bs-dropdown-link-hover-bg: var(--ban-bg);
  --bs-navbar-padding-y: .75rem;
  --bs-nav-link-color: var(--ban-ink);
  --bs-nav-link-hover-color: var(--ban-green);
  --bs-nav-link-font-weight: 600;
  --bs-accordion-btn-color: var(--ban-ink);
  --bs-accordion-active-color: var(--ban-green-900);
  --bs-accordion-active-bg: var(--ban-green-050);
  --bs-accordion-border-color: var(--ban-border);
  --bs-accordion-btn-focus-box-shadow: 0 0 0 3px rgba(229, 154, 31, .55);
  --bs-table-color: var(--ban-ink);
  --bs-table-border-color: var(--ban-border);
  --bs-table-striped-bg: var(--ban-surface-alt);
  --bs-pagination-color: var(--ban-green);
  --bs-pagination-active-bg: var(--ban-green);
  --bs-pagination-active-border-color: var(--ban-green);
  --bs-form-control-border-radius: var(--ban-radius-md);
  --bs-breadcrumb-divider-color: var(--ban-ink-300);
  --bs-breadcrumb-item-active-color: var(--ban-ink-700);
}


/* =====================================================================================
   03 · BASE
   ===================================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  background-color: var(--ban-bg);
  color: var(--ban-ink);
  font-family: var(--ban-font-body);
  font-size: var(--ban-fs-body);
  line-height: var(--ban-lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;              /* belt and braces against any table/grid overflow */
}

h1, h2, h3, h4, h5, h6, .ban-h {
  font-family: var(--ban-font-head);
  color: var(--ban-ink);
  letter-spacing: -.02em;
  text-wrap: balance;
}
h1 { font-size: var(--ban-fs-h1); font-weight: 800; line-height: var(--ban-lh-tight); letter-spacing: -.032em; }
h2 { font-size: var(--ban-fs-h2); font-weight: 800; line-height: var(--ban-lh-head); }
h3 { font-size: var(--ban-fs-h3); font-weight: 700; line-height: 1.3; }
h4 { font-size: var(--ban-fs-h4); font-weight: 700; }
h5, h6 { font-size: var(--ban-fs-sm); font-weight: 700; }

p { margin: 0 0 var(--ban-4); max-width: var(--ban-measure); }
p:last-child { margin-bottom: 0; }
.ban-lead { font-size: var(--ban-fs-lead); color: var(--ban-ink-700); line-height: 1.55; max-width: 46rem; }

a { color: var(--ban-green); text-decoration-thickness: 1px; text-underline-offset: .18em; }
a:hover { color: var(--ban-green-900); text-decoration-thickness: 2px; }

strong, b { font-weight: 700; }
small, .ban-small { font-size: var(--ban-fs-sm); color: var(--ban-ink-700); }
.ban-xs { font-size: var(--ban-fs-xs); color: var(--ban-ink-500); }

hr { border: 0; border-top: 1px solid var(--ban-border); margin: var(--ban-6) 0; opacity: 1; }

code, kbd, samp, .ban-code {
  font-family: var(--ban-font-mono);
  font-size: .875em;
  background: var(--ban-surface-alt);
  border: 1px solid var(--ban-border);
  border-radius: var(--ban-radius-sm);
  padding: .1em .4em;
  color: var(--ban-ink);
}

/* Focus: one rule for the whole site, visible on every background. */
:focus-visible {              /* see --ban-focus; amber family, verified in both themes */
  outline: 3px solid var(--ban-focus);
  outline-offset: 2px;
  border-radius: var(--ban-radius-sm);
}
/* On dark greens the amber ring is the original brand treatment; on light surfaces
   the ring darkens to --ban-focus so it always clears 3:1 (WCAG 1.4.11 / 2.4.11). */
.ban-section--ink :focus-visible,
.ban-footer :focus-visible,
.ban-header__top :focus-visible { outline-color: var(--ban-on-deep-accent); }
.btn:focus-visible, .form-control:focus-visible, .form-select:focus-visible {
  outline: 3px solid var(--ban-amber); outline-offset: 2px; box-shadow: none;
}
.skip-link:focus { outline-offset: 3px; }

::selection { background: var(--ban-amber-100); color: var(--ban-ink); }

/* Media never overflows its column and never shifts layout. */
img, svg, video, canvas { max-width: 100%; height: auto; display: block; }
img[width][height] { height: auto; }


/* =====================================================================================
   04 · LAYOUT
   ===================================================================================== */

.ban-container { width: 100%; max-width: var(--ban-container); margin-inline: auto; padding-inline: var(--ban-4); }
.ban-narrow    { width: 100%; max-width: var(--ban-container-narrow); margin-inline: auto; }

/* Vertical rhythm: sections own their padding, not the pages. */
.ban-section        { padding-block: var(--ban-8); }
.ban-section--tight { padding-block: var(--ban-6); }
.ban-section--loose { padding-block: var(--ban-10); }
.ban-section--paper { background: var(--ban-surface); }
.ban-section--tint  { background: var(--ban-green-050); }
.ban-section--amber { background: var(--ban-amber-050); }
.ban-section--ink   { background: var(--ban-deep); color: var(--ban-on-deep); }
.ban-section--ink h1, .ban-section--ink h2, .ban-section--ink h3 { color: var(--ban-white); }
.ban-section--ink p, .ban-section--ink li { color: var(--ban-on-deep); }
.ban-section--ink a { color: var(--ban-on-deep-accent); }

.ban-section + .ban-section { border-top: 1px solid var(--ban-border); }
.ban-section--paper + .ban-section--paper,
.ban-section--tint + .ban-section--tint,
.ban-section--ink + .ban-section--ink,
.ban-section--amber + .ban-section--amber { border-top: 0; }

/* Section heading block — used at the top of nearly every section. */
.ban-section-head { max-width: 46rem; margin-bottom: var(--ban-6); }
.ban-section-head--center { margin-inline: auto; text-align: center; }
.ban-eyebrow {
  display: inline-flex; align-items: center; gap: var(--ban-2);
  font-family: var(--ban-font-head); font-size: var(--ban-fs-xs); font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ban-green);
  margin-bottom: var(--ban-3);
}
.ban-eyebrow::before { content: ""; width: 1.5rem; height: 2px; background: var(--ban-amber); border-radius: 2px; }
.ban-section-head--center .ban-eyebrow::before { display: none; }
.ban-section-head h2 { margin-bottom: var(--ban-3); }
.ban-section-head p  { color: var(--ban-ink-700); margin-bottom: 0; }

/* Card grid — one class, three densities. Collapses without media-query gymnastics. */
.ban-grid { display: grid; gap: var(--ban-5); grid-template-columns: 1fr; }
.ban-grid--2 > * , .ban-grid--3 > *, .ban-grid--4 > * { min-width: 0; }

.ban-stack   { display: flex; flex-direction: column; gap: var(--ban-4); }
.ban-row     { display: flex; flex-wrap: wrap; gap: var(--ban-3); align-items: center; }
.ban-row--between { justify-content: space-between; }
.ban-actions { display: flex; flex-wrap: wrap; gap: var(--ban-3); align-items: center; }


/* =====================================================================================
   05 · COMPONENTS
   ===================================================================================== */

/* --- 5.1 Skip link ---------------------------------------------------------------- */
.skip-link, .ban-skip-link {
  position: absolute; left: var(--ban-4); top: -100px; z-index: 2000;
  background: var(--ban-ink); color: var(--ban-white);
  padding: var(--ban-3) var(--ban-5); border-radius: var(--ban-radius-md);
  font-weight: 700; text-decoration: none; transition: top var(--ban-t-med) var(--ban-ease);
}
.skip-link:focus, .ban-skip-link:focus { top: var(--ban-4); color: var(--ban-white); }

/* --- 5.2 Header ------------------------------------------------------------------- */
.ban-header {
  background: var(--ban-surface);
  border-bottom: 1px solid var(--ban-border);
  position: relative; z-index: 1030;
}
.ban-header__top {                    /* utility strip: language bar + verify shortcut */
  background: var(--ban-deep-alt); color: var(--ban-on-deep);
  font-size: var(--ban-fs-xs);
}
.ban-header__top .ban-container {
  display: flex; flex-wrap: wrap; gap: var(--ban-3) var(--ban-5);
  align-items: center; justify-content: space-between; min-height: 2.25rem;
}
.ban-header__top a { color: var(--ban-bg); text-decoration: none; }
.ban-header__top a:hover { color: var(--ban-amber); text-decoration: underline; }

.ban-brand { display: inline-flex; align-items: center; gap: var(--ban-3); text-decoration: none; color: inherit; }
.ban-brand__mark {
  width: 3rem; height: 3rem; flex: none; border-radius: 50%;
  background: var(--ban-white); border: 1px solid var(--ban-border);
  object-fit: contain;
}
.ban-brand__name {
  font-family: var(--ban-font-head); font-weight: 800; font-size: 1.125rem;
  line-height: 1.05; letter-spacing: -.01em; color: var(--ban-ink);
}
.ban-brand__name span { display: block; color: var(--ban-green); }
.ban-brand__sub {
  display: block; font-family: var(--ban-font-body); font-weight: 600;
  font-size: .6875rem; letter-spacing: .1em; text-transform: uppercase; color: var(--ban-ink-500);
}

/* --- 5.3 Navigation --------------------------------------------------------------- */
.ban-nav { display: none; align-items: center; gap: var(--ban-1); }
.ban-nav__link {
  display: inline-flex; align-items: center; min-height: var(--ban-control-h);
  padding: var(--ban-2) var(--ban-3); border-radius: var(--ban-radius-md);
  font-weight: 600; color: var(--ban-ink); text-decoration: none;
  transition: background var(--ban-t-fast) var(--ban-ease), color var(--ban-t-fast) var(--ban-ease);
}
.ban-nav__link:hover { background: var(--ban-green-050); color: var(--ban-green-900); }
.ban-nav__link.is-active { color: var(--ban-green); background: var(--ban-green-050); }
.ban-nav__link.is-active::after {
  content: ""; display: block; height: 2px; width: 1.25rem; background: var(--ban-amber);
  border-radius: 2px; margin-inline: auto; margin-top: -2px;
}
.ban-nav__toggle {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--ban-2);
  min-height: var(--ban-control-h); min-width: var(--ban-control-h);
  border: 1px solid var(--ban-border-strong); border-radius: var(--ban-radius-md);
  background: var(--ban-surface); color: var(--ban-ink); font-weight: 600;
}
.ban-nav__toggle:hover { background: var(--ban-bg); }

/* Off-canvas mobile menu (Bootstrap offcanvas, restyled) */
.ban-offcanvas { background: var(--ban-surface); width: min(22rem, 88vw) !important; }
.ban-offcanvas .offcanvas-header { border-bottom: 1px solid var(--ban-border); }
.ban-offcanvas .ban-nav { flex-direction: column; align-items: stretch; gap: 0; }
.ban-offcanvas .ban-nav__link {
  justify-content: space-between; padding-inline: var(--ban-3);
  border-bottom: 1px solid var(--ban-border); border-radius: 0;
}
.ban-offcanvas .ban-nav__link.is-active::after { display: none; }
.ban-offcanvas .ban-nav__link.is-active { box-shadow: inset 3px 0 0 var(--ban-amber); }

/* Header — main bar: brand, nav, actions. Mobile-first: the nav collapses into the
   offcanvas below 992px, so the phone bar is just brand + CTA + burger. */
.ban-header__main { background: var(--ban-surface); }
.ban-header__row {
  display: flex; align-items: center; gap: var(--ban-3);
  padding-block: var(--ban-3); min-height: 4.5rem;
}
.ban-header__actions { display: flex; align-items: center; gap: var(--ban-3); margin-inline-start: auto; }
.ban-header__tools { display: flex; align-items: center; gap: var(--ban-2); }
.ban-header__verify {
  display: inline-flex; align-items: center; gap: .4rem; min-height: 2.25rem;
  padding: .25rem .5rem; border-radius: var(--ban-radius-pill); white-space: nowrap;
}
.ban-icon { flex: none; display: block; }
.ban-theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.25rem; height: 2.25rem; padding: 0; cursor: pointer;
  background: transparent; color: var(--ban-on-deep);
  border: 1px solid rgba(255, 255, 255, .3); border-radius: var(--ban-radius-pill);
}
.ban-theme-toggle:hover { background: rgba(255, 255, 255, .14); }
.ban-theme-toggle .ban-icon--sun { display: inline; }
.ban-theme-toggle .ban-icon--moon { display: none; }
/* The toggle lives on the dark utility strip in both themes, so show the icon for
   the theme the *system* is not already using. Kept simple: sun = "go light". */
.ban-burger {
  display: inline-flex; flex-direction: column; justify-content: center; gap: .28rem;
  width: var(--ban-control-h); height: var(--ban-control-h); padding: 0 .7rem;
  background: var(--ban-surface); border: 1px solid var(--ban-border-strong);
  border-radius: var(--ban-radius-md); cursor: pointer;
}
.ban-burger__bar { display: block; height: 2px; background: var(--ban-ink); border-radius: 2px; }
.ban-burger:hover { background: var(--ban-bg); }
.ban-nav__list, .ban-offcanvas__list { list-style: none; margin: 0; padding: 0; }
.ban-nav__list { display: flex; align-items: center; gap: var(--ban-1); }
.ban-offcanvas__list { display: grid; gap: 0; margin-bottom: var(--ban-5); }
.ban-offcanvas__note {
  margin-top: var(--ban-5); font-size: var(--ban-fs-sm); color: var(--ban-ink-700);
  border-top: 1px solid var(--ban-border); padding-top: var(--ban-4);
}
.ban-lang__list { display: flex; flex-wrap: wrap; gap: var(--ban-2) var(--ban-3); list-style: none; margin: 0; padding: 0; }
.ban-lang__list a.is-active { font-weight: 700; text-decoration: underline; }

/* --- 5.4 Hero --------------------------------------------------------------------- */
.ban-hero { position: relative; background: var(--ban-surface); border-bottom: 1px solid var(--ban-border); }
.ban-hero__inner { display: grid; gap: var(--ban-7); padding-block: var(--ban-8) var(--ban-9); align-items: center; }
.ban-hero__badge {
  display: inline-flex; align-items: center; gap: var(--ban-2);
  background: var(--ban-green-050); color: var(--ban-green-900);
  border: 1px solid #C7DED2; border-radius: var(--ban-radius-pill);
  padding: .35rem .9rem; font-size: var(--ban-fs-xs); font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
}
.ban-hero__badge .dot {
  width: .5rem; height: .5rem; border-radius: 50%; background: var(--ban-green);
  box-shadow: 0 0 0 3px rgba(14, 107, 71, .15);
}
.ban-hero h1 { margin: var(--ban-4) 0 var(--ban-4); }
.ban-hero h1 .accent { color: var(--ban-green); display: block; }
.ban-hero__lede { font-size: var(--ban-fs-lead); color: var(--ban-ink-700); max-width: 40rem; }
.ban-hero__audience {
  display: flex; flex-wrap: wrap; gap: var(--ban-2) var(--ban-4);
  margin-top: var(--ban-5); padding-top: var(--ban-5); border-top: 1px solid var(--ban-border);
  font-size: var(--ban-fs-sm); color: var(--ban-ink-700);
}
.ban-hero__audience span::before { content: "·"; color: var(--ban-amber); font-weight: 700; margin-right: .45rem; }
.ban-hero__audience span:first-child::before { display: none; }

/* Hero figure: the battery motif, redrawn as a reusable graphic */
.ban-hero__figure {
  display: flex; align-items: center; justify-content: center;
  min-height: 14rem; padding: var(--ban-6);
  background: linear-gradient(160deg, var(--ban-green-050), var(--ban-bg) 70%);
  border: 1px solid var(--ban-border); border-radius: var(--ban-radius-lg);
}

/* --- 5.5 Zone strip (signature component — the six-cell battery) ------------------ */
.ban-zone-strip { width: 100%; max-width: 30rem; }
.ban-zone-strip__battery { display: flex; align-items: center; gap: 4px; }
.ban-zone-strip__body {
  flex: 1; display: grid; grid-template-columns: repeat(6, 1fr); gap: 4px;
  padding: 5px; border: 3px solid var(--ban-green); border-radius: var(--ban-radius-md);
  background: var(--ban-surface);
}
.ban-zone-strip__tip { width: 8px; height: 30px; border-radius: 0 5px 5px 0; background: var(--ban-green); flex: none; }
.ban-zone-strip__cell { height: 3.25rem; border-radius: 4px; background: #CFDAD5; }
.ban-zone-strip__cell.is-charged { background: var(--ban-amber); }
.ban-zone-strip__labels {
  display: grid; grid-template-columns: repeat(6, 1fr); gap: 4px;
  margin: 1.5rem 8px 0 5px; padding: 0; list-style: none;
  font-size: .6875rem; line-height: 1.15; text-align: center; color: var(--ban-ink-500);
}
.ban-zone-strip__labels li { font-weight: 600; }
.ban-zone-strip__labels li.is-charged { color: var(--ban-ink); }
.ban-zone-strip__caption { margin-top: var(--ban-4); font-size: var(--ban-fs-sm); color: var(--ban-ink-700); }

/* Zone strip: code label under each zone name in the labels row */
.ban-zone-strip__code {
  display: block; font-family: var(--ban-font-head); font-weight: 800;
  font-size: .75rem; letter-spacing: .06em; color: var(--ban-green);
}
.ban-zone-strip__labels li:not(.is-charged) .ban-zone-strip__code { color: var(--ban-ink-300); }
.ban-zone-strip__labels .ban-badge { margin-top: .4rem; text-transform: none; letter-spacing: 0; }
.ban-zone-strip__state {
  display: block; margin-top: .1rem; font-size: .625rem; font-weight: 600;
  letter-spacing: .02em; text-transform: uppercase; color: var(--ban-ink-500);
}
.ban-zone-strip__labels li.is-charged .ban-zone-strip__state { color: var(--ban-success-fg); }

/* --- 5.6 Cards -------------------------------------------------------------------- */
.ban-card {
  display: flex; flex-direction: column; height: 100%;
  background: var(--ban-surface); border: 1px solid var(--ban-border);
  border-radius: var(--ban-radius-lg); overflow: hidden;
  transition: border-color var(--ban-t-med) var(--ban-ease), transform var(--ban-t-med) var(--ban-ease);
}
.ban-card:hover { border-color: var(--ban-green); }
.ban-card:focus-within { border-color: var(--ban-green); }
.ban-card__media { aspect-ratio: 16 / 9; background: var(--ban-green-050); border-bottom: 1px solid var(--ban-border); }
.ban-card__media img { width: 100%; height: 100%; object-fit: cover; }
.ban-card__body { padding: var(--ban-5); display: flex; flex-direction: column; gap: var(--ban-3); flex: 1; }
.ban-card__title { margin: 0; font-size: 1.125rem; font-weight: 700; line-height: 1.3; }
.ban-card__title a { color: inherit; text-decoration: none; }
.ban-card__title a:hover { color: var(--ban-green); text-decoration: underline; }
.ban-card__text { margin: 0; font-size: var(--ban-fs-sm); color: var(--ban-ink-700); flex: 1; }
.ban-card__meta {
  display: flex; flex-wrap: wrap; gap: var(--ban-2) var(--ban-4);
  font-size: var(--ban-fs-xs); color: var(--ban-ink-500);
}
.ban-card__footer {
  padding: var(--ban-4) var(--ban-5); border-top: 1px solid var(--ban-border);
  background: var(--ban-surface-alt);
  display: flex; flex-wrap: wrap; gap: var(--ban-3); align-items: center; justify-content: space-between;
}
.ban-card__code {
  font-family: var(--ban-font-head); font-weight: 800; font-size: var(--ban-fs-xs);
  letter-spacing: .06em; color: var(--ban-green);
}
.ban-card--quiet { background: var(--ban-surface-alt); }
.ban-card--feature { border-top: 3px solid var(--ban-amber); }
.ban-card--link { text-decoration: none; color: inherit; }

/* --- 5.7 Buttons ------------------------------------------------------------------ */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: .55rem; }
.btn svg { flex: none; }
.btn-ban {
  border-radius: var(--ban-radius-pill); min-height: var(--ban-control-h);
  padding: .7rem 1.35rem; font-weight: 600; border: 2px solid transparent;
  transition: background var(--ban-t-fast) var(--ban-ease), color var(--ban-t-fast) var(--ban-ease),
              border-color var(--ban-t-fast) var(--ban-ease);
}
.btn-ban-primary { background: var(--ban-green); color: var(--ban-on-green); }
.btn-ban-primary:hover, .btn-ban-primary:focus { background: var(--ban-green-900); color: var(--ban-on-green); }
.btn-ban-primary:active { background: var(--ban-green-700); }
.btn-ban-secondary { background: transparent; color: var(--ban-ink); border-color: var(--ban-green); }
.btn-ban-secondary:hover, .btn-ban-secondary:focus { background: var(--ban-green-050); color: var(--ban-green-900); border-color: var(--ban-green-900); }
.btn-ban-accent { background: var(--ban-amber); color: var(--ban-on-amber); }
.btn-ban-accent:hover, .btn-ban-accent:focus { background: #D08A12; color: var(--ban-on-amber); }
.btn-ban-neutral { background: var(--ban-surface); color: var(--ban-ink); border-color: var(--ban-border-strong); }
.btn-ban-neutral:hover, .btn-ban-neutral:focus { background: var(--ban-bg); border-color: var(--ban-ink-300); }
.btn-ban-ghost { background: transparent; color: var(--ban-white); border-color: rgba(255, 255, 255, .4); }
.btn-ban-ghost:hover, .btn-ban-ghost:focus { background: rgba(255, 255, 255, .12); color: var(--ban-white); border-color: var(--ban-white); }
.btn-ban-lg { min-height: 3.5rem; padding: .95rem 1.7rem; font-size: 1.125rem; }
.btn-ban-sm { min-height: 2.5rem; padding: .45rem .95rem; font-size: var(--ban-fs-sm); }
.btn[disabled], .btn.disabled, .btn-ban[aria-disabled="true"] {
  background: var(--ban-neutral-bg); color: var(--ban-ink-300);
  border-color: var(--ban-border); cursor: not-allowed; opacity: 1;
}

/* --- 5.8 Badges / status ---------------------------------------------------------- */
.ban-badge {
  display: inline-flex; align-items: center; gap: .35rem;
  font-family: var(--ban-font-body); font-size: var(--ban-fs-xs); font-weight: 700;
  padding: .25rem .6rem; border-radius: var(--ban-radius-pill);
  border: 1px solid var(--ban-neutral-br); background: var(--ban-neutral-bg); color: var(--ban-neutral-fg);
  white-space: nowrap;
}
.ban-badge--success { background: var(--ban-success-bg); color: var(--ban-success-fg); border-color: var(--ban-success-br); }
.ban-badge--warning { background: var(--ban-warning-bg); color: var(--ban-warning-fg); border-color: var(--ban-warning-br); }
.ban-badge--info    { background: var(--ban-info-bg);    color: var(--ban-info-fg);    border-color: var(--ban-info-br); }
.ban-badge--danger  { background: var(--ban-danger-bg);  color: var(--ban-danger-fg);  border-color: var(--ban-danger-br); }
.ban-badge--outline { background: transparent; color: var(--ban-ink-700); border-color: var(--ban-border-strong); }
.ban-badge--dot::before { content: ""; width: .45rem; height: .45rem; border-radius: 50%; background: currentColor; }

/* --- 5.9 Alerts / callouts -------------------------------------------------------- */
.ban-alert {
  display: flex; gap: var(--ban-3); padding: var(--ban-4) var(--ban-5);
  border: 1px solid var(--ban-info-br); border-left: 4px solid var(--ban-green);
  background: var(--ban-info-bg); border-radius: var(--ban-radius-md); color: var(--ban-ink);
}
.ban-alert__icon { flex: none; margin-top: .15rem; }
.ban-alert__body { min-width: 0; }
.ban-alert__title { font-family: var(--ban-font-head); font-weight: 700; margin: 0 0 var(--ban-1); }
.ban-alert p { margin: 0; font-size: var(--ban-fs-sm); }
.ban-alert--warning { border-color: var(--ban-warning-br); border-left-color: var(--ban-amber); background: var(--ban-warning-bg); }
.ban-alert--warning .ban-alert__title { color: var(--ban-warning-fg); }
.ban-alert--danger  { border-color: var(--ban-danger-br);  border-left-color: #7A2E1B; background: var(--ban-danger-bg); }
.ban-alert--danger .ban-alert__title { color: var(--ban-danger-fg); }
.ban-alert--success { border-color: var(--ban-success-br); border-left-color: var(--ban-green); background: var(--ban-success-bg); }
.ban-alert--success .ban-alert__title { color: var(--ban-success-fg); }
.ban-alert--neutral { border-color: var(--ban-neutral-br); border-left-color: var(--ban-ink-300); background: var(--ban-neutral-bg); }

/* --- 5.10 Forms ------------------------------------------------------------------- */
.ban-field { margin-bottom: var(--ban-4); }
.ban-label {
  display: block; font-weight: 700; font-size: var(--ban-fs-sm);
  margin-bottom: var(--ban-2); color: var(--ban-ink);
}
.ban-label .req { color: var(--ban-amber-800); margin-left: .15rem; }
.ban-hint { font-size: var(--ban-fs-xs); color: var(--ban-ink-500); margin: var(--ban-2) 0 0; }
.ban-input, .form-control, .form-select {
  width: 100%; min-height: var(--ban-control-h);
  padding: .6rem .85rem; font-size: var(--ban-fs-body); font-family: var(--ban-font-body);
  color: var(--ban-ink); background: var(--ban-white);
  border: 1px solid var(--ban-border-strong); border-radius: var(--ban-radius-md);
  transition: border-color var(--ban-t-fast) var(--ban-ease);
}
.ban-input:hover, .form-control:hover, .form-select:hover { border-color: var(--ban-ink-300); }
.ban-input:focus, .form-control:focus, .form-select:focus {
  border-color: var(--ban-green); box-shadow: 0 0 0 3px var(--bs-focus-ring-color); outline: none;
}
.ban-input--lg { min-height: 3.5rem; font-size: 1.125rem; }
.ban-input[aria-invalid="true"], .form-control.is-invalid {
  border-color: #7A2E1B; box-shadow: 0 0 0 3px rgba(122, 46, 27, .18);
}
.ban-error { display: flex; gap: .4rem; align-items: flex-start; color: var(--ban-danger-fg); font-size: var(--ban-fs-sm); font-weight: 600; margin-top: var(--ban-2); }
.ban-input-group { display: flex; gap: var(--ban-2); flex-wrap: wrap; }
.ban-input-group .ban-input { flex: 1 1 14rem; }
.ban-check { display: flex; gap: var(--ban-3); align-items: flex-start; font-size: var(--ban-fs-sm); }
.ban-check input { width: 1.25rem; height: 1.25rem; margin-top: .2rem; flex: none; accent-color: var(--ban-green); }
.ban-fieldset { border: 1px solid var(--ban-border); border-radius: var(--ban-radius-md); padding: var(--ban-4); margin-bottom: var(--ban-4); }
.ban-fieldset legend { font-family: var(--ban-font-head); font-weight: 700; font-size: var(--ban-fs-sm); width: auto; padding: 0 .4rem; }

/* --- 5.11 Metadata rows (course/module/zone detail) -------------------------------- */
.ban-meta { border-top: 1px solid var(--ban-border); margin: 0; }
.ban-meta__row {
  display: grid; grid-template-columns: 1fr; gap: var(--ban-1);
  padding: var(--ban-4) 0; border-bottom: 1px solid var(--ban-border);
}
.ban-meta__key {
  font-family: var(--ban-font-head); font-weight: 700; font-size: var(--ban-fs-xs);
  letter-spacing: .08em; text-transform: uppercase; color: var(--ban-ink-500);
}
.ban-meta__val { font-size: var(--ban-fs-sm); color: var(--ban-ink); }
.ban-meta__val ul { margin: 0; padding-left: 1.1rem; }

/* --- 5.12 Timeline (training days, process steps) --------------------------------- */
.ban-timeline { list-style: none; margin: 0; padding: 0; }
.ban-timeline > li { position: relative; padding: 0 0 var(--ban-5) 2.25rem; border-left: 2px solid var(--ban-border); }
.ban-timeline > li:last-child { padding-bottom: 0; border-left-color: transparent; }
.ban-timeline > li::before {
  content: ""; position: absolute; left: -8px; top: .35rem;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--ban-surface); border: 3px solid var(--ban-green);
}
.ban-timeline > li.is-done::before { background: var(--ban-green); }
.ban-timeline__title { font-family: var(--ban-font-head); font-weight: 700; margin: 0 0 .25rem; font-size: 1rem; }
.ban-timeline__meta { font-size: var(--ban-fs-xs); color: var(--ban-ink-500); }

/* --- 5.13 Verification result ----------------------------------------------------- */
.ban-verify-result { border: 2px solid var(--ban-border-strong); border-radius: var(--ban-radius-lg); background: var(--ban-surface); overflow: hidden; }
.ban-verify-result__head {
  display: flex; flex-wrap: wrap; gap: var(--ban-3); align-items: center; justify-content: space-between;
  padding: var(--ban-5); border-bottom: 1px solid var(--ban-border);
}
.ban-verify-result__status {
  display: inline-flex; align-items: center; gap: var(--ban-2);
  font-family: var(--ban-font-head); font-weight: 800; letter-spacing: -.01em;
  font-size: 1.125rem; text-transform: uppercase;
}
.ban-verify-result__icon {
  width: 2.25rem; height: 2.25rem; border-radius: 50%; display: grid; place-items: center;
  background: var(--ban-neutral-bg); color: var(--ban-neutral-fg); flex: none;
}
.ban-verify-result__body { padding: var(--ban-5); }
.ban-verify-result--valid  { border-color: var(--ban-success-br); }
.ban-verify-result--valid .ban-verify-result__head { background: var(--ban-success-bg); border-color: var(--ban-success-br); }
.ban-verify-result--valid .ban-verify-result__status { color: var(--ban-success-fg); }
.ban-verify-result--valid .ban-verify-result__icon { background: var(--ban-green); color: var(--ban-white); }
.ban-verify-result--warning { border-color: var(--ban-warning-br); }
.ban-verify-result--warning .ban-verify-result__head { background: var(--ban-warning-bg); border-color: var(--ban-warning-br); }
.ban-verify-result--warning .ban-verify-result__status { color: var(--ban-warning-fg); }
.ban-verify-result--warning .ban-verify-result__icon { background: var(--ban-amber); color: var(--ban-ink); }
.ban-verify-result--danger { border-color: var(--ban-danger-br); }
.ban-verify-result--danger .ban-verify-result__head { background: var(--ban-danger-bg); border-color: var(--ban-danger-br); }
.ban-verify-result--danger .ban-verify-result__status { color: var(--ban-danger-fg); }
.ban-verify-result--danger .ban-verify-result__icon { background: var(--ban-danger-fg); color: var(--ban-white); }
.ban-verify-result--unknown .ban-verify-result__status { color: var(--ban-ink-700); }
.ban-verify-result--unknown .ban-verify-result__icon { background: var(--ban-neutral-bg); color: var(--ban-ink-700); }
.ban-verify__scope {
  margin-top: var(--ban-4); padding: var(--ban-4); background: var(--ban-surface-alt);
  border: 1px dashed var(--ban-border-strong); border-radius: var(--ban-radius-md);
  font-size: var(--ban-fs-sm); color: var(--ban-ink-700);
}
.ban-code-value {
  font-family: var(--ban-font-mono); font-weight: 700; letter-spacing: .04em;
  font-size: 1.0625rem; color: var(--ban-ink);
}

/* --- 5.14 Kobo embed (click-to-load) --------------------------------------------- */
.ban-embed { border: 1px solid var(--ban-border); border-radius: var(--ban-radius-lg); background: var(--ban-surface); overflow: hidden; }
.ban-embed__poster { padding: var(--ban-6); text-align: center; background: var(--ban-green-050); }
.ban-embed__poster h2, .ban-embed__poster h3 { margin-bottom: var(--ban-2); }
.ban-embed__poster p { margin-inline: auto; color: var(--ban-ink-700); font-size: var(--ban-fs-sm); max-width: 34rem; }
.ban-embed__frame { width: 100%; min-height: 42rem; border: 0; display: block; background: var(--ban-white); }
.ban-embed__note {
  display: flex; gap: var(--ban-2); align-items: flex-start;
  padding: var(--ban-3) var(--ban-5); border-top: 1px solid var(--ban-border);
  background: var(--ban-surface-alt); font-size: var(--ban-fs-xs); color: var(--ban-ink-700);
}

/* --- 5.15 Audio (jingles) --------------------------------------------------------- */
.ban-audio { display: flex; flex-wrap: wrap; gap: var(--ban-3) var(--ban-4); align-items: center;
  padding: var(--ban-4); border: 1px solid var(--ban-border); border-radius: var(--ban-radius-md); background: var(--ban-surface); }
.ban-audio audio { width: 100%; max-width: 26rem; }
.ban-audio__label { font-size: var(--ban-fs-sm); font-weight: 600; }
.ban-audio__note { font-size: var(--ban-fs-xs); color: var(--ban-ink-500); }

/* --- 5.16 Breadcrumbs, pagination, filter bar ------------------------------------- */
.ban-breadcrumb { font-size: var(--ban-fs-sm); }
.ban-breadcrumb ol { display: flex; flex-wrap: wrap; gap: var(--ban-2); list-style: none; margin: 0; padding: 0; }
.ban-breadcrumb li { display: flex; align-items: center; gap: var(--ban-2); color: var(--ban-ink-500); }
.ban-breadcrumb li + li::before { content: "/"; color: var(--ban-ink-300); }
.ban-breadcrumb a { color: var(--ban-ink-700); text-decoration: none; }
.ban-breadcrumb a:hover { color: var(--ban-green); text-decoration: underline; }
.ban-breadcrumb [aria-current="page"] { color: var(--ban-ink); font-weight: 600; }

.ban-pagination { display: flex; flex-wrap: wrap; gap: var(--ban-2); list-style: none; margin: 0; padding: 0; }
.ban-pagination a, .ban-pagination span {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 2.75rem; min-height: 2.75rem; padding: 0 .6rem;
  border: 1px solid var(--ban-border-strong); border-radius: var(--ban-radius-md);
  background: var(--ban-surface); color: var(--ban-ink); text-decoration: none; font-weight: 600;
}
.ban-pagination a:hover { border-color: var(--ban-green); color: var(--ban-green); }
.ban-pagination [aria-current="page"] { background: var(--ban-green); border-color: var(--ban-green); color: var(--ban-white); }
.ban-pagination .is-disabled { color: var(--ban-ink-300); background: var(--ban-surface-alt); }

.ban-filter { border: 1px solid var(--ban-border); border-radius: var(--ban-radius-lg); background: var(--ban-surface); padding: var(--ban-5); }
.ban-filter__grid { display: grid; gap: var(--ban-4); }
.ban-filter__count { font-size: var(--ban-fs-sm); color: var(--ban-ink-700); }
.ban-filter__chips { display: flex; flex-wrap: wrap; gap: var(--ban-2); }
.ban-chip {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .35rem .8rem; border-radius: var(--ban-radius-pill);
  border: 1px solid var(--ban-border-strong); background: var(--ban-surface);
  color: var(--ban-ink); font-size: var(--ban-fs-sm); font-weight: 600; text-decoration: none;
  min-height: 2.5rem;
}
.ban-chip:hover { border-color: var(--ban-green); color: var(--ban-green); }
.ban-chip.is-active { background: var(--ban-green); border-color: var(--ban-green); color: var(--ban-white); }

/* --- 5.17 Tables (restack on mobile) ---------------------------------------------- */
.ban-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.ban-table { width: 100%; border-collapse: collapse; font-size: var(--ban-fs-sm); }
.ban-table caption { caption-side: top; text-align: left; font-size: var(--ban-fs-xs); color: var(--ban-ink-500); padding-bottom: var(--ban-2); }
.ban-table th, .ban-table td { padding: var(--ban-3) var(--ban-4); border-bottom: 1px solid var(--ban-border); text-align: left; vertical-align: top; }
.ban-table thead th {
  font-family: var(--ban-font-head); font-size: var(--ban-fs-xs); font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ban-ink-700);
  background: var(--ban-surface-alt); border-bottom: 2px solid var(--ban-border-strong);
}
.ban-table tbody tr:hover { background: var(--ban-surface-alt); }
.ban-table--stack { min-width: 32rem; }   /* inside .ban-table-wrap, scrolls rather than squashing */

/* --- 5.17b Responsive data tables ------------------------------------------------ */
/* Below 768px a wide table restacks into labelled rows instead of forcing sideways
   scrolling. This is a max-width query on purpose: un-doing `display: table` and the
   screen-reader-only thead at a min-width breakpoint is more fragile than scoping the
   stacked form to narrow screens. The td::before labels come from data-label, which the
   page builder writes into the HTML (not JavaScript), so the table still explains itself
   with scripting switched off. */
@media (max-width: 47.9375rem) {
  .ban-table--stack { min-width: 0; }
  .ban-table--stack thead {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
  .ban-table--stack tbody, .ban-table--stack tr, .ban-table--stack th, .ban-table--stack td {
    display: block; width: 100%;
  }
  .ban-table--stack tr {
    border: 1px solid var(--ban-border); border-radius: var(--ban-radius-md);
    background: var(--ban-surface); margin-bottom: var(--ban-4); padding: var(--ban-2) 0;
  }
  .ban-table--stack tbody th[scope="row"],
  .ban-table--stack tbody th {
    font-family: var(--ban-font-head); font-size: var(--ban-fs-body);
    background: var(--ban-surface-alt); margin-bottom: var(--ban-2);
  }
  .ban-table--stack td {
    display: grid; grid-template-columns: minmax(6.5rem, 38%) 1fr; gap: var(--ban-3);
    border-bottom: 1px solid var(--ban-border);
  }
  .ban-table--stack tr > *:last-child { border-bottom: 0; }
  .ban-table--stack td::before {
    content: attr(data-label);
    font-family: var(--ban-font-head); font-weight: 700; font-size: var(--ban-fs-xs);
    letter-spacing: .06em; text-transform: uppercase; color: var(--ban-ink-500);
  }
  .ban-table--stack caption { caption-side: top; }
}

/* --- 5.18 Empty state, loading, restricted ---------------------------------------- */
.ban-empty {
  text-align: center; padding: var(--ban-8) var(--ban-5);
  border: 1px dashed var(--ban-border-strong); border-radius: var(--ban-radius-lg); background: var(--ban-surface);
}
.ban-empty__icon { width: 3rem; height: 3rem; margin: 0 auto var(--ban-4); color: var(--ban-ink-300); }
.ban-empty h3 { margin-bottom: var(--ban-2); }
.ban-empty p { margin-inline: auto; color: var(--ban-ink-700); font-size: var(--ban-fs-sm); max-width: 32rem; }
.ban-skeleton { background: linear-gradient(90deg, var(--ban-border) 25%, var(--ban-surface-alt) 37%, var(--ban-border) 63%);
  background-size: 400% 100%; animation: ban-shimmer 1.4s ease infinite; border-radius: var(--ban-radius-sm); height: 1rem; }
@keyframes ban-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
.ban-restricted {
  display: flex; gap: var(--ban-3); align-items: center;
  padding: var(--ban-4); border: 1px dashed var(--ban-border-strong);
  border-radius: var(--ban-radius-md); background: var(--ban-surface-alt);
  font-size: var(--ban-fs-sm); color: var(--ban-ink-700);
}

/* --- 5.19 Content-required marker (design-phase placeholder, must be removable) --- */
.ban-todo {
  display: block; border: 2px dashed var(--ban-amber); border-radius: var(--ban-radius-md);
  background: var(--ban-amber-050); padding: var(--ban-4) var(--ban-4) var(--ban-4) var(--ban-5);
  font-size: var(--ban-fs-sm); color: var(--ban-ink);
}
.ban-todo__tag {
  display: inline-flex; align-items: center; gap: .35rem;
  font-family: var(--ban-font-head); font-size: .6875rem; font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase; color: var(--ban-amber-800); margin-bottom: var(--ban-2);
}
.ban-todo__id { font-family: var(--ban-font-mono); font-size: .75rem; color: var(--ban-ink-500); }
.ban-todo p { margin: 0; color: var(--ban-ink-700); }

/* --- 5.19a Trust band (homepage) --------------------------------------------------- */
.ban-trust {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--ban-5); grid-template-columns: 1fr;
}
.ban-trust li { border-left: 3px solid var(--ban-amber); padding-left: var(--ban-4); }
.ban-trust strong {
  display: block; font-family: var(--ban-font-head); font-size: 1rem;
  color: var(--ban-ink); margin-bottom: var(--ban-1);
}
.ban-trust span { display: block; font-size: var(--ban-fs-sm); color: var(--ban-ink-700); }

/* --- 5.19b Restricted panel ------------------------------------------------------- */
.ban-restricted__icon { margin: 0 0 var(--ban-3); color: var(--ban-ink-500); }
.ban-restricted__list {
  list-style: none; margin: var(--ban-4) 0 0; padding: 0;
  display: grid; gap: var(--ban-2); font-size: var(--ban-fs-sm);
}

/* --- 5.19c Event/date display ----------------------------------------------------- */
.ban-event-date {
  margin: 0; font-family: var(--ban-font-head); font-weight: 800;
  font-size: 1.0625rem; color: var(--ban-ink); line-height: 1.25;
}

/* --- 5.19d Badge neutral (explicit, matches the badge base) ----------------------- */
.ban-badge--neutral { background: var(--ban-neutral-bg); color: var(--ban-neutral-fg); border-color: var(--ban-neutral-br); }

/* --- 5.22 Search results ---------------------------------------------------------- */
.ban-results { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--ban-4); }
.ban-result {
  padding: var(--ban-4) 0 var(--ban-4) var(--ban-5);
  border-left: 3px solid var(--ban-border); border-bottom: 1px solid var(--ban-border);
}
.ban-result:hover { border-left-color: var(--ban-green); }
.ban-result__kind {
  margin: 0 0 var(--ban-1); font-family: var(--ban-font-head); font-weight: 800;
  font-size: var(--ban-fs-xs); letter-spacing: .08em; text-transform: uppercase;
  color: var(--ban-ink-500);
}
.ban-result__title { margin: 0 0 var(--ban-1); font-size: 1.0625rem; }
.ban-result__title a { color: var(--ban-green); text-decoration: none; }
.ban-result__title a:hover { text-decoration: underline; }
.ban-result__text { margin: 0; font-size: var(--ban-fs-sm); color: var(--ban-ink-700); }

/* --- 5.23 Style-guide helpers (used by /design-system only) ------------------------ */
.ban-swatches {
  list-style: none; margin: var(--ban-5) 0 0; padding: 0;
  display: grid; gap: var(--ban-4); grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
}
.ban-swatch { display: flex; gap: var(--ban-3); align-items: flex-start; }
.ban-swatch__chip {
  width: 3rem; height: 3rem; flex: none; border-radius: var(--ban-radius-md);
  border: 1px solid var(--ban-border);
}
.ban-swatch__meta { display: grid; gap: 2px; min-width: 0; }
.ban-swatch__meta code { font-size: var(--ban-fs-xs); word-break: break-all; }
.ban-swatch__hex { font-family: var(--ban-font-mono); font-size: var(--ban-fs-xs); font-weight: 700; }
.ban-swatch__ratio { font-size: .6875rem; color: var(--ban-ink-500); }
.ban-demo-row { display: flex; flex-wrap: wrap; gap: var(--ban-3); align-items: center; margin-top: var(--ban-5); }
.ban-type-scale { margin-top: var(--ban-5); }
.ban-type-scale > * { margin-bottom: var(--ban-2); }
.ban-type-scale__label {
  display: inline-block; font-family: var(--ban-font-mono); font-size: .6875rem;
  color: var(--ban-ink-500); background: var(--ban-surface-alt);
  border: 1px solid var(--ban-border); border-radius: var(--ban-radius-sm);
  padding: 1px 6px; margin-top: var(--ban-5);
}
.ban-display-1 {
  font-family: var(--ban-font-head); font-weight: 800; letter-spacing: -.02em;
  font-size: clamp(1.75rem, 4vw, 2.75rem); line-height: 1.12; color: var(--ban-ink);
}
.ban-btn-disabled {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--ban-control-h); padding: .7rem 1.35rem; border-radius: var(--ban-radius-pill);
  background: var(--ban-neutral-bg); color: var(--ban-ink-300);
  border: 2px solid var(--ban-border); font-weight: 600;
}

/* --- 5.20 Footer ------------------------------------------------------------------ */
.ban-footer { background: var(--ban-deep); color: var(--ban-on-deep); margin-top: var(--ban-9); }
.ban-footer a { color: var(--ban-on-deep); text-decoration: none; }
.ban-footer a:hover { color: var(--ban-on-deep-accent); text-decoration: underline; }
.ban-footer__main { display: grid; gap: var(--ban-6); padding-block: var(--ban-8); }
.ban-footer h2, .ban-footer h3 { color: var(--ban-white); font-size: var(--ban-fs-sm); text-transform: uppercase; letter-spacing: .1em; margin-bottom: var(--ban-4); }
.ban-footer__brand { display: flex; gap: var(--ban-3); align-items: center; margin-bottom: var(--ban-4); }
.ban-footer__brand img { width: 3rem; height: 3rem; border-radius: 50%; background: var(--ban-white); object-fit: contain; }
.ban-footer__brand strong { font-family: var(--ban-font-head); color: var(--ban-white); font-size: 1.125rem; display: block; line-height: 1.1; }
.ban-footer__brand span { font-size: .6875rem; letter-spacing: .1em; text-transform: uppercase; color: var(--ban-on-deep-soft); }
.ban-footer__nav { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--ban-3); font-size: var(--ban-fs-sm); }
.ban-footer__note { font-size: var(--ban-fs-sm); color: var(--ban-on-deep-muted); max-width: 34rem; }
.ban-footer__bottom {
  border-top: 1px solid rgba(255, 255, 255, .14); padding-block: var(--ban-5);
  display: flex; flex-wrap: wrap; gap: var(--ban-3) var(--ban-5); align-items: center; justify-content: space-between;
  font-size: var(--ban-fs-xs); color: var(--ban-on-deep-muted);
}
.ban-footer__bottom ul { display: flex; flex-wrap: wrap; gap: var(--ban-2) var(--ban-4); list-style: none; margin: 0; padding: 0; }
.ban-footer__logos { display: flex; flex-wrap: wrap; gap: var(--ban-4); align-items: center; margin-top: var(--ban-5); }
.ban-footer__logos img { height: 2.5rem; width: auto; opacity: .92; }

/* Footer — Bootstrap grid (row/col) inside .ban-container provides the columns. */
.ban-footer__logotype { display: inline-flex; flex-direction: column; }
.ban-footer__partner {
  display: inline-flex; align-items: center; justify-content: center;
  background: #FFFFFF; border-radius: var(--ban-radius-md);
  padding: var(--ban-3) var(--ban-4); margin-block: var(--ban-4);
}
.ban-footer__partner img { height: 2rem; width: auto; }
.ban-footer__note--small { font-size: var(--ban-fs-xs); }
.ban-footer__col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--ban-3); font-size: var(--ban-fs-sm); }
.ban-todo--compact { font-size: var(--ban-fs-xs); padding: var(--ban-3) var(--ban-4); }

/* --- 5.21 Language bar ------------------------------------------------------------ */
.ban-lang { display: flex; flex-wrap: wrap; gap: var(--ban-2) var(--ban-3); align-items: center; }
.ban-lang__label { color: var(--ban-on-deep-soft); font-weight: 600; }
.ban-lang .soon { color: #8FA39B; }
.ban-lang .soon::after { content: " · soon"; font-size: .6875rem; text-transform: uppercase; letter-spacing: .06em; }


/* =====================================================================================
   06 · UTILITIES  (a small, deliberately limited set — no Bootstrap duplication)
   ===================================================================================== */

.ban-visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.ban-mt-0 { margin-top: 0 !important; }      .ban-mt-3 { margin-top: var(--ban-3) !important; }
.ban-mt-4 { margin-top: var(--ban-4) !important; }  .ban-mt-5 { margin-top: var(--ban-5) !important; }
.ban-mt-6 { margin-top: var(--ban-6) !important; }  .ban-mt-7 { margin-top: var(--ban-7) !important; }
.ban-mb-0 { margin-bottom: 0 !important; }   .ban-mb-3 { margin-bottom: var(--ban-3) !important; }
.ban-mb-4 { margin-bottom: var(--ban-4) !important; } .ban-mb-5 { margin-bottom: var(--ban-5) !important; }
.ban-mb-6 { margin-bottom: var(--ban-6) !important; }
.ban-text-center { text-align: center !important; }
.ban-text-sm { font-size: var(--ban-fs-sm) !important; }
.ban-text-muted { color: var(--ban-ink-700) !important; }
.ban-text-green { color: var(--ban-green) !important; }
.ban-w-full { width: 100% !important; }
.ban-max-narrow { max-width: var(--ban-container-narrow) !important; }
.ban-hr-tight { margin-block: var(--ban-5) !important; }
.ban-no-underline, .ban-no-underline:hover { text-decoration: none !important; }
.ban-sticky { position: sticky; top: calc(var(--ban-header-h) + var(--ban-4)); }


/* =====================================================================================
   07 · RESPONSIVE  (mobile-first: the single-column layout above is the phone layout)
   ===================================================================================== */

@media (min-width: 36rem) {                       /* 576px — large phone            */
  .ban-container { padding-inline: var(--ban-5); }
  .ban-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ban-zone-strip__cell { height: 3.75rem; }
  .ban-zone-strip__labels { font-size: .75rem; }
}

@media (min-width: 48rem) {                       /* 768px — tablet                 */
  :root { --ban-control-h: 3.125rem; }
  .ban-section { padding-block: var(--ban-9); }
  .ban-section--loose { padding-block: var(--ban-11); }
  .ban-hero__inner { grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr); padding-block: var(--ban-9) var(--ban-10); }
  .ban-grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ban-meta__row { grid-template-columns: 14rem minmax(0, 1fr); gap: var(--ban-5); align-items: baseline; }
  .ban-filter__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ban-footer__main { grid-template-columns: 1.4fr 1fr 1fr; }
}

@media (min-width: 62rem) {                       /* 992px — desktop                */
  .ban-header__row { padding-block: .6rem; }
  .ban-nav { display: flex; }
  .ban-burger { display: none; }
  .ban-trust { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ban-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .ban-trust { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .ban-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .ban-filter__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (min-width: 75rem) {                       /* 1200px — wide desktop          */
  .ban-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .ban-hero__inner { gap: var(--ban-9); }
}

@media (min-width: 90rem) {                       /* 1440px+                        */
  .ban-container { padding-inline: var(--ban-6); }
}


/* =====================================================================================
   08 · PREFERENCES
   ===================================================================================== */

/* Dark theme — honours the existing site's behaviour. Mapped to both the system
   preference and Bootstrap's data-bs-theme switch so components follow the brand. */
/* ------------------------------------------------------------------------------
   DARK THEME — one token set, emitted twice on purpose.
   There is no Sass or build step in this project, so the media-query fallback
   (for visitors with JavaScript disabled) and the explicit toggle
   ([data-bs-theme="dark"], set by assets/js/ban.js) are written out in full.
   Keep both in step: this block is generated by tools/patch-theme.py.
   The media query is guarded so an explicit *light* choice always wins on a
   dark-preference device.
   ------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------
   DARK THEME — a single token set, written out twice on purpose.
   This project has no Sass and no build step, so the media-query fallback (for
   visitors without JavaScript) and the explicit toggle
   ([data-bs-theme="dark"], set by assets/js/ban.js) each need the full set.
   Generated by tools/patch-theme.py — never edit one without the other.
   The media query is guarded so an explicit *light* choice wins on a device
   that prefers dark.
   ------------------------------------------------------------------------------ */
@media (prefers-color-scheme: dark) {
  :root:not([data-bs-theme="light"]) {
    --ban-bg:              #0F1A16;   /* page background */
    --ban-surface:         #14211C;   /* cards */
    --ban-surface-alt:     #18261F;   /* inset panels */
    --ban-border:          #26362E;   /* hairline (decorative, not a UI boundary) */
    --ban-border-strong:   #6B8077;   /* input borders — 3.9:1 */
    --ban-ink:             #EAF1ED;   /* body text */
    --ban-ink-700:         #C2D0CA;   /* secondary text */
    --ban-ink-500:         #9BAEA6;   /* metadata */
    --ban-ink-300:         #6E8078;   /* disabled text */
    --ban-white:           #FFFFFF;   /* pure white */
    --ban-green:           #3FA97C;   /* primary fill and link text — 6.1:1 */
    --ban-green-900:       #7FD3A6;   /* green as TEXT on dark tints — 9.0:1 */
    --ban-green-700:       #1F5C44;   /* pressed state, background only */
    --ban-green-050:       #17281F;   /* green tint */
    --ban-green-100:       #1C3428;   /* green tint 2 */
    --ban-amber:           #E59A1F;   /* brand amber, identical in both themes */
    --ban-amber-050:       #241E12;   /* amber tint */
    --ban-amber-100:       #2E2615;   /* amber tint 2 */
    --ban-amber-800:       #F0BE63;   /* amber as text on dark */
    --ban-on-green:        #0F1A16;   /* label on the lighter dark green — 6.1:1 */
    --ban-on-amber:        #13261F;   /* label on amber — 7.6:1 */
    --ban-focus:           #E59A1F;   /* focus ring on dark — 6.8:1 */
    --ban-success-bg:      #16281F;
    --ban-success-fg:      #7FD3A6;
    --ban-success-br:      #24523B;
    --ban-warning-bg:      #241E12;
    --ban-warning-fg:      #F0BE63;
    --ban-warning-br:      #4A3A1A;
    --ban-info-bg:         #17281F;
    --ban-info-fg:         #D8E9E0;
    --ban-info-br:         #2A4437;
    --ban-danger-bg:       #2A1A16;
    --ban-danger-fg:       #E7A99A;
    --ban-danger-br:       #5A2E23;
    --ban-neutral-bg:      #1B2621;
    --ban-neutral-fg:      #C2D0CA;
    --ban-neutral-br:      #33443B;
    --bs-body-bg:          var(--ban-bg);
    --bs-body-color:       var(--ban-ink);
    --bs-border-color:     var(--ban-border);
    --bs-heading-color:    var(--ban-ink);
    --bs-secondary-color:  var(--ban-ink-700);
    --bs-tertiary-color:   var(--ban-ink-500);
    --bs-link-color:       var(--ban-green);
    --bs-link-hover-color: #7FD3A6;
    --bs-card-bg:          var(--ban-surface);
    --bs-card-border-color: var(--ban-border);
    --bs-table-bg:         transparent;
    --bs-table-color:      var(--ban-ink);
    --bs-table-border-color: var(--ban-border);
    --bs-table-striped-bg: var(--ban-surface-alt);
    --bs-emphasis-color:   var(--ban-ink);
    --bs-secondary-bg:     var(--ban-surface-alt);
  /* Shadows in a dark theme must be darker rather than the same translucent ink: on a dark
     surface a green-tinted shadow is invisible, so these are declared as true black with a
     higher opacity. Declared here so both themes carry the same token set. */
  --ban-shadow-sm: 0 1px 2px rgba(0, 0, 0, .45), 0 2px 8px rgba(0, 0, 0, .35);
  --ban-shadow-md: 0 8px 24px rgba(0, 0, 0, .50);
  --ban-shadow-lg: 0 18px 48px rgba(0, 0, 0, .58);
  }
  .ban-zone-strip__cell { background: #2A3A33; }
  .ban-brand__mark, .ban-footer__brand img { background: #FFFFFF; }
}
[data-bs-theme="dark"] {
  --ban-bg:              #0F1A16;   /* page background */
  --ban-surface:         #14211C;   /* cards */
  --ban-surface-alt:     #18261F;   /* inset panels */
  --ban-border:          #26362E;   /* hairline (decorative, not a UI boundary) */
  --ban-border-strong:   #6B8077;   /* input borders — 3.9:1 */
  --ban-ink:             #EAF1ED;   /* body text */
  --ban-ink-700:         #C2D0CA;   /* secondary text */
  --ban-ink-500:         #9BAEA6;   /* metadata */
  --ban-ink-300:         #6E8078;   /* disabled text */
  --ban-white:           #FFFFFF;   /* pure white */
  --ban-green:           #3FA97C;   /* primary fill and link text — 6.1:1 */
  --ban-green-900:       #7FD3A6;   /* green as TEXT on dark tints — 9.0:1 */
  --ban-green-700:       #1F5C44;   /* pressed state, background only */
  --ban-green-050:       #17281F;   /* green tint */
  --ban-green-100:       #1C3428;   /* green tint 2 */
  --ban-amber:           #E59A1F;   /* brand amber, identical in both themes */
  --ban-amber-050:       #241E12;   /* amber tint */
  --ban-amber-100:       #2E2615;   /* amber tint 2 */
  --ban-amber-800:       #F0BE63;   /* amber as text on dark */
  --ban-on-green:        #0F1A16;   /* label on the lighter dark green — 6.1:1 */
  --ban-on-amber:        #13261F;   /* label on amber — 7.6:1 */
  --ban-focus:           #E59A1F;   /* focus ring on dark — 6.8:1 */
  --ban-success-bg:      #16281F;
  --ban-success-fg:      #7FD3A6;
  --ban-success-br:      #24523B;
  --ban-warning-bg:      #241E12;
  --ban-warning-fg:      #F0BE63;
  --ban-warning-br:      #4A3A1A;
  --ban-info-bg:         #17281F;
  --ban-info-fg:         #D8E9E0;
  --ban-info-br:         #2A4437;
  --ban-danger-bg:       #2A1A16;
  --ban-danger-fg:       #E7A99A;
  --ban-danger-br:       #5A2E23;
  --ban-neutral-bg:      #1B2621;
  --ban-neutral-fg:      #C2D0CA;
  --ban-neutral-br:      #33443B;
  --bs-body-bg:          var(--ban-bg);
  --bs-body-color:       var(--ban-ink);
  --bs-border-color:     var(--ban-border);
  --bs-heading-color:    var(--ban-ink);
  --bs-secondary-color:  var(--ban-ink-700);
  --bs-tertiary-color:   var(--ban-ink-500);
  --bs-link-color:       var(--ban-green);
  --bs-link-hover-color: #7FD3A6;
  --bs-card-bg:          var(--ban-surface);
  --bs-card-border-color: var(--ban-border);
  --bs-table-bg:         transparent;
  --bs-table-color:      var(--ban-ink);
  --bs-table-border-color: var(--ban-border);
  --bs-table-striped-bg: var(--ban-surface-alt);
  --bs-emphasis-color:   var(--ban-ink);
  --bs-secondary-bg:     var(--ban-surface-alt);
  /* Shadows in a dark theme must be darker rather than the same translucent ink: on a dark
     surface a green-tinted shadow is invisible, so these are declared as true black with a
     higher opacity. Declared here so both themes carry the same token set. */
  --ban-shadow-sm: 0 1px 2px rgba(0, 0, 0, .45), 0 2px 8px rgba(0, 0, 0, .35);
  --ban-shadow-md: 0 8px 24px rgba(0, 0, 0, .50);
  --ban-shadow-lg: 0 18px 48px rgba(0, 0, 0, .58);
}
/* Kept out of the token blocks: these are component adjustments, not tokens. */
[data-bs-theme="dark"] .ban-zone-strip__cell,
:root:not([data-bs-theme="light"]) .ban-zone-strip__cell { background: #2A3A33; }
[data-bs-theme="dark"] .ban-brand__mark,
[data-bs-theme="dark"] .ban-footer__brand img { background: #FFFFFF; }
[data-bs-theme="dark"] .ban-theme-toggle .ban-icon--sun { display: inline; }
[data-bs-theme="dark"] .ban-theme-toggle .ban-icon--moon { display: none; }


@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
  .ban-card:hover { transform: none; }
}

@media (forced-colors: active) {
  .ban-card, .ban-badge, .ban-alert, .ban-verify-result { border: 1px solid CanvasText; }
  .ban-zone-strip__cell { border: 1px solid CanvasText; }
  .ban-zone-strip__cell.is-charged { background: Highlight; }
}

@media print {
  :root { --ban-bg: #fff; --ban-surface: #fff; }
  .ban-header, .ban-footer, .ban-filter, .ban-actions, .skip-link, .ban-embed { display: none !important; }
  body { font-size: 11pt; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; color: #444; }
  .ban-card, .ban-verify-result { break-inside: avoid; box-shadow: none; }
  .ban-section { padding-block: 1rem; }
}


/* =====================================================================================
   09 · BOOTSTRAP STRUCTURAL INTEGRATION  (Phase 09)
   -------------------------------------------------------------------------------------
   Bootstrap 5.3 is now the structural framework: the grid, the offcanvas, the accordion,
   the tab set and the form controls come from bootstrap.min.css. This layer does the
   reverse of the usual integration — instead of restyling our markup to look like
   Bootstrap, it maps every Bootstrap component we actually use back onto the approved
   Battery Academy identity, using the tokens in layer 01 and nothing else.
   No new hues. No new type sizes. No !important unless Bootstrap itself uses one.
   ===================================================================================== */

/* --- 9.1 Containers and grid ------------------------------------------------------- */
/* Bootstrap's own container adopts the site measure so a grid row and a .ban-container
   line up exactly; nothing shifts when a section mixes the two. */
.container,
.container-sm, .container-md, .container-lg, .container-xl, .container-xxl {
  max-width: var(--ban-container);
  padding-inline: var(--ban-4);
}
@media (min-width: 90rem) {
  .container, .container-lg, .container-xl, .container-xxl { padding-inline: var(--ban-6); }
}
.row { --bs-gutter-x: var(--ban-5); --bs-gutter-y: var(--ban-5); }
/* Column padding must never create horizontal scroll on a 320px phone. */
.row > [class*="col"] { min-width: 0; }

/* --- 9.2 Buttons ------------------------------------------------------------------- */
/* The site's own button set is .btn-ban*; these rules make Bootstrap's variants render
   identically, so a Bootstrap button can never appear in default blue. */
.btn-primary {
  --bs-btn-bg: var(--ban-green); --bs-btn-border-color: var(--ban-green);
  --bs-btn-color: var(--ban-on-green);
  --bs-btn-hover-bg: var(--ban-green-900); --bs-btn-hover-border-color: var(--ban-green-900);
  --bs-btn-hover-color: var(--ban-on-green);
  --bs-btn-active-bg: var(--ban-green-700); --bs-btn-active-border-color: var(--ban-green-700);
  --bs-btn-active-color: var(--ban-on-green);
  --bs-btn-disabled-bg: var(--ban-neutral-bg); --bs-btn-disabled-border-color: var(--ban-border);
  --bs-btn-disabled-color: var(--ban-ink-300);
}
.btn-outline-primary {
  --bs-btn-color: var(--ban-green); --bs-btn-border-color: var(--ban-green);
  --bs-btn-hover-bg: var(--ban-green-050); --bs-btn-hover-color: var(--ban-green-900);
  --bs-btn-hover-border-color: var(--ban-green-900);
  --bs-btn-active-bg: var(--ban-green-100); --bs-btn-active-color: var(--ban-green-900);
}
.btn-outline-secondary {
  --bs-btn-color: var(--ban-ink); --bs-btn-border-color: var(--ban-border-strong);
  --bs-btn-hover-bg: var(--ban-bg); --bs-btn-hover-color: var(--ban-ink);
  --bs-btn-hover-border-color: var(--ban-ink-300);
  --bs-btn-active-bg: var(--ban-neutral-bg); --bs-btn-active-color: var(--ban-ink);
}
.btn-warning {
  --bs-btn-bg: var(--ban-amber); --bs-btn-border-color: var(--ban-amber);
  --bs-btn-color: var(--ban-on-amber);
  --bs-btn-hover-bg: #D08A12; --bs-btn-hover-border-color: #D08A12;
  --bs-btn-hover-color: var(--ban-on-amber);
  --bs-btn-active-bg: #B9790F; --bs-btn-active-border-color: #B9790F;
  --bs-btn-active-color: var(--ban-on-amber);
}
.btn-link { --bs-btn-color: var(--ban-green); --bs-btn-hover-color: var(--ban-green-900); }
.btn-close { --bs-btn-close-focus-shadow: 0 0 0 3px var(--ban-focus); }

/* --- 9.3 Cards --------------------------------------------------------------------- */
.card {
  --bs-card-bg: var(--ban-surface);
  --bs-card-border-color: var(--ban-border);
  --bs-card-cap-color: var(--ban-ink);
  --bs-card-color: var(--ban-ink);
  border-radius: var(--ban-radius-lg);
}
.card-header, .card-footer { border-color: var(--ban-border); }

/* --- 9.4 Accordion (course sections, module topics, FAQ) -------------------------- */
.accordion {
  --bs-accordion-color: var(--ban-ink);
  --bs-accordion-bg: var(--ban-surface);
  --bs-accordion-border-color: var(--ban-border);
  --bs-accordion-btn-color: var(--ban-ink);
  --bs-accordion-btn-bg: var(--ban-surface);
  --bs-accordion-active-color: var(--ban-ink);
  --bs-accordion-active-bg: var(--ban-surface);
  --bs-accordion-btn-focus-box-shadow: 0 0 0 3px var(--ban-focus);
  --bs-accordion-border-radius: var(--ban-radius-md);
  --bs-accordion-inner-border-radius: var(--ban-radius-md);
}
.accordion-button { font-family: var(--ban-font-head); font-weight: 700; }
.accordion-button:not(.collapsed) { box-shadow: inset 3px 0 0 var(--ban-green); }
.accordion-body { color: var(--ban-ink-700); font-size: var(--ban-fs-sm); }
.accordion-body .ban-meta { margin-top: var(--ban-3); }
/* The marker is decorative: state is announced by the button, not by the arrow. */
.accordion-button::after { background-size: 1rem; }

/* --- 9.5 Tabs, pills and filters -------------------------------------------------- */
.nav-tabs {
  --bs-nav-tabs-border-color: var(--ban-border);
  --bs-nav-tabs-link-active-color: var(--ban-green-900);
  --bs-nav-tabs-link-active-bg: var(--ban-surface);
  --bs-nav-tabs-link-active-border-color: var(--ban-border) var(--ban-border) var(--ban-surface);
  --bs-nav-link-color: var(--ban-ink-700);
  --bs-nav-link-hover-color: var(--ban-green);
  gap: var(--ban-1);
}
.nav-tabs .nav-link { font-weight: 600; min-height: 2.75rem; }
.nav-pills { --bs-nav-pills-link-active-bg: var(--ban-green); --bs-nav-pills-link-active-color: var(--ban-on-green); }
.nav-pills .nav-link { color: var(--ban-ink); font-weight: 600; }
.nav-pills .nav-link:hover { background: var(--ban-green-050); color: var(--ban-green-900); }

/* --- 9.6 Lists, tables, and the responsive wrap ----------------------------------- */
.list-group {
  --bs-list-group-color: var(--ban-ink);
  --bs-list-group-bg: var(--ban-surface);
  --bs-list-group-border-color: var(--ban-border);
  --bs-list-group-action-hover-bg: var(--ban-green-050);
  --bs-list-group-action-hover-color: var(--ban-green-900);
  --bs-list-group-action-active-bg: var(--ban-green-100);
  --bs-list-group-disabled-color: var(--ban-ink-300);
}
.list-group-item { padding: var(--ban-3) var(--ban-4); }
.list-group-item + .list-group-item { border-top-width: 1px; }
.table-responsive { -webkit-overflow-scrolling: touch; }
/* Inside a responsive wrapper the stacked variant is not used: the table scrolls. */
.table-responsive .ban-table--stack td::before { content: none; }

/* --- 9.7 Forms (Bootstrap structure, site skin) ----------------------------------- */
.form-label { font-weight: 700; font-size: var(--ban-fs-sm); color: var(--ban-ink); margin-bottom: var(--ban-2); }
.form-control, .form-select {
  min-height: var(--ban-control-h);
  border-radius: var(--ban-radius-md);
  border-color: var(--ban-border-strong);
  background-color: var(--ban-surface);
  color: var(--ban-ink);
  font-size: var(--ban-fs-body);
}
.form-control::placeholder { color: var(--ban-ink-500); opacity: 1; }
.form-control:focus, .form-select:focus {
  border-color: var(--ban-green);
  box-shadow: 0 0 0 3px var(--ban-focus);
  outline: 2px solid transparent;   /* the ring above is the visible indicator */
}
.form-control:disabled, .form-select:disabled { background: var(--ban-neutral-bg); color: var(--ban-ink-300); }
.form-text { color: var(--ban-ink-700); font-size: var(--ban-fs-sm); }
.form-check-input { border-color: var(--ban-border-strong); }
.form-check-input:checked { background-color: var(--ban-green); border-color: var(--ban-green); }
.form-check-input:focus { border-color: var(--ban-green); box-shadow: 0 0 0 3px var(--ban-focus); }
.form-check-label { font-size: var(--ban-fs-sm); }
.form-switch .form-check-input { width: 2.5rem; height: 1.4rem; }
.invalid-feedback, .form-control.is-invalid ~ .invalid-feedback { color: var(--ban-danger-fg); font-weight: 600; }
.form-control.is-invalid, .form-select.is-invalid { border-color: var(--ban-danger-fg); }
/* Error text plus a red border is not enough on its own: the field also carries
   aria-invalid and aria-describedby, and the error never depends on colour alone. */
.input-group-text { background: var(--ban-surface-alt); border-color: var(--ban-border-strong); color: var(--ban-ink-700); }

/* --- 9.8 Offcanvas (mobile navigation) ------------------------------------------- */
.offcanvas { --bs-offcanvas-color: var(--ban-ink); --bs-offcanvas-bg: var(--ban-surface); }
.offcanvas-header { border-bottom: 1px solid var(--ban-border); }
.offcanvas-title { font-family: var(--ban-font-head); }

/* --- 9.9 Dropdowns, modals, tooltips, toasts ------------------------------------- */
.dropdown-menu {
  --bs-dropdown-bg: var(--ban-surface); --bs-dropdown-color: var(--ban-ink);
  --bs-dropdown-border-color: var(--ban-border);
  --bs-dropdown-link-hover-bg: var(--ban-bg);
  --bs-dropdown-link-hover-color: var(--ban-ink);
  --bs-dropdown-link-active-bg: var(--ban-green-050);
  --bs-dropdown-link-active-color: var(--ban-green-900);
  padding: var(--ban-2);
  box-shadow: var(--ban-shadow-md);
}
.dropdown-item { border-radius: var(--ban-radius-sm); padding: var(--ban-2) var(--ban-3); font-size: var(--ban-fs-sm); }
.modal { --bs-modal-bg: var(--ban-surface); --bs-modal-color: var(--ban-ink); --bs-modal-border-radius: var(--ban-radius-lg); }
.modal-header, .modal-footer { border-color: var(--ban-border); }
.modal-title { font-family: var(--ban-font-head); }
.tooltip { --bs-tooltip-bg: var(--ban-deep); --bs-tooltip-color: var(--ban-on-deep);
  --bs-tooltip-border-radius: var(--ban-radius-sm); --bs-tooltip-opacity: 1; font-size: var(--ban-fs-xs); }
.toast { --bs-toast-bg: var(--ban-surface); --bs-toast-color: var(--ban-ink); --bs-toast-border-color: var(--ban-border); }
.progress { --bs-progress-bg: var(--ban-neutral-bg); --bs-progress-bar-bg: var(--ban-green); height: .6rem;
  border-radius: var(--ban-radius-pill); }
.progress-bar { color: var(--ban-ink); }        /* only ever read with a visible label */

/* --- 9.10 Badges, alerts, breadcrumbs, pagination -------------------------------- */
.badge { font-weight: 700; border-radius: var(--ban-radius-pill); }
.text-bg-primary { background-color: var(--ban-green) !important; color: var(--ban-on-green) !important; }
.text-bg-success { background-color: var(--ban-success-bg) !important; color: var(--ban-success-fg) !important; }
.text-bg-warning { background-color: var(--ban-warning-bg) !important; color: var(--ban-warning-fg) !important; }
.text-bg-danger  { background-color: var(--ban-danger-bg)  !important; color: var(--ban-danger-fg)  !important; }
.text-bg-secondary { background-color: var(--ban-neutral-bg) !important; color: var(--ban-neutral-fg) !important; }
.alert { border-radius: var(--ban-radius-md); border-left: 4px solid var(--ban-green); }
.alert-success { background: var(--ban-success-bg); border-color: var(--ban-success-br); border-left-color: var(--ban-green); color: var(--ban-success-fg); }
.alert-warning { background: var(--ban-warning-bg); border-color: var(--ban-warning-br); border-left-color: var(--ban-amber); color: var(--ban-warning-fg); }
.alert-danger  { background: var(--ban-danger-bg);  border-color: var(--ban-danger-br);  border-left-color: var(--ban-danger-fg); color: var(--ban-danger-fg); }
.alert-info    { background: var(--ban-info-bg);    border-color: var(--ban-info-br);    border-left-color: var(--ban-green); color: var(--ban-ink); }
.breadcrumb { --bs-breadcrumb-divider-color: var(--ban-ink-300); --bs-breadcrumb-item-active-color: var(--ban-ink-700);
  font-size: var(--ban-fs-sm); margin-bottom: 0; }
.pagination {
  --bs-pagination-color: var(--ban-green); --bs-pagination-bg: var(--ban-surface);
  --bs-pagination-border-color: var(--ban-border);
  --bs-pagination-hover-bg: var(--ban-green-050); --bs-pagination-hover-color: var(--ban-green-900);
  --bs-pagination-hover-border-color: var(--ban-border-strong);
  --bs-pagination-active-bg: var(--ban-green); --bs-pagination-active-border-color: var(--ban-green);
  --bs-pagination-active-color: var(--ban-on-green);
  --bs-pagination-disabled-color: var(--ban-ink-300);
  --bs-pagination-focus-box-shadow: 0 0 0 3px var(--ban-focus);
  --bs-pagination-focus-color: var(--ban-green-900);
  gap: var(--ban-1);
}
.page-link { min-width: 2.75rem; min-height: 2.75rem; display: inline-flex; align-items: center; justify-content: center; }
.page-item.active .page-link { color: var(--ban-on-green); }

/* --- 9.11 Tables ------------------------------------------------------------------ */
.table {
  --bs-table-color: var(--ban-ink);
  --bs-table-bg: transparent;
  --bs-table-border-color: var(--ban-border);
  --bs-table-striped-bg: var(--ban-surface-alt);
  --bs-table-hover-bg: var(--ban-green-050);
  --bs-table-hover-color: var(--ban-ink);
  caption-side: top;
}
.table > :not(caption) > * > * { padding: .7rem var(--ban-3); }
.table caption { color: var(--ban-ink-700); font-size: var(--ban-fs-sm); }

/* --- 9.12 Ratio (course and zone imagery, no layout shift) ------------------------ */
.ratio { background: var(--ban-green-050); border-radius: var(--ban-radius-md); overflow: hidden; }

/* --- 9.13 Scroll-spy and sticky helpers used by the module pages ------------------ */
.ban-sticky-aside { position: sticky; top: calc(var(--ban-header-h) + var(--ban-4)); }
@media (max-width: 61.99rem) { .ban-sticky-aside { position: static; } }


/* =====================================================================================
   10 · PHASE 09 ADDITIONS
   -------------------------------------------------------------------------------------
   Every class here is new in Phase 09 and exists for a reason that is written next to it.
   Nothing in this layer changes an existing component: the Phase 08 component layer is
   untouched, so a page that looked right in the design phase still looks the same.
   ===================================================================================== */

/* Tighter action row for card footers — cards have less room than page sections. */
.ban-actions--tight { gap: var(--ban-2); }

/* Zone strip: the labels gained a zone name and a state word, and the strip gained a small
   variant for the footer of a page. The cell geometry itself is unchanged. */
.ban-zone-strip__labels li { display: grid; grid-template-columns: 2.25rem 1fr; gap: 0 var(--ban-2); }
.ban-zone-strip__name { font-weight: 600; }
.ban-zone-strip__state {
  grid-column: 2; font-size: var(--ban-fs-xs); font-weight: 600; color: var(--ban-ink-500);
}
.ban-zone-strip--sm { max-width: 22rem; }
.ban-zone-strip--sm .ban-zone-strip__cell { height: 2rem; }
.ban-zone-strip--sm .ban-zone-strip__labels { font-size: var(--ban-fs-xs); }

/* A placeholder whose id is not in the register: a build fault, shown as one. It is still
   amber — it is still missing content — but the tag says "unregistered" rather than
   pretending a reviewer simply has not looked at it. */
.ban-todo--unknown { border-color: var(--ban-danger-br); background: var(--ban-danger-bg); }
.ban-todo--unknown .ban-todo__tag { background: var(--ban-danger-fg); color: var(--ban-white); }

/* A plain link list inside a card or a panel (related files, other categories, other series).
   Distinct from the footer's navigation list so a footer rule change cannot move a card. */
.ban-card__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--ban-2); font-size: var(--ban-fs-sm); }

/* The verification result when no check was made. It must not borrow the success or the
   failure treatment: it is neutral by design, and the wording says so. */
.ban-verify-result__body .ban-xs { color: var(--ban-ink-500); }

/* A single-line statement of what an access level means, used on restricted cards. */
.ban-lockline { display: inline-flex; align-items: center; gap: var(--ban-2);
  font-size: var(--ban-fs-xs); color: var(--ban-ink-700); }

/* =====================================================================================
   11 · BOOTSTRAP COLOUR CONTAINMENT
   =====================================================================================
   Bootstrap 5.3.3 is loaded before this file as the structural framework. Its default theme
   colour is #0d6efd, and several of its components and utilities carry that colour or a
   stock grey regardless of what the site's own classes do. Layer 09 mapped the components
   the site actually uses; this layer closes the rest of the door, so that a developer who
   reaches for a plain Bootstrap class — .btn-success, .text-bg-dark, .alert-primary,
   .bg-light, .link-primary — still gets the Academy's palette rather than a stray blue.

   Two rules govern everything below:
     1. Only tokens are used (never a raw hex, other than the two amber hover steps already
        declared in layer 09.2), so both themes stay correct without a second declaration.
     2. Contrast is taken from the theme blocks: --ban-on-green, --ban-on-amber and the
        *-fg tokens are the audited pairings. Do not invent new foregrounds here.

   A test in tests/run.php asserts that every selector listed below is declared in this file,
   so the containment cannot be lost by an edit to another layer.
   ===================================================================================== */

/* --- 11.1 Text and background utilities -------------------------------------------- */
/* Bootstrap marks these !important; the skin has to match it or the default would win in
   a cascade tie. */
.text-primary   { color: var(--ban-green) !important; }
.text-secondary { color: var(--ban-ink-700) !important; }
.text-muted     { color: var(--ban-ink-500) !important; }
.text-body      { color: var(--ban-ink) !important; }
.text-body-secondary { color: var(--ban-ink-500) !important; }
.text-success   { color: var(--ban-green-700) !important; }
.text-danger    { color: var(--ban-danger-fg) !important; }
.text-warning   { color: var(--ban-amber-800) !important; }
.text-info      { color: var(--ban-green-700) !important; }
.text-dark      { color: var(--ban-ink) !important; }
.text-light     { color: var(--ban-white) !important; }
.text-white     { color: var(--ban-white) !important; }

.bg-primary   { background-color: var(--ban-green) !important; color: var(--ban-on-green) !important; }
.bg-secondary { background-color: var(--ban-neutral-bg) !important; color: var(--ban-neutral-fg) !important; }
.bg-body      { background-color: var(--ban-bg) !important; }
.bg-body-secondary { background-color: var(--ban-surface-alt) !important; }
.bg-light     { background-color: var(--ban-surface-alt) !important; color: var(--ban-ink) !important; }
.bg-dark      { background-color: var(--ban-deep) !important; color: var(--ban-on-deep) !important; }
.bg-white     { background-color: var(--ban-surface) !important; color: var(--ban-ink) !important; }
.bg-success   { background-color: var(--ban-success-bg) !important; color: var(--ban-success-fg) !important; }
.bg-warning   { background-color: var(--ban-warning-bg) !important; color: var(--ban-warning-fg) !important; }
.bg-danger    { background-color: var(--ban-danger-bg) !important; color: var(--ban-danger-fg) !important; }
.bg-info      { background-color: var(--ban-info-bg) !important; color: var(--ban-ink) !important; }

/* .text-bg-* is Bootstrap's pairing of a background with a readable foreground; the
   remaining members of that set are completed here (primary, success, warning, danger and
   secondary are already declared in layer 09.10). */
.text-bg-info { background-color: var(--ban-info-bg) !important; color: var(--ban-ink) !important; }
.text-bg-dark { background-color: var(--ban-deep) !important; color: var(--ban-on-deep) !important; }
.text-bg-light { background-color: var(--ban-surface-alt) !important; color: var(--ban-ink) !important; }
.text-bg-body { background-color: var(--ban-bg) !important; color: var(--ban-ink) !important; }
.text-bg-white { background-color: var(--ban-surface) !important; color: var(--ban-ink) !important; }

/* Links that Bootstrap colours by variant. Underlines are left to the base layer, which
   keeps them on in body copy and off in components. */
.link-primary   { color: var(--ban-green) !important; }
.link-secondary { color: var(--ban-ink-700) !important; }
.link-body      { color: var(--ban-ink) !important; }
.link-success, .link-info { color: var(--ban-green-700) !important; }
.link-warning   { color: var(--ban-amber-800) !important; }
.link-danger    { color: var(--ban-danger-fg) !important; }

/* Borders: Bootstrap's .border-* utilities default to its own grey ramp. */
.border-primary { border-color: var(--ban-green) !important; }
.border-secondary { border-color: var(--ban-border-strong) !important; }
.border-success { border-color: var(--ban-success-br) !important; }
.border-warning { border-color: var(--ban-warning-br) !important; }
.border-danger  { border-color: var(--ban-danger-br) !important; }
.border-info    { border-color: var(--ban-info-br) !important; }
.border-light   { border-color: var(--ban-border) !important; }
.border-dark    { border-color: var(--ban-ink) !important; }

/* --- 11.2 The rest of the button set ----------------------------------------------- */
/* Layer 09.2 covers primary, outline-primary, outline-secondary, warning, link and
   close. The remaining variants exist so nobody has to reach for a hex value; each maps
   onto a token pairing that already passes contrast. */
.btn-secondary {
  --bs-btn-bg: var(--ban-neutral-bg); --bs-btn-border-color: var(--ban-border-strong);
  --bs-btn-color: var(--ban-neutral-fg);
  --bs-btn-hover-bg: var(--ban-green-050); --bs-btn-hover-border-color: var(--ban-green-700);
  --bs-btn-hover-color: var(--ban-green-900);
  --bs-btn-active-bg: var(--ban-green-100); --bs-btn-active-border-color: var(--ban-green-700);
  --bs-btn-active-color: var(--ban-green-900);
  --bs-btn-disabled-bg: var(--ban-neutral-bg); --bs-btn-disabled-border-color: var(--ban-border);
  --bs-btn-disabled-color: var(--ban-ink-300);
}
.btn-success {
  --bs-btn-bg: var(--ban-green-700); --bs-btn-border-color: var(--ban-green-700);
  --bs-btn-color: var(--ban-on-green);
  --bs-btn-hover-bg: var(--ban-green-900); --bs-btn-hover-border-color: var(--ban-green-900);
  --bs-btn-hover-color: var(--ban-on-green);
  --bs-btn-active-bg: var(--ban-deep); --bs-btn-active-border-color: var(--ban-deep);
  --bs-btn-active-color: var(--ban-on-deep);
}
.btn-info {
  --bs-btn-bg: var(--ban-info-bg); --bs-btn-border-color: var(--ban-info-br);
  --bs-btn-color: var(--ban-ink);
  --bs-btn-hover-bg: var(--ban-green-050); --bs-btn-hover-border-color: var(--ban-green-700);
  --bs-btn-hover-color: var(--ban-green-900);
}
.btn-danger {
  --bs-btn-bg: var(--ban-danger-bg); --bs-btn-border-color: var(--ban-danger-br);
  --bs-btn-color: var(--ban-danger-fg);
  --bs-btn-hover-bg: var(--ban-danger-fg); --bs-btn-hover-border-color: var(--ban-danger-fg);
  --bs-btn-hover-color: var(--ban-surface);
}
.btn-dark {
  --bs-btn-bg: var(--ban-deep); --bs-btn-border-color: var(--ban-deep);
  --bs-btn-color: var(--ban-on-deep);
  --bs-btn-hover-bg: var(--ban-deep-alt); --bs-btn-hover-border-color: var(--ban-deep-alt);
  --bs-btn-hover-color: var(--ban-on-deep);
}
.btn-light {
  --bs-btn-bg: var(--ban-surface); --bs-btn-border-color: var(--ban-border);
  --bs-btn-color: var(--ban-ink);
  --bs-btn-hover-bg: var(--ban-surface-alt); --bs-btn-hover-border-color: var(--ban-border-strong);
  --bs-btn-hover-color: var(--ban-ink);
}
.btn-outline-success {
  --bs-btn-color: var(--ban-green-700); --bs-btn-border-color: var(--ban-green-700);
  --bs-btn-hover-bg: var(--ban-green-700); --bs-btn-hover-border-color: var(--ban-green-700);
  --bs-btn-hover-color: var(--ban-on-green);
}
.btn-outline-warning {
  --bs-btn-color: var(--ban-amber-800); --bs-btn-border-color: var(--ban-amber);
  --bs-btn-hover-bg: var(--ban-amber); --bs-btn-hover-border-color: var(--ban-amber);
  --bs-btn-hover-color: var(--ban-on-amber);
}
.btn-outline-danger {
  --bs-btn-color: var(--ban-danger-fg); --bs-btn-border-color: var(--ban-danger-br);
  --bs-btn-hover-bg: var(--ban-danger-fg); --bs-btn-hover-border-color: var(--ban-danger-fg);
  --bs-btn-hover-color: var(--ban-surface);
}
.btn-outline-info {
  --bs-btn-color: var(--ban-ink); --bs-btn-border-color: var(--ban-info-br);
  --bs-btn-hover-bg: var(--ban-info-bg); --bs-btn-hover-color: var(--ban-ink);
}
.btn-outline-dark {
  --bs-btn-color: var(--ban-ink); --bs-btn-border-color: var(--ban-ink);
  --bs-btn-hover-bg: var(--ban-deep); --bs-btn-hover-border-color: var(--ban-deep);
  --bs-btn-hover-color: var(--ban-on-deep);
}
.btn-outline-light {
  --bs-btn-color: var(--ban-on-deep); --bs-btn-border-color: var(--ban-on-deep-soft);
  --bs-btn-hover-bg: var(--ban-surface); --bs-btn-hover-border-color: var(--ban-surface);
  --bs-btn-hover-color: var(--ban-ink);
}
/* A .btn that is not one of the variants above — a bare <button class="btn"> — must still
   read as a button rather than as unstyled text. */
.btn:not([class*="btn-"]) {
  --bs-btn-bg: var(--ban-surface); --bs-btn-border-color: var(--ban-border-strong);
  --bs-btn-color: var(--ban-ink);
}

/* --- 11.3 Alerts, list groups, tables ---------------------------------------------- */
.alert-primary { background: var(--ban-green-050); border-color: var(--ban-green-100); border-left-color: var(--ban-green); color: var(--ban-green-900); }
.alert-secondary { background: var(--ban-neutral-bg); border-color: var(--ban-border); border-left-color: var(--ban-border-strong); color: var(--ban-neutral-fg); }
.alert-dark { background: var(--ban-surface-alt); border-color: var(--ban-border); border-left-color: var(--ban-ink); color: var(--ban-ink); }
.alert-light { background: var(--ban-surface); border-color: var(--ban-border); border-left-color: var(--ban-border-strong); color: var(--ban-ink); }
.alert-heading { color: inherit; }

.list-group {
  --bs-list-group-color: var(--ban-ink);
  --bs-list-group-bg: var(--ban-surface);
  --bs-list-group-border-color: var(--ban-border);
  --bs-list-group-action-hover-bg: var(--ban-green-050);
  --bs-list-group-action-hover-color: var(--ban-ink);
  --bs-list-group-active-bg: var(--ban-green-050);
  --bs-list-group-active-color: var(--ban-green-900);
  --bs-list-group-active-border-color: var(--ban-green);
}
.list-group-item-success { background: var(--ban-success-bg); color: var(--ban-success-fg); }
.list-group-item-warning { background: var(--ban-warning-bg); color: var(--ban-warning-fg); }
.list-group-item-danger  { background: var(--ban-danger-bg);  color: var(--ban-danger-fg); }
.list-group-item-info    { background: var(--ban-info-bg);    color: var(--ban-ink); }
.list-group-item-primary { background: var(--ban-green-050);  color: var(--ban-green-900); }

/* Contextual table rows: a tint behind the row, never a coloured foreground, so the cell
   text keeps the contrast it was audited at. */
.table-success { --bs-table-bg: var(--ban-success-bg); --bs-table-color: var(--ban-success-fg); }
.table-warning { --bs-table-bg: var(--ban-warning-bg); --bs-table-color: var(--ban-warning-fg); }
.table-danger  { --bs-table-bg: var(--ban-danger-bg);  --bs-table-color: var(--ban-danger-fg); }
.table-info    { --bs-table-bg: var(--ban-info-bg);    --bs-table-color: var(--ban-ink); }
.table-primary { --bs-table-bg: var(--ban-green-050);  --bs-table-color: var(--ban-green-900); }
.table-dark {
  --bs-table-bg: var(--ban-deep); --bs-table-color: var(--ban-on-deep);
  --bs-table-border-color: var(--ban-deep-alt); --bs-table-striped-bg: var(--ban-deep-alt);
  --bs-table-hover-bg: var(--ban-deep-alt); --bs-table-hover-color: var(--ban-on-deep);
}
.table-light {
  --bs-table-bg: var(--ban-surface-alt); --bs-table-color: var(--ban-ink);
  --bs-table-border-color: var(--ban-border);
}

/* --- 11.4 Forms: checks, switches, input groups, validation ------------------------ */
.form-check-input {
  --bs-form-check-bg: var(--ban-surface);
  border-color: var(--ban-border-strong);
  width: 1.25rem; height: 1.25rem; margin-top: .15em;
}
.form-check-input:checked { background-color: var(--ban-green); border-color: var(--ban-green); }
.form-check-input:focus { border-color: var(--ban-green); box-shadow: 0 0 0 3px var(--ban-focus); }
.form-check-input[disabled] { background-color: var(--ban-surface-alt); border-color: var(--ban-border); }
.form-check-label { color: var(--ban-ink); }
.form-switch .form-check-input { width: 2.5rem; height: 1.4rem; }
/* The tick and the radio dot are images, so they cannot use a token directly — the colour is
   baked into the SVG. Each mark is therefore declared once per theme, using the *audited*
   pairing for that theme: white on --ban-green in light, and --ban-on-green on --ban-green in
   dark, where the fill is a lighter green and a white tick would all but disappear.
   Bootstrap's own marks are #0d6efd, which is exactly the stray blue this layer removes. */
.form-check-input:checked[type="checkbox"] {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23FFFFFF' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e");
}
.form-check-input[type="radio"]:checked {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%230E6B47'/%3e%3c/svg%3e");
}
@media (prefers-color-scheme: dark) {
  :root:not([data-bs-theme="light"]) .form-check-input:checked[type="checkbox"] {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%230F1A16' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e");
  }
  :root:not([data-bs-theme="light"]) .form-check-input[type="radio"]:checked {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%233FA97C'/%3e%3c/svg%3e");
  }
}
[data-bs-theme="dark"] .form-check-input:checked[type="checkbox"] {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%230F1A16' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e");
}
[data-bs-theme="dark"] .form-check-input[type="radio"]:checked {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%233FA97C'/%3e%3c/svg%3e");
}
.input-group-text {
  background: var(--ban-surface-alt); border-color: var(--ban-border-strong);
  color: var(--ban-ink-700); font-family: var(--ban-font-mono); font-size: var(--ban-fs-sm);
}
.form-control.is-valid, .form-select.is-valid { border-color: var(--ban-green-700); }
.form-control.is-valid:focus, .form-select.is-valid:focus { box-shadow: 0 0 0 3px var(--ban-focus); }
.form-control.is-invalid, .form-select.is-invalid { border-color: var(--ban-danger-fg); }
.form-control.is-invalid:focus, .form-select.is-invalid:focus { box-shadow: 0 0 0 3px var(--ban-danger-br); }
.valid-feedback { color: var(--ban-green-700); }
.invalid-feedback { color: var(--ban-danger-fg); }

/* --- 11.5 Progress, and the remaining small components ----------------------------- */
.progress {
  --bs-progress-bg: var(--ban-surface-alt);
  --bs-progress-bar-bg: var(--ban-green);
  --bs-progress-bar-color: var(--ban-on-green);
  --bs-progress-height: .75rem;
}
.progress-bar { font-size: var(--ban-fs-xs); font-weight: 700; }
.accordion {
  --bs-accordion-btn-color: var(--ban-ink);
  --bs-accordion-btn-bg: var(--ban-surface);
  --bs-accordion-active-color: var(--ban-green-900);
  --bs-accordion-active-bg: var(--ban-green-050);
  --bs-accordion-border-color: var(--ban-border);
  --bs-accordion-btn-focus-box-shadow: 0 0 0 3px var(--ban-focus);
}
.accordion-button:not(.collapsed) { box-shadow: inset 3px 0 0 var(--ban-green); }
.nav {
  --bs-nav-link-color: var(--ban-green);
  --bs-nav-link-hover-color: var(--ban-green-900);
  --bs-nav-link-disabled-color: var(--ban-ink-300);
}
.spinner-border { color: var(--ban-green); }
