/* ==========================================================================
   MENTORIA LMS — DESIGN SYSTEM  v3.0
   Navy + Leaf Green · accessible · fluid · mobile-first
   ==========================================================================

   USER PREFERENCES (PERMANENT — carried over from v2, still honoured)
   -------------------------------------------------------------------
   ✗ NO coloured vertical strip on the LEFT side of any card. Emphasis
     goes on the icon chip + value, never a side bar.
   ✓ Khan Academy / Duolingo feel: friendly, depth, bold typography.
   ✓ Generous padding, rounded corners (14–20px), pastel + gradient chips.
   ✓ Mobile rows stack as labelled cards — never a horizontal scroller.

   WHAT CHANGED IN v3.0
   -------------------------------------------------------------------
   1. CONTRAST. Eight text/background pairs in v2 failed WCAG AA, some
      badly: white on the success green measured 2.28:1 against a 4.5
      requirement, white on amber 2.15:1, and in dark mode the navy
      table-action icons sat at 1.67:1 — effectively invisible. Solid
      fills that carry white text now use the darker end of each ramp,
      and dark mode has its own foreground set. Every pair in this file
      was measured, not eyeballed; the numbers are in the comments.

   2. MOBILE TABLES ACTUALLY WORK. v2 turned table rows into stacked
      cards using `td::before { content: attr(data-label) }` — but the
      markup never set a single `data-label`, so on a phone a student
      row rendered as eight unlabelled values in a column, each with an
      88px empty indent, and you could not tell Level from Enrolled In.
      Only 9 of ~30 tables even carried `.lms-table`; the rest fell back
      to horizontal scrolling, which the preferences above rule out.
      `enhanceTables()` in mentoria-lms.js now stamps every cell with its
      column heading, and the CSS below is written against that.

   3. TOUCH TARGETS. `--tap-min: 44px` was declared in v2 and then
      applied to almost nothing: the topbar buttons measured 34×34 and
      table actions 47×38 on a phone. Sizing now keys off
      `(pointer: coarse)` rather than viewport width, so a small laptop
      window doesn't get thumb-sized controls it has no use for.

   4. DARK MODE IS FINISHED. Several v2 rules hardcoded light values
      that leaked through: `.subject-card:hover` painted a near-white
      panel behind light text, the skeleton shimmer drew pale grey bars
      on a dark page, and soft badges and alerts kept pastel
      backgrounds. All of it is tokenised.

   5. FLUID TYPE AND SPACING via clamp(), so 320px phones and 1920px
      monitors both get sensible measure without a stack of breakpoints.

   6. MOTION RESPECTS `prefers-reduced-motion`. v2 animated every page
      transition, KPI tile and sidebar item with no opt-out.

   CONTRACT
   -------------------------------------------------------------------
   Every class name and structural selector from v2 still exists and
   still means the same thing. This file is a drop-in replacement — no
   markup changes are required for anything except the mobile table
   labels, which are added by JS.

   BREAKPOINTS
     ≤ 400px   very small phones
     ≤ 640px   phones — tables become cards
     ≤ 768px   large phones / small tablets
     ≤ 991px   tablets — sidebar becomes a drawer
     ≥ 992px   desktop — fixed shell, independent scroll regions
     ≥ 1400px  wide desktop
   ========================================================================== */

/* ==========================================================================
   1. DESIGN TOKENS — LIGHT
   ========================================================================== */
:root{

  /* ---- Brand ----------------------------------------------------------
     Two ramps per hue, and the distinction matters:

       --x-fill    bright, friendly. Safe for things with NO text on top
                   (progress bars, decorative chips, borders).
       --x-solid   darker. Used wherever WHITE TEXT or a white icon sits
                   on the colour, because the bright end does not reach
                   4.5:1 and in most cases not even 3:1.

     Measured against #FFFFFF:
       #22C55E 2.28 ✗    #15803D 5.02 ✓
       #F59E0B 2.15 ✗    #B45309 5.02 ✓
       #0EA5E9 2.77 ✗    #0369A1 5.93 ✓
       #EF4444 3.76 ✗    #B91C1C 6.47 ✓
       #8B5CF6 4.23 ✗    #6D28D9 7.10 ✓
     --------------------------------------------------------------------- */
  --primary:#1E3A8A;            /* navy — 10.36:1 with white, already fine */
  --primary-dark:#152C6B;
  --primary-mid:#2747A8;
  --primary-light:#DBE4FF;
  --primary-tint:#EEF2FF;

  --accent:#22C55E;             /* leaf green — the brand colour */
  --accent-fill:#22C55E;
  --accent-solid:#15803D;       /* white text passes here */
  --accent-dark:#166534;
  --accent-light:#DCFCE7;

  --warning:#F59E0B;
  --warning-fill:#F59E0B;
  --warning-solid:#B45309;
  --warning-light:#FEF3C7;

  --danger:#EF4444;
  --danger-fill:#EF4444;
  --danger-solid:#B91C1C;
  --danger-light:#FEE2E2;

  --sky:#0EA5E9;
  --info-fill:#0EA5E9;
  --info-solid:#0369A1;
  --info-light:#E0F2FE;

  --purple:#8B5CF6;
  --purple-solid:#6D28D9;
  --purple-light:#EDE9FE;

  --gold:#EAB308;
  --gold-solid:#A16207;
  --gold-light:#FEF9C3;

  /* ---- On-colour text -------------------------------------------------
     Paired with the -light pastels above. All ≥ 6:1. */
  --on-accent-light:#166534;    /* 6.49 */
  --on-warning-light:#92400E;   /* 6.37 */
  --on-danger-light:#991B1B;    /* 6.80 */
  --on-info-light:#075985;      /* 6.59 */
  --on-primary-light:#1E3A8A;   /* 8.16 */
  --on-purple-light:#5B21B6;    /* 7.57 */

  /* ---- Surfaces -------------------------------------------------------- */
  --bg:#F4F7FB;
  --surface:#FFFFFF;
  --surface-2:#F8FAFC;
  --surface-3:#F1F5F9;
  --border:#E2E8F0;
  --border-strong:#CBD5E1;

  /* ---- Text -----------------------------------------------------------
     --text-muted was #64748B in v2: 4.76:1 on white, but only 4.43:1 on
     the page background — and it is used at 10–12px for KPI labels and
     table headings, where marginal is not good enough. #556377 gives
     6.11 / 5.69 and still reads as clearly secondary. */
  --text:#0F172A;
  --text-muted:#556377;
  --text-subtle:#6B7A90;        /* genuinely de-emphasised, ≥4.5 on white */
  --text-invert:#FFFFFF;

  /* ---- Sidebar ---------------------------------------------------------
     --sb-section was #64748B on #0B1F4D: 3.35:1. The section headings
     ("OVERVIEW", "PEOPLE") were close to unreadable at 9.6px. #A5B4CE
     gives 7.61:1. */
  --sb-bg:#0B1F4D;
  --sb-bg-2:#0E2658;
  --sb-text:#CBD5E1;            /* 10.74 */
  --sb-text-muted:#94A3B8;      /* 6.22  */
  --sb-section:#A5B4CE;         /* 7.61  */
  --sb-text-active:#FFFFFF;
  --sb-active-bg:rgba(34,197,94,.16);
  --sb-active-bar:#22C55E;
  --sb-hover-bg:rgba(255,255,255,.07);
  --sb-chip-bg:rgba(255,255,255,.07);
  --sb-divider:rgba(255,255,255,.09);
  --sb-accent-soft:#86EFAC;

  /* ---- Topbar ---------------------------------------------------------- */
  --tb-bg:#FFFFFF;
  --tb-border:#E2E8F0;
  --tb-text:#1E3A8A;
  --tb-btn-fg:#556377;

  /* ---- Focus ring ------------------------------------------------------ */
  --focus-ring:0 0 0 3px rgba(37,99,235,.35);
  --focus-ring-inset:inset 0 0 0 2px rgba(37,99,235,.55);

  /* ---- Elevation ------------------------------------------------------- */
  --shadow-sm:0 1px 2px rgba(15,23,42,.06);
  --shadow:0 1px 3px rgba(15,23,42,.06), 0 4px 12px rgba(15,23,42,.07);
  --shadow-lg:0 4px 8px rgba(15,23,42,.06), 0 18px 38px rgba(15,23,42,.13);
  --shadow-card:0 1px 2px rgba(15,23,42,.04), 0 6px 16px rgba(15,23,42,.06);
  --shadow-card-hover:0 2px 4px rgba(15,23,42,.06), 0 14px 30px rgba(15,23,42,.10);
  --shadow-kpi:0 2px 4px rgba(15,23,42,.05), 0 10px 26px rgba(30,58,138,.10);

  /* ---- Radius ---------------------------------------------------------- */
  --radius-xs:8px;
  --radius-sm:10px;
  --radius:14px;
  --radius-lg:18px;
  --radius-xl:22px;
  --radius-pill:999px;

  /* ---- Spacing scale (4px base) ---------------------------------------- */
  --sp-1:4px;  --sp-2:8px;  --sp-3:12px; --sp-4:16px;
  --sp-5:20px; --sp-6:24px; --sp-8:32px; --sp-10:40px;

  /* ---- Layout ----------------------------------------------------------
     Fluid so a 1280px laptop and a 1920px monitor both feel right
     without a stack of breakpoint overrides. */
  --sb-width:244px;
  --tb-height:60px;
  --content-pad:clamp(14px, 1.2vw + 8px, 28px);
  --card-pad:clamp(16px, 1vw + 10px, 22px);
  --gutter:clamp(12px, 1vw + 6px, 20px);
  --page-max:1560px;

  /* ---- Type scale (fluid) ---------------------------------------------- */
  --fs-body:clamp(14.5px, 0.35vw + 13.5px, 15.5px);
  --fs-sm:clamp(12.5px, 0.2vw + 12px, 13.2px);
  --fs-xs:clamp(11px, 0.15vw + 10.6px, 11.8px);
  --fs-h1:clamp(1.3rem, 1.1vw + 1rem, 1.7rem);
  --fs-h2:clamp(1.15rem, 0.7vw + 0.95rem, 1.4rem);
  --fs-kpi:clamp(1.45rem, 1.4vw + 1rem, 1.95rem);

  --font-sans:'Inter','Segoe UI',system-ui,-apple-system,'Helvetica Neue',sans-serif;
  --font-display:'Poppins','Inter',system-ui,-apple-system,sans-serif;

  /* ---- Icon sizes ------------------------------------------------------ */
  --icon-xs:12px;  --icon-sm:14px;  --icon-md:16px;
  --icon-lg:20px;  --icon-xl:24px;  --icon-2xl:28px; --icon-3xl:34px;
  --icon-nav:17px; --icon-btn:15px; --icon-kpi:22px;
  --icon-page:20px; --icon-table:15px;

  /* ---- Icon chip containers -------------------------------------------- */
  --chip-xs:24px; --chip-sm:30px; --chip-md:36px;
  --chip-lg:44px; --chip-xl:52px; --chip-2xl:64px;

  /* ---- Touch --------------------------------------------------------- */
  --tap-min:44px;

  /* ---- Motion ---------------------------------------------------------- */
  --ease:cubic-bezier(.2,.7,.2,1);
  --dur-fast:.12s;
  --dur:.18s;
  --dur-slow:.3s;

  /* ---- Z-index scale --------------------------------------------------- */
  --z-topbar:100;
  --z-backdrop:1040;
  --z-drawer:1050;
  --z-modal:1055;
  --z-flash:9999;

  /* ---- Skeleton -------------------------------------------------------- */
  --skeleton-a:#E8ECF1;
  --skeleton-b:#F4F7FA;
}

/* ==========================================================================
   2. DESIGN TOKENS — DARK
   --------------------------------------------------------------------------
   v2 defined eleven dark overrides and left everything else on its light
   value, so pastel badges, alerts, skeletons and the subject-card hover
   state all leaked through. Every token the UI reads is redefined here.
   ========================================================================== */
