/*
 * SPDX-FileCopyrightText: 2026 fuddlesworth
 * SPDX-License-Identifier: GPL-3.0-or-later
 *
 * Phosphor brand overrides for doxygen-awesome-css v2.x.
 *
 * doxygen-awesome scopes its dark values under THREE separate
 * selectors — the overrides below mirror all three so our custom
 * palette wins in every theme source-of-truth path:
 *
 *   html                                     — light defaults
 *   @media (prefers-color-scheme: dark)
 *     html:not(.light-mode)                  — OS dark mode (no override)
 *   html.dark-mode                           — user-selected dark via toggle
 *
 * Missing any one of the three leaves a path where doxygen-awesome's
 * own dark palette wins (higher specificity) — that's why inline
 * <code> was rendering with a light background on a dark OS earlier.
 *
 * Variable names below all exist in doxygen-awesome.css (grep
 * --code-*, --fragment-*, --side-nav-*, etc.).  Phosphor brand colors
 * track data/palettes/phosphor.toml.
 */

/* ══════════════════════════════════════════════════════════════════════
   LIGHT — html default
   ══════════════════════════════════════════════════════════════════════ */
html {
    /* ─── Typography ─── */
    --font-family:             'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --font-family-monospace:   'JetBrains Mono', 'Fira Code', ui-monospace, monospace;

    /* ─── Primary accent — blue-500 ─── */
    --primary-color:           #3B82F6;
    --primary-dark-color:      #1E3A8A;
    --primary-light-color:     #DBEAFE;

    /* ─── Page chrome ─── */
    --page-background-color:           #F8FAFC;
    --page-foreground-color:           #050916;
    --page-secondary-foreground-color: #64748B;
    --separator-color:                 #E2E8F0;

    /* ─── Inline code (backtick text in Markdown, <code> tags) ───
       Previously illegible when doxygen-awesome's dark-mode default
       won: we set only `html` and `html.dark-mode`, missing the
       `@media prefers-color-scheme` path. */
    --code-background:  rgba(59, 130, 246, 0.08);   /* subtle blue tint */
    --code-foreground:  #1E3A8A;                    /* deep blue */

    /* ─── Fragment (pre-formatted code blocks) ─── */
    --fragment-background:         #F1F5F9;
    --fragment-foreground:         #0B1730;
    --fragment-keyword:            #7C3AED;   /* violet-600 */
    --fragment-keywordtype:        #0891B2;   /* cyan-600 */
    --fragment-keywordflow:        #E11D48;   /* rose-600 */
    --fragment-token:              #10B981;   /* emerald-500 */
    --fragment-comment:            #64748B;
    --fragment-link:               #3B82F6;
    --fragment-preprocessor:       #A855F7;
    --fragment-linenumber-color:       #94A3B8;
    --fragment-linenumber-background:  #EEF2F7;
    --fragment-linenumber-border:      #CBD5E1;

    /* ─── Tables (markdown + doxtable + fieldtable) ─── */
    --tablehead-background:   #EEF2F7;
    --tablehead-foreground:   #050916;
    --odd-color:              #FAFBFC;

    /* ─── Top nav / header band ─── */
    --header-background:             #FFFFFF;
    --header-foreground:             #050916;

    /* ─── Side nav (treeview) ─── */
    --side-nav-background:           #F1F5F9;
    --side-nav-foreground:           #050916;
    --side-nav-arrow-color:          #3B82F6;
    --side-nav-arrow-selected-color: #3B82F6;

    /* ─── Search box ─── */
    --searchbar-background:   #FFFFFF;
    --searchbar-foreground:   #050916;
    --searchbar-border-color: #E2E8F0;

    /* ─── Dropdown menus ─── */
    --menu-focus-foreground:  #FFFFFF;
    --menu-focus-background:  #3B82F6;
    --menu-selected-background: #DBEAFE;

    /* ─── Doxygen callouts (@note, @warning, etc.) ─── */
    --note-color:       #0EA5E9;   /* sky — neutral informational */
    --warning-color:    #F59E0B;   /* amber */
    --bug-color:        #E11D48;   /* rose */
    --deprecated-color: #A855F7;   /* purple */
    --todo-color:       #22D3EE;   /* cyan */
    --invariant-color:  #10B981;   /* emerald */

    /* ─── Blockquote ─── */
    --blockquote-background:   #F1F5F9;
    --blockquote-foreground:   #1E293B;

    /* ─── TOC ─── */
    --toc-background:   #F1F5F9;
    --toc-foreground:   #050916;

    --webkit-scrollbar-color: #CBD5E1;
}

/* ══════════════════════════════════════════════════════════════════════
   DARK — system preference (no user toggle override)
   ══════════════════════════════════════════════════════════════════════ */
