/* ==========================================================================
   AXING custom stylesheet
   ========================================================================== */

/* --- Brand palette ------------------------------------------------------- */
:root {
  --ax: #009993;                            /* primary teal */
  --ax-rgb: 0, 153, 147;                    /* single source for rgba mixes */
  --ax-dark: #007a75;                       /* hover shade */
  --ax-dark-rgb: 0, 122, 117;
  --ax-light: #e8f4f4;                      /* lightest tint (light theme) */
  --ax-soft: rgba(var(--ax-rgb), 0.05);     /* very subtle teal wash */

  /* Brand tint scale — shades for Bootstrap subtle/emphasis variants */
  --ax-100: #ccebea;   /* bg-subtle on light */
  --ax-300: #80ccc9;   /* border-subtle */
  --ax-700: #00605d;   /* pressed/active */
  --ax-900: #003d3a;   /* text-emphasis on light */
  --ax-950: #001f1d;   /* deepest tint, used as bg-subtle on dark */
}

/* --- Transitions & focus rings ------------------------------------------ */
:root {
  --ax-trans-fast:   0.15s ease-in-out;
  --ax-trans-medium: 0.2s  ease-in-out;
  --ring-strong: 0 0 0 3px rgba(var(--ax-rgb), 0.25);  /* slimmer than BS default 0.25rem */
}

/* --- Layout ------------------------------------------------------------- */
:root {
  --ax-sidebar-width: 12rem;   /* .navbar-aside width at lg+ */
  --ax-footer-height: 5rem;    /* page-level <footer> + aside-footer */
}

/* --- Reserved tokens — not consumed in this template -------------------- */
/* Predefined for downstream apps (FTTR-Configurator, MIP-v2, etc.) so the
   visual language stays consistent across projects. Safe to ignore in this
   stylesheet but DO NOT remove without checking downstream usage. */
:root {
  --ring-focus:      0 0 0 3px rgba(var(--ax-rgb), 0.12);  /* reserved */
  --ring-danger:     0 0 0 3px rgba(220, 38, 38, 0.1);     /* reserved */
  --overlay-dark:    rgba(0, 0, 0, 0.4);                    /* reserved */
  --transition-fast: all 0.15s ease;                        /* reserved */

  /* Optical-budget segment palette (reserved) */
  --color-fiber:    #60a5fa;
  --color-splitter: #f97316;
  --color-conn:     #a78bfa;

  /* Topology signal palette — three of four reuse segment palette so the
     color language stays coherent across budget / BOM / topology (reserved) */
  --sig-internet: #3b82f6;
  --sig-combined: var(--color-conn);   /* purple — GPON + RF overlay (post-WDM) */
  --sig-pon:      var(--ax);
  --sig-rf:       var(--color-splitter);

  /* 15px — gap between body (16) and small (14), reserved */
  --fs-15: 15px;
}

/* --- Bootstrap theme tokens — light mode -------------------------------- */
/* Bootstrap references primary via CSS variables — we replace those
   globally here. Components with hardcoded colors get additional explicit
   overrides further below. */
:root {
  --bs-primary: var(--ax);
  --bs-primary-rgb: var(--ax-rgb);
  --bs-primary-text-emphasis: var(--ax-900);
  --bs-primary-bg-subtle: var(--ax-100);
  --bs-primary-border-subtle: var(--ax-300);

  --bs-link-color: var(--ax);
  --bs-link-color-rgb: var(--ax-rgb);
  --bs-link-hover-color: var(--ax-dark);
  --bs-link-hover-color-rgb: var(--ax-dark-rgb);

  /* Body text: higher contrast than BS defaults */
  --bs-body-color: #111;
  --bs-body-color-rgb: 17, 17, 17;

  /* Borders: slightly darker than BS default (#dee2e6) — sharper card
     and form-control edges against white surfaces */
  --bs-border-color: #ced4da;

  --bs-focus-ring-color: rgba(var(--ax-rgb), 0.25);  /* .focus-ring utility */

  /* Border-radius: BS default is 0.375rem (6px). Bumped to 0.5rem (8px) —
     softer, modern-app feel (Linear / Stripe / shadcn norm). Affects
     buttons, cards, inputs, alerts, modals, dropdowns, accordion etc.
     -sm raised from 0.25rem (4px) to 0.375rem (6px) so .btn-sm /
     .form-control-sm scale proportionally with the new base. -lg (8px)
     still collides with base; bump if needed. */
  --bs-border-radius: 0.5rem;
  --bs-border-radius-sm: 0.375rem;

  --bs-body-font-family: "Inter", system-ui, -apple-system, sans-serif;
  --bs-font-monospace: "Cascadia Code", "Cascadia Mono", SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}

