/* ═══════════════════════════════════════════════════════════════
   PDGT Hub · macOS Tahoe Design System
   Central tokens, shell, components — single source of truth
   ═══════════════════════════════════════════════════════════════ */

/* ── BREAKPOINTS ──
   One structural breakpoint governs the app shell:

     768px — below this the shell switches to the mobile layout: bottom tab
             bar, off-canvas sidebar drawer, full-bleed window. Anything that
             needs to change *because the layout changed* belongs here, and
             page-level stylesheets must use this same value so a page never
             ends up half-converted (see the note in tahoe-profile.css).

   Everything else is a component breakpoint, chosen from where that specific
   component runs out of room, and is deliberately NOT snapped to a shared
   scale. A four-card game grid, a six-card dashboard grid and a toolbar title
   stop fitting at genuinely different widths, e.g.:

     .ggrid      1100 / 680   (arcade: 4 → 2 → 1 columns)
     .dash-grid  1080 / 720   (home: 6 → 4 → 1 columns)
     .ach-grid    980 / 680   (profile achievements)
     .tb-title    500 / 380   (toolbar title truncation)
     .search-pill 580         (pill no longer fits beside the title)

   Rounding these onto a shared 480/768/1024 scale would collapse or stretch
   each grid at the wrong width, so prefer measuring the component over
   reusing a number from elsewhere. */