[data-bs-theme="dark"]{
  --bg:#0B1220;
  --surface:#111A2E;
  --surface-2:#0F172A;
  --surface-3:#16203A;
  --border:#22304C;
  --border-strong:#31415F;

  --text:#E8EEF7;
  --text-muted:#9FB0C4;         /* 7.4:1 on --surface */
  --text-subtle:#8798AE;
  --text-invert:#0B1220;

  /* Brand reads brighter on dark: the light-mode navy is 1.67:1 here. */
  --primary:#93C5FD;            /* 9.62 on --surface */
  --primary-mid:#60A5FA;
  --primary-dark:#3B82F6;
  --primary-light:rgba(96,165,250,.18);
  --primary-tint:rgba(96,165,250,.10);

  --accent:#4ADE80;             /* 9.95 */
  --accent-fill:#22C55E;
  --accent-solid:#16A34A;
  --accent-dark:#4ADE80;
  --accent-light:rgba(34,197,94,.16);

  --warning:#FBBF24;            /* 10.39 */
  --warning-fill:#F59E0B;
  --warning-solid:#B45309;
  --warning-light:rgba(245,158,11,.16);

  --danger:#F87171;             /* 6.27 */
  --danger-fill:#EF4444;
  --danger-solid:#B91C1C;
  --danger-light:rgba(239,68,68,.16);

  --sky:#38BDF8;                /* 8.09 */
  --info-fill:#0EA5E9;
  --info-solid:#0369A1;
  --info-light:rgba(14,165,233,.16);

  --purple:#A78BFA;
  --purple-solid:#6D28D9;
  --purple-light:rgba(139,92,246,.18);

  --gold:#FCD34D;
  --gold-light:rgba(234,179,8,.16);

  /* Soft-chip text switches to the bright end on dark tinted backgrounds. */
  --on-accent-light:#6EE7A0;
  --on-warning-light:#FCD34D;
  --on-danger-light:#FCA5A5;
  --on-info-light:#7DD3FC;
  --on-primary-light:#BFDBFE;
  --on-purple-light:#C4B5FD;

  --sb-bg:#0A1426;
  --sb-bg-2:#0D1B33;
  --sb-text:#CBD5E1;
  --sb-text-muted:#94A3B8;
  --sb-section:#A5B4CE;
  --sb-hover-bg:rgba(255,255,255,.06);
  --sb-chip-bg:rgba(255,255,255,.06);
  --sb-divider:rgba(255,255,255,.07);

  --tb-bg:#0E1730;
  --tb-border:#22304C;
  --tb-text:#E8EEF7;
  --tb-btn-fg:#9FB0C4;

  --focus-ring:0 0 0 3px rgba(147,197,253,.42);
  --focus-ring-inset:inset 0 0 0 2px rgba(147,197,253,.60);

  --shadow-sm:0 1px 2px rgba(0,0,0,.40);
  --shadow:0 1px 3px rgba(0,0,0,.40), 0 4px 12px rgba(0,0,0,.34);
  --shadow-lg:0 4px 8px rgba(0,0,0,.40), 0 18px 38px rgba(0,0,0,.48);
  --shadow-card:0 1px 2px rgba(0,0,0,.30), 0 6px 16px rgba(0,0,0,.26);
  --shadow-card-hover:0 2px 4px rgba(0,0,0,.34), 0 14px 30px rgba(0,0,0,.38);
  --shadow-kpi:0 2px 4px rgba(0,0,0,.30), 0 10px 26px rgba(0,0,0,.34);

  --skeleton-a:#18233B;
  --skeleton-b:#22304C;
}

/* ==========================================================================
   3. BOOTSTRAP BRIDGE
   Keeps Bootstrap's own components (dropdowns, tooltips, list groups,
   anything we haven't restyled) inside the same palette.
   ========================================================================== */
[data-bs-theme="light"]{
  --bs-primary:#1E3A8A;
  --bs-success:#15803D;
  --bs-warning:#B45309;
  --bs-danger:#B91C1C;
  --bs-info:#0369A1;
  --bs-body-bg:#F4F7FB;
  --bs-body-color:#0F172A;
  --bs-border-color:#E2E8F0;
  --bs-secondary-color:#556377;
  --bs-link-color:#1E3A8A;
  --bs-link-hover-color:#15803D;
  --bs-emphasis-color:#0F172A;
}
[data-bs-theme="dark"]{
  --bs-primary:#93C5FD;
  --bs-success:#4ADE80;
  --bs-warning:#FBBF24;
  --bs-danger:#F87171;
  --bs-info:#38BDF8;
  --bs-body-bg:#0B1220;
  --bs-body-color:#E8EEF7;
  --bs-border-color:#22304C;
  --bs-secondary-color:#9FB0C4;
  --bs-link-color:#93C5FD;
  --bs-link-hover-color:#4ADE80;
  --bs-emphasis-color:#F8FAFC;
}

/* ==========================================================================
   4. RESET & BASE
   ========================================================================== */
*{ -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale; }
*,*::before,*::after{ box-sizing:border-box; }

html{
  scroll-behavior:smooth;
  -webkit-text-size-adjust:100%;   /* stop iOS inflating text in landscape */
}
html,body{ font-family:var(--font-sans); }

body{
  background:var(--bg);
  color:var(--text);
  font-size:var(--fs-body);
  line-height:1.6;
  margin:0;
  /* Nothing should ever scroll sideways. v2 relied on per-component
     overflow rules and a few of them leaked. */
  overflow-x:hidden;
}

/* Never let a long email, URL or course title blow out its container. */
p,td,th,li,dd,dt,figcaption,label,.card-body,.kpi,.badge{ overflow-wrap:anywhere; }

h1,h2,h3,h4,h5,h6,
.page-title,.kpi .kpi-value,.topbar .brand,
.sidebar .nav-section,.sidebar-role,.modal-title,
.card-header,.nav-tabs .nav-link,.nav-pills .nav-link{
  font-family:var(--font-display);
  letter-spacing:-0.012em;
}
h1,h2,h3,h4,h5,h6{ font-weight:700; color:var(--text); margin-top:0; }
h1{ font-size:var(--fs-h1); }
h2{ font-size:var(--fs-h2); }
h4{ font-size:clamp(1.15rem,0.6vw+1rem,1.35rem); }
h5{ font-size:clamp(1.02rem,0.4vw+.92rem,1.15rem); }
h6{ font-size:1rem; font-weight:700; }

a{ text-decoration:none; color:var(--bs-link-color); }
a:hover{ color:var(--bs-link-hover-color); }

.fw-600{ font-weight:600; }
.fw-700{ font-weight:700; }
.small,small{ font-size:var(--fs-sm); }

/* Figures line up in columns instead of drifting. */
.kpi-value,.table td,.table th,.badge,
[class*="amount"],[class*="marks"],[class*="score"],[class*="percent"]{
  font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1;
}

/* Muted helpers must follow the theme, not Bootstrap's grey. */
.text-muted{ color:var(--text-muted)!important; }
.text-secondary{ color:var(--text-muted)!important; }

::selection{ background:rgba(34,197,94,.24); color:var(--text); }

/* ==========================================================================
   5. ACCESSIBILITY PRIMITIVES
   ========================================================================== */

/* One focus treatment everywhere. Keyboard users get a ring; mouse users
   don't, because :focus-visible already makes that distinction. */
:focus{ outline:none; }
:focus-visible{
  outline:none!important;
  box-shadow:var(--focus-ring)!important;
  border-radius:var(--radius-xs);
  position:relative;
  z-index:1;
}
.btn:focus-visible,.form-control:focus-visible,.form-select:focus-visible{
  box-shadow:var(--focus-ring)!important;
}

/* Skip link — no visual cost, real benefit for keyboard and screen readers. */
.skip-link{
  position:absolute; left:-9999px; top:0;
  background:var(--primary); color:#fff;
  padding:10px 16px; border-radius:0 0 var(--radius-sm) 0;
  font-weight:700; z-index:calc(var(--z-flash) + 1);
}
.skip-link:focus{ left:0; }

.visually-hidden-focusable:not(:focus):not(:focus-within){
  position:absolute!important; width:1px; height:1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap;
}

/* People who ask for less motion get less motion. v2 had no such rule and
   animated every navigation, KPI tile and sidebar item unconditionally. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.001ms!important;
    animation-iteration-count:1!important;
    transition-duration:.001ms!important;
    scroll-behavior:auto!important;
  }
  html{ scroll-behavior:auto; }
}

/* Windows high-contrast / forced-colors mode. */
@media (forced-colors: active){
  .card,.kpi,.btn,.form-control,.form-select,.modal-content{ border:1px solid CanvasText; }
  .kpi .kpi-icon,.icon-chip{ forced-color-adjust:none; }
}

/* ==========================================================================
   6. ICON SYSTEM
   Bootstrap Icons (font) and Lucide (SVG) render identically.
   ========================================================================== */
.bi,[data-lucide],.icon > *{
  display:inline-flex; align-items:center; justify-content:center;
  font-style:normal; line-height:1; vertical-align:-.125em;
}
svg.lucide,[data-lucide]{ width:1em; height:1em; stroke-width:2; }

.icon{
  display:inline-flex; align-items:center; justify-content:center;
  flex-shrink:0; font-size:var(--icon-md); line-height:1;
}
.icon-xs{font-size:var(--icon-xs)} .icon-sm{font-size:var(--icon-sm)}
.icon-md{font-size:var(--icon-md)} .icon-lg{font-size:var(--icon-lg)}
.icon-xl{font-size:var(--icon-xl)} .icon-2xl{font-size:var(--icon-2xl)}
.icon-3xl{font-size:var(--icon-3xl)}

/* Consistent optical sizing per context. */
.btn .bi,.btn [data-lucide]                 { font-size:var(--icon-btn); }
.tb-btn .bi,.tb-btn [data-lucide]           { font-size:var(--icon-md); }
.sidebar .nav-link > i.bi,
.sidebar .nav-link > [data-lucide]          { font-size:var(--icon-nav); }
.kpi-icon .bi,.kpi-icon [data-lucide]       { font-size:var(--icon-kpi); }
.page-title > i.bi,
.page-title > [data-lucide]                 { font-size:var(--icon-page); }
.table .bi,.lms-table .bi                   { font-size:var(--icon-table); }
.input-group-text .bi,
.input-group-text [data-lucide]             { font-size:var(--icon-sm); }
.card-header .bi,.card-header [data-lucide],
.modal-header .bi,.modal-header [data-lucide]{ font-size:var(--icon-md); }
.badge .bi                                   { font-size:.9em; vertical-align:-.1em; }

