:root {
  --sidebar-width: 240px;

  /* Premium palette (brand tokens) */
  --brand-primary: #4F46E5;
  --brand-primary-dark: #4338CA;
  --brand-emerald: #10B981;
  --brand-orange: #F59E0B;
  --brand-purple: #8B5CF6;
  --brand-red: #EF4444;
  --brand-info: #0891B2;
  --brand-cream: #FFFDF8;
  --brand-offwhite: #FAF9F6;

  /* Vibrant multi-accent rotation — used to color-code sidebar sections and
     stat cards so each area of the app reads with its own identity instead
     of one repeated hue. Independent of the Bootstrap semantic tokens below
     (those stay tied to meaning: success/warning/danger/info). */
  --accent-1: var(--brand-primary);   /* indigo */
  --accent-1-soft: #E0E7FF;
  --accent-2: #0D9488;                /* teal */
  --accent-2-soft: #CCFBF1;
  --accent-3: #DB2777;                /* pink */
  --accent-3-soft: #FCE7F3;
  --accent-4: var(--brand-orange);    /* amber */
  --accent-4-soft: #FEF3C7;
  --accent-5: var(--brand-purple);    /* violet */
  --accent-5-soft: #EDE9FE;
  --accent-6: #0284C7;                /* sky */
  --accent-6-soft: #E0F2FE;

  /* Retheme Bootstrap's own semantic tokens so every utility/badge/alert/link
     that reads them at runtime (a Bootstrap 5.3 feature) picks up the palette
     without recompiling Sass or touching per-page markup. */
  --bs-primary: var(--brand-primary);
  --bs-primary-rgb: 79, 70, 229;
  --bs-success: var(--brand-emerald);
  --bs-success-rgb: 16, 185, 129;
  --bs-warning: var(--brand-orange);
  --bs-warning-rgb: 245, 158, 11;
  --bs-danger: var(--brand-red);
  --bs-danger-rgb: 239, 68, 68;
  --bs-info: var(--brand-info);
  --bs-info-rgb: 8, 145, 178;
  --bs-link-color: var(--brand-primary);
  --bs-link-hover-color: var(--brand-primary-dark);
  --bs-link-color-rgb: 79, 70, 229;
  --bs-link-hover-color-rgb: 67, 56, 202;

  /* -subtle/-text-emphasis tokens are hardcoded pastels in Bootstrap's build,
     not derived from --bs-primary at runtime, so they need their own override
     to keep stat-card icons, badges, and alerts consistent with the palette. */
  --bs-primary-bg-subtle: #E0E7FF;
  --bs-primary-border-subtle: #C7D2FE;
  --bs-primary-text-emphasis: #4338CA;
  --bs-success-bg-subtle: #D1FAE5;
  --bs-success-border-subtle: #A7F3D0;
  --bs-success-text-emphasis: #047857;
  --bs-warning-bg-subtle: #FEF3C7;
  --bs-warning-border-subtle: #FDE68A;
  --bs-warning-text-emphasis: #B45309;
  --bs-danger-bg-subtle: #FEE2E2;
  --bs-danger-border-subtle: #FECACA;
  --bs-danger-text-emphasis: #B91C1C;
  --bs-info-bg-subtle: #CFFAFE;
  --bs-info-border-subtle: #A5F3FC;
  --bs-info-text-emphasis: #155E75;

  --bs-body-bg: var(--brand-cream);
  --bs-body-font-family: 'Inter', 'Segoe UI', system-ui, sans-serif;
  --bs-border-radius-sm: .625rem;
  --bs-border-radius: .875rem;
  --bs-border-radius-lg: 1.125rem;
  --bs-border-radius-xl: 1.25rem;
  --bs-border-radius-2xl: 1.5rem;
}