/* ── DESIGN TOKENS ── */
:root {
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Helvetica Neue", system-ui, sans-serif;
  --font-mono: "SF Mono", "JetBrains Mono", ui-monospace, monospace;

  /* Layout */
  --sb-w: 218px;
  --tb-h: 50px;
  --foot-h: 26px;
  --r-sm: 7px;
  --r-md: 10px;
  --r-lg: 14px;
  --r-xl: 18px;
  --r-full: 999px;

  /* Aurora wallpaper */
  --a1: #2a165f;
  --a2: #4f2a95;
  --a3: #1f4b8a;
  --a4: #0f6a7b;
  --a5: #0a0f25;
  --wall:
    radial-gradient(120% 80% at 12% 18%, rgba(95, 58, 180, 0.48) 0%, transparent 58%),
    radial-gradient(95% 70% at 85% 16%, rgba(52, 109, 190, 0.44) 0%, transparent 62%),
    radial-gradient(85% 70% at 78% 84%, rgba(24, 130, 150, 0.38) 0%, transparent 58%),
    radial-gradient(88% 68% at 20% 82%, rgba(38, 22, 88, 0.5) 0%, transparent 62%),
    linear-gradient(145deg, #130a31 0%, var(--a1) 26%, var(--a3) 54%, var(--a4) 78%, #0a1028 100%);

  /* Window / glass */
  --win-bg: rgba(247, 247, 250, 0.965);
  --win-bdr: rgba(0, 0, 0, 0.22);
  --win-shadow: 0 26px 70px rgba(0, 0, 0, 0.28), 0 6px 16px rgba(0, 0, 0, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.55);
  --glass-bg: rgba(255, 255, 255, 0.05);
  --glass-bg-solid: #16132a;
  --glass-bdr: rgba(255, 255, 255, 0.2);
  --glass-hi: rgba(255, 255, 255, 0.42);
  --glass-sh: 0 2px 36px rgba(0, 0, 0, 0.35), 0 6px 16px rgba(0, 0, 0, 0.24);

  /* Titlebar */
  --tb-bg: rgba(239, 239, 243, 0.98);
  --tb-bdr: rgba(0, 0, 0, 0.11);

  /* Sidebar */
  --sb-bg: rgba(224, 224, 230, 0.93);
  --sb-bdr: rgba(0, 0, 0, 0.1);
  --sb-hover: rgba(0, 0, 0, 0.05);
  --sb-active-bg: rgba(110, 93, 216, 0.11);
  --sb-active-c: #4e42a8;

  /* Main content area */
  --main-bg: rgba(252, 252, 254, 0.72);

  /* Cards & surfaces */
  --card: rgba(255, 255, 255, 0.965);
  --card-bdr: rgba(15, 23, 42, 0.08);
  --card-sh: 0 1px 2px rgba(15, 23, 42, 0.06), 0 3px 8px rgba(15, 23, 42, 0.04);
  --card-sh-h: 0 6px 18px rgba(15, 23, 42, 0.09), 0 12px 30px rgba(15, 23, 42, 0.06);
  --panel: rgba(255, 255, 255, 0.975);
  --panel2: rgba(246, 246, 250, 0.92);

  /* Typography */
  --t1: #18181b;
  --t2: #3f3f46;
  --t3: #71717a;
  --t4: #a1a1aa;

  /* Brand accents */
  --purple: #6e5dd8;
  --purple-d: #5040b5;
  --purple-l: rgba(110, 93, 216, 0.1);
  --amber: #c96a0a;
  --amber-d: #92400E;
  --amber-l: rgba(201, 106, 10, 0.1);
  --teal: #0D9488;
  --teal-l: rgba(13, 148, 136, 0.1);
  --blue: #2563EB;
  --blue-l: rgba(37, 99, 235, 0.1);
  --green: #16A34A;
  --green-l: rgba(22, 163, 74, 0.1);
  --rose: #E11D48;
  --rose-l: rgba(225, 29, 72, 0.1);
  --cyan: #0891B2;
  --cyan-l: rgba(8, 145, 178, 0.1);

  /* Forms */
  --field-bg: rgba(0, 0, 0, 0.05);
  --field-bdr: rgba(0, 0, 0, 0.12);
  --field-focus-bdr: rgba(108, 71, 208, 0.7);
  --field-focus-sh: 0 0 0 3px rgba(108, 71, 208, 0.18);

  /* Status */
  --error: #DC2626;
  --error-bg: rgba(220, 38, 38, 0.08);
  --error-bdr: rgba(220, 38, 38, 0.25);
  --success: #0D9488;
  --success-bg: rgba(13, 148, 136, 0.1);

  /* Traffic lights */
  --tl-r: #FF5F57;
  --tl-y: #FEBC2E;
  --tl-g: #28C840;

  /* Motion */
  --ease: cubic-bezier(0.2, 0, 0, 1);
  --spring: cubic-bezier(0.34, 1.4, 0.64, 1);
  --dur-fast: 0.12s;
  --dur: 0.25s;
  --dur-slow: 0.4s;
  --dur-route: 0.28s;
  --dur-press: 0.08s;
  --mobile-nav-h: 56px;

  /* Login window */
  --win-w: 420px;
  --win-r: 20px;
}

:root {
  color-scheme: light;
}

[data-theme="dark"] {
  color-scheme: dark;
  --a1: #241353;
  --a2: #4b268f;
  --a3: #19467f;
  --a4: #0b5c6c;
  --a5: #050410;
  --wall:
    radial-gradient(120% 78% at 14% 20%, rgba(82, 45, 170, 0.42) 0%, transparent 56%),
    radial-gradient(92% 68% at 86% 14%, rgba(39, 102, 178, 0.36) 0%, transparent 60%),
    radial-gradient(80% 66% at 76% 84%, rgba(19, 116, 130, 0.3) 0%, transparent 56%),
    radial-gradient(82% 64% at 18% 84%, rgba(28, 16, 66, 0.48) 0%, transparent 60%),
    linear-gradient(145deg, #0f0828 0%, var(--a1) 26%, var(--a3) 54%, var(--a4) 78%, #060a1c 100%);

  --win-bg: rgba(22, 22, 26, 0.985);
  --win-bdr: rgba(255, 255, 255, 0.1);
  --win-shadow: 0 26px 70px rgba(0, 0, 0, 0.55), 0 6px 16px rgba(0, 0, 0, 0.36), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  --glass-bg: rgba(255, 255, 255, 0.065);
  --glass-bg-solid: #16132a;
  --glass-bdr: rgba(255, 255, 255, 0.2);
  --glass-hi: rgba(255, 255, 255, 0.42);
  --glass-sh: 0 2px 36px rgba(0, 0, 0, 0.46), 0 6px 16px rgba(0, 0, 0, 0.3);

  --tb-bg: rgba(28, 28, 33, 0.995);
  --tb-bdr: rgba(255, 255, 255, 0.07);
  --sb-bg: rgba(36, 36, 41, 0.96);
  --sb-bdr: rgba(255, 255, 255, 0.07);
  --sb-hover: rgba(255, 255, 255, 0.05);
  --sb-active-bg: rgba(140, 120, 245, 0.14);
  --sb-active-c: #b0a0ff;
  --main-bg: rgba(10, 10, 12, 0.24);

  --card: rgba(36, 36, 41, 0.965);
  --card-bdr: rgba(255, 255, 255, 0.09);
  --card-sh: 0 1px 2px rgba(0, 0, 0, 0.34), 0 3px 8px rgba(0, 0, 0, 0.25);
  --card-sh-h: 0 6px 18px rgba(0, 0, 0, 0.4), 0 12px 30px rgba(0, 0, 0, 0.3);
  --panel: rgba(30, 30, 34, 0.985);
  --panel2: rgba(39, 39, 45, 0.95);

  --t1: rgba(255, 255, 255, 0.94);
  --t2: rgba(255, 255, 255, 0.69);
  --t3: rgba(255, 255, 255, 0.45);
  --t4: rgba(255, 255, 255, 0.24);

  --purple: #a292ff;
  --purple-d: #c0b2ff;
  --purple-l: rgba(162, 146, 255, 0.14);
  --amber: #F59E0B;
  --amber-l: rgba(245, 158, 11, 0.12);
  --teal: #34D399;
  --teal-l: rgba(52, 211, 153, 0.12);
  --blue: #60A5FA;
  --blue-l: rgba(96, 165, 250, 0.12);
  --green: #4ADE80;
  --green-l: rgba(74, 222, 128, 0.12);
  --rose: #FB7185;
  --rose-l: rgba(251, 113, 133, 0.12);
  --cyan: #22D3EE;
  --cyan-l: rgba(34, 211, 238, 0.12);

  --field-bg: rgba(255, 255, 255, 0.07);
  --field-bdr: rgba(255, 255, 255, 0.14);
  --field-focus-bdr: rgba(155, 125, 245, 0.7);
  --field-focus-sh: 0 0 0 3px rgba(155, 125, 245, 0.25);

  --error: #FF6B6B;
  --error-bg: rgba(255, 107, 107, 0.12);
  --error-bdr: rgba(255, 107, 107, 0.3);
}

/* Wallpaper presets */
[data-wall="tahoe"] {
  --a1: #2a165f;
  --a2: #4f2a95;
  --a3: #1f4b8a;
  --a4: #0f6a7b;
  --a5: #0a0f25;
  --wall:
    radial-gradient(120% 80% at 12% 18%, rgba(95, 58, 180, 0.48) 0%, transparent 58%),
    radial-gradient(95% 70% at 85% 16%, rgba(52, 109, 190, 0.44) 0%, transparent 62%),
    radial-gradient(85% 70% at 78% 84%, rgba(24, 130, 150, 0.38) 0%, transparent 58%),
    radial-gradient(88% 68% at 20% 82%, rgba(38, 22, 88, 0.5) 0%, transparent 62%),
    linear-gradient(145deg, #130a31 0%, var(--a1) 26%, var(--a3) 54%, var(--a4) 78%, #0a1028 100%);
}

[data-wall="sunset"] {
  --a1: #4e1f62;
  --a2: #8a2f74;
  --a3: #c04b5e;
  --a4: #f07b49;
  --a5: #2a1029;
  --wall:
    radial-gradient(120% 82% at 14% 16%, rgba(150, 54, 130, 0.45) 0%, transparent 58%),
    radial-gradient(100% 76% at 86% 18%, rgba(202, 84, 98, 0.42) 0%, transparent 60%),
    radial-gradient(84% 68% at 74% 86%, rgba(242, 129, 86, 0.38) 0%, transparent 56%),
    radial-gradient(86% 66% at 18% 84%, rgba(70, 24, 78, 0.5) 0%, transparent 60%),
    linear-gradient(148deg, #2b1134 0%, var(--a1) 26%, var(--a2) 48%, var(--a3) 70%, #6a253a 100%);
}

[data-wall="mint"] {
  --a1: #143f58;
  --a2: #1f7a7a;
  --a3: #2f9a93;
  --a4: #5bbf9f;
  --a5: #0c2433;
  --wall:
    radial-gradient(118% 78% at 12% 20%, rgba(45, 145, 140, 0.44) 0%, transparent 58%),
    radial-gradient(96% 72% at 84% 14%, rgba(58, 170, 160, 0.4) 0%, transparent 60%),
    radial-gradient(82% 66% at 76% 84%, rgba(103, 194, 165, 0.34) 0%, transparent 56%),
    radial-gradient(86% 68% at 22% 82%, rgba(20, 60, 86, 0.5) 0%, transparent 60%),
    linear-gradient(145deg, #0a2535 0%, var(--a1) 28%, var(--a2) 52%, var(--a3) 74%, #173a4b 100%);
}

[data-theme="dark"][data-wall="tahoe"] {
  --a5: #050410;
}
[data-theme="dark"][data-wall="sunset"] {
  --a5: #160a16;
}
[data-theme="dark"][data-wall="mint"] {
  --a5: #06131a;
}

/* Login pages default dark-first glass */
[data-page="login"] {
  --t1: rgba(255, 255, 255, 0.92);
  --t2: rgba(255, 255, 255, 0.6);
  --t3: rgba(255, 255, 255, 0.35);
  --t4: rgba(255, 255, 255, 0.18);
  --field-bg: rgba(255, 255, 255, 0.07);
  --field-bdr: rgba(255, 255, 255, 0.14);
  --field-focus-bdr: rgba(155, 125, 245, 0.7);
  --field-focus-sh: 0 0 0 3px rgba(155, 125, 245, 0.25);
}

[data-page="login"][data-theme="light"] {
  --a1: #2a1060;
  --a2: #0f1e5c;
  --a3: #0d3050;
  --a4: #3a1260;
  --a5: #180a38;
  --glass-bg: rgba(250, 248, 255, 0.92);
  --glass-bg-solid: #f0ecfa;
  --glass-bdr: rgba(0, 0, 0, 0.18);
  --glass-hi: rgba(255, 255, 255, 0.7);
  --glass-sh: 0 2px 80px rgba(0, 0, 0, 0.28), 0 8px 24px rgba(0, 0, 0, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.8);
  --tb-bg: rgba(238, 234, 252, 0.95);
  --tb-bdr: rgba(0, 0, 0, 0.1);
  --t1: rgba(18, 8, 44, 0.92);
  --t2: rgba(60, 40, 120, 0.72);
  --t3: rgba(100, 80, 160, 0.52);
  --t4: rgba(140, 120, 200, 0.32);
  --purple: #6C47D0;
  --purple-d: #4828A8;
  --field-bg: rgba(0, 0, 0, 0.05);
  --field-bdr: rgba(0, 0, 0, 0.12);
  --field-focus-bdr: rgba(108, 71, 208, 0.7);
  --field-focus-sh: 0 0 0 3px rgba(108, 71, 208, 0.18);
  --error: #DC2626;
  --error-bg: rgba(220, 38, 38, 0.08);
  --error-bdr: rgba(220, 38, 38, 0.25);
}

/* Admin accent override */
[data-page="admin"] {
  --purple: var(--amber, #c96a0a);
  --purple-d: var(--amber-d, #92400E);
  --purple-l: var(--amber-l, rgba(201, 106, 10, 0.1));
  --sb-active-bg: rgba(201, 106, 10, 0.13);
  --sb-active-c: var(--amber-d);
}

[data-page="admin"][data-theme="dark"] {
  --purple: #F59E0B;
  --purple-d: #FCD34D;
  --purple-l: rgba(245, 158, 11, 0.12);
  --sb-active-bg: rgba(245, 158, 11, 0.16);
  --sb-active-c: #F59E0B;
}

/* ── RESET & BASE ── */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  overflow-x: hidden;
}

body {
  font-family: var(--font);
  background: var(--wall);
  background-size: 400% 400%;
  min-height: 100dvh;
  -webkit-font-smoothing: antialiased;
  color: var(--t1);
  transition: background var(--dur-slow), color var(--dur-slow);
  overflow-x: hidden;
}

body.tahoe-app {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 22px;
  overflow: hidden;
  animation: wallDrift 22s ease infinite;
}

body.tahoe-login {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: max(24px, env(safe-area-inset-top)) 16px max(24px, env(safe-area-inset-bottom));
  overflow: hidden;
  background: var(--a5);
}

body.tahoe-admin {
  display: flex;
  min-height: 100vh;
  padding: 0;
  overflow: hidden;
  animation: none;
  background: var(--wall);
}

@media (max-width: 768px) {
  html {
    background: var(--tb-bg);
    min-height: 100dvh;
    height: 100dvh;
    overflow: hidden;
  }

  body.tahoe-app {
    padding: 0;
    overflow: hidden;
    background: var(--tb-bg);
    align-items: stretch;
    justify-content: flex-start;
    min-height: 100dvh;
    height: 100dvh;
    max-height: none;
  }

  html:has(body.tahoe-app) {
    background: var(--tb-bg);
  }

  html:has(body.tahoe-login) {
    background: var(--a5);
    height: auto;
    min-height: 100dvh;
    overflow: auto;
  }

  body.tahoe-login {
    min-height: 100dvh;
    width: 100%;
  }

  /* Paint browser chrome inset below visual viewport (Safari toolbar gap only) */
  html.mobile-vv:not(.pwa-standalone)::after {
    content: "";
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: var(--vvp-offset-bottom, 0px);
    background: var(--tb-bg);
    pointer-events: none;
    z-index: 89;
  }

  body.tahoe-app .aurora {
    display: none;
  }

  body.tahoe-notes {
    padding: 0;
    overflow: hidden;
    background: var(--tb-bg);
    animation: none;
    align-items: stretch;
    justify-content: flex-start;
    min-height: 100dvh;
    height: 100dvh;
  }

  html:has(body.tahoe-notes) {
    background: var(--tb-bg);
  }

  body.tahoe-notes .aurora {
    display: none;
  }
}

@keyframes wallDrift {
  0%, 100% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
}

.material-symbols-rounded {
  font-family: 'Material Symbols Rounded';
  font-weight: normal;
  font-style: normal;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  display: inline-block;
  white-space: nowrap;
  font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
  user-select: none;
  pointer-events: none;
  vertical-align: middle;
}

.msf, .ms-fill {
  font-variation-settings: 'FILL' 1, 'wght' 500, 'GRAD' 0, 'opsz' 24;
}

button, a {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

button:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[role="button"]:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--field-focus-bdr);
  outline-offset: 2px;
}

/* ── AURORA BACKGROUND ── */
.aurora {
  position: fixed;
  inset: -20%;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(ellipse 70% 60% at 15% 25%, var(--a1) 0%, transparent 70%),
    radial-gradient(ellipse 55% 50% at 85% 15%, var(--a2) 0%, transparent 65%),
    radial-gradient(ellipse 60% 55% at 75% 80%, var(--a3) 0%, transparent 65%),
    radial-gradient(ellipse 50% 45% at 25% 80%, var(--a4) 0%, transparent 60%),
    var(--a5);
}

.aurora-band, .aband, .ab {
  position: absolute;
  pointer-events: none;
  border-radius: 50%;
  filter: blur(80px);
  mix-blend-mode: screen;
  animation: bandFloat ease-in-out infinite;
}

.b1, .ab1 { width: 70vw; height: 40vh; top: -10vh; left: -10vw; background: rgba(108, 71, 208, 0.18); animation-duration: 18s; }
.b2, .ab2 { width: 60vw; height: 35vh; bottom: -5vh; right: -5vw; background: rgba(13, 148, 136, 0.14); animation-duration: 22s; animation-delay: -8s; }
.b3, .ab3 { width: 45vw; height: 30vh; top: 30%; left: 30%; background: rgba(180, 80, 220, 0.1); animation-duration: 28s; animation-delay: -14s; }

@keyframes bandFloat {
  0%, 100% { transform: translate(0, 0) scale(1); }
  33% { transform: translate(3vw, -3vh) scale(1.06); }
  66% { transform: translate(-2vw, 4vh) scale(0.96); }
}

@keyframes fadeUp {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

@keyframes winIn {
  from { opacity: 0; transform: scale(0.95) translateY(14px); }
  to { opacity: 1; transform: none; }
}

@keyframes routeIn {
  from { opacity: 0; transform: translateY(10px) scale(0.992); }
  to { opacity: 1; transform: none; }
}

@keyframes routeOut {
  to { opacity: 0; transform: translateY(-6px) scale(0.996); }
}

@keyframes contentReveal {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

/* Cross-document view transitions — shell stays fixed, main content crossfades in-window */
@media (prefers-reduced-motion: no-preference) {
  @view-transition {
    navigation: auto;
  }

  .win,
  .exam-app.win {
    view-transition-name: app-win;
  }

  .tb { view-transition-name: app-tb; }

  html.has-mobile-mini .mobile-mini {
    view-transition-name: app-tb;
  }

  html.has-mobile-mini body.tahoe-app .tb,
  html.has-mobile-mini body.tahoe-exam .exam-app .tb {
    view-transition-name: none;
  }

  html.has-mobile-mini body.tahoe-notes .notes-app .tb {
    view-transition-name: none;
  }

  .mobile-nav { view-transition-name: app-nav; }
  .sb, .sidebar { view-transition-name: app-sb; }

  /* The aurora wallpaper is byte-identical on the landing page, login and
     signup. Naming it means it is carried across as one element instead of
     being torn down and rebuilt inside the root snapshot, so the background
     sits perfectly still while the content above it changes. Every page has at
     most one .aurora, so this cannot collide. */
  .aurora { view-transition-name: app-bg; }
  ::view-transition-group(app-bg),
  ::view-transition-old(app-bg),
  ::view-transition-new(app-bg) { animation: none; }

  /* A view-transition-name must be unique per document — if two elements share
     one the browser aborts the WHOLE transition ("invalid state"), which is a
     silent hard cut rather than a visible error.

     arcade.html nests <main class="arcade-stage"> inside
     <main class="main arcade-main">, so the outer matched `.main` and the inner
     matched `.arcade-main main`, both claiming app-main. That killed every
     transition into and out of the game screen. Exclude the arcade wrapper so
     only its inner stage carries the name. */
  .main:not(.arcade-main),
  .notes-app #main,
  .exam-app .main,
  .arcade-main main { view-transition-name: app-main; }

  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation: none;
  }

  ::view-transition-group(app-win),
  ::view-transition-group(app-tb),
  ::view-transition-group(app-nav) {
    animation-duration: 0.16s;
    animation-timing-function: cubic-bezier(0.2, 0, 0, 1);
  }

  ::view-transition-group(app-sb) {
    animation: none;
  }

  ::view-transition-old(app-main),
  ::view-transition-new(app-main) {
    animation-duration: 0.36s;
    animation-timing-function: cubic-bezier(0.2, 0, 0, 1);
  }

  ::view-transition-old(app-main) {
    animation-name: routeOut;
    z-index: 1;
  }

  ::view-transition-new(app-main) {
    animation-name: routeIn;
    z-index: 2;
  }

  html.sh-page-ready .main > *:not(.app-hero),
  html.sh-page-ready .exam-app .main .page-wrap > *:not(.app-hero),
  html.sh-page-ready .arcade-main main > *:not(.app-hero) {
    animation: contentReveal 0.42s cubic-bezier(0.2, 0, 0, 1) both;
  }

  /* Generic staggered cascade — any section reveals in order, no per-class
     tuning needed. Hero (excluded above) is typically the first child, so the
     cascade naturally begins at the second slot. */
  html.sh-page-ready .main > *:nth-child(2),
  html.sh-page-ready .exam-app .main .page-wrap > *:nth-child(2),
  html.sh-page-ready .arcade-main main > *:nth-child(2) { animation-delay: 0.03s; }
  html.sh-page-ready .main > *:nth-child(3),
  html.sh-page-ready .exam-app .main .page-wrap > *:nth-child(3),
  html.sh-page-ready .arcade-main main > *:nth-child(3) { animation-delay: 0.06s; }
  html.sh-page-ready .main > *:nth-child(4),
  html.sh-page-ready .exam-app .main .page-wrap > *:nth-child(4),
  html.sh-page-ready .arcade-main main > *:nth-child(4) { animation-delay: 0.09s; }
  html.sh-page-ready .main > *:nth-child(5),
  html.sh-page-ready .exam-app .main .page-wrap > *:nth-child(5),
  html.sh-page-ready .arcade-main main > *:nth-child(5) { animation-delay: 0.12s; }
  html.sh-page-ready .main > *:nth-child(n+6),
  html.sh-page-ready .exam-app .main .page-wrap > *:nth-child(n+6),
  html.sh-page-ready .arcade-main main > *:nth-child(n+6) { animation-delay: 0.14s; }

  @media (max-width: 768px) {
    ::view-transition-old(app-main),
    ::view-transition-new(app-main) {
      animation-duration: 0.28s;
    }

    ::view-transition-group(app-win),
    ::view-transition-group(app-tb),
    ::view-transition-group(app-nav) {
      animation-duration: 0.10s;
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
  }
}

/* ── APP WINDOW SHELL ── */
.win {
  position: relative;
  z-index: 10;
  width: min(100%, 1280px);
  /* Height follows the viewport (capped well above any realistic screen) rather
     than a fixed 800px. The old cap left the inner scroll area at ~720px no
     matter how tall the display was, so 1080p/1440p users scrolled far more
     than necessary while the window sat letterboxed in the backdrop. Width
     stays capped at 1280px so the macOS-window proportions are unchanged. */
  height: min(calc(100vh - 44px), 1600px);
  background: var(--win-bg);
  backdrop-filter: saturate(200%) blur(44px);
  -webkit-backdrop-filter: saturate(200%) blur(44px);
  border: 1px solid var(--win-bdr);
  border-radius: var(--r-md);
  box-shadow: var(--win-shadow);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: background var(--dur-slow), border-color var(--dur-slow), box-shadow var(--dur-slow);
}

/* (The tablet-portrait height override that used to live here is gone: the base
   .win rule now uses the same viewport-following height at every width, so
   iPad portrait and tall desktops are covered by the same declaration.) */

@media (min-width: 769px) {
  body.route-enter .body,
  body.route-enter .body-area,
  body.route-enter .main,
  body.route-enter .notes-app #main,
  body.route-enter .exam-app .main,
  body.route-enter .arcade-main main {
    animation: routeIn var(--dur-route) var(--ease) both;
  }

  body.route-leave .body,
  body.route-leave .body-area,
  body.route-leave .main,
  body.route-leave .notes-app #main,
  body.route-leave .exam-app .main,
  body.route-leave .arcade-main main {
    opacity: 0;
    transform: translateY(-6px) scale(0.996);
    transition: opacity var(--dur-route) var(--ease), transform var(--dur-route) var(--ease);
  }
}

.win::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: var(--r-md);
  padding: 1px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.5) 0%, rgba(180, 120, 255, 0.35) 25%, rgba(80, 220, 255, 0.25) 50%, rgba(255, 140, 200, 0.2) 75%, rgba(255, 255, 255, 0.3) 100%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: destination-out;
  mask-composite: exclude;
  pointer-events: none;
}

.win--login {
  width: min(var(--win-w), 100%);
  height: auto;
  display: flex;
  flex-direction: column;
  border-radius: var(--win-r);
  background: var(--glass-bg);
  backdrop-filter: blur(80px) saturate(200%);
  -webkit-backdrop-filter: blur(80px) saturate(200%);
  border: 1px solid var(--glass-bdr);
  box-shadow: var(--glass-sh), inset 0 1.5px 0 var(--glass-hi), inset 0 -1px 0 rgba(255, 255, 255, 0.05);
  animation: winIn 0.55s var(--spring) both;
}

.win--login::before {
  border-radius: var(--win-r);
}

/* Login titlebar: traffic lights, title, language switch and theme toggle */
.win--login .tb {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 8px;
  padding: 0 12px;
}

.win--login .tb-center {
  position: static;
  left: auto;
  transform: none;
  min-width: 0;
  display: block;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.1px;
  color: var(--t2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: center;
}

.win--login .tb-theme {
  margin-left: 0;
  flex-shrink: 0;
}

.win--login .tls {
  gap: 6px;
}

.win--login .field-icon {
  top: 50%;
  left: 12px;
  transform: translateY(-50%);
}

.win--login .pw-toggle {
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
}

.win--login .submit-btn {
  min-height: 44px;
  height: 44px;
}

.win--login .auth-hint {
  color: var(--t2);
}

.win--fullscreen {
  width: 100vw;
  height: 100dvh;
  border-radius: 0;
  border: none;
  box-shadow: none;
}

@media (max-width: 768px) {
  .win:not(.win--login):not(.win--fullscreen) {
    width: 100%;
    max-width: 100vw;
    height: var(--app-h, 100dvh);
    min-height: var(--app-h, 100dvh);
    max-height: var(--app-h, 100dvh);
    border-radius: 0;
    border: none;
    box-shadow: none;
  }
  .win:not(.win--login):not(.win--fullscreen)::before { display: none; }
}

/* ── TITLEBAR ── */
.tb {
  height: var(--tb-h);
  flex-shrink: 0;
  background: var(--tb-bg);
  border-bottom: 1px solid var(--tb-bdr);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  display: flex;
  align-items: center;
  padding: 0 14px;
  gap: 10px;
  user-select: none;
  transition: background var(--dur-slow), border-color var(--dur-slow);
  position: relative;
}

.tls {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
  z-index: 1;
}

.tl {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 7px;
  font-weight: 800;
  color: transparent;
  cursor: pointer;
  transition: filter 0.15s, color 0.15s;
}

.tls:hover .tl { color: rgba(0, 0, 0, 0.5); }
.tl:hover { filter: brightness(0.8); }
.tl-r { background: var(--tl-r); }
.tl-y { background: var(--tl-y); }
.tl-g { background: var(--tl-g); }

.tb-center {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 8px;
  pointer-events: none;
}

.tb-app-icon, .tb-app-ic {
  width: 20px;
  height: 20px;
  border-radius: 5px;
  background: var(--purple-l);
  display: flex;
  align-items: center;
  justify-content: center;
}

.tb-app-icon .material-symbols-rounded,
.tb-app-ic .material-symbols-rounded {
  font-size: 12px;
  color: var(--purple);
}

.tb-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--t2);
  letter-spacing: -0.1px;
  white-space: nowrap;
  display: inline-block;
  max-width: min(62vw, 520px);
  overflow: hidden;
  text-overflow: ellipsis;
}

.tb-spacer { flex: 1; }
.tb-right { display: flex; align-items: center; gap: 6px; position: relative; z-index: 240; }

.search-pill {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0 10px;
  background: rgba(0, 0, 0, 0.06);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 7px;
  cursor: pointer;
  min-width: 150px;
  transition: background 0.15s, transform var(--dur-press) var(--ease);
}

[data-theme="dark"] .search-pill {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.1);
}

.search-pill:hover { background: rgba(0, 0, 0, 0.1); }
[data-theme="dark"] .search-pill:hover { background: rgba(255, 255, 255, 0.13); }
.search-pill:active { transform: scale(0.98); }
.search-pill .material-symbols-rounded { font-size: 13px; color: var(--t3); }
.search-pill span { font-size: 12px; color: var(--t3); flex: 1; }
.search-pill kbd {
  font-size: 10px;
  color: var(--t4);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 4px;
  padding: 0 4px;
  font-family: var(--font);
}

[data-theme="dark"] .search-pill kbd { border-color: rgba(255, 255, 255, 0.12); }

.tb-btn {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--t2);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s, transform var(--dur-press) var(--ease);
}

/* 50×30 rather than 46×26: the neighbouring avatar is 30px and the language
   switch and mission chip are 40px, so the old size left the toggle visibly
   short against everything beside it. The knob grows to match, which keeps
   the travel distance at 20px. */
#themeBtn.theme-pill {
  width: 50px;
  height: 30px;
  border-radius: 999px;
  padding: 2px;
  background: #d4d9e0;
  border: 1px solid rgba(15, 23, 42, 0.14);
  justify-content: flex-start;
  position: relative;
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.55);
}
[data-theme="dark"] #themeBtn.theme-pill {
  background: #4a525f;
  border-color: rgba(255, 255, 255, 0.2);
}
#themeBtn.theme-pill .material-symbols-rounded {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0;
  background: radial-gradient(circle at 35% 30%, #ffffff 0%, #f3f4f6 60%, #e5e7eb 100%);
  color: transparent;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.22), inset 0 -1px 0 rgba(0, 0, 0, 0.08);
  transform: translateX(0);
  transition: transform 0.2s var(--ease), background 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
#themeBtn.theme-pill .material-symbols-rounded::after {
  content: "";
  width: 8px;
  height: 2px;
  border-radius: 999px;
  background: rgba(156, 163, 175, 0.65);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
}

@media (max-width: 768px) {
  #themeBtn.theme-pill {
    width: 44px !important;
    height: 26px !important;
    min-width: 44px;
    min-height: 26px;
    border-radius: 999px !important;
    padding: 2px !important;
    box-sizing: border-box;
  }

  #themeBtn.theme-pill .material-symbols-rounded {
    width: 20px !important;
    height: 20px !important;
  }

  /* 44 − 2 border − 4 padding − 20 knob = 18px of travel. */
  #themeBtn.theme-pill[aria-pressed="true"] .material-symbols-rounded {
    transform: translateX(18px);
  }
}
/* The "on" state used iOS system green (#30b95a), a colour that appears
   nowhere else in the app and read as a stray success-toggle next to the
   purple language switch and mission chip. Uses the accent instead, so the
   whole header row is one palette. */
