/* IEDEP quiz panel — navy system tokens (light/dark) as RGB channels.
   Colors are consumed by tailwind-theme.js as rgb(var(--token) / <alpha-value>),
   so every bg / text / border utility flips automatically when <html> gets .dark.
   Generated by scripts/gen_theme.mjs from the navy palette (design/DESIGN.md):
   navy primary, exam-blue secondary, amber / red / green semantics, slate
   neutrals. Edit the generator, not per screen. */
:root {
  color-scheme: light;
  --on-error: 255 255 255;
  --error-dim: 185 28 28;
  --on-tertiary: 255 255 255;
  --primary: 30 58 138;
  --on-secondary-fixed: 23 37 84;
  --inverse-surface: 30 41 59;
  --tertiary-dim: 146 64 14;
  --secondary-container: 224 235 255;
  --on-background: 15 23 42;
  --on-primary: 255 255 255;
  --inverse-primary: 169 188 245;
  --tertiary: 180 83 9;
  --outline-variant: 226 232 240;
  --surface-variant: 241 245 249;
  --outline: 125 139 161;
  --on-tertiary-fixed: 69 26 3;
  --surface-tint: 30 58 138;
  --primary-container: 227 233 251;
  --primary-fixed: 227 233 251;
  --tertiary-container: 254 243 199;
  --surface-bright: 255 255 255;
  --secondary: 37 99 235;
  --error-container: 254 226 226;
  --on-primary-container: 30 58 138;
  --primary-dim: 23 46 112;
  --tertiary-fixed: 253 230 138;
  --secondary-dim: 29 78 216;
  --surface-dim: 226 232 240;
  --secondary-fixed-dim: 191 219 254;
  --surface-container: 241 245 249;
  --on-secondary: 255 255 255;
  --on-surface: 15 23 42;
  --on-primary-fixed-variant: 30 58 138;
  --on-error-container: 153 27 27;
  --surface: 248 250 252;
  --on-tertiary-container: 146 64 14;
  --on-tertiary-fixed-variant: 146 64 14;
  --secondary-fixed: 219 234 254;
  --on-secondary-container: 30 64 175;
  --error: 220 38 38;
  --on-primary-fixed: 15 31 77;
  --surface-container-low: 245 247 250;
  --surface-container-highest: 226 232 240;
  --tertiary-fixed-dim: 217 119 6;
  --primary-fixed-dim: 188 202 243;
  --background: 248 250 252;
  --surface-container-lowest: 255 255 255;
  --on-secondary-fixed-variant: 30 64 175;
  --inverse-on-surface: 241 245 249;
  --surface-container-high: 233 238 244;
  --on-surface-variant: 82 96 117;
  --success: 21 128 61;
  --on-success: 255 255 255;
  --success-container: 220 252 231;
  --on-success-container: 22 101 52;
}

html.dark {
  color-scheme: dark;
  --on-error: 69 10 10;
  --error-dim: 239 68 68;
  --on-tertiary: 59 37 3;
  --primary: 169 188 245;
  --on-secondary-fixed: 23 37 84;
  --inverse-surface: 226 232 240;
  --tertiary-dim: 245 158 11;
  --secondary-container: 26 52 102;
  --on-background: 226 232 240;
  --on-primary: 15 31 77;
  --inverse-primary: 30 58 138;
  --tertiary: 251 191 36;
  --outline-variant: 37 49 71;
  --surface-variant: 30 41 59;
  --outline: 100 116 139;
  --on-tertiary-fixed: 69 26 3;
  --surface-tint: 169 188 245;
  --primary-container: 31 50 112;
  --primary-fixed: 227 233 251;
  --tertiary-container: 71 48 10;
  --surface-bright: 39 52 73;
  --secondary: 110 168 251;
  --error-container: 74 23 23;
  --on-primary-container: 223 230 251;
  --primary-dim: 145 168 239;
  --tertiary-fixed: 253 230 138;
  --secondary-dim: 85 150 246;
  --surface-dim: 11 18 32;
  --secondary-fixed-dim: 191 219 254;
  --surface-container: 23 33 53;
  --on-secondary: 11 26 58;
  --on-surface: 226 232 240;
  --on-primary-fixed-variant: 30 58 138;
  --on-error-container: 254 202 202;
  --surface: 11 18 32;
  --on-tertiary-container: 253 230 138;
  --on-tertiary-fixed-variant: 146 64 14;
  --secondary-fixed: 219 234 254;
  --on-secondary-container: 219 234 254;
  --error: 248 113 113;
  --on-primary-fixed: 15 31 77;
  --surface-container-low: 19 28 47;
  --surface-container-highest: 40 53 72;
  --tertiary-fixed-dim: 217 119 6;
  --primary-fixed-dim: 188 202 243;
  --background: 11 18 32;
  --surface-container-lowest: 15 23 42;
  --on-secondary-fixed-variant: 30 64 175;
  --inverse-on-surface: 30 41 59;
  --surface-container-high: 30 41 59;
  --on-surface-variant: 154 168 189;
  --success: 74 222 128;
  --on-success: 5 46 22;
  --success-container: 18 59 38;
  --on-success-container: 187 247 208;
}

