/* input(2096,1): run-time error CSS1019: Unexpected token, found '}' */
/* ── Skip Link (A11y) ── */
.skip-link {
    position: absolute;
    top: -40px;
    left: 0;
    padding: 8px 16px;
    background: #112549;
    color: #fff;
    z-index: 1100;
    text-decoration: none;
    font-weight: 600;
}
.skip-link:focus {
    top: 0;
}

/* ── Sidebar Navigation ── */
.sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 240px;
    background: var(--ccmf-sidebar-bg, #112549);
    color: #c5cdd8;
    display: flex;
    flex-direction: column;
    z-index: 1050;
    overflow: hidden;
    overscroll-behavior: contain;
    transform: translateX(-100%);
    visibility: hidden;
}
@media (min-width: 992px) {
    .sidebar {
        transform: translateX(0);
        visibility: visible;
    }
}
.sidebar.sidebar-open {
    transform: translateX(0);
    visibility: visible;
}
@media (prefers-reduced-motion: no-preference) {
    .sidebar {
        transition: transform 0.25s ease, visibility 0.25s ease;
    }
}
.sidebar-header {
    display: flex;
    align-items: center;
    padding: 0.75rem;
    border-bottom: 1px solid rgba(255,255,255,0.1);
}
.sidebar-brand {
    display: flex;
    align-items: center;
    width: 100%;
    text-decoration: none;
}
.sidebar-logo {
    width: 100%;
    height: auto;
}
.sidebar-body {
    flex: 1;
    padding: 0.75rem 0;
    overflow-y: auto;
    /* Hide scrollbar cosmetically; nav remains scrollable via wheel/touch. */
    scrollbar-width: none;
}
.sidebar-body::-webkit-scrollbar {
    display: none;
}
.sidebar-section-label {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: rgba(255,255,255,0.4);
    padding: 1rem 1rem 0.25rem 1rem;
}
.sidebar-link {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.5rem 1rem;
    color: #c5cdd8;
    text-decoration: none;
    font-size: 0.875rem;
    border-left: 3px solid transparent;
    min-height: 40px;
}
button.sidebar-link {
    background: none;
    border: none;
    border-left: 3px solid transparent;
    cursor: pointer;
    width: 100%;
    text-align: left;
}
.sidebar-link:hover,
.sidebar-link:focus-visible {
    background: rgba(255,255,255,0.08);
    color: #fff;
    text-decoration: none;
}
.sidebar-link:focus-visible {
    outline: 2px solid var(--ccmf-sidebar-accent, #5b9bd5);
    outline-offset: -2px;
}
.sidebar-link.active {
    background: rgba(255,255,255,0.12);
    color: #fff;
    border-left-color: var(--ccmf-sidebar-accent, #5b9bd5);
    font-weight: 600;
}
.sidebar-link i {
    font-size: 1.1rem;
    width: 1.25rem;
    text-align: center;
    flex-shrink: 0;
}
.sidebar-badge {
    margin-left: auto;
    font-size: 0.7rem;
}
.sidebar-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 1040;
}
.sidebar-backdrop.show {
    display: block;
}

/* ── Top Bar ── */
.topbar {
    position: fixed;
    top: 0;
    right: 0;
    left: 0;
    height: 56px;
    background: var(--bs-body-bg);
    border-bottom: 1px solid var(--bs-border-color);
    z-index: 1030;
    display: flex;
    align-items: center;
}
@media (min-width: 992px) {
    .topbar {
        left: 240px;
    }
}
.topbar-inner {
    display: flex;
    align-items: center;
    width: 100%;
    padding: 0 1rem;
    gap: 0.5rem;
}
.topbar-toggle {
    color: var(--bs-body-color);
}
.topbar-brand {
    display: flex;
    align-items: center;
}
.topbar-logo {
    height: 32px;
    width: auto;
}
.topbar-actions {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}
.topbar-action-btn {
    min-width: 36px;
    min-height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* ── Topbar Social Links ── */
.topbar-social {
    gap: 0.1rem;
}
.topbar-social-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    color: var(--bs-secondary-color);
    font-size: 1.15rem;
    text-decoration: none;
    transition: color 0.15s ease, background-color 0.15s ease;
}
.topbar-social-link:hover,
.topbar-social-link:focus-visible {
    background-color: var(--bs-tertiary-bg);
    text-decoration: none;
}
.topbar-social-link:focus-visible {
    outline: 2px solid #005fcc;
    outline-offset: 2px;
}
.topbar-social-link--youtube:hover,
.topbar-social-link--youtube:focus-visible {
    color: #ff0000;
}
.topbar-social-link--instagram:hover,
.topbar-social-link--instagram:focus-visible {
    color: #e4405f;
}
.topbar-social-link--tiktok:hover,
.topbar-social-link--tiktok:focus-visible {
    color: #111;
}
[data-bs-theme="dark"] .topbar-social-link--tiktok:hover,
[data-bs-theme="dark"] .topbar-social-link--tiktok:focus-visible {
    color: #fff;
}
.topbar-social-link--discord:hover,
.topbar-social-link--discord:focus-visible {
    color: #5865f2;
}
.topbar-social-label {
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--bs-secondary-color);
    white-space: nowrap;
}

/* ── Main Content ──
   Simple natural flow: topbar is fixed (56px), so main-content has 56px
   of top padding to clear it. Content and footer render in normal block
   flow inside main-content, no flex/min-height gymnastics. */
.main-content {
    padding-top: 56px;
}
@media (min-width: 992px) {
    .main-content {
        margin-left: 240px;
    }
}
.main-content > main {
    padding: 1.5rem 1.5rem 4rem 1.5rem;
    max-width: 1400px;
    width: 100%;
}

/* Footer — plain block element at the end of .main-content. */
.footer {
    background-color: var(--bs-body-bg);
}

/* ── Dark mode sidebar overrides ── */
[data-bs-theme="dark"] .sidebar {
    background: var(--ccmf-sidebar-bg-dark, #0c1a32);
}
[data-bs-theme="dark"] .sidebar-link:hover,
[data-bs-theme="dark"] .sidebar-link:focus-visible {
    background: rgba(255,255,255,0.06);
}
[data-bs-theme="dark"] .sidebar-link.active {
    background: rgba(255,255,255,0.1);
}

/* Navbar logo */
.navbar-logo {
  height: 40px;
  width: auto;
}

html {
  font-size: 14px;
}

@media (min-width: 768px) {
  html {
    font-size: 16px;
  }
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
  box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #112549;
}

/* Prevent horizontal scroll from any stray overflowing element,
   applied to body (not html) so it never interferes with vertical
   scrolling / document height calculations. */
body {
  overflow-x: clip;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
  color: var(--bs-secondary-color);
  text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
  text-align: start;
}

/* Hide spin buttons on number inputs */
.hide-spin-buttons::-webkit-outer-spin-button,
.hide-spin-buttons::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.hide-spin-buttons {
  -moz-appearance: textfield;
}

/* File Preview Modal */
.file-preview-image {
  max-width: 100%;
  max-height: 80vh;
  object-fit: contain;
}

.file-preview-iframe {
  width: 100%;
  height: 80vh;
  border: none;
}

.file-preview-link:hover img {
  opacity: 0.85;
  transition: opacity 0.15s ease-in-out;
}

/* Preserve line breaks in description / notes fields */
.preserve-whitespace {
  white-space: pre-line;
}

/* ── Admin Page ── */

:root {
  --ccmf-blue: #112549;
  --ccmf-red: #DF2023;
  /* Brand + dashboard chart palette (shared globally so the icon-pack theme block and the
     Chart.js getComputedStyle reader resolve the same tokens; previously these lived in the
     Dashboard view's inline <style>, which rendered at end-of-body and overrode the theme). */
  --ccmf-navy: #112549;
  --ccmf-light: #F7F7F7;
  --ccmf-navy-mid: #1e3d6f;
  --ccmf-navy-light: #2a5a99;
  --ccmf-red-dark: #b51a1d;
  --ccmf-red-light: #e8546b;
  --ccmf-steel: #6c757d;
  --ccmf-dark: #212529;
  --ccmf-navy-alpha: rgba(17,37,73,0.35);
  --ccmf-red-alpha: rgba(223,32,35,0.35);
  --ccmf-navy-bright: #3a70b2;
  --ccmf-red-mid: #f0888a;
  --ccmf-navy-bright-mid: #4a88c9;
  --ccmf-grid-color: rgba(0,0,0,.05);
  --ccmf-tooltip-bg: #112549;
  --ccmf-pie-border: #fff;
  /* Sidebar chrome */
  --ccmf-sidebar-bg: #112549;
  --ccmf-sidebar-bg-dark: #0c1a32;
  --ccmf-sidebar-accent: #5b9bd5;
}

.text-ccmf-blue { color: var(--ccmf-blue); }
.text-ccmf-red { color: var(--ccmf-red); }

.admin-page-title {
  font-weight: 700;
  margin-bottom: 1rem;
}

.admin-divider {
  border-color: #dee2e6;
  margin: 2rem 0;
}

.admin-section-header {
  font-size: 1.25rem;
  font-weight: 600;
  border-left: 4px solid var(--ccmf-blue);
  padding-left: 0.75rem;
  margin-bottom: 1rem;
}

/* Admin accordion */
#adminAccordion .accordion-button {
  font-size: 1.1rem;
  font-weight: 600;
  padding: 0.875rem 1.25rem;
  border-left: 4px solid var(--ccmf-blue);
}

#adminAccordion .accordion-button:not(.collapsed) {
  background-color: #f0f6ff;
  color: var(--ccmf-blue);
  box-shadow: none;
}

#adminAccordion .accordion-button:focus {
  box-shadow: 0 0 0 0.2rem rgba(0, 86, 179, 0.15);
}

#adminAccordion .accordion-item {
  border-color: #dee2e6;
}

#adminAccordion .accordion-body {
  padding: 1.25rem;
}

/* Stat cards */
.admin-stat-card {
  background: #fff;
  border: 1px solid #e9ecef;
  border-radius: 0.5rem;
  padding: 1rem;
  text-align: center;
  height: 100%;
  min-height: 7.5rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  transition: box-shadow 0.15s, border-color 0.15s;
}

.admin-stat-card--clickable {
  cursor: pointer;
}

.admin-stat-card--clickable:hover,
.admin-stat-card--clickable:focus-visible {
  border-color: var(--ccmf-blue);
  box-shadow: 0 2px 8px rgba(0, 86, 179, 0.12);
}

.admin-stat-value {
  font-size: 1.75rem;
  font-weight: 700;
  line-height: 1.2;
}

.admin-stat-label {
  font-size: 0.8rem;
  color: #6c757d;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-top: 0.25rem;
}

/* ── Dashboard Overview stat cards ───────────────────────────────── */
/* Two variants: --global (community / platform-wide) and --personal (user). */
.dashboard-stat-card {
  position: relative;
  background: #fff;
  border: 1px solid #e9ecef;
  border-left: 4px solid transparent;
  border-radius: 0.5rem;
  padding: 0.75rem 1rem;
  text-align: left;
  height: 100%;
  min-height: 7rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  transition: box-shadow 0.15s, border-color 0.15s, transform 0.15s;
}

.dashboard-stat-card--clickable {
  cursor: pointer;
}

.dashboard-stat-card--clickable:hover,
.dashboard-stat-card--clickable:focus-visible,
a:focus-visible .dashboard-stat-card--clickable {
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
  transform: translateY(-1px);
}

.dashboard-stat-label-top {
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 0.25rem;
}