#themeBtn.theme-pill[aria-pressed="true"] {
  background: var(--purple);
  border-color: color-mix(in srgb, var(--purple) 45%, transparent);
}
#themeBtn.theme-pill[aria-pressed="true"] .material-symbols-rounded {
  transform: translateX(20px);
}
#themeBtn.theme-pill:active,
#themeBtn.theme-pill.theme-just-toggled,
[data-theme="dark"] #themeBtn.theme-pill[aria-pressed="true"] {
  border-color: color-mix(in srgb, var(--purple) 55%, transparent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--purple) 22%, transparent);
}
.tb-btn:hover { background: rgba(0, 0, 0, 0.08); }
[data-theme="dark"] .tb-btn:hover { background: rgba(255, 255, 255, 0.1); }
.tb-btn:active { transform: scale(0.96); }
.tb-btn .material-symbols-rounded { font-size: 16px; }

.ham { display: none; }
@media (max-width: 768px) { .ham { display: flex; } }
@media (max-width: 500px) {
  .tb-center {
    display: flex;
    max-width: min(46vw, 220px);
    gap: 6px;
  }
  .tb-app-icon, .tb-app-ic {
    display: none;
  }
  .tb-title {
    font-size: 11.5px;
    max-width: min(46vw, 220px);
  }
}
@media (max-width: 380px) {
  .tb-center {
    max-width: min(40vw, 170px);
  }
  .tb-title {
    font-size: 11px;
    max-width: min(40vw, 170px);
  }
}
@media (max-width: 580px) { .search-pill { display: none; } }
@media (max-width: 1024px) {
  .tb-title { max-width: min(54vw, 420px); }
}

/* Tablet-width desktop titlebar: keep the centred page title in normal flex
   flow so the language switcher/search controls always reserve their width.
   The absolute desktop centring otherwise lets the title render underneath
   those controls at widths such as iPad portrait (820/834/1024px). */
@media (min-width: 769px) and (max-width: 1024px) {
  .tb-center {
    position: static;
    left: auto;
    transform: none;
    min-width: 0;
    max-width: none;
    flex: 0 1 auto;
  }

  .tb-center .tb-title {
    max-width: 100%;
  }
}

/* ── BODY LAYOUT ── */
.body, .body-area {
  flex: 1;
  display: flex;
  overflow: hidden;
  position: relative;
}

/* ── SIDEBAR ── */
.sb, .sidebar {
  width: var(--sb-w);
  min-width: var(--sb-w);
  max-width: var(--sb-w);
  flex: 0 0 var(--sb-w);
  background: var(--sb-bg);
  backdrop-filter: blur(32px);
  -webkit-backdrop-filter: blur(32px);
  border-right: 1px solid var(--sb-bdr);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 8px;
  transition: background var(--dur-slow), border-color var(--dur-slow), transform 0.28s var(--ease);
}

@media (max-width: 768px) {
  .sb, .sidebar {
    min-width: 0;
    max-width: none;
    flex: initial;
    position: fixed;
    top: var(--tb-h);
    left: 0;
    bottom: 0;
    z-index: 90;
    transform: translateX(-100%);
    box-shadow: 6px 0 28px rgba(0, 0, 0, 0.22);
    /* The drawer runs to bottom:0, but the fixed bottom nav sits on top of its
       last ~57px. With only a safe-area pad the tail of the menu was both
       covered AND unreachable — content height exactly matched the box, so
       overflow-y never engaged and there was nothing to scroll. Clear the nav
       the same way .main does, which both frees the last item and gives the
       drawer something to scroll when the menu is long. */
    padding-bottom: calc(var(--mobile-nav-h) + env(safe-area-inset-bottom, 0px) + 12px);
  }
  .sb.open, .sidebar.open { transform: translateX(0); }

  html.has-mobile-mini .sb,
  html.has-mobile-mini .sidebar,
  html.has-mobile-mini .sb-scrim {
    top: var(--mobile-mini-h, 56px);
  }
}

.sb::-webkit-scrollbar, .sidebar::-webkit-scrollbar { width: 0; }

.sb-brand, .sidebar-logo {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 14px 14px 10px;
  flex-shrink: 0;
}

.sb-bmark {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  overflow: hidden;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.22), 0 0 0 1px rgba(255, 255, 255, 0.05);
}

.sb-bmark--logo { width: 30px; height: 30px; border-radius: 8px; }

.sb-bmark .material-symbols-rounded { font-size: 14px; color: var(--purple); }

.sb-bname {
  font-size: 13.5px;
  font-weight: 700;
  letter-spacing: -0.2px;
  color: var(--t1);
  transition: color var(--dur-slow);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sb-bname em { color: var(--purple); font-style: normal; }

.sb-lbl, .nav-section-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--t3);
  padding: 8px 14px 4px;
  transition: color var(--dur-slow);
}

.sb-item, .nav-item {
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 32px;
  padding: 5px 10px;
  border-radius: var(--r-sm);
  margin: 1px 6px;
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  font-family: var(--font);
  font-size: 13.5px;
  font-weight: 400;
  color: var(--t1);
  text-decoration: none;
  transition: background var(--dur-fast), color var(--dur-fast), transform var(--dur-fast) var(--ease);
}

.sb-item:hover, .nav-item:hover { background: var(--sb-hover); }
.sb-item.act, .nav-item.active { background: var(--sb-active-bg); color: var(--sb-active-c); font-weight: 600; }

/* ── Submit Examination (sidebar) ──
   This is the one irreversible action in the exam, but it was rendered with
   the plain .sb-item styling — visually identical to "Nota" or "Profil", so it
   read as just another nav row and students missed it. Given the amber
   treatment already used by the mobile submit CTA, plus a slow glow so it
   draws the eye without behaving like an error. */
/* Fixed amber values rather than var(--amber)/var(--amber-d): those tokens
   invert between themes (--amber-d is a deep brown in light but a pale #FCD34D
   in dark), which made the gradient end lighter in dark mode and washed out
   the white label.
   The fill is also deliberately darker than .mobile-submit-final's. That
   button can carry a brighter amber because its label is large bold text,
   which only needs 3:1; this sidebar row is 13.5px normal text and needs
   4.5:1, and white on the brighter amber measured just 2.15:1. This fill
   gives ~5:1 while the bright halo below still does the attention-grabbing. */
.sb-item.sb-exam-submit {
  margin-top: 6px;
  /* A <button> shrink-wraps its label, so this sat 26px narrower than the rows
     above it — invisible while the row was transparent, obvious once it had a
     fill. Stretch it to the sidebar width so both edges line up, and centre the
     icon + label inside it so it reads as a CTA rather than a nav row. */
  width: calc(100% - 12px);
  box-sizing: border-box;
  justify-content: center;
  font-weight: 700;
  color: #fff;
  background: linear-gradient(135deg, #b45309 0%, #92400e 100%);
  box-shadow: 0 2px 10px color-mix(in srgb, var(--amber) 40%, transparent);
  animation: examSubmitGlow 2.4s ease-in-out infinite;
}
.sb-item.sb-exam-submit:hover {
  background: linear-gradient(135deg, #c2610a 0%, #a04910 100%);
}
.sb-item.sb-exam-submit > .material-symbols-rounded { color: #fff; }

@keyframes examSubmitGlow {
  0%, 100% { box-shadow: 0 2px 10px color-mix(in srgb, var(--amber) 35%, transparent); }
  50%      { box-shadow: 0 2px 18px color-mix(in srgb, var(--amber) 70%, transparent); }
}

/* The pulse is an attention cue, not information — drop it for anyone who has
   asked for reduced motion, keeping the colour treatment that does the work. */
@media (prefers-reduced-motion: reduce) {
  .sb-item.sb-exam-submit { animation: none; }
}
/* Mod Belajar / nav — keep per-mode icon accent when row is active */
.sb-item > .material-symbols-rounded.msf:first-child {
  flex-shrink: 0;
}
.sb-item.act > .material-symbols-rounded.msf:first-child[style*="color"] {
  opacity: 1;
}
.sb-item .material-symbols-rounded, .nav-item .material-symbols-rounded { font-size: 15px; width: 17px; flex-shrink: 0; }
.sb-item-subj {
  align-items: flex-start;
  min-height: 48px;
  padding-top: 6px;
  padding-bottom: 6px;
}
.sb-item-subj .material-symbols-rounded {
  margin-top: 2px;
}
.sb-subj-label {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.2;
  flex: 1;
}
.sb-subj-code {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.25px;
  color: inherit;
}
.sb-subj-name {
  font-size: 10.5px;
  color: var(--t3);
  white-space: normal;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.sb-item.act .sb-subj-name {
  color: var(--sb-active-c);
  opacity: 0.85;
}

.sb-badge {
  margin-left: auto;
  flex-shrink: 0;
  font-size: 11px;
  font-weight: 600;
  background: rgba(0, 0, 0, 0.07);
  color: var(--t3);
  border-radius: 20px;
  padding: 1px 7px;
}
.sb-item-subj .sb-badge {
  margin-top: 2px;
}

[data-theme="dark"] .sb-badge { background: rgba(255, 255, 255, 0.1); }

.sb-div {
  height: 1px;
  background: var(--sb-bdr);
  margin: 6px 10px;
  flex-shrink: 0;
}

.sb-spacer { flex: 1; }

.sb-prog { padding: 6px 14px 10px; }
.sb-prog-row {
  display: flex;
  justify-content: space-between;
  font-size: 11.5px;
  color: var(--t2);
  margin-bottom: 5px;
}

.sb-prog-row span { color: var(--purple); font-weight: 600; }

.sb-track, .prog-track {
  height: 3px;
  border-radius: var(--r-full);
  background: rgba(0, 0, 0, 0.09);
  overflow: hidden;
  transition: background var(--dur-slow);
}

[data-theme="dark"] .sb-track, [data-theme="dark"] .prog-track { background: rgba(255, 255, 255, 0.1); }

.sb-fill, .prog-fill {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--purple), var(--teal));
  width: 0%;
  transition: width 1s var(--ease);
}

.sb-profile { padding: 8px 10px 6px; flex-shrink: 0; }

.sp {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: 10px;
  background: var(--sb-hover);
  text-decoration: none;
  color: var(--t1);
  cursor: pointer;
  transition: background 0.15s;
}

.sp:hover { background: rgba(0, 0, 0, 0.1); }
[data-theme="dark"] .sp:hover { background: rgba(255, 255, 255, 0.1); }

.sp-av, .sb-avatar {
  width: 30px;
  height: 30px;
  border-radius: var(--r-sm);
  background: var(--purple-l);
  border: 1.5px solid rgba(108, 71, 208, 0.28);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  flex-shrink: 0;
}

.sp-info { flex: 1; min-width: 0; }
.sp-name { font-size: 12.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sp-sub { font-size: 11px; color: var(--t3); margin-top: 1px; }
.sp-sync {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 999px;
  border: 1px solid var(--card-bdr);
  background: var(--panel2);
  color: var(--t2);
  font-size: 10px;
  font-weight: 700;
  line-height: 1.2;
}
.sp-ch .material-symbols-rounded { font-size: 14px; color: var(--t3); }

.sb-scrim {
  display: none;
  position: absolute;
  inset: 0;
  z-index: 55;
  background: rgba(0, 0, 0, 0.38);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.28s;
}

@media (max-width: 768px) {
  .sb-scrim {
    display: block;
    position: fixed;
    top: var(--tb-h);
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 80;
  }
  /* Freeze background scrollers while the drawer is open (no scroll-bleed) */
  body.sb-locked .main,
  body.sb-locked .notes-app .main,
  body.sb-locked .notes-app #main,
  body.sb-locked .exam-app .main,
  body.sb-locked .arcade-main main { overflow: hidden; touch-action: none; }
}
.sb-scrim.on { opacity: 1; pointer-events: auto; }

/* Sidebar contextual widgets */
.xp-card {
  margin: 0 10px 8px;
  padding: 12px;
  border-radius: 10px;
  background: var(--purple-l);
  border: 1px solid rgba(108, 71, 208, 0.25);
}

.xp-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.xp-val { font-size: 20px; font-weight: 700; letter-spacing: -0.4px; color: var(--purple); }
.xp-streak { display: flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 600; color: var(--t2); }
.xp-bar-track { height: 4px; border-radius: var(--r-full); background: rgba(108, 71, 208, 0.2); overflow: hidden; }
.xp-bar-fill { height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--purple-d), var(--teal)); transition: width 1s var(--ease); }
.xp-lbl { font-size: 10.5px; color: var(--t3); margin-top: 4px; display: flex; justify-content: space-between; }

/* The sidebar Daily Mission block was removed (home.html's .dc-mission card is
   now the single renderer), so its .quest-* styles are gone with it. Only the
   completion pop survives, retargeted to the dashboard's .mission-row. */
.mission-row.quest-pop {
  animation: questPop 380ms var(--spring);
}

@keyframes questPop {
  0% { transform: scale(1); }
  35% { transform: scale(1.03); background: color-mix(in srgb, var(--green) 18%, transparent); }
  100% { transform: scale(1); }
}

.sb-hero {
  padding: 18px 14px 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  border-bottom: 1px solid var(--sb-bdr);
}

.sb-avatar { width: 60px; height: 60px; border-radius: var(--r-lg); font-size: 30px; }

.sb-empty {
  padding: 8px 14px 10px;
  font-size: 11px;
  color: var(--t3);
  line-height: 1.45;
}

.sb-mini-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  padding: 0 10px 8px;
}

.sb-mini-stat {
  padding: 10px 8px;
  border-radius: 10px;
  background: var(--sb-hover);
  border: 1px solid var(--sb-bdr);
  text-align: center;
  /* Same centring fix as .week-stat — "Cubaan" is one line while
     "Skor Terbaik" is two, which left the pair looking misaligned. */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-width: 0;
  overflow-wrap: anywhere;
}

.sb-mini-val {
  display: block;
  font-size: 18px;
  font-weight: 700;
  color: var(--purple);
  letter-spacing: -0.3px;
}

.sb-mini-lbl {
  display: block;
  font-size: 10px;
  color: var(--t3);
  margin-top: 2px;
  font-weight: 600;
}

.sb-recent-body {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: 1px;
}

.sb-recent-title {
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sb-recent-sub {
  font-size: 10.5px;
  color: var(--t3);
}

.notes-sb-context {
  border-top: 1px solid var(--sb-bdr);
  margin-top: 8px;
  padding-top: 8px;
}

.notes-sb-panel .notes-sb-title {
  font-size: 12px;
  font-weight: 600;
  color: var(--t2);
  padding: 0 14px 8px;
  line-height: 1.4;
}

.notes-sb-links .sb-item {
  font-size: 12.5px;
}

.sb-level {
  padding: 10px 14px;
  border-bottom: 1px solid var(--sb-bdr);
}

.sb-lv-label {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  font-weight: 600;
  color: var(--t2);
  margin-bottom: 6px;
}

.sb-lv-track {
  height: 5px;
  border-radius: var(--r-full);
  background: var(--sb-track, rgba(0,0,0,.08));
  overflow: hidden;
}

.sb-lv-fill {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--purple-d), var(--teal));
  transition: width .8s var(--ease);
}

.sb-lv-sub {
  display: flex;
  justify-content: space-between;
  font-size: 10.5px;
  color: var(--t3);
  margin-top: 4px;
}

.sb-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  padding: 10px 14px 12px;
  border-bottom: 1px solid var(--sb-bdr);
}

.sb-stat {
  text-align: center;
  padding: 8px;
  border-radius: 10px;
  background: var(--sb-hover);
}

.sb-stat-val {
  font-size: 18px;
  font-weight: 700;
  color: var(--t1);
}

.sb-stat-lbl {
  font-size: 10px;
  color: var(--t3);
  margin-top: 2px;
}

.sb-display-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--t1);
  text-align: center;
}

.sb-email {
  font-size: 11px;
  color: var(--t3);
  text-align: center;
}

.sb-rank {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  font-weight: 600;
  color: var(--purple);
  padding: 4px 10px;
  border-radius: var(--r-full);
  background: var(--purple-l);
}

.sb-logout {
  color: #e74c3c !important;
}

/* Exam live sidebar */
.exam-lobby-card,
.exam-live-card,
.exam-result-card {
  margin: 0 10px 8px;
  padding: 12px;
  border-radius: 10px;
  background: var(--sb-hover);
  border: 1px solid var(--sb-bdr);
}

.exam-lobby-mode,
.exam-live-mode {
  display: inline-block;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: var(--r-full);
  margin-bottom: 8px;
}

.exam-lobby-mode,
.exam-live-mode.learn { background: rgba(34, 197, 94, 0.15); color: #16a34a; }
.exam-live-mode.final { background: rgba(217, 119, 6, 0.15); color: var(--amber); }

.exam-lobby-row,
.exam-live-subj {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 700;
  color: var(--t1);
  margin-bottom: 4px;
}

.exam-lobby-meta {
  font-size: 11px;
  color: var(--t3);
}

.exam-live-timer {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--t1);
  margin: 8px 0 10px;
  padding: 6px 10px;
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.04);
}

