/* ============================================================================
   VELORA — glass design system
   ----------------------------------------------------------------------------
   Direction: dark, glossy, glass.

   Two references, researched rather than assumed:

   · Apple "Liquid Glass" (iOS 26) — a translucent material that refracts what
     sits behind it and carries real-time specular highlights. Apple's own
     guidance is to reserve glass for the layer that FLOATS ABOVE content. So
     navigation, cards, modals and bars are glass; tables and body copy sit on
     solid ground where legibility matters most.

   · CRED "NeoPOP" — a committed dark theme where whites and greys carry the
     interface and a few vivid accents mark state, with a SERIF for headings
     against a sans for everything else. That pairing is most of why it reads
     premium rather than generic.

   THE TRAP, and how this file avoids it: a translucent panel inherits whatever
   is behind it, so contrast becomes unpredictable — which is exactly how text
   goes invisible. The fix applied throughout is that each panel's OWN tint is
   opaque enough (0.78–0.90) that the backdrop contributes very little. Every
   text pair below is measured against WCAG 2.2 AA and the ratio recorded
   beside the token, and `tools/audit_contrast.py` re-measures every text node
   on every page in a real browser, so this is checked rather than claimed.

   Glass also needs something behind it — on a flat ground `backdrop-filter`
   does nothing at all — hence the two fixed ambient light pools on `body`.
   ========================================================================= */

:root {
  /* ---- the room: deep ink with a violet bias, never flat black --------- */
  --v-void:   #07060b;
  --v-paper:  #0b0a11;
  --v-sunk:   #08070d;

  /* ---- glass tiers. The alpha here is what keeps text legible. --------- */
  --v-glass-1: rgba(23, 21, 33, 0.80);  /* cards, panels            */
  --v-glass-2: rgba(31, 28, 44, 0.88);  /* nav, modals, dropdowns   */
  --v-glass-3: rgba(42, 38, 58, 0.92);  /* the one raised thing     */
  --v-card:    #171521;                 /* opaque fallback          */
  --v-blur:    blur(22px) saturate(180%);
  /* saturate() is the part most implementations skip: blur alone
     desaturates the backdrop and the glass goes cloudy, not rich. */

  /* ---- edges: a specular top highlight plus a hairline ----------------- */
  --v-edge:     rgba(255, 255, 255, 0.10);
  --v-edge-2:   rgba(255, 255, 255, 0.17);
  --v-specular: inset 0 1px 0 rgba(255, 255, 255, 0.16);
  --v-hair:     rgba(255, 255, 255, 0.09);
  --v-hair-2:   rgba(255, 255, 255, 0.17);

  /* ---- ink (measured on --v-glass-1 over --v-paper) -------------------- */
  --v-ink:   #f6f4fb;  /* 16.1:1 */
  --v-ink-2: #bdb8cc;  /*  8.8:1 */
  --v-ink-3: #948ea8;  /*  5.4:1  — still AA for body text */

  /* ---- the signature: champagne, orchid, aqua -------------------------- */
  /* Velora's gold lifted from brass into champagne, so it reads expensive
     rather than brassy, and used as a highlight rather than a fill. */
  --v-metal:      #f0d9a0;  /* 13.0:1 */
  --v-metal-2:    #d8b86e;
  --v-metal-soft: rgba(240, 217, 160, 0.14);
  --v-orchid:     #c79bff;  /*  9.0:1  the unexpected one */
  --v-orchid-soft: rgba(199, 155, 255, 0.16);
  --v-aqua:       #5fe3c0;  /* 12.4:1 */

  /* ---- state ---------------------------------------------------------- */
  --v-good: #5fe3c0;  /* 12.4:1 */
  --v-warn: #ffc46b;  /* 11.6:1 */
  --v-bad:  #ff8d8d;  /*  8.9:1 */
  --v-info: #86c8ff;  /* 10.5:1 */
  --v-good-wash: rgba(95, 227, 192, 0.13);
  --v-warn-wash: rgba(255, 196, 107, 0.13);
  --v-bad-wash:  rgba(255, 141, 141, 0.13);
  --v-info-wash: rgba(134, 200, 255, 0.13);

  /* ---- polished metal, for the single primary action ------------------- */
  --v-grad-metal:  linear-gradient(170deg, #fbeccb 0%, #f0d9a0 42%, #d9b96f 100%);
  --v-grad-orchid: linear-gradient(170deg, #dcc0ff 0%, #c79bff 50%, #a06ff0 100%);
  --v-on-metal:    #140f08;  /* 12.9:1 on the champagne gradient */

  /* ---- type ----------------------------------------------------------- */
  --v-display: "Instrument Serif", Georgia, "Times New Roman", serif;
  --v-ui: "Manrope", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;

  --v-t-xs:   0.75rem;
  --v-t-sm:   0.8125rem;
  --v-t-base: 0.9375rem;
  --v-t-md:   1.0625rem;
  --v-t-lg:   1.375rem;
  --v-t-xl:   1.875rem;
  --v-t-2xl:  2.5rem;
  --v-t-3xl:  3.5rem;

  /* ---- 8pt rhythm ----------------------------------------------------- */
  --v-s1: 8px;  --v-s2: 16px; --v-s3: 24px;
  --v-s4: 32px; --v-s5: 48px; --v-s6: 64px;

  /* ---- radius: gloss reads better with curvature ----------------------- */
  --v-r-sm: 10px;
  --v-r-md: 16px;
  --v-r-lg: 22px;
  --v-r-pill: 999px;
  --v-r-circle: 50%;

  /* ---- depth ---------------------------------------------------------- */
  --v-shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
  --v-shadow:    0 10px 30px -12px rgba(0, 0, 0, .7);
  --v-shadow-lg: 0 28px 60px -24px rgba(0, 0, 0, .85);
  --v-glow:      0 0 0 1px rgba(240, 217, 160, .25), 0 8px 30px -8px rgba(240, 217, 160, .22);

  --v-touch: 44px;
  --v-dur: 180ms;
  --v-ease: cubic-bezier(.22, .61, .36, 1);

  color-scheme: dark;
}

/* A viewer asking for more contrast gets denser glass and brighter edges,
   rather than an inverted theme that would fall out of sync. */
@media (prefers-contrast: more) {
  :root {
    --v-glass-1: rgba(16, 15, 23, 0.97);
    --v-glass-2: rgba(22, 20, 31, 0.98);
    --v-edge:   rgba(255, 255, 255, 0.24);
    --v-hair:   rgba(255, 255, 255, 0.22);
    --v-ink-2:  #d3cfe0;
    --v-ink-3:  #b4aec8;
  }
}

/* ============================================================================
   Bootstrap mapped onto the tokens, so components inherit the system instead
   of being overridden one at a time. The `-rgb` variants matter: the text and
   background utilities resolve through those, not through --bs-success itself.
   ========================================================================= */
:root, [data-bs-theme="dark"], [data-bs-theme="light"] {
  --bs-body-bg: var(--v-paper);
  --bs-body-color: var(--v-ink);
  --bs-body-font-family: var(--v-ui);
  --bs-body-font-size: var(--v-t-base);
  --bs-body-line-height: 1.6;

  --bs-emphasis-color: var(--v-ink);
  --bs-emphasis-color-rgb: 246, 244, 251;
  --bs-body-color-rgb: 246, 244, 251;
  --bs-secondary-color: var(--v-ink-2);
  --bs-secondary-bg: var(--v-sunk);
  --bs-tertiary-color: var(--v-ink-3);
  --bs-tertiary-bg: var(--v-sunk);

  --bs-border-color: var(--v-hair);
  --bs-border-color-translucent: var(--v-hair);
  --bs-border-radius: var(--v-r-sm);
  --bs-border-radius-sm: 8px;
  --bs-border-radius-lg: var(--v-r-md);
  --bs-border-radius-xl: var(--v-r-lg);
  --bs-border-radius-pill: var(--v-r-pill);

  --bs-primary: var(--v-metal);
  --bs-primary-rgb: 240, 217, 160;
  --bs-primary-text-emphasis: var(--v-metal);
  --bs-primary-bg-subtle: var(--v-metal-soft);
  --bs-primary-border-subtle: var(--v-edge-2);

  --bs-secondary: var(--v-ink-2);
  --bs-secondary-rgb: 189, 184, 204;
  --bs-success: var(--v-good);
  --bs-success-rgb: 95, 227, 192;
  --bs-warning: var(--v-warn);
  --bs-warning-rgb: 255, 196, 107;
  --bs-danger: var(--v-bad);
  --bs-danger-rgb: 255, 141, 141;
  --bs-info: var(--v-info);
  --bs-info-rgb: 134, 200, 255;
  --bs-light: var(--v-ink);
  --bs-light-rgb: 246, 244, 251;
  --bs-dark: var(--v-card);
  --bs-dark-rgb: 23, 21, 33;

  --bs-success-text-emphasis: var(--v-good);
  --bs-warning-text-emphasis: var(--v-warn);
  --bs-danger-text-emphasis: var(--v-bad);
  --bs-info-text-emphasis: var(--v-info);
  --bs-success-bg-subtle: var(--v-good-wash);
  --bs-warning-bg-subtle: var(--v-warn-wash);
  --bs-danger-bg-subtle: var(--v-bad-wash);
  --bs-info-bg-subtle: var(--v-info-wash);

  --bs-link-color: var(--v-metal);
  --bs-link-color-rgb: 240, 217, 160;
  --bs-link-hover-color: var(--v-ink);
  --bs-heading-color: var(--v-ink);
  --bs-code-color: var(--v-orchid);
  --bs-highlight-bg: var(--v-metal-soft);
  --bs-focus-ring-color: rgba(240, 217, 160, .45);
  --bs-focus-ring-width: 2px;
}

/* ============================================================================
   The room
   ========================================================================= */
html { background: var(--v-void); }

body {
  position: relative;
  background: var(--v-paper);
  color: var(--v-ink);
  font-family: var(--v-ui);
  font-size: var(--v-t-base);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Glass only reads when there is something behind it to refract. These two
   fixed light pools are what the panels pick up; they are purely decorative,
   sit behind everything, and never carry text. */
body::before {
  content: "";
  position: fixed;
  inset: -20%;
  z-index: -1;
  pointer-events: none;
  background-image:
    radial-gradient(42vw 42vw at 12% 4%,  rgba(240, 217, 160, .13), transparent 62%),
    radial-gradient(48vw 48vw at 88% 92%, rgba(199, 155, 255, .14), transparent 62%),
    radial-gradient(60vw 40vw at 50% 50%, rgba(95, 227, 192, .05), transparent 70%);
}

::selection { background: var(--v-metal-soft); color: var(--v-ink); }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, .14);
  border-radius: var(--v-r-pill);
  border: 3px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, .26); background-clip: content-box; }