/* --- Bootstrap theme tokens — dark mode --------------------------------- */
[data-bs-theme="dark"] {
  --ax-light: rgba(var(--ax-rgb), 0.12);
  --bs-primary-text-emphasis: var(--ax-300);
  --bs-primary-bg-subtle: var(--ax-950);
  --bs-primary-border-subtle: var(--ax-700);

  /* Link hover/active: lighten instead of darken (mirrors the
     outline-button + sidebar-nav-link pattern). Default --bs-link-color
     stays at --ax (visible enough on dark BG); hover lightens via
     --ax-300, the :active rule below pushes one step further. */
  --bs-link-hover-color: var(--ax-300);
  --bs-link-hover-color-rgb: 128, 204, 201;   /* = #80ccc9 = --ax-300 */

  /* Body text: lighter than BS default (#dee2e6), but not pure white */
  --bs-body-color: #fafafa;
  --bs-body-color-rgb: 250, 250, 250;

  /* Surface hierarchy: deeper dark than BS default, three clear levels.
     tertiary-bg = body (recessed), body-bg = cards/nav/inputs (elevated),
     secondary-bg = accents/hover/striped (top). Cool, neutral hue ~220°.
     --ax-surface-chrome is a 4th, deepest level used for the dark navbar. */
  --bs-tertiary-bg:      #13161a;
  --bs-tertiary-bg-rgb:  19, 22, 26;
  --bs-body-bg:          #1c1f23;
  --bs-body-bg-rgb:      28, 31, 35;
  --bs-secondary-bg:     #272a2e;
  --bs-secondary-bg-rgb: 39, 42, 46;
  --ax-surface-chrome:   #0d1017;

  /* Borders: darker than BS default (#495057) — blends more subtly between
     surface and accent, modern-app look instead of sharp lines */
  --bs-border-color: #33373c;
}


/* --- Base ---------------------------------------------------------------- */
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* Native-control accent — colors OS-rendered parts of <select> options
     (hover/selected highlight in dropdowns) and native range track,
     progress bar, and native checkbox/radio (the latter we've overridden
     via appearance:none, where this has no effect). */
  accent-color: var(--ax);
}

body {
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}

::selection {
  background: rgba(var(--ax-rgb), 0.25);
}

img, svg {
  display: block;
  max-width: 100%;
}

/* Anchored sections land below the sticky navbar instead of hiding under
   it. --ax-navbar-h is set by JS (offsetHeight + resize listener). */
section[id] {
  scroll-margin-top: calc(var(--ax-navbar-h, 56px) + 1rem);
}

/* Reserved for later use — uniform line-height across form controls + buttons.
.form-control,
.form-select:where(:not(.form-select-lg,.form-select-sm)),
.btn:where(:not(.btn-link,.btn-lg,.btn-sm)) { line-height: 1.375; } */