.exam-live-timer.warn { color: #dc2626; background: rgba(220, 38, 38, 0.1); }

.exam-live-prog { padding: 0 !important; margin-bottom: 10px; }

.sb-exam-palette {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 5px;
  padding: 0 10px 8px;
}

.sb-exam-q {
  min-height: 28px;
  border: 1px solid var(--sb-bdr);
  border-radius: 7px;
  background: var(--main-bg);
  color: var(--t2);
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}

.sb-exam-q.answered { background: rgba(34, 197, 94, 0.12); border-color: rgba(34, 197, 94, 0.35); color: #16a34a; }
.sb-exam-q.current { background: var(--purple-l); border-color: var(--purple); color: var(--purple); }

.exam-result-pct {
  font-size: 32px;
  font-weight: 800;
  letter-spacing: -1px;
  color: var(--purple);
  line-height: 1;
  margin-bottom: 6px;
}

.exam-result-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--t1);
  margin-bottom: 4px;
}

.exam-result-meta {
  font-size: 11px;
  color: var(--t3);
  margin-bottom: 10px;
}

/* ── MAIN CONTENT ── */
.main {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
  padding: 28px 32px 24px;
  background: var(--main-bg);
  transition: background var(--dur-slow);
  scroll-behavior: smooth;
}

@media (max-width: 768px) {
  .main { padding: 20px 16px calc(var(--mobile-nav-h) + env(safe-area-inset-bottom, 0px) + 12px); }
}

.main::-webkit-scrollbar { width: 4px; }
.main::-webkit-scrollbar-track { background: transparent; }
.main::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.15); border-radius: var(--r-full); }
[data-theme="dark"] .main::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.15); }

/* ── TYPOGRAPHY ── */
.welcome { margin-bottom: 22px; }
.continue-card,
.continue-hub {
  margin: 0 0 14px;
  padding: 14px 15px 13px;
  border: 1px solid var(--card-bdr);
  border-radius: 14px;
  background: var(--card);
  box-shadow: var(--card-sh);
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.continue-hub-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}
.continue-copy { min-width: 0; }
.continue-kicker {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--t3);
  font-weight: 700;
}
.continue-access {
  flex-shrink: 0;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--t3);
  padding: 4px 9px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--t3) 12%, transparent);
  border: 1px solid var(--card-bdr);
  white-space: nowrap;
}
.continue-last {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 12px;
  align-items: center;
  padding: 11px 12px;
  border-radius: 12px;
  background: linear-gradient(135deg, color-mix(in srgb, var(--purple) 12%, var(--sb-hover)), var(--sb-hover));
  border: 1px solid color-mix(in srgb, var(--purple) 22%, var(--card-bdr));
}
.continue-last-ic {
  width: 44px;
  height: 44px;
  border-radius: 11px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--purple-l);
  color: var(--purple);
}
.continue-last-ic .material-symbols-rounded { font-size: 24px; }
.continue-last-body { min-width: 0; }
.continue-subject {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--purple);
}
.continue-title {
  font-size: 14px;
  font-weight: 800;
  color: var(--t1);
  line-height: 1.25;
  margin: 2px 0 8px;
  letter-spacing: -0.15px;
}
.continue-prog-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.continue-prog-track {
  flex: 1;
  height: 5px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--t3) 18%, transparent);
  overflow: hidden;
  min-width: 72px;
}
.continue-prog-fill {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--purple), var(--teal));
  transition: width 0.7s var(--ease);
}
.continue-prog-lbl {
  font-size: 10.5px;
  font-weight: 700;
  color: var(--t3);
  min-width: 72px;
  text-align: right;
}
.continue-sub {
  font-size: 11px;
  color: var(--t3);
  margin-top: 2px;
  line-height: 1.4;
}
.continue-btn {
  border: none;
  background: linear-gradient(135deg, var(--purple), var(--purple-d));
  color: #fff;
  border-radius: 10px;
  min-height: 44px;
  padding: 0 16px;
  font-weight: 700;
  font-size: 13px;
  font-family: var(--font);
  cursor: pointer;
  box-shadow: 0 4px 14px color-mix(in srgb, var(--purple) 35%, transparent);
  transition: transform 0.15s var(--spring), box-shadow 0.15s;
  white-space: nowrap;
}
.continue-btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 18px color-mix(in srgb, var(--purple) 42%, transparent);
}
.continue-btn:active { transform: scale(0.98); }
.continue-recent-wrap { display: flex; flex-direction: column; gap: 6px; }
.continue-recent-wrap[hidden] { display: none; }
.continue-recent-lbl {
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.35px;
  color: var(--t3);
}
.continue-recent-list { display: flex; flex-direction: column; gap: 5px; }
.continue-recent-item {
  display: grid;
  grid-template-columns: 26px 1fr auto;
  gap: 8px;
  align-items: center;
  padding: 7px 8px;
  min-height: 44px;
  border-radius: 9px;
  text-decoration: none;
  color: inherit;
  background: var(--sb-hover);
  border: 1px solid var(--sb-bdr);
  transition: background 0.15s, transform 0.15s var(--spring);
}
.continue-recent-item:hover {
  background: color-mix(in srgb, var(--purple) 8%, var(--sb-hover));
  transform: translateX(2px);
}
.continue-recent-item .cr-ic {
  width: 26px;
  height: 26px;
  border-radius: 7px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--purple-l);
  color: var(--purple);
}
.continue-recent-item .cr-ic .material-symbols-rounded { font-size: 15px; }
.continue-recent-item .cr-name {
  font-size: 12px;
  font-weight: 700;
  color: var(--t1);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.continue-recent-item .cr-sub {
  font-size: 10px;
  color: var(--t3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.continue-recent-item .cr-time {
  font-size: 10px;
  color: var(--t3);
  font-weight: 600;
  white-space: nowrap;
}
.continue-empty {
  font-size: 12px;
  color: var(--t3);
  line-height: 1.45;
  padding: 4px 2px 2px;
}
@media (max-width: 640px) {
  .continue-last {
    grid-template-columns: auto 1fr;
    grid-template-rows: auto auto;
  }
  .continue-last .continue-btn {
    grid-column: 1 / -1;
    width: 100%;
    margin-top: 4px;
  }
}
.w-eyebrow { font-size: 11.5px; font-weight: 600; color: var(--t3); margin-bottom: 5px; letter-spacing: 0.2px; }
.w-h { font-size: 26px; font-weight: 700; letter-spacing: -0.45px; color: var(--t1); line-height: 1.15; margin-bottom: 5px; }
.w-h .hi { color: var(--purple); }
.w-sub { font-size: 13px; color: var(--t2); line-height: 1.6; }

/* Wraps rather than squeezing: the right-hand label can be a full subject name
   ("HPGD1203 · Teori & Amalan P&P"), which on a narrow phone left both it and
   the title broken across two lines and overlapping. */
.sec-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin-bottom: 14px;
}
.sec-title { font-size: 15.5px; font-weight: 700; letter-spacing: -0.2px; color: var(--t1); }
.sec-title em { color: var(--purple); font-style: normal; }

/* ── Subject filter chip row (arcade lobby, notes hub, etc.) ──
   This used to be a horizontal scroller. With a handful of same-width chips it
   almost fitted, so instead of looking scrollable it just sliced the last chip
   down the middle ("HPGD2303" showing as "HPGD230") — which reads as broken
   rather than as "swipe for more". Wrapping can never clip: the chips either
   fit on one line or move to a second one. */
.subj-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 16px;
}
.subj-chip {
  flex-shrink: 0;
  padding: 8px 15px;
  border-radius: var(--r-full);
  font-size: 12.5px;
  font-weight: 700;
  color: var(--t2);
  background: var(--card);
  border: 1px solid var(--card-bdr);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.15s var(--spring);
  white-space: nowrap;
}

/* Trim the chips just enough that the three subject codes still share one line
   on a 320px screen rather than dropping one onto a row of its own. */
@media (max-width: 400px) {
  .subj-chip-row { gap: 6px; }
  .subj-chip { padding: 7px 11px; font-size: 12px; }
}
.subj-chip:hover { border-color: var(--purple); color: var(--purple); }
.subj-chip.act {
  background: var(--purple);
  border-color: var(--purple);
  color: #fff;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px color-mix(in srgb, var(--purple) 35%, transparent);
}

/* ── Tap-target helper ──
   Stretches an element's *hit area* to at least 44px tall (Apple HIG / WCAG
   2.5.5) using a centred, invisible overlay, so small text links stay visually
   small while still being comfortably tappable. Because the overlay is
   absolutely positioned it adds no height to the row the link sits in — which
   matters for .view-all and the compact mobile header, where a real
   min-height would push the surrounding layout around. */
.tap44 { position: relative; }
.tap44::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  height: 100%;
  min-height: 44px;
}

.view-all {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--purple);
  background: none;
  border: none;
  cursor: pointer;
  opacity: 0.8;
  transition: opacity 0.15s;
  text-decoration: none;
  /* Rendered ~15px tall; widen the hit area without changing the header row. */
  position: relative;
}

.view-all::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  height: 100%;
  min-height: 44px;
}

.view-all:hover { opacity: 1; }

/* ── STATS ── */
.stats { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 26px; }

.stat, .stat-card {
  flex: 1;
  min-width: 76px;
  background: var(--card);
  border: 1px solid var(--card-bdr);
  border-radius: 10px;
  box-shadow: var(--card-sh);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  padding: 12px 14px;
  transition: background var(--dur-slow), border-color var(--dur-slow), box-shadow 0.2s, transform 0.2s var(--spring);
  cursor: default;
}

.stat:hover, .stat-card:hover { box-shadow: var(--card-sh-h); transform: translateY(-1px); }
.stat-n { font-size: 24px; font-weight: 700; letter-spacing: -0.5px; color: var(--purple); line-height: 1; margin-bottom: 3px; }
.stat-l { font-size: 11px; color: var(--t3); font-weight: 500; }

/* ── GRID & CARDS ── */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(255px, 1fr));
  gap: 13px;
}

@media (max-width: 960px) { .grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) { .grid { grid-template-columns: 1fr; } .stats { gap: 8px; } .stat-n { font-size: 20px; } }

.sc, .glass-card {
  background: var(--card);
  border: 1px solid var(--card-bdr);
  border-radius: 14px;
  box-shadow: var(--card-sh);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: box-shadow var(--dur), transform var(--dur) var(--spring), background var(--dur-slow), border-color var(--dur-slow);
  animation: fadeUp 0.44s var(--ease) both;
}

.sc:hover, .glass-card:hover { box-shadow: var(--card-sh-h); transform: translateY(-1px); }

.sc-cov { padding: 15px 18px 12px; position: relative; overflow: hidden; }
.c1 .sc-cov { background: linear-gradient(135deg, rgba(108, 71, 208, 0.1), rgba(108, 71, 208, 0.03)); }
.c2 .sc-cov { background: linear-gradient(135deg, rgba(13, 148, 136, 0.1), rgba(13, 148, 136, 0.03)); }
.c3 .sc-cov { background: linear-gradient(135deg, rgba(37, 99, 235, 0.1), rgba(37, 99, 235, 0.03)); }

.sc-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 9px; }
.sc-code { font-size: 10px; font-weight: 700; letter-spacing: 0.8px; text-transform: uppercase; padding: 2px 8px; border-radius: 5px; }
.c1 .sc-code { color: var(--purple-d); background: rgba(108, 71, 208, 0.12); }
.c2 .sc-code { color: #065F46; background: rgba(13, 148, 136, 0.12); }
.c3 .sc-code { color: #1D4ED8; background: rgba(37, 99, 235, 0.12); }
[data-theme="dark"] .c1 .sc-code { color: var(--purple); background: var(--purple-l); }
[data-theme="dark"] .c2 .sc-code { color: var(--teal); background: var(--teal-l); }
[data-theme="dark"] .c3 .sc-code { color: var(--blue); background: var(--blue-l); }

.sc-ic { width: 34px; height: 34px; border-radius: 9px; display: flex; align-items: center; justify-content: center; transition: transform 0.28s var(--spring); }
.sc:hover .sc-ic { transform: rotate(-8deg) scale(1.1); }
.c1 .sc-ic { background: rgba(108, 71, 208, 0.12); }
.c2 .sc-ic { background: rgba(13, 148, 136, 0.12); }
.c3 .sc-ic { background: rgba(37, 99, 235, 0.12); }
.sc-ic .material-symbols-rounded { font-size: 18px; }
.c1 .sc-ic .material-symbols-rounded { color: var(--purple); }
.c2 .sc-ic .material-symbols-rounded { color: var(--teal); }
.c3 .sc-ic .material-symbols-rounded { color: var(--blue); }

.sc-name { font-size: 14px; font-weight: 700; letter-spacing: -0.15px; color: var(--t1); line-height: 1.35; }
.sc-body { padding: 10px 18px 12px; flex: 1; }
.sc-desc { font-size: 12px; color: var(--t3); line-height: 1.65; margin-bottom: 9px; }
.sc-chips { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 11px; }

.chip {
  font-size: 10.5px;
  font-weight: 500;
  padding: 2px 8px;
  border-radius: 5px;
  background: rgba(0, 0, 0, 0.05);
  border: 1px solid rgba(0, 0, 0, 0.06);
  color: var(--t3);
}

[data-theme="dark"] .chip { background: rgba(255, 255, 255, 0.07); border-color: rgba(255, 255, 255, 0.08); }

.sc-prog { margin-bottom: 0; }
.prog-meta { display: flex; justify-content: space-between; font-size: 10.5px; font-weight: 500; color: var(--t3); }
.sc-div { height: 1px; background: rgba(0, 0, 0, 0.06); margin: 0 18px; }
[data-theme="dark"] .sc-div { background: rgba(255, 255, 255, 0.07); }

.sc-modes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; padding: 10px 14px 14px; }

.mb, .quick-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 9px 4px;
  border-radius: var(--r-sm);
  border: 1px solid var(--card-bdr);
  background: rgba(0, 0, 0, 0.03);
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, transform 0.15s var(--spring), box-shadow 0.15s;
  font-family: var(--font);
}
.quick-btn {
  color: var(--t1);
  text-decoration: none;
}

[data-theme="dark"] .mb, [data-theme="dark"] .quick-btn { background: rgba(255, 255, 255, 0.04); }
.mb:hover, .quick-btn:hover { transform: translateY(-1px); box-shadow: var(--card-sh); }
.mb:active, .quick-btn:active { transform: translateY(0) scale(0.98); }
.mb .material-symbols-rounded, .quick-btn .material-symbols-rounded { font-size: 17px; }
.mb-lbl { font-size: 10.5px; font-weight: 600; color: var(--t2); }
.mb-n:hover { background: var(--purple-l); border-color: rgba(108, 71, 208, 0.3); }
.mb-n:hover .mb-lbl { color: var(--purple); }
.mb-n .material-symbols-rounded { color: var(--purple); }
.mb-e:hover { background: var(--amber-l); border-color: rgba(201, 106, 10, 0.3); }
.mb-e:hover .mb-lbl { color: var(--amber); }
.mb-e .material-symbols-rounded { color: var(--amber); }
.mb-g:hover { background: var(--teal-l); border-color: rgba(13, 148, 136, 0.3); }
.mb-g:hover .mb-lbl { color: var(--teal); }
.mb-g .material-symbols-rounded { color: var(--teal); }

/* ════════════════════════════════════════
   HOME DASHBOARD (Menu Utama)
   Personalised cards — XP, streak, missions,
   subjects, recent topics, weekly, badges
   ════════════════════════════════════════ */
.hero-strip {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  margin-bottom: 14px;
}
@media (max-width: 960px) { .hero-strip { grid-template-columns: repeat(2, 1fr); } }

/* Below ~400px a two-column strip leaves each tile's text column about 90px
   wide. "Skor Terbaik Peperiksaan" and "Belum ada topik diselesaikan" then wrap
   one word per line and spill past the tile, which clips them because .hero-kpi
   is overflow:hidden. One column gives the full width back so every label fits
   on a single line. Measured at 320px this costs ~80px of height (297 -> 378)
   and each tile drops from ~145px to ~88px — worth it to stop clipping data. */
@media (max-width: 400px) {
  .hero-strip { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 480px) {
  .hero-strip { gap: 8px; }
  .hero-kpi { padding: 10px; gap: 8px; }
  .hero-ic { width: 30px; height: 30px; border-radius: 8px; }
  .hero-ic .material-symbols-rounded { font-size: 17px; }
  .hero-val { font-size: 17px; }
  .hero-val-sm { font-size: 10.5px; }
  .hero-lbl { font-size: 9.5px; }
  .hero-sub { font-size: 9px; margin-top: 3px; }
  .hero-bar { margin-top: 5px; }
  .hero-bar-meta { font-size: 8.5px; }
}

.hero-kpi {
  display: flex;
  gap: 12px;
  padding: 13px 14px;
  background: var(--card);
  border: 1px solid var(--card-bdr);
  border-radius: 14px;
  box-shadow: var(--card-sh);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  position: relative;
  overflow: hidden;
  transition: transform 0.18s var(--spring), box-shadow 0.2s ease;
  animation: fadeUp 0.42s var(--ease) both;
}
.hero-kpi:hover { transform: translateY(-1px); box-shadow: var(--card-sh-h); }
.hero-kpi::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, var(--kpi-c, var(--purple-l)) 0%, transparent 55%);
  pointer-events: none;
  opacity: 0.55;
}
.hero-kpi > * { position: relative; z-index: 1; }
.hero-kpi.k-xp { --kpi-c: var(--purple-l); }
.hero-kpi.k-streak { --kpi-c: var(--amber-l); }
.hero-kpi.k-topic { --kpi-c: var(--teal-l); }
.hero-kpi.k-exam { --kpi-c: var(--blue-l); }