@media (prefers-color-scheme: dark) {
    html:not(.light-mode) {
        --primary-color:      #60A5FA;          /* blue-400 (AA on dark bg) */
        --primary-dark-color: #3B82F6;
        --primary-light-color:#1E3A8A;

        --page-background-color:           #050916;
        --page-foreground-color:           #E6EDFF;
        --page-secondary-foreground-color: #94A3B8;
        --separator-color:                 #1E293B;

        /* Inline code — cyan tint on near-black */
        --code-background:    rgba(34, 211, 238, 0.12);
        --code-foreground:    #67E8F9;          /* cyan-300 */

        --fragment-background:         #070F22;
        --fragment-foreground:         #E6EDFF;
        --fragment-keyword:            #C084FC;   /* purple-400 */
        --fragment-keywordtype:        #22D3EE;   /* cyan-400 */
        --fragment-keywordflow:        #FB7185;   /* rose-400 */
        --fragment-token:              #34D399;   /* emerald-400 */
        --fragment-comment:            #64748B;
        --fragment-link:               #60A5FA;
        --fragment-preprocessor:       #A855F7;
        --fragment-linenumber-color:       #475569;
        --fragment-linenumber-background:  #0B1730;
        --fragment-linenumber-border:      #1E293B;

        --tablehead-background:   #0B1730;
        --tablehead-foreground:   #E6EDFF;
        --odd-color:              #080F22;

        --header-background:             #0B1730;
        --header-foreground:             #E6EDFF;

        --side-nav-background:           #070F22;
        --side-nav-foreground:           #E6EDFF;
        --side-nav-arrow-color:          #22D3EE;
        --side-nav-arrow-selected-color: #22D3EE;

        --searchbar-background:   #0B1730;
        --searchbar-foreground:   #E6EDFF;
        --searchbar-border-color: #1E293B;

        --menu-focus-foreground:  #050916;
        --menu-focus-background:  #22D3EE;
        --menu-selected-background: #1E3A8A;

        --note-color:       #60A5FA;
        --warning-color:    #FCD34D;
        --bug-color:        #FB7185;
        --deprecated-color: #C084FC;
        --todo-color:       #67E8F9;
        --invariant-color:  #34D399;

        --blockquote-background:   #0B1730;
        --blockquote-foreground:   #CBD5E1;

        --toc-background:   #0B1730;
        --toc-foreground:   #E6EDFF;

        --webkit-scrollbar-color: #1E293B;
    }
}

/* ══════════════════════════════════════════════════════════════════════
   DARK — user-selected (localStorage-backed toggle)
   Same values as the prefers-color-scheme block; duplicated because
   doxygen-awesome itself uses two separate selectors and either one
   can be the active source of truth at any moment.
   ══════════════════════════════════════════════════════════════════════ */
html.dark-mode {
    --primary-color:      #60A5FA;
    --primary-dark-color: #3B82F6;
    --primary-light-color:#1E3A8A;

    --page-background-color:           #050916;
    --page-foreground-color:           #E6EDFF;
    --page-secondary-foreground-color: #94A3B8;
    --separator-color:                 #1E293B;

    --code-background:    rgba(34, 211, 238, 0.12);
    --code-foreground:    #67E8F9;

    --fragment-background:         #070F22;
    --fragment-foreground:         #E6EDFF;
    --fragment-keyword:            #C084FC;
    --fragment-keywordtype:        #22D3EE;
    --fragment-keywordflow:        #FB7185;
    --fragment-token:              #34D399;
    --fragment-comment:            #64748B;
    --fragment-link:               #60A5FA;
    --fragment-preprocessor:       #A855F7;
    --fragment-linenumber-color:       #475569;
    --fragment-linenumber-background:  #0B1730;
    --fragment-linenumber-border:      #1E293B;

    --tablehead-background:   #0B1730;
    --tablehead-foreground:   #E6EDFF;
    --odd-color:              #080F22;

    --header-background:             #0B1730;
    --header-foreground:             #E6EDFF;

    --side-nav-background:           #070F22;
    --side-nav-foreground:           #E6EDFF;
    --side-nav-arrow-color:          #22D3EE;
    --side-nav-arrow-selected-color: #22D3EE;

    --searchbar-background:   #0B1730;
    --searchbar-foreground:   #E6EDFF;
    --searchbar-border-color: #1E293B;

    --menu-focus-foreground:  #050916;
    --menu-focus-background:  #22D3EE;
    --menu-selected-background: #1E3A8A;

    --note-color:       #60A5FA;
    --warning-color:    #FCD34D;
    --bug-color:        #FB7185;
    --deprecated-color: #C084FC;
    --todo-color:       #67E8F9;
    --invariant-color:  #34D399;

    --blockquote-background:   #0B1730;
    --blockquote-foreground:   #CBD5E1;

    --toc-background:   #0B1730;
    --toc-foreground:   #E6EDFF;

    --webkit-scrollbar-color: #1E293B;
}