/* --- Bootstrap component overrides --------------------------------------- */
/* Buttons */
.btn-primary {
  --bs-btn-bg: var(--ax);
  --bs-btn-border-color: var(--ax);
  --bs-btn-hover-bg: var(--ax-dark);
  --bs-btn-hover-border-color: var(--ax-dark);
  --bs-btn-active-bg: var(--ax-700);
  --bs-btn-active-border-color: var(--ax-700);
  --bs-btn-disabled-bg: var(--ax);
  --bs-btn-disabled-border-color: var(--ax);
  --bs-btn-focus-shadow-rgb: var(--ax-rgb);
}
.btn-outline-primary {
  --bs-btn-color: var(--ax);
  --bs-btn-border-color: var(--ax);
  --bs-btn-hover-color: var(--ax-dark);
  --bs-btn-hover-bg: rgba(var(--ax-rgb), 0.07);
  --bs-btn-hover-border-color: var(--ax-dark);
  --bs-btn-active-color: var(--ax-700);
  --bs-btn-active-bg: rgba(var(--ax-rgb), 0.15);
  --bs-btn-active-border-color: var(--ax-700);
  --bs-btn-disabled-color: var(--ax);
  --bs-btn-disabled-border-color: var(--ax);
  --bs-btn-focus-shadow-rgb: var(--ax-rgb);
}
/* Outline buttons (all variants except primary): hover/active gets a
   subtle tint (7% / 15%) in the variant color instead of a full fill.
   Color + border also shift darker (18% / 32% black-mix). Primary uses
   its own scale (--ax-dark / --ax-700 + --ax-rgb wash) and is set
   explicitly above; the wildcard `[class*="btn-outline-"]` here matches
   any BS outline variant and the :not() excludes primary. */
[class*="btn-outline-"]:not(.btn-outline-primary) {
  --bs-btn-hover-bg:           color-mix(in srgb, var(--bs-btn-color) 7%, transparent);
  --bs-btn-active-bg:          color-mix(in srgb, var(--bs-btn-color) 15%, transparent);
  --bs-btn-hover-color:        color-mix(in srgb, var(--bs-btn-color), black 18%);
  --bs-btn-hover-border-color: color-mix(in srgb, var(--bs-btn-border-color), black 18%);
  --bs-btn-active-color:       color-mix(in srgb, var(--bs-btn-color), black 32%);
  --bs-btn-active-border-color: color-mix(in srgb, var(--bs-btn-border-color), black 32%);
}

/* Form controls — focus, checked checkbox/radio, range thumb.
   Focus pattern: BS' default :focus draws a blue ring on every click;
   we suppress that and draw our teal ring on :focus-visible instead.
   For text inputs, click also activates :focus-visible (typing intent
   counts as keyboard interaction) — so click+type still gets the ring.
   For checkboxes/radios/range, click alone no longer flashes the ring;
   keyboard nav (Tab/Space) does. Cleaner UX, still a11y-correct. */