.hero-ic {
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--kpi-c);
}
.hero-ic .material-symbols-rounded { font-size: 22px; color: #fff; }

/* .hero-kpi is overflow:hidden, so a word too long for the text column is
   clipped rather than wrapped. Malay labels here are long ("Peperiksaan",
   "diselesaikan"), so break inside a word as a last resort. */
.hero-meta {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  flex: 1;
  overflow-wrap: anywhere;
}
.hero-val {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.5px;
  color: var(--t1);
  line-height: 1.05;
}
.hero-val-sm {
  font-size: 13px;
  font-weight: 600;
  color: var(--t3);
  margin-left: 2px;
}
.hero-lbl {
  font-size: 11px;
  color: var(--t3);
  font-weight: 600;
  margin-top: 2px;
  letter-spacing: 0.1px;
}
.hero-sub {
  font-size: 10.5px;
  color: var(--t3);
  margin-top: 5px;
  line-height: 1.3;
}
.hero-bar {
  height: 4px;
  margin-top: 7px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--t3) 18%, transparent);
  overflow: hidden;
}
.hero-bar-fill {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--purple), var(--purple-d));
  transition: width 0.8s var(--ease);
}
.hero-bar-fill.green { background: linear-gradient(90deg, var(--teal), var(--green)); }
.hero-bar-meta {
  font-size: 10px;
  color: var(--t3);
  margin-top: 3px;
  font-weight: 500;
}

/* ── Shared app hero banner ── */
[data-page="home"] .welcome,
[data-page="notes-hub"] .welcome,
[data-page="arcade"] .welcome { display: none; }

.app-hero {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  border-radius: 20px;
  padding: 20px 26px;
  margin-bottom: 14px;
  color: #fff;
  background:
    radial-gradient(135% 150% at 0% 0%, rgba(255, 255, 255, 0.20) 0%, transparent 42%),
    linear-gradient(135deg, #7d5fe6 0%, #5a35be 36%, #2f4fb0 68%, #0d9488 128%);
  box-shadow: 0 16px 42px rgba(79, 42, 149, 0.34), inset 0 1px 0 rgba(255, 255, 255, 0.28);
  animation: fadeUp 0.5s var(--ease) both;
}
.app-hero::before,
.app-hero::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  filter: blur(34px);
  pointer-events: none;
  z-index: -1;
}
.app-hero::before { width: 280px; height: 280px; background: rgba(255, 255, 255, 0.16); top: -130px; right: -30px; }
.app-hero::after  { width: 220px; height: 220px; background: rgba(13, 148, 136, 0.55); bottom: -120px; right: 130px; }

/* Per-section accents */
.app-hero--notes {
  background:
    radial-gradient(135% 150% at 0% 0%, rgba(255, 255, 255, 0.20) 0%, transparent 42%),
    linear-gradient(135deg, #8b5cf6 0%, #6d28d9 40%, #4f2a95 75%, #5a35be 130%);
  box-shadow: 0 16px 42px rgba(91, 53, 190, 0.34), inset 0 1px 0 rgba(255, 255, 255, 0.28);
}
.app-hero--notes::after { background: rgba(139, 92, 246, 0.5); }
.app-hero--arcade {
  background:
    radial-gradient(135% 150% at 0% 0%, rgba(255, 255, 255, 0.20) 0%, transparent 42%),
    linear-gradient(135deg, #0ea5a3 0%, #0d9488 38%, #2f6fb0 78%, #5a35be 135%);
  box-shadow: 0 16px 42px rgba(13, 148, 136, 0.34), inset 0 1px 0 rgba(255, 255, 255, 0.28);
}
.app-hero--arcade::after { background: rgba(45, 111, 176, 0.55); }

.app-hero-inner {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 22px;
}
.app-hero-main { flex: 1; min-width: 0; }

.hero-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.2px;
  color: rgba(255, 255, 255, 0.88);
  text-transform: capitalize;
}
.hero-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #7CFFB2;
  box-shadow: 0 0 0 4px rgba(124, 255, 178, 0.25);
  animation: heroPulse 2.4s var(--ease) infinite;
}
@keyframes heroPulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(124, 255, 178, 0.28); }
  50% { box-shadow: 0 0 0 7px rgba(124, 255, 178, 0.08); }
}
.hero-title {
  font-size: 28px;
  font-weight: 800;
  letter-spacing: -0.6px;
  line-height: 1.12;
  margin: 9px 0 7px;
  color: #fff;
}
.hero-title em {
  font-style: normal;
  background: linear-gradient(90deg, #FFE6A7, #FFB37C);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
.hero-tag {
  font-size: 13px;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.82);
  max-width: 540px;
}
.hero-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 15px;
}
.hero-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
  border: 1px solid rgba(255, 255, 255, 0.28);
  font-size: 12.5px;
  font-weight: 600;
  color: #fff;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.hero-chip .material-symbols-rounded { font-size: 16px; }
.hero-chip.hot { background: rgba(255, 159, 64, 0.26); border-color: rgba(255, 191, 120, 0.5); }
.hero-cta {
  margin-top: 18px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 18px;
  border-radius: 12px;
  border: none;
  cursor: pointer;
  background: #fff;
  color: #5a35be;
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 700;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
  transition: transform 0.16s var(--spring), box-shadow 0.2s ease;
}
.hero-cta:hover { transform: translateY(-2px); box-shadow: 0 11px 28px rgba(0, 0, 0, 0.26); }
.hero-cta:active { transform: translateY(0); }
.hero-cta .material-symbols-rounded { font-size: 18px; }
.hero-cta .material-symbols-rounded:last-child { font-size: 17px; transition: transform 0.18s var(--ease); }
.hero-cta:hover .material-symbols-rounded:last-child { transform: translateX(3px); }

.home-hero-visual { flex-shrink: 0; display: grid; place-items: center; }
.hero-ring {
  width: 108px;
  height: 108px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  position: relative;
  background: conic-gradient(#fff calc(var(--ring, 0%) * 1), rgba(255, 255, 255, 0.22) 0);
  transition: background 0.8s var(--ease);
}
.hero-ring::before {
  content: '';
  position: absolute;
  inset: 9px;
  border-radius: 50%;
  background: linear-gradient(135deg, #5a35be, #2f4fb0);
  box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.25);
}
.hero-ring-inner { position: relative; z-index: 1; text-align: center; }
.hero-ring-lvl { font-size: 28px; font-weight: 800; line-height: 1; color: #fff; }
.hero-ring-lbl { font-size: 9.5px; letter-spacing: 1.5px; margin-top: 3px; color: rgba(255, 255, 255, 0.82); font-weight: 700; }

@media (max-width: 640px) {
  .app-hero { padding: 20px; border-radius: 18px; }
  .hero-title { font-size: 22px; }
  .app-hero-visual { display: none; }
}

/* ── KPI card polish ── */
.hero-kpi { border-radius: 16px; }
.hero-kpi::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--kpi-strong, var(--purple));
  z-index: 2;
  opacity: 0.95;
}
.hero-kpi.k-xp { --kpi-strong: var(--purple); }
.hero-kpi.k-streak { --kpi-strong: var(--amber); }
.hero-kpi.k-topic { --kpi-strong: var(--teal); }
.hero-kpi.k-exam { --kpi-strong: var(--blue); }
.hero-kpi:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 26px color-mix(in srgb, var(--kpi-strong, var(--purple)) 24%, transparent);
}
.hero-kpi .hero-ic {
  background: var(--kpi-strong, var(--purple));
  box-shadow: 0 4px 12px color-mix(in srgb, var(--kpi-strong, var(--purple)) 35%, transparent);
}
.hero-kpi .hero-ic .material-symbols-rounded { color: #fff; }

/* Dashboard grid */
.dash-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 13px;
  margin-bottom: 20px;
}
.dash-card {
  background: var(--card);
  border: 1px solid var(--card-bdr);
  border-radius: 14px;
  box-shadow: var(--card-sh);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  padding: 14px 15px 13px;
  display: flex;
  flex-direction: column;
  gap: 11px;
  transition: box-shadow 0.2s, transform 0.18s var(--spring);
  animation: fadeUp 0.44s var(--ease) both;
  min-width: 0;
}
.dash-card:hover { box-shadow: var(--card-sh-h); transform: translateY(-1px); }

/* Column spans on desktop */
.dash-card.dc-subj    { grid-column: span 4; }
.dash-card.dc-mission { grid-column: span 2; }
.dash-card.dc-recent  { grid-column: span 3; }
.dash-card.dc-weekly  { grid-column: span 3; }
.dash-card.dc-arcade  { grid-column: span 3; }
/* Badges read as a lighter full-width strip at the bottom (no empty half-row,
   keeps the actionable cards above more prominent). */
.dash-card.dc-badges  { grid-column: span 6; }

@media (max-width: 1080px) {
  .dash-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .dash-card.dc-subj    { grid-column: span 4; }
  .dash-card.dc-mission { grid-column: span 4; }
  .dash-card.dc-recent  { grid-column: span 2; }
  .dash-card.dc-weekly  { grid-column: span 2; }
  .dash-card.dc-arcade  { grid-column: span 2; }
  .dash-card.dc-badges  { grid-column: span 4; }
}
@media (max-width: 720px) {
  .dash-grid { grid-template-columns: 1fr; gap: 10px; }
  .dash-card,
  .dash-card.dc-subj, .dash-card.dc-mission,
  .dash-card.dc-recent, .dash-card.dc-weekly,
  .dash-card.dc-arcade, .dash-card.dc-badges { grid-column: span 1; }
}

.dash-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.dash-card-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--t1);
  letter-spacing: -0.1px;
  /* Lets the title take the wrap instead of squeezing the pill next to it. */
  min-width: 0;
}
.dash-card-pill {
  font-size: 10.5px;
  color: var(--t3);
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--t3) 12%, transparent);
  /* A date range ("03 OGO – 09 OGO") broke across two lines on narrow phones
     and left the pill looking misaligned against the title. */
  white-space: nowrap;
  flex-shrink: 0;
}
.dash-card-pill.done {
  color: var(--green);
  background: color-mix(in srgb, var(--green) 16%, transparent);
}

/* Subject progress rows */
.subj-progress-list { display: flex; flex-direction: column; gap: 9px; }
.subj-progress-row {
  display: grid;
  grid-template-columns: 38px 1fr auto;
  gap: 11px;
  align-items: center;
  padding: 9px 10px;
  border-radius: 11px;
  background: var(--sb-hover);
  border: 1px solid var(--sb-bdr);
  transition: background 0.18s, transform 0.18s var(--spring);
  text-decoration: none;
  color: inherit;
  min-width: 0;
}
.subj-progress-row:hover {
  background: color-mix(in srgb, var(--purple) 6%, var(--sb-hover));
  transform: translateX(2px);
}
.subj-progress-row.highlight {
  background: color-mix(in srgb, var(--purple) 14%, var(--sb-hover));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--purple) 35%, transparent);
}
.subj-ic {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.subj-progress-row[data-subj="1203"] .subj-ic { background: var(--purple-l); color: var(--purple); }
.subj-progress-row[data-subj="2203"] .subj-ic { background: var(--teal-l); color: var(--teal); }
.subj-progress-row[data-subj="2303"] .subj-ic { background: var(--blue-l); color: var(--blue); }
.subj-ic .material-symbols-rounded { font-size: 20px; }
.subj-text { min-width: 0; }
.subj-code {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  color: var(--t3);
  text-transform: uppercase;
}
.subj-continuing-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: none;
  color: var(--purple);
  background: var(--purple-l);
  border-radius: 999px;
  vertical-align: middle;
}
.subj-name {
  font-size: 13px;
  font-weight: 700;
  color: var(--t1);
  line-height: 1.25;
  margin: 1px 0 5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.subj-bar-row { display: flex; align-items: center; gap: 8px; }
.subj-bar {
  flex: 1;
  height: 5px;
  background: color-mix(in srgb, var(--t3) 18%, transparent);
  border-radius: 999px;
  overflow: hidden;
  min-width: 60px;
}
.subj-bar-fill {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--purple), var(--teal));
  transition: width 0.85s var(--ease);
}
.subj-progress-row[data-subj="2203"] .subj-bar-fill { background: linear-gradient(90deg, var(--teal), var(--green)); }
.subj-progress-row[data-subj="2303"] .subj-bar-fill { background: linear-gradient(90deg, var(--blue), var(--purple)); }
.subj-bar-lbl { font-size: 10.5px; color: var(--t3); font-weight: 700; min-width: 38px; text-align: right; }
.subj-arrow {
  color: var(--t3);
  display: flex;
  align-items: center;
}
.subj-progress-row:hover .subj-arrow { color: var(--purple); }

/* Mission card */
.mission-progress-bar {
  height: 6px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--t3) 18%, transparent);
  overflow: hidden;
}
.mission-progress-fill {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--purple), var(--teal));
  transition: width 0.5s var(--ease);
}
.mission-list { display: flex; flex-direction: column; gap: 6px; }
.mission-row {
  display: grid;
  grid-template-columns: 22px 1fr 18px;
  gap: 9px;
  align-items: center;
  font-size: 11.5px;
  color: var(--t2);
  padding: 4px 2px;
}
.mission-row .m-ic-wrap {
  width: 22px;
  height: 22px;
  border-radius: 7px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--t3) 16%, transparent);
}
.mission-row .m-ic-wrap .material-symbols-rounded { font-size: 14px; color: var(--t3); }
.mission-row .m-st { font-size: 16px; color: var(--t3); }
.mission-row.done { color: var(--t1); }
.mission-row.done .m-ic-wrap { background: color-mix(in srgb, var(--green) 18%, transparent); }
.mission-row.done .m-ic-wrap .material-symbols-rounded { color: var(--green); }
.mission-row.done .m-st { color: var(--green); }

/* Recent topics */
.recent-body { display: flex; flex-direction: column; gap: 7px; }
.recent-row {
  display: grid;
  grid-template-columns: 30px 1fr;
  gap: 9px;
  align-items: center;
  padding: 7px 8px;
  border-radius: 9px;
  text-decoration: none;
  background: var(--sb-hover);
  border: 1px solid var(--sb-bdr);
  color: inherit;
  transition: background 0.15s, transform 0.18s var(--spring);
  min-width: 0;
}
.recent-row:hover {
  background: color-mix(in srgb, var(--purple) 8%, var(--sb-hover));
  transform: translateX(2px);
}
.recent-ic {
  width: 30px;
  height: 30px;
  border-radius: 8px;
  background: var(--purple-l);
  color: var(--purple);
  display: flex;
  align-items: center;
  justify-content: center;
}
.recent-ic .material-symbols-rounded { font-size: 16px; }
.recent-meta { min-width: 0; }
.recent-name {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--t1);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.recent-sub {
  font-size: 10.5px;
  color: var(--t3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.recent-empty {
  font-size: 12px;
  color: var(--t3);
  padding: 12px 4px;
  text-align: center;
  line-height: 1.4;
}

/* Weekly card */
.week-stats { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; }
.week-stat {
  padding: 10px 8px;
  border-radius: 10px;
  background: var(--sb-hover);
  border: 1px solid var(--sb-bdr);
  text-align: center;
  /* Grid stretches the tiles to equal height, but the content used to sit at
     the top — so a one-line label ("TOPIK BARU") and a two-line one
     ("XP MINGGUAN") left the row looking off-centre. Centre the content in the
     tile and give them a common floor so the row reads as a set. */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 62px;
  min-width: 0;
}
.week-val {
  font-size: 19px;
  font-weight: 800;
  color: var(--purple);
  letter-spacing: -0.3px;
  line-height: 1.05;
}
.week-val.green { color: var(--green); }
.week-val.amber { color: var(--amber); }
.week-lbl {
  font-size: 10px;
  font-weight: 600;
  color: var(--t3);
  margin-top: 3px;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  line-height: 1.25;
  /* Split a two-word label evenly instead of dropping a single orphan word,
     and never let a long word push past the tile. */
  text-wrap: balance;
  overflow-wrap: anywhere;
}
.week-empty {
  font-size: 11px;
  color: var(--t3);
  text-align: center;
  padding: 6px 4px 0;
  line-height: 1.45;
}

/* Arcade snippet */
.arcade-snippet {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 12px;
  align-items: center;
}
.arcade-rank-ic {
  width: 48px;
  height: 48px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--amber-l);
  color: var(--amber);
  font-size: 24px;
}
.arcade-rank-ic .material-symbols-rounded { font-size: 26px; }
.arcade-meta { display: flex; flex-direction: column; min-width: 0; }
.arcade-rank-name {
  font-size: 14px;
  font-weight: 800;
  color: var(--t1);
  letter-spacing: -0.2px;
}
.arcade-rank-sub {
  font-size: 11px;
  color: var(--t3);
  margin-top: 2px;
}
.arcade-rank-bar {
  margin-top: 7px;
  height: 4px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--t3) 18%, transparent);
  overflow: hidden;
}
.arcade-rank-bar-fill {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--amber), var(--purple));
  transition: width 0.8s var(--ease);
}