/* ══════════════════════════════════════════════════════════════════════
   Phosphor topbar (injected by docs/header.html above Doxygen content)
   ══════════════════════════════════════════════════════════════════════

   Mirrors src/styles/home.css::.pz-topbar so the Astro topbar and the
   doxygen topbar render identically.  Colors route through
   doxygen-awesome's own CSS vars (--page-background-color /
   --page-foreground-color / --primary-color) so theme toggle flips
   both at once, without needing a second set of phosphor-* tokens.

   flex-wrap: wrap + min-height keeps the bar legible when the full
   link set can't fit on one row (narrow viewports, doxygen-awesome's
   mobile mode < 768px).  A pz-topbar that silently clips its first
   item — which was what made only "Ph" visible in the recent bug
   report — loses the primary home link, so never nowrap here. */
.pz-topbar {
    /* !important on display + box-sizing because doxygen-awesome's
       cascade has several `nav` / generic flex rules further down
       the file that can clobber these at random viewport widths,
       squeezing the bar to a ~15px sliver.  Height is explicit so
       min-height isn't needed. */
    display: flex !important;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    padding: 10px 24px;
    min-height: 48px;
    box-sizing: border-box;
    font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
    font-size: 13px;
    /* Solid side-nav background (same as doxygen uses for the left
       column below) instead of color-mix transparency — the
       transparent version blended into the page bg and made the
       bar visually disappear. */
    background: var(--side-nav-background, var(--page-background-color));
    color: var(--page-foreground-color);
    border-bottom: 1px solid var(--separator-color, #1E293B);
    position: sticky;
    top: 0;
    z-index: 1000;
}
/* On narrow viewports hide the non-essential pz-link entries so the
   first row keeps showing the home brand + crumb + spacer + search +
   theme toggle.  Users still reach those sections via the site-search
   hand-off or by visiting the Astro pages directly. */
@media (max-width: 720px) {
    .pz-topbar .pz-link { display: none; }
    .pz-topbar .pz-link[href*="github.com"] { display: inline; }
}
.pz-home {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--primary-color);
    text-decoration: none;
    font-weight: 600;
}
.pz-home:hover { color: var(--primary-dark-color, #93C5FD); }
.pz-sep      { color: #475569; }
.pz-crumb    { color: #94A3B8; }
.pz-spacer   { flex: 1; }
.pz-link {
    color: var(--primary-color);
    text-decoration: none;
    font-size: 12px;
    font-weight: 500;
}
.pz-link:hover { color: var(--primary-dark-color, #93C5FD); text-decoration: underline; }

/* Inner "window" of the Phi mark — follows the page background so
   the square disappears into the topbar on both themes. */
.pz-topbar-inner { fill: var(--page-background-color); }

/* Skip-to-content link.  Hidden off-screen by default; pops back in
   when keyboard focus lands on it (first tab stop on every doxygen
   page). */
.skip-link {
    position: fixed;
    top: 8px;
    left: 8px;
    padding: 8px 14px;
    background: var(--primary-color);
    color: var(--page-background-color);
    font-weight: 600;
    text-decoration: none;
    border-radius: 8px;
    z-index: 2000;
    transform: translateY(calc(-100% - 16px));
    transition: transform 0.15s ease;
}
.skip-link:focus,
.skip-link:focus-visible {
    transform: translateY(0);
    outline: 2px solid var(--page-foreground-color);
    outline-offset: 2px;
}

/* Site-search hand-off link in the doxygen topbar.  Shaped like the
   Astro SiteSearch trigger so the two look and act identical — the
   href jumps to a site page that auto-opens Pagefind on #search. */
.site-search-trigger {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 4px 10px 4px 8px;
    background: transparent;
    border: 1px solid var(--separator-color, #1E293B);
    border-radius: 8px;
    color: #94A3B8;
    font-size: 12px;
    text-decoration: none;
    transition: border-color 0.15s ease, color 0.15s ease;
}
.site-search-trigger:hover {
    border-color: var(--primary-color);
    color: var(--page-foreground-color);
}
.site-search-label { line-height: 1; }
@media (max-width: 800px) {
    .site-search-label { display: none; }
}

/* Theme toggle — shaped identical to the Astro ThemeToggle button.
   Shows the moon icon in dark mode (click to go light) and the sun
   in light mode (click to go dark), matching the site convention. */
.site-theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    background: transparent;
    border: 1px solid var(--separator-color, #1E293B);
    border-radius: 8px;
    color: #94A3B8;
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease;
}
.site-theme-toggle:hover {
    border-color: var(--primary-color);
    color: var(--page-foreground-color);
}
.site-theme-icon { display: none; }
html[data-theme="dark"]  .site-theme-icon-light { display: block; }
html[data-theme="light"] .site-theme-icon-dark  { display: block; }

/* Global focus-visible ring — matches home.css so keyboard users
   get a consistent affordance across the site ↔ doxygen boundary. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
    border-radius: 4px;
}

/* ── Doxygen #top: slim down (keep doxygen search) ────────────
   #top hosts the MSearchBox (doxygen's own symbol search).  We
   KEEP doxygen search — it's excellent for API lookups — so we
   can't `display: none` #top wholesale.  Instead:
     • Hide only the redundant #projectrow (project logo + name +
       brief), since .pz-topbar already shows that info above.
     • Collapse --top-height to just the search-input height so
       there's no ghost whitespace under #top.
   An earlier pass `display: none`'d #top entirely.  That broke
   doxygen-awesome's layout assumptions — the #MSearchSelectWindow
   and #MSearchResultsWindow popups (siblings of #top inside
   #container, but anchored by #top's presence) stranded at
   viewport 0,0 and drew as a thin strip down the left edge. */

#projectrow {
    display: none !important;
}

html {
    --top-height: 56px;
}

#titlearea { padding: 6px 12px !important; }
#titlearea table { margin: 0; width: 100%; }

/* Search popups are supposed to stay display:none until the user
   types in #MSearchField.  Belt-and-suspenders: pin them out of
   flow so any leftover positioning quirks can't paint them on
   the left edge.  Doxygen's searchBox JS sets inline style to
   open them, which overrides these. */
#MSearchSelectWindow,
#MSearchResultsWindow {
    display: none;
}

/* navtree.css sets `border-radius: 0 6px 6px 0` on the selected
   row, which carves a visible 6px arc out of the top-right corner
   of the highlight — under the slim #top above it that arc reads
   as a mystery "curved spot above the highlighted row".  Flatten
   to a simple rectangle so the selection fills the whole row and
   sits flush with the sidebar column chrome. */
#nav-tree .selected {
    border-radius: 0 !important;
}

/* Hide the nav-tree sync indicator ( `#nav-sync` is an absolutely-
   positioned widget doxygen injects at the top-right of the tree
   for a "jump to current page" action we don't use). */
#nav-sync {
    display: none !important;
}

/* #main-nav is an empty <div> that lives INSIDE #top, right after
   #titlearea.  doxygen-awesome gives it `padding: var(--spacing-small)
   var(--spacing-medium)` — on FULL_SIDEBAR pages where SmartMenus
   items are hidden (--menu-display: none from sidebar-only.css),
   the div is empty but still reserves ~16px of padded height
   below the search input.  That 16px strip, with a different
   background-blend from the surrounding sidebar column, was what
   drew as a mystery "curved spot above the highlighted row".
   Hide it outright. */
#main-nav {
    display: none !important;
}

/* Belt-and-suspenders: clip anything overflowing #top + kill any
   stray pseudo-element chrome near the top of the nav tree. */
#top { overflow: hidden; }
#nav-tree::before,
#nav-tree::after,
#nav-tree-contents::before,
#nav-tree-contents::after {
    display: none !important;
}

/* At sidebar-only breakpoint, .pz-topbar is sticky at y=0 (~48px)
   and #top sits directly under it in normal flow.  The fixed
   #side-nav's `top: var(--top-height)` needs to account for BOTH
   the pz-topbar height AND the reserved #top height so the
   sidebar starts at y=48+56=104 — otherwise it slides under #top
   and the MSearchBox goes missing. */
@media screen and (min-width: 768px) {
    #side-nav {
        top: calc(48px + var(--top-height)) !important;
    }
    #nav-tree,
    #side-nav {
        height: calc(100vh - 48px - var(--top-height)) !important;
    }
    #doc-content { padding-top: 0 !important; }
    #top { max-width: var(--side-nav-fixed-width); }
}