/* Base surface + smooth theme transition */
body {
  background-color: rgb(var(--background));
  color: rgb(var(--on-surface));
}
/* The theme flips instantly, on purpose — the way iOS and macOS switch
   appearance. Only the toggle button animates.

   There used to be a `body *` colour cross-fade here. Measured on study-plan
   (~690 elements) it cost ~100-125ms of style recalc per flip versus ~13-20ms
   without, then repainted every element for a further 250ms; background-color
   and color are paint properties, so none of that can go on the compositor.
   It also outranked Tailwind's own `.transition-colors`, retiming every hover
   on the page. A cross-fade whose cost scales with DOM size is the wrong trade
   on the densest screens — snapping is both faster and closer to the platform. */

/* Glassmorphism cards/headers: light frost -> dark frost */
html.dark .glass-card {
  background: rgb(var(--surface-container-lowest) / 0.78) !important;
  border-color: rgb(var(--outline-variant)) !important;
}
html.dark .glass-header {
  background: rgb(var(--surface-container-lowest) / 0.78) !important;
}
html.dark .gold-glow { box-shadow: none; }

/* in_exam custom scrollbar in dark */
html.dark .custom-scrollbar::-webkit-scrollbar-track { background: rgb(var(--surface-container)); }
html.dark .custom-scrollbar::-webkit-scrollbar-thumb { background: rgb(var(--outline-variant)); }
html.dark .custom-scrollbar::-webkit-scrollbar-thumb:hover { background: rgb(var(--outline)); }

/* Theme toggle (injected by theme-toggle.js).
   Floats bottom-left only when the screen provides no [data-theme-toggle-slot];
   slotted screens place it in the sidebar footer instead, so it stops covering
   content that scrolls beneath it. */
#theme-toggle[data-slotted] {
  position: static;
  width: 100%; height: auto;
  justify-content: flex-start;
  gap: .75rem;
  padding: .75rem 1rem;
  border-radius: .875rem;
  border: 0;
  background: transparent;
  box-shadow: none;
  font: inherit;
  font-weight: 700;
  font-size: .875rem;
  color: rgb(var(--on-surface-variant));
}
#theme-toggle[data-slotted]:hover {
  transform: none;
  background: rgb(var(--surface-container));
}
#theme-toggle[data-slotted]:active { transform: scale(.98); }
#theme-toggle[data-slotted]::after {
  content: attr(data-label);
  font: inherit;
}

#theme-toggle {
  position: fixed; bottom: 1rem; left: 1rem; z-index: 60;
  width: 2.75rem; height: 2.75rem; border-radius: 9999px;
  display: flex; align-items: center; justify-content: center;
  background: rgb(var(--surface-container-high));
  color: rgb(var(--on-surface));
  border: 1px solid rgb(var(--outline-variant));
  box-shadow: 0 2px 10px rgba(0,0,0,.18);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform .34s var(--morph-settle), background-color .2s ease;

  /* Per DESIGN.md: ease-out only, no bounce. Reuse the app's existing iOS
     motion vocabulary (injected at :root by interactions.js) rather than
     inventing a competing curve; the fallbacks keep this file standalone.
     The premium feel here comes from the choreography and the expo settle,
     not from overshoot. */
  --morph-settle: var(--ios-ease, cubic-bezier(.16,1,.3,1));   /* ease-out-expo */
  --morph-quick:  var(--ios-spring, cubic-bezier(.22,1,.36,1)); /* ease-out-quint */
}
#theme-toggle:hover { transform: scale(1.06); background: rgb(var(--surface-container-highest)); }
/* Press squash resolves instantly; the release rides the spring back. */
#theme-toggle:active { transform: scale(.88); transition-duration: .1s; }
#theme-toggle:focus-visible { outline: 2px solid rgb(var(--primary)); outline-offset: 2px; }
#theme-toggle svg { width: 1.35rem; height: 1.35rem; overflow: visible; }