/* Badges row */
.badge-row {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 8px;
}
.badge-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 10px 6px 9px;
  border-radius: 11px;
  background: var(--sb-hover);
  border: 1px solid var(--sb-bdr);
  text-align: center;
  min-width: 0;
  transition: transform 0.18s var(--spring), box-shadow 0.18s;
  cursor: pointer;
}
.badge-tile:hover { transform: translateY(-2px); box-shadow: var(--card-sh); }
.badge-tile.locked { opacity: 0.45; filter: grayscale(70%); }
.badge-tile.featured { border-color: color-mix(in srgb, var(--amber) 55%, transparent); background: color-mix(in srgb, var(--amber) 7%, var(--sb-hover)); }
.badge-tile .bt-img {
  width: 38px;
  height: 38px;
  object-fit: contain;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.12));
}
.badge-tile .bt-emoji {
  display: none;
  font-size: 28px;
  line-height: 1;
}
.badge-tile .bt-name {
  font-size: 10px;
  font-weight: 700;
  color: var(--t2);
  letter-spacing: 0.1px;
  line-height: 1.2;
  width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.badge-tile .bt-feat-star {
  position: absolute;
  top: 4px;
  right: 4px;
  font-size: 12px;
  color: var(--amber);
}
.badge-tile { position: relative; }
.badge-empty {
  grid-column: 1 / -1;
  font-size: 11.5px;
  color: var(--t3);
  text-align: center;
  padding: 14px 8px;
  line-height: 1.45;
}

/* Notes hub topic cards */
.quick-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 16px;
}
@media (max-width: 820px) {
  .quick-row { grid-template-columns: 1fr; }
}
.sec-count {
  font-size: 12px;
  color: var(--t3);
  font-weight: 700;
  min-width: 0;
  overflow-wrap: anywhere;
}
.tgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 10px;
}
.tc {
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  gap: 8px;
  text-decoration: none;
  color: var(--t1);
  border: 1px solid var(--card-bdr);
  border-radius: 12px;
  background: var(--card);
  box-shadow: var(--card-sh);
  padding: 12px;
  transition: transform .2s var(--spring), box-shadow .2s ease;
}
.tc:hover {
  transform: translateY(-2px);
  box-shadow: var(--card-sh-h);
}
.tc-body { min-width: 0; }
.tc-num { font-size: 11px; font-weight: 700; color: var(--purple); margin-bottom: 4px; }
.tc-icon { font-size: 16px; display: inline-block; margin-bottom: 4px; }
.tc-title { font-weight: 700; line-height: 1.25; margin-bottom: 2px; }
.tc-sub { font-size: 12px; color: var(--t3); line-height: 1.35; }
.tc-arrow {
  display: flex;
  align-items: center;
  color: var(--purple);
}

/* ── BUTTONS ── */
.btn, .submit-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 40px;
  padding: 0 20px;
  border-radius: 10px;
  border: none;
  font-family: var(--font);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, transform 0.12s var(--spring), box-shadow 0.15s, opacity 0.15s;
}

.btn-primary, .submit-btn {
  background: linear-gradient(135deg, var(--purple), var(--purple-d));
  color: #fff;
  box-shadow: 0 4px 18px rgba(108, 71, 208, 0.32), inset 0 1px 0 rgba(255, 255, 255, 0.25);
}

.btn-primary:hover, .submit-btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 6px 24px rgba(108, 71, 208, 0.4); }
.btn-primary:active, .submit-btn:active:not(:disabled) { transform: scale(0.98); }
.btn-primary:disabled, .submit-btn:disabled { opacity: 0.55; cursor: not-allowed; }

.btn-secondary {
  background: var(--card);
  border: 1px solid var(--card-bdr);
  color: var(--t1);
  box-shadow: var(--card-sh);
}

.btn-secondary:hover { background: var(--sb-hover); }

.btn-danger {
  background: var(--error-bg);
  border: 1px solid var(--error-bdr);
  color: var(--error);
}

.btn-ghost {
  background: transparent;
  border: 1px solid var(--card-bdr);
  color: var(--t2);
}

.btn-sm { height: 32px; padding: 0 14px; font-size: 12.5px; border-radius: var(--r-sm); }
.btn-lg { height: 48px; padding: 0 28px; font-size: 15px; border-radius: var(--r-md); }

/* ── FORMS ── */
.field { margin-bottom: 14px; }

.field-label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--t2);
  margin-bottom: 6px;
  letter-spacing: 0.02em;
}

.field-input, .form-input, input[type="text"], input[type="email"], input[type="password"], input[type="number"], select, textarea {
  width: 100%;
  height: 42px;
  padding: 0 14px;
  background: var(--field-bg);
  border: 1px solid var(--field-bdr);
  border-radius: 10px;
  font-family: var(--font);
  font-size: 14px;
  color: var(--t1);
  outline: none;
  appearance: none;
  -webkit-appearance: none;
  text-align: left;
  transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}

textarea { height: auto; min-height: 80px; padding: 12px 14px; resize: vertical; }

.field-input:focus, .form-input:focus, input:focus, select:focus, textarea:focus {
  border-color: var(--field-focus-bdr);
  box-shadow: var(--field-focus-sh);
}

.field-input::placeholder, input::placeholder, textarea::placeholder { color: var(--t3); }

.field-input:-webkit-autofill,
.field-input:-webkit-autofill:hover,
.field-input:-webkit-autofill:focus,
.field-input:-webkit-autofill:active {
  -webkit-box-shadow: 0 0 0 1000px var(--field-bg) inset;
  -webkit-text-fill-color: var(--t1);
  caret-color: var(--t1);
  transition: background-color 9999s ease-out 0s;
}

html.auth-pending .main,
html.auth-pending .notes-app #main,
html.auth-pending .exam-app .main,
html.auth-pending .arcade-main main {
  opacity: 0;
  pointer-events: none;
}

html.auth-checking .win--login .win-body,
html.auth-checking .win--login .win-foot { opacity: 0; }
html.auth-checking .win--login .tb { opacity: 1; }

.field-row { display: flex; gap: 10px; align-items: flex-end; }
.field-row .field { flex: 1; }

.alert {
  padding: 10px 14px;
  border-radius: var(--r-sm);
  font-size: 13px;
  background: var(--error-bg);
  border: 1px solid var(--error-bdr);
  color: var(--error);
  margin-bottom: 14px;
}

.alert-success { background: var(--success-bg); border-color: rgba(13, 148, 136, 0.3); color: var(--success); }

/* ── MODALS & OVERLAYS ── */
.modal-overlay, .spot {
  position: fixed;
  inset: 0;
  z-index: 280;
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 80px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s;
}

.modal-overlay.on, .spot.on { opacity: 1; pointer-events: auto; }

.modal, .spot-box {
  width: min(540px, 90%);
  background: var(--win-bg);
  backdrop-filter: saturate(180%) blur(44px);
  -webkit-backdrop-filter: saturate(180%) blur(44px);
  border: 1px solid var(--win-bdr);
  border-radius: 14px;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.4), 0 6px 18px rgba(0, 0, 0, 0.22);
  overflow: hidden;
  transform: scale(0.96) translateY(-10px);
  transition: transform 0.2s var(--spring);
}

.modal-overlay.on .modal, .spot.on .spot-box { transform: none; }

.modal-header { padding: 16px 20px; border-bottom: 1px solid var(--sb-bdr); display: flex; align-items: center; justify-content: space-between; }
.modal-title { font-size: 15px; font-weight: 700; color: var(--t1); }
.modal-body { padding: 20px; }
.modal-footer { padding: 14px 20px; border-top: 1px solid var(--sb-bdr); display: flex; gap: 8px; justify-content: flex-end; }

.spot-inp-row { display: flex; align-items: center; gap: 10px; padding: 13px 16px; border-bottom: 1px solid var(--sb-bdr); }
.spot-inp-row .material-symbols-rounded { font-size: 19px; color: var(--t3); }
.spot-inp { flex: 1; min-height: 44px; background: none; border: none; outline: none; font-family: var(--font); font-size: 16px; color: var(--t1); }
.spot-inp::placeholder { color: var(--t3); }
.spot-esc { font-size: 10px; color: var(--t4); border: 1px solid var(--card-bdr); border-radius: 4px; padding: 1px 6px; }
.spot-results { padding: 8px; min-height: 80px; }
.spot-item { display: flex; align-items: center; gap: 12px; padding: 9px 12px; border-radius: var(--r-sm); cursor: pointer; text-decoration: none; color: var(--t1); transition: background 0.1s; }
.spot-item:hover, .spot-item.sel { background: var(--sb-active-bg); }
.spot-item .material-symbols-rounded { font-size: 17px; color: var(--purple); flex-shrink: 0; }
.spot-body { flex: 1; min-width: 0; }
.spot-name { font-size: 13.5px; font-weight: 500; }
.spot-sub { font-size: 11px; color: var(--t3); }
.spot-empty { text-align: center; padding: 22px; font-size: 13px; color: var(--t3); }

/* ── FOOTER & MOBILE NAV ── */
.foot {
  height: var(--foot-h);
  flex-shrink: 0;
  background: var(--tb-bg);
  border-top: 1px solid var(--tb-bdr);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background var(--dur-slow), border-color var(--dur-slow);
}

.foot span { font-size: 11px; color: var(--t3); }

.mobile-nav {
  display: none;
  flex-shrink: 0;
  background: var(--tb-bg);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border-top: 1px solid var(--tb-bdr);
  z-index: 90;
}

@media (max-width: 768px) {
  .mobile-nav {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: var(--vvp-offset-bottom, 0px);
    width: 100%;
    box-sizing: border-box;
    min-height: var(--mobile-nav-h);
    height: auto;
    padding: 0;
    padding-bottom: env(safe-area-inset-bottom, 0px);
    align-items: flex-start;
    transform: translateZ(0);
    -webkit-transform: translateZ(0);
  }

  html.pwa-standalone .mobile-nav {
    bottom: 0;
  }

  /* Installed PWA: nav lives in the flex shell (not fixed + vvp offset) */
  html.pwa-standalone body.tahoe-app .win > .mobile-nav,
  html.pwa-standalone body.tahoe-notes .win > .mobile-nav,
  html.pwa-standalone body.tahoe-notes .notes-app > .mobile-nav,
  html.pwa-standalone body.tahoe-exam .exam-app > .mobile-nav {
    position: relative;
    bottom: auto;
    left: auto;
    right: auto;
    transform: none;
    flex-shrink: 0;
    width: 100%;
  }

  html.pwa-standalone.has-mobile-mini body.tahoe-app .win,
  html.pwa-standalone body.tahoe-notes .notes-app,
  html.pwa-standalone body.tahoe-exam .exam-app {
    display: flex;
    flex-direction: column;
  }

  html.pwa-standalone .main {
    padding-bottom: 16px;
  }

  .foot { display: none; }
  .sb-item, .nav-item { min-height: 44px; padding: 8px 10px; }
  .sb-item-subj { min-height: 52px; }
  .tb-btn:not(#themeBtn), .ham { width: 44px; height: 44px; border-radius: 10px; }
  .tls { gap: 1px; }
  .tl {
    width: 22px;
    height: 22px;
    font-size: 0;
    background: transparent !important;
    display: grid;
    place-items: center;
  }
  .tl::before {
    content: "";
    width: 12px;
    height: 12px;
    border-radius: 50%;
    display: block;
  }
  .tl-r::before { background: var(--tl-r); }
  .tl-y::before { background: var(--tl-y); }
  .tl-g::before { background: var(--tl-g); }
  .quick-btn { min-height: 44px; }
}

.mn-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  text-decoration: none;
  color: var(--t3);
  font-family: var(--font);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.2px;
  min-height: var(--mobile-nav-h);
  height: var(--mobile-nav-h);
  padding: 4px 2px;
  border: none;
  background: none;
  cursor: pointer;
  transition: color 0.15s;
}

.mn-item.act { color: var(--purple); }
.mn-item.act .material-symbols-rounded { color: var(--purple); font-variation-settings: 'FILL' 1, 'wght' 500, 'GRAD' 0, 'opsz' 24; }
.mn-item .material-symbols-rounded { font-size: 22px; margin-bottom: 1px; }

/* ── TOAST ── */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(var(--foot-h) + 12px);
  z-index: 200;
  transform: translate(-50%, 10px);
  opacity: 0;
  pointer-events: none;
  background: var(--card);
  border: 1px solid var(--card-bdr);
  border-radius: var(--r-full);
  box-shadow: var(--card-sh-h);
  padding: 6px 8px 6px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  transition: transform 0.22s var(--ease), opacity 0.22s;
  white-space: nowrap;
}

.toast.on { transform: translate(-50%, 0); opacity: 1; pointer-events: auto; }
.toast span { font-size: 12.5px; font-weight: 600; color: var(--t2); }
.toast button { min-height: 26px; height: 26px; padding: 0 12px; border-radius: var(--r-full); border: none; background: var(--purple); color: #fff; font-family: var(--font); font-size: 12px; font-weight: 700; cursor: pointer; }

/* Release announcements carry more copy than the compact update toast. */
.language-update-toast {
  width: min(calc(100vw - 32px), 430px);
  max-width: 430px;
  padding: 13px 14px;
  border-radius: 18px;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 11px;
  white-space: normal;
}
.toast.language-update-toast { display: grid; }
.toast .language-update-icon {
  width: 38px;
  height: 38px;
  border-radius: 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  background: linear-gradient(135deg, var(--purple), var(--blue));
  box-shadow: 0 6px 16px rgba(90, 53, 190, .24);
  font-size: 20px;
  font-weight: 400;
}
.toast .language-update-copy {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
  color: var(--t2);
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.35;
}
.toast .language-update-copy > span {
  color: var(--t2);
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.35;
}
.language-update-copy strong {
  color: var(--t1);
  font-size: 13px;
  font-weight: 800;
  line-height: 1.25;
}
.language-update-toast #languageUpdateDismiss {
  min-height: 38px;
  height: 38px;
  padding: 0 15px;
}

.xp-toast {
  position: fixed;
  right: 20px;
  bottom: calc(var(--foot-h) + 16px);
  z-index: 240;
  min-width: 180px;
  max-width: min(92vw, 300px);
  background: var(--card);
  border: 1px solid var(--card-bdr);
  border-radius: 12px;
  box-shadow: var(--card-sh-h);
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  transform: translateY(10px);
  opacity: 0;
  pointer-events: none;
  transition: transform .2s var(--ease), opacity .2s var(--ease);
}
.xp-toast.on {
  transform: translateY(0);
  opacity: 1;
}
.xp-toast .material-symbols-rounded {
  color: var(--purple);
  font-size: 18px;
}
.xp-toast-title {
  font-size: 12.5px;
  color: var(--t1);
  font-weight: 700;
  line-height: 1.2;
}
.xp-toast-sub {
  font-size: 11px;
  color: var(--t3);
  margin-top: 1px;
}

@media (max-width: 768px) {
  .xp-toast {
    right: 12px;
    left: 12px;
    bottom: calc(var(--mobile-nav-h) + env(safe-area-inset-bottom, 0px) + 12px);
    max-width: none;
  }

  .toast {
    bottom: calc(var(--mobile-nav-h) + env(safe-area-inset-bottom, 0px) + 12px);
    white-space: normal;
    max-width: min(92vw, 360px);
  }

  .toast button {
    min-height: 44px;
    height: auto;
    padding: 0 16px;
    flex-shrink: 0;
  }

  .language-update-toast {
    bottom: calc(var(--mobile-nav-h) + env(safe-area-inset-bottom, 0px) + 14px);
  }

  .language-update-toast #languageUpdateDismiss {
    min-height: 40px;
    height: 40px;
  }
}

.sh-notice-banner {
  position: fixed;
  left: 20px;
  bottom: calc(var(--foot-h) + 16px + var(--notice-offset, 0px));
  z-index: 241;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  max-width: min(92vw, 380px);
  background: var(--card);
  border: 1px solid var(--card-bdr);
  border-radius: 12px;
  box-shadow: var(--card-sh-h);
  padding: 9px 8px 9px 12px;
  opacity: 0;
  pointer-events: none;
  transform: translateY(10px);
  transition: transform .25s var(--ease), opacity .25s var(--ease);
}
.sh-notice-banner.on {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}
.sh-notice-banner .material-symbols-rounded {
  flex-shrink: 0;
  color: var(--purple);
  font-size: 16px;
  line-height: 1.35;
}
.sh-notice-banner .sh-notice-text {
  font-size: 11px;
  line-height: 1.4;
  color: var(--t3);
}
.sh-notice-banner .sh-notice-close {
  flex-shrink: 0;
  border: none;
  background: transparent;
  color: var(--t3);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  padding: 3px 5px;
  border-radius: 6px;
}
.sh-notice-banner .sh-notice-close:hover {
  background: rgba(127, 127, 127, .15);
  color: var(--t1);
}