/* Phosphor footer band was removed — duplicated the Home/Palette/GitHub
   links that already live in the sticky .pz-topbar, and its render
   position clashed with Doxygen's fixed #nav-path breadcrumb.  The
   class rules below kept in case a future page re-adds the element. */

/* ══════════════════════════════════════════════════════════════════════
   Targeted fixes that don't go through CSS variables
   ══════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════
   Stop literal-white leaks from doxygen.css
   ══════════════════════════════════════════════════════════════════════
   The default doxygen.css ships a handful of hard-coded `white`
   backgrounds that doxygen-awesome doesn't fully shadow:
     body { background-color: white; }
     .classindex dl.even { background-color: white; }
     h2.groupheader { box-shadow: 12px 0 white, -12px 0 white, ... }
     td h2.groupheader { box-shadow: 13px 0 white, ... }
     span.tt { background-color: #FBFCFD; }
   Any of these wins when my overrides don't match precisely — and
   when the html element has no background, the viewport outside the
   body shows bare white too.  These rules nail down every source.
*/

/* Paint html + body the same as the page bg so the viewport margins
   don't flash white when body is narrower than the window. */
html,
body {
    background-color: var(--page-background-color) !important;
}

/* Tell the browser to paint scrollbars + form controls in dark mode
   when appropriate — otherwise the OS scrollbar stays white against
   the dark page (which reads as the "solid white vertical strip"
   running down the right edge). */