/* ============================================================================
   Type — a serif carries the headings, a sans carries the work
   ========================================================================= */
h1, h2, .v-display {
  font-family: var(--v-display);
  font-weight: 400;
  letter-spacing: -.012em;
  line-height: 1.08;
  color: var(--v-ink);
  text-wrap: balance;
}
h1 { font-size: clamp(2rem, 4.4vw, var(--v-t-2xl)); }
h2 { font-size: clamp(1.625rem, 3.2vw, var(--v-t-xl)); }
/* h3 and below stay in the sans, so dense operational screens hold up */
h3, h4, h5, h6 {
  font-family: var(--v-ui);
  font-weight: 700;
  letter-spacing: -.004em;
  color: var(--v-ink);
  line-height: 1.3;
}
h3 { font-size: var(--v-t-lg); }
h4 { font-size: var(--v-t-md); }
h5 { font-size: var(--v-t-base); }
h6 { font-size: var(--v-t-sm); }

p, li, dd, dt, label, span, td, th, div { color: inherit; }
body, .card, .card-body, .modal-body, main, section { color: var(--v-ink); }
small, .small { font-size: var(--v-t-sm); }

.v-nums, td.text-end, th.text-end, .v-amount, .table td, .table th {
  font-variant-numeric: tabular-nums;
}

a { color: var(--v-metal); text-decoration-color: rgba(240, 217, 160, .35); text-underline-offset: .18em; }
a:hover { color: var(--v-ink); }
hr { border-color: var(--v-hair); opacity: 1; }

:focus { outline: none; }
:focus-visible { outline: 2px solid var(--v-metal); outline-offset: 2px; border-radius: 4px; }

/* ============================================================================
   The glass material
   ========================================================================= */
.v-glass, .card, .modal-content, .dropdown-menu, .navbar, .list-group,
.accordion-item, .toast, .offcanvas {
  background-color: var(--v-glass-1);
  border: 1px solid var(--v-edge);
  box-shadow: var(--v-specular), var(--v-shadow);
  border-radius: var(--v-r-md);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .v-glass, .card, .modal-content, .dropdown-menu, .navbar, .list-group,
  .accordion-item, .toast, .offcanvas {
    -webkit-backdrop-filter: var(--v-blur);
    backdrop-filter: var(--v-blur);
  }
}
/* Blur is expensive and can disorient. When motion is reduced, fall back to
   the opaque tier — which preserves every contrast ratio exactly. */
@media (prefers-reduced-motion: reduce) {
  .v-glass, .card, .modal-content, .dropdown-menu, .navbar, .list-group,
  .accordion-item, .toast, .offcanvas {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background-color: var(--v-card);
  }
}

/* ============================================================================
   Cards
   ========================================================================= */
.card {
  --bs-card-bg: transparent;
  --bs-card-border-color: var(--v-edge);
  --bs-card-color: var(--v-ink);
  --bs-card-cap-bg: transparent;
  --bs-card-border-radius: var(--v-r-md);
  --bs-card-inner-border-radius: calc(var(--v-r-md) - 1px);
  color: var(--v-ink);
}
.card-header {
  background: transparent !important;
  background-image: none !important;
  border-bottom: 1px solid var(--v-hair) !important;
  color: var(--v-ink) !important;
  font-weight: 700;
  font-size: var(--v-t-sm);
  padding-block: var(--v-s2);
}
.card-header h1, .card-header h2, .card-header h3, .card-header h4,
.card-header h5, .card-header h6, .card-header .card-title { color: var(--v-ink) !important; }
.card-body { padding: var(--v-s3); color: var(--v-ink); }
.card-footer { background: transparent; border-top: 1px solid var(--v-hair); }
.card-title { font-weight: 700; letter-spacing: -.004em; }