@media (max-width: 768px) {
  .sh-notice-banner {
    left: 12px;
    right: 12px;
    bottom: calc(var(--mobile-nav-h) + env(safe-area-inset-bottom, 0px) + 12px + var(--notice-offset, 0px));
    max-width: none;
  }
}

.wish-overlay {
  position: fixed;
  inset: 0;
  z-index: 500;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .3s;
}
.wish-overlay.on {
  opacity: 1;
  pointer-events: auto;
}
.wish-modal {
  position: relative;
  width: min(420px, 100%);
  background: var(--card);
  border: 1px solid var(--card-bdr);
  border-radius: 24px;
  padding: 34px 30px 28px;
  text-align: center;
  box-shadow: 0 24px 70px rgba(0, 0, 0, .45), 0 0 0 1px rgba(162, 146, 255, .25), 0 0 50px -6px rgba(110, 93, 216, .6);
  transform: scale(.92) translateY(14px);
  transition: transform .4s var(--spring), opacity .3s;
}
.wish-overlay.on .wish-modal {
  transform: none;
}
.wish-icon {
  font-size: 46px;
  margin-bottom: 8px;
  filter: drop-shadow(0 4px 14px rgba(110, 93, 216, .5));
}
.wish-title {
  font-weight: 800;
  font-size: 19px;
  margin: 2px 0 16px;
  letter-spacing: .2px;
  background: linear-gradient(135deg, #1976D2 0%, #64B5F6 50%, #6A1B9A 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}
.wish-text {
  font-size: 14.5px;
  line-height: 1.7;
  color: var(--t2);
  margin-bottom: 16px;
}
.wish-sign {
  font-size: 12.5px;
  color: var(--t3);
  font-style: italic;
  margin-bottom: 24px;
}
.wish-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: linear-gradient(135deg, var(--purple) 0%, #1976D2 100%);
  color: #fff;
  border: none;
  padding: 13px 32px;
  font-weight: 800;
  font-size: 14.5px;
  border-radius: 100px;
  cursor: pointer;
  box-shadow: 0 6px 20px rgba(110, 93, 216, .45);
  transition: all .25s var(--spring);
}
.wish-btn:hover {
  transform: translateY(-2px) scale(1.03);
}
@media (max-width: 480px) {
  .wish-modal {
    padding: 28px 22px 24px;
  }
}

@media (max-width: 420px) {
  .language-update-toast {
    width: calc(100vw - 28px);
    padding: 14px;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: start;
  }

  .language-update-toast #languageUpdateDismiss {
    grid-column: 2;
    justify-self: start;
    min-width: 76px;
    margin-top: 4px;
  }
}

/* ── MOBILE MINI TOP BAR (in layout flow, not over scroll content) ── */
.mobile-mini {
  display: none;
}
@media (max-width: 768px) {
  /* Exam: always mini bar on mobile (no :has() — survives older browsers + stale shell HTML) */
  body.tahoe-exam .exam-app > .tb {
    display: none !important;
  }

  body.tahoe-exam .exam-app > .mobile-mini,
  body.tahoe-exam .exam-app > #mobileMiniTopbar {
    display: block !important;
  }

  /* Shared mini top bar — hide desktop titlebar whenever mini bar is in the shell */
  .win:has(#mobileMiniTopbar) > .tb,
  .exam-app:has(#mobileMiniTopbar) > .tb,
  .notes-app:has(#mobileMiniTopbar) > .tb {
    display: none !important;
  }

  .win:has(#mobileMiniTopbar) > .mobile-mini,
  .exam-app:has(#mobileMiniTopbar) > .mobile-mini,
  .notes-app:has(#mobileMiniTopbar) > .mobile-mini {
    display: block !important;
  }

  html.has-mobile-mini .win {
    display: flex;
    flex-direction: column;
  }

  /* Single unified mobile header — replaces stacked titlebar + mini bar overlay */
  html.has-mobile-mini body.tahoe-app .tb {
    display: none !important;
  }

  html.has-mobile-mini body.tahoe-app .win:not(:has(#mobileMiniTopbar))::before {
    content: "";
    display: block;
    flex: 0 0 auto;
    height: var(--mobile-mini-h, 46px);
    background: var(--tb-bg);
    border-bottom: 1px solid var(--tb-bdr);
    view-transition-name: app-tb;
  }

  html.has-mobile-mini body.tahoe-exam .exam-app:not(:has(#mobileMiniTopbar))::before {
    content: "";
    display: block;
    flex: 0 0 auto;
    height: var(--mobile-mini-h, 46px);
    background: var(--tb-bg);
    border-bottom: 1px solid var(--tb-bdr);
    view-transition-name: app-tb;
  }

  html.has-mobile-mini body.tahoe-exam .exam-app {
    display: flex;
    flex-direction: column;
    height: var(--app-h, 100dvh);
    min-height: var(--app-h, 100dvh);
    max-height: var(--app-h, 100dvh);
  }

  html.pwa-standalone html.has-mobile-mini body.tahoe-exam .exam-app {
    height: 100%;
    min-height: 100%;
    max-height: 100%;
  }

  html.has-mobile-mini body.tahoe-exam .exam-app .tb {
    display: none !important;
  }

  html.has-mobile-mini body.tahoe-exam .exam-app .body {
    flex: 1;
    min-height: 0;
  }

  html.has-mobile-mini body.tahoe-notes .notes-app:not(:has(#mobileMiniTopbar))::before {
    content: "";
    display: block;
    flex: 0 0 auto;
    height: var(--mobile-mini-h, 46px);
    background: var(--tb-bg);
    border-bottom: 1px solid var(--tb-bdr);
  }

  html.has-mobile-mini body.tahoe-notes .notes-app {
    display: flex;
    flex-direction: column;
  }

  html.has-mobile-mini body.tahoe-notes .notes-app .tb {
    display: none !important;
  }

  html.has-mobile-mini body.tahoe-notes .notes-app .notes-body,
  html.has-mobile-mini body.tahoe-notes .notes-app .body {
    flex: 1;
    min-height: 0;
  }

  html.has-mobile-mini .mobile-mini {
    display: block;
    position: relative;
    flex: 0 0 auto;
    width: 100%;
    z-index: 120;
    margin: 0;
    padding: max(8px, env(safe-area-inset-top, 0px)) 12px 7px;
    border-radius: 0;
    border: none;
    border-bottom: 1px solid var(--tb-bdr);
    background: var(--tb-bg);
    backdrop-filter: blur(24px);
    -webkit-backdrop-filter: blur(24px);
    box-shadow: none;
    isolation: isolate;
  }

  html.has-mobile-mini .body,
  html.has-mobile-mini .body-area {
    flex: 1;
    min-height: 0;
  }

  .mm-row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 8px;
  }

  .mm-lead,
  .mm-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
  }

  .mobile-mini .ham {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    flex-shrink: 0;
  }

  .mobile-mini .ham .material-symbols-rounded {
    font-size: 22px;
  }

  /* 44×26 keeps the switch in proportion with the 32px pills beside it — 50×30
     made it the widest thing in the row. Hit area stays 44px via ::after. */
  .mobile-mini #themeBtn.theme-pill {
    width: 44px !important;
    height: 26px !important;
    min-width: 44px !important;
    min-height: 26px !important;
    padding: 2px !important;
    flex-shrink: 0;
  }

  .mobile-mini #themeBtn.theme-pill .material-symbols-rounded {
    width: 20px !important;
    height: 20px !important;
  }

  /* 44px track − 2px border − 4px padding − 20px knob = 18px of travel. */
  .mobile-mini #themeBtn.theme-pill[aria-pressed="true"] .material-symbols-rounded {
    transform: translateX(18px) !important;
  }

  .mobile-mini .tb-btn:not(#themeBtn):not(.ham) {
    width: 32px;
    height: 32px;
    flex-shrink: 0;
  }

  .mobile-mini .tb-btn:not(#themeBtn):not(.ham) .material-symbols-rounded {
    font-size: 18px;
  }

  /* The mobile header is deliberately compact — the theme switch renders 42×24,
     the profile link 30px tall and the BM/EN buttons ~36px, all under the 44px
     tap-target guideline. Extend each one's hit area with a centred invisible
     overlay so they stay visually compact but are comfortably tappable; using
     a real min-height here would make the whole header taller. */
  .mobile-mini #themeBtn.theme-pill,
  .mobile-mini .mm-user,
  .mobile-mini .mm-mission,
  .mobile-mini .sh-lang-switch button,
  .mobile-mini .sh-lang-switch a {
    position: relative;
  }

  .mobile-mini #themeBtn.theme-pill::after,
  .mobile-mini .mm-user::after,
  .mobile-mini .mm-mission::after,
  .mobile-mini .sh-lang-switch button::after,
  .mobile-mini .sh-lang-switch a::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    height: 100%;
    min-height: 44px;
  }

  /* The theme switch is only 42px wide — widen its hit area too. */
  .mobile-mini #themeBtn.theme-pill::after {
    left: -2px;
    right: -2px;
  }

  .mm-user {
    min-width: 0;
    flex: 1;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    text-decoration: none;
    color: var(--t1);
  }
  .mm-avatar {
    width: 30px;
    height: 30px;
    /* Circular, matching the pill language switch, theme toggle and mission
       chip beside it — a 9px squircle was the last shape in the row that did
       not belong to the same family. */
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: 700;
    color: var(--purple);
    background: var(--purple-l);
    border: 1px solid color-mix(in srgb, var(--purple) 26%, transparent);
    flex-shrink: 0;
  }
  .mm-copy {
    min-width: 0;
    /* Without grow this sized to its content and left the space freed up in
       .mm-user unused, so the name and XP line ellipsised while ~9px sat empty
       beside them. min-width:0 still lets it shrink below content width. */
    flex: 1;
    display: flex;
    flex-direction: column;
    line-height: 1.15;
  }
  .mm-name {
    font-size: 13px;
    font-weight: 700;
    color: var(--t1);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .mm-meta {
    margin-top: 1px;
    font-size: 10.5px;
    color: var(--t3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /* Compact 32px cluster: at 40px these pills filled most of the 55px header
     content box and read as oversized. Safe to shrink because each control
     keeps a 44px invisible hit area via its ::after overlay. */
  .mm-mission {
    min-width: 44px;
    min-height: 32px;
    height: 32px;
    border: 1px solid color-mix(in srgb, var(--purple) 30%, transparent);
    background: color-mix(in srgb, var(--purple) 12%, transparent);
    border-radius: 999px;
    /* Was 0 9px. The row is a fixed 351px on a 375px screen and the name/XP
       column was being squeezed to 70px, too narrow for the meta line. min-width
       still holds the 44px tap target, so trimming the horizontal padding hands
       ~12px back to that column without shrinking the chip below its hit area. */
    padding: 0 4px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--purple);
    font-family: var(--font);
    font-size: 11px;
    font-weight: 700;
    cursor: pointer;
    flex-shrink: 0;
    line-height: 1;
  }
  .mm-mission .material-symbols-rounded {
    font-size: 15px;
  }
  .mm-mission-label {
    display: none;
  }
  .mm-mission #mmMissionTxt {
    white-space: nowrap;
  }
  .mm-progress {
    margin-top: 7px;
    height: 3px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--t3) 20%, transparent);
    overflow: hidden;
  }

  /* ── Slim header while a question is on screen ──
     During an active exam this bar is pure overhead sitting above all 40
     questions — on a 667px-tall phone it costs ~20% of the viewport and
     pushed the last option below the fold. Drop the identity block, the
     mission chip and the XP bar; keep the hamburger, the avatar (still a
     link to the profile) and the language/theme controls, so nothing
     becomes unreachable mid-exam. Restored the moment the exam ends. */
  html.sh-exam-active .mobile-mini {
    padding-top: 6px;
    padding-bottom: 6px;
  }
  html.sh-exam-active .mm-copy,
  html.sh-exam-active .mm-mission,
  html.sh-exam-active .mm-progress {
    display: none;
  }
  html.sh-exam-active .mm-avatar {
    width: 26px;
    height: 26px;
    font-size: 11px;
  }
  .mm-progress-fill {
    width: 0%;
    height: 100%;
    border-radius: inherit;
    background: linear-gradient(90deg, var(--purple), var(--teal));
    transition: width 260ms var(--ease);
  }
}

/* ── LOGIN SPECIFIC ── */
.win-body, .login-body { padding: 28px 28px 24px; }
.tb-theme { margin-left: auto; width: 28px; height: 28px; border-radius: 6px; background: none; border: none; cursor: pointer; color: var(--t2); display: flex; align-items: center; justify-content: center; transition: background 0.15s; }
.tb-theme:hover { background: rgba(255, 255, 255, 0.08); }
[data-theme="light"] .tb-theme:hover { background: rgba(0, 0, 0, 0.05); }
.field-lbl { display: block; font-size: 12px; font-weight: 600; color: var(--t2); margin-bottom: 6px; }
.field-wrap { position: relative; display: flex; align-items: center; }
.field-icon { position: absolute; left: 12px; display: flex; color: var(--t3); pointer-events: none; }
.field-icon .material-symbols-rounded { font-size: 18px; }
.field-wrap .field-input { padding-left: 40px; }
.field-wrap .field-input[type="password"], .field-wrap .field-input[type="text"] { padding-right: 44px; }
.alert { display: flex; align-items: center; gap: 8px; }
.alert .material-symbols-rounded { font-size: 18px; flex-shrink: 0; }
.auth-hint { font-size: 12px; color: var(--t3); text-align: center; margin-top: 10px; }
.login-after {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin-top: 16px;
  text-align: center;
}
.login-after .auth-hint { margin-top: 0; font-size: 11px; color: var(--t3); }
.login-after .support { margin-top: 0; font-size: 12px; line-height: 1.5; }
.support { text-align: center; font-size: 12px; color: var(--t3); margin-top: 20px; line-height: 1.6; }
.support a { color: var(--purple); text-decoration: none; font-weight: 600; }
.submit-btn { width: 100%; margin-top: 6px; }
.submit-btn .material-symbols-rounded { font-size: 18px; pointer-events: auto; }
.win-foot {
  padding: 10px 20px max(12px, env(safe-area-inset-bottom));
  border-top: 1px solid var(--tb-bdr);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-shrink: 0;
  font-size: 11px;
  color: var(--t3);
  background: transparent;
  border-radius: 0 0 var(--win-r) var(--win-r);
}
.foot-badge { display: flex; align-items: center; gap: 5px; min-width: 0; }
.foot-badge .material-symbols-rounded { font-size: 14px; color: var(--teal); flex-shrink: 0; }
.foot-admin { display: flex; align-items: center; gap: 5px; color: var(--t3); text-decoration: none; font-size: 11px; transition: color 0.15s; flex-shrink: 0; white-space: nowrap; }
.foot-admin:hover { color: var(--purple); }
.foot-admin .material-symbols-rounded { font-size: 14px; }
.brand { display: flex; align-items: center; gap: 14px; margin-bottom: 24px; text-align: left; }
.brand-text { text-align: left; }
.brand-mark {
  width: 52px;
  height: 52px;
  border-radius: 14px;
  background: var(--purple-l);
  border: 1px solid rgba(108, 71, 208, 0.25);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  flex-shrink: 0;
  overflow: hidden;
}
.brand-mark--logo {
  width: 56px;
  height: 56px;
  background: transparent;
  border: none;
  border-radius: 15px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.28), 0 0 0 1px rgba(255, 255, 255, 0.06);
}
.brand-mark img,
.sb-bmark img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.brand-mark .material-symbols-rounded { font-size: 26px; color: var(--purple); }
.brand-name { font-size: 22px; font-weight: 700; letter-spacing: -0.4px; color: var(--t1); }
.brand-name em { color: var(--purple); font-style: normal; }
.brand-tag { font-size: 13px; color: var(--t3); margin-top: 4px; }
.win-h { font-size: 18px; font-weight: 700; color: var(--t1); margin-bottom: 4px; }
.win-h em { color: var(--purple); font-style: normal; }
.win-sub { font-size: 13px; color: var(--t3); margin-bottom: 20px; }

.login-features { display: flex; flex-wrap: wrap; gap: 8px; margin: -8px 0 20px; }
.login-feature { display: flex; align-items: center; gap: 6px; min-width: 0; padding: 6px 10px; border-radius: 999px; background: var(--sb-hover); border: 1px solid var(--sb-bdr); font-size: 11.5px; font-weight: 600; color: var(--t2); }
.login-feature .material-symbols-rounded { font-size: 15px; color: var(--purple); flex-shrink: 0; }