html[data-bs-theme="dark"] {
  --bs-primary: #6366F1;
  --bs-primary-rgb: 99, 102, 241;
  --bs-primary-bg-subtle: #312E81;
  --bs-primary-border-subtle: #4338CA;
  --bs-primary-text-emphasis: #A5B4FC;

  --bs-success-bg-subtle: #064E3B;
  --bs-success-border-subtle: #047857;
  --bs-success-text-emphasis: #6EE7B7;

  --bs-warning-bg-subtle: #78350F;
  --bs-warning-border-subtle: #B45309;
  --bs-warning-text-emphasis: #FCD34D;

  --bs-danger: #F87171;
  --bs-danger-rgb: 248, 113, 113;
  --bs-danger-bg-subtle: #7F1D1D;
  --bs-danger-border-subtle: #B91C1C;
  --bs-danger-text-emphasis: #FCA5A5;

  --bs-info: #22D3EE;
  --bs-info-rgb: 34, 211, 238;
  --bs-info-bg-subtle: #164E63;
  --bs-info-border-subtle: #0E7490;
  --bs-info-text-emphasis: #67E8F9;

  --bs-link-color: #818CF8;
  --bs-link-hover-color: #A5B4FC;

  --bs-body-bg: #15161B;
  --bs-tertiary-bg: #1C1D24;

  /* Darker soft chips for the accent rotation (sidebar icons, etc.) */
  --accent-1-soft: #312E81;
  --accent-2-soft: #134E4A;
  --accent-3-soft: #831843;
  --accent-4-soft: #78350F;
  --accent-5-soft: #4C1D95;
  --accent-6-soft: #0C4A6E;
}

body {
  background-color: var(--bs-body-bg);
}

h1, h2, h3, h4, h5, h6, .navbar-brand, .sidebar-brand, .stat-value {
  font-family: 'Poppins', 'Inter', sans-serif;
}

.top-navbar {
  position: sticky;
  top: 0;
  z-index: 1030;
  height: 56px;
  background-color: var(--brand-offwhite);
  border-bottom: 1px solid var(--bs-border-color);
  display: flex;
  align-items: center;
}

.top-navbar::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  height: 3px;
  background: linear-gradient(90deg, var(--accent-1), var(--accent-3) 35%, var(--accent-4) 65%, var(--accent-6));
  opacity: .55;
}

html[data-bs-theme="dark"] .top-navbar {
  background-color: #1C1D24;
}

.user-menu-btn {
  display: flex;
  align-items: center;
  gap: .5rem;
  background-color: var(--bs-tertiary-bg);
  border: 1px solid var(--bs-border-color);
  color: var(--bs-body-color);
}

.user-menu-btn:hover {
  background-color: var(--bs-tertiary-bg);
  color: var(--bs-body-color);
}

.avatar-initials {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  font-size: .72rem;
  font-weight: 700;
  color: #fff;
  background: linear-gradient(135deg, var(--accent-1), var(--accent-3));
  flex-shrink: 0;
}

.avatar-initials-lg {
  width: 64px;
  height: 64px;
  font-size: 1.4rem;
  box-shadow: 0 .35rem 1rem rgba(0, 0, 0, .2);
}

.profile-banner {
  background: linear-gradient(135deg, var(--brand-primary), var(--accent-5));
  border: none;
}

.profile-banner .avatar-initials-lg {
  background: rgba(255, 255, 255, .2);
  border: 2px solid rgba(255, 255, 255, .5);
}

.app-wrapper {
  display: flex;
  min-height: calc(100vh - 56px);
}

.sidebar {
  --bs-body-color: #EDECFB;
  --bs-secondary-color: rgba(237, 236, 251, .7);
  --bs-tertiary-bg: rgba(255, 255, 255, .12);
  --bs-border-color: rgba(255, 255, 255, .15);
  width: var(--sidebar-width);
  flex-shrink: 0;
  background-color: var(--brand-primary);
  color: var(--bs-body-color);
  border-right: 1px solid var(--bs-border-color);
  padding: 1rem .6rem;
  position: sticky;
  top: 56px;
  height: calc(100vh - 56px);
  overflow-y: auto;
}

html[data-bs-theme="dark"] .sidebar {
  background-color: var(--brand-primary);
}

.sidebar-brand {
  font-weight: 700;
  padding: .25rem .4rem 1rem;
  display: flex;
  align-items: center;
  gap: .5rem;
}

.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: .15rem;
}

.sidebar-link {
  display: flex;
  align-items: center;
  gap: .65rem;
  padding: .5rem .6rem;
  border-radius: var(--bs-border-radius-sm);
  color: var(--bs-body-color);
  text-decoration: none;
  transition: background-color .15s ease, color .15s ease;
}

.sidebar-link:hover {
  background-color: var(--bs-tertiary-bg);
}

.sidebar-link.active {
  background: linear-gradient(90deg, var(--bs-primary-bg-subtle), transparent);
  color: var(--bs-primary);
  font-weight: 600;
}

.sidebar-heading {
  padding: 1rem .6rem .35rem;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--bs-secondary-color);
}

/* Custom typeahead dropdown used instead of native <datalist> — the native
   popup scrolls janky/laggy in Chromium once it has more than a handful of
   options, and can't be restyled, so food-name suggestion fields build their
   own small absolutely-positioned list instead. */
