/* Shared web UI chrome -- the base layout, navbar, sidebar, and footer
   used by every ops-tool dashboard built on this module (yasta, yasl,
   yaiam, yakwui, yamase-web, yamocir). Loaded after bootstrap.min.css.
   Page-content styling (cards, tables, badges, forms, ...) is each
   project's own concern and lives in that project's own stylesheet,
   loaded alongside this one -- see PageHeader.ExtraHeadHTML.

   Theming has two independent axes, both set on <html> (see layout.go):

   - data-theme (PageHeader.Theme): the mode -- "dark", "light" or
     "system" (follows the browser's prefers-color-scheme). Unset is
     dark, the look every consumer had before themes existed. The mode
     only sets color-scheme and the --yw-if-* switches below.
   - data-palette (PageHeader.Palette): the colors -- "default",
     "graphite" or "contrast". Unset is "default".

   Every color token is written once, as light-dark(<light>, <dark>), so
   a palette is one block and no mode duplicates another's values. The
   palette is exposed as --yw-* custom properties and bridged into
   Bootstrap's own --bs-* variables further down, so Bootstrap's
   components (tables, forms, links, ...) follow the theme too. See
   README.md's Theming section. */

/* --- Mode --------------------------------------------------------- */

/* --yw-if-light/--yw-if-dark pick between two values where
   light-dark() can't: it only takes colors, not the r, g, b triplets
   Bootstrap builds rgba() from or url() images. The active mode's
   switch is "initial" (guaranteed-invalid), so var(--yw-if-dark, X)
   falls back to X; the other one is empty, so its var() adds nothing:
     --x: var(--yw-if-light, <light>) var(--yw-if-dark, <dark>); */
:root {
  color-scheme: dark;
  --yw-if-dark: initial;
  --yw-if-light: ;
}

:root[data-theme="light"] {
  color-scheme: light;
  --yw-if-dark: ;
  --yw-if-light: initial;
}

:root[data-theme="system"] {
  color-scheme: light dark;
}

@media (prefers-color-scheme: light) {
  :root[data-theme="system"] {
    --yw-if-dark: ;
    --yw-if-light: initial;
  }
}

/* --- Palettes ----------------------------------------------------- */

/* default: the original Yetano look. Also the base every other palette
   starts from -- a palette block only lists what it changes. Each
   *-rgb triplet repeats its color for Bootstrap's rgba(var(...), a);
   TestPaletteTripletsMatch keeps the two in step. --yw-nav-link stays
   #0b82b8 in both modes (a cross-project design token, see the
   meta-repo AGENTS.md). */