html.dark-mode {
    color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
    html:not(.light-mode) {
        color-scheme: dark;
    }
}

/* Classindex stripe colors — swap the literal-white from doxygen.css
   for our themed odd/even colors. */
.classindex dl.even,
.classindex dl.odd {
    background-color: var(--odd-color) !important;
}

/* Doxygen 1.16's per-page nav (the right-side mini-TOC that shows
   members of the current page).  navtree.css paints it with LITERAL
   light colors — background #F9FAFC for the panel, #DCE2EF for the
   resize handle — with no var() usage, and doxygen-awesome v2.3.4
   predates the feature so it's unstyled.  Result: a large white
   rectangle covering ~20-30% of the right-hand viewport in dark mode.
   These overrides pull it back into the Phosphor surface palette. */
#page-nav,
#page-nav-tree,
#page-nav-contents {
    background: var(--side-nav-background) !important;
    color: var(--side-nav-foreground) !important;
    border-left: 1px solid var(--separator-color) !important;
}
#page-nav a,
#page-nav .label,
#page-nav-tree a,
#page-nav-tree .label {
    color: var(--side-nav-foreground) !important;
}
#page-nav a:hover,
#page-nav-tree a:hover {
    color: var(--primary-color) !important;
}
#page-nav-resize-handle {
    background-color: var(--separator-color) !important;
}
#page-nav-resize-handle:hover,
#page-nav-resize-handle.dragging {
    background-color: var(--primary-color) !important;
}

/* Active/visible entry in the page-outline tree — navtree.css paints
   ul.page-outline li.vis { background-color: #EEF1F7 } (literal light
   slate).  When the reader scrolls a section into view, navtree.js
   adds class `vis` to the matching outline entry, producing a white
   rectangle over the dark sidebar.  Use --primary-light-color (dark
   blue tint in dark mode, pale blue in light mode) plus rounded
   corners so the highlight reads as a brand accent. */
ul.page-outline li.vis,
ul.page-outline li.vis > div.item,
#nav-tree .selected {
    background-color: var(--primary-light-color) !important;
    border-radius: 4px;
}
ul.page-outline li.vis a,
ul.page-outline li.vis > div.item a,
#nav-tree .selected a {
    color: var(--primary-color) !important;
}

/* #nav-sync — the little chevron button doxygen-awesome positions at
   bottom-right of the sidebar to "sync" the treeview to the current
   page.  navtree.css paints it with three literal-light hexes:
     background-color: #F9FAFC   (the button face)
     border:           #C4CFE5   (the button outline)
     chevron borders:  #C4CFE5   (the arrow glyph)
   + hover cues using #EEF1F7 / #6884BD.  Route every surface to our
   Phosphor palette so the control reads as a subtle in-theme affordance
   instead of a white rectangle on a dark sidebar. */
div.nav-sync-icon {
    background-color: var(--side-nav-background) !important;
    border: 1px solid var(--separator-color) !important;
    opacity: 0.7;
}
div.nav-sync-icon:hover {
    background-color: var(--surface-variant) !important;
    border-color: var(--primary-color) !important;
    opacity: 1;
}
div.nav-sync-icon.active:after {
    background-color: var(--separator-color) !important;
    border-top-color: var(--primary-color) !important;
}
div.nav-sync-icon.active:hover:after {
    border-top-color: var(--primary-color) !important;
}
/* The chevron arrows themselves are <span>s with border-left/top
   (left-chevron) and border-right/bottom (right-chevron).  Use
   per-side overrides because the shorthand `border-left:` that
   paints them wins against a generic `border-color:`. */
span.sync-icon-left {
    border-left-color: var(--side-nav-foreground) !important;
    border-top-color:  var(--side-nav-foreground) !important;
}
span.sync-icon-right {
    border-right-color:  var(--side-nav-foreground) !important;
    border-bottom-color: var(--side-nav-foreground) !important;
}
div.nav-sync-icon:hover span.sync-icon-left {
    border-left-color: var(--primary-color) !important;
    border-top-color:  var(--primary-color) !important;
}
div.nav-sync-icon:hover span.sync-icon-right {
    border-right-color:  var(--primary-color) !important;
    border-bottom-color: var(--primary-color) !important;
}

/* #nav-path ul — navtree.css paints a `border-top: 1px solid #C4CFE5`
   above the bottom breadcrumb strip.  Route it to --separator-color
   so the bar blends cleanly into the page instead of showing a pale
   horizontal line above the "Generated by doxygen" attribution. */