.autocomplete-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 1070;
  background-color: var(--bs-body-bg);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius-sm);
  max-height: 220px;
  overflow-y: auto;
  box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .15);
  display: none;
}

.autocomplete-item {
  padding: .4rem .65rem;
  cursor: pointer;
  font-size: .9rem;
}

.autocomplete-item:hover,
.autocomplete-item.active {
  background-color: var(--bs-tertiary-bg);
}

.sidebar-back-link {
  margin-bottom: .5rem;
  padding-bottom: .65rem;
  border-bottom: 1px solid var(--bs-border-color);
  color: var(--bs-secondary-color);
  font-size: .87rem;
}

.sidebar-group-toggle {
  width: 100%;
  background: none;
  border: none;
  cursor: pointer;
}

.sidebar-group-chevron {
  font-size: .75rem;
  transition: transform .2s ease;
}

.sidebar-group-toggle[aria-expanded="true"] .sidebar-group-chevron {
  transform: rotate(180deg);
}

.sidebar-subnav {
  display: flex;
  flex-direction: column;
  gap: .15rem;
  background-color: transparent;
  margin: .1rem 0 .35rem;
}

.sidebar-sublink {
  padding-left: .6rem;
  font-size: .87rem;
}

/* Colorful nav icon chips — each item's icon sits in a small rounded badge.
   Rotated through the accent palette by position so every section of the
   sidebar reads with its own identity at a glance instead of one repeated
   hue (rotation is per parent+tag, matching how the menu array renders:
   top-level <a> links, group <button> toggles, and each group's <a>
   sublinks are counted separately, so every sub-list also starts its own
   cycle from accent-1). */
.nav-icon-chip {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  border-radius: .6rem;
  font-size: .95rem;
  background-color: var(--bs-tertiary-bg);
  color: var(--bs-secondary-color);
  transition: background-color .15s ease, color .15s ease, transform .15s ease;
}

.sidebar-link:hover .nav-icon-chip {
  transform: translateY(-1px);
}

.sidebar-link.active .nav-icon-chip,
.sidebar-group-toggle.active .nav-icon-chip {
  box-shadow: 0 .35rem .75rem rgba(15, 23, 42, .18);
}

/* Active-state color:#fff lives in each numbered rule below (not a shared
   .active selector) so its specificity always beats the plain colored
   variant above it — otherwise the plain rule's higher specificity
   (nth-of-type + more classes) wins the color and the icon ends up the
   same color as its own solid-fill background: invisible. */