:root {
  --yw-bg: light-dark(#f4f6f9, #1a1d23);
  --yw-bg-rgb: var(--yw-if-light, 244, 246, 249) var(--yw-if-dark, 26, 29, 35);
  --yw-surface: light-dark(#ffffff, #20242c);
  --yw-surface-rgb: var(--yw-if-light, 255, 255, 255) var(--yw-if-dark, 32, 36, 44);
  --yw-surface-2: light-dark(#e9edf2, #272c35);
  --yw-surface-2-rgb: var(--yw-if-light, 233, 237, 242) var(--yw-if-dark, 39, 44, 53);
  --yw-text: light-dark(#1f2530, #d4d8e0);
  --yw-text-rgb: var(--yw-if-light, 31, 37, 48) var(--yw-if-dark, 212, 216, 224);
  --yw-text-strong: light-dark(#000000, #f1f3f6);
  --yw-text-strong-rgb: var(--yw-if-light, 0, 0, 0) var(--yw-if-dark, 241, 243, 246);
  --yw-muted: light-dark(#5a6678, #8a94a6);
  --yw-border: light-dark(#d3d9e2, #333333);
  --yw-chrome-bg: light-dark(#ffffff, #14171e);
  --yw-chrome-border: light-dark(#dde2ea, #272d3a);
  --yw-brand: light-dark(#0a72a3, #4fc3f7);
  --yw-accent: light-dark(#0a72a3, #4fc3f7);
  --yw-accent-rgb: var(--yw-if-light, 10, 114, 163) var(--yw-if-dark, 79, 195, 247);
  --yw-link: light-dark(#0a72a3, #4fc3f7);
  --yw-link-rgb: var(--yw-if-light, 10, 114, 163) var(--yw-if-dark, 79, 195, 247);
  --yw-link-hover: light-dark(#085a80, #81d4fa);
  --yw-link-hover-rgb: var(--yw-if-light, 8, 90, 128) var(--yw-if-dark, 129, 212, 250);
  --yw-primary: light-dark(#2595c8, #2595c8);
  --yw-primary-rgb: var(--yw-if-light, 37, 149, 200) var(--yw-if-dark, 37, 149, 200);
  --yw-on-primary: light-dark(#ffffff, #ffffff);
  --yw-nav-link: light-dark(#0b82b8, #0b82b8);
  --yw-nav-link-hover-text: light-dark(#0a4f72, #c8d4e4);
  --yw-subtitle: light-dark(#5a7088, #5a7a9a);
  --yw-subtitle-sep: light-dark(#c3cad5, #333c4a);
  --yw-footer-text: light-dark(#6a7a90, #4a5a72);
  --yw-success-bg: light-dark(#e5f4ea, #192e22);
  --yw-success-border: light-dark(#a6d4b4, #2a5c3a);
  --yw-success-text: light-dark(#1c5e33, #7ecf98);
  --yw-danger-bg: light-dark(#fbe9ec, #2e1820);
  --yw-danger-border: light-dark(#e6b0b8, #5c2a32);
  --yw-danger-text: light-dark(#9b2335, #e08090);
  --yw-warning-bg: light-dark(#fff4dc, #2e2716);
  --yw-warning-border: light-dark(#f0d08a, #5c4a1f);
  --yw-warning-text: light-dark(#7a5300, #e8c76a);
  --yw-info-bg: light-dark(#e3f3fb, #15283a);
  --yw-info-border: light-dark(#a8d8ef, #24506b);
  --yw-info-text: light-dark(#0b5a80, #7fc8ec);
}

/* graphite: grey and violet, after nessajina.tv -- near-black graphite
   (#1a1a1a), violet accent (#aa88ff), deep violet (#463a59), and the
   brand in the logo's brushed silver. */
:root[data-palette="graphite"] {
  --yw-bg: light-dark(#f3f2f5, #1a1a1a);
  --yw-bg-rgb: var(--yw-if-light, 243, 242, 245) var(--yw-if-dark, 26, 26, 26);
  --yw-surface: light-dark(#ffffff, #222222);
  --yw-surface-rgb: var(--yw-if-light, 255, 255, 255) var(--yw-if-dark, 34, 34, 34);
  --yw-surface-2: light-dark(#ebe9ef, #2a2a2a);
  --yw-surface-2-rgb: var(--yw-if-light, 235, 233, 239) var(--yw-if-dark, 42, 42, 42);
  --yw-text: light-dark(#232029, #e2e0e8);
  --yw-text-rgb: var(--yw-if-light, 35, 32, 41) var(--yw-if-dark, 226, 224, 232);
  --yw-text-strong: light-dark(#000000, #ffffff);
  --yw-text-strong-rgb: var(--yw-if-light, 0, 0, 0) var(--yw-if-dark, 255, 255, 255);
  --yw-muted: light-dark(#6b6675, #888888);
  --yw-border: light-dark(#d6d2dd, #3a3a40);
  --yw-chrome-bg: light-dark(#fbfafc, #141414);
  --yw-chrome-border: light-dark(#e0dce6, #2a2a2a);
  --yw-brand: light-dark(#463a59, #cfcfd8);
  --yw-accent: light-dark(#6c4bc4, #aa88ff);
  --yw-accent-rgb: var(--yw-if-light, 108, 75, 196) var(--yw-if-dark, 170, 136, 255);
  --yw-link: light-dark(#6c4bc4, #aa88ff);
  --yw-link-rgb: var(--yw-if-light, 108, 75, 196) var(--yw-if-dark, 170, 136, 255);
  --yw-link-hover: light-dark(#523599, #c4adff);
  --yw-link-hover-rgb: var(--yw-if-light, 82, 53, 153) var(--yw-if-dark, 196, 173, 255);
  --yw-primary: light-dark(#6c4bc4, #7c5ce0);
  --yw-primary-rgb: var(--yw-if-light, 108, 75, 196) var(--yw-if-dark, 124, 92, 224);
  --yw-nav-link: light-dark(#7a5fd0, #9a82d6);
  --yw-nav-link-hover-text: light-dark(#463a59, #d8ccff);
  --yw-subtitle: light-dark(#6b6675, #8a8494);
  --yw-subtitle-sep: light-dark(#cfcad6, #3a3a40);
  --yw-footer-text: light-dark(#7a7584, #6a6670);
  --yw-info-bg: light-dark(#efe9fb, #241e33);
  --yw-info-border: light-dark(#cbbcef, #463a59);
  --yw-info-text: light-dark(#463a59, #c4adff);
}

/* contrast: high contrast for readability -- black/white, a bright
   cyan accent in dark mode, deep blue in light. Not the classic yellow:
   in these dashboards yellow means "warning", and an accent in that
   color reads as a status. */
:root[data-palette="contrast"] {
  --yw-bg: light-dark(#ffffff, #000000);
  --yw-bg-rgb: var(--yw-if-light, 255, 255, 255) var(--yw-if-dark, 0, 0, 0);
  --yw-surface: light-dark(#ffffff, #0a0a0a);
  --yw-surface-rgb: var(--yw-if-light, 255, 255, 255) var(--yw-if-dark, 10, 10, 10);
  --yw-surface-2: light-dark(#f0f0f0, #161616);
  --yw-surface-2-rgb: var(--yw-if-light, 240, 240, 240) var(--yw-if-dark, 22, 22, 22);
  --yw-text: light-dark(#000000, #ffffff);
  --yw-text-rgb: var(--yw-if-light, 0, 0, 0) var(--yw-if-dark, 255, 255, 255);
  --yw-text-strong: light-dark(#000000, #ffffff);
  --yw-text-strong-rgb: var(--yw-if-light, 0, 0, 0) var(--yw-if-dark, 255, 255, 255);
  --yw-muted: light-dark(#333333, #d0d0d0);
  --yw-border: light-dark(#555555, #8a8a8a);
  --yw-chrome-bg: light-dark(#ffffff, #000000);
  --yw-chrome-border: light-dark(#555555, #8a8a8a);
  --yw-brand: light-dark(#0040a0, #66e0ff);
  --yw-accent: light-dark(#0040a0, #66e0ff);
  --yw-accent-rgb: var(--yw-if-light, 0, 64, 160) var(--yw-if-dark, 102, 224, 255);
  --yw-link: light-dark(#0040a0, #66e0ff);
  --yw-link-rgb: var(--yw-if-light, 0, 64, 160) var(--yw-if-dark, 102, 224, 255);
  --yw-link-hover: light-dark(#002a6b, #b3f0ff);
  --yw-link-hover-rgb: var(--yw-if-light, 0, 42, 107) var(--yw-if-dark, 179, 240, 255);
  --yw-primary: light-dark(#0040a0, #66e0ff);
  --yw-primary-rgb: var(--yw-if-light, 0, 64, 160) var(--yw-if-dark, 102, 224, 255);
  --yw-on-primary: light-dark(#ffffff, #000000);
  --yw-nav-link: light-dark(#00549e, #a8e6ff);
  --yw-nav-link-hover-text: light-dark(#000000, #ffffff);
  --yw-subtitle: light-dark(#333333, #d0d0d0);
  --yw-subtitle-sep: light-dark(#888888, #8a8a8a);
  --yw-footer-text: light-dark(#333333, #d0d0d0);
  --yw-success-text: light-dark(#0a4d1f, #8ff0a8);
  --yw-danger-text: light-dark(#7a0010, #ffa0ae);
  --yw-warning-text: light-dark(#5a3d00, #ffe08a);
  --yw-info-text: light-dark(#003f5c, #a0dcff);
}

/* --- Bootstrap bridge --------------------------------------------- */

/* Bootstrap's theme-dependent variables, taken from the palette. This
   replaces Bootstrap's own data-bs-theme switch, which has no "follow
   the system" mode without a script. Same selector weight as
   Bootstrap's own :root block and loaded after it, so these win. */
:root {
  --bs-body-bg: var(--yw-bg);
  --bs-body-bg-rgb: var(--yw-bg-rgb);
  --bs-body-color: var(--yw-text);
  --bs-body-color-rgb: var(--yw-text-rgb);
  --bs-emphasis-color: var(--yw-text-strong);
  --bs-emphasis-color-rgb: var(--yw-text-strong-rgb);
  --bs-secondary-color: color-mix(in srgb, var(--yw-text) 75%, transparent);
  --bs-secondary-color-rgb: var(--yw-text-rgb);
  --bs-secondary-bg: var(--yw-surface-2);
  --bs-secondary-bg-rgb: var(--yw-surface-2-rgb);
  --bs-tertiary-color: color-mix(in srgb, var(--yw-text) 50%, transparent);
  --bs-tertiary-color-rgb: var(--yw-text-rgb);
  --bs-tertiary-bg: var(--yw-surface);
  --bs-tertiary-bg-rgb: var(--yw-surface-rgb);
  --bs-heading-color: inherit;
  --bs-link-color: var(--yw-link);
  --bs-link-color-rgb: var(--yw-link-rgb);
  --bs-link-hover-color: var(--yw-link-hover);
  --bs-link-hover-color-rgb: var(--yw-link-hover-rgb);
  --bs-border-color: var(--yw-border);
  --bs-border-color-translucent: color-mix(in srgb, var(--yw-text) 15%, transparent);
  --bs-focus-ring-color: color-mix(in srgb, var(--yw-accent) 25%, transparent);
  --bs-code-color: light-dark(#d63384, #e685b5);
  --bs-highlight-color: var(--yw-text);
  --bs-highlight-bg: var(--yw-warning-bg);

  --bs-primary: var(--yw-primary);
  --bs-primary-rgb: var(--yw-primary-rgb);
  --bs-primary-text-emphasis: var(--yw-accent);
  --bs-primary-bg-subtle: color-mix(in srgb, var(--yw-accent) 15%, var(--yw-bg));
  --bs-primary-border-subtle: color-mix(in srgb, var(--yw-accent) 45%, var(--yw-bg));
  --bs-secondary-text-emphasis: var(--yw-muted);
  --bs-secondary-bg-subtle: var(--yw-surface-2);
  --bs-secondary-border-subtle: var(--yw-border);
  --bs-success-text-emphasis: var(--yw-success-text);
  --bs-success-bg-subtle: var(--yw-success-bg);
  --bs-success-border-subtle: var(--yw-success-border);
  --bs-danger-text-emphasis: var(--yw-danger-text);
  --bs-danger-bg-subtle: var(--yw-danger-bg);
  --bs-danger-border-subtle: var(--yw-danger-border);
  --bs-warning-text-emphasis: var(--yw-warning-text);
  --bs-warning-bg-subtle: var(--yw-warning-bg);
  --bs-warning-border-subtle: var(--yw-warning-border);
  --bs-info-text-emphasis: var(--yw-info-text);
  --bs-info-bg-subtle: var(--yw-info-bg);
  --bs-info-border-subtle: var(--yw-info-border);
  --bs-light-text-emphasis: light-dark(#495057, #f8f9fa);
  --bs-light-bg-subtle: light-dark(#fcfcfd, #343a40);
  --bs-light-border-subtle: light-dark(#e9ecef, #495057);
  --bs-dark-text-emphasis: light-dark(#495057, #dee2e6);
  --bs-dark-bg-subtle: light-dark(#ced4da, #1a1d20);
  --bs-dark-border-subtle: light-dark(#adb5bd, #343a40);

  --bs-form-valid-color: var(--yw-success-text);
  --bs-form-valid-border-color: var(--yw-success-text);
  --bs-form-invalid-color: var(--yw-danger-text);
  --bs-form-invalid-border-color: var(--yw-danger-text);
}

/* Bootstrap writes its primary blue straight into these components
   rather than reading --bs-primary, so they get the palette's here.
   The default palette's #2595c8 is the button color every consumer's
   own stylesheet used (as yasta), so those rules can go. */
.btn-primary {
  --bs-btn-color: var(--yw-on-primary);
  --bs-btn-bg: var(--yw-primary);
  --bs-btn-border-color: var(--yw-primary);
  --bs-btn-hover-color: var(--yw-on-primary);
  --bs-btn-hover-bg: color-mix(in srgb, var(--yw-primary) 85%, #000000);
  --bs-btn-hover-border-color: color-mix(in srgb, var(--yw-primary) 80%, #000000);
  --bs-btn-focus-shadow-rgb: var(--yw-primary-rgb);
  --bs-btn-active-color: var(--yw-on-primary);
  --bs-btn-active-bg: color-mix(in srgb, var(--yw-primary) 80%, #000000);
  --bs-btn-active-border-color: color-mix(in srgb, var(--yw-primary) 75%, #000000);
  --bs-btn-disabled-color: var(--yw-on-primary);
  --bs-btn-disabled-bg: var(--yw-primary);
  --bs-btn-disabled-border-color: var(--yw-primary);
}

.btn-outline-primary {
  --bs-btn-color: var(--yw-primary);
  --bs-btn-border-color: var(--yw-primary);
  --bs-btn-hover-color: var(--yw-on-primary);
  --bs-btn-hover-bg: var(--yw-primary);
  --bs-btn-hover-border-color: var(--yw-primary);
  --bs-btn-focus-shadow-rgb: var(--yw-primary-rgb);
  --bs-btn-active-color: var(--yw-on-primary);
  --bs-btn-active-bg: var(--yw-primary);
  --bs-btn-active-border-color: var(--yw-primary);
  --bs-btn-disabled-color: var(--yw-primary);
  --bs-btn-disabled-border-color: var(--yw-primary);
}

.list-group {
  --bs-list-group-active-color: var(--yw-on-primary);
  --bs-list-group-active-bg: var(--yw-primary);
  --bs-list-group-active-border-color: var(--yw-primary);
}

.nav-pills {
  --bs-nav-pills-link-active-color: var(--yw-on-primary);
  --bs-nav-pills-link-active-bg: var(--yw-primary);
}

.dropdown-menu {
  --bs-dropdown-link-active-color: var(--yw-on-primary);
  --bs-dropdown-link-active-bg: var(--yw-primary);
}

.pagination {
  --bs-pagination-focus-box-shadow: 0 0 0 .25rem color-mix(in srgb, var(--yw-primary) 25%, transparent);
  --bs-pagination-active-color: var(--yw-on-primary);
  --bs-pagination-active-bg: var(--yw-primary);
  --bs-pagination-active-border-color: var(--yw-primary);
}

.progress,
.progress-stacked {
  --bs-progress-bar-color: var(--yw-on-primary);
  --bs-progress-bar-bg: var(--yw-primary);
}

.form-check-input:checked {
  background-color: var(--yw-primary);
  border-color: var(--yw-primary);
}

.form-control:focus,
.form-select:focus,
.form-check-input:focus {
  border-color: color-mix(in srgb, var(--yw-primary) 50%, var(--yw-bg));
  box-shadow: 0 0 0 .25rem color-mix(in srgb, var(--yw-primary) 25%, transparent);
}

.form-range::-webkit-slider-thumb { background-color: var(--yw-primary); }
.form-range::-moz-range-thumb { background-color: var(--yw-primary); }

/* The images Bootstrap swaps under data-bs-theme="dark": they carry a
   fixed color, so each needs both versions. */
.form-select {
  --bs-form-select-bg-img: var(--yw-if-light, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e")) var(--yw-if-dark, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"));
}

.form-switch .form-check-input:not(:checked):not(:focus) {
  --bs-form-switch-bg: var(--yw-if-light, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e")) var(--yw-if-dark, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e"));
}

.navbar-toggler-icon {
  --bs-navbar-toggler-icon-bg: var(--yw-if-light, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%2833, 37, 41, 0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")) var(--yw-if-dark, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"));
}

/* Light has no filter: the empty value leaves filter at its initial
   "none". */
.btn-close {
  filter: var(--yw-if-dark, var(--bs-btn-close-white-filter));
}

/* --- Page ---------------------------------------------------------- */

html {
  height: 100%;
}

/* Flex column so the footer sits right after the content when the page is
   short, and grows naturally when content is long. */
body {
  background: var(--yw-bg);
  color: var(--yw-text);
  font-size: 0.875rem;
  min-height: 100%;
  display: flex;
  flex-direction: column;
}

/* bootstrap.min.css's own ".container-fluid" rule sets
   "display: flex; align-items: center; justify-content: space-between"
   (meant for a navbar's inner container-fluid, but the selector isn't
   scoped to .navbar, so it also matches the page's own top-level
   .container-fluid below). Scoped to "body > .container-fluid" -- NOT a
   bare ".container-fluid" -- so this doesn't also hijack the navbar's own
   inner .container-fluid. */
body > .container-fluid {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

/* .row's own height must come from flex-grow, not a percentage
   min-height: without this the sidebar's dark background only extends as
   far as its own nav links on short pages instead of the full available
   height. */
body > .container-fluid > .row {
  flex: 1 0 auto;
}

/* --- Navbar ------------------------------------------------ */
/* Bootstrap's own navbar colors come from the palette (the navbar has
   no .navbar-dark, which would pin them to white). */
.navbar {
  --bs-navbar-color: var(--yw-subtitle);
  --bs-navbar-hover-color: var(--yw-accent);
  --bs-navbar-active-color: var(--yw-accent);
  --bs-navbar-brand-color: var(--yw-brand);
  --bs-navbar-brand-hover-color: var(--yw-brand);
  --bs-navbar-toggler-border-color: var(--yw-chrome-border);
  background: var(--yw-chrome-bg) !important;
  border-bottom: 1px solid var(--yw-chrome-border);
  padding: .6rem 1.2rem;
}

.navbar-brand {
  color: var(--yw-brand) !important;
  letter-spacing: 2.5px;
  font-size: 1rem;
}

.navbar-subtitle {
  color: var(--yw-subtitle);
  font-size: .82rem;
  text-decoration: none;
}

a.navbar-subtitle:hover {
  color: var(--yw-accent);
}

.navbar-subtitle-sep {
  color: var(--yw-subtitle-sep);
  margin: 0 .5rem;
}

/* --- Appearance menu (PageHeader.AppearancePath) ------------------- */
/* A <details> dropdown: opens and closes without a script, so it works
   under a strict script-src CSP. Each choice is a submit button of one
   POST form. */
.yw-appearance {
  position: relative;
}

.yw-appearance > summary {
  list-style: none;
}

.yw-appearance > summary::-webkit-details-marker {
  display: none;
}

.yw-appearance-menu {
  position: absolute;
  right: 0;
  top: calc(100% + .35rem);
  z-index: 1030;
  min-width: 12rem;
  padding: .35rem 0;
  background: var(--yw-chrome-bg);
  border: 1px solid var(--yw-chrome-border);
  border-radius: .375rem;
  box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .25);
}

.yw-appearance-menu h6 {
  color: var(--yw-muted);
  font-size: .72rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  margin: .35rem .9rem .2rem;
}

.yw-appearance-menu button {
  display: block;
  width: 100%;
  padding: .3rem .9rem;
  border: 0;
  background: none;
  color: var(--yw-text);
  text-align: left;
}

.yw-appearance-menu button:hover {
  background: color-mix(in srgb, var(--yw-accent) 10%, transparent);
}

.yw-appearance-menu button[aria-pressed="true"] {
  color: var(--yw-accent);
  font-weight: 600;
}

.yw-appearance-menu hr {
  margin: .35rem 0;
  border-color: var(--yw-chrome-border);
  opacity: 1;
}

/* --- Sidebar ------------------------------------------------ */
.sidebar {
  background: var(--yw-chrome-bg);
  border-right: 1px solid var(--yw-chrome-border);
  padding-top: .5rem;
}

.sidebar .nav-link {
  color: var(--yw-nav-link);
  font-size: .85rem;
  padding: .5rem 1rem;
  border-radius: 0;
}

.sidebar .nav-link:hover {
  background: color-mix(in srgb, var(--yw-accent) 8%, transparent);
  color: var(--yw-nav-link-hover-text);
}

.sidebar .nav-link.active {
  background: color-mix(in srgb, var(--yw-accent) 10%, transparent);
  color: var(--yw-accent);
  font-weight: 600;
  border-left: 2px solid var(--yw-accent);
}

/* A page without a sidebar (a login page): BodyAttrs ` class="no-sidebar"`.
   The layout always renders the sidebar column; this hides it and gives
   <main> the full width. !important: Bootstrap's d-md-block, column and
   ms-sm-auto classes on those elements are !important or more specific. */
body.no-sidebar .sidebar {
  display: none !important;
}

body.no-sidebar main {
  width: 100% !important;
  margin-left: 0 !important;
}

/* --- Alerts (flash banners) ---------------------------------------- */
.alert-success { background: var(--yw-success-bg); border-color: var(--yw-success-border); color: var(--yw-success-text); }
.alert-danger  { background: var(--yw-danger-bg); border-color: var(--yw-danger-border); color: var(--yw-danger-text); }

/* --- Footer ------------------------------------------------- */
.footer {
  color: var(--yw-footer-text);
  font-size: 0.8rem;
  text-align: center;
  padding: 0.8rem 1rem;
  border-top: 1px solid var(--yw-chrome-border);
}

/* Narrow screens (below Bootstrap's md breakpoint, where the sidebar
   column stacks above the content): the sidebar becomes a tab bar --
   the same look as a page's own Bootstrap .nav-tabs (e.g. a manual's
   topic tabs): one row of links that wraps onto further rows when they
   don't fit, never a sideways-scrolling strip, the active one
   underlined in the accent color. */
@media (max-width: 767.98px) {
  .sidebar {
    border-right: none;
    border-bottom: 1px solid var(--yw-chrome-border);
    padding-top: 0;
  }
  /* !important: Bootstrap's .flex-column utility is !important itself. */
  .sidebar .nav.flex-column {
    flex-direction: row !important;
    flex-wrap: wrap;
    padding-top: 0 !important;
  }
  .sidebar .nav-link {
    padding: .55rem .85rem;
    border-bottom: 2px solid transparent;
    white-space: nowrap;
  }
  .sidebar .nav-link.active {
    border-left: none;
    border-bottom: 2px solid var(--yw-accent);
  }
  /* The navbar's own extras (a project's config path, action buttons)
     wrap onto a second line instead of widening the page past the
     screen. */
  .navbar > .container-fluid {
    flex-wrap: wrap;
    row-gap: .4rem;
  }
  .navbar > .container-fluid > div {
    flex-wrap: wrap;
    min-width: 0;
  }
  .navbar-subtitle {
    overflow-wrap: anywhere;
  }
  /* The stacked row still grows to fill the page (see above); without
     this, the extra height is shared out between its wrapped lines and
     the tab bar gets an empty band below its links. */
  body > .container-fluid > .row {
    align-content: flex-start;
  }
}