#nav-path ul {
    border-top: 1px solid var(--separator-color) !important;
}

/* Scrollbar theming for every scroll container doxygen-awesome MISSES.
   doxygen-awesome sets webkit-scrollbar styles on #nav-tree, .fragment,
   .memproto, .toc, .dotgraph, .tabs-overview-container — but not on
   #doc-content (the main content scroll area) or #page-nav /
   #page-nav-contents.  Those elements fall back to the OS default
   scrollbar, which on a light-themed OS paints two pale vertical
   lines down the right edge — exactly the "white bar" that can't be
   inspected in devtools because scrollbars aren't DOM nodes.
   Fix both the Firefox (scrollbar-color) and Webkit (::-webkit-
   scrollbar*) sides. */
#doc-content,
#page-nav,
#page-nav-contents,
#page-nav-tree,
#side-nav,
body,
html {
    scrollbar-color: var(--separator-color) transparent;
    scrollbar-width: thin;
}
#doc-content::-webkit-scrollbar,
#page-nav::-webkit-scrollbar,
#page-nav-contents::-webkit-scrollbar,
#page-nav-tree::-webkit-scrollbar,
#side-nav::-webkit-scrollbar,
body::-webkit-scrollbar,
html::-webkit-scrollbar {
    width:  calc(var(--webkit-scrollbar-size, 7px) + 2 * var(--webkit-scrollbar-padding, 4px));
    height: calc(var(--webkit-scrollbar-size, 7px) + 2 * var(--webkit-scrollbar-padding, 4px));
    background: transparent;
}
#doc-content::-webkit-scrollbar-thumb,
#page-nav::-webkit-scrollbar-thumb,
#page-nav-contents::-webkit-scrollbar-thumb,
#page-nav-tree::-webkit-scrollbar-thumb,
#side-nav::-webkit-scrollbar-thumb,
body::-webkit-scrollbar-thumb,
html::-webkit-scrollbar-thumb {
    background-color: var(--separator-color);
    border: var(--webkit-scrollbar-padding, 4px) solid transparent;
    border-radius: calc(var(--webkit-scrollbar-padding, 4px) * 2);
    background-clip: padding-box;
}
#doc-content::-webkit-scrollbar-thumb:hover,
#page-nav::-webkit-scrollbar-thumb:hover,
#page-nav-contents::-webkit-scrollbar-thumb:hover,
#page-nav-tree::-webkit-scrollbar-thumb:hover,
#side-nav::-webkit-scrollbar-thumb:hover,
body::-webkit-scrollbar-thumb:hover,
html::-webkit-scrollbar-thumb:hover {
    background-color: var(--primary-color);
}

/* jQuery-UI east resize handle grip — `.ui-resizable-e:after`:
     border-left:  1px solid #9CAFD4
     border-right: 1px solid #9CAFD4
   A 2px × 15px grip-indicator drawn from two literal medium-slate
   borders, positioned vertically-centered on the resize handle
   (#splitbar between left sidebar + content).  jQuery-UI adds
   .ui-resizable-e to #splitbar at runtime, so the grip pair paints
   as two near-white vertical lines visible at the sidebar/content
   boundary — the "white bar next to PhosphorLayout" the user saw.
   Hide the grip — doxygen-awesome already draws a subtle hairline
   on .ui-resizable-handle via inset-shadow, which is enough
   affordance. */
.ui-resizable-e:after {
    display: none !important;
}

/* Belt-and-suspenders for the base handle itself — navtree.css:
   `.ui-resizable-e { background-color: #DCE2EF }` (literal light).
   doxygen-awesome overrides to background:transparent but only via
   equal-specificity source-order; force transparent here so no
   cascade path paints a solid light bar. */
.ui-resizable-e {
    background-color: transparent !important;
    box-shadow: inset -1px 0 0 0 var(--separator-color) !important;
}

/* #nav-path breadcrumb chevron separators — four commits of
   debugging showed that BOTH doxygen.css and doxygen-awesome paint
   these pseudo-elements with literal-light backgrounds, border
   colors, and box-shadows that kept leaking through every var()-
   based override.  The chevron is decorative — breadcrumbs read
   fine with ` / ` separators inserted via ::after on links, so
   nuke the native pseudos entirely and re-inject a themed slash
   between breadcrumb items.  `content` + `color` are both themed
   vars so nothing can fall back to a literal hex. */
#nav-path li.navelem::before,
#nav-path li.navelem::after {
    display: none !important;
    content: none !important;
    border: none !important;
    background: transparent !important;
}
#nav-path li.navelem + li.navelem::before {
    display: inline-block !important;
    content: "/" !important;
    margin: 0 10px 0 4px !important;
    color: var(--page-secondary-foreground-color) !important;
    opacity: 0.5;
    font-weight: 400;
    border: none !important;
    background: transparent !important;
    transform: none !important;
}
#nav-path li.navelem:hover {
    background-color: var(--surface-variant, var(--side-nav-background)) !important;
}