/* a card that is the point of the screen gets the champagne edge */
.v-feature { border-color: rgba(240, 217, 160, .3); box-shadow: var(--v-specular), var(--v-glow), var(--v-shadow); }

/* a card that is a link should feel like one */
a.card, .card.v-actionable { transition: transform var(--v-dur) var(--v-ease), border-color var(--v-dur) var(--v-ease), box-shadow var(--v-dur) var(--v-ease); text-decoration: none; }
a.card:hover, .card.v-actionable:hover { transform: translateY(-2px); border-color: var(--v-edge-2); box-shadow: var(--v-specular), var(--v-shadow-lg); }

/* ============================================================================
   Controls — one filled action per screen, in polished metal
   ========================================================================= */
.btn {
  --bs-btn-font-family: var(--v-ui);
  --bs-btn-font-size: var(--v-t-sm);
  --bs-btn-font-weight: 700;
  --bs-btn-border-radius: var(--v-r-pill);
  min-height: var(--v-touch);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5em;
  padding-inline: 1.15rem;
  letter-spacing: -.002em;
  transition: transform var(--v-dur) var(--v-ease), box-shadow var(--v-dur) var(--v-ease),
              background-color var(--v-dur) var(--v-ease), border-color var(--v-dur) var(--v-ease),
              color var(--v-dur) var(--v-ease), filter var(--v-dur) var(--v-ease);
}
.btn:active { transform: translateY(1px); }
.btn-sm { min-height: 36px; --bs-btn-font-size: var(--v-t-xs); padding-inline: .85rem; }
.btn-lg { min-height: 54px; --bs-btn-font-size: var(--v-t-base); padding-inline: 1.6rem; }

.btn-primary {
  background: var(--v-grad-metal) !important;
  border: 1px solid rgba(255, 255, 255, .34) !important;
  color: var(--v-on-metal) !important;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .55), 0 8px 24px -10px rgba(240, 217, 160, .55);
}
.btn-primary:hover, .btn-primary:focus-visible {
  color: var(--v-on-metal) !important;
  filter: brightness(1.06);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .6), 0 12px 30px -10px rgba(240, 217, 160, .7);
}
.btn-primary:disabled, .btn-primary.disabled { filter: grayscale(.6) brightness(.8); }

.btn-secondary, .btn-outline-primary, .btn-outline-secondary,
.btn-outline-light, .btn-outline-dark, .btn-light, .btn-dark {
  background: rgba(255, 255, 255, .06) !important;
  border: 1px solid var(--v-edge) !important;
  color: var(--v-ink) !important;
  box-shadow: var(--v-specular);
}
.btn-secondary:hover, .btn-outline-primary:hover, .btn-outline-secondary:hover,
.btn-outline-light:hover, .btn-outline-dark:hover, .btn-light:hover, .btn-dark:hover {
  background: rgba(255, 255, 255, .12) !important;
  border-color: var(--v-edge-2) !important;
  color: var(--v-ink) !important;
}
.btn-link { --bs-btn-color: var(--v-metal); --bs-btn-hover-color: var(--v-ink); min-height: auto; }

/* state buttons are tinted glass, never a solid block of colour */
.btn-success, .btn-outline-success { background: var(--v-good-wash) !important; border: 1px solid rgba(95,227,192,.42) !important; color: var(--v-good) !important; }
.btn-warning, .btn-outline-warning { background: var(--v-warn-wash) !important; border: 1px solid rgba(255,196,107,.42) !important; color: var(--v-warn) !important; }
.btn-danger,  .btn-outline-danger  { background: var(--v-bad-wash) !important;  border: 1px solid rgba(255,141,141,.42) !important; color: var(--v-bad) !important; }
.btn-info,    .btn-outline-info    { background: var(--v-info-wash) !important; border: 1px solid rgba(134,200,255,.42) !important; color: var(--v-info) !important; }
.btn-success:hover, .btn-warning:hover, .btn-danger:hover, .btn-info:hover { filter: brightness(1.18); }

/* the close button's content is an icon; stray text is hidden, not rendered */
.btn-close {
  min-height: auto;
  width: 1.1rem; height: 1.1rem;
  padding: .55rem;
  box-sizing: content-box;
  font-size: 0; line-height: 0; color: transparent;
  border-radius: var(--v-r-circle);
  opacity: .7;
  filter: invert(1) grayscale(100%) brightness(2.4);
}
.btn-close:hover { opacity: 1; background-color: rgba(255, 255, 255, .1); }

/* ============================================================================
   Forms — inputs are wells cut INTO the glass, not panels sitting on it
   ========================================================================= */