.sidebar-nav > a.sidebar-link:nth-of-type(6n+1) .nav-icon-chip,
.sidebar-subnav > a.sidebar-sublink:nth-of-type(6n+1) .nav-icon-chip,
.sidebar-group-toggle:nth-of-type(6n+1) .nav-icon-chip { color: var(--accent-1); background-color: var(--accent-1-soft); }
.sidebar-nav > a.sidebar-link:nth-of-type(6n+1).active .nav-icon-chip,
.sidebar-subnav > a.sidebar-sublink:nth-of-type(6n+1).active .nav-icon-chip,
.sidebar-group-toggle:nth-of-type(6n+1).active .nav-icon-chip { color: #fff; background-color: var(--accent-1); }

.sidebar-nav > a.sidebar-link:nth-of-type(6n+2) .nav-icon-chip,
.sidebar-subnav > a.sidebar-sublink:nth-of-type(6n+2) .nav-icon-chip,
.sidebar-group-toggle:nth-of-type(6n+2) .nav-icon-chip { color: var(--accent-2); background-color: var(--accent-2-soft); }
.sidebar-nav > a.sidebar-link:nth-of-type(6n+2).active .nav-icon-chip,
.sidebar-subnav > a.sidebar-sublink:nth-of-type(6n+2).active .nav-icon-chip,
.sidebar-group-toggle:nth-of-type(6n+2).active .nav-icon-chip { color: #fff; background-color: var(--accent-2); }

.sidebar-nav > a.sidebar-link:nth-of-type(6n+3) .nav-icon-chip,
.sidebar-subnav > a.sidebar-sublink:nth-of-type(6n+3) .nav-icon-chip,
.sidebar-group-toggle:nth-of-type(6n+3) .nav-icon-chip { color: var(--accent-3); background-color: var(--accent-3-soft); }
.sidebar-nav > a.sidebar-link:nth-of-type(6n+3).active .nav-icon-chip,
.sidebar-subnav > a.sidebar-sublink:nth-of-type(6n+3).active .nav-icon-chip,
.sidebar-group-toggle:nth-of-type(6n+3).active .nav-icon-chip { color: #fff; background-color: var(--accent-3); }

.sidebar-nav > a.sidebar-link:nth-of-type(6n+4) .nav-icon-chip,
.sidebar-subnav > a.sidebar-sublink:nth-of-type(6n+4) .nav-icon-chip,
.sidebar-group-toggle:nth-of-type(6n+4) .nav-icon-chip { color: var(--accent-4); background-color: var(--accent-4-soft); }
.sidebar-nav > a.sidebar-link:nth-of-type(6n+4).active .nav-icon-chip,
.sidebar-subnav > a.sidebar-sublink:nth-of-type(6n+4).active .nav-icon-chip,
.sidebar-group-toggle:nth-of-type(6n+4).active .nav-icon-chip { color: #fff; background-color: var(--accent-4); }

.sidebar-nav > a.sidebar-link:nth-of-type(6n+5) .nav-icon-chip,
.sidebar-subnav > a.sidebar-sublink:nth-of-type(6n+5) .nav-icon-chip,
.sidebar-group-toggle:nth-of-type(6n+5) .nav-icon-chip { color: var(--accent-5); background-color: var(--accent-5-soft); }
.sidebar-nav > a.sidebar-link:nth-of-type(6n+5).active .nav-icon-chip,
.sidebar-subnav > a.sidebar-sublink:nth-of-type(6n+5).active .nav-icon-chip,
.sidebar-group-toggle:nth-of-type(6n+5).active .nav-icon-chip { color: #fff; background-color: var(--accent-5); }

.sidebar-nav > a.sidebar-link:nth-of-type(6n+6) .nav-icon-chip,
.sidebar-subnav > a.sidebar-sublink:nth-of-type(6n+6) .nav-icon-chip,
.sidebar-group-toggle:nth-of-type(6n+6) .nav-icon-chip { color: var(--accent-6); background-color: var(--accent-6-soft); }
.sidebar-nav > a.sidebar-link:nth-of-type(6n+6).active .nav-icon-chip,
.sidebar-subnav > a.sidebar-sublink:nth-of-type(6n+6).active .nav-icon-chip,
.sidebar-group-toggle:nth-of-type(6n+6).active .nav-icon-chip { color: #fff; background-color: var(--accent-6); }

.content {
  flex-grow: 1;
  padding: 1.25rem;
  min-width: 0;
}

.flash-stack {
  margin-bottom: 1rem;
}

.stat-card {
  position: relative;
  overflow: hidden;
}

/* Colorful top accent bar, matched to whichever text-* tone the page already
   put on that card's .stat-icon (bg-primary-subtle/text-primary, etc.) —
   no markup change needed, :has() just reads what's already there. */
.stat-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  opacity: .75;
  background: var(--bs-secondary-color);
}

.stat-card:has(.text-primary)::before { background: linear-gradient(90deg, var(--bs-primary), var(--accent-5)); }
.stat-card:has(.text-success)::before { background: linear-gradient(90deg, var(--brand-emerald), var(--accent-2)); }
.stat-card:has(.text-warning)::before { background: linear-gradient(90deg, var(--brand-orange), var(--accent-3)); }
.stat-card:has(.text-info)::before { background: linear-gradient(90deg, var(--bs-info), var(--accent-6)); }
.stat-card:has(.text-danger)::before { background: linear-gradient(90deg, var(--brand-red), var(--accent-3)); }
.stat-card:has(.text-secondary)::before { background: linear-gradient(90deg, var(--accent-5), var(--accent-1)); }

.stat-card .card-body {
  display: flex;
  flex-direction: column;
  gap: .35rem;
}

.stat-icon {
  width: 48px;
  height: 48px;
  border-radius: 1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.25rem;
  transition: transform .2s ease;
}

.stat-card:hover .stat-icon {
  transform: scale(1.08) rotate(-3deg);
}

.stat-value {
  font-size: 1.6rem;
  font-weight: 700;
}

.stat-label {
  color: var(--bs-secondary-color);
  font-size: .85rem;
}

.status-select {
  width: 100%;
  max-width: 190px;
}

.timeline {
  border-left: 2px solid var(--bs-border-color);
  padding-left: 1rem;
}

.timeline-item {
  position: relative;
  padding-bottom: 1.25rem;
}

.timeline-item::before {
  content: '';
  position: absolute;
  left: -1.4rem;
  top: .35rem;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--bs-primary);
}

.timeline-date {
  font-size: .8rem;
  color: var(--bs-secondary-color);
  margin-bottom: .2rem;
}

.login-body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(circle at 12% 15%, rgba(79, 70, 229, .14), transparent 40%),
    radial-gradient(circle at 88% 20%, rgba(219, 39, 119, .10), transparent 42%),
    radial-gradient(circle at 20% 88%, rgba(13, 148, 136, .10), transparent 42%),
    radial-gradient(circle at 85% 82%, rgba(245, 158, 11, .10), transparent 45%),
    var(--brand-cream);
}

html[data-bs-theme="dark"] .login-body {
  background:
    radial-gradient(circle at 12% 15%, rgba(99, 102, 241, .22), transparent 40%),
    radial-gradient(circle at 88% 20%, rgba(219, 39, 119, .16), transparent 42%),
    radial-gradient(circle at 20% 88%, rgba(13, 148, 136, .18), transparent 42%),
    radial-gradient(circle at 85% 82%, rgba(245, 158, 11, .14), transparent 45%),
    var(--bs-body-bg);
}

.login-card {
  background: #fff;
  border-radius: var(--bs-border-radius-xl);
  padding: 2.25rem 2rem;
  width: 100%;
  max-width: 380px;
  box-shadow: 0 1rem 3rem rgba(15, 23, 42, .1);
  border: 1px solid var(--bs-border-color);
  text-align: center;
}

.login-card form {
  text-align: left;
}

.password-field-wrap {
  position: relative;
}

.password-field-wrap input {
  padding-right: 2.5rem;
}

.password-toggle-btn {
  position: absolute;
  right: .5rem;
  top: 50%;
  transform: translateY(-50%);
  border: none;
  background: none;
  color: var(--bs-secondary-color);
  padding: .25rem;
  line-height: 1;
  cursor: pointer;
}

.password-toggle-btn:hover {
  color: var(--bs-primary);
}

.login-logo {
  height: 64px;
  width: 64px;
  object-fit: contain;
  border-radius: 1rem;
  margin: 0 auto 1rem;
  display: block;
}

.login-logo-placeholder {
  height: 64px;
  width: 64px;
  border-radius: 1rem;
  margin: 0 auto 1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  color: #fff;
  background: linear-gradient(135deg, var(--brand-primary), var(--brand-purple));
}

html[data-bs-theme="dark"] .login-card {
  background: #1C1D24;
}

@media (max-width: 991.98px) {
  .sidebar {
    position: fixed;
    left: -260px;
    top: 56px;
    z-index: 1040;
    transition: left .2s ease-in-out;
    box-shadow: 0 0 1rem rgba(0, 0, 0, .15);
  }
  .sidebar.show {
    left: 0;
  }
  body.has-bottom-nav .sidebar {
    height: calc(100vh - 56px - 64px);
  }
}

/* Student mobile bottom navigation (Module 19) */
.student-bottom-nav {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 1050;
  display: flex;
  background: var(--bs-body-bg);
  border-top: 1px solid var(--bs-border-color);
  box-shadow: 0 -.25rem .75rem rgba(0, 0, 0, .08);
}

.bottom-nav-link {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .1rem;
  padding: .4rem 0 .5rem;
  color: var(--bs-secondary-color);
  text-decoration: none;
  font-size: .68rem;
}

.bottom-nav-icon {
  width: 38px;
  height: 38px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.15rem;
  background: transparent;
  transition: background-color .2s ease, color .2s ease, transform .2s ease;
}

/* Colorful, rotating accent per tab position (works regardless of labels) */
.bottom-nav-link:nth-child(1) .bottom-nav-icon { color: var(--brand-primary); }
.bottom-nav-link:nth-child(2) .bottom-nav-icon { color: var(--brand-purple); }
.bottom-nav-link:nth-child(3) .bottom-nav-icon { color: var(--brand-orange); }
.bottom-nav-link:nth-child(4) .bottom-nav-icon { color: var(--brand-emerald); }
.bottom-nav-link:nth-child(5) .bottom-nav-icon { color: var(--brand-info); }

.bottom-nav-link.active:nth-child(1) .bottom-nav-icon { background: var(--brand-primary); }
.bottom-nav-link.active:nth-child(2) .bottom-nav-icon { background: var(--brand-purple); }
.bottom-nav-link.active:nth-child(3) .bottom-nav-icon { background: var(--brand-orange); }
.bottom-nav-link.active:nth-child(4) .bottom-nav-icon { background: var(--brand-emerald); }
.bottom-nav-link.active:nth-child(5) .bottom-nav-icon { background: var(--brand-info); }

.bottom-nav-link.active .bottom-nav-icon {
  color: #fff;
  transform: translateY(-2px);
  box-shadow: 0 .35rem .75rem rgba(0, 0, 0, .18);
}

.bottom-nav-link.active {
  color: var(--bs-body-color);
  font-weight: 700;
}

body.has-bottom-nav .content {
  padding-bottom: 1.25rem;
}

/* QR verification result stamp */
.verified-stamp {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  font-weight: 700;
  letter-spacing: .05em;
  color: #198754;
  border: 2px solid #198754;
  border-radius: .5rem;
  padding: .35rem .9rem;
  transform: rotate(-3deg);
}

.verified-stamp-invalid {
  color: #dc3545;
  border-color: #dc3545;
}

@media (max-width: 991.98px) {
  body.has-bottom-nav .content {
    padding-bottom: 4.5rem;
  }
}

/* Glassmorphism chrome for the mobile-first panels (Module 19) — scoped to
   Student/Faculty/Staff layouts only via .has-bottom-nav, not the admin panel. */
body.has-bottom-nav .top-navbar {
  background-color: rgba(255, 255, 255, 0.65);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

html[data-bs-theme="dark"] body.has-bottom-nav .top-navbar {
  background-color: rgba(33, 37, 41, 0.65);
}

body.has-bottom-nav .student-bottom-nav {
  background-color: rgba(255, 255, 255, 0.75);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

html[data-bs-theme="dark"] body.has-bottom-nav .student-bottom-nav {
  background-color: rgba(33, 37, 41, 0.75);
}

/* Skeleton loading shimmer utility (Module 19) */
.skeleton {
  position: relative;
  overflow: hidden;
  background-color: var(--bs-tertiary-bg);
  border-radius: .375rem;
  color: transparent !important;
}

.skeleton::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .4), transparent);
  animation: skeleton-shimmer 1.4s infinite;
}

@keyframes skeleton-shimmer {
  100% { transform: translateX(100%); }
}

/* Floating action button — Staff "Scan QR", persistent on every staff page */
.fab {
  position: fixed;
  right: 1.25rem;
  bottom: 5.5rem;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--brand-primary), var(--brand-purple));
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .25);
  z-index: 1060;
  text-decoration: none;
}