.form-control:focus,     .form-control:focus-visible,
.form-select:focus,      .form-select:focus-visible,
.form-check-input:focus, .form-check-input:focus-visible {
  border-color: var(--ax);
}
.form-control:focus, .form-select:focus, .form-check-input:focus {
  box-shadow: none;
}
.form-control:focus-visible, .form-select:focus-visible, .form-check-input:focus-visible {
  box-shadow: var(--ring-strong);
}
.form-check {
  padding-left: 1.75em;
}
.form-check-input {
  width: 1.25em;
  height: 1.25em;
  margin-top: 0.125em;
}
.form-check .form-check-input {
  margin-left: -1.75em;
}
.form-switch {
  padding-left: 2.5em;
}
.form-switch .form-check-input {
  margin-left: -2.5em;
}
/* Form-switch: focus dot in teal instead of #86b7fe (--ax-300 = %2380ccc9 URL-encoded) */
.form-switch .form-check-input:focus {
  --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2380ccc9'/%3e%3c/svg%3e");
}
.form-check-input:checked {
  background-color: var(--ax);
  border-color: var(--ax);
}
.form-range::-webkit-slider-thumb        { background-color: var(--ax); }
.form-range::-moz-range-thumb            { background-color: var(--ax); }
.form-range::-webkit-slider-thumb:active { background-color: var(--ax-300); }
.form-range::-moz-range-thumb:active     { background-color: var(--ax-300); }
.form-range:focus::-webkit-slider-thumb  { box-shadow: none; }
.form-range:focus::-moz-range-thumb      { box-shadow: none; }
.form-range:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, var(--ring-strong); }
.form-range:focus-visible::-moz-range-thumb     { box-shadow: 0 0 0 1px #fff, var(--ring-strong); }

/* Components — focus & active-state overrides */
.dropdown-menu {
  --bs-dropdown-link-active-bg: var(--ax-soft);
  --bs-dropdown-link-active-color: inherit;
}
.nav-pills { --bs-nav-pills-link-active-bg: var(--ax); }
.pagination {
  --bs-pagination-color: var(--ax);
  --bs-pagination-hover-color: var(--ax-dark);
  --bs-pagination-focus-box-shadow: var(--ring-strong);
  --bs-pagination-active-bg: var(--ax);
  --bs-pagination-active-border-color: var(--ax);
}
.progress  { --bs-progress-bar-bg: var(--ax); }
.list-group {
  --bs-list-group-active-bg: var(--ax);
  --bs-list-group-active-border-color: var(--ax);
}
.accordion {
  --bs-accordion-btn-focus-box-shadow: var(--ring-strong);
  /* Active chevron in --ax-900 instead of BS blue (#052c65) */
  --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23003d3a' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}
.btn-close { --bs-btn-close-focus-shadow: var(--ring-strong); }
.btn-link  { --bs-btn-focus-shadow-rgb: var(--ax-rgb); }

/* .nav-link has no token for focus box-shadow — override directly */
.nav-link:focus-visible { box-shadow: var(--ring-strong); }


/* --- Aside layout (Pattern 1: header on top, sidebar left) ------------- */
/* Triggered by including a .navbar-aside element inside <body>. The body
   becomes a CSS Grid wrapper; header / aside / main / footer must be
   direct children. Header spans full width on top; aside sits left below
   header; main fills the rest; footer spans full width at the bottom.
   Mobile (<lg): grid collapses to one column, the aside falls back to a
   Bootstrap offcanvas drawer (slide-from-left) below the header.
   Switching back to a horizontal-navbar layout means restructuring the
   HTML — there's no CSS-only toggle. */
body:has(.navbar-aside) {
  display: grid;
  grid-template-areas:
    "header header"
    "aside  main"
    "aside  footer";
  grid-template-columns: var(--ax-sidebar-width) 1fr;
  grid-template-rows: auto 1fr auto;
  min-height: 100dvh;
}
body:has(.navbar-aside) > header         { grid-area: header; }
body:has(.navbar-aside) > .navbar-aside  { grid-area: aside; }
body:has(.navbar-aside) > main           { grid-area: main; }
body:has(.navbar-aside) > footer {
  grid-area: footer;
  height: var(--ax-footer-height);
  display: flex;
  align-items: center;
}

@media (max-width: 991.98px) {
  body:has(.navbar-aside) {
    grid-template-areas:
      "header"
      "main"
      "footer";
    grid-template-columns: 1fr;
  }
}

/* Sidebar styling — desktop only (≥lg). Below lg, .offcanvas-lg makes
   the element a fixed-position drawer (rules in the mobile-drawer block
   further down). Sticky so nav stays visible while main scrolls.
   `!important` on background-color is required because BS resets
   `.offcanvas-lg { background-color: transparent !important }` at ≥lg
   to unstyle the element when the drawer behavior is off — without
   !important, the recessed body color shows through and the aside no
   longer matches the navbar (white in light, chrome in dark). */
@media (min-width: 992px) {
  .navbar-aside {
    position: sticky;
    top: var(--ax-navbar-h, 56px);
    height: calc(100dvh - var(--ax-navbar-h, 56px));
    overflow-y: auto;
    border-right: 1px solid var(--bs-border-color);
    background-color: var(--bs-body-bg) !important;
  }
}

/* Aside body uses flex-column so the bottom nav-list (theme toggle) can
   be pushed against the bottom edge with mt-auto. height: 100% is
   needed at ≥lg because then BS does NOT make .offcanvas-lg a flex
   parent — without an explicit height, the body would only be as tall
   as its content and mt-auto would have nothing to push against. */
.navbar-aside .offcanvas-body {
  display: flex;
  flex-direction: column;
  height: 100%;
}

/* Aside footer (theme-toggle row at the bottom): full-width border-top
   that escapes the parent's .p-3 horizontal padding via negative margin,
   matched by re-added internal padding so the toggle button sits at the
   same indent as the nav items above. Fixed 6rem height to mirror the
   page-level <footer>. */
.navbar-aside-footer {
  margin: 0 -1rem -1rem;       /* escape parent .p-3 horizontally + bottom — */
  padding: 0 1rem;             /* re-add internal horizontal padding only.    */
  height: var(--ax-footer-height);
  border-top: 1px solid var(--bs-border-color);
  justify-content: center;     /* center single LI vertically (column flex from .navbar-nav) */
}

/* Sidebar nav-link look: subtle "subdued default → brighter on
   interaction" pattern (mirrors BS' original navbar text-color ramp,
   theme-aware via --bs-secondary-color → --bs-emphasis-color). Active
   item uses the brand teal as the accent. */
.navbar-aside .nav-link {
  border-radius: var(--bs-border-radius-sm);
  padding: 0.5rem 0.75rem;
  color: var(--bs-secondary-color);
}
.navbar-aside .nav-link:hover {
  background-color: var(--ax-soft);
  color: var(--bs-emphasis-color);
}
.navbar-aside .nav-link.active {
  background-color: rgba(var(--ax-rgb), 0.10);
  color: var(--ax);
  font-weight: 600;
}

/* --- Navbar (header & mobile drawer) ------------------------------------ */
/* Logo size: pinned to 28px height via CSS (in addition to the HTML
   `height="28"` attribute) so the PNG natural dimensions can't override
   it through the global `img { max-width: 100% }` reset. */
.navbar-brand img {
  height: 28px;
  width: auto;
}

/* Responsive logo swap:
   - <lg: compact 'a' mark (single PNG, theme-agnostic)
   - ≥lg: full AXING wordmark via i-version SVGs, theme-aware
   The .logo-light / .logo-dark helper classes are kept available for
   downstream apps that want this same swap on the i-version (or any
   other theme-aware asset). */
.navbar-brand .logo-light,
.navbar-brand .logo-dark {
  display: none;  /* hidden by default; ≥lg shows one based on theme */
}
@media (min-width: 992px) {
  .navbar-brand .logo-light { display: inline; }
  [data-bs-theme="dark"] .navbar-brand .logo-light { display: none; }
  [data-bs-theme="dark"] .navbar-brand .logo-dark  { display: inline; }
}
/* Dark-mode workaround for the 'a' PNG (axing-logo-a.png) — only one
   variant exists, so we flip its luminosity on dark BG. `invert(1)`
   alone would also flip the brand-teal hue to red-orange; pairing it
   with `hue-rotate(180deg)` restores the original hue while keeping the
   brightness inverted (black → white, teal stays teal). The i-SVGs
   handle dark mode natively via the swap above and aren't affected. */
[data-bs-theme="dark"] .navbar-brand .d-lg-none {
  filter: invert(1) hue-rotate(180deg);
}

/* Navbar toggler:
   - Hamburger ↔ X crossfade. Both icons stack inside the same 24×24
     wrapper; aria-expanded triggers the CSS transitions (opacity +
     rotation). The attribute is set via JS — Bootstrap's offcanvas does
     not maintain aria-expanded on the toggler itself.
   - Color pulled to --bs-body-color instead of BS' default
     --bs-navbar-color (rgba(emphasis, 0.65)) — the toggler is a primary
     UI element on mobile and shouldn't look de-emphasized. */
.navbar-toggler {
  color: var(--bs-body-color);
  display: flex;
  align-items: center;
  justify-content: center;
}
.navbar-toggler-icons {
  position: relative;
  display: inline-block;
  width: 32px;
  height: 32px;
}
.navbar-toggler-icons .ico {
  position: absolute;
  inset: 0;
  transition: opacity var(--ax-trans-medium), transform var(--ax-trans-medium);
}
.navbar-toggler-icons .ico-close {
  opacity: 0;
  transform: rotate(-90deg);
}
.navbar-toggler[aria-expanded="true"] .ico-hamburger {
  opacity: 0;
  transform: rotate(90deg);
}
.navbar-toggler[aria-expanded="true"] .ico-close {
  opacity: 1;
  transform: rotate(0);
}

/* Mobile drawer: aside slides in from the left, sitting below the sticky
   header. Active under lg (.offcanvas-lg makes the element fixed); from
   lg up, the aside is inline in the grid and these rules are irrelevant.
   The --ax-navbar-h var is set by JS because the navbar height depends
   on logo + padding and can change on resize. We use BS' default
   slide-from-left animation — no need to kill the transform here (the
   conflict with the sticky header that we had on offcanvas-top doesn't
   exist when sliding horizontally). */
@media (max-width: 991.98px) {
  #mainNav.offcanvas-lg {
    --bs-offcanvas-zindex: 1015;     /* below sticky-top header (1020) */
    top: var(--ax-navbar-h, 56px);
    height: calc(100dvh - var(--ax-navbar-h, 56px));
    border: 0;
  }
}


/* --- Scrollbar ----------------------------------------------------------- */
/* One custom-scrollbar look shared by the document viewport and the
   sidebar: thin rail, transparent track, muted thumb that darkens on
   hover. html + body are both styled because the document scrollbar
   "propagates" from one or the other depending on browser/layout — in
   the grid layout in particular some browsers route it via <html>, so
   only styling <body> leaves the viewport scrollbar unthemed. WebKit
   (Chrome/Edge/Safari) uses the ::-webkit-scrollbar pseudos; Firefox
   uses scrollbar-width + scrollbar-color. */
html,
body,
.sidebar {
  scrollbar-width: thin;
  scrollbar-color: var(--bs-border-color) transparent;
}

html::-webkit-scrollbar,
body::-webkit-scrollbar,
.sidebar::-webkit-scrollbar {
  width: 0.5rem;
}

html::-webkit-scrollbar-track,
body::-webkit-scrollbar-track,
.sidebar::-webkit-scrollbar-track {
  background: transparent;
}

html::-webkit-scrollbar-thumb,
body::-webkit-scrollbar-thumb,
.sidebar::-webkit-scrollbar-thumb {
  background: var(--bs-border-color);
  border-radius: 0.25rem;
}

html::-webkit-scrollbar-thumb:hover,
body::-webkit-scrollbar-thumb:hover,
.sidebar::-webkit-scrollbar-thumb:hover {
  background: var(--bs-secondary-color);
}


/* --- Heading scale (compact, gentle fluid) ------------------------------- */
/* Tighter scale than BS default: h3/h4 -4px each, h5 = body (16px),
   h6 = small (14px). .fs-1…-6 are overridden alongside so that
   <h5 class="fs-5"> doesn't suddenly diverge from <h5>. Weight 500 →
   600, because h5 = body size now and otherwise wouldn't stand out
   visually.

   Fluid scaling via clamp(min, calc, max) — slopes are half BS' default
   (1 / 0.75 / 0.5 / 0.25 vw) so headings grow with viewport width but
   less aggressively. Bases are picked so the calc value AT 1200px equals
   the desktop max — no step at the lock point. Above 1200px the max kicks
   in and the size is fixed.
   Targets at 1200px: h1=40 / h2=32 / h3=24 / h4=20 / h5=16 / h6=14.
   Mobile (375px viewport): h1≈31.75 / h2≈25.8 / h3≈19.9 / h4≈17.9. */

h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6 {
  font-weight: 600;
}

h1, .h1, .fs-1 { font-size: clamp(1.75rem,   calc(1.75rem   + 1vw),    2.5rem);  }
h2, .h2, .fs-2 { font-size: clamp(1.4375rem, calc(1.4375rem + 0.75vw), 2rem);    }
h3, .h3, .fs-3 { font-size: clamp(1.125rem,  calc(1.125rem  + 0.5vw),  1.5rem);  }
h4, .h4, .fs-4 { font-size: clamp(1.0625rem, calc(1.0625rem + 0.25vw), 1.25rem); }
h5, .h5, .fs-5 { font-size: 1rem;     }
h6, .h6, .fs-6 { font-size: 0.875rem; }


/* --- Dark mode component overrides -------------------------------------- */
/* All [data-bs-theme="dark"] component-level rules grouped here. Token
   overrides for dark mode live with the other :root tokens at the top.
   (Note: the responsive logo light/dark swap is up in the navbar
   section, scoped to .navbar-brand and the lg breakpoint.) */

/* Sidebar nav-link active state in dark mode: brand teal goes one step
   lighter (--ax-300 instead of --ax) and the bg wash gets bumped, since
   alpha looks dimmer on dark BG. Default and hover colors don't need a
   dark override — they use --bs-secondary-color / --bs-emphasis-color
   which are already theme-aware. */
[data-bs-theme="dark"] .navbar-aside .nav-link.active {
  background-color: rgba(var(--ax-rgb), 0.18);
  color: var(--ax-300);
}

/* Plain <a> :active in dark mode — BS has no token for this state, so
   we set color directly. Pushes one step beyond the hover color for a
   subtle "you clicked it" cue. */
[data-bs-theme="dark"] a:active {
  color: var(--ax-100);
}

/* Navbar + sidebar: deeper than body — clearer "chrome strip" feel and
   keeps header / sidebar visually unified as a single chrome layer.
   .bg-body uses !important (BS), so the navbar rule needs it here too;
   .navbar-aside doesn't, but we share the value via the same custom
   token. */
[data-bs-theme="dark"] .navbar.bg-body {
  background-color: var(--ax-surface-chrome) !important;
}
[data-bs-theme="dark"] .navbar-aside {
  background-color: var(--ax-surface-chrome) !important;
}

/* Accordion chevron — both states, because BS in dark overrides both
   to light blue. Selector matches BS' own
   [data-bs-theme=dark] .accordion-button::after */
[data-bs-theme="dark"] .accordion-button::after {
  --bs-accordion-btn-icon:        url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2380ccc9' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
  --bs-accordion-btn-active-icon: var(--bs-accordion-btn-icon);
}

/* Outline buttons — invert the interaction model. In light mode we
   darken color/border on hover/active for more contrast on white BG.
   On dark BG that makes buttons LESS visible, so we mirror nav-link's
   "dim default → bright on interaction" pattern instead: opacity 0.95
   at rest (parallels --bs-navbar-color's rgba alpha trick), full
   opacity + lightened color on :hover/:focus-visible/:active. Bg tint
   bumped slightly (10%/20% vs 7%/15%) because alpha looks dimmer on
   dark BG. */
[data-bs-theme="dark"] [class*="btn-outline-"] {
  opacity: 0.95;
  /* Re-list BS' own button transition to keep color/bg/border smooth and
     add opacity. `transition` is not additive — overriding requires the
     full list. */
  transition: color var(--ax-trans-fast),
              background-color var(--ax-trans-fast),
              border-color var(--ax-trans-fast),
              box-shadow var(--ax-trans-fast),
              opacity var(--ax-trans-fast);
}
[data-bs-theme="dark"] [class*="btn-outline-"]:is(:hover, :focus-visible, :active, .active) {
  opacity: 1;
}
[data-bs-theme="dark"] .btn-outline-primary {
  --bs-btn-hover-color:        var(--ax-300);
  --bs-btn-hover-bg:           rgba(var(--ax-rgb), 0.10);
  --bs-btn-hover-border-color: var(--ax-300);
  --bs-btn-active-color:       var(--ax-100);
  --bs-btn-active-bg:          rgba(var(--ax-rgb), 0.20);
  --bs-btn-active-border-color: var(--ax-100);
}
[data-bs-theme="dark"] [class*="btn-outline-"]:not(.btn-outline-primary) {
  --bs-btn-hover-bg:            color-mix(in srgb, var(--bs-btn-color) 10%, transparent);
  --bs-btn-active-bg:           color-mix(in srgb, var(--bs-btn-color) 20%, transparent);
  --bs-btn-hover-color:         color-mix(in srgb, var(--bs-btn-color), white 28%);
  --bs-btn-hover-border-color:  color-mix(in srgb, var(--bs-btn-border-color), white 28%);
  --bs-btn-active-color:        color-mix(in srgb, var(--bs-btn-color), white 45%);
  --bs-btn-active-border-color: color-mix(in srgb, var(--bs-btn-border-color), white 45%);
}
/* Default-state color brightening: lift the variant color ~15% toward
   white so the resting state pops more on dark BG. We can't override
   --bs-btn-color via color-mix(... var(--bs-btn-color) ...) (CSS treats
   that as a self-reference and drops it), so instead set `color` /
   `border-color` directly. The :not() chain scopes this to the resting
   state — hover/active keep their own brighter colors via the regular
   --bs-btn-hover-color / --bs-btn-active-color cascade. */
[data-bs-theme="dark"] [class*="btn-outline-"]:not(:hover):not(:focus-visible):not(:active):not(.active) {
  color:        color-mix(in srgb, var(--bs-btn-color), white 15%);
  border-color: color-mix(in srgb, var(--bs-btn-border-color), white 15%);
}

/* Filled buttons — subtle "darker default → normal hover → slightly
   brighter active" progression, mirroring the outline / nav-link
   pattern but with smaller steps (±5%) so the white button label keeps
   enough contrast against the bg. Opacity 0.95 → 1 reinforces the lift.
   Hover bg falls back to the original BS variant color (read from
   --bs-btn-bg via the cascade), so hover effectively *removes* the
   default-state darkening rather than going darker as in light mode. */
[data-bs-theme="dark"] :is(.btn-primary, .btn-secondary, .btn-success,
                           .btn-danger, .btn-warning, .btn-info,
                           .btn-light, .btn-dark) {
  --bs-btn-hover-bg:            var(--bs-btn-bg);
  --bs-btn-hover-border-color:  var(--bs-btn-border-color);
  --bs-btn-active-bg:           color-mix(in srgb, var(--bs-btn-bg), white 5%);
  --bs-btn-active-border-color: color-mix(in srgb, var(--bs-btn-border-color), white 5%);
  opacity: 0.95;
  /* Re-list BS' button transition + opacity (transition is not additive). */
  transition: color var(--ax-trans-fast),
              background-color var(--ax-trans-fast),
              border-color var(--ax-trans-fast),
              box-shadow var(--ax-trans-fast),
              opacity var(--ax-trans-fast);
}
[data-bs-theme="dark"] :is(.btn-primary, .btn-secondary, .btn-success,
                           .btn-danger, .btn-warning, .btn-info,
                           .btn-light, .btn-dark):is(
                           :hover, :focus-visible, :active, .active) {
  opacity: 1;
}
/* Default-state -5% darken: same trick as for outlines — set
   background-color / border-color directly (overriding --bs-btn-bg via
   color-mix(... var(--bs-btn-bg) ...) would self-reference). :not()
   chain scopes to the resting state. */
[data-bs-theme="dark"] :is(.btn-primary, .btn-secondary, .btn-success,
                           .btn-danger, .btn-warning, .btn-info,
                           .btn-light, .btn-dark):not(
                           :hover):not(:focus-visible):not(:active):not(.active) {
  background-color: color-mix(in srgb, var(--bs-btn-bg), black 5%);
  border-color:     color-mix(in srgb, var(--bs-btn-border-color), black 5%);
}