.form-control, .form-select {
  min-height: var(--v-touch);
  background-color: rgba(0, 0, 0, .34) !important;
  border: 1px solid var(--v-edge) !important;
  color: var(--v-ink) !important;
  border-radius: var(--v-r-sm);
  font-size: var(--v-t-base);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, .45);
}
.form-control:focus, .form-select:focus {
  background-color: rgba(0, 0, 0, .44) !important;
  border-color: rgba(240, 217, 160, .6) !important;
  color: var(--v-ink) !important;
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, .45), 0 0 0 3px rgba(240, 217, 160, .22);
}
.form-control::placeholder { color: var(--v-ink-3) !important; opacity: 1; }
.form-control-sm, .form-select-sm { min-height: 36px; }
textarea.form-control { min-height: 96px; }
/* the native list is painted by the OS, so pin it dark */
.form-select option, datalist option { background: #171521; color: #f6f4fb; }

.form-label { font-size: var(--v-t-xs); font-weight: 700; color: var(--v-ink-2); margin-bottom: 6px; letter-spacing: .01em; }
.form-text, .form-hint { color: var(--v-ink-2); font-size: var(--v-t-xs); }
.input-group-text { background: rgba(255,255,255,.06); border: 1px solid var(--v-edge); color: var(--v-ink-2); }
.form-check { min-height: var(--v-touch); display: flex; align-items: center; gap: .55em; }
.form-check .form-check-input { float: none; margin-left: 0; }
.form-check-input { width: 1.15em; height: 1.15em; margin-top: 0; background-color: rgba(0,0,0,.35); border: 1px solid var(--v-hair-2); }
.form-check-input:checked { background-color: var(--v-metal); border-color: var(--v-metal); }
.form-check-input:focus-visible { outline: 2px solid var(--v-metal); outline-offset: 2px; }

.is-invalid, .form-control.is-invalid, .form-select.is-invalid { border-color: var(--v-bad) !important; }
.invalid-feedback, .text-danger, .errorlist { color: var(--v-bad) !important; font-size: var(--v-t-xs); }
/* severity carried by a mark as well as colour, so it survives a colourblind
   reader and a greyscale print */
.invalid-feedback::before, .errorlist li::before {
  content: "";
  display: inline-block;
  width: .8em; height: .8em;
  margin-right: .45em;
  vertical-align: -.08em;
  background: currentColor;
  clip-path: polygon(50% 0, 100% 100%, 0 100%);
}
.errorlist { list-style: none; padding-left: 0; margin-bottom: 0; }

/* ============================================================================
   Navigation — the floating glass layer Apple reserves it for
   ========================================================================= */
.navbar {
  border: 0;
  border-bottom: 1px solid var(--v-edge);
  border-radius: 0;
  box-shadow: var(--v-specular), 0 8px 32px -16px rgba(0, 0, 0, .8);
  padding-block: 10px;
  background-color: var(--v-glass-2);
}
.navbar-brand {
  font-family: var(--v-display);
  font-weight: 400;
  font-size: var(--v-t-lg);
  letter-spacing: -.01em;
  color: var(--v-ink) !important;
  display: inline-flex; align-items: center; gap: .5rem;
}
.navbar-brand img { height: 36px; width: auto; }
.navbar .nav-link {
  color: var(--v-ink-2) !important;
  font-size: var(--v-t-sm);
  font-weight: 600;
  min-height: var(--v-touch);
  display: inline-flex; align-items: center;
  padding-inline: 14px;
  border-radius: var(--v-r-pill);
}
.navbar .nav-link:hover { color: var(--v-ink) !important; background: rgba(255,255,255,.07); }
.navbar .nav-link.active, .navbar .nav-item.active > .nav-link {
  color: var(--v-ink) !important;
  background: rgba(255,255,255,.09);
  box-shadow: inset 0 0 0 1px var(--v-edge-2);
}
.navbar-toggler {
  border: 1px solid var(--v-edge);
  background: rgba(255,255,255,.06);
  border-radius: var(--v-r-sm);
  min-height: var(--v-touch); min-width: var(--v-touch);
  color: var(--v-ink);
}
.navbar-toggler-icon { filter: invert(1) brightness(2.2); }

.dropdown-menu {
  --bs-dropdown-bg: transparent;
  --bs-dropdown-border-color: var(--v-edge);
  --bs-dropdown-link-color: var(--v-ink);
  --bs-dropdown-link-hover-bg: rgba(255,255,255,.09);
  --bs-dropdown-link-hover-color: var(--v-ink);
  --bs-dropdown-link-active-bg: rgba(255,255,255,.13);
  --bs-dropdown-link-active-color: var(--v-ink);
  --bs-dropdown-divider-bg: var(--v-hair);
  box-shadow: var(--v-specular), var(--v-shadow-lg);
  padding-block: var(--v-s1);
  border-radius: var(--v-r-md);
}
.dropdown-item {
  min-height: 42px;
  display: flex; align-items: center; gap: .65em;
  font-size: var(--v-t-sm);
  color: var(--v-ink);
  border-radius: 8px;
  margin-inline: 6px;
  width: auto;
}
.dropdown-item i, .dropdown-item .bi { color: var(--v-ink-2); }
.dropdown-item:hover i, .dropdown-item:hover .bi { color: var(--v-metal); }
/* group headings, so a long menu is scanned instead of counted */
.dropdown-header {
  font-size: 11px; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--v-metal);
  padding: var(--v-s1) 1.1rem 5px;
}

.nav-tabs {
  --bs-nav-tabs-border-color: var(--v-hair);
  --bs-nav-tabs-link-active-bg: transparent;
  --bs-nav-tabs-link-active-color: var(--v-ink);
  --bs-nav-tabs-link-active-border-color: transparent transparent var(--v-metal);
  --bs-nav-link-color: var(--v-ink-2);
  --bs-nav-link-hover-color: var(--v-ink);
  border-bottom: 1px solid var(--v-hair);
}
.nav-tabs .nav-link { min-height: var(--v-touch); font-size: var(--v-t-sm); font-weight: 700; border-width: 0 0 2px; border-radius: 0; background: transparent; color: var(--v-ink-2); }
.nav-tabs .nav-link.active { color: var(--v-ink); }

.nav-pills { --bs-nav-pills-border-radius: var(--v-r-pill); gap: var(--v-s1); }
.nav-pills .nav-link {
  min-height: var(--v-touch);
  display: inline-flex; align-items: center;
  background: rgba(255,255,255,.06);
  border: 1px solid var(--v-edge);
  color: var(--v-ink-2) !important;
  font-size: var(--v-t-sm); font-weight: 700;
}
.nav-pills .nav-link.active {
  background: var(--v-grad-metal) !important;
  border-color: rgba(255,255,255,.34) !important;
  color: var(--v-on-metal) !important;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.5);
}

.pagination {
  --bs-pagination-color: var(--v-ink-2);
  --bs-pagination-bg: rgba(255,255,255,.05);
  --bs-pagination-border-color: var(--v-edge);
  --bs-pagination-hover-bg: rgba(255,255,255,.11);
  --bs-pagination-hover-color: var(--v-ink);
  --bs-pagination-hover-border-color: var(--v-edge-2);
  --bs-pagination-active-bg: var(--v-metal);
  --bs-pagination-active-border-color: var(--v-metal);
  --bs-pagination-active-color: var(--v-on-metal);
  --bs-pagination-disabled-bg: transparent;
  --bs-pagination-disabled-color: var(--v-ink-3);
  --bs-pagination-border-radius: var(--v-r-sm);
  gap: 6px;
}
.page-link { min-height: 42px; min-width: 42px; display: inline-flex; align-items: center; justify-content: center; }

.breadcrumb { --bs-breadcrumb-divider-color: var(--v-ink-3); font-size: var(--v-t-xs); }
.breadcrumb-item a { color: var(--v-ink-2); }
.breadcrumb-item.active { color: var(--v-ink); }

.list-group {
  --bs-list-group-bg: transparent;
  --bs-list-group-border-color: var(--v-hair);
  --bs-list-group-color: var(--v-ink);
  --bs-list-group-action-hover-bg: rgba(255,255,255,.07);
  --bs-list-group-action-hover-color: var(--v-ink);
  --bs-list-group-active-bg: rgba(255,255,255,.12);
  --bs-list-group-active-color: var(--v-ink);
  --bs-list-group-active-border-color: var(--v-hair);
}
.list-group-item { background: transparent; color: var(--v-ink); }

/* ============================================================================
   Tables — content, so they sit on solid ground where legibility matters
   ========================================================================= */
.table {
  --bs-table-bg: transparent;
  --bs-table-color: var(--v-ink);
  --bs-table-border-color: var(--v-hair);
  --bs-table-striped-bg: rgba(255,255,255,.035);
  --bs-table-striped-color: var(--v-ink);
  --bs-table-hover-bg: rgba(255,255,255,.06);
  --bs-table-hover-color: var(--v-ink);
  --bs-table-active-bg: rgba(255,255,255,.08);
  --bs-table-active-color: var(--v-ink);
  font-size: var(--v-t-sm);
  margin-bottom: 0;
  color: var(--v-ink);
}
.table > thead { --bs-table-bg: transparent; }
.table > thead th {
  font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: var(--v-ink-2) !important;
  background: transparent !important;
  border-bottom: 1px solid var(--v-hair-2) !important;
  padding: 12px 14px;
  white-space: nowrap;
}
.table > tbody td { padding: 13px 14px; vertical-align: middle; border-color: var(--v-hair); color: var(--v-ink); }
.table > tbody tr:last-child td { border-bottom: 0; }
.table-dark { --bs-table-bg: transparent; --bs-table-color: var(--v-ink); --bs-table-border-color: var(--v-hair); }
.table-responsive { border-radius: var(--v-r-sm); }