.fab:hover, .fab:focus {
  color: #fff;
  filter: brightness(1.1);
}

/* Pull-to-refresh indicator */
.ptr-indicator {
  position: fixed;
  top: 56px;
  left: 50%;
  transform: translate(-50%, -100%);
  background: var(--bs-body-bg);
  border: 1px solid var(--bs-border-color);
  border-radius: 50%;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1070;
  transition: transform .1s linear;
  box-shadow: 0 .25rem .5rem rgba(0, 0, 0, .15);
}

.ptr-indicator.visible {
  transform: translate(-50%, .5rem);
}

.ptr-indicator i {
  transition: transform .2s;
}

.ptr-indicator.ready i {
  transform: rotate(180deg);
}

/* ============================================================
   Premium UI/UX — global design-system pass
   Cards, buttons, forms, tables, and load-in/ripple/loading
   animations. Cascades to every page via shared Bootstrap
   classes; no per-page markup changes required.
   ============================================================ */

.card {
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius-lg);
  box-shadow: 0 .125rem .5rem rgba(15, 23, 42, .05);
  transition: transform .15s ease, box-shadow .15s ease;
}

.card:hover {
  transform: translateY(-2px);
  box-shadow: 0 .5rem 1.5rem rgba(15, 23, 42, .1);
}