/* Memberdecls + memTemplParams CELL BACKGROUNDS — doxygen.css sets a
   literal `background-color: #F9FAFC` on these classes.  Earlier
   commits routed the BORDER colors onto --separator-color but never
   touched the fill, so the cells still paint a near-white strip
   across the page whenever the row contains visible text.  Force
   transparent so the page bg shows through. */
.memItemLeft, .memItemRight,
.mdescLeft, .mdescRight,
.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
    background-color: transparent !important;
}

/* Interactive in-page TOC (`div.contents .toc.interactive`) — the
   collapsible right-floating "on this page" widget doxygen-awesome
   injects via doxygen-awesome-interactive-toc.js.  Its background
   cascade is inconsistent: doxygen-awesome uses
   `var(--page-background-color)` but wraps the rule in an @media
   min-width gate, and on some viewport widths the base doxygen.css
   rule `div.toc { background-color: #F4F6FA }` wins, so the widget
   renders as a white rectangle on the otherwise-dark page.
   Force every TOC element onto --toc-background / --toc-foreground. */
div.contents .toc,
div.contents .toc.interactive,
div.contents .toc.interactive.open,
div.contents .toc > h3,
div.contents .toc > ul {
    background-color: var(--toc-background) !important;
    color: var(--toc-foreground) !important;
    border-color: var(--separator-color) !important;
}
div.contents .toc a,
div.contents .toc li {
    color: var(--toc-foreground) !important;
}
div.contents .toc a:hover,
div.contents .toc a.active,
div.contents .toc a.aboveActive {
    color: var(--primary-color) !important;
}
/* Collapsed-state chevron — pick up the brand blue */
div.contents .toc.interactive > h3::before {
    border-top-color: var(--primary-color) !important;
}

/* #page-nav is the right-side per-page outline that doxygen 1.16
   generates when PAGE_OUTLINE_PANEL = YES.  Its theming lives higher
   up in this file (search for `#page-nav,` near the classindex rules);
   don't hide it — readers rely on it to jump between members. */

/* Memberdecls table borders — `Namespaces`, `Classes`, `Functions`
   sections on namespace/class reference pages.  doxygen.css ships
   literal-#D5DDEC (light slate-blue) borders on these cells:
     .memItemLeft / .memItemRight   left / right / bottom
     .mdescLeft   / .mdescRight     left / right / bottom
   doxygen-awesome overrides the left+right of the mem* classes with
   var(--separator-color) but ignores the bottom and all four sides of
   the mdesc* classes, so every row shows a pale light border on a
   dark page.  Blanket-override border-color on all the cells so any
   side doxygen.css still paints lands on --separator-color too. */
table.memberdecls .memItemLeft,
table.memberdecls .memItemRight,
table.memberdecls .mdescLeft,
table.memberdecls .mdescRight,
table.memberdecls .memTemplItemLeft,
table.memberdecls .memTemplItemRight,
table.memberdecls .memTemplParams,
table.memberdecls tr.inherit_header + tr[class^='memitem'] td.memItemLeft,
table.memberdecls tr.inherit_header + tr[class^='memitem'] td.memItemRight {
    border-color: var(--separator-color) !important;
}

/* Belt and suspenders for the h2 groupheader box-shadow.  doxygen.css
   paints LITERAL white stripes at ±12px; doxygen-awesome overrides
   with `var(--page-background-color)` at ±100/500/900px but relies on
   source-order tiebreak.  An explicit !important removes any
   possibility of a specificity upset and guarantees the stripe color
   follows our page bg. */
h2.groupheader,
td h2.groupheader {
    box-shadow:
        100px 0     var(--page-background-color),
        -100px 0    var(--page-background-color),
        100px 0.75px var(--separator-color),
        -100px 0.75px var(--separator-color),
        500px 0     var(--page-background-color),
        -500px 0    var(--page-background-color),
        500px 0.75px var(--separator-color),
        -500px 0.75px var(--separator-color),
        900px 0     var(--page-background-color),
        -900px 0    var(--page-background-color) !important;
}

/* Inline code — cover ALL the selectors Doxygen 1.16 emits for
   backticked Markdown text:
     <code>         standard Markdown inline code
     <span class="tt">   Doxygen-emitted tt (used inside markdown tables;
                         the root cause of the white-on-white bug:
                         doxygen.css default sets background #FBFCFD
                         with no color, so the dark-mode page fg bled
                         through as white text on white).
   Every rule below is !important because doxygen.css ships literal-hex
   backgrounds that would otherwise win specificity ties. */