/* Fullscreen layout on mobile; window chrome desktop-only */
@media (max-width: 768px) {
  /* Desktop titlebar fallback for pages without mini bar — never on exam (exam uses tahoe-exam.css hide) */
  body.tahoe-app:not(.tahoe-exam) .win:not(:has(#mobileMiniTopbar)) .tb {
    display: grid;
    grid-template-columns: auto auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 6px;
    padding: 0 8px;
  }

  body.tahoe-app .tb-spacer {
    display: none;
  }

  body.tahoe-app .tb-center {
    position: static;
    left: auto;
    transform: none;
    min-width: 0;
    max-width: none;
    display: flex;
    align-items: center;
    gap: 6px;
  }

  body.tahoe-app .tb-title {
    font-size: 12.5px;
    max-width: 100%;
  }

  body.tahoe-app .tb-app-icon,
  body.tahoe-app .tb-app-ic {
    display: none;
  }

  body.tahoe-app .win:not(.win--fullscreen) {
    width: 100%;
    max-width: 100vw;
    margin: 0;
    border-radius: 0;
    border: none;
    box-shadow: none;
    height: var(--app-h, 100dvh);
    min-height: var(--app-h, 100dvh);
    max-height: var(--app-h, 100dvh);
  }

  html.pwa-standalone body.tahoe-app .win:not(.win--fullscreen),
  html.pwa-standalone .win:not(.win--login):not(.win--fullscreen) {
    height: 100%;
    min-height: 100%;
    max-height: 100%;
  }

  /* Mobile mini bar is the only top chrome on tahoe-app pages */
  body.tahoe-app .tb {
    padding-top: env(safe-area-inset-top, 0px);
  }

  html.has-mobile-mini body.tahoe-app .tb {
    padding-top: 0;
  }

  body.tahoe-app .win:not(.win--fullscreen)::before {
    display: none;
  }

  body.tahoe-login {
    padding: max(10px, env(safe-area-inset-top)) 12px max(10px, env(safe-area-inset-bottom));
    overflow: hidden;
    align-items: center;
    justify-content: center;
    min-height: 100dvh;
    height: 100dvh;
    box-sizing: border-box;
  }

  .win--login {
    width: min(var(--win-w), calc(100vw - 24px));
    min-height: auto;
    height: auto;
    max-height: calc(100dvh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px) - 20px);
    margin: 0 auto;
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    border-radius: var(--win-r);
    border: 1px solid var(--glass-bdr);
    box-shadow: var(--glass-sh), inset 0 1.5px 0 var(--glass-hi), inset 0 -1px 0 rgba(255, 255, 255, 0.05);
    background: var(--glass-bg-solid);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  .win--login::before {
    display: block;
    border-radius: var(--win-r);
  }

  .win--login .win-body {
    flex: 0 0 auto;
    min-height: auto;
    padding: 22px 20px 14px;
  }

  .win--login .login-after {
    gap: 6px;
    margin-top: 12px;
    padding-bottom: 2px;
  }

  .win--login .win-foot {
    position: relative;
    z-index: 2;
    padding: 10px 16px max(14px, env(safe-area-inset-bottom));
    background: var(--glass-bg-solid);
  }

  .win--login .pwa-login-link {
    min-height: 38px;
    padding: 7px 10px;
  }

  /* Mobile login inherits unified titlebar grid from .win--login .tb above */
  .win--login .tb {
    gap: 5px;
    padding: 0 10px;
  }

  .win--login .tb-center {
    font-size: 13.5px;
  }

  .win--login .tls {
    gap: 2px;
  }

  .win--login .tl {
    width: 16px;
    height: 16px;
  }

  .win--login .tb-theme {
    width: 40px;
    height: 40px;
  }

  .tb-theme {
    width: 44px;
    height: 44px;
    border-radius: 10px;
  }

  .field-input, .form-input, input[type="text"], input[type="email"], input[type="password"], input[type="number"], select, textarea {
    height: 44px;
  }

  .submit-btn, .btn {
    min-height: 44px;
  }

  .pw-toggle {
    width: 44px;
    height: 44px;
    right: 4px;
  }

  .support a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 2px 4px;
  }

  .foot-admin {
    display: inline-flex;
    align-items: center;
    min-height: 36px;
    padding: 2px 0;
  }
}

@media (max-width: 440px) {
  .win--login .brand { gap: 10px; }
  .win--login .brand-mark--logo { width: 50px; height: 50px; border-radius: 13px; }
  .win--login .brand-mark { width: 46px; height: 46px; border-radius: 12px; }
  .win--login .brand-mark .material-symbols-rounded { font-size: 22px; }
  .win--login .brand-name { font-size: 18px; }
  .win--login .brand-tag { font-size: 12px; }
}

@media (max-width: 360px) {
  .win--login .tb {
    grid-template-columns: minmax(0, 1fr) auto auto;
  }

  .win--login .tls {
    display: none;
  }
}

@media (max-width: 768px) and (max-height: 760px) {
  body.tahoe-login {
    padding-top: max(6px, env(safe-area-inset-top));
    padding-bottom: max(6px, env(safe-area-inset-bottom));
  }

  .win--login {
    max-height: calc(100dvh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px) - 12px);
  }

  .win--login .win-body { padding: 15px 18px 10px; }
  .win--login .brand { gap: 9px; margin-bottom: 12px; }
  .win--login .brand-mark--logo { width: 44px; height: 44px; border-radius: 12px; }
  .win--login .brand-name { font-size: 17px; }
  .win--login .brand-tag { margin-top: 2px; font-size: 11px; }
  .win--login .win-h { font-size: 17px; margin-bottom: 3px; }
  .win--login .win-sub { font-size: 12px; line-height: 1.4; margin-bottom: 13px; }
  .win--login .login-features { gap: 5px; margin: -2px 0 13px; }
  .win--login .login-feature { padding: 4px 8px; font-size: 10.5px; }
  .win--login .field { margin-bottom: 10px; }
  .win--login .login-after { gap: 2px; margin-top: 7px; }
  .win--login .login-after .support { font-size: 11px; line-height: 1.3; }
  .win--login .pwa-login-link { min-height: 34px; padding-top: 5px; padding-bottom: 5px; }
  .win--login .win-foot { padding: 7px 14px max(9px, env(safe-area-inset-bottom)); }
}
.pw-wrap { position: relative; }
.pw-toggle { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); background: none; border: none; cursor: pointer; color: var(--t3); width: 32px; height: 32px; border-radius: 6px; display: flex; align-items: center; justify-content: center; touch-action: manipulation; }
.pw-toggle:hover { background: rgba(255, 255, 255, 0.08); }
.spinner { width: 16px; height: 16px; border: 2px solid rgba(255, 255, 255, 0.3); border-top-color: #fff; border-radius: 50%; animation: spin 0.7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

@media (max-width: 768px) {
  .pw-toggle {
    width: 44px;
    height: 44px;
    right: 4px;
    border-radius: 10px;
  }
}

/* PWA standalone — edge-to-edge fullscreen shell */
html.pwa-standalone,
html.pwa-standalone body {
  touch-action: manipulation;
}

@media (max-width: 768px) {
  html.pwa-standalone {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    min-height: 100%;
    min-height: 100dvh;
    overflow: hidden;
    background: var(--tb-bg);
  }

  html.pwa-standalone body.tahoe-app,
  html.pwa-standalone body.tahoe-notes,
  html.pwa-standalone body.tahoe-exam,
  html.pwa-standalone body.tahoe-app.tahoe-exam {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    min-height: 0;
    max-height: none;
    overflow: hidden;
    padding: 0;
    margin: 0;
  }

  html.pwa-standalone body.tahoe-app .win:not(.win--fullscreen),
  html.pwa-standalone body.tahoe-notes .notes-app,
  html.pwa-standalone body.tahoe-exam .exam-app,
  html.pwa-standalone .win:not(.win--login):not(.win--fullscreen) {
    width: 100%;
    height: 100%;
    min-height: 100%;
    max-height: 100%;
  }

  html.pwa-standalone .mobile-mini {
    padding-top: max(6px, env(safe-area-inset-top, 0px));
  }

  /* Safe-area fill is handled by .mobile-nav padding-bottom in standalone */
  html.pwa-standalone::after {
    display: none;
  }

  html.pwa-standalone body.tahoe-login {
    position: fixed;
    inset: 0;
    width: 100%;
    height: var(--app-h, 100dvh);
    min-height: var(--app-h, 100dvh);
    max-height: var(--app-h, 100dvh);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: max(10px, env(safe-area-inset-top)) 12px max(10px, env(safe-area-inset-bottom));
    box-sizing: border-box;
    background: var(--a5);
  }

  html.pwa-standalone.pwa-login-vv .win--login {
    width: min(var(--win-w), calc(100vw - 24px));
    max-height: calc(var(--app-h, 100dvh) - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px) - 20px);
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    flex-shrink: 1;
  }
}

@media (max-width: 768px) and (display-mode: standalone) {
  .mobile-nav {
    bottom: 0 !important;
    align-items: flex-start;
  }
}

/* ── ADMIN TABLES ── */
.table-wrap { overflow-x: auto; border-radius: var(--r-md); border: 1px solid var(--card-bdr); background: var(--card); }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { padding: 10px 14px; text-align: left; border-bottom: 1px solid var(--card-bdr); }
th { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--t3); background: var(--panel2); }
tr:last-child td { border-bottom: none; }
tr:hover td { background: var(--sb-hover); }

.badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: var(--r-full);
  font-size: 11px;
  font-weight: 600;
}

.badge-success { background: var(--green-l); color: var(--green); }
.badge-warning { background: var(--amber-l); color: var(--amber); }
.badge-danger { background: var(--error-bg); color: var(--error); }

/* ── SKELETON LOADING ── */
.skel { background: linear-gradient(90deg, var(--sb-hover) 25%, rgba(255, 255, 255, 0.08) 50%, var(--sb-hover) 75%); background-size: 200% 100%; animation: skelShimmer 1.4s ease infinite; border-radius: var(--r-sm); }
@keyframes skelShimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* ── UTILITIES ── */
.hidden { display: none !important; }
.text-center { text-align: center; }
.text-muted { color: var(--t3); }
.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.gap-sm { gap: 8px; }
.gap-md { gap: 14px; }
.mt-sm { margin-top: 8px; }
.mt-md { margin-top: 16px; }
.mb-md { margin-bottom: 16px; }

/* ── BACKDROP FILTER FALLBACKS ── */
@supports not (backdrop-filter: blur(1px)) {
  .win { background: #f4f4f6; }
  .tb { background: #e8e8ec; }
  .sb, .sidebar { background: #d8d8de; }
  .main { background: #f0f0f4; }
  .spot-box, .modal { background: #f4f4f6; }
  .win--login { background: var(--glass-bg-solid); }
  [data-theme="dark"] .win { background: #18181c; }
  [data-theme="dark"] .tb { background: #1c1c20; }
  [data-theme="dark"] .sb, [data-theme="dark"] .sidebar { background: #222226; }
  [data-theme="dark"] .main { background: #141418; }
}

/* ── Selected-subject indicators (shared: Nota, Arcade) ── */
.tb-subj-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-left: 10px;
  padding: 4px 11px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 750;
  letter-spacing: -0.01em;
  color: #fff;
  background: linear-gradient(135deg, #7c3aed 0%, #5a35be 100%);
  box-shadow: 0 2px 9px rgba(124, 58, 237, 0.32), inset 0 1px 0 rgba(255, 255, 255, 0.26);
  white-space: nowrap;
  cursor: default;
  --pulse-ring: rgba(124, 58, 237, 0.45);
}
.tb-subj-pill .material-symbols-rounded { font-size: 15px; flex-shrink: 0; }
.tb-subj-pill #tbSubjText {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 240px;
}

/* Make the section subject badge read clearly as the active subject */
#secCount {
  padding: 4px 11px;
  border-radius: 999px;
  font-weight: 800;
  color: #fff;
  background: linear-gradient(135deg, #7c3aed 0%, #5a35be 100%);
  border: none;
  box-shadow: 0 2px 8px rgba(124, 58, 237, 0.28);
  --pulse-ring: rgba(124, 58, 237, 0.45);
}

.subj-pulse { animation: subjPulse 0.6s var(--ease, cubic-bezier(.2,.8,.2,1)); }
@keyframes subjPulse {
  0%   { transform: scale(1); box-shadow: 0 0 0 0 var(--pulse-ring, rgba(124, 58, 237, 0.45)); }
  40%  { transform: scale(1.1); box-shadow: 0 0 0 6px transparent; }
  100% { transform: scale(1); }
}

.subj-toast {
  position: fixed;
  left: 50%;
  bottom: 86px;
  transform: translateX(-50%) translateY(12px);
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 16px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  color: #fff;
  background: rgba(18, 20, 28, 0.92);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.38);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  opacity: 0;
  pointer-events: none;
  z-index: 9999;
  transition: opacity 0.25s ease, transform 0.28s var(--ease, cubic-bezier(.2,.8,.2,1));
}
.subj-toast .material-symbols-rounded { font-size: 18px; color: #34d399; }
.subj-toast b { font-weight: 800; }
.subj-toast.on { opacity: 1; transform: translateX(-50%) translateY(0); }

@media (max-width: 600px) {
  .tb-center:has(.tb-subj-pill) .tb-title { display: none; }
  .tb-subj-pill { margin-left: 6px; font-size: 11px; padding: 3px 9px; }
  .tb-subj-pill .material-symbols-rounded { font-size: 14px; }
  .tb-subj-pill #tbSubjText { max-width: 42vw; }
  .subj-toast { bottom: 78px; font-size: 12px; padding: 8px 14px; max-width: 90vw; }
}
/* ── EN/BM language switch ─────────────────────────────────────────────── */
.sh-lang-switch{
  display:inline-flex;
  flex:0 0 auto;
  align-items:center;
  gap:2px;
  padding:3px;
  border:1px solid var(--card-bdr);
  border-radius:var(--r-full);
  background:color-mix(in srgb,var(--card) 84%,transparent);
  box-shadow:0 1px 4px rgba(20,15,50,.08);
  font-family:var(--font);
}
.sh-lang-switch button,
.sh-lang-switch a{
  min-width:34px;
  height:26px;
  padding:0 8px;
  border:0;
  border-radius:var(--r-full);
  color:var(--t3);
  background:transparent;
  font:800 11px/1 var(--font);
  letter-spacing:.04em;
  cursor:pointer;
  text-decoration:none;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  position:relative;
  z-index:1;
  touch-action:manipulation;
  -webkit-tap-highlight-color:transparent;
  transition:background var(--dur1) var(--ease),color var(--dur1) var(--ease),box-shadow var(--dur1) var(--ease);
}
.sh-lang-switch button:hover,
.sh-lang-switch a:hover{color:var(--t1);background:var(--glass-bg)}
/* Flat accent, not a purple→blue gradient: every other active control in the
   app (subject chips, section badges) fills with var(--purple), and the blue
   shift made this one read as a different design language in the same row. */
.sh-lang-switch button[aria-pressed="true"],
.sh-lang-switch a[aria-pressed="true"]{
  color:#fff;
  background:var(--purple);
  box-shadow:0 2px 7px color-mix(in srgb,var(--purple) 30%,transparent);
}
/* A box-shadow ring rather than an outline: iOS Safari draws `outline` as a
   rectangle even on a fully-rounded element, so after tapping BM/EN the pill
   sat inside a hard square box. box-shadow follows the border-radius. */
.sh-lang-switch button:focus-visible,
.sh-lang-switch a:focus-visible{
  outline:none;
  box-shadow:0 0 0 2px color-mix(in srgb,var(--purple) 55%,transparent);
}
.sh-lang-switch--mobile{display:none}
.sh-lang-switch--floating{position:fixed;z-index:10000;top:max(12px,env(safe-area-inset-top));right:12px}
.win--login>.tb .sh-lang-switch{margin:0}
.sh-lang-changing .sh-lang-switch{opacity:.65;pointer-events:none}

@media(max-width:768px){
  .tb-right .sh-lang-switch{margin-right:2px}
  .sh-lang-switch{padding:2px;gap:1px}
  .sh-lang-switch button,
  .sh-lang-switch a{min-width:36px;height:34px;padding:0 7px;font-size:10.5px}
  /* 32px tall overall (28 + 2px padding + 2px border), matching the mission
     chip and theme toggle. At 40px this was the bulkiest thing in the header.
     The 44px hit area is preserved by the ::after overlay. */
  html.has-mobile-mini .sh-lang-switch--mobile{display:inline-flex;padding:1px}
  html.has-mobile-mini .sh-lang-switch--mobile button,
  html.has-mobile-mini .sh-lang-switch--mobile a{min-width:32px;height:28px;padding:0 7px;font-size:10.5px}
}

@media(max-width:360px){
  html.has-mobile-mini .mobile-mini{padding-left:8px;padding-right:8px}
  html.has-mobile-mini .mm-row{gap:6px}
  html.has-mobile-mini .mm-actions{gap:4px}
  html.has-mobile-mini .sh-lang-switch--mobile button,
  html.has-mobile-mini .sh-lang-switch--mobile a{min-width:31px;padding:0 5px}
  /* No theme-pill override needed here: the switch is already 44×26 across all
     mobile widths, so a fourth competing size rule would only invite drift. */
  html.has-mobile-mini .mm-mission{min-width:42px;padding:0 7px}
  html.has-mobile-mini .mm-avatar{width:28px;height:28px}
  html.has-mobile-mini .mm-meta{display:none}
}