html[data-bs-theme="dark"] .card {
  box-shadow: 0 .125rem .5rem rgba(0, 0, 0, .25);
}

html[data-bs-theme="dark"] .card:hover {
  box-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .4);
}

.card-header {
  background: linear-gradient(90deg, rgba(79, 70, 229, .07), rgba(219, 39, 119, .05));
  font-weight: 600;
}

html[data-bs-theme="dark"] .card-header {
  background: linear-gradient(90deg, rgba(99, 102, 241, .14), rgba(219, 39, 119, .1));
}

/* Buttons — rounded, gradient, soft-lift hover, loading & disabled states */
.btn {
  position: relative;
  overflow: hidden;
  border-radius: var(--bs-border-radius);
  font-weight: 600;
  transition: transform .15s ease, box-shadow .15s ease, filter .15s ease;
}

.btn:hover {
  transform: translateY(-1px);
  filter: brightness(1.05);
}

.btn:active {
  transform: translateY(0);
  filter: brightness(.97);
}

.btn:disabled, .btn.disabled {
  transform: none;
  filter: grayscale(.15) brightness(.97);
}

.btn-primary, .btn-success, .btn-danger, .btn-warning, .btn-info {
  border: none;
  box-shadow: 0 .25rem .75rem rgba(15, 23, 42, .12);
}