/* Inline <code>, <tt>, and span.tt elements — NOT hljs block code
   inside .hljs-fragment (which must preserve its pre-formatted
   whitespace to render correctly).  The :not() guard is what keeps
   the rewritten fenced blocks from collapsing onto one line. */
code:not(.hljs),
span.tt,
.tt {
    background-color: var(--code-background) !important;
    color: var(--code-foreground) !important;
    padding: 1px 6px !important;
    border-radius: 4px !important;
    font-family: var(--font-family-monospace) !important;
    font-size: 0.92em !important;
    white-space: normal !important;   /* doxygen.css forces pre — breaks table wrapping */
}

/* Nested `.tt` inside doxygen's @warning / @note / @todo callout
   panels gets its own background-color override in doxygen.css (based
   on the callout hue).  Let ours win there too — otherwise callouts
   reintroduce the illegibility. */
dl.warning .tt, dl.attention .tt, dl.important .tt,
dl.note .tt,    dl.remark .tt,
dl.todo .tt,    dl.bug .tt,
dl.deprecated .tt {
    background-color: var(--code-background) !important;
    color: var(--code-foreground) !important;
}

/* Side-nav arrow hover picks up the cyan brand accent */
.arrow:hover { color: #22D3EE !important; }

/* Compound template params de-emphasised — PhosphorFoo<Bar> shows the
   <Bar> part slightly dimmer so the concrete type reads first */
.compoundTemplParams { opacity: 0.7; }

/* ──────────────────────────────────────────────────────────────────────
   highlight.js token colors
   ──────────────────────────────────────────────────────────────────────
   scripts/preprocess-md-fences.py rewrites fenced code blocks as
   <div class="fragment hljs-fragment"><pre><code class="hljs language-X">
   so they look like doxygen fragments but highlight.js tokens them.
   Reuse the --fragment-* theme variables so hljs output matches the
   colors doxygen's own lexer produces on C++ blocks.  Both LIGHT and
   DARK palettes are already defined above — these rules just plumb
   the vars into the hljs class names. */
/* doxygen's `.fragment` class normally contains <div class="line"> wrappers,
   so doxygen.css sets white-space behaviors that don't expect a <pre>
   child.  Force the native <pre> behavior back on so our preprocessed
   blocks keep line breaks and indentation.  The outer `div.fragment`
   already provides the background, border, and padding from
   doxygen-awesome — the inner <pre> must stay transparent so we don't
   get a nested "double box" look. */
.hljs-fragment pre {
    background: transparent;
    color: var(--fragment-foreground);
    white-space: pre;
    overflow-x: auto;
    margin: 0;
    padding: 0;
    border: 0;
    font-family: var(--font-family-monospace, monospace);
    font-size: var(--code-font-size, 0.9em);
    line-height: var(--fragment-lineheight, 1.5);
}
.hljs-fragment code.hljs {
    background: transparent;
    color: inherit;
    white-space: pre;
    padding: 0;
    /* doxygen-awesome gives bare <code> a 1px border + radius for inline
       code styling; strip it here so the block code doesn't render as a
       second box nested inside the outer .fragment. */
    border: 0;
    border-radius: 0;
    overflow: visible;
    font-family: inherit;
    font-size: inherit;
    display: block;
}
code.hljs .hljs-comment,
code.hljs .hljs-quote {
    color: var(--fragment-comment);
    font-style: italic;
}
code.hljs .hljs-keyword,
code.hljs .hljs-selector-tag,
code.hljs .hljs-meta-keyword {
    color: var(--fragment-keyword);
    font-weight: 600;
}
code.hljs .hljs-built_in,
code.hljs .hljs-type,
code.hljs .hljs-class .hljs-title,
code.hljs .hljs-title.class_,
code.hljs .hljs-attr,
code.hljs .hljs-attribute {
    color: var(--fragment-keywordtype);
}
code.hljs .hljs-literal,
code.hljs .hljs-number,
code.hljs .hljs-string,
code.hljs .hljs-regexp,
code.hljs .hljs-symbol {
    color: var(--fragment-token);
}
code.hljs .hljs-section,
code.hljs .hljs-name,
code.hljs .hljs-selector-id,
code.hljs .hljs-selector-class {
    color: var(--fragment-keywordflow);
}
code.hljs .hljs-meta,
code.hljs .hljs-doctag,
code.hljs .hljs-preprocessor {
    color: var(--fragment-preprocessor);
}
code.hljs .hljs-variable,
code.hljs .hljs-template-variable,
code.hljs .hljs-params {
    color: var(--fragment-foreground);
}
code.hljs .hljs-link {
    color: var(--fragment-link);
    text-decoration: underline;
}
code.hljs .hljs-emphasis { font-style: italic; }
code.hljs .hljs-strong   { font-weight: 700; }