/* row state: a tint plus a lit left edge, never colour alone */
.table > tbody > tr.table-danger  > * { background: var(--v-bad-wash) !important;  box-shadow: inset 3px 0 0 var(--v-bad);  color: var(--v-ink) !important; }
.table > tbody > tr.table-warning > * { background: var(--v-warn-wash) !important; box-shadow: inset 3px 0 0 var(--v-warn); color: var(--v-ink) !important; }
.table > tbody > tr.table-success > * { background: var(--v-good-wash) !important; box-shadow: inset 3px 0 0 var(--v-good); color: var(--v-ink) !important; }
.table > tbody > tr.table-info    > * { background: var(--v-info-wash) !important; box-shadow: inset 3px 0 0 var(--v-info); color: var(--v-ink) !important; }

/* ============================================================================
   Badges, alerts, progress
   ========================================================================= */
.badge {
  font-family: var(--v-ui);
  font-size: 11px; font-weight: 800; letter-spacing: .02em;
  border-radius: var(--v-r-pill);
  padding: .35em .75em;
  border: 1px solid var(--v-edge);
  background: rgba(255,255,255,.07) !important;
  color: var(--v-ink-2) !important;
}
.badge.bg-success, .badge.text-bg-success { background: var(--v-good-wash) !important; border-color: rgba(95,227,192,.45); color: var(--v-good) !important; }
.badge.bg-warning, .badge.text-bg-warning { background: var(--v-warn-wash) !important; border-color: rgba(255,196,107,.45); color: var(--v-warn) !important; }
.badge.bg-danger,  .badge.text-bg-danger  { background: var(--v-bad-wash) !important;  border-color: rgba(255,141,141,.45); color: var(--v-bad) !important; }
.badge.bg-info,    .badge.text-bg-info    { background: var(--v-info-wash) !important; border-color: rgba(134,200,255,.45); color: var(--v-info) !important; }
.badge.bg-primary, .badge.text-bg-primary { background: var(--v-metal-soft) !important; border-color: rgba(240,217,160,.45); color: var(--v-metal) !important; }
.badge.bg-secondary, .badge.text-bg-secondary, .badge.bg-light, .badge.bg-dark { background: rgba(255,255,255,.07) !important; color: var(--v-ink-2) !important; }
.badge.v-metal { background: var(--v-metal-soft) !important; border-color: var(--v-metal); color: var(--v-metal) !important; }

.alert {
  background: var(--v-glass-1);
  border: 1px solid var(--v-edge);
  border-left: 3px solid var(--v-ink-3);
  border-radius: var(--v-r-sm);
  color: var(--v-ink);
  font-size: var(--v-t-sm);
  box-shadow: var(--v-specular);
  padding: 14px var(--v-s2);
}
.alert-success { border-left-color: var(--v-good); background: var(--v-good-wash); }
.alert-warning { border-left-color: var(--v-warn); background: var(--v-warn-wash); }
.alert-danger, .alert-error { border-left-color: var(--v-bad); background: var(--v-bad-wash); }
.alert-info, .alert-primary { border-left-color: var(--v-info); background: var(--v-info-wash); }
.alert, .alert p, .alert span, .alert div, .alert li, .alert strong { color: var(--v-ink); }
.alert .alert-link { color: var(--v-metal); font-weight: 800; }

.progress { background: rgba(0,0,0,.4); border-radius: var(--v-r-pill); height: 8px; box-shadow: inset 0 1px 2px rgba(0,0,0,.5); }
.progress-bar { background: var(--v-grad-metal); border-radius: var(--v-r-pill); }
.progress-bar.bg-success { background: var(--v-good) !important; }
.progress-bar.bg-warning { background: var(--v-warn) !important; }
.progress-bar.bg-danger  { background: var(--v-bad) !important; }

.modal-header, .modal-footer { border-color: var(--v-hair); }
.modal-title { font-family: var(--v-display); font-weight: 400; font-size: var(--v-t-lg); }
.modal-backdrop.show { opacity: .74; }

/* ============================================================================
   Figures and empty states
   ========================================================================= */
.v-lead {
  background: var(--v-glass-2);
  border: 1px solid var(--v-edge-2);
  border-radius: var(--v-r-md);
  padding: var(--v-s3);
  box-shadow: var(--v-specular), var(--v-shadow);
}
.v-lead__label { font-size: var(--v-t-xs); color: var(--v-ink-2); margin: 0 0 6px; letter-spacing: .05em; text-transform: uppercase; }
.v-lead__figure {
  font-family: var(--v-display); font-weight: 400;
  font-size: var(--v-t-3xl); line-height: 1; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums; margin: 0;
  color: var(--v-metal);
}
.v-mini { border-top: 1px solid var(--v-hair); padding-top: var(--v-s1); }
.v-mini__label { font-size: var(--v-t-xs); color: var(--v-ink-2); margin: 0; }
.v-mini__figure { font-size: var(--v-t-md); font-weight: 800; font-variant-numeric: tabular-nums; margin: 0; color: var(--v-ink); }

.v-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--v-s1); text-align: center; padding: var(--v-s5) var(--v-s3); color: var(--v-ink-2); }
.v-empty__icon { color: var(--v-ink-3); font-size: 1.6rem; line-height: 1; }
.v-empty__title { font-family: var(--v-display); font-size: var(--v-t-lg); font-weight: 400; color: var(--v-ink); margin: 0; }
.v-empty__body { font-size: var(--v-t-sm); max-width: 34ch; margin: 0; }
.v-empty .btn { margin-top: var(--v-s1); }

/* ============================================================================
   Legacy utilities. The app was written dark, so `.text-white` and friends
   are CORRECT here — they only need to resolve to this system's ink.
   ========================================================================= */
.text-white, .text-light, .text-gray-100, .text-gray-200, .text-gray-300,
.text-dark, .text-body, .text-gray-800, .text-gray-900, .text-black {
  color: var(--v-ink) !important;
}
.text-muted, .text-secondary, .text-gray-600, .text-gray-700 { color: var(--v-ink-2) !important; }
.text-gray-400, .text-gray-500 { color: var(--v-ink-3) !important; }
.text-primary { color: var(--v-metal) !important; }
.text-success { color: var(--v-good) !important; }
.text-warning { color: var(--v-warn) !important; }
.text-danger  { color: var(--v-bad) !important; }
.text-info    { color: var(--v-info) !important; }

/* filled surfaces become tinted glass, so anything on them stays legible */
.bg-dark, .bg-black, .bg-body, .bg-body-tertiary, .bg-body-secondary,
.bg-light, .bg-white, .bg-secondary {
  background-color: var(--v-glass-1) !important;
  color: var(--v-ink) !important;
  border-color: var(--v-edge);
}
.bg-primary { background: var(--v-metal-soft) !important; color: var(--v-ink) !important; }
.bg-success { background: var(--v-good-wash) !important; color: var(--v-ink) !important; }
.bg-warning { background: var(--v-warn-wash) !important; color: var(--v-ink) !important; }
.bg-danger  { background: var(--v-bad-wash) !important;  color: var(--v-ink) !important; }
.bg-info    { background: var(--v-info-wash) !important; color: var(--v-ink) !important; }
.bg-dark h1, .bg-dark h2, .bg-dark h3, .bg-dark h4, .bg-dark h5, .bg-dark h6,
.bg-primary h1, .bg-primary h2, .bg-primary h3, .bg-primary h4, .bg-primary h5, .bg-primary h6,
.bg-light h1, .bg-light h2, .bg-light h3, .bg-light h4, .bg-light h5, .bg-light h6,
.bg-dark p, .bg-primary p, .bg-light p, .bg-dark span, .bg-primary span, .bg-light span,
.bg-dark div, .bg-primary div, .bg-light div, .bg-dark small, .bg-primary small, .bg-light small,
.bg-dark strong, .bg-primary strong, .bg-light strong, .bg-dark a, .bg-light a {
  color: var(--v-ink) !important;
}
.bg-dark .text-muted, .bg-light .text-muted, .bg-primary .text-muted { color: var(--v-ink-2) !important; }