.dashboard-stat-card .dashboard-stat-value {
  font-size: 1.75rem;
  font-weight: 700;
  line-height: 1.2;
}

.dashboard-stat-card .dashboard-stat-label {
  font-size: 0.85rem;
  color: #495057;
  margin-top: 0.15rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
}

/* Global (Community) variant — navy accent */
.dashboard-stat-card--global {
  background: #f4f7fb;
  border-left-color: var(--ccmf-navy, #1b3a6b);
}
.dashboard-stat-card--global .dashboard-stat-label-top {
  color: var(--ccmf-navy, #1b3a6b);
}
.dashboard-stat-card--global .dashboard-stat-value {
  color: var(--ccmf-navy, #1b3a6b);
}

/* Personal (Your Collection) variant — red accent */
.dashboard-stat-card--personal {
  background: #fdf5f5;
  border-left-color: var(--ccmf-red, #c8102e);
}
.dashboard-stat-card--personal .dashboard-stat-label-top {
  color: var(--ccmf-red, #c8102e);
}
.dashboard-stat-card--personal .dashboard-stat-value {
  color: var(--ccmf-red, #c8102e);
}

/* Overview section collapse animation */
.overview-body {
  overflow: hidden;
  transition: max-height 0.25s ease, opacity 0.2s ease;
}
.overview-body.is-collapsed {
  max-height: 0 !important;
  opacity: 0;
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .overview-body { transition: none; }
}

/* Featured Model image — larger centered display on the dashboard card */
.featured-model-img {
  max-width: 100%;
  width: 260px;
  height: auto;
  max-height: 260px;
  object-fit: contain;
  background: #fff;
  padding: 0.5rem;
  border: 1px solid #e9ecef;
}
[data-bs-theme="dark"] .featured-model-img {
  background: var(--bs-tertiary-bg);
  border-color: var(--bs-border-color);
}

/* Tables */
.admin-table {
  font-size: 0.875rem;
}

.admin-table th {
  font-weight: 600;
  white-space: nowrap;
  border-bottom-width: 2px;
}

.admin-table td {
  vertical-align: middle;
}

.admin-actions {
  white-space: nowrap;
}

.admin-actions .btn {
  padding: 0.15rem 0.4rem;
  font-size: 0.75rem;
}

.admin-actions .btn-admin-toggle {
  min-width: 6.5rem;
  text-align: center;
}

.admin-actions .btn-status-toggle {
  min-width: 4.2rem;
  text-align: center;
}

/* Sortable column headers */
.sortable-header {
  text-decoration: none;
  color: inherit;
  white-space: nowrap;
  cursor: pointer;
}
.sortable-header:hover {
  color: var(--ccmf-blue);
}
.sort-icon {
  font-size: 0.7rem;
  opacity: 0.6;
  margin-left: 0.2rem;
}

/* Nuclear button */
.btn-nuclear {
  background-color: var(--ccmf-red);
  color: #fff;
  border: none;
  font-weight: 600;
}

.btn-nuclear:hover {
  background-color: #a3172f;
  color: #fff;
}

.btn-nuclear:disabled {
  background-color: #6c757d;
  cursor: not-allowed;
}

/* Batch toolbar */
.admin-batch-toolbar {
  background: #f8f9fa;
  border: 1px solid #dee2e6;
  border-radius: 0.375rem;
  padding: 0.5rem 1rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* Search dropdown */
.admin-search-dropdown {
  position: absolute;
  z-index: 1000;
  background: #fff;
  border: 1px solid #dee2e6;
  border-radius: 0.375rem;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  max-height: 200px;
  overflow-y: auto;
  width: 100%;
}

.admin-search-item {
  margin: 0;
}

.admin-search-item .btn {
  padding: 0.4rem 0.75rem;
  text-decoration: none;
  color: #212529;
}

.admin-search-item .btn:hover {
  background: #f0f6ff;
}

/* Usage detail inline panel */
.usage-detail-row td {
  background: #f8f9fa;
  border-left: 3px solid var(--ccmf-blue);
}

.usage-detail-panel h6 {
  color: var(--ccmf-blue);
}

.usage-detail-panel .table {
  font-size: 0.875rem;
}

/* Step indicator */
.admin-step-indicator {
  display: flex;
  gap: 1rem;
}

.admin-step-indicator .step {
  padding: 0.25rem 0.75rem;
  border-radius: 1rem;
  font-size: 0.85rem;
  background: #e9ecef;
  color: #6c757d;
}

.admin-step-indicator .step.active {
  background: var(--ccmf-blue);
  color: #fff;
  font-weight: 600;
}

.admin-step-indicator .step.completed {
  background: #198754;
  color: #fff;
}

/* ── Dark Mode Toggle ── */

/* Icon visibility: show moon in light mode, sun in dark mode */
.dark-mode-icon-sun { display: none; }
.dark-mode-icon-moon { display: inline-block; }

[data-bs-theme="dark"] .dark-mode-icon-sun { display: inline-block; }
[data-bs-theme="dark"] .dark-mode-icon-moon { display: none; }

/* ── Dark Mode Overrides ── */

[data-bs-theme="dark"] {
  --ccmf-blue: #6db3f8;
  --ccmf-red: #ff6b7a;
  /* Dashboard chart palette (dark). Relocated from the Dashboard view's inline <style> so the
     defaults sit after the light :root block (equal specificity → source order wins) and the
     icon-pack theme block can still override them. */
  --ccmf-navy: #6db3f8;
  --ccmf-navy-mid: #5a9de6;
  --ccmf-navy-light: #82c4ff;
  --ccmf-light: rgba(255,255,255,0.07);
  --ccmf-red-dark: #ff8f99;
  --ccmf-red-light: #ffb0b8;
  --ccmf-steel: #b0b8c4;
  --ccmf-navy-alpha: rgba(109,179,248,0.4);
  --ccmf-red-alpha: rgba(255,107,122,0.4);
  --ccmf-navy-bright: #82c4ff;
  --ccmf-red-mid: #ffb0b8;
  --ccmf-navy-bright-mid: #6db3f8;
  --ccmf-grid-color: rgba(255,255,255,.08);
  --ccmf-tooltip-bg: rgba(20,22,35,0.92);
  --ccmf-pie-border: rgba(255,255,255,.12);
  color-scheme: dark;
}

/* Navbar */
[data-bs-theme="dark"] .navbar {
  background-color: var(--bs-body-bg) !important;
  border-bottom-color: var(--bs-border-color) !important;
}

/* Focus ring */
[data-bs-theme="dark"] .btn:focus,
[data-bs-theme="dark"] .btn:active:focus,
[data-bs-theme="dark"] .btn-link.nav-link:focus,
[data-bs-theme="dark"] .form-control:focus,
[data-bs-theme="dark"] .form-check-input:focus {
  box-shadow: 0 0 0 0.1rem var(--bs-body-bg), 0 0 0 0.25rem var(--ccmf-blue);
}

/* Admin stat cards */
[data-bs-theme="dark"] .admin-stat-card {
  background: var(--bs-tertiary-bg);
  border-color: var(--bs-border-color);
}

[data-bs-theme="dark"] .admin-stat-card--clickable:hover,
[data-bs-theme="dark"] .admin-stat-card--clickable:focus-visible {
  border-color: var(--ccmf-blue);
  box-shadow: 0 2px 8px rgba(100, 160, 255, 0.18);
}

[data-bs-theme="dark"] .admin-stat-label {
  color: var(--bs-secondary-color);
}

/* Dashboard Overview stat cards — dark */
[data-bs-theme="dark"] .dashboard-stat-card {
  background: var(--bs-tertiary-bg);
  border-color: var(--bs-border-color);
}
[data-bs-theme="dark"] .dashboard-stat-card .dashboard-stat-label {
  color: var(--bs-body-color);
}
[data-bs-theme="dark"] .dashboard-stat-card--global {
  background: rgba(27, 58, 107, 0.18);
}
[data-bs-theme="dark"] .dashboard-stat-card--global .dashboard-stat-label-top,
[data-bs-theme="dark"] .dashboard-stat-card--global .dashboard-stat-value {
  color: #8ab4f8;
}
[data-bs-theme="dark"] .dashboard-stat-card--personal {
  background: rgba(200, 16, 46, 0.12);
}
[data-bs-theme="dark"] .dashboard-stat-card--personal .dashboard-stat-label-top,
[data-bs-theme="dark"] .dashboard-stat-card--personal .dashboard-stat-value {
  color: #ff8896;
}

/* Achievements Earned badges — dark. Bootstrap's bg-light/text-dark utilities are fixed light
   values that don't adapt to the dark theme, so the pills render near-white on the dark card.
   Override to the same surface tokens the other dark cards use. */
[data-bs-theme="dark"] .achievement-badge {
  background-color: var(--bs-tertiary-bg) !important;
  color: var(--bs-body-color) !important;
  border-color: var(--bs-border-color) !important;
}

/* btn-outline-dark — dark. Bootstrap's outline-dark is a near-black outline that
   disappears against the dark body (e.g. ScaleModels "Convert to Set"). Remap its
   button tokens so it reads as a light outline, mirroring btn-outline-light. */
[data-bs-theme="dark"] .btn-outline-dark {
  --bs-btn-color: var(--bs-body-color);
  --bs-btn-border-color: var(--bs-border-color);
  --bs-btn-hover-bg: var(--bs-body-color);
  --bs-btn-hover-color: var(--bs-body-bg);
  --bs-btn-hover-border-color: var(--bs-body-color);
  --bs-btn-active-bg: var(--bs-body-color);
  --bs-btn-active-color: var(--bs-body-bg);
  --bs-btn-active-border-color: var(--bs-body-color);
}

/* ── $1M+ Milestone card (Community → Total Inventory Cost) ──
   Gold gradient background, pulsing glow, and corner ribbon to mark the
   community crossing $1,000,000 in total inventory cost. */
.milestone-card {
  position: relative;
  overflow: hidden;
  background: linear-gradient(135deg, #fff8dc 0%, #fff3b0 50%, #ffe98a 100%) !important;
  border-left-color: #b8860b !important;
  box-shadow: 0 0 0 0 rgba(184, 134, 11, 0.55);
  animation: milestone-glow 3s ease-in-out infinite;
}
.milestone-card .dashboard-stat-label-top,
.milestone-card .dashboard-stat-value,
.milestone-card .dashboard-stat-label {
  color: #5c4400 !important;
}
.milestone-ribbon {
  position: absolute;
  /* Generously oversized so any milestone label fits — from "$1M Club" up through
     four-digit-million labels like "$10.75M Club" — without truncation. */
  top: 14px;
  right: -56px;
  transform: rotate(35deg);
  background: linear-gradient(135deg, #b8860b 0%, #d4a017 50%, #f3c623 100%);
  /* Dark text on the gold gradient — WCAG AA contrast (~12:1 vs the lightest stop). */
  color: #2f2200;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  /* border-box so padding doesn't push the rendered width past min-width on narrow cards. */
  box-sizing: border-box;
  padding: 4px 64px;
  min-width: 180px;
  text-align: center;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  z-index: 2;
  pointer-events: none;
  white-space: nowrap;
}
.milestone-ribbon .bi {
  margin-right: 2px;
}
/* On narrow viewports each card is ~half the screen (col-6), so the ribbon needs to
   shrink to avoid clipping the stat value or overflowing the .milestone-card overflow:
   hidden frame in a way that hides the whole label. */
@media (max-width: 575.98px) {
  .milestone-ribbon {
    top: 10px;
    right: -42px;
    padding: 3px 44px;
    min-width: 130px;
    font-size: 0.65rem;
    letter-spacing: 0.02em;
  }
}
@keyframes milestone-glow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(184, 134, 11, 0.45); }
  50%      { box-shadow: 0 0 18px 4px rgba(184, 134, 11, 0.55); }
}
@media (prefers-reduced-motion: reduce) {
  .milestone-card { animation: none; }
}
/* Keyboard focus indicator: stop the pulsing glow and apply a high-contrast outline
   so the milestone card still has a visible focus ring (WCAG 2.4.7). The animated
   box-shadow would otherwise mask the shared :focus-visible state defined for all
   .dashboard-stat-card--clickable elements. */
a:focus-visible .milestone-card,
.milestone-card:focus-visible {
  animation: none;
  outline: 3px solid #0d6efd;
  outline-offset: 2px;
  box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.35);
}
[data-bs-theme="dark"] .milestone-card {
  background: linear-gradient(135deg, #3a2e0a 0%, #4a3a0e 50%, #5a4612 100%) !important;
  border-left-color: #f3c623 !important;
}
[data-bs-theme="dark"] .milestone-card .dashboard-stat-label-top,
[data-bs-theme="dark"] .milestone-card .dashboard-stat-value,
[data-bs-theme="dark"] .milestone-card .dashboard-stat-label {
  color: #ffe98a !important;
}
[data-bs-theme="dark"] .milestone-ribbon {
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
}

/* Admin batch toolbar */
[data-bs-theme="dark"] .admin-batch-toolbar {
  background: var(--bs-tertiary-bg);
  border-color: var(--bs-border-color);
}

/* Admin search dropdown */
[data-bs-theme="dark"] .admin-search-dropdown {
  background: var(--bs-body-bg);
  border-color: var(--bs-border-color);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}

[data-bs-theme="dark"] .admin-search-item .btn {
  color: var(--bs-body-color);
}

[data-bs-theme="dark"] .admin-search-item .btn:hover {
  background: var(--bs-tertiary-bg);
}

/* Usage detail panel */
[data-bs-theme="dark"] .usage-detail-row td {
  background: var(--bs-tertiary-bg);
}

/* Admin step indicator */
[data-bs-theme="dark"] .admin-step-indicator .step {
  background: var(--bs-tertiary-bg);
  color: var(--bs-secondary-color);
}

/* Admin divider */
[data-bs-theme="dark"] .admin-divider {
  border-color: var(--bs-border-color);
}

/* Footer */
[data-bs-theme="dark"] .footer {
  border-top-color: var(--bs-border-color) !important;
}

/* File preview modal */
[data-bs-theme="dark"] .file-preview-image {
  background: var(--bs-tertiary-bg);
}

/* Nuclear button stays red in both modes */
[data-bs-theme="dark"] .btn-nuclear {
  background-color: var(--ccmf-red);
}

[data-bs-theme="dark"] .btn-nuclear:hover {
  background-color: #c9354b;
}

/* Template builder column items */
[data-bs-theme="dark"] #available-columns .border-bottom {
  border-color: var(--bs-border-color) !important;
}

[data-bs-theme="dark"] #selected-columns .list-group-item {
  background-color: var(--bs-body-bg);
  border-color: var(--bs-border-color);
  color: var(--bs-body-color);
}

/* Import review table: warning rows readable in dark mode */
[data-bs-theme="dark"] .table-warning {
  --bs-table-bg: #332701;
  --bs-table-border-color: #664e03;
  color: var(--bs-body-color);
}

/* ── Account / Profile ── */

.profile-avatar {
  border-radius: 50%;
  object-fit: cover;
}

.profile-avatar-sm {
  width: 24px;
  height: 24px;
}

.profile-avatar-lg {
  width: 100px;
  height: 100px;
}

/* ── Notification Bell ── */

.notification-badge {
  position: absolute;
  top: -2px;
  right: -4px;
  font-size: 0.65rem;
  min-width: 1.1rem;
  padding: 0.15rem 0.35rem;
  line-height: 1;
}

.notification-dropdown {
  width: 340px;
  max-width: 90vw;
}

.notification-dropdown-body {
  max-height: 320px;
  overflow-y: auto;
}

.notification-dropdown-item {
  display: flex;
  align-items: flex-start;
  padding: 0.5rem 0.75rem;
  text-decoration: none;
  color: inherit;
  border-bottom: 1px solid var(--bs-border-color-translucent);
  gap: 0.5rem;
}

.notification-dropdown-item:last-child {
  border-bottom: none;
}

.notification-dropdown-item:hover {
  background-color: var(--bs-tertiary-bg);
}

.notification-unread {
  background-color: rgba(13, 110, 253, 0.04);
  border-left: 3px solid var(--bs-primary);
}

.notification-unread-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: var(--bs-primary);
  flex-shrink: 0;
  margin-top: 0.35rem;
}

/* Dark mode notification overrides */
[data-bs-theme="dark"] .notification-dropdown {
  background-color: var(--bs-body-bg);
  border-color: var(--bs-border-color);
}

[data-bs-theme="dark"] .notification-dropdown-item:hover {
  background-color: var(--bs-tertiary-bg);
}

[data-bs-theme="dark"] .notification-unread {
  background-color: rgba(100, 160, 255, 0.08);
}

/* ── Inquiries panel (#302) ── */
.inquiry-row.inquiry-unread {
  background-color: rgba(13, 110, 253, 0.04);
  border-left: 3px solid var(--bs-primary);
}

.inquiry-unread-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: var(--bs-primary);
  flex-shrink: 0;
  display: inline-block;
}

[data-bs-theme="dark"] .inquiry-row.inquiry-unread {
  background-color: rgba(100, 160, 255, 0.08);
}

.account-card .card-header {
  background: #f8f9fa;
  font-weight: 600;
}

[data-bs-theme="dark"] .account-card .card-header {
  background: var(--bs-tertiary-bg);
}

[data-bs-theme="dark"] .account-card {
  border-color: var(--bs-border-color);
}

/* Footer legal links */
.footer-legal-links a {
  color: #6c757d;
  text-decoration: none;
  margin-left: 1rem;
  font-size: 0.85rem;
}

.footer-legal-links a:hover {
  color: var(--ccmf-blue);
  text-decoration: underline;
}

/* ── Card Grid View ── */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 1rem;
}

.card-grid-item {
  transition: box-shadow 0.15s ease-in-out;
}

.card-grid-item:hover {
  box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.12);
}

.card-grid-item:focus-within {
  outline: 2px solid var(--bs-primary);
  outline-offset: 2px;
}

.card-grid-item .card-title a {
  text-decoration: none;
  color: inherit;
}

.card-grid-item .card-title a:hover {
  text-decoration: underline;
}

[data-bs-theme="dark"] .card-grid-item {
  border-color: var(--bs-border-color);
}

/* ── Piece Card Image ── */
.piece-card-img {
  width: 150px;
  height: 100%;
  min-height: 150px;
  object-fit: cover;
  border-radius: var(--bs-card-inner-border-radius) 0 0 var(--bs-card-inner-border-radius);
  flex-shrink: 0;
  align-self: stretch;
  background-color: var(--bs-tertiary-bg, #f8f9fa);
}

.card-grid-item-horizontal {
  /* Was a hard 150px (the image height) with overflow:hidden, which clipped the
     user-tag row (#555) whenever the title wrapped to two or three lines. Let the
     card grow to fit its content, keeping the image height as a floor. */
  min-height: 150px;
  overflow: hidden;
}

/* Make the inner flex row fill the now content-driven card height so the image
   column stretches to match instead of leaving a gap below a fixed-height image. */
.card-grid-item-horizontal > .d-flex {
  flex: 1 1 auto;
  min-height: 0;
}

.card-grid-item-horizontal > .d-flex > a:first-child {
  display: flex;
}

.piece-card-name {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.3;
  min-height: calc(1.3em * 3);
  margin-bottom: 0.15rem;
}

@media (max-width: 575.98px) {
  .card-grid {
    grid-template-columns: 1fr;
  }
}

/* ── Card Grid Controls ── */
.card-grid-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
}

/* ── View Mode Toggle ── */
.view-mode-toggle .btn {
  padding: 0.25rem 0.5rem;
}

/* ── Search Input with Clear Button (#357) ── */
.ccmf-search-wrap {
  position: relative;
}

.ccmf-search-wrap .ccmf-search-input {
  /* Reserve space on the right so typed text never sits underneath the
     clear button (44px = button width incl. padding). */
  padding-right: 2.75rem;
}

.ccmf-search-clear {
  position: absolute;
  top: 50%;
  right: 0.25rem;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* WCAG 2.5.8: target size at least 24x24 CSS px. We use 32x32. */
  width: 2rem;
  height: 2rem;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 50%;
  color: var(--bs-secondary-color, #6c757d);
  cursor: pointer;
  line-height: 1;
}

.ccmf-search-clear:hover,
.ccmf-search-clear:focus-visible {
  color: var(--bs-body-color);
  background-color: var(--bs-secondary-bg, rgba(0, 0, 0, 0.06));
}

.ccmf-search-clear:focus-visible {
  outline: 2px solid var(--bs-primary, #0d6efd);
  outline-offset: 2px;
}

.ccmf-search-clear[hidden] {
  display: none;
}

/* ── Filter Panel ── */
.ccmf-filter-panel {
  background-color: var(--bs-light, #f8f9fa);
  border: 1px solid var(--bs-border-color);
  border-radius: 0.375rem;
  padding: 1rem;
}

[data-bs-theme="dark"] .ccmf-filter-panel {
  background-color: var(--bs-tertiary-bg);
}

/* ── Remote card-grid loading overlay (#737) ──
   Parity with Tabulator's built-in ajaxLoader for the card-grid view: a dim + spinner
   shown over the grid while a remote fetch is in flight. Toggled by card-grid.js setBusy(). */
.ccmf-grid-busy-host {
  position: relative;
}

.ccmf-grid-busy-overlay {
  position: absolute;
  inset: 0;
  min-height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(var(--bs-body-bg-rgb, 255, 255, 255), 0.6);
  border-radius: 0.375rem;
  z-index: 5;
}

/* Static busy indicator when motion is reduced (no spin). */
@media (prefers-reduced-motion: reduce) {
  .ccmf-grid-busy-overlay .spinner-border {
    animation: none;
  }
}

/* ── Active Filter Badges ── */
.ccmf-filter-badge {
  font-size: 0.8rem;
  font-weight: 500;
  padding: 0.3em 0.55em;
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
}

.ccmf-badge-close {
  font-size: 0.55em;
  padding: 0;
  opacity: 0.8;
}

.ccmf-badge-close:hover {
  opacity: 1;
}

/* ── Tabulator Cell Overflow ── */
.tabulator .tabulator-cell {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Tabulator Dark Mode Tweaks ── */
[data-bs-theme="dark"] .tabulator {
  background-color: var(--bs-body-bg);
  border-color: var(--bs-border-color);
}

[data-bs-theme="dark"] .tabulator .tabulator-header {
  background-color: var(--bs-tertiary-bg);
  border-color: var(--bs-border-color);
  color: var(--bs-body-color);
}

[data-bs-theme="dark"] .tabulator .tabulator-header .tabulator-col {
  background-color: var(--bs-tertiary-bg);
  border-color: var(--bs-border-color);
}

[data-bs-theme="dark"] .tabulator .tabulator-tableholder .tabulator-table .tabulator-row {
  background-color: var(--bs-body-bg);
  color: var(--bs-body-color);
}

[data-bs-theme="dark"] .tabulator .tabulator-tableholder .tabulator-table .tabulator-row:nth-child(even) {
  background-color: var(--bs-tertiary-bg);
}

[data-bs-theme="dark"] .tabulator .tabulator-tableholder .tabulator-table .tabulator-row:hover {
  background-color: var(--bs-secondary-bg);
}

[data-bs-theme="dark"] .tabulator .tabulator-footer {
  background-color: var(--bs-tertiary-bg);
  border-color: var(--bs-border-color);
  color: var(--bs-body-color);
}

/* ── Wantlist ── */

/* Distinctive, clearly-clickable search affordance: a small primary pill
   button rather than a faint inline glyph, so users notice it and understand
   it triggers an external-search action (#119 feedback). */
.wantlist-search-icon {
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  margin-left: 0.4rem;
  font-size: 0.9rem;
  line-height: 1;
  color: var(--bs-primary);
  background-color: var(--bs-primary-bg-subtle);
  border: 1px solid var(--bs-primary-border-subtle);
  border-radius: 50%;
  vertical-align: middle;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.wantlist-search-icon:hover,
.wantlist-search-icon:focus-visible {
  color: #fff;
  background-color: var(--bs-primary);
  border-color: var(--bs-primary);
  outline: none;
}
@media (prefers-reduced-motion: reduce) {
  .wantlist-search-icon { transition: none; }
}

/* ── External search badges (#119) ──
   Centralized look for the marketplace / catalog / auction / association
   "search this item elsewhere" badges. Markup is built by
   wwwroot/js/external-search-links.js. */
.ccmf-search-badges {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem;
}
.ccmf-search-badges-label {
  color: var(--bs-secondary-color);
  margin-right: 0.25rem;
}
.ccmf-search-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  /* 24px min target (WCAG 2.5.8); roomy enough to tap on mobile. */
  min-height: 1.6rem;
  padding: 0.1rem 0.5rem;
  font-size: 0.78rem;
  line-height: 1.2;
  white-space: nowrap;
  text-decoration: none;
  border: 1px solid var(--bs-border-color);
  border-radius: 0.85rem;
  color: var(--bs-body-color);
  background-color: var(--bs-body-bg);
  transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.ccmf-search-badge:hover,
.ccmf-search-badge:focus-visible {
  border-color: var(--bs-primary);
  color: var(--bs-primary);
  background-color: var(--bs-tertiary-bg);
}
.ccmf-search-badge .bi {
  font-size: 0.78rem;
}
/* Group accents so manufacturer / association badges read as distinct. */
.ccmf-search-badge-manufacturer {
  border-color: var(--bs-primary-border-subtle);
}
.ccmf-search-badge-manufacturer:hover,
.ccmf-search-badge-manufacturer:focus-visible {
  border-color: var(--bs-primary);
}
.ccmf-search-badge-association {
  border-color: var(--bs-warning-border-subtle);
}
.ccmf-search-badge-association:hover,
.ccmf-search-badge-association:focus-visible {
  border-color: var(--bs-warning);
  color: var(--bs-warning-text-emphasis);
}
.ccmf-search-badge-lock {
  font-size: 0.65rem;
  opacity: 0.7;
}
@media (prefers-reduced-motion: reduce) {
  .ccmf-search-badge {
    transition: none;
  }
}

/* ── Sticky Form Actions ──
   Action bar that sticks just below the fixed 56px topbar so Save/Cancel are
   always reachable on long edit forms without scrolling to the bottom. */
.form-actions-sticky {
  position: sticky;
  top: 56px;
  z-index: 1020;
  margin: -0.5rem -0.5rem 1rem;
  padding: 0.5rem;
  background: var(--bs-body-bg);
  border-bottom: 1px solid var(--bs-border-color);
  backdrop-filter: saturate(140%) blur(2px);
}
.form-actions-sticky-inner {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.form-actions-sticky-title {
  font-weight: 600;
  color: var(--bs-secondary-color);
  max-width: 50%;
}
.form-actions-sticky-buttons {
  display: flex;
  gap: 0.5rem;
}

/* Hide the sticky form actions bar while EasyMDE is in fullscreen mode.
   EasyMDE's fullscreen layers (.editor-toolbar.fullscreen, .CodeMirror-fullscreen,
   .editor-preview-active-side) use position:fixed with a low z-index, which would
   otherwise sit underneath our z-index:1020 sticky bar. Hiding the bar lets the
   fullscreen editor own the viewport; users exit fullscreen to save. */
body:has(.editor-toolbar.fullscreen) .form-actions-sticky,
body:has(.CodeMirror-fullscreen) .form-actions-sticky {
  display: none;
}

/* ── Show Feature ── */

/* Show card hover effect on Index listing */
@media (prefers-reduced-motion: no-preference) {
  .show-card {
    transition: transform 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
  }
  .show-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.12);
  }
}

/* Show status badge pill shape */
.show-status-badge {
  border-radius: 1rem;
  font-size: 0.75rem;
  padding: 0.3em 0.7em;
  letter-spacing: 0.02em;
}

/* Countdown card */
#countdown-card {
  border-color: var(--bs-border-color);
}

/* Logo initials circle */
.show-initials-circle {
  width: 120px;
  height: 120px;
  font-size: 2.5rem;
  font-weight: 700;
  color: #fff;
}

/* Spot buttons — ensure minimum 48x48 tap target on mobile (WCAG 2.5.8) */
@media (max-width: 575.98px) {
  .spot-btn {
    min-width: 48px;
    min-height: 48px;
    padding: 0.5rem;
  }
}

/* Note template buttons in spot modal */
.note-template-btn {
  font-size: 0.8rem;
}

/* Dark mode show overrides */
[data-bs-theme="dark"] .show-card:hover {
  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.3);
}

/* ──────────────────────────────────────────────────────────────────────────
   Shared dashboard primitives
   ──────────────────────────────────────────────────────────────────────────
   These card/icon/color utilities were originally scoped to /Dashboard but
   are reused by /Community (and other pages) through shared partials like
   ~/Views/Dashboard/_CommunitySection.cshtml and _ActiveContestWidget.cshtml.
   They need to be globally available so the visual style matches across
   pages. Dashboard-only layout rules (module sidebar, customize mode,
   chart palette variables) stay in Dashboard/Index.cshtml's inline style
   block.
   ────────────────────────────────────────────────────────────────────────── */

/* CCMF palette utilities */
.bg-ccmf-navy  { background-color: var(--ccmf-navy, #112549) !important; }
.bg-ccmf-red   { background-color: var(--ccmf-red,  #DF2023) !important; }
.bg-ccmf-blue  { background-color: var(--ccmf-navy-light, #2a5a99) !important; }
.bg-ccmf-light { background-color: var(--ccmf-light, #F7F7F7) !important; }
.text-ccmf-navy { color: var(--ccmf-navy, #112549); }
.text-ccmf-red  { color: var(--ccmf-red,  #DF2023); }
.text-ccmf-blue { color: var(--ccmf-navy-light, #2a5a99); }

/* Card shell used across Dashboard, Community, and other feature pages */
.dashboard-card {
    border: none;
    border-radius: 12px;
    box-shadow: 0 2px 12px rgba(0, 0, 0, .06);
}

[data-bs-theme="dark"] .dashboard-card {
    box-shadow: 0 2px 12px rgba(0, 0, 0, .3);
}

/* Round color-filled icon badge (used next to card titles) */
.dashboard-icon-circle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    font-size: 1rem;
    flex-shrink: 0;
}

/* Big number callout inside cards */
.dashboard-big-number {
    font-size: 2rem;
    font-weight: 700;
    line-height: 1.1;
}

/* Row-link hover state (used inside .dashboard-card lists) */
.dashboard-row-link {
    padding: 2px 4px;
    border-radius: 6px;
    transition: background-color 0.15s;
}

.dashboard-row-link:hover {
    background-color: var(--ccmf-light, #F7F7F7);
}

.dashboard-notice-link:hover {
    color: var(--ccmf-navy, #112549) !important;
    text-decoration: underline !important;
}

/* Manufacturer detail "most-owned" top-3 card row */
.top-owned-card {
    transition: transform 0.15s ease, box-shadow 0.15s ease;
    overflow: hidden;
}
.top-owned-card:hover,
.top-owned-card:focus-visible {
    transform: translateY(-2px);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .1);
}
.top-owned-thumb-col {
    min-height: 120px;
}
.top-owned-thumb {
    max-height: 110px;
    object-fit: contain;
    padding: 0.5rem;
    background: rgba(255, 255, 255, 0.9);
    border-radius: 6px;
}
@media (prefers-reduced-motion: reduce) {
    .top-owned-card { transition: none; }
    .top-owned-card:hover,
    .top-owned-card:focus-visible { transform: none; }
}

/* ── Needs Attention dashboard card (issue #765) ──
   Action tiles: each is a full-width link to a filtered /Pieces list. Meaning is
   carried by icon + count badge + text + priority order (never color alone). */
.needs-attention-tile {
    color: inherit;
    background-color: var(--bs-body-bg, #fff);
    border-color: var(--bs-border-color, #dee2e6) !important;
    min-height: 56px; /* comfortable tap target (WCAG 2.5.8) */
    transition: background-color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}
.needs-attention-tile:hover,
.needs-attention-tile:focus-visible {
    background-color: var(--ccmf-light, #F7F7F7);
    border-color: var(--ccmf-red, #DF2023) !important;
    transform: translateY(-2px);
}
.needs-attention-tile .needs-attention-text { color: var(--bs-body-color, #212529); }
@media (prefers-reduced-motion: reduce) {
    .needs-attention-tile { transition: none; }
    .needs-attention-tile:hover,
    .needs-attention-tile:focus-visible { transform: none; }
}

/* ── Get Started hero card tiles (issue #951, PR-2) ──
   First-run onboarding action tiles. Each tile is a full focusable <a>; meaning is
   carried by icon + heading + supporting text (never color alone). Visible focus ring
   per WCAG 2.4.7; comfortable target size per WCAG 2.5.8. The --ccmf-navy / --ccmf-light
   custom properties already remap for dark mode, so no theme-specific overrides needed. */
.get-started-tile {
    display: flex;
    align-items: flex-start;
    color: inherit;
    text-decoration: none;
    background-color: var(--bs-body-bg, #fff);
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: 10px;
    min-height: 56px;
    transition: background-color 0.15s ease, border-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}
.get-started-tile:hover,
.get-started-tile:focus-visible {
    background-color: var(--ccmf-light, #F7F7F7);
    border-color: var(--ccmf-navy, #112549);
    transform: translateY(-2px);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .08);
}
.get-started-tile:focus-visible {
    outline: 2px solid var(--ccmf-navy, #112549);
    outline-offset: 2px;
}
.get-started-tile .get-started-tile-title { color: var(--bs-body-color, #212529); }
.get-started-tile-body { min-width: 0; }
@media (prefers-reduced-motion: reduce) {
    .get-started-tile { transition: none; }
    .get-started-tile:hover,
    .get-started-tile:focus-visible { transform: none; }
}

/* "?" help affordance next to the hardware scanner toggle (issue #951, PR-2).
   Guarantees a >=24px square target (WCAG 2.5.8) for the icon-only button. */
.scanner-help-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 31px;
    line-height: 1;
}

/* ── Recent marketplace matches (issue #766) ──
   Wantlist-matched public listings tile. Mirrors .needs-attention-tile so the two
   discovery cards read consistently, with a fixed-size thumbnail and truncating body. */
.marketplace-match-tile {
    color: inherit;
    background-color: var(--bs-body-bg, #fff);
    border-color: var(--bs-border-color, #dee2e6) !important;
    min-height: 56px; /* comfortable tap target (WCAG 2.5.8) */
    transition: background-color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}
.marketplace-match-tile:hover,
.marketplace-match-tile:focus-visible {
    background-color: var(--ccmf-light, #F7F7F7);
    border-color: var(--ccmf-red, #DF2023) !important;
    transform: translateY(-2px);
}
.marketplace-match-thumb {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: 0.375rem;
    overflow: hidden;
    background-color: var(--ccmf-light, #F7F7F7);
    font-size: 1.5rem;
}
.marketplace-match-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
/* Allow the flex body to shrink so .text-truncate works inside the tile. */
.marketplace-match-body {
    min-width: 0;
}
@media (prefers-reduced-motion: reduce) {
    .marketplace-match-tile { transition: none; }
    .marketplace-match-tile:hover,
    .marketplace-match-tile:focus-visible { transform: none; }
}

/* ── Milestones / streaks card (Issue #767) ──
   Per-track tile with achieved badge + progress bar toward the next threshold.
   Progress is conveyed as text too (".milestone-progress" sibling), not colour
   alone, for accessibility (#751). */
.milestone-track {
    background-color: var(--bs-tertiary-bg, #f8f9fa);
}
.milestone-current {
    font-variant-numeric: tabular-nums;
}
.milestone-progress {
    height: 8px;
}

/* ── Hardware Barcode Scanner (Issue #347) ──
   Sticky listening banner + non-blocking floating result toast for the desktop
   USB / Bluetooth keyboard-emulating scanner. Uses Bootstrap CSS variables so
   the colors flip cleanly under data-bs-theme="dark". */
.hw-scan-banner {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1080;
    display: none;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.4rem 0.75rem;
    font-size: 0.875rem;
    color: #fff;
    background: var(--bs-success, #198754);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}
.hw-scan-banner.hw-scan-banner-active { display: flex; }
.hw-scan-banner .hw-scan-banner-pulse {
    width: 0.65rem;
    height: 0.65rem;
    border-radius: 50%;
    background: #fff;
    animation: hw-scan-pulse 1.4s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
    .hw-scan-banner .hw-scan-banner-pulse { animation: none; opacity: 0.85; }
}
@keyframes hw-scan-pulse {
    0%, 100% { opacity: 0.4; transform: scale(0.85); }
    50%      { opacity: 1;   transform: scale(1.1); }
}

.hw-scan-toast {
    position: fixed;
    top: 4rem;
    right: 1rem;
    z-index: 1085;
    width: 22rem;
    max-width: calc(100vw - 2rem);
    background: var(--bs-body-bg);
    color: var(--bs-body-color);
    border: 1px solid var(--bs-border-color);
    border-radius: 0.5rem;
    box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.2);
    padding: 0.75rem;
}
.hw-scan-toast .hw-scan-toast-close {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
}
.hw-scan-toast .hw-scan-toast-body { padding-right: 1.25rem; }

/* Push page content down by the banner height when scanner mode is active.
   Banner is ~32px tall; using padding-top on body keeps fixed elements like
   the topbar in their original positions but shifts the rest. */
body:has(.hw-scan-banner.hw-scan-banner-active) { padding-top: 2rem; }

/* Shared scan-result renderer styles (mobile.css has the same rules — these
   are duplicated here so the desktop hardware-scanner toast on /ScaleModels
   and /Dashboard, which doesn't load mobile.css, renders match cards
   correctly). Without these, <img> elements render at intrinsic size and
   blow out the toast. */
.scan-match-card {
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: 0.5rem;
    padding: 0.75rem;
}

.scan-match-thumb {
    width: 80px;
    height: 80px;
    object-fit: cover;
    border-radius: 0.375rem;
    flex-shrink: 0;
}

.scan-match-thumb-sm {
    width: 48px;
    height: 48px;
    object-fit: cover;
    border-radius: 0.25rem;
    flex-shrink: 0;
}

.scan-match-placeholder {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--bs-tertiary-bg);
    color: var(--bs-secondary);
    font-size: 1.5rem;
}

.scan-match-list {
    list-style: none;
    padding: 0;
    margin: 0;
    border-top: 1px solid var(--bs-border-color);
}

.scan-match-row {
    border-bottom: 1px solid var(--bs-border-color);
}

.scan-match-pick {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    min-height: 56px;
    padding: 0.5rem;
    background: transparent;
    border: 0;
    color: inherit;
    text-align: left;
}

.scan-match-pick:hover {
    background: var(--bs-tertiary-bg);
}

.scan-match-pick:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: -2px;
}

/* Desktop toast is narrow (22rem); shrink the thumb a touch and allow the
   action buttons to wrap so they're never cropped under the close button. */
.hw-scan-toast .scan-match-thumb {
    width: 64px;
    height: 64px;
}

.hw-scan-toast .scan-match-card {
    border: 0;
    padding: 0;
}

.hw-scan-toast .scan-btn {
    min-height: 38px;
}


/* -- Barcode display (read-only, on /ScaleModels/Details + /Pieces/Details) -- */
.barcode-display {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.25rem;
}

.barcode-display .barcode-svg {
    /* JsBarcode renders into the SVG; we only constrain the box.
       Using currentColor for the bars lets the bars adapt to dark mode. */
    max-width: 240px;
    width: 100%;
    height: auto;
    color: var(--bs-body-color);
}

.barcode-display .barcode-digits {
    font-size: 0.875rem;
    color: var(--bs-secondary-color);
    letter-spacing: 0.05em;
    user-select: all;     /* one-click select for typing into another system */
}

@media print {
    /* On a printed inventory card, force the bars black on white so cheap
       printers + cheap scanners cooperate. Hide the rest of the chrome. */
    .barcode-display .barcode-svg {
        color: #000 !important;
        max-width: 60mm;
    }

    .barcode-display .barcode-digits {
        color: #000 !important;
    }
}

/* Inventory manifest: a clean shelf-walk printout. Scoped via :has() so hiding the
   app chrome only affects the manifest page, not every print in the app. Buttons and
   other non-essential controls opt out with Bootstrap's .d-print-none. */
@media print {
    body:has(.inventory-manifest) .sidebar,
    body:has(.inventory-manifest) .topbar,
    body:has(.inventory-manifest) .sidebar-backdrop {
        display: none !important;
    }

    body:has(.inventory-manifest) .main-content {
        margin: 0 !important;
        padding: 0 !important;
    }

    .inventory-manifest .manifest-table th,
    .inventory-manifest .manifest-table td {
        border: 1px solid #000 !important;
    }
}

/* -- Inventory count-mode camera viewfinder (Issue #847, Slice B) --
   Self-contained copy of the viewfinder rules that mobile.css defines for the
   add-to-collection scanner. The main app layout does NOT load mobile.css, so
   the inventory Workspace (a desktop/tablet audit surface) needs its own copy —
   same precedent as the duplicated .scan-match-* rules above. Prefixed .inv-* so
   they never collide with the mobile .scan-* classes. */
.inv-viewfinder {
    position: relative;
    aspect-ratio: 4 / 3;
    max-height: 320px;
    background: #000;
    border-radius: 0.5rem;
    overflow: hidden;
}

.inv-viewfinder video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.inv-viewfinder[data-state="idle"] video {
    opacity: 0.3;
}

.inv-reticle {
    position: absolute;
    inset: 15% 10%;
    border: 2px solid rgba(255, 255, 255, 0.85);
    border-radius: 0.5rem;
    pointer-events: none;
    box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.25);
}

/* On an accepted count the reticle border flashes green. Gated behind a colour
   change only (no motion), and the transition itself is suppressed under
   prefers-reduced-motion so the cue is instantaneous rather than animated. */
.inv-viewfinder[data-state="hit"] .inv-reticle {
    border-color: var(--bs-success, #198754);
    box-shadow: 0 0 0 9999px rgba(25, 135, 84, 0.18);
}

@media (prefers-reduced-motion: no-preference) {
    .inv-reticle {
        transition: border-color 0.15s ease, box-shadow 0.15s ease;
    }
}

.inv-overlay {
    position: absolute;
    bottom: 0.5rem;
    left: 0.5rem;
    right: 0.5rem;
    color: #fff;
    font-size: 0.875rem;
    text-align: center;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
    pointer-events: none;
}

/* ── Inventory triage: mobile parity (Issue #880) ──
   The triage / attribution surfaces (scan list, attribute, adjust-set, report,
   audit index) were laid out for desktop. The scan-row action cluster now wraps
   on every viewport, and at the xs breakpoint the .btn-sm / .form-control-sm
   controls grow to a comfortable touch target. Scoped to the inventory page
   roots so nothing else in the app is affected. */
.inventory-scans .inv-action-cluster {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
    justify-content: flex-end;
}

@media (max-width: 575.98px) {
    /* Comfortable tap targets. WCAG 2.5.8 asks for 24px minimum; 44px matches the
       touch guidance the mobile scanner surfaces already follow. inline-flex keeps
       the icon + label centered once the button grows past its text height. */
    .inventory-scans .btn-sm,
    .inventory-attribute-scan .btn-sm,
    .inventory-adjust-set-scan .btn-sm,
    .inventory-report .btn-sm,
    .inventory-index .btn-sm {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }

    /* The icon-only delete button needs width as well as height to be tappable. */
    .inventory-scans .inv-action-cluster .btn {
        min-width: 44px;
    }

    /* Match the set-member "not present" stepper height to its Save button so the
       pair reads as one comfortable control. */
    .inventory-adjust-set-scan .form-control-sm {
        min-height: 44px;
    }
}

/* -- Manufacturer Lookup: highlight filled fields (Issue #464) --
   Applied by the Set form (and reusable elsewhere) to inputs the lookup just
   populated. Picks a bg/border tint that works in both light and dark themes
   via Bootstrap's --bs-info-bg-subtle / --bs-info-border-subtle CSS variables.
   The .lookup-filled-flash variant adds a brief highlight pulse and is
   removed after a short JS-driven timeout, leaving .lookup-filled in place
   as a persistent reminder while the user reviews the form. */
.lookup-filled {
    border-color: var(--bs-info-border-subtle, #9eeaf9);
    background-color: var(--bs-info-bg-subtle, #cff4fc);
}
.lookup-filled:focus {
    /* Re-use Bootstrap's focus ring color so contrast stays intact when the
       user tabs into a highlighted field. */
    box-shadow: 0 0 0 0.25rem rgba(13, 202, 240, 0.25);
}
@media (prefers-reduced-motion: no-preference) {
    .lookup-filled-flash {
        animation: lookup-filled-pulse 1.4s ease-out;
    }
    @keyframes lookup-filled-pulse {
        0%   { background-color: rgba(13, 202, 240, 0.55); }
        100% { background-color: var(--bs-info-bg-subtle, #cff4fc); }
    }
}

/* ── Blog post body / Docs body — YouTube embeds ──
   Chrome around the <lite-youtube> facade emitted by the :::youtube ::: shortcode.
   The vendored lite-yt-embed.css only handles the play-button + 16:9 padding; the
   rounded corners, shadow, hover lift, and the 9:16 Shorts variant are ours.
   Scoped to both .blog-post-body (Blog) and .content-body (Docs) so each surface
   gets identical chrome without the rules leaking onto, say, an admin preview
   pane on an unrelated screen. */

/* Reading-column cap. The surrounding `.main-content > main` is 1400px wide, so
   without this rule a blog article + a `.blog-img-medium` (640px) float-left image
   stretches across an uncomfortably wide column on desktop and the image visually
   "escapes" the text block. 720px matches the `sizes="(max-width: 720px) 100vw, 720px"`
   hint that ResponsiveImageRewriter emits — adjust both together if the cap moves.

   The cap is applied to the `.blog-post` <article> (not the inner `.blog-post-body`)
   so the article's <header> (h1 + byline) shares the same left edge as the body
   prose. Capping the inner div alone would center the body inside a full-width
   article and visually offset the heading from the text. We deliberately do NOT
   set `margin: auto` here — the column is left-aligned within the main content
   area so a `.blog-img-align-left` image actually appears at the LEFT edge of the
   reading column, matching the author's explicit alignment choice.

   `.markdown-editor__preview` gets the same cap so authors see the production
   layout while drafting. It has no separate header sibling, so the cap can sit
   directly on the preview pane.

   `display: flow-root` on `.blog-post-body` and `.markdown-editor__preview` is
   the float containment guarantee. Without it, the `.blog-img-align-left` /
   `-right` floats escape the article body and the page footer ends up flowing
   around them at the side of the article. The per-paragraph `clear: both` rule
   below handles intra-paragraph float ending, but the body-level flow-root is
   the safety net that keeps the float contained no matter how Markdig or
   ResponsiveImageRewriter wraps the image (bare <img>, <p><img></p>, or
   <p><picture><img></picture></p>). */
.blog-post,
.markdown-editor__preview {
    max-width: 720px;
}
.blog-post-body,
.markdown-editor__preview {
    display: flow-root;
}

.blog-post-body lite-youtube,
.content-body lite-youtube {
    border-radius: 0.5rem;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    margin: 1.5rem auto;
    max-width: 720px;
    /* Clip the poster image to the rounded corners. */
    overflow: hidden;
}

/* 9:16 vertical for YouTube Shorts (opt-in via `:::youtube ID short:::`). The
   override on ::after { padding-bottom: 0 } is required because the vendored CSS
   uses the padding-bottom hack for 16:9; aspect-ratio doesn't take effect until
   we cancel that padding. */
.blog-post-body lite-youtube.lyt-short,
.content-body lite-youtube.lyt-short {
    aspect-ratio: 9 / 16;
    max-width: 360px;
}
.blog-post-body lite-youtube.lyt-short::after,
.content-body lite-youtube.lyt-short::after {
    padding-bottom: 0;
}

/* Hover lift — purely decorative, gated behind prefers-reduced-motion. */
@media (prefers-reduced-motion: no-preference) {
    .blog-post-body lite-youtube,
    .content-body lite-youtube {
        transition: transform 0.2s ease, box-shadow 0.2s ease;
    }
    .blog-post-body lite-youtube:hover,
    .content-body lite-youtube:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
    }
}

/* Deeper shadow on dark backgrounds — the 0.15 alpha disappears against #1a1a1a. */
[data-bs-theme="dark"] .blog-post-body lite-youtube,
[data-bs-theme="dark"] .content-body lite-youtube {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45);
}
[data-bs-theme="dark"] .blog-post-body lite-youtube:hover,
[data-bs-theme="dark"] .content-body lite-youtube:hover {
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.6);
}

/* ── Blog post body — inline images ──
   Defence-in-depth cap so a single oversized image never dominates the page even
   if the upload pipeline (ImageProcessingService + GenerateWebpDerivativesAsync)
   is bypassed for some reason. The 70vh ceiling keeps portrait phone photos from
   becoming a vertical wall; the 640px ceiling stops landscape photos from pushing
   the page below the fold. object-fit: contain preserves aspect ratio inside the
   ceiling so we never crop. The same rules apply to .markdown-editor__preview
   inside the admin editor so authors see the production layout while drafting. */
.blog-post-body img,
.content-body img,
.markdown-editor__preview img {
    display: block;
    max-width: 100%;
    width: auto;
    height: auto;
    max-height: min(70vh, 640px);
    object-fit: contain;
    margin: 1.5rem auto;
    border-radius: 0.375rem;
    /* picture > source srcset only applies when the wrapper is the <picture>; the
       inner <img> still gets these constraints. */
}

/* <picture> wrapper — needed because the rewriter emits <picture><source/><img/></picture>;
   without display:block the wrapper would be a 1px-line inline anchor. */
.blog-post-body picture,
.content-body picture,
.markdown-editor__preview picture {
    display: block;
    max-width: 100%;
}

/* ── Blog post — hero banner (16:3) ──
   The hero is intentionally a wide masthead rather than a hero photo, so it sits
   across the top of the post without pushing the title and body below the fold on
   a 1080p viewport. The aspect-ratio reserves the layout slot at parse time so
   the page doesn't shift when the image loads (CLS protection). object-fit: cover
   shields against legacy 16:9 heroes from before the ratio change — they get
   trimmed top/bottom rather than letterboxed. */
.blog-post-hero-banner {
    width: 100%;
    aspect-ratio: 16 / 3;
    object-fit: cover;
}

/* ── Blog post body — inline image size + border overrides ──
   Authors pick Small / Medium / Large + optional border in the upload modal on
   /AdminBlog/Edit (#blog-improvements). The picker writes a Markdig generic
   attribute on the image (e.g. `![alt](url){.blog-img-medium .blog-img-bordered}`)
   which Markdig converts to a real `class=` attribute on the rendered <img>.
   These class values are explicitly whitelisted in MarkdownPipelineFactory's
   HtmlSanitizer (AllowedClasses) — adding a new size or border variant requires
   updating BOTH this CSS rule AND the sanitizer allowlist. The 70vh / 640px ceiling
   from the base .blog-post-body img rule still applies; these classes only lower the
   max-width further (Small / Medium) and override no other axis. */
.blog-post-body img.blog-img-small,
.markdown-editor__preview img.blog-img-small {
    max-width: 320px;
}
.blog-post-body img.blog-img-medium,
.markdown-editor__preview img.blog-img-medium {
    max-width: 640px;
}
.blog-post-body img.blog-img-large,
.markdown-editor__preview img.blog-img-large {
    max-width: 100%;
}
.blog-post-body img.blog-img-bordered,
.markdown-editor__preview img.blog-img-bordered {
    border: 1px solid var(--bs-border-color);
    padding: 0.25rem;
    background: var(--bs-tertiary-bg);
}

/* ── Blog post body — inline image alignment ──
   Authors pick Position: Left / Center / Right in the upload modal alongside the
   size + border choice. Left and Right float the image so prose wraps around it;
   Center sits the image block-level with auto margins. These classes are paired
   with a size class (`.blog-img-small` / `.blog-img-medium`) — at "Large" width
   floating doesn't visually do anything because the image already spans the
   content column, so the modal hides the Position group when Large is selected.

   Responsive escape hatch: below 768px (Bootstrap `md` breakpoint) we drop the
   float and revert to block layout. On a phone, a 320px floated image next to
   100vw prose would crush the text column to nothing — block + center keeps the
   article readable. The desktop float is intentionally only an enhancement.

   These class values are explicitly whitelisted in MarkdownPipelineFactory's
   HtmlSanitizer (AllowedClasses) — adding a new alignment variant requires
   updating BOTH this CSS rule AND the sanitizer allowlist. */
.blog-post-body img.blog-img-align-left,
.markdown-editor__preview img.blog-img-align-left {
    float: left;
    margin: 0.25rem 1rem 0.5rem 0;
}
.blog-post-body img.blog-img-align-right,
.markdown-editor__preview img.blog-img-align-right {
    float: right;
    margin: 0.25rem 0 0.5rem 1rem;
}
.blog-post-body img.blog-img-align-center,
.markdown-editor__preview img.blog-img-align-center {
    display: block;
    margin-left: auto;
    margin-right: auto;
}
/* Float-clearing helper. Markdig wraps every standalone image in its own <p>, so
   the next paragraph begins a fresh block formatting context — usually enough to
   "end" the float on its own. This rule is a safety net for the case where two
   floated images appear back-to-back, or where the prose between them is shorter
   than the image height.

   IMPORTANT: ResponsiveImageRewriter wraps the bare <img> in <picture>, so on the
   server-rendered side the actual structure is <p><picture><img …></picture></p>.
   The selectors below match BOTH shapes: the raw <p>><img> case (the live preview
   pane during typing, before the server has rendered) AND the <p>><picture>><img>
   case (server-rendered HTML on the published page and the post preview). Updating
   one without the other breaks float clearing in exactly one of those two surfaces. */
.blog-post-body p:has(> img.blog-img-align-left)::after,
.blog-post-body p:has(> img.blog-img-align-right)::after,
.blog-post-body p:has(> picture > img.blog-img-align-left)::after,
.blog-post-body p:has(> picture > img.blog-img-align-right)::after,
.markdown-editor__preview p:has(> img.blog-img-align-left)::after,
.markdown-editor__preview p:has(> img.blog-img-align-right)::after,
.markdown-editor__preview p:has(> picture > img.blog-img-align-left)::after,
.markdown-editor__preview p:has(> picture > img.blog-img-align-right)::after {
    content: "";
    display: block;
    clear: both;
}
@media (max-width: 767.98px) {
    .blog-post-body img.blog-img-align-left,
    .blog-post-body img.blog-img-align-right,
    .markdown-editor__preview img.blog-img-align-left,
    .markdown-editor__preview img.blog-img-align-right {
        float: none;
        display: block;
        margin-left: auto;
        margin-right: auto;
    }
}

/* Paragraph-alignment wrapper rules. Emitted by AlignContainerExtension when an
   author writes `:::align left|center|right` … `:::` in Markdown. The class
   names align-left / align-center / align-right are explicitly whitelisted in
   MarkdownPipelineFactory's HtmlSanitizer (AllowedClasses) — adding a new
   variant requires updating BOTH the regex / sanitizer pair AND this CSS.

   Scoped to the public reading surfaces (`.blog-post-body`, `.doc-body`) and to
   the editor preview pane (`.markdown-editor__preview`) so the AdminBlog /
   AdminDocs / AdminAlbums Markdown previews show the same alignment the
   published page will, without risking a class collision in unrelated UI. */
.blog-post-body .align-left,
.doc-body .align-left,
.album-description .align-left,
.markdown-editor__preview .align-left {
    text-align: left;
}
.blog-post-body .align-center,
.doc-body .align-center,
.album-description .align-center,
.markdown-editor__preview .align-center {
    text-align: center;
}
.blog-post-body .align-right,
.doc-body .align-right,
.album-description .align-right,
.markdown-editor__preview .align-right {
    text-align: right;
}

/* -- Albums (PhotoSwipe lightbox) -- */
/* Hover affordance so users see thumbnails are clickable. Transform-only so it stays cheap
   on the compositor. Gated behind prefers-reduced-motion. */
@media (prefers-reduced-motion: no-preference) {
    .album-item a {
        transition: transform 0.15s ease, box-shadow 0.15s ease;
    }
    .album-item a:hover,
    .album-item a:focus-visible {
        transform: scale(1.02);
        box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
    }
}
.album-item a:focus-visible {
    outline: 2px solid var(--bs-primary, #0d6efd);
    outline-offset: 2px;
    border-radius: 0.375rem;
}

/* PhotoSwipe caption block rendered by lightbox.js's custom-caption registration. */
.pswp__custom-caption {
    background: rgba(0, 0, 0, 0.6);
    color: #fff;
    font-size: 0.95rem;
    line-height: 1.4;
    padding: 0.5rem 1rem;
    position: absolute;
    left: 50%;
    bottom: 1rem;
    transform: translateX(-50%);
    max-width: min(90%, 60ch);
    border-radius: 0.375rem;
    text-align: center;
}
.pswp__custom-caption[hidden] {
    display: none;
}

/* ── User Tags (#555) ──
   A self-contained 8-hue palette, intentionally decoupled from the Bootstrap theme and the
   icon pack so tag colors stay stable regardless of the active theme. Each hue exposes its
   light-mode values; the [data-bs-theme=dark] block below remaps them for dark mode. Surfaces
   that show tags (form picker chips, grid pills, filter chips, quick-apply swatches) all reuse
   the same `.ccmf-tag` base + `.ccmf-tag-{hue}` color class. */
.ccmf-tag {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.125rem 0.5rem;
    font-size: 0.8125rem;
    line-height: 1.3;
    font-weight: 500;
    border-radius: 1rem;
    border: 1px solid var(--ccmf-tag-border, #cbd5e1);
    background-color: var(--ccmf-tag-bg, #f1f5f9);
    color: var(--ccmf-tag-fg, #334155);
    white-space: nowrap;
    max-width: 100%;
}

.ccmf-tag-name {
    overflow: hidden;
    text-overflow: ellipsis;
}

.ccmf-tag-remove {
    appearance: none;
    border: 0;
    background: transparent;
    color: inherit;
    opacity: 0.7;
    font-size: 1rem;
    line-height: 1;
    padding: 0 0.1rem;
    cursor: pointer;
    border-radius: 50%;
}

.ccmf-tag-remove:hover,
.ccmf-tag-remove:focus-visible {
    opacity: 1;
}

/* Small color dot used in the picker dropdown and quick-apply menu. */
.ccmf-tag-swatch {
    display: inline-block;
    width: 0.85rem;
    height: 0.85rem;
    border-radius: 50%;
    flex: 0 0 auto;
    border: 1px solid var(--ccmf-tag-border, #cbd5e1);
    background-color: var(--ccmf-tag-bg, #f1f5f9);
}

/* Light-mode hue definitions. */
.ccmf-tag-slate  { --ccmf-tag-bg: #f1f5f9; --ccmf-tag-fg: #334155; --ccmf-tag-border: #cbd5e1; }
.ccmf-tag-rose   { --ccmf-tag-bg: #ffe4e6; --ccmf-tag-fg: #9f1239; --ccmf-tag-border: #fda4af; }
.ccmf-tag-amber  { --ccmf-tag-bg: #fef3c7; --ccmf-tag-fg: #92400e; --ccmf-tag-border: #fcd34d; }
.ccmf-tag-teal   { --ccmf-tag-bg: #ccfbf1; --ccmf-tag-fg: #115e59; --ccmf-tag-border: #5eead4; }
.ccmf-tag-violet { --ccmf-tag-bg: #ede9fe; --ccmf-tag-fg: #5b21b6; --ccmf-tag-border: #c4b5fd; }
.ccmf-tag-green  { --ccmf-tag-bg: #dcfce7; --ccmf-tag-fg: #166534; --ccmf-tag-border: #86efac; }
.ccmf-tag-blue   { --ccmf-tag-bg: #dbeafe; --ccmf-tag-fg: #1e40af; --ccmf-tag-border: #93c5fd; }
.ccmf-tag-gray   { --ccmf-tag-bg: #e5e7eb; --ccmf-tag-fg: #374151; --ccmf-tag-border: #d1d5db; }

/* Dark-mode hue remaps — muted fills with bright text for contrast on dark surfaces. */
[data-bs-theme="dark"] .ccmf-tag-slate  { --ccmf-tag-bg: #334155; --ccmf-tag-fg: #e2e8f0; --ccmf-tag-border: #475569; }
[data-bs-theme="dark"] .ccmf-tag-rose   { --ccmf-tag-bg: #881337; --ccmf-tag-fg: #fecdd3; --ccmf-tag-border: #be123c; }
[data-bs-theme="dark"] .ccmf-tag-amber  { --ccmf-tag-bg: #78350f; --ccmf-tag-fg: #fde68a; --ccmf-tag-border: #b45309; }
[data-bs-theme="dark"] .ccmf-tag-teal   { --ccmf-tag-bg: #134e4a; --ccmf-tag-fg: #99f6e4; --ccmf-tag-border: #0f766e; }
[data-bs-theme="dark"] .ccmf-tag-violet { --ccmf-tag-bg: #4c1d95; --ccmf-tag-fg: #ddd6fe; --ccmf-tag-border: #6d28d9; }
[data-bs-theme="dark"] .ccmf-tag-green  { --ccmf-tag-bg: #14532d; --ccmf-tag-fg: #bbf7d0; --ccmf-tag-border: #15803d; }
[data-bs-theme="dark"] .ccmf-tag-blue   { --ccmf-tag-bg: #1e3a8a; --ccmf-tag-fg: #bfdbfe; --ccmf-tag-border: #1d4ed8; }
[data-bs-theme="dark"] .ccmf-tag-gray   { --ccmf-tag-bg: #374151; --ccmf-tag-fg: #e5e7eb; --ccmf-tag-border: #4b5563; }

/* Tag filter chips on /Pieces: a toggle-button variant of the pill. */
.ccmf-tag-filter {
    cursor: pointer;
    user-select: none;
    opacity: 0.65;
    transition: opacity 0.12s ease, box-shadow 0.12s ease;
}

@media (prefers-reduced-motion: reduce) {
    .ccmf-tag-filter { transition: none; }
}

.ccmf-tag-filter:hover {
    opacity: 0.9;
}

.ccmf-tag-filter[aria-pressed="true"] {
    opacity: 1;
    box-shadow: 0 0 0 2px var(--ccmf-tag-fg, #334155) inset;
}

/* Compact pill variant used on card-grid items where vertical space is tight. */
.ccmf-tag-sm {
    padding: 0.05rem 0.4rem;
    font-size: 0.72rem;
    line-height: 1.25;
}

/* Quick-apply "+" affordance on grid rows / cards and its checkbox menu. */
.ccmf-tag-add-btn {
    --bs-btn-padding-y: 0.05rem;
    --bs-btn-padding-x: 0.3rem;
    --bs-btn-font-size: 0.72rem;
    line-height: 1;
}

.ccmf-tag-add-btn .bi-plus {
    margin-left: -0.15rem;
}

.ccmf-tag-menu .dropdown-item:active,
.ccmf-tag-menu .dropdown-item:focus {
    background-color: var(--bs-tertiary-bg);
    color: inherit;
}

/* The quick-apply menu is portaled to <body> and fixed-positioned (#555 Slice 2b) so it escapes the
   Tabulator cell/tableholder `overflow:hidden` clipping. JS sets its top/left; these rules size it and
   lift it above sticky chrome. It keeps Bootstrap's .dropdown-menu base styling (bg/border/shadow). */
.ccmf-tag-menu {
    position: fixed;
    z-index: 1080;
    min-width: 14rem;
    max-height: 16rem;
    overflow-y: auto;
    margin: 0;
}

/* Inline "create a new tag" row pinned under the checkbox list. */
.ccmf-tag-create {
    border-top: 1px solid var(--bs-border-color);
}

.ccmf-tag-create .form-control {
    min-width: 0;
}

/* Keep the bulk-selection checkbox column visually quiet. */
.ccmf-select-col {
    color: var(--bs-secondary-color);
}

/* ── Breadcrumbs (#564) ──
   Single source of truth for the site-wide breadcrumb trail rendered by
   Views/Shared/_Breadcrumbs.cshtml. Bootstrap 5.3 already adapts the divider
   and active-segment colours via data-bs-theme, so the work here is the
   responsive truncation the acceptance criteria call for: keep the trail on
   one line and ellipsize long segments rather than wrapping. Full labels stay
   in the DOM (title="…") so nothing is lost to assistive tech. */
.ccmf-breadcrumb-nav .breadcrumb {
    flex-wrap: nowrap;
    margin-bottom: 0;
}
.ccmf-breadcrumb-nav .breadcrumb-item {
    min-width: 0; /* let flex items shrink so ellipsis can engage */
}
.ccmf-breadcrumb-nav .breadcrumb-item > a,
.ccmf-breadcrumb-nav .breadcrumb-item.active {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
}
@media (max-width: 575.98px) {
    /* On phones, cap the intermediate (non-first, non-current) segments hard so
       the root and the current page stay readable; the current page gets a
       larger share. */
    .ccmf-breadcrumb-nav .breadcrumb-item:not(:first-child):not(.active) > a {
        max-width: 6rem;
    }
    .ccmf-breadcrumb-nav .breadcrumb-item.active {
        max-width: 12rem;
    }
}

/* ── FAQ help-centre layout (Docs/Section.cshtml, FAQ section) ─────────────────
   Notion-style: a centred hero search, a responsive grid of topic cards (the
   default view), and a single-topic detail view revealed on demand. Visibility is
   JS-driven via the `.faq--js` class added to [data-faq-root] on load; without JS
   the grid and the full topic list both render (progressive enhancement), so every
   answer stays reachable. */

.faq-hero-title {
    font-weight: 700;
}

.faq-hero-search {
    position: relative;
    max-width: 36rem;
}

.faq-hero-search .faq-hero-search-icon {
    position: absolute;
    left: 0.95rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--bs-secondary-color);
    pointer-events: none;
    z-index: 2;
}

.faq-hero-search .ccmf-search-input {
    padding-left: 2.5rem;
    border-radius: 2rem;
}

/* Topic card grid. auto-fill + minmax yields 1→N columns with no media queries;
   min(100%, 17rem) lets a card collapse to the full width at 320px. The
   :not([hidden]) guard lets the JS `hidden` property (grid/search/topic modes)
   win over this display:grid rule. */
.faq-grid:not([hidden]) {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
    gap: 1rem;
    margin-top: 0.5rem;
}

.faq-card {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: 1.1rem 1.15rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 0.75rem;
    background: var(--bs-body-bg);
    cursor: pointer;
}

.faq-card-head {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-bottom: 0.65rem;
}

.faq-card-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 0.6rem;
    font-size: 1.1rem;
    background: var(--bs-tertiary-bg);
    color: var(--bs-emphasis-color);
}

.faq-card-title {
    flex: 1 1 auto;
    min-width: 0;
}

.faq-card-title a {
    color: var(--bs-emphasis-color);
    text-decoration: none;
}

.faq-card-count {
    flex: 0 0 auto;
    background: var(--bs-tertiary-bg);
    color: var(--bs-secondary-color);
}

.faq-card-links {
    flex: 1 1 auto;
    list-style: none;
    margin: 0 0 0.75rem;
    padding: 0;
}

.faq-card-links li {
    margin-bottom: 0.3rem;
    font-size: 0.92rem;
    line-height: 1.35;
}

.faq-card-links a {
    color: var(--bs-secondary-color);
    text-decoration: none;
}

.faq-card-links a:hover {
    color: var(--bs-link-hover-color);
    text-decoration: underline;
}

.faq-card-all {
    margin-top: auto;
    font-size: 0.9rem;
    font-weight: 600;
    text-decoration: none;
}

.faq-card-all .bi {
    transition: transform 0.15s ease;
}

.faq-card:hover .faq-card-all .bi {
    transform: translateX(3px);
}

/* Detail view */
.faq-detail-bar {
    margin-bottom: 1.25rem;
}

.faq-back {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin-bottom: 0.85rem;
    font-size: 0.95rem;
    text-decoration: none;
}

.faq-detail-nav {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.faq-chip {
    border: 1px solid var(--bs-border-color);
    background: var(--bs-body-bg);
    color: var(--bs-secondary-color);
    font-weight: 500;
    text-decoration: none;
}

.faq-chip .faq-chip-count {
    margin-left: 0.25rem;
    opacity: 0.6;
}

.faq-chip:hover {
    border-color: var(--bs-primary);
    color: var(--bs-primary);
}

.faq-chip.is-active {
    background: var(--bs-primary);
    border-color: var(--bs-primary);
    color: #fff;
}

.faq-chip.is-active:hover {
    color: #fff;
}

.faq-chip.is-active .faq-chip-count {
    opacity: 0.85;
}

.faq-topic-group {
    margin-bottom: 2rem;
}

.faq-topic-heading {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 1rem;
    outline: none;
}

/* Programmatic focus lands here on topic drill-in; show a visible ring only
   when the topic was opened via keyboard so mouse clicks stay clean. */
.faq-topic-heading:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: 4px;
    border-radius: 0.25rem;
}

.faq-topic-heading-icon {
    color: var(--bs-secondary-color);
}

.faq-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.faq-item {
    border: 1px solid var(--bs-border-color);
    border-radius: 0.6rem;
    background: var(--bs-body-bg);
    overflow: hidden;
}

.faq-item-summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.85rem 1rem;
    font-weight: 600;
    cursor: pointer;
    list-style: none;
}

.faq-item-summary::-webkit-details-marker {
    display: none;
}

.faq-item-chevron {
    flex: 0 0 auto;
    color: var(--bs-secondary-color);
    transition: transform 0.2s ease;
}

.faq-item[open] .faq-item-chevron {
    transform: rotate(180deg);
}

.faq-item-body {
    padding: 0 1rem 1rem;
}

/* Hover lift — only when the user hasn't asked for reduced motion. */
@media (prefers-reduced-motion: no-preference) {
    .faq-card {
        transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
    }

    .faq-card:hover {
        transform: translateY(-2px);
        border-color: var(--bs-primary);
        box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
    }
}

@media (prefers-reduced-motion: reduce) {
    .faq-item-chevron,
    .faq-card-all .bi {
        transition: none;
    }
}

.faq-card:focus-within {
    border-color: var(--bs-primary);
}

/* Dark theme — deeper hover shadow against the darker surface. */
[data-bs-theme="dark"] .faq-card:hover {
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
}

/* ── Cookie Consent Banner (#944 L2.1) ── */
.ccmf-cookie-consent {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1030; /* Bootstrap "fixed" level: above page chrome, below modals/offcanvas so an open modal sits on top */
    background: var(--bs-body-bg, #fff);
    border-top: 1px solid var(--bs-border-color, #dee2e6);
    box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.12);
    padding: 0.875rem 1rem;
}

.ccmf-cookie-consent[hidden] {
    display: none;
}

.ccmf-cookie-consent__inner {
    max-width: 1200px;
    margin: 0 auto;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem 1.5rem;
}

.ccmf-cookie-consent__body {
    flex: 1 1 320px;
    min-width: 0;
}

.ccmf-cookie-consent__text {
    font-size: 0.9rem;
    color: var(--bs-secondary-color, #6c757d);
}

.ccmf-cookie-consent__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.ccmf-cookie-consent__btn {
    min-height: 2.5rem; /* >=24px target; comfortable tap size */
}

@media (max-width: 575.98px) {
    .ccmf-cookie-consent__actions {
        width: 100%;
    }
    .ccmf-cookie-consent__btn {
        flex: 1 1 auto;
    }
}

/* Footer "Cookie preferences" trigger styled as a link to match its siblings. */
.ccmf-cookie-prefs-link {
    background: none;
    border: 0;
    padding: 0;
    color: #6c757d;
    text-decoration: none;
    font-size: 0.85rem;
    cursor: pointer;
}

.ccmf-cookie-prefs-link:hover,
.ccmf-cookie-prefs-link:focus-visible {
    color: var(--ccmf-blue);
    text-decoration: underline;
}

[data-bs-theme="dark"] .ccmf-cookie-consent {
    box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.5);
}

/* ──────────────────────────────────────────────────────────────────────────
   Unified search (issue #700)
   Navbar typeahead dropdown + Cmd/Ctrl+K command palette.
   Shared scope-row + result-row markup keeps the dropdown and palette
   visually consistent without each owning their own template.
   ────────────────────────────────────────────────────────────────────────── */

/* ── Navbar input ────────────────────────────────────────────────────────── */
.navbar-search-wrap {
    flex: 1 1 auto;
    max-width: 28rem;
    margin: 0 0.75rem;
}

.navbar-search-form {
    width: 100%;
}

.navbar-search-input-group {
    width: 100%;
    position: relative;
}

.navbar-search-icon {
    position: absolute;
    top: 50%;
    left: 0.625rem;
    transform: translateY(-50%);
    color: var(--bs-secondary-color);
    pointer-events: none;
    font-size: 0.95rem;
}

.navbar-search-input {
    padding-left: 2rem;
    padding-right: 3rem;
    height: 36px;
    border-radius: 999px;
    background: var(--bs-tertiary-bg);
    border-color: transparent;
    transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.navbar-search-input::placeholder {
    color: var(--bs-secondary-color);
    opacity: 0.85;
}

.navbar-search-input:focus,
.navbar-search-input:focus-visible {
    background: var(--bs-body-bg);
    border-color: var(--bs-primary);
    box-shadow: 0 0 0 0.2rem rgba(var(--bs-primary-rgb), 0.25);
    outline: none;
}

.navbar-search-kbd {
    position: absolute;
    top: 50%;
    right: 0.375rem;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    text-decoration: none;
    min-width: 32px;
    min-height: 24px;
}

.navbar-search-kbd:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
    border-radius: 4px;
}

.navbar-search-kbd-key {
    font-size: 0.7rem;
    background: var(--bs-secondary-bg);
    color: var(--bs-body-color);
    border: 1px solid var(--bs-border-color);
    padding: 0.05rem 0.4rem;
    border-radius: 4px;
    font-family: inherit;
    line-height: 1.4;
}

.navbar-search-mobile-btn {
    min-width: 36px;
    min-height: 36px;
}

/* ── Dropdown (typeahead) ────────────────────────────────────────────────── */
.navbar-search-dropdown {
    position: absolute;
    top: calc(100% + 0.375rem);
    left: 0;
    right: 0;
    z-index: 1050;
    max-height: 32rem;
    overflow-y: auto;
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: 0.5rem;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
}

[data-bs-theme="dark"] .navbar-search-dropdown,
[data-bs-theme="dark"] .search-palette-panel {
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}

/* ── Shared dropdown + palette result rows ───────────────────────────────── */
.unified-search-group-heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.5rem 0.875rem 0.25rem;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--bs-secondary-color);
    background: transparent;
}

.unified-search-group-heading .see-all-link {
    font-size: 0.7rem;
    font-weight: 500;
    text-transform: none;
    letter-spacing: normal;
}

.unified-search-result {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.5rem 0.875rem;
    min-height: 44px;
    color: var(--bs-body-color);
    text-decoration: none;
    border-left: 3px solid transparent;
    transition: background-color 0.1s ease, border-left-color 0.1s ease;
}

.unified-search-result:hover,
.unified-search-result:focus,
.unified-search-result.is-active {
    background: var(--bs-tertiary-bg);
    border-left-color: var(--bs-primary);
    color: var(--bs-body-color);
    text-decoration: none;
}

.unified-search-result:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: -2px;
}

.unified-search-result-icon {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    background: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
    font-size: 1rem;
}

.unified-search-result-text {
    flex: 1 1 auto;
    min-width: 0; /* enables truncation in flex child */
}

.unified-search-result-title {
    font-size: 0.9rem;
    color: var(--bs-body-color);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.unified-search-result-subtitle {
    font-size: 0.78rem;
    color: var(--bs-secondary-color);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.unified-search-result-barcode {
    background: rgba(var(--bs-primary-rgb), 0.08);
    border-left-color: var(--bs-primary);
}

.unified-search-empty,
.unified-search-loading {
    padding: 1.25rem 1rem;
    text-align: center;
    color: var(--bs-secondary-color);
    font-size: 0.875rem;
}

/* ── Command palette modal ───────────────────────────────────────────────── */
.search-palette {
    position: fixed;
    inset: 0;
    z-index: 1080;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 4rem 1rem 1rem;
}

.search-palette[hidden] {
    display: none;
}

.search-palette-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    backdrop-filter: blur(2px);
    animation: search-palette-fade-in 0.15s ease;
}

.search-palette-panel {
    position: relative;
    width: 100%;
    max-width: 38rem;
    max-height: calc(100vh - 6rem);
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: 0.75rem;
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.25);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    animation: search-palette-slide-in 0.15s ease;
}

.search-palette-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.875rem 1rem;
    border-bottom: 1px solid var(--bs-border-color);
}

.search-palette-search-icon {
    color: var(--bs-secondary-color);
    font-size: 1.15rem;
}

.search-palette-input {
    flex: 1 1 auto;
    border: 0;
    background: transparent;
    font-size: 1rem;
    color: var(--bs-body-color);
    outline: none;
    padding: 0.25rem 0;
}

.search-palette-input::placeholder {
    color: var(--bs-secondary-color);
}

.search-palette-esc {
    font-size: 0.7rem;
    background: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
    border: 1px solid var(--bs-border-color);
    padding: 0.05rem 0.4rem;
    border-radius: 4px;
}

.search-palette-close {
    min-width: 32px;
    min-height: 32px;
    color: var(--bs-secondary-color);
    padding: 0.25rem;
}

.search-palette-close:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
    border-radius: 4px;
}

.search-palette-results {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 0.25rem 0;
}

.search-palette-footer {
    border-top: 1px solid var(--bs-border-color);
    padding: 0.5rem 1rem;
    font-size: 0.75rem;
    color: var(--bs-secondary-color);
    background: var(--bs-tertiary-bg);
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.search-palette-footer-note {
    font-size: 0.7rem;
}

.search-palette-footer-note code {
    font-size: 0.7rem;
    padding: 0 0.2rem;
}

.search-palette-footer kbd {
    background: var(--bs-secondary-bg);
    color: var(--bs-body-color);
    border: 1px solid var(--bs-border-color);
    padding: 0.05rem 0.3rem;
    border-radius: 3px;
    font-size: 0.7rem;
    margin: 0 0.1rem 0 0.3rem;
}

/* Recent searches surfaced when the palette opens with an empty input. */
.search-palette-recent-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.875rem;
    min-height: 36px;
    cursor: pointer;
    color: var(--bs-body-color);
    background: transparent;
    border: 0;
    width: 100%;
    text-align: left;
}

.search-palette-recent-row:hover,
.search-palette-recent-row:focus,
.search-palette-recent-row.is-active {
    background: var(--bs-tertiary-bg);
}

.search-palette-recent-row:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: -2px;
}

.search-palette-recent-icon {
    color: var(--bs-secondary-color);
    font-size: 0.9rem;
}

/* ── Hide kbd-hint on coarse pointers / narrow screens ───────────────────── */
@media (max-width: 991.98px) {
    .navbar-search-kbd {
        display: none;
    }
    .navbar-search-input {
        padding-right: 0.75rem;
    }
}

/* ── Reduced motion: drop the entry animations ───────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    .search-palette-backdrop,
    .search-palette-panel,
    .navbar-search-input,
    .unified-search-result {
        animation: none;
        transition: none;
    }
}

@keyframes search-palette-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes search-palette-slide-in {
    from { opacity: 0; transform: translateY(-8px); }
    to   { opacity: 1; transform: translateY(0); }
}