/* Icon chips ------------------------------------------------------------ */
.icon-chip{
  display:inline-flex; align-items:center; justify-content:center;
  width:var(--chip-md); height:var(--chip-md);
  border-radius:var(--radius-sm); flex-shrink:0;
  font-size:calc(var(--chip-md) * .46);
  transition:transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.icon-chip-xs {width:var(--chip-xs); height:var(--chip-xs); border-radius:7px;             font-size:calc(var(--chip-xs)*.50)}
.icon-chip-sm {width:var(--chip-sm); height:var(--chip-sm); border-radius:var(--radius-xs); font-size:calc(var(--chip-sm)*.48)}
.icon-chip-md {width:var(--chip-md); height:var(--chip-md); border-radius:var(--radius-sm); font-size:calc(var(--chip-md)*.46)}
.icon-chip-lg {width:var(--chip-lg); height:var(--chip-lg); border-radius:12px;             font-size:calc(var(--chip-lg)*.44)}
.icon-chip-xl {width:var(--chip-xl); height:var(--chip-xl); border-radius:14px;             font-size:calc(var(--chip-xl)*.42)}
.icon-chip-2xl{width:var(--chip-2xl);height:var(--chip-2xl);border-radius:18px;             font-size:calc(var(--chip-2xl)*.40)}
.icon-chip.circle{ border-radius:50%; }
.icon-chip.squircle{ border-radius:30%; }

/* Soft chips — pastel ground, saturated glyph. All ≥ 6:1. */
.icon-chip-soft-primary{ background:var(--primary-light); color:var(--on-primary-light); }
.icon-chip-soft-success{ background:var(--accent-light);  color:var(--on-accent-light);  }
.icon-chip-soft-warning{ background:var(--warning-light); color:var(--on-warning-light); }
.icon-chip-soft-danger { background:var(--danger-light);  color:var(--on-danger-light);  }
.icon-chip-soft-info   { background:var(--info-light);    color:var(--on-info-light);    }
.icon-chip-soft-purple { background:var(--purple-light);  color:var(--on-purple-light);  }
.icon-chip-soft-gold   { background:var(--gold-light);    color:var(--gold-solid);       }
.icon-chip-soft-neutral{ background:var(--surface-3);     color:var(--text-muted);       }

/* Solid chips — a white glyph sits on these, so both gradient stops must
   clear 3:1 against white (the non-text minimum). v2's bright stops were
   2.15–2.85:1, i.e. a white icon on a pale wash. */
.icon-chip-solid-primary{ background:linear-gradient(135deg,var(--primary-mid) 0%,#1E3A8A 100%);  color:#fff; box-shadow:0 4px 12px rgba(30,58,138,.28), inset 0 1px 0 rgba(255,255,255,.20); }
.icon-chip-solid-success{ background:linear-gradient(135deg,#17A34A 0%,#15803D 100%);             color:#fff; box-shadow:0 4px 12px rgba(21,128,61,.30),  inset 0 1px 0 rgba(255,255,255,.20); }
.icon-chip-solid-warning{ background:linear-gradient(135deg,#D97706 0%,#B45309 100%);             color:#fff; box-shadow:0 4px 12px rgba(180,83,9,.30),   inset 0 1px 0 rgba(255,255,255,.20); }
.icon-chip-solid-danger { background:linear-gradient(135deg,#DC2626 0%,#B91C1C 100%);             color:#fff; box-shadow:0 4px 12px rgba(185,28,28,.30),  inset 0 1px 0 rgba(255,255,255,.20); }
.icon-chip-solid-info   { background:linear-gradient(135deg,#0284C7 0%,#0369A1 100%);             color:#fff; box-shadow:0 4px 12px rgba(3,105,161,.30),  inset 0 1px 0 rgba(255,255,255,.20); }
.icon-chip-solid-purple { background:linear-gradient(135deg,#7C3AED 0%,#6D28D9 100%);             color:#fff; box-shadow:0 4px 12px rgba(109,40,217,.30), inset 0 1px 0 rgba(255,255,255,.20); }
.icon-chip-solid-gold   { background:linear-gradient(135deg,#CA8A04 0%,#A16207 100%);             color:#fff; box-shadow:0 4px 12px rgba(161,98,7,.30),   inset 0 1px 0 rgba(255,255,255,.20); }

.icon-chip[role="button"]:hover,.icon-chip.icon-chip-interactive:hover{ transform:translateY(-2px) scale(1.04); }
.icon-chip[role="button"]:active,.icon-chip.icon-chip-interactive:active{ transform:translateY(0) scale(.98); }
.icon-chip[class*="solid"] [data-lucide]{ stroke-width:2.4; }
.icon-spin > *,.icon-spin{ animation:spin 1.1s linear infinite; transform-origin:center; }

/* ==========================================================================
   7. APP SHELL
   Desktop: fixed viewport, sidebar and content scroll independently.
   Mobile:  normal document scroll, sidebar is an off-canvas drawer.
   ========================================================================== */
@media(min-width:992px){
  html,body{ height:100vh; height:100dvh; overflow:hidden; }
  .app-shell{
    display:flex;
    height:calc(100dvh - var(--tb-height));
    overflow:hidden; position:relative;
  }
  .sidebar{ height:100%; overflow-y:auto; overscroll-behavior:contain; }
  .main-content{ height:100%; overflow-y:auto; overflow-x:hidden; overscroll-behavior:contain; }
}
@media(max-width:991px){
  .app-shell{ display:flex; min-height:100dvh; position:relative; }
}

.main-content{
  flex:1; min-width:0;
  background:var(--bg);
  padding:var(--content-pad) var(--content-pad) var(--sp-8);
  /* Respect notches and home indicators on modern phones. */
  padding-left:max(var(--content-pad), env(safe-area-inset-left));
  padding-right:max(var(--content-pad), env(safe-area-inset-right));
  padding-bottom:max(var(--sp-8), env(safe-area-inset-bottom));
}
/* Keep the measure sane on very wide monitors instead of stretching
   tables to 1900px, which makes rows genuinely hard to track across. */
.main-content > *{ max-width:var(--page-max); }

/* ==========================================================================
   8. TOPBAR
   ========================================================================== */
.topbar{
  background:var(--tb-bg);
  color:var(--tb-text);
  padding:0 var(--sp-4);
  padding-left:max(var(--sp-4), env(safe-area-inset-left));
  padding-right:max(var(--sp-4), env(safe-area-inset-right));
  height:var(--tb-height);
  display:flex; align-items:center; justify-content:space-between;
  gap:var(--sp-2);
  position:sticky; top:0; z-index:var(--z-topbar);
  border-bottom:1px solid var(--tb-border);
  box-shadow:var(--shadow-sm);
}
.topbar .brand{
  font-weight:800; font-size:clamp(.85rem,.5vw+.75rem,.98rem);
  letter-spacing:.2px; color:var(--primary);
  display:flex; align-items:center; gap:var(--sp-2);
  line-height:1.15; min-width:0;
}
.topbar .brand > span{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.topbar .brand img{
  height:28px!important; width:auto; display:block;
  object-fit:contain; border-radius:6px;
  padding:1px 3px; background:rgba(30,58,138,.06);
  flex-shrink:0;
}
[data-bs-theme="dark"] .topbar .brand img{ background:rgba(147,197,253,.10); }

.topbar .tb-btn{
  background:transparent;
  border:1px solid var(--border);
  color:var(--tb-btn-fg);
  width:38px; height:38px; min-width:38px;
  border-radius:var(--radius-sm);
  display:inline-flex; align-items:center; justify-content:center;
  transition:background var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease);
  padding:0; flex-shrink:0;
}
.topbar .tb-btn:hover{
  background:var(--primary-light);
  color:var(--on-primary-light);
  border-color:transparent;
}
.topbar .tb-btn .badge{
  position:absolute; top:-4px; right:-4px;
  min-width:17px; height:17px; padding:0 4px;
  font-size:10px; line-height:17px;
  display:inline-flex; align-items:center; justify-content:center;
}

#lms-sync-status{ font-size:var(--fs-xs); padding:0 var(--sp-1); white-space:nowrap; }
#lms-sync-status .bi{ font-size:var(--icon-sm); }

@media(max-width:768px){
  :root{ --tb-height:54px; }
  .topbar{ padding:0 var(--sp-2); }
  .topbar .brand img{ height:24px!important; }
}
@media(max-width:420px){
  .topbar .brand span{ display:none!important; }
  #lms-sync-status{ display:none!important; }
}

/* ==========================================================================
   9. SIDEBAR
   ========================================================================== */
.sidebar{
  width:var(--sb-width); flex-shrink:0;
  /* background-color first so anything computing a background gets a real
     value, then the gradient on top. */
  background-color:var(--sb-bg);
  background-image:linear-gradient(180deg,var(--sb-bg) 0%,var(--sb-bg-2) 100%);
  color:var(--sb-text);
  padding:0 0 var(--sp-5);
  border-right:1px solid rgba(0,0,0,.22);
  box-shadow:2px 0 12px rgba(11,31,77,.18);
}
.sidebar::-webkit-scrollbar{ width:6px; }
.sidebar::-webkit-scrollbar-thumb{ background:rgba(255,255,255,.14); border-radius:6px; }
.sidebar::-webkit-scrollbar-track{ background:transparent; }

.sidebar-role{
  display:flex; align-items:center; gap:7px;
  margin:var(--sp-3) var(--sp-3) var(--sp-1);
  padding:8px 11px;
  background:rgba(34,197,94,.14);
  color:var(--sb-accent-soft);
  border:1px solid rgba(34,197,94,.24);
  border-radius:var(--radius-sm);
  font-size:.7rem; font-weight:700;
  letter-spacing:.08em; text-transform:uppercase;
  line-height:1.15;
}
.sidebar-role .bi{ font-size:13px; color:var(--sb-accent-soft); }

.sidebar .nav-section{
  padding:var(--sp-3) var(--sp-4) var(--sp-1);
  font-size:.64rem;
  letter-spacing:.13em; text-transform:uppercase;
  color:var(--sb-section);          /* 7.61:1 — was 3.35:1 in v2 */
  font-weight:700;
}
.sidebar nav{ padding:2px var(--sp-2); }

.sidebar .nav-link{
  color:var(--sb-text);
  border-radius:var(--radius-sm);
  margin:2px 0; padding:10px 12px;
  font-size:.88rem; font-weight:600;
  display:flex; align-items:center; gap:11px;
  transition:background var(--dur) var(--ease), color var(--dur) var(--ease);
  position:relative; min-height:42px;
}
.sidebar .nav-link > i.bi,
.sidebar .nav-link > [data-lucide]{
  display:inline-flex; align-items:center; justify-content:center;
  width:30px; height:30px; border-radius:var(--radius-xs);
  background:var(--sb-chip-bg);
  color:var(--sb-text);
  font-size:var(--icon-nav);
  flex-shrink:0;
  transition:background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.sidebar .nav-link > span,
.sidebar .nav-link > .label{ min-width:0; overflow:hidden; text-overflow:ellipsis; }
.sidebar .nav-link:hover{ background:var(--sb-hover-bg); color:var(--sb-text-active); }
.sidebar .nav-link:hover > i.bi{ background:rgba(34,197,94,.20); color:var(--sb-accent-soft); }
.sidebar .nav-link.active{ background:var(--sb-active-bg); color:var(--sb-text-active); font-weight:700; }
.sidebar .nav-link.active > i.bi{
  background:linear-gradient(135deg,#22C55E 0%,#15803D 100%);
  color:#fff;
  box-shadow:0 2px 6px rgba(21,128,61,.45), inset 0 1px 0 rgba(255,255,255,.20);
}
.sidebar .nav-link.active::before{
  content:""; position:absolute; left:-8px; top:7px; bottom:7px;
  width:3px; background:var(--sb-active-bar); border-radius:0 4px 4px 0;
}
.sidebar .nav-link .ms-auto{ margin-left:auto; }
.sidebar .nav-link .badge{ font-size:.65rem; padding:3px 7px; font-weight:700; flex-shrink:0; }

/* Drawer mode ------------------------------------------------------------ */
.sidebar-toggle{ display:none; }
.sidebar-backdrop{ display:none; }
@media(max-width:991px){
  :root{ --sb-width:270px; }
  .sidebar{
    position:fixed; left:-310px; top:0; z-index:var(--z-drawer);
    height:100dvh; width:270px;
    padding-bottom:calc(var(--sp-8) + env(safe-area-inset-bottom));
    padding-left:env(safe-area-inset-left);
    transition:left var(--dur-slow) var(--ease);
    overflow-y:auto; -webkit-overflow-scrolling:touch;
    overscroll-behavior:contain;
  }
  .sidebar.open{ left:0; box-shadow:8px 0 30px rgba(0,0,0,.38); }
  .sidebar-toggle{ display:inline-flex; }
  .sidebar-backdrop.show{
    display:block; position:fixed; inset:0;
    background:rgba(8,15,30,.58);
    z-index:var(--z-backdrop);
    -webkit-backdrop-filter:blur(2px); backdrop-filter:blur(2px);
  }
  .sidebar .nav-link{ font-size:.92rem; min-height:var(--tap-min); }
}

/* ==========================================================================
   10. CARDS
   ========================================================================== */
.card{
  border:1px solid var(--border);
  border-radius:var(--radius-lg);
  background:var(--surface);
  box-shadow:var(--shadow-card);
  transition:box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.card:not(.no-hover):hover{ transform:translateY(-1px); box-shadow:var(--shadow-card-hover); }
.card-header{
  background:var(--surface);
  color:var(--text);
  border-bottom:1px solid var(--border);
  font-weight:700;
  padding:var(--sp-4) var(--sp-5);
  font-size:1rem;
  letter-spacing:-0.006em;
  display:flex; align-items:center; gap:var(--sp-2); flex-wrap:wrap;
  border-radius:var(--radius-lg) var(--radius-lg) 0 0;
}
.card-header .btn{ margin-left:auto; }
.card-body{ padding:var(--card-pad); border-radius:inherit; }
.card.p-3{ padding:var(--sp-4)!important; }
.card.p-4,.card.p-5{ padding:var(--card-pad)!important; }
.card-footer{ background:var(--surface-2); border-top:1px solid var(--border); padding:var(--sp-3) var(--sp-5); }

@media(max-width:768px){
  .card{ border-radius:var(--radius); }
  .card-header{ padding:var(--sp-3) var(--sp-4); font-size:.95rem; border-radius:var(--radius) var(--radius) 0 0; }
  /* A card lift on a touch screen is just a tap flicker. */
  .card:not(.no-hover):hover{ transform:none; }
}

/* ==========================================================================
   11. KPI TILES
   ========================================================================== */
.kpi{
  border-radius:var(--radius-xl);
  background:var(--surface);
  border:1px solid var(--border);
  padding:var(--sp-4) var(--sp-5);
  display:flex; gap:var(--sp-4); align-items:center;
  transition:transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
  position:relative; overflow:hidden;
  min-height:88px; height:100%;   /* equal heights in a grid row */
  box-shadow:var(--shadow-card);
}
.kpi:hover{ transform:translateY(-2px); box-shadow:var(--shadow-card-hover); }
/* No side strip — per the standing preference at the top of this file. */

.kpi .kpi-icon{
  width:56px; height:56px; border-radius:var(--radius-lg);
  display:inline-flex; align-items:center; justify-content:center;
  color:#fff;
  background:linear-gradient(135deg,var(--primary-mid) 0%,#1E3A8A 100%);
  flex-shrink:0;
  box-shadow:0 6px 16px rgba(30,58,138,.30), inset 0 1px 0 rgba(255,255,255,.22);
}
.kpi .kpi-body{ min-width:0; }
.kpi .kpi-label{
  font-size:.72rem; color:var(--text-muted);
  font-weight:700; text-transform:uppercase;
  letter-spacing:.06em; line-height:1.25;
}
.kpi .kpi-value{
  font-size:var(--fs-kpi); font-weight:800; color:var(--text);
  line-height:1.1; margin-top:var(--sp-1);
  font-family:var(--font-display);
  letter-spacing:-0.025em;
}
.kpi .kpi-trend{
  font-size:.74rem; margin-top:3px;
  color:var(--on-accent-light); font-weight:700;
  display:inline-flex; align-items:center; gap:3px;
}
.kpi .kpi-trend.down{ color:var(--on-danger-light); }

/* Variants — darker gradient stops so the white glyph clears 3:1. */
.kpi.kpi-success .kpi-icon{ background:linear-gradient(135deg,#17A34A 0%,#15803D 100%); box-shadow:0 6px 16px rgba(21,128,61,.32), inset 0 1px 0 rgba(255,255,255,.22); }
.kpi.kpi-warning .kpi-icon{ background:linear-gradient(135deg,#D97706 0%,#B45309 100%); box-shadow:0 6px 16px rgba(180,83,9,.32),  inset 0 1px 0 rgba(255,255,255,.22); }
.kpi.kpi-danger  .kpi-icon{ background:linear-gradient(135deg,#DC2626 0%,#B91C1C 100%); box-shadow:0 6px 16px rgba(185,28,28,.32), inset 0 1px 0 rgba(255,255,255,.22); }
.kpi.kpi-info    .kpi-icon{ background:linear-gradient(135deg,#0284C7 0%,#0369A1 100%); box-shadow:0 6px 16px rgba(3,105,161,.32), inset 0 1px 0 rgba(255,255,255,.22); }
.kpi.kpi-purple  .kpi-icon{ background:linear-gradient(135deg,#7C3AED 0%,#6D28D9 100%); box-shadow:0 6px 16px rgba(109,40,217,.32),inset 0 1px 0 rgba(255,255,255,.22); }

/* Depth motif */
.kpi::after{
  content:""; position:absolute; right:-20px; bottom:-30px;
  width:120px; height:120px; border-radius:50%;
  background:radial-gradient(circle,rgba(30,58,138,.05) 0%,transparent 65%);
  pointer-events:none;
}
.kpi.kpi-success::after{ background:radial-gradient(circle,rgba(21,128,61,.07) 0%,transparent 65%); }
.kpi.kpi-warning::after{ background:radial-gradient(circle,rgba(180,83,9,.07) 0%,transparent 65%); }
.kpi.kpi-danger::after { background:radial-gradient(circle,rgba(185,28,28,.07) 0%,transparent 65%); }
.kpi.kpi-info::after   { background:radial-gradient(circle,rgba(3,105,161,.07) 0%,transparent 65%); }
.kpi.kpi-purple::after { background:radial-gradient(circle,rgba(109,40,217,.07) 0%,transparent 65%); }
[data-bs-theme="dark"] .kpi::after{ background:radial-gradient(circle,rgba(147,197,253,.05) 0%,transparent 65%); }

@media(max-width:768px){
  .kpi{ padding:var(--sp-3) var(--sp-4); gap:var(--sp-3); min-height:76px; border-radius:var(--radius-lg); }
  .kpi .kpi-icon{ width:46px; height:46px; border-radius:var(--radius); }
  .kpi .kpi-icon .bi{ font-size:19px; }
  .kpi:hover{ transform:none; }
}
@media(max-width:400px){
  .kpi{ padding:10px 12px; gap:10px; min-height:68px; }
  .kpi .kpi-icon{ width:40px; height:40px; border-radius:12px; }
  .kpi .kpi-icon .bi{ font-size:17px; }
  .kpi .kpi-label{ font-size:.64rem; letter-spacing:.04em; }
}

/* KPI grid on phones — a real grid, so tiles line up and match heights
   whatever the label length. */
@media(max-width:640px){
  .row.g-3:has(.kpi),
  .row.g-2:has(.kpi),
  .row:has(> [class*="col-"] > .kpi){
    display:grid!important;
    grid-template-columns:repeat(2,minmax(0,1fr));
    gap:var(--sp-3);
    --bs-gutter-x:0; --bs-gutter-y:0;
    margin:0;
  }
  .row:has(.kpi) > [class*="col-"]{
    width:100%!important; max-width:none!important;
    flex:initial!important; padding:0!important; margin:0!important;
  }
}
@media(max-width:340px){
  .row:has(.kpi){ grid-template-columns:1fr; }
}

/* Legacy stat-card */
.stat-card{
  border-radius:var(--radius)!important;
  padding:var(--sp-4)!important;
  color:#fff!important;
  box-shadow:var(--shadow-sm);
  position:relative; overflow:hidden;
}
.stat-card::after{
  content:""; position:absolute; right:-30px; bottom:-30px;
  width:120px; height:120px; border-radius:50%; background:rgba(255,255,255,.08);
}

/* ==========================================================================
   12. PAGE HEADER
   ========================================================================== */
.page-title{
  color:var(--text);
  font-weight:800;
  font-size:var(--fs-h1);
  letter-spacing:-0.022em;
  display:flex; align-items:center; gap:var(--sp-3);
  line-height:1.2; margin:0; min-width:0;
}
.page-title > i.bi{
  display:inline-flex; align-items:center; justify-content:center;
  width:42px; height:42px; border-radius:12px;
  background:linear-gradient(135deg,var(--primary-light) 0%,var(--primary-tint) 100%);
  color:var(--on-primary-light);
  font-size:var(--icon-page);
  box-shadow:0 2px 6px rgba(30,58,138,.10), inset 0 1px 0 rgba(255,255,255,.50);
  flex-shrink:0;
}
[data-bs-theme="dark"] .page-title > i.bi{
  background:linear-gradient(135deg,rgba(96,165,250,.22) 0%,rgba(96,165,250,.09) 100%);
  color:var(--primary);
  box-shadow:none;
}
.page-subtitle{ color:var(--text-muted); font-size:.92rem; margin-top:var(--sp-1); }

.page-header{
  display:flex; justify-content:space-between; align-items:center;
  flex-wrap:wrap; gap:var(--sp-3);
  margin-bottom:var(--sp-5);
}
.page-header > div:last-child{ display:inline-flex; gap:var(--sp-2); flex-wrap:wrap; }

@media(max-width:768px){
  .page-title > i.bi{ width:38px; height:38px; font-size:17px; }
  .page-subtitle{ font-size:.85rem; }
}
/* Title above actions, actions full width and evenly split. */
@media(max-width:576px){
  .page-header,
  .d-flex.justify-content-between.align-items-center.mb-4{
    flex-direction:column!important; align-items:stretch!important; gap:var(--sp-3)!important;
  }
  .page-header > div:last-child{ width:100%; }
  .page-header > div:last-child > .btn{ flex:1 1 0; min-width:0; }
  .d-flex.justify-content-between.align-items-center.mb-4 > .d-flex{ flex-wrap:wrap; gap:var(--sp-2); }
}

/* ==========================================================================
   13. BUTTONS
   --------------------------------------------------------------------------
   v2 declared each solid button twice — a gradient first, then a flat
   override later in the file that silently won. The gradients were dead
   code. This section states each style once.

   White labels now sit on the -solid ramp:
     success #15803D 5.02 · warning #B45309 5.02
     danger  #B91C1C 6.47 · info    #0369A1 5.93
   ========================================================================== */
.btn{
  font-weight:700;
  border-radius:var(--radius-sm);
  padding:10px 18px;
  font-size:.92rem;
  line-height:1.3;
  transition:transform var(--dur-fast) var(--ease), box-shadow var(--dur) var(--ease),
             background-color var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease);
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  border-width:1.5px; border-style:solid;
  letter-spacing:0;
  min-height:40px;
}
.btn-sm{ border-radius:9px; padding:7px 13px; font-size:.82rem; min-height:34px; }
.btn-lg{ padding:13px 24px; font-size:1rem; min-height:48px; border-radius:12px; }
.btn:active{ transform:scale(.975); }
.btn:disabled,.btn.disabled{ opacity:.55; cursor:not-allowed; transform:none!important; box-shadow:none!important; }

.btn-primary,.btn-success,.btn-warning,.btn-danger,.btn-info,.btn-secondary{
  color:#fff;
  box-shadow:0 1px 2px rgba(15,23,42,.12), 0 2px 0 rgba(15,23,42,.06);
}
.btn-primary:hover,.btn-success:hover,.btn-warning:hover,
.btn-danger:hover,.btn-info:hover,.btn-secondary:hover{
  color:#fff;
  transform:translateY(-1px);
  box-shadow:0 4px 12px rgba(15,23,42,.16), 0 1px 0 rgba(15,23,42,.10);
}

.btn-primary  { background:var(--primary);       border-color:var(--primary);       }
.btn-primary:hover,.btn-primary:focus  { background:var(--primary-dark); border-color:var(--primary-dark); }
.btn-success  { background:var(--accent-solid);  border-color:var(--accent-solid);  }
.btn-success:hover,.btn-success:focus  { background:#166534; border-color:#166534; }
.btn-warning  { background:var(--warning-solid); border-color:var(--warning-solid); }
.btn-warning:hover,.btn-warning:focus  { background:#92400E; border-color:#92400E; }
.btn-danger   { background:var(--danger-solid);  border-color:var(--danger-solid);  }
.btn-danger:hover,.btn-danger:focus    { background:#991B1B; border-color:#991B1B; }
.btn-info     { background:var(--info-solid);    border-color:var(--info-solid);    }
.btn-info:hover,.btn-info:focus        { background:#075985; border-color:#075985; }
.btn-secondary{ background:#475569;              border-color:#475569;              }
.btn-secondary:hover,.btn-secondary:focus{ background:#334155; border-color:#334155; }

/* Dark mode keeps the same solid fills — white on them still passes, and
   inverting to pale fills would make primary actions shout. */
[data-bs-theme="dark"] .btn-primary{ background:#1D4ED8; border-color:#1D4ED8; color:#fff; }
[data-bs-theme="dark"] .btn-primary:hover{ background:#2563EB; border-color:#2563EB; }

/* Outline buttons — token-driven so dark mode inherits the bright ramp.
   In v2 these were hardcoded light-mode hexes: the navy outline-primary
   measured 1.67:1 on the dark card surface, i.e. invisible. */
.btn-outline-primary  { color:var(--primary);          border-color:currentColor; background:transparent; }
.btn-outline-success  { color:var(--on-accent-light);  border-color:currentColor; background:transparent; }
.btn-outline-warning  { color:var(--on-warning-light); border-color:currentColor; background:transparent; }
.btn-outline-danger   { color:var(--on-danger-light);  border-color:currentColor; background:transparent; }
.btn-outline-info     { color:var(--on-info-light);    border-color:currentColor; background:transparent; }
.btn-outline-secondary{ color:var(--text-muted);       border-color:var(--border-strong); background:transparent; }

.btn-outline-primary:hover{ background:var(--primary);       border-color:var(--primary);       color:#fff; }
.btn-outline-success:hover{ background:var(--accent-solid);  border-color:var(--accent-solid);  color:#fff; }
.btn-outline-warning:hover{ background:var(--warning-solid); border-color:var(--warning-solid); color:#fff; }
.btn-outline-danger:hover { background:var(--danger-solid);  border-color:var(--danger-solid);  color:#fff; }
.btn-outline-info:hover   { background:var(--info-solid);    border-color:var(--info-solid);    color:#fff; }
.btn-outline-secondary:hover{ background:var(--surface-3);   border-color:var(--border-strong); color:var(--text); }
[data-bs-theme="dark"] .btn-outline-primary:hover{ background:#1D4ED8; border-color:#1D4ED8; }
[data-bs-theme="dark"] .btn-outline-success:hover,
[data-bs-theme="dark"] .btn-outline-warning:hover,
[data-bs-theme="dark"] .btn-outline-danger:hover,
[data-bs-theme="dark"] .btn-outline-info:hover{ color:#fff; }

.btn-link{ color:var(--bs-link-color); font-weight:600; text-decoration:none; }
.btn-link:hover{ text-decoration:underline; }

/* Soft icon buttons */
.btn-icon{
  width:34px; height:34px; min-width:34px; padding:0;
  display:inline-flex; align-items:center; justify-content:center;
  border-radius:var(--radius-xs); border:1px solid transparent;
  transition:transform var(--dur-fast) var(--ease), background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.btn-icon:hover{ transform:translateY(-1px); }

/* ==========================================================================
   14. FORMS
   ========================================================================== */
.form-control,.form-select{
  border:1.5px solid var(--border);
  border-radius:var(--radius-xs);
  padding:8px 12px;
  font-size:.88rem;
  background:var(--surface);
  color:var(--text);
  transition:border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
  min-height:38px;
}
.form-control::placeholder{ color:var(--text-subtle); opacity:1; }
.form-control:hover,.form-select:hover{ border-color:var(--border-strong); }
.form-control:focus,.form-select:focus{
  border-color:var(--primary);
  box-shadow:var(--focus-ring);
  background:var(--surface);
  color:var(--text);
}
.form-control:disabled,.form-select:disabled,
.form-control[readonly]{ background:var(--surface-3); color:var(--text-muted); cursor:not-allowed; }
.form-control.is-invalid,.form-select.is-invalid{ border-color:var(--danger-solid); }
.invalid-feedback{ color:var(--on-danger-light); font-weight:600; font-size:var(--fs-sm); }

.form-label{
  font-weight:600; font-size:.8rem;
  color:var(--text); margin-bottom:var(--sp-1);
  display:inline-block;
}
.form-text{ color:var(--text-muted); font-size:var(--fs-sm); }
.form-floating > label{ color:var(--text-muted); font-weight:500; }

.input-group-text{
  background:var(--surface-2);
  border:1.5px solid var(--border);
  color:var(--text-muted);
  border-radius:var(--radius-xs) 0 0 var(--radius-xs);
  padding:6px 11px;
}
.input-group > .form-control:not(:first-child){ border-radius:0 var(--radius-xs) var(--radius-xs) 0; }
.input-group > .form-control:first-child{ border-radius:var(--radius-xs) 0 0 var(--radius-xs); }

.form-control-sm,.form-select-sm{ font-size:.8rem; padding:5px 9px; min-height:32px; }

.form-check-input{ width:1.1em; height:1.1em; margin-top:.2em; border-color:var(--border-strong); }
.form-check-input:checked{ background-color:var(--primary); border-color:var(--primary); }
.form-check-input:focus{ box-shadow:var(--focus-ring); border-color:var(--primary); }
.form-check-label{ color:var(--text); }

/* Native date/time pickers are unreadable in dark mode without this. */
[data-bs-theme="dark"] input[type="date"],
[data-bs-theme="dark"] input[type="time"],
[data-bs-theme="dark"] input[type="datetime-local"],
[data-bs-theme="dark"] input[type="month"]{ color-scheme:dark; }

/* Touch: 16px inputs stop iOS Safari zooming the page on focus, and the
   taller control is easier to hit. Keyed to pointer type, not width, so a
   narrow desktop window keeps its compact form. */
@media (pointer: coarse){
  .form-control,.form-select{ font-size:16px; min-height:var(--tap-min); padding:10px 13px; }
  .form-control-sm,.form-select-sm{ font-size:15px; min-height:38px; }
  .input-group-text{ padding:9px 13px; }
  .form-check-input{ width:1.25em; height:1.25em; }
}

/* ==========================================================================
   15. TABLES — DESKTOP
   ========================================================================== */
.table{ color:var(--text); font-size:.9rem; margin:0; width:100%; }
.table thead th{
  background:transparent;
  border-bottom:1px solid var(--border)!important;
  font-weight:700;
  font-size:.72rem;
  text-transform:uppercase;
  letter-spacing:.075em;
  color:var(--text-muted);
  padding:var(--sp-3) var(--sp-4);
  white-space:nowrap;
  vertical-align:middle;
  position:relative;
}
.table tbody td{
  padding:var(--sp-3) var(--sp-4);
  border-color:var(--border)!important;
  vertical-align:middle;
  font-size:.9rem;
  line-height:1.45;
  color:var(--text);
}
.table tbody tr{ transition:background var(--dur) var(--ease); }
.table-hover tbody tr:hover{ background:var(--surface-2)!important; }
[data-bs-theme="dark"] .table-hover tbody tr:hover{ background:rgba(147,197,253,.06)!important; }
.table tbody tr:last-child td{ border-bottom:0!important; }
.table > :not(caption) > * > *{ background-color:transparent; }

/* Name column — avatar and name side by side, never stacked. */
.table tbody td:first-child{ white-space:nowrap; font-weight:700; color:var(--text); }
.table tbody td:first-child .avatar{ margin-right:var(--sp-2); vertical-align:middle; }
.table tbody td:first-child .avatar + span,
.table tbody td:first-child .avatar + .fw-600,
.table tbody td:first-child .avatar + a,
.table tbody td:first-child .avatar + strong{ vertical-align:middle; display:inline-block; font-size:.96rem; font-weight:700; }

/* Badges never wrap mid-pill. */
.table tbody td .badge,
.table tbody td [class*="badge-"]{ white-space:nowrap; }

/* Actions column stays on one row. */
.table tbody td:last-child{ white-space:nowrap; text-align:left; }
.table thead th:last-child{ text-align:left; }

/* Table action chips */
.table tbody td > .btn-outline-info,
.table tbody td > .btn-outline-primary,
.table tbody td > .btn-outline-success,
.table tbody td > .btn-outline-warning,
.table tbody td > .btn-outline-danger,
.table tbody td > .btn-outline-secondary{
  border-radius:9px;
  padding:0;
  width:34px; height:34px; min-width:34px; min-height:34px;
  display:inline-flex; align-items:center; justify-content:center;
  margin:0 3px 0 0;
  border-width:1.5px;
}
.table tbody td > .btn-outline-primary { background:color-mix(in srgb, currentColor 9%, transparent); }
.table tbody td > .btn-outline-success { background:color-mix(in srgb, currentColor 9%, transparent); }
.table tbody td > .btn-outline-warning { background:color-mix(in srgb, currentColor 10%, transparent); }
.table tbody td > .btn-outline-danger  { background:color-mix(in srgb, currentColor 9%, transparent); }
.table tbody td > .btn-outline-info    { background:color-mix(in srgb, currentColor 9%, transparent); }
.table tbody td > .btn:hover{ transform:translateY(-1px); box-shadow:0 4px 12px rgba(15,23,42,.12); }
.table tbody td > .btn + .btn{ margin-left:0; }
.table tbody td > .btn i{ font-size:14px; vertical-align:0; line-height:1; }

/* Status pill buttons in rows */
.table tbody td .btn.btn-success,
.table tbody td .btn.btn-secondary{
  border-radius:var(--radius-pill)!important;
  padding:5px 14px!important;
  font-size:.78rem!important;
  font-weight:700!important;
  min-height:30px!important;
  width:auto!important;
  letter-spacing:0;
}

/* Empty state */
.table tbody tr td[colspan]{
  text-align:center; color:var(--text-muted);
  padding:var(--sp-10) var(--sp-4); font-size:.9rem;
}
.table tbody tr td[colspan] i.bi{ font-size:30px; opacity:.45; display:block; margin-bottom:var(--sp-2); }

/* ==========================================================================
   16. TABLES — PHONE (≤640px): every row becomes a labelled card
   --------------------------------------------------------------------------
   The label comes from `data-label`, which enhanceTables() in
   mentoria-lms.js copies off each column's <th> after every render. In v2
   this CSS existed but nothing ever set data-label, so rows rendered as a
   column of bare values — you could not tell Level from Enrolled In — each
   indented by 88px of empty pseudo-element.

   The layout is a two-column grid per cell: label left, value right. That
   keeps values aligned down the card instead of raggedly following labels
   of different lengths.
   ========================================================================== */
@media(max-width:640px){
  /* `.lms-stack` is applied by enhanceTables() to any table with eight
     columns or fewer, at the same moment it stamps the labels — so the
     card layout and the labels it depends on can never get out of step.
     Note this is NOT `.lms-table`: that class is initDataTables()'s
     selector, and reusing it here would bolt search and pagination onto
     every small summary table in the app.

     The class is doubled in each selector (`.lms-stack.lms-stack`) purely
     to raise specificity to (0,2,4). It matches exactly the same
     elements, but it means a stale cached copy of the v2 stylesheet — or
     any theme rule of the form `.card .lms-table td { display:block }`,
     which scores (0,2,1) — cannot win the display property and collapse
     the label/value grid back into a single column. Verified against the
     live site, where exactly that happened. */
  table.lms-stack.lms-stack{
    display:block!important;
    border:0!important;
    background:transparent!important;
    width:100%!important;
  }
  table.lms-stack.lms-stack > thead{ display:none!important; }
  table.lms-stack.lms-stack > tbody{ display:block!important; width:100%!important; }

  table.lms-stack.lms-stack > tbody > tr{
    display:block!important; width:100%!important;
    background:var(--surface);
    border:1px solid var(--border);
    border-radius:var(--radius);
    padding:var(--sp-3) var(--sp-4);
    margin:0 0 var(--sp-3);
    box-shadow:var(--shadow-sm);
  }
  table.lms-stack.lms-stack > tbody > tr:hover{ background:var(--surface)!important; }

  table.lms-stack.lms-stack > tbody > tr > td{
    display:grid!important;
    grid-template-columns:minmax(76px, 38%) 1fr;
    align-items:baseline;
    gap:var(--sp-3);
    width:100%!important;
    padding:7px 0!important;
    border:0!important;
    text-align:left!important;
    white-space:normal!important;
    word-break:break-word;
    font-size:.9rem;
  }
  table.lms-stack.lms-stack > tbody > tr > td::before{
    content:attr(data-label);
    font-weight:700;
    color:var(--text-muted);
    font-size:.68rem;
    text-transform:uppercase;
    letter-spacing:.06em;
    line-height:1.5;
  }
  /* No label (or nothing to label) → the value takes the full width
     instead of sitting in a phantom 88px indent, which is what v2 did
     to every single cell. */
  table.lms-stack.lms-stack > tbody > tr > td:not([data-label])::before{ content:none; }
  table.lms-stack.lms-stack > tbody > tr > td:not([data-label]){ display:block!important; }

  /* Row 1 is the card's heading: no label, bigger, with a rule under it. */
  table.lms-stack.lms-stack > tbody > tr > td:first-child{
    display:block!important;
    font-size:1.02rem; font-weight:700;
    border-bottom:1px solid var(--border)!important;
    padding-bottom:var(--sp-3)!important;
    margin-bottom:var(--sp-2)!important;
    white-space:normal!important;
  }
  table.lms-stack.lms-stack > tbody > tr > td:first-child::before{ content:none; }

  /* Last row is the action bar. */
  table.lms-stack.lms-stack > tbody > tr > td:last-child{
    display:flex!important;
    gap:var(--sp-2)!important;
    flex-wrap:wrap;
    border-top:1px solid var(--border)!important;
    margin-top:var(--sp-2)!important;
    padding-top:var(--sp-3)!important;
  }
  table.lms-stack.lms-stack > tbody > tr > td:last-child::before{ content:none; }
  table.lms-stack.lms-stack > tbody > tr > td:last-child > .btn{
    flex:1 1 auto;
    min-width:var(--tap-min);
    width:auto!important;
    height:var(--tap-min)!important;
    min-height:var(--tap-min)!important;
  }

  /* Empty state spans the card. */
  table.lms-stack.lms-stack > tbody > tr > td[colspan]{
    display:block!important;
    text-align:center!important;
    border:0!important;
    padding:var(--sp-8) var(--sp-3)!important;
  }
  table.lms-stack.lms-stack > tbody > tr > td[colspan]::before{ content:none; }

  /* Card wrapper gives the stack its own breathing room. */
  .card > .card-body.p-0{ padding:var(--sp-3)!important; }
  .card.lms-list-card,
  .card:has(> .card-body.p-0 > .dataTables_wrapper){ min-height:auto; }

  /* DataTables is initialised with scrollX:true, which wraps the table
     in cloned-header scroll containers. Those wrappers clip and
     duplicate the stacked cards, so switch them off at this width. */
  .dataTables_scroll,
  .dataTables_scrollBody,
  .dataTables_scrollHead,
  .dt-scroll,.dt-scroll-body,.dt-scroll-head{
    overflow:visible!important; width:auto!important; max-height:none!important;
  }
  .dataTables_scrollHead,.dt-scroll-head{ display:none!important; }

  /* A few tables are genuinely matrices (attendance registers, mark
     grids) where stacking destroys the meaning. Opt those out with
     .lms-table-keep and they scroll horizontally instead. */
  table.lms-table-keep{ display:table!important; white-space:nowrap; }
  table.lms-table-keep > thead{ display:table-header-group!important; }
  table.lms-table-keep > tbody{ display:table-row-group!important; }
  table.lms-table-keep > tbody > tr{ display:table-row!important; background:transparent; border:0; padding:0; margin:0; box-shadow:none; border-radius:0; }
  table.lms-table-keep > tbody > tr > td{ display:table-cell!important; padding:10px 12px!important; border-bottom:1px solid var(--border)!important; }
  table.lms-table-keep > tbody > tr > td::before{ content:none!important; }
  .card:has(table.lms-table-keep) .card-body, .table-responsive:has(table.lms-table-keep){ overflow-x:auto; -webkit-overflow-scrolling:touch; }
}

/* Min-height so a one-row table doesn't leave a sliver mid-page (desktop). */
@media(min-width:641px){
  .card.lms-list-card,
  .card:has(> .card-body.p-0 > .dataTables_wrapper){ min-height:320px; }
}

@media(max-width:768px) and (min-width:641px){
  .table thead th{ padding:11px 13px; font-size:.68rem; }
  .table tbody td{ padding:11px 13px; font-size:.86rem; }
  /* Between the card breakpoint and desktop, let wide tables scroll. */
  .card > .card-body > .table:not(.dataTable),
  .card > .card-body.p-0 > .table:not(.dataTable){ display:block; overflow-x:auto; -webkit-overflow-scrolling:touch; }
}

/* ==========================================================================
   17. DATATABLES
   ========================================================================== */
.dataTables_wrapper{ padding:var(--sp-5) var(--sp-5) var(--sp-2); font-family:var(--font-sans); }
:root{ --dt-control-h:40px; }

.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_length label{
  display:inline-flex; align-items:center; gap:var(--sp-2);
  margin:0; font-size:.88rem; font-weight:600; color:var(--text-muted);
}
.dataTables_wrapper .dataTables_length select{
  border:1.5px solid var(--border);
  border-radius:12px;
  padding:0 36px 0 14px;
  height:var(--dt-control-h);
  font-size:.92rem; font-weight:700;
  color:var(--text); background-color:var(--surface);
  appearance:none; -webkit-appearance:none;
  background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 16 16" fill="%23556377"><path d="M4 6l4 4 4-4z"/></svg>');
  background-repeat:no-repeat; background-position:right 12px center; background-size:12px;
  cursor:pointer;
  transition:border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
[data-bs-theme="dark"] .dataTables_wrapper .dataTables_length select{
  background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 16 16" fill="%239FB0C4"><path d="M4 6l4 4 4-4z"/></svg>');
}
.dataTables_wrapper .dataTables_length select:hover{ border-color:var(--border-strong); }
.dataTables_wrapper .dataTables_length select:focus{ outline:none; border-color:var(--primary); box-shadow:var(--focus-ring); }

.dataTables_wrapper .dataTables_filter{ text-align:right; }
.dataTables_wrapper .dataTables_filter label{ display:inline-flex; align-items:center; gap:var(--sp-2); font-size:0; }
.dataTables_wrapper .dataTables_filter input{
  border:1.5px solid var(--border);
  border-radius:12px;
  padding:0 var(--sp-4) 0 42px;
  height:var(--dt-control-h);
  font-size:.92rem; font-weight:500;
  color:var(--text); background-color:var(--surface);
  background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="%23556377" stroke-width="2" stroke-linecap="round"><circle cx="7" cy="7" r="5"/><path d="M11 11l3 3"/></svg>');
  background-repeat:no-repeat; background-position:14px center; background-size:16px;
  min-width:250px; max-width:100%; margin:0;
  transition:border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
[data-bs-theme="dark"] .dataTables_wrapper .dataTables_filter input{
  background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="%239FB0C4" stroke-width="2" stroke-linecap="round"><circle cx="7" cy="7" r="5"/><path d="M11 11l3 3"/></svg>');
}
.dataTables_wrapper .dataTables_filter input::placeholder{ color:var(--text-subtle); }
.dataTables_wrapper .dataTables_filter input:hover{ border-color:var(--border-strong); }
.dataTables_wrapper .dataTables_filter input:focus{ outline:none; border-color:var(--primary); box-shadow:var(--focus-ring); }

.dataTables_wrapper .dataTables_info{
  font-size:.86rem; font-weight:600; color:var(--text-muted);
  padding-top:var(--sp-4)!important;
}
.dataTables_wrapper .dataTables_paginate{
  padding-top:var(--sp-3)!important;
  display:flex; align-items:center; justify-content:flex-end;
  gap:var(--sp-1); flex-wrap:wrap;
}
.dataTables_wrapper .dataTables_paginate .paginate_button{
  border:none!important; background:transparent!important;
  border-radius:var(--radius-sm)!important;
  margin:0!important; padding:0 10px!important;
  min-width:36px; height:36px;
  font-size:.88rem; font-weight:700;
  color:var(--text-muted)!important;
  display:inline-flex; align-items:center; justify-content:center;
  transition:background var(--dur) var(--ease), color var(--dur) var(--ease);
  cursor:pointer;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.previous,
.dataTables_wrapper .dataTables_paginate .paginate_button.next{
  font-size:1.35rem; line-height:1; width:36px; min-width:36px;
  color:var(--text)!important; font-weight:400;
}
.dataTables_wrapper .dataTables_paginate .paginate_button:hover{
  background:var(--primary-light)!important; color:var(--on-primary-light)!important;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.current,
.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{
  background:var(--primary)!important;
  color:var(--text-invert)!important;
  box-shadow:0 4px 12px rgba(30,58,138,.26);
}
[data-bs-theme="dark"] .dataTables_wrapper .dataTables_paginate .paginate_button.current,
[data-bs-theme="dark"] .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{
  background:#1D4ED8!important; color:#fff!important;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.disabled,
.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover{
  opacity:.35; cursor:not-allowed;
  background:transparent!important; color:var(--text-muted)!important; box-shadow:none;
}
.dataTables_wrapper .dataTables_paginate .ellipsis{ color:var(--text-muted); padding:0 var(--sp-1); }

table.dataTable thead .sorting,
table.dataTable thead .sorting_asc,
table.dataTable thead .sorting_desc{ cursor:pointer; position:relative; }
table.dataTable thead .sorting:after,
table.dataTable thead .sorting_asc:after,
table.dataTable thead .sorting_desc:after{
  opacity:.45; right:8px; bottom:50%; transform:translateY(50%); font-size:.75rem;
}
table.dataTable thead .sorting_asc:after,
table.dataTable thead .sorting_desc:after{ opacity:.9; color:var(--primary); }

.card > .card-body.p-0 > .dataTables_wrapper{ padding-top:var(--sp-5); }
.card > .card-body.p-0 > .table:not(.dataTable){ margin:0; }

@media(max-width:768px){
  .dataTables_wrapper{ padding:var(--sp-3)!important; }
  .dataTables_wrapper .dataTables_length,
  .dataTables_wrapper .dataTables_length label{ width:100%; }
  .dataTables_wrapper .dataTables_length select{ flex:1; }
  .dataTables_wrapper .dataTables_filter{ text-align:left; margin-top:var(--sp-2); width:100%; }
  .dataTables_wrapper .dataTables_filter label{ width:100%; }
  .dataTables_wrapper .dataTables_filter input{ width:100%; min-width:0; }
  .dataTables_wrapper .row > div.text-end{ text-align:left!important; }
  .dataTables_wrapper .dataTables_paginate{ justify-content:center; padding-top:var(--sp-2)!important; }
  .dataTables_wrapper .dataTables_paginate .paginate_button{ height:var(--tap-min); min-width:var(--tap-min); }
  .dataTables_wrapper .dataTables_info{ font-size:.8rem; padding-top:var(--sp-2)!important; text-align:center; }
}

/* ==========================================================================
   18. BADGES & STATUS
   --------------------------------------------------------------------------
   Solid badges use the -solid ramp (white text ≥ 4.5:1). Soft badges are
   tokenised so dark mode gets a tinted ground and a bright glyph instead
   of a pastel rectangle floating on a dark card.
   ========================================================================== */
.badge{
  font-weight:700; padding:6px 11px; border-radius:var(--radius-pill);
  font-size:.72rem; letter-spacing:.015em;
  font-family:var(--font-display);
  display:inline-flex; align-items:center; gap:5px;
  line-height:1.35;
}
.badge.bg-primary{ background:var(--primary)!important;       color:var(--text-invert)!important; }
.badge.bg-success{ background:var(--accent-solid)!important;  color:#fff!important; }
.badge.bg-warning{ background:var(--warning-solid)!important; color:#fff!important; }
.badge.bg-danger { background:var(--danger-solid)!important;  color:#fff!important; }
.badge.bg-info   { background:var(--info-solid)!important;    color:#fff!important; }
.badge.bg-secondary{ background:#475569!important;            color:#fff!important; }
/* Bootstrap's .text-dark on a warning badge was unreadable on the old
   bright amber; on the solid amber white is correct, so override it. */
.badge.bg-warning.text-dark{ color:#fff!important; font-size:.72rem; font-weight:700; padding:5px 10px; }
[data-bs-theme="dark"] .badge.bg-primary{ background:#1D4ED8!important; color:#fff!important; }

.badge-level,
.badge-soft-primary{
  background:var(--primary-light); color:var(--on-primary-light);
  border-radius:var(--radius-pill); padding:5px 12px;
  font-size:.72rem; font-weight:700; font-family:var(--font-display);
  letter-spacing:0; white-space:nowrap; display:inline-block;
}
.badge-soft-success{ background:var(--accent-light);  color:var(--on-accent-light);  padding:5px 12px; border-radius:var(--radius-pill); font-size:.72rem; font-weight:700; font-family:var(--font-display); display:inline-block; }
.badge-soft-warning{ background:var(--warning-light); color:var(--on-warning-light); padding:5px 12px; border-radius:var(--radius-pill); font-size:.72rem; font-weight:700; font-family:var(--font-display); display:inline-block; }
.badge-soft-danger { background:var(--danger-light);  color:var(--on-danger-light);  padding:5px 12px; border-radius:var(--radius-pill); font-size:.72rem; font-weight:700; font-family:var(--font-display); display:inline-block; }
.badge-soft-info   { background:var(--info-light);    color:var(--on-info-light);    padding:5px 12px; border-radius:var(--radius-pill); font-size:.72rem; font-weight:700; font-family:var(--font-display); display:inline-block; }

/* ==========================================================================
   19. ALERTS
   ========================================================================== */
.alert{
  border:1px solid transparent;
  border-radius:12px;
  padding:var(--sp-3) var(--sp-4);
  font-size:.92rem; font-weight:500;
  display:flex; align-items:flex-start; gap:var(--sp-3);
}
.alert > i.bi:first-child,
.alert > [data-lucide]:first-child{ flex-shrink:0; font-size:18px; margin-top:2px; }
.alert-warning{ background:var(--warning-light); color:var(--on-warning-light); border-color:color-mix(in srgb, var(--warning-solid) 28%, transparent); }
.alert-danger { background:var(--danger-light);  color:var(--on-danger-light);  border-color:color-mix(in srgb, var(--danger-solid) 28%, transparent); }
.alert-success{ background:var(--accent-light);  color:var(--on-accent-light);  border-color:color-mix(in srgb, var(--accent-solid) 28%, transparent); }
.alert-info   { background:var(--info-light);    color:var(--on-info-light);    border-color:color-mix(in srgb, var(--info-solid) 28%, transparent); }
.alert .btn-close{ margin-left:auto; }
[data-bs-theme="dark"] .alert .btn-close{ filter:invert(1) grayscale(1) brightness(1.8); }

/* Flash toasts */
#flash{
  position:fixed; top:calc(var(--tb-height) + 14px); right:16px;
  z-index:var(--z-flash); min-width:280px; max-width:min(420px, calc(100vw - 32px));
}
#flash .alert{ box-shadow:var(--shadow-lg); animation:slideIn var(--dur-slow) var(--ease); }
@media(max-width:576px){
  #flash{
    top:auto!important; bottom:calc(12px + env(safe-area-inset-bottom));
    right:12px; left:12px; min-width:0; max-width:none;
  }
  #flash .alert{ animation:slideUp var(--dur-slow) var(--ease); }
}

/* ==========================================================================
   20. TABS
   ========================================================================== */
.nav-tabs{ border-bottom:1px solid var(--border); gap:var(--sp-1); }
.nav-tabs .nav-link{
  color:var(--text-muted);
  border:none; border-bottom:2px solid transparent;
  border-radius:var(--radius-xs) var(--radius-xs) 0 0;
  padding:10px 16px; font-weight:600; font-size:.88rem;
  transition:color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.nav-tabs .nav-link:hover{ color:var(--primary); background:var(--primary-tint); }
.nav-tabs .nav-link.active{ color:var(--primary); background:transparent; border-bottom-color:var(--primary); }
.nav-pills .nav-link{ color:var(--text-muted); font-weight:600; border-radius:var(--radius-sm); }
.nav-pills .nav-link.active{ background:var(--primary); color:var(--text-invert); }
[data-bs-theme="dark"] .nav-pills .nav-link.active{ background:#1D4ED8; color:#fff; }

@media(max-width:768px){
  .nav-tabs,.nav-pills{
    flex-wrap:nowrap; overflow-x:auto; overflow-y:hidden;
    -webkit-overflow-scrolling:touch;
    scrollbar-width:none;
    /* Fade the right edge so it's obvious there's more to scroll to. */
    -webkit-mask-image:linear-gradient(90deg,#000 88%,transparent 100%);
    mask-image:linear-gradient(90deg,#000 88%,transparent 100%);
  }
  .nav-tabs::-webkit-scrollbar,.nav-pills::-webkit-scrollbar{ height:0; }
  .nav-tabs .nav-link,.nav-pills .nav-link{ white-space:nowrap; padding:9px 13px; font-size:.84rem; min-height:var(--tap-min); display:inline-flex; align-items:center; }
}

/* ==========================================================================
   21. MODALS
   ========================================================================== */
.modal{ position:fixed!important; z-index:var(--z-modal); }
.modal-content{
  border:none; border-radius:var(--radius-lg); overflow:hidden;
  box-shadow:var(--shadow-lg);
  background:var(--surface); color:var(--text);
}
.modal-header{
  background:var(--surface); color:var(--text);
  border-bottom:1px solid var(--border);
  padding:var(--sp-4) var(--sp-5);
}
.modal-title{ font-weight:700; color:inherit; font-size:1.05rem; }
.modal-body{ padding:var(--sp-5); }
.modal-footer{ border-top:1px solid var(--border); padding:var(--sp-3) var(--sp-5); gap:var(--sp-2); background:var(--surface); }

/* Coloured modal headers are set inline in the markup with a handful of
   different hexes. Normalise them all to the brand navy so every dialog
   reads the same, and force a legible close button on top. */
.modal-header[style*="background"]{ background:var(--primary)!important; color:#fff!important; }
[data-bs-theme="dark"] .modal-header[style*="background"]{ background:#1D4ED8!important; }
.modal-header[style*="background"] .modal-title{ color:#fff!important; }
.modal-header[style*="background"] .btn-close{ filter:invert(1) brightness(2.2); opacity:.9; }
[data-bs-theme="dark"] .modal-content .btn-close{ filter:invert(1) grayscale(1) brightness(1.8); }

/* Phones: full-screen sheet with a pinned header and footer, so the
   primary action is always reachable without scrolling to the bottom of
   a long form. 100dvh, not 100vh — iOS Safari's toolbar makes 100vh
   overshoot and hides the footer under the chrome. */
@media(max-width:576px){
  .modal-dialog,
  .modal-dialog.modal-lg,
  .modal-dialog.modal-xl{
    margin:0!important; max-width:100%!important; width:100%;
    min-height:100dvh;
  }
  .modal-content{ min-height:100dvh; border-radius:0; }
  .modal-header{
    padding:var(--sp-4); position:sticky; top:0; z-index:2;
    padding-top:max(var(--sp-4), env(safe-area-inset-top));
  }
  .modal-body{ padding:var(--sp-4); }
  .modal-footer{
    padding:var(--sp-3) var(--sp-4);
    padding-bottom:max(var(--sp-3), env(safe-area-inset-bottom));
    position:sticky; bottom:0; z-index:2;
    flex-direction:column-reverse;
  }
  .modal-footer > .btn{ width:100%; margin:0; min-height:var(--tap-min); }
}

/* ==========================================================================
   22. AVATARS
   ========================================================================== */
.avatar{
  width:38px; height:38px; border-radius:50%;
  background:linear-gradient(135deg,var(--primary-mid) 0%,#15803D 100%);
  color:#fff;
  display:inline-flex; align-items:center; justify-content:center;
  font-weight:800; font-size:.88rem;
  font-family:var(--font-display); letter-spacing:-0.02em;
  box-shadow:0 2px 4px rgba(15,23,42,.12), inset 0 1px 0 rgba(255,255,255,.18);
  flex-shrink:0; overflow:hidden;
}
.avatar-sm{ width:30px; height:30px; font-size:.74rem; }
.avatar-lg{ width:52px; height:52px; font-size:1.05rem; }

/* Colour variety down a list. Every gradient's LIGHT stop clears 4.5:1
   against white — v2 included an orange (#E65100) that measured 3.79. */
.table tbody tr:nth-child(5n+1) .avatar:not(.avatar-sm):not(.avatar-lg){ background:linear-gradient(135deg,#2563EB 0%,#1E3A8A 100%); }
.table tbody tr:nth-child(5n+2) .avatar:not(.avatar-sm):not(.avatar-lg){ background:linear-gradient(135deg,#15803D 0%,#14532D 100%); }
.table tbody tr:nth-child(5n+3) .avatar:not(.avatar-sm):not(.avatar-lg){ background:linear-gradient(135deg,#B45309 0%,#92400E 100%); }
.table tbody tr:nth-child(5n+4) .avatar:not(.avatar-sm):not(.avatar-lg){ background:linear-gradient(135deg,#7C3AED 0%,#5B21B6 100%); }
.table tbody tr:nth-child(5n+5) .avatar:not(.avatar-sm):not(.avatar-lg){ background:linear-gradient(135deg,#BE185D 0%,#9D174D 100%); }

/* ==========================================================================
   23. LISTS, PROGRESS, MISC COMPONENTS
   ========================================================================== */
.task-dash-row:hover{ background:var(--primary-tint); border-radius:var(--radius-xs); }
.quiz-timer{ font-size:clamp(1.3rem,2vw+1rem,1.7rem); font-weight:800; color:var(--danger); font-variant-numeric:tabular-nums; }

.lesson-item{
  background:var(--surface-2);
  border:1px solid var(--border);
  border-radius:12px;
  padding:var(--sp-3) var(--sp-4);
  transition:background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.lesson-item:hover{ background:var(--primary-tint); border-color:var(--primary-light); }

.progress-bar-custom{ height:8px; border-radius:var(--radius-pill); background:var(--surface-3); overflow:hidden; }
.progress-bar-custom .fill{ height:100%; background:linear-gradient(90deg,var(--primary-mid) 0%,var(--accent-fill) 100%); border-radius:var(--radius-pill); transition:width .4s var(--ease); }
.progress{ background:var(--surface-3); border-radius:var(--radius-pill); height:8px; }
.progress-bar{ background:linear-gradient(90deg,var(--primary-mid) 0%,var(--accent-fill) 100%); }

.list-group-item{ background:var(--surface); color:var(--text); border-color:var(--border); }
.dropdown-menu{ background:var(--surface); border-color:var(--border); border-radius:var(--radius); box-shadow:var(--shadow-lg); padding:var(--sp-1); }
.dropdown-item{ color:var(--text); border-radius:var(--radius-xs); padding:9px 12px; font-size:.9rem; }
.dropdown-item:hover,.dropdown-item:focus{ background:var(--primary-tint); color:var(--on-primary-light); }
.dropdown-divider{ border-color:var(--border); }
@media (pointer: coarse){ .dropdown-item{ min-height:var(--tap-min); display:flex; align-items:center; } }

hr{ border-color:var(--border); opacity:1; }

/* Footer intentionally hidden per standing preference. */
.institute-footer{ display:none!important; }

/* ==========================================================================
   24. SUBJECT / COURSE PICKER CARDS
   ========================================================================== */
.subject-card{ display:block; margin:0; cursor:pointer; -webkit-tap-highlight-color:transparent; }
.subject-card-input{ position:absolute; opacity:0; pointer-events:none; width:0; height:0; }
.subject-card-inner{
  display:flex; align-items:center; gap:var(--sp-3);
  padding:var(--sp-3) var(--sp-4);
  background:var(--surface);
  border:2px solid var(--border);
  border-radius:var(--radius);
  transition:border-color var(--dur) var(--ease), background var(--dur) var(--ease),
             box-shadow var(--dur) var(--ease), transform var(--dur-fast) var(--ease);
  position:relative; min-height:68px;
}
/* v2 hardcoded #F8FAFF here — a near-white panel that in dark mode sat
   behind light text and made the row unreadable. */
.subject-card:hover .subject-card-inner{
  border-color:var(--primary-light);
  background:var(--surface-2);
  transform:translateY(-1px);
}
.subject-card-input:focus-visible + .subject-card-inner{ box-shadow:var(--focus-ring); }
.subject-card-input:checked + .subject-card-inner{
  border-color:var(--primary);
  background:var(--primary-tint);
  box-shadow:0 4px 16px rgba(30,58,138,.10);
}
.subject-card-check{
  width:24px; height:24px;
  border:2px solid var(--border-strong);
  background:var(--surface);
  border-radius:var(--radius-xs);
  display:inline-flex; align-items:center; justify-content:center;
  flex-shrink:0;
  transition:border-color var(--dur) var(--ease), background var(--dur) var(--ease), transform var(--dur-fast) var(--ease);
}
.subject-card-check::after{
  content:""; width:11px; height:6px;
  border-left:2px solid #fff; border-bottom:2px solid #fff;
  transform:rotate(-45deg) translate(1px,-1px);
  opacity:0; transition:opacity var(--dur-fast) var(--ease);
}
.subject-card:hover .subject-card-check{ border-color:var(--primary); }
.subject-card-input:checked + .subject-card-inner .subject-card-check{
  background:var(--primary); border-color:var(--primary);
  box-shadow:0 2px 6px rgba(30,58,138,.30); transform:scale(1.04);
}
[data-bs-theme="dark"] .subject-card-input:checked + .subject-card-inner .subject-card-check{ background:#1D4ED8; border-color:#1D4ED8; }
.subject-card-input:checked + .subject-card-inner .subject-card-check::after{ opacity:1; }
.subject-card-body{ flex:1; min-width:0; }
.subject-card-title{
  font-weight:700; font-size:.95rem; color:var(--text);
  letter-spacing:-0.01em; font-family:var(--font-display);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.subject-card-input:checked + .subject-card-inner .subject-card-title{ color:var(--on-primary-light); }
.subject-card-meta{
  margin-top:3px; display:flex; gap:var(--sp-2); flex-wrap:wrap;
  font-size:.78rem; color:var(--text-muted); font-weight:500;
}
/* v2 left this on --text-muted, which on the checked card's pale blue
   ground measured under 2:1. */
.subject-card-input:checked + .subject-card-inner .subject-card-meta{ color:var(--on-primary-light); opacity:.85; }
.subject-card-meta .badge{ background:var(--primary-light); color:var(--on-primary-light); font-weight:600; font-size:.68rem; padding:3px 8px; }
.subject-card-meta .bi{ font-size:11px; margin-right:3px; }
@media (pointer: coarse){ .subject-card-inner{ min-height:var(--tap-min); } }

/* ==========================================================================
   25. LOGIN
   ========================================================================== */
.login-shell{
  min-height:100dvh; display:flex;
  background:linear-gradient(135deg,var(--bg) 0%,var(--primary-light) 100%);
}
[data-bs-theme="dark"] .login-shell{ background:linear-gradient(135deg,#0B1220 0%,#0E2658 100%); }
.login-left{
  background:linear-gradient(160deg,var(--sb-bg) 0%,#1E3A8A 100%);
  color:#fff;
  padding:clamp(28px,4vw,48px) clamp(22px,3.5vw,44px);
  display:flex; flex-direction:column; justify-content:center;
  position:relative; overflow:hidden;
}
.login-left::before{
  content:""; position:absolute; right:-100px; top:-100px;
  width:340px; height:340px; border-radius:50%;
  background:radial-gradient(circle,rgba(34,197,94,.25) 0%,transparent 70%);
}
.login-left::after{
  content:""; position:absolute; left:-80px; bottom:-80px;
  width:280px; height:280px; border-radius:50%;
  background:radial-gradient(circle,rgba(14,165,233,.20) 0%,transparent 70%);
}
.login-left > *{ position:relative; z-index:1; }
.login-social a{
  display:inline-flex; align-items:center; justify-content:center;
  width:40px; height:40px; border-radius:50%;
  background:rgba(255,255,255,.14); color:#fff; font-size:1rem;
  transition:background var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.login-social a:hover{ background:var(--accent-solid); color:#fff; transform:translateY(-2px); }
@media(max-width:768px){
  .login-shell{ min-height:100dvh; flex-direction:column; }
  .login-left{ padding:28px 22px; }
}

/* ==========================================================================
   26. LOADING STATES
   ========================================================================== */
@keyframes lms-shimmer{ 0%{ background-position:-320px 0; } 100%{ background-position:320px 0; } }

body.lms-loading .dataTables_empty,
.lms-skeleton,
.lms-skeleton-line{
  display:block; height:12px; border-radius:6px;
  background:linear-gradient(90deg,var(--skeleton-a) 0%,var(--skeleton-b) 40%,var(--skeleton-a) 80%);
  background-size:640px 100%;
  animation:lms-shimmer 1.2s linear infinite;
  color:transparent!important;
}
body.lms-loading .dataTables_empty{ margin:var(--sp-3) var(--sp-4); min-height:24px; }
.lms-skeleton-line{ height:14px; margin:var(--sp-2) 0; }
.lms-skeleton-line.w-40{ width:40%; }
.lms-skeleton-line.w-60{ width:60%; }
.lms-skeleton-line.w-80{ width:80%; }

.spinner-border{ border-width:.18em; }

/* Banner shown when a section fails to load (see _showLoadError in the JS). */
#lms-load-error{
  border:1px solid color-mix(in srgb, var(--warning-solid) 30%, transparent);
  background:var(--warning-light);
  color:var(--on-warning-light);
  font-weight:600;
  padding:10px var(--sp-4);
  margin-bottom:var(--sp-3);
}

/* ==========================================================================
   27. MOTION
   ========================================================================== */
@keyframes slideIn { from{ transform:translateX(120%); opacity:0; } to{ transform:translateX(0); opacity:1; } }
@keyframes slideUp { from{ transform:translateY(120%); opacity:0; } to{ transform:translateY(0); opacity:1; } }
@keyframes fadeUp  { from{ opacity:0; transform:translateY(10px); } to{ opacity:1; transform:translateY(0); } }
@keyframes fadeIn  { from{ opacity:0; } to{ opacity:1; } }
@keyframes slideRight{ from{ opacity:0; transform:translateX(-10px); } to{ opacity:1; transform:translateX(0); } }
@keyframes spin    { from{ transform:rotate(0); } to{ transform:rotate(360deg); } }
.spin{ display:inline-block; animation:spin 1s linear infinite; }

/* Entry animations run ONLY on a real navigation paint — body carries
   .lms-fresh-render then. Background auto-refresh repaints must not
   re-animate, or the page appears to twitch every few seconds. */
body.lms-fresh-render .main-content > *:not(.modal):not(.modal-backdrop){
  animation:fadeUp .26s var(--ease);
}
body.lms-fresh-render .kpi{ animation:fadeUp .32s var(--ease) both; }
body.lms-fresh-render .row > [class*="col-"]:nth-child(1) .kpi{ animation-delay:.02s; }
body.lms-fresh-render .row > [class*="col-"]:nth-child(2) .kpi{ animation-delay:.07s; }
body.lms-fresh-render .row > [class*="col-"]:nth-child(3) .kpi{ animation-delay:.12s; }
body.lms-fresh-render .row > [class*="col-"]:nth-child(4) .kpi{ animation-delay:.17s; }
body.lms-fresh-render .row > [class*="col-"]:nth-child(5) .kpi{ animation-delay:.22s; }
body.lms-fresh-render .row > [class*="col-"]:nth-child(6) .kpi{ animation-delay:.27s; }

.sidebar nav .nav-item{ opacity:0; animation:slideRight .32s var(--ease) forwards; }
.sidebar nav .nav-item:nth-child(1){ animation-delay:.02s; }
.sidebar nav .nav-item:nth-child(2){ animation-delay:.05s; }
.sidebar nav .nav-item:nth-child(3){ animation-delay:.08s; }
.sidebar nav .nav-item:nth-child(4){ animation-delay:.11s; }
.sidebar nav .nav-item:nth-child(5){ animation-delay:.14s; }
.sidebar nav .nav-item:nth-child(6){ animation-delay:.17s; }
.sidebar nav .nav-item:nth-child(7){ animation-delay:.20s; }

.tab-pane{ animation:fadeUp .22s var(--ease); }

/* Bootstrap handles modal transitions itself; a transform on an ancestor
   breaks position:fixed, so keep our animations off them entirely. */
.modal,.modal-dialog,.modal-content,.modal-backdrop{ animation:none!important; }

/* If motion is reduced, nothing should start invisible and stay that way. */
@media (prefers-reduced-motion: reduce){
  .sidebar nav .nav-item,
  body.lms-fresh-render .kpi,
  body.lms-fresh-render .main-content > *{ opacity:1!important; animation:none!important; }
}

/* ==========================================================================
   28. SCROLLBARS
   ========================================================================== */
::-webkit-scrollbar{ width:10px; height:10px; }
::-webkit-scrollbar-track{ background:transparent; }
::-webkit-scrollbar-thumb{ background:rgba(100,116,139,.32); border-radius:6px; border:2px solid transparent; background-clip:padding-box; }
::-webkit-scrollbar-thumb:hover{ background:rgba(100,116,139,.50); background-clip:padding-box; }
[data-bs-theme="dark"] ::-webkit-scrollbar-thumb{ background:rgba(148,163,184,.30); background-clip:padding-box; }
[data-bs-theme="dark"] ::-webkit-scrollbar-thumb:hover{ background:rgba(148,163,184,.46); background-clip:padding-box; }
*{ scrollbar-width:thin; scrollbar-color:rgba(100,116,139,.35) transparent; }

/* ==========================================================================
   29. TOUCH SIZING
   Keyed to the pointer, not the viewport: a 700px-wide desktop window
   keeps compact controls, a 1024px tablet gets thumb-sized ones.
   ========================================================================== */
@media (pointer: coarse){
  .btn{ min-height:var(--tap-min); padding:11px 18px; }
  .btn-sm{ min-height:38px; padding:8px 14px; }
  .btn-icon,
  .topbar .tb-btn{ width:var(--tap-min); height:var(--tap-min); min-width:var(--tap-min); }
  .table tbody td > .btn-outline-info,
  .table tbody td > .btn-outline-primary,
  .table tbody td > .btn-outline-success,
  .table tbody td > .btn-outline-warning,
  .table tbody td > .btn-outline-danger,
  .table tbody td > .btn-outline-secondary{
    width:var(--tap-min); height:var(--tap-min); min-width:var(--tap-min);
  }
  .sidebar .nav-link{ min-height:var(--tap-min); }
  .nav-tabs .nav-link,.nav-pills .nav-link{ min-height:var(--tap-min); }
  /* Hover lifts are meaningless on touch and read as a flicker. */
  .card:hover,.kpi:hover,.btn:hover,.table tbody td > .btn:hover{ transform:none!important; }
}

/* Icon-only action buttons on phones: drop the text label but keep an
   accessible name via title/aria-label in the markup. */
@media(max-width:768px){
  .table tbody td > .btn > span:not(.bi):not(.badge),
  .table tbody td > .btn > .ms-1{
    position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap;
  }
}

/* ==========================================================================
   30. LAYOUT UTILITIES
   ========================================================================== */
.row.g-3 > [class*="col"]{ padding-top:.5rem; padding-bottom:.5rem; }
@media(min-width:1200px){ .row.g-3{ --bs-gutter-x:1rem; } }

/* Equal-height cards when they sit side by side in a row. */
.row > [class*="col-"] > .card{ height:100%; }

/* Stop flex/grid children overflowing their track — the single most
   common cause of a stray horizontal scrollbar. */
.row > [class*="col-"],
.d-flex > *{ min-width:0; }

@media(max-width:576px){
  .row.g-2 > [class*="col-"]{ margin-bottom:var(--sp-1); }
  .input-group{ flex-wrap:nowrap; }
  .form-label{ font-size:.85rem; margin-bottom:6px; }
  /* Button clusters go full-width rather than wrapping one orphan. */
  .d-flex.gap-2 > .btn,
  .d-flex.gap-1 > .btn{ flex:1 1 auto; }
}

@media(max-width:640px){
  .course-card,.schedule-row,.lesson-row{ flex-direction:column!important; align-items:stretch!important; }
  .schedule-row .btn,.lesson-row .btn{ width:100%; }
}

/* Charts must never dictate page height on a phone. */
canvas{ max-width:100%!important; }
@media(max-width:768px){ canvas{ max-height:260px!important; } }

/* ==========================================================================
   31. INLINE-STYLE SAFETY NETS
   --------------------------------------------------------------------------
   Parts of the markup set colours and borders with inline `style=`
   attributes, which no stylesheet can reach without matching the
   attribute itself. Two things need catching.
   ========================================================================== */

/* (a) NO COLOURED STRIP DOWN THE LEFT OF A CARD.
   This is a standing preference (see the header of this file), but the
   markup sets `border-left:4px solid <colour>` inline in a dozen places —
   summary cards, the daily-report panels, the 1-to-1 session callouts.
   Rather than edit each one, neutralise the pattern here. The border
   stays, at hairline width in the neutral border colour, so spacing and
   alignment are unchanged. */
[style*="border-left:4px"],[style*="border-left: 4px"],
[style*="border-left:5px"],[style*="border-left: 5px"],
[style*="border-left:3px"],[style*="border-left: 3px"]{
  border-left-width:1px!important;
  border-left-color:var(--border)!important;
}

/* (b) HARDCODED PASTEL PANELS IN DARK MODE.
   A handful of inline backgrounds are pale Material tints
   (#E8F5E9, #FFF8E1, #E3F2FD, #FCE4EC, #F0F4FA, #E0F7FA, #F8F9FA…)
   chosen for light mode. In dark mode they render as bright white-ish
   slabs, and any inherited light text on them disappears. Map them to
   the themed surface instead. Light mode is untouched. */
[data-bs-theme="dark"] [style*="background:#e3f2fd"],
[data-bs-theme="dark"] [style*="background:#E3F2FD"],
[data-bs-theme="dark"] [style*="background:#e8f5e9"],
[data-bs-theme="dark"] [style*="background:#E8F5E9"],
[data-bs-theme="dark"] [style*="background:#fff8e1"],
[data-bs-theme="dark"] [style*="background:#FFF8E1"],
[data-bs-theme="dark"] [style*="background:#fce4ec"],
[data-bs-theme="dark"] [style*="background:#FCE4EC"],
[data-bs-theme="dark"] [style*="background:#e0f7fa"],
[data-bs-theme="dark"] [style*="background:#E0F7FA"],
[data-bs-theme="dark"] [style*="background:#f0f4fa"],
[data-bs-theme="dark"] [style*="background:#F0F4FA"],
[data-bs-theme="dark"] [style*="background:#eef6ff"],
[data-bs-theme="dark"] [style*="background:#EEF6FF"],
[data-bs-theme="dark"] [style*="background:#f8f9fa"],
[data-bs-theme="dark"] [style*="background:#F8F9FA"],
[data-bs-theme="dark"] [style*="background:#fffbeb"],
[data-bs-theme="dark"] [style*="background:#FFFBEB"],
[data-bs-theme="dark"] [style*="background:#ede7f6"],
[data-bs-theme="dark"] [style*="background:#EDE7F6"]{
  background:var(--surface-2)!important;
  color:var(--text)!important;
  border-color:var(--border)!important;
}

/* The attendance register's Present / Absent / Late cells are inline
   pastel-on-dark-text pairs. They read fine in light mode; in dark mode
   the pale ground has to go, but the SIGNAL must survive — so each keeps
   its own tint rather than collapsing to a neutral surface. */
[data-bs-theme="dark"] [style*="background:#d4edda"],
[data-bs-theme="dark"] [style*="background:#D4EDDA"]{ background:var(--accent-light)!important;  color:var(--on-accent-light)!important; }
[data-bs-theme="dark"] [style*="background:#f8d7da"],
[data-bs-theme="dark"] [style*="background:#F8D7DA"]{ background:var(--danger-light)!important;  color:var(--on-danger-light)!important; }
[data-bs-theme="dark"] [style*="background:#fff3cd"],
[data-bs-theme="dark"] [style*="background:#FFF3CD"]{ background:var(--warning-light)!important; color:var(--on-warning-light)!important; }

/* (c) Inline avatar spans. `avatar()` in the JS builds its own circle
   with an inline background rather than using the .avatar class, so the
   design-system sizing never reached it. Bring it into line. */
span.rounded-circle[style*="width:36px"]{
  font-family:var(--font-display);
  font-weight:800;
  letter-spacing:-0.02em;
  box-shadow:0 2px 4px rgba(15,23,42,.12), inset 0 1px 0 rgba(255,255,255,.18);
}

/* ==========================================================================
   32. PRINT
   ========================================================================== */
@media print{
  .sidebar,.topbar,.sidebar-toggle,.sidebar-backdrop,
  button,.btn,#flash,#lms-load-error,.institute-footer,.no-print{ display:none!important; }
  html,body{ background:#fff!important; color:#000!important; font-size:11pt; height:auto!important; overflow:visible!important; }
  .app-shell{ display:block!important; height:auto!important; overflow:visible!important; }
  .main-content{ padding:0!important; background:#fff!important; height:auto!important; overflow:visible!important; }
  .card{ box-shadow:none!important; border:1px solid #ccc!important; break-inside:avoid; }
  .kpi{ box-shadow:none!important; border:1px solid #ccc!important; break-inside:avoid; }
  .page-title{ color:#000!important; border-bottom:2px solid #000; padding-bottom:6px; margin-bottom:14px; }
  .page-title > i.bi{ display:none!important; }
  .table{ font-size:9.5pt; }
  .table thead th{ background:#f3f3f3!important; color:#000!important; -webkit-print-color-adjust:exact; print-color-adjust:exact; }
  .table thead{ display:table-header-group; }      /* repeat headers across pages */
  .table tr{ break-inside:avoid; }
  .badge,[class*="badge-"]{ border:1px solid #888; color:#000!important; background:#fff!important; }
  a{ color:#000!important; text-decoration:none!important; }
  @page{ margin:14mm 12mm; }
}