/* gradients were decoration standing in for hierarchy */
[class*="bg-gradient"] {
  background-image: none !important;
  background-color: var(--v-glass-1) !important;
  color: var(--v-ink) !important;
}
[class*="bg-gradient"] h1, [class*="bg-gradient"] h2, [class*="bg-gradient"] h3,
[class*="bg-gradient"] h4, [class*="bg-gradient"] h5, [class*="bg-gradient"] p,
[class*="bg-gradient"] span, [class*="bg-gradient"] div, [class*="bg-gradient"] .text-white {
  color: var(--v-ink) !important;
}

.border, .border-top, .border-end, .border-bottom, .border-start,
.border-light, .border-dark, .border-secondary, .border-primary { border-color: var(--v-hair) !important; }
.border-warning { border-color: rgba(255,196,107,.5) !important; }
.border-danger  { border-color: rgba(255,141,141,.5) !important; }
.border-success { border-color: rgba(95,227,192,.5) !important; }
.border-info    { border-color: rgba(134,200,255,.5) !important; }
[class*="border-left-"] { border-left-width: 3px !important; border-left-style: solid !important; }

.shadow, .shadow-sm, .shadow-lg { box-shadow: var(--v-specular), var(--v-shadow) !important; }
.font-weight-bold { font-weight: 800 !important; }
.small-box, .info-box { background: var(--v-glass-1) !important; color: var(--v-ink) !important; border: 1px solid var(--v-edge); border-radius: var(--v-r-md); }
.small-box > .inner, .small-box h3, .small-box p { color: var(--v-ink) !important; }

code, kbd { color: var(--v-orchid); background: rgba(0,0,0,.35); border-radius: 6px; padding: .1em .4em; }
pre { color: var(--v-ink-2); background: rgba(0,0,0,.35); border-radius: 8px; padding: var(--v-s2); border: 1px solid var(--v-hair); overflow-x: auto; }

/* ============================================================================
   The hero sits on a photograph under a dark scrim
   ========================================================================= */