/* --- Sun <-> moon morph -------------------------------------------------
   Choreographed rather than simultaneous: the rays retract one by one, the
   disc swells and the mask slides in to carve the crescent slightly behind
   them, and the stars land last. Reversing swaps the order, so the sun's
   rays only spring back out once the crescent has gone.
   Geometry (r/cx/cy) carries units: the spec wants <length-percentage>, and
   while Blink also accepts a bare `9`, other engines are not obliged to. */

/* The whole icon counter-rotates a touch — cheap depth, reads as one object. */
#theme-toggle .icon-morph { transition: transform .6s var(--morph-settle); }
html.dark #theme-toggle .icon-morph { transform: rotate(-14deg); }

#theme-toggle .disc {
  r: 5px;
  transition: r .55s var(--morph-settle);
  transition-delay: 40ms;
}
html.dark #theme-toggle .disc { r: 9px; transition-delay: 90ms; }

#theme-toggle .bite {
  cx: 24px; cy: 4px;
  transition: cx .55s var(--morph-settle), cy .55s var(--morph-settle);
  transition-delay: 40ms;
}
html.dark #theme-toggle .bite { cx: 16px; cy: 6px; transition-delay: 90ms; }

/* Each ray owns its index (--i, set in the markup) so it can rotate about the
   icon centre and retract on its own beat. */
#theme-toggle .ray {
  transform-box: view-box;
  transform-origin: 12px 12px;
  transform: rotate(calc(var(--i) * 45deg));
  opacity: 1;
  transition: transform .55s var(--morph-quick), opacity .25s ease;
  transition-delay: calc(140ms + (7 - var(--i)) * 14ms); /* returning: after the crescent leaves */
}
html.dark #theme-toggle .ray {
  transform: rotate(calc(var(--i) * 45deg + 90deg)) scale(.15);
  opacity: 0;
  transition-delay: calc(var(--i) * 14ms);                /* leaving: immediate, staggered */
}

/* Stars sit in the region the mask carves away, so they only ever appear over
   empty space. They pop in last and vanish first. */
#theme-toggle .star {
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(0);
  opacity: 0;
  transition: transform .4s var(--morph-quick), opacity .2s ease;
}
html.dark #theme-toggle .star {
  transform: scale(1);
  opacity: .9;
  transition-delay: calc(300ms + var(--i) * 70ms);
}

/* Tap ripple. Driven by a class from the JS so it fires on real presses only,
   never on the initial paint. */
#theme-toggle .halo {
  position: absolute; inset: -1px;
  border-radius: 9999px;
  border: 1.5px solid currentColor;
  opacity: 0; pointer-events: none;
}
#theme-toggle.is-toggling .halo { animation: theme-halo .62s ease-out; }
@keyframes theme-halo {
  0%   { opacity: .45; transform: scale(.82); }
  100% { opacity: 0;   transform: scale(1.75); }
}

@media (prefers-reduced-motion: reduce) {
  #theme-toggle, #theme-toggle .icon-morph, #theme-toggle .disc,
  #theme-toggle .bite, #theme-toggle .ray, #theme-toggle .star {
    transition: none;
    transition-delay: 0ms;
  }
  #theme-toggle.is-toggling .halo { animation: none; }
}

/* --- Session chrome, applied before first paint ------------------------
   The server stamps `data-kind` on <html> from the session cookie, so a مهمان
   never sees the student-only nav items appear and then get removed by
   `applyGuestChrome()` a network round-trip later. The JS still runs (it also
   relabels the account line) but by then there is nothing left to hide. */
html[data-kind="guest"] aside nav a[href="/app"],
html[data-kind="guest"] aside nav a[href="/app/exam-builder"],
html[data-kind="guest"] aside nav a[href="/app/study-plan"],
html[data-kind="guest"] aside nav a[href="/app/party"],
html[data-kind="guest"] [data-nav="/app"],
html[data-kind="guest"] [data-nav="/app/exam-builder"],
html[data-kind="guest"] [data-nav="/app/study-plan"],
html[data-kind="guest"] [data-nav="/app/party"],
html[data-kind="guest"] [data-route="/app"],
html[data-kind="guest"] [data-route="/app/exam-builder"],
html[data-kind="guest"] [data-route="/app/study-plan"],
html[data-kind="guest"] [data-route="/app/party"] {
  display: none;
}

/* Mobile: keep form controls at >=16px so iOS Safari does not auto-zoom the
   viewport when a field gains focus. Desktop sizing is untouched. */
@media (max-width: 640px) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]),
  select,
  textarea {
    font-size: 16px;
  }
}