.btn-primary {
  --bs-btn-bg: var(--bs-primary);
  --bs-btn-border-color: var(--bs-primary);
  --bs-btn-hover-bg: var(--bs-primary);
  --bs-btn-hover-border-color: var(--bs-primary);
  --bs-btn-active-bg: var(--bs-primary);
  --bs-btn-active-border-color: var(--bs-primary);
  background-image: linear-gradient(135deg, var(--brand-primary), var(--brand-purple));
}

.btn-success {
  --bs-btn-bg: var(--brand-emerald);
  --bs-btn-border-color: var(--brand-emerald);
  --bs-btn-hover-bg: var(--brand-emerald);
  --bs-btn-hover-border-color: var(--brand-emerald);
  --bs-btn-active-bg: var(--brand-emerald);
  --bs-btn-active-border-color: var(--brand-emerald);
  background-image: linear-gradient(135deg, var(--brand-emerald), #059669);
}

.btn-danger {
  --bs-btn-bg: var(--brand-red);
  --bs-btn-border-color: var(--brand-red);
  --bs-btn-hover-bg: var(--brand-red);
  --bs-btn-hover-border-color: var(--brand-red);
  --bs-btn-active-bg: var(--brand-red);
  --bs-btn-active-border-color: var(--brand-red);
  background-image: linear-gradient(135deg, var(--brand-red), #DC2626);
}

.btn-warning {
  --bs-btn-bg: var(--brand-orange);
  --bs-btn-border-color: var(--brand-orange);
  --bs-btn-hover-bg: var(--brand-orange);
  --bs-btn-hover-border-color: var(--brand-orange);
  --bs-btn-active-bg: var(--brand-orange);
  --bs-btn-active-border-color: var(--brand-orange);
  --bs-btn-color: #fff;
  --bs-btn-hover-color: #fff;
  --bs-btn-active-color: #fff;
  background-image: linear-gradient(135deg, var(--brand-orange), #D97706);
}

.btn-info {
  --bs-btn-bg: var(--brand-info);
  --bs-btn-border-color: var(--brand-info);
  --bs-btn-hover-bg: var(--brand-info);
  --bs-btn-hover-border-color: var(--brand-info);
  --bs-btn-active-bg: var(--brand-info);
  --bs-btn-active-border-color: var(--brand-info);
  --bs-btn-color: #fff;
  --bs-btn-hover-color: #fff;
  --bs-btn-active-color: #fff;
  background-image: linear-gradient(135deg, var(--brand-info), #2563EB);
}

/* Color-matched hover glow per variant, instead of one neutral gray shadow */
.btn-primary:hover { box-shadow: 0 .5rem 1.25rem rgba(var(--bs-primary-rgb), .35); }
.btn-success:hover { box-shadow: 0 .5rem 1.25rem rgba(16, 185, 129, .35); }
.btn-danger:hover { box-shadow: 0 .5rem 1.25rem rgba(239, 68, 68, .35); }
.btn-warning:hover { box-shadow: 0 .5rem 1.25rem rgba(245, 158, 11, .35); }
.btn-info:hover { box-shadow: 0 .5rem 1.25rem rgba(var(--bs-info-rgb), .35); }

.btn-outline-primary { --bs-btn-color: var(--bs-primary); --bs-btn-border-color: var(--bs-primary); --bs-btn-hover-bg: var(--bs-primary); --bs-btn-hover-border-color: var(--bs-primary); }
.btn-outline-success { --bs-btn-color: var(--brand-emerald); --bs-btn-border-color: var(--brand-emerald); --bs-btn-hover-bg: var(--brand-emerald); --bs-btn-hover-border-color: var(--brand-emerald); }
.btn-outline-danger { --bs-btn-color: var(--brand-red); --bs-btn-border-color: var(--brand-red); --bs-btn-hover-bg: var(--brand-red); --bs-btn-hover-border-color: var(--brand-red); }
.btn-outline-warning { --bs-btn-color: var(--brand-orange); --bs-btn-border-color: var(--brand-orange); --bs-btn-hover-bg: var(--brand-orange); --bs-btn-hover-border-color: var(--brand-orange); --bs-btn-hover-color: #fff; }
.btn-outline-info { --bs-btn-color: var(--brand-info); --bs-btn-border-color: var(--brand-info); --bs-btn-hover-bg: var(--brand-info); --bs-btn-hover-border-color: var(--brand-info); --bs-btn-hover-color: #fff; }

/* Ripple click animation (JS spawns a .btn-ripple span at the click point) */
.btn-ripple {
  position: absolute;
  border-radius: 50%;
  transform: scale(0);
  background-color: rgba(255, 255, 255, .5);
  pointer-events: none;
  animation: btn-ripple-anim .6s ease-out;
}

.btn-outline-primary .btn-ripple, .btn-outline-success .btn-ripple,
.btn-outline-danger .btn-ripple, .btn-outline-warning .btn-ripple,
.btn-outline-info .btn-ripple, .btn-outline-secondary .btn-ripple {
  background-color: rgba(79, 70, 229, .18);
}

@keyframes btn-ripple-anim {
  to { transform: scale(2.5); opacity: 0; }
}

/* Loading state (JS toggles .btn-loading + disabled while an AJAX submit is in flight) */
.btn-loading {
  color: transparent !important;
}

.btn-loading::after {
  content: '';
  position: absolute;
  width: 1rem;
  height: 1rem;
  top: 50%;
  left: 50%;
  margin: -.5rem 0 0 -.5rem;
  border: .15rem solid rgba(255, 255, 255, .5);
  border-top-color: #fff;
  border-radius: 50%;
  animation: btn-spin .6s linear infinite;
}

.btn-outline-primary.btn-loading::after, .btn-outline-secondary.btn-loading::after,
.btn-outline-success.btn-loading::after, .btn-outline-danger.btn-loading::after,
.btn-outline-warning.btn-loading::after, .btn-outline-info.btn-loading::after {
  border-color: rgba(0, 0, 0, .2);
  border-top-color: var(--bs-primary);
}

@keyframes btn-spin {
  to { transform: rotate(360deg); }
}

/* Forms */
.form-control, .form-select {
  border-radius: var(--bs-border-radius-sm);
}

.form-control:focus, .form-select:focus {
  border-color: var(--bs-primary);
  box-shadow: 0 0 0 .2rem rgba(var(--bs-primary-rgb), .18);
}

/* Tables */
.table thead th {
  position: sticky;
  top: 0;
  background-color: var(--bs-body-bg);
  z-index: 1;
}

.table-hover tbody tr:hover {
  background-color: rgba(var(--bs-primary-rgb), .05);
}

/* Toasts */
.toast {
  border-radius: var(--bs-border-radius-sm);
  box-shadow: 0 .5rem 1.5rem rgba(15, 23, 42, .15);
}

/* Card load-in animation (JS adds .fade-in-card with a staggered delay on
   DOMContentLoaded; if JS never runs, cards simply render at full opacity —
   no permanently-hidden state, so there's no blank-page risk). */
@keyframes fade-slide-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

.fade-in-card {
  animation: fade-slide-in .45s ease both;
}

@media (prefers-reduced-motion: reduce) {
  .fade-in-card { animation: none; }
  .card, .btn { transition: none; }
}

/* Welcome / page-hero banner — used on every role's dashboard top section */
.welcome-banner {
  position: relative;
  overflow: hidden;
  background: linear-gradient(135deg, var(--brand-primary), var(--brand-purple));
  border-radius: var(--bs-border-radius-lg);
  color: #fff;
  padding: 1.5rem 1.75rem;
  margin-bottom: 1.25rem;
}

.welcome-banner::after {
  content: '';
  position: absolute;
  right: -50px;
  top: -60px;
  width: 180px;
  height: 180px;
  background: rgba(255, 255, 255, .08);
  border-radius: 50%;
}

.welcome-banner::before {
  content: '';
  position: absolute;
  right: 40px;
  bottom: -70px;
  width: 120px;
  height: 120px;
  background: rgba(255, 255, 255, .06);
  border-radius: 50%;
}

.welcome-banner h1 {
  color: #fff;
  position: relative;
}

.welcome-banner p {
  color: rgba(255, 255, 255, .85);
  position: relative;
  margin-bottom: 0;
}