.carousel-item, .hero-slide, .hero, [class*="hero-"] { color: #fff; }
.carousel-item h1, .carousel-item h2, .carousel-item h3, .carousel-item p,
.hero-slide h1, .hero-slide h2, .hero-slide h3, .hero-slide p,
.hero h1, .hero h2, .hero h3, .hero p,
.carousel-caption h1, .carousel-caption h2, .carousel-caption h3, .carousel-caption p,
.hero-content h1, .hero-content h2, .hero-content h3, .hero-content p {
  color: #fff !important;
  text-shadow: 0 2px 30px rgba(0, 0, 0, .65);
}
.carousel-item .btn:not(.btn-primary), .hero-slide .btn:not(.btn-primary),
.hero .btn:not(.btn-primary), .hero-content .btn:not(.btn-primary) {
  background: rgba(255,255,255,.14) !important;
  border-color: rgba(255,255,255,.55) !important;
  color: #fff !important;
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
.carousel-control-prev-icon, .carousel-control-next-icon { filter: none; }

/* ============================================================================
   Mobile
   ========================================================================= */
.v-screen { min-height: 100vh; min-height: 100dvh; }
.v-sticky-actions {
  position: sticky; bottom: 0; z-index: 20;
  background: var(--v-glass-2);
  -webkit-backdrop-filter: var(--v-blur);
  backdrop-filter: var(--v-blur);
  border-top: 1px solid var(--v-edge);
  padding: var(--v-s1) var(--v-s2);
  padding-bottom: max(var(--v-s2), env(safe-area-inset-bottom));
}

@media (max-width: 767.98px) {
  .card-body { padding: var(--v-s2); }
  h1 { font-size: 1.875rem; }
  h2 { font-size: 1.5rem; }
  /* EVERY table scrolls inside its own box, so the page never moves sideways */
  table { display: block; overflow-x: auto; max-width: 100%; }
  table > tbody td, table > thead th { white-space: nowrap; }
  .table-responsive { overflow-x: auto; max-width: 100%; -webkit-overflow-scrolling: touch; }
  .container, .container-fluid, .row { max-width: 100%; }
  [class*="col-"] { min-width: 0; }
  pre, code { overflow-x: auto; max-width: 100%; }
  .btn-group { flex-wrap: wrap; }
  .btn { width: 100%; }
  .btn-group .btn, .d-flex > .btn, .input-group .btn, .v-actions .btn,
  td .btn, th .btn, .navbar .btn, .dropdown .btn, .btn-toolbar .btn { width: auto; }
  .navbar .nav-link { min-height: 48px; width: 100%; }
  .dropdown-item { min-height: 48px; }
  /* blur is costly on phones; the opaque tier keeps every contrast ratio */
  .card, .list-group, .accordion-item { -webkit-backdrop-filter: none; backdrop-filter: none; background-color: var(--v-card); }
}

/* ============================================================================
   Motion: answers an action, never plays on its own
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============================================================================
   Print — paper is white, so the system inverts for ink
   ========================================================================= */
@media print {
  html, body { background: #fff !important; color: #000 !important; }
  body::before { display: none !important; }
  .navbar, .v-sticky-actions, .pagination, .btn, .no-print, .dropdown-menu { display: none !important; }
  .card, .v-glass, .alert, .list-group {
    background: #fff !important; color: #000 !important;
    border: 1px solid #bbb !important; box-shadow: none !important;
    -webkit-backdrop-filter: none !important; backdrop-filter: none !important;
  }
  .table, .table th, .table td, h1, h2, h3, h4, h5, h6, p, span, div, li {
    color: #000 !important; background: transparent !important;
  }
  a[href]::after { content: ""; }
}

/* The active page number is the one filled pagination control: Bootstrap
   paints it on .page-item.active .page-link, not on .page-link itself. */
.page-item.active .page-link, .page-link.active {
  background: var(--v-grad-metal) !important;
  border-color: rgba(255, 255, 255, .34) !important;
  color: var(--v-on-metal) !important;
}
.page-item.disabled .page-link { background: transparent !important; color: var(--v-ink-3) !important; }

/* A semantic utility used as a FILL is a tint on this theme, so whatever sits
   on it stays legible. Text and borders keep the full-strength colour. */
.badge.bg-light, .badge.bg-white, .badge.text-bg-light { background: rgba(255,255,255,.08) !important; color: var(--v-ink) !important; }
.badge.text-dark, .badge.text-white, .badge .text-dark, .badge .text-white { color: inherit !important; }
.bg-success *, .bg-warning *, .bg-danger *, .bg-info *, .bg-primary * { color: var(--v-ink) !important; }
.btn-success *, .btn-warning *, .btn-danger *, .btn-info * { color: inherit !important; }

/* ============================================================================
   Specificity reinforcement
   ----------------------------------------------------------------------------
   Bootstrap ships its colour utilities as `!important`, so a single class of
   ours ties on importance and loses on source order in a few places. Doubling
   the class raises specificity without escalating the importance war further.
   Each of these was found by tools/audit_contrast.py, not by eye.
   ========================================================================= */
.bg-secondary.bg-secondary, .bg-light.bg-light, .bg-white.bg-white,
.bg-dark.bg-dark, .bg-black.bg-black, .bg-body.bg-body {
  background-color: var(--v-glass-1) !important;
  color: var(--v-ink) !important;
}
.bg-secondary.bg-secondary *, .bg-light.bg-light *, .bg-white.bg-white * {
  color: var(--v-ink) !important;
}

/* a list group item defaults to the body background, which is not transparent
   once Bootstrap resolves it on the item rather than the group */
.list-group-item.list-group-item {
  background-color: transparent !important;
  color: var(--v-ink) !important;
  border-color: var(--v-hair) !important;
}
.list-group-item-action:hover, .list-group-item-action:focus {
  background-color: rgba(255, 255, 255, .07) !important;
  color: var(--v-ink) !important;
}
.list-group-item h1, .list-group-item h2, .list-group-item h3,
.list-group-item h4, .list-group-item h5, .list-group-item h6 { color: var(--v-ink) !important; }
.list-group-item p, .list-group-item small { color: var(--v-ink-2) !important; }

/* the AdminLTE-style stat box */
.small-box.small-box { background: var(--v-glass-1) !important; color: var(--v-ink) !important; border: 1px solid var(--v-edge); }
.small-box.small-box h3, .small-box.small-box p, .small-box.small-box .inner { color: var(--v-ink) !important; }
.small-box-footer, .small-box .small-box-footer {
  color: var(--v-metal) !important;
  background: rgba(0, 0, 0, .22) !important;
  border-top: 1px solid var(--v-hair);
}
.small-box-footer:hover { color: var(--v-ink) !important; background: rgba(0, 0, 0, .3) !important; }

/* ============================================================================
   Polish
   ========================================================================= */

/* ---- 1. The navbar spans the window -----------------------------------
   The markup nests .container-fluid > .container-fluid > .container > .navbar,
   so the bar was painting as a floating box with gutters. The glass moves to
   the outer sticky wrapper and the bar itself becomes transparent. */
.sticky-top > .container-fluid:first-child,
.container-fluid.sticky-top {
  background-color: var(--v-glass-2);
  -webkit-backdrop-filter: var(--v-blur);
  backdrop-filter: var(--v-blur);
  border-bottom: 1px solid var(--v-edge);
  box-shadow: var(--v-specular), 0 8px 32px -16px rgba(0, 0, 0, .85);
}
.container-fluid.sticky-top .navbar,
.sticky-top .navbar {
  background: transparent !important;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  border: 0 !important;
  box-shadow: none !important;
}

/* ---- 2. An outline button is navigation, not state ---------------------
   The stock pages used four outline colours side by side for what are simply
   links, so colour carried no meaning. Outlines are one neutral glass; solid
   state buttons keep their colour, because there the colour IS the message. */
.btn-outline-primary, .btn-outline-secondary, .btn-outline-success,
.btn-outline-danger, .btn-outline-warning, .btn-outline-info,
.btn-outline-light, .btn-outline-dark {
  background: rgba(255, 255, 255, .06) !important;
  border: 1px solid var(--v-edge) !important;
  color: var(--v-ink) !important;
  box-shadow: var(--v-specular);
}
.btn-outline-primary:hover, .btn-outline-secondary:hover, .btn-outline-success:hover,
.btn-outline-danger:hover, .btn-outline-warning:hover, .btn-outline-info:hover,
.btn-outline-light:hover, .btn-outline-dark:hover {
  background: rgba(255, 255, 255, .13) !important;
  border-color: var(--v-edge-2) !important;
  color: var(--v-ink) !important;
}
/* the one exception: a destructive outline keeps its warning */
.btn-outline-danger { color: var(--v-bad) !important; border-color: rgba(255, 141, 141, .35) !important; }
.btn-outline-danger:hover { background: var(--v-bad-wash) !important; border-color: var(--v-bad) !important; color: var(--v-bad) !important; }

/* ---- 3. Depth: let the ambient light actually show --------------------- */
body::before { opacity: 1; }
body::after {
  content: "";
  position: fixed; inset: 0;
  z-index: -1; pointer-events: none;
  background-image: radial-gradient(110vw 70vh at 50% -10%, rgba(255, 255, 255, .05), transparent 60%);
}

/* ---- 4. Smooth, but only in response to the person -------------------- */
html { scroll-behavior: smooth; }

.card, .list-group-item, .badge, .form-control, .form-select, .nav-link, .page-link {
  transition: background-color var(--v-dur) var(--v-ease),
              border-color var(--v-dur) var(--v-ease),
              color var(--v-dur) var(--v-ease),
              box-shadow var(--v-dur) var(--v-ease),
              transform var(--v-dur) var(--v-ease);
}
/* a card that goes somewhere lifts toward the light on hover */
.card:hover { border-color: var(--v-edge-2); box-shadow: var(--v-specular), var(--v-shadow-lg); }
a .card:hover, a.card:hover, .card.v-actionable:hover { transform: translateY(-3px); }
.table > tbody > tr { transition: background-color 120ms var(--v-ease); }

/* one orchestrated entrance for the page, not a cascade of section reveals */
@keyframes v-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
main, .admin-dashboard-container { animation: v-rise 420ms var(--v-ease) both; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  main, .admin-dashboard-container { animation: none; }
  .card:hover, a.card:hover, .card.v-actionable:hover { transform: none; }
}

/* ---- 5. Rhythm: give dense admin screens room to breathe -------------- */
main.container-fluid, main.container { padding-block: var(--v-s4); }
.card + .card, .row + .row { margin-top: var(--v-s2); }
.table-responsive + .pagination, .table + .pagination { margin-top: var(--v-s3); }

/* ============================================================================
   Depth, corrected
   ----------------------------------------------------------------------------
   `body` was both positioned AND opaque, so the ambient light pools painted at
   z-index:-1 were hidden behind body's own background and the glass had
   nothing to refract. The ground moves to <html>, body goes transparent, and
   the pools sit between the two.
   ========================================================================= */

body { background: transparent !important; }
body::before, body::after { display: none; }

/* a page header band is glass with a champagne edge, not a washed strip */
.bg-primary.container-fluid, .container-fluid.bg-primary,
.bg-primary.py-3, .bg-primary.py-4, .bg-primary.py-5 {
  background: var(--v-glass-2) !important;
  -webkit-backdrop-filter: var(--v-blur);
  backdrop-filter: var(--v-blur);
  border-top: 1px solid var(--v-edge);
  border-bottom: 1px solid var(--v-edge);
  box-shadow: inset 0 2px 0 rgba(240, 217, 160, .35), var(--v-specular);
  color: var(--v-ink) !important;
}

/* the glass needs a touch more presence against a dark room */
.card, .v-glass { box-shadow: var(--v-specular), 0 1px 0 rgba(0,0,0,.4), var(--v-shadow); }

/* ============================================================================
   Gloss — lift the glass off the ground
   ----------------------------------------------------------------------------
   With near-white ink at 16:1 there is a lot of headroom, so the panels can be
   lighter and the room brighter without costing legibility. Re-checked with
   tools/audit_contrast.py after every change here.
   ========================================================================= */
:root {
  --v-glass-1: rgba(34, 31, 48, 0.72);
  --v-glass-2: rgba(44, 40, 62, 0.80);
  --v-glass-3: rgba(56, 51, 76, 0.86);
  --v-card:    #221f30;
  --v-edge:    rgba(255, 255, 255, 0.13);
  --v-edge-2:  rgba(255, 255, 255, 0.22);
  --v-specular: inset 0 1px 0 rgba(255, 255, 255, 0.22);
  --v-hair:    rgba(255, 255, 255, 0.11);
  --v-hair-2:  rgba(255, 255, 255, 0.20);
}

html {
  /* colour and image are set SEPARATELY and deliberately: a gradient-only
     background leaves background-color transparent, so if the image does not
     paint — print, forced colours, an old engine — the ground falls back to
     white and every light-on-dark pair inverts. */
  background-color: var(--v-paper);
  background-image:
    radial-gradient(46vw 46vw at 8% -4%,   rgba(240, 217, 160, .26), transparent 58%),
    radial-gradient(54vw 54vw at 94% 98%,  rgba(199, 155, 255, .28), transparent 60%),
    radial-gradient(64vw 44vw at 52% 40%,  rgba(95, 227, 192, .10), transparent 66%);
  background-attachment: fixed;
  background-repeat: no-repeat;
}

/* a specular sheen across the top of each panel, the way a lit edge behaves */
.card, .v-glass, .modal-content {
  position: relative;
  background-image: linear-gradient(177deg, rgba(255,255,255,.055) 0%, rgba(255,255,255,0) 42%);
}
.navbar, .container-fluid.sticky-top {
  background-image: linear-gradient(180deg, rgba(255,255,255,.07) 0%, rgba(255,255,255,0) 60%);
}

/* the champagne stays the one bright thing on the page */
.v-lead__figure, .navbar-brand { text-shadow: 0 0 36px rgba(240, 217, 160, .28); }

/* ============================================================================
   Brand mark
   ----------------------------------------------------------------------------
   The logo is a square, STACKED lockup — crest over wordmark over tagline,
   and the two overlap, so it cannot be split into a horizontal lockup from
   this asset. That means it can only be sized by height, and the word
   "Velora" is roughly 40% of that height. At the 36px it had, the word was
   ~14px and the tagline was sub-pixel; the original 120px made it legible but
   dominated the bar.

   velora_logo_trimmed.png removes the 17–18% transparent padding baked into
   the square canvas, which buys about 25% more apparent size at the same
   slot. 52px then puts the wordmark near 20px — legible without a heavy bar.
   Only height is set: giving a lockup a fixed width squashes it.
   ========================================================================= */
.navbar-brand img {
  height: 52px;
  width: auto;
  display: block;
}
@media (max-width: 767.98px) {
  .navbar-brand img { height: 44px; }
}

/* The markup carries `py-3` on .navbar-collapse, which is right when the menu
   stacks on a phone but adds 32px to the bar on desktop, where the links are
   already 44px tall. The bar was 106px for a 52px mark. */
@media (min-width: 1200px) {
  .navbar-collapse.py-3 { padding-top: 0 !important; padding-bottom: 0 !important; }
  .navbar { padding-block: 8px; }
}

/* ============================================================================
   Touch targets found by measuring every control at 390px and 360px.
   WCAG 2.2 AA asks 24x24 as a floor; Apple and Google recommend 44-48.
   The 1x1 "Skip to main content" link is deliberate — it is visually hidden
   until focused — so it is not in scope here.
   ========================================================================= */
/* carousel dots were 19x19: the tap area grows, the dot itself stays small */
.carousel-indicators [data-bs-target] {
  width: 32px;
  height: 32px;
  border: 0;
  background: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  opacity: 1;
  margin-inline: 2px;
}
.carousel-indicators [data-bs-target]::after {
  content: "";
  width: 9px; height: 9px;
  border-radius: var(--v-r-circle);
  background: rgba(255, 255, 255, .45);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .5);
  transition: background-color var(--v-dur) var(--v-ease), transform var(--v-dur) var(--v-ease);
}
.carousel-indicators [data-bs-target].active::after {
  background: var(--v-metal);
  transform: scale(1.3);
}

/* footer and inline text links were 18px tall */
footer a, .footer a, .small-box-footer, a.text-decoration-none {
  min-height: 24px;
  display: inline-flex;
  align-items: center;
  gap: .4em;
}
.small-box-footer { min-height: 36px; justify-content: center; }

/* breadcrumbs are navigation, not running text, so they take a real target */
.breadcrumb-item a {
  min-height: 24px;
  display: inline-flex;
  align-items: center;
  padding-inline: 2px;
}

/* A segmented control or tab strip must not lift on hover: its parts are
   glued together (Bootstrap overlaps them by -1px), so raising one and not
   its neighbour makes the pair step apart as the pointer crosses between
   them. Lifting is a gesture for cards, which stand alone. */
.btn-group .btn:hover, .btn-group .btn:focus-visible,
.nav-pills .nav-link:hover, .nav-tabs .nav-link:hover,
.pagination .page-link:hover {
  transform: none !important;
}
/* and the overlap should not reorder on hover, which pops one border over the other */
.btn-group > .btn:hover, .btn-group > .btn:focus-visible { z-index: 2; }

/* Thumb comfort: adjacent controls measured 7px apart on a phone. WCAG 2.2
   only requires spacing when a target is under 24x24 (these are 42px, so they
   already conform), but 7px is tight for a thumb. */
@media (max-width: 767.98px) {
  .pagination { gap: 10px; }
  .nav-pills { gap: 10px; }
  .btn-toolbar, .d-flex.gap-2 { gap: 10px !important; }
}

/* mobile-responsive.css loads after this file and sets .pagination { gap: 4px },
   which puts page numbers 7px apart under a thumb. */
@media (max-width: 767.98px) {
  .pagination.pagination { gap: 10px; }
  .pagination.pagination .page-item { margin: 0; }
}

/* The POS catalogue tiles keep a comfortable tap height on a phone; the grid
   gutter itself is owned by mobile-responsive.css, which loads after this
   file, so it is set there rather than fought over here. */
@media (max-width: 767.98px) {
  .pos-container .service-card-btn,
  .pos-container .package-card-btn,
  .pos-container .product-card-btn { min-height: 86px; }
}

/* ============================================================================
   Navbar size — larger logo and tab text on every page
   ========================================================================= */
.navbar-brand img { height: 68px; }
.navbar .nav-link {
  font-size: clamp(1rem, .75rem + .35vw, 1.2rem);
  padding-inline: clamp(10px, .4vw + 6px, 18px);
  min-height: 52px;
}
.navbar #userDropdown { font-size: 1.05rem; }
@media (max-width: 1199.98px) {
  .navbar .nav-link { font-size: 1.1rem; }
}
@media (max-width: 767.98px) {
  .navbar-brand img { height: 54px; }
}
