/* ============================================
   CS MULTIVERSE — Global Design System
   ============================================ */

:root {
  /* Base cosmic palette */
  --bg-void: #050410;
  --bg-deep: #0a0820;
  --bg-elevated: #14122c;
  --bg-glass: rgba(255, 255, 255, 0.04);
  --bg-glass-strong: rgba(255, 255, 255, 0.08);

  --ink-100: #f6f5ff;
  --ink-200: #d8d6f0;
  --ink-300: #a3a0c8;
  --ink-400: #6f6c95;
  --ink-500: #4a4775;
  --ink-line: rgba(255, 255, 255, 0.08);
  --ink-line-strong: rgba(255, 255, 255, 0.16);

  /* Iridescent platform accent */
  --iris-1: oklch(75% 0.18 300);
  --iris-2: oklch(78% 0.16 220);
  --iris-3: oklch(80% 0.16 160);
  --iris-warm: oklch(82% 0.16 60);

  /* Default active world (overridden per world via data-world) */
  --w-h: 300;
  --w-c: 0.2;
  --w-primary: oklch(75% var(--w-c) var(--w-h));
  --w-bright: oklch(85% var(--w-c) var(--w-h));
  --w-deep: oklch(40% 0.16 var(--w-h));
  --w-glow: oklch(75% var(--w-c) var(--w-h) / 0.35);
  --w-tint: oklch(75% var(--w-c) var(--w-h) / 0.12);

  /* Type */
  --font-display: "Space Grotesk", "Inter", system-ui, sans-serif;
  --font-body: "Inter", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, monospace;

  /* Density */
  --d: 1;          /* density multiplier — 1 cinematic, 0.7 compact */
  --space-1: calc(4px * var(--d));
  --space-2: calc(8px * var(--d));
  --space-3: calc(12px * var(--d));
  --space-4: calc(16px * var(--d));
  --space-5: calc(20px * var(--d));
  --space-6: calc(24px * var(--d));
  --space-8: calc(32px * var(--d));
  --space-10: calc(40px * var(--d));
  --space-12: calc(48px * var(--d));
  --space-16: calc(64px * var(--d));

  --r-sm: 8px;
  --r-md: 14px;
  --r-lg: 22px;
  --r-xl: 32px;
  --r-full: 999px;

  /* Theme presets — arcade & glass override these */
  --shell-bg: radial-gradient(ellipse 80% 60% at 20% -10%, oklch(35% 0.15 280 / 0.4), transparent 60%),
              radial-gradient(ellipse 60% 50% at 100% 100%, oklch(40% 0.18 200 / 0.3), transparent 60%),
              radial-gradient(ellipse 50% 40% at 50% 50%, oklch(30% 0.12 320 / 0.2), transparent 70%),
              var(--bg-void);
}

[data-theme="arcade"] {
  --bg-void: #0d0d10;
  --bg-deep: #16161c;
  --bg-elevated: #1f1f28;
  --shell-bg:
    linear-gradient(180deg, #0d0d10 0%, #0a0a0c 100%);
  --iris-1: oklch(72% 0.22 30);
}

[data-theme="glass"] {
  --bg-void: #1a1830;
  --bg-deep: #221f3c;
  --bg-elevated: rgba(255, 255, 255, 0.06);
  --bg-glass: rgba(255, 255, 255, 0.08);
  --bg-glass-strong: rgba(255, 255, 255, 0.16);
  --shell-bg:
    radial-gradient(ellipse 100% 70% at 50% 0%, oklch(60% 0.18 260 / 0.5), transparent 70%),
    radial-gradient(ellipse 80% 60% at 0% 100%, oklch(55% 0.18 320 / 0.4), transparent 70%),
    linear-gradient(180deg, #1a1830, #0e0c1e);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg-void);
  color: var(--ink-100);
  font-family: var(--font-body);
  font-feature-settings: "ss01", "cv11";
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  height: 100%;
  overflow: hidden;
}

html { height: 100%; }

#root {
  position: relative;
  height: 100vh;
  height: 100dvh;
  width: 100vw;
}

/* App fills the real viewport. No fake-device bezel. */
.app-shell {
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--shell-bg);
  overflow: hidden;
}

/* ===== STARFIELD ===== */
.stars {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}
.stars::before, .stars::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(1px 1px at 20% 30%, white, transparent),
    radial-gradient(1px 1px at 70% 60%, white, transparent),
    radial-gradient(1px 1px at 40% 80%, white, transparent),
    radial-gradient(2px 2px at 85% 15%, white, transparent),
    radial-gradient(1px 1px at 15% 75%, white, transparent),
    radial-gradient(1px 1px at 55% 25%, white, transparent),
    radial-gradient(2px 2px at 92% 88%, white, transparent),
    radial-gradient(1px 1px at 33% 55%, white, transparent);
  background-size: 400px 400px;
  background-repeat: repeat;
  opacity: 0.35;
}
.stars::after {
  background-size: 700px 700px;
  opacity: 0.5;
  /* animation: drift removed — animating background-position forces a full-viewport
     repaint every frame. Static starfield is visually equivalent at this opacity. */
}
/* @keyframes drift removed along with the animation above. */

/* ===== Noise overlay =====
   The SVG feTurbulence noise was re-rasterized every frame on every page
   that uses .noise (which is most of them). On phones and integrated GPUs
   this alone was burning ~5-8ms per frame. The aesthetic loss is ~0 at
   the 0.05 opacity we were drawing it at. Kept as an empty rule so any
   stray <div class="noise"> doesn't reflow the layout. */
.noise {
  display: none;
}

/* ===== Top Nav ===== */
.topnav {
  position: relative;
  z-index: 10;
  display: flex;
  align-items: center;
  padding: var(--space-4) var(--space-6);
  gap: var(--space-6);
  border-bottom: 1px solid var(--ink-line);
  /* Dropped backdrop-filter: blur(20px) — tanked frame rate on integrated GPUs.
     A slightly more opaque solid gives the same visual weight without GPU cost. */
  background: linear-gradient(180deg, rgba(10, 8, 32, 0.88), rgba(10, 8, 32, 0.78));
  flex-shrink: 0;
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 17px;
  letter-spacing: -0.01em;
}

.brand-mark {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  background:
    conic-gradient(from 0deg,
      oklch(75% 0.2 300),
      oklch(75% 0.2 220),
      oklch(75% 0.2 160),
      oklch(75% 0.2 60),
      oklch(75% 0.2 300));
  position: relative;
  box-shadow: 0 0 20px oklch(75% 0.2 280 / 0.5);
}
.brand-mark::after {
  content: "";
  position: absolute;
  inset: 6px;
  border-radius: 4px;
  background: var(--bg-void);
}

.nav-pills {
  display: flex;
  gap: var(--space-1);
  margin-left: var(--space-8);
}

.nav-pill {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 13px;
  padding: 8px 14px;
  border-radius: var(--r-full);
  color: var(--ink-300);
  background: transparent;
  border: none;
  cursor: pointer;
  transition: background-color 0.2s, color 0.2s;
  letter-spacing: 0.01em;
}
.nav-pill:hover {
  color: var(--ink-100);
  background: var(--bg-glass);
}
.nav-pill.active {
  color: var(--ink-100);
  background: var(--bg-glass-strong);
}

.teacher-brand-button {
  border: none;
  background: transparent;
  color: inherit;
  padding: 0;
  cursor: pointer;
  font: inherit;
  text-align: left;
}

.teacher-nav-badge {
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: var(--r-full);
  background: oklch(75% 0.2 20);
  color: #0a0820;
  font-size: 10px;
  font-weight: 700;
}

.teacher-mobile-nav {
  display: none;
}

.nav-spacer { flex: 1; }

.nav-stats {
  display: flex;
  gap: var(--space-4);
  align-items: center;
}

.stat-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--r-full);
  background: var(--bg-glass);
  border: 1px solid var(--ink-line);
  font-size: 12px;
  font-weight: 600;
  font-family: var(--font-mono);
}
.stat-chip svg { width: 14px; height: 14px; }
.stat-chip.streak { color: oklch(85% 0.16 60); }
.stat-chip.xp { color: oklch(85% 0.16 160); }
.stat-chip.gem { color: oklch(80% 0.16 280); }

.avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: conic-gradient(from 90deg, oklch(70% 0.2 280), oklch(70% 0.2 60));
  border: 1.5px solid rgba(255, 255, 255, 0.2);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 12px;
  color: white;
}

/* ===== Mobile bottom nav ===== */
.bottomnav {
  position: relative;
  z-index: 10;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 2px;
  padding: 10px 8px calc(20px + env(safe-area-inset-bottom));
  /* Dropped backdrop-filter — solid bottom on mobile reads better and frees the GPU. */
  background: linear-gradient(180deg, rgba(10, 8, 32, 0.92), rgba(10, 8, 32, 0.98));
  border-top: 1px solid var(--ink-line);
  flex-shrink: 0;
}
.bottomnav-btn {
  background: transparent;
  border: none;
  color: var(--ink-400);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  min-width: 0;
  padding: 6px 4px;
  cursor: pointer;
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  transition: color 0.2s;
}
.bottomnav-btn span {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bottomnav-btn.active { color: var(--ink-100); }
.bottomnav-btn svg { width: 22px; height: 22px; }
.bottomnav-btn.active svg { /* filter: drop-shadow removed — filter on animated/active elements triggers compositor skip. */ color: var(--w-primary); }

/* ===== Scroll area ===== */
.scroll-area {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  position: relative;
  z-index: 2;
  scrollbar-width: thin;
  scrollbar-color: var(--ink-line-strong) transparent;
}
.scroll-area::-webkit-scrollbar { width: 6px; height: 6px; }
.scroll-area::-webkit-scrollbar-thumb { background: var(--ink-line-strong); border-radius: 3px; }

/* ===== Buttons ===== */
.btn {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.005em;
  border: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transition: transform 0.2s, box-shadow 0.2s, background 0.2s;
}
.btn:active { transform: translateY(1px); }

.btn-primary {
  background: linear-gradient(135deg, var(--w-bright), var(--w-primary));
  color: #0a0820;
  padding: 14px 28px;
  border-radius: var(--r-full);
  font-size: 15px;
  box-shadow:
    0 10px 30px -10px var(--w-glow),
    inset 0 1px 0 rgba(255, 255, 255, 0.4);
}
.btn-primary:hover {
  box-shadow:
    0 14px 40px -8px var(--w-glow),
    inset 0 1px 0 rgba(255, 255, 255, 0.5);
}

.btn-ghost {
  background: var(--bg-glass);
  color: var(--ink-100);
  padding: 13px 26px;
  border-radius: var(--r-full);
  border: 1px solid var(--ink-line-strong);
  font-size: 15px;
  /* backdrop-filter dropped — too many .btn-ghost on screen at once to be free. */
}
.btn-ghost:hover { background: var(--bg-glass-strong); border-color: rgba(255, 255, 255, 0.3); }

.btn-sm { padding: 8px 14px; font-size: 12px; }

button:not(:disabled):focus-visible,
.btn:focus-visible,
.nav-pill:focus-visible {
  outline: 2px solid var(--w-bright);
  outline-offset: 3px;
}

/* ===== Cards / panels ===== */
.panel {
  /* backdrop-filter dropped: 10+ panels on screen at once was the single biggest
     paint cost on integrated GPUs. The slightly heavier solid (--bg-glass +
     border) reads the same at normal opacity. */
  background: var(--bg-glass);
  border: 1px solid var(--ink-line);
  border-radius: var(--r-lg);
}

.panel-bordered {
  background: linear-gradient(180deg, var(--bg-glass), transparent);
  border: 1px solid var(--ink-line);
  border-radius: var(--r-lg);
  position: relative;
  overflow: hidden;
}

/* Type ramps */
.eyebrow {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-300);
  font-weight: 500;
}

.display-xl { font-family: var(--font-display); font-weight: 700; font-size: clamp(40px, 6vw, 84px); line-height: 0.95; letter-spacing: -0.035em; }
.display-lg { font-family: var(--font-display); font-weight: 700; font-size: clamp(32px, 4vw, 56px); line-height: 1; letter-spacing: -0.03em; }
.display-md { font-family: var(--font-display); font-weight: 700; font-size: clamp(24px, 3vw, 36px); line-height: 1.05; letter-spacing: -0.02em; }
.display-sm { font-family: var(--font-display); font-weight: 600; font-size: 22px; line-height: 1.1; letter-spacing: -0.01em; }

.text-mono { font-family: var(--font-mono); }
.muted { color: var(--ink-300); }

/* Page transition */
.page {
  animation: pageIn 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes pageIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Utility */
.hidden { display: none !important; }
.row { display: flex; gap: var(--space-4); }
.col { display: flex; flex-direction: column; gap: var(--space-4); }
.center { display: flex; align-items: center; justify-content: center; }

/* Iridescent text */
.iridescent {
  background: linear-gradient(135deg,
    oklch(85% 0.15 300) 0%,
    oklch(85% 0.15 240) 30%,
    oklch(85% 0.15 180) 60%,
    oklch(88% 0.15 60) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Glow ring (world card) */
.glow-ring {
  position: relative;
}
.glow-ring::before {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(135deg, var(--w-bright), transparent 50%, var(--w-primary));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}

/* Progress bar */
.progress {
  height: 6px;
  background: var(--bg-glass);
  border-radius: var(--r-full);
  overflow: hidden;
  position: relative;
}
.progress-fill {
  height: 100%;
  width: 100%;
  background: linear-gradient(90deg, var(--w-deep), var(--w-bright));
  border-radius: var(--r-full);
  position: relative;
  transform-origin: left center;
  transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.progress-fill::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
  animation: shimmer 2.5s linear infinite;
  will-change: transform;
}
@keyframes shimmer {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

@media (prefers-reduced-motion: reduce) {
  .progress-fill::after {
    animation: none;
  }
}

/* Hover lift */
.lift {
  position: relative;
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}
.lift::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5);
  opacity: 0;
  transition: opacity 0.3s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
  z-index: -1;
  will-change: opacity;
}
.lift:hover { transform: translateY(-3px); }
.lift:hover::before { opacity: 1; }

/* ===== Planet animations ===== */
@keyframes planet-slide {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@keyframes planet-wobble {
  0%, 100% { transform: translateX(-12%); }
  50% { transform: translateX(-38%); }
}
/* @keyframes nebula-drift removed — the nebula clouds are static now (see landing.jsx). */
/* @keyframes shooting-star removed — shooting-star elements were removed from JSX (see landing.jsx). */
@keyframes float-y {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}
@keyframes ring-shimmer {
  0%, 100% { opacity: 0.6; }
  50% { opacity: 1; }
}

/* .shooting-star removed — element no longer exists in JSX (confirmed dead code). */

/* World-tinted glass */
.world-glass {
  background:
    radial-gradient(ellipse 80% 60% at 0% 0%, var(--w-tint), transparent 60%),
    var(--bg-glass);
  border: 1px solid var(--ink-line);
  position: relative;
  overflow: hidden;
}
.world-glass::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at top right, var(--w-glow), transparent 60%);
  opacity: 0.4;
  pointer-events: none;
}

/* ===== Student journey layer ===== */
.mentor-briefing {
  position: relative;
  display: grid;
  gap: 12px;
  padding: 14px;
  border-radius: 16px;
  background:
    radial-gradient(circle at 30% 0%, oklch(82% var(--w-c) var(--w-h) / 0.18), transparent 58%),
    rgba(0, 0, 0, 0.3);
  border: 1px solid var(--ink-line);
  overflow: hidden;
}
.mentor-briefing::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent, rgba(255, 255, 255, 0.05));
  pointer-events: none;
}
.mentor-portrait {
  position: relative;
  z-index: 1;
  width: 96px;
  height: 96px;
  margin: 0 auto;
  border-radius: 26px;
  background-image: url("assets/mentor-guide-talk.webp?v=2");
  background-repeat: no-repeat;
  background-size: 200% 200%;
  background-position: 0% 0%;
  animation:
    guide-talk 2.4s steps(1, end) infinite,
    guide-breathe 3.2s ease-in-out infinite;
  filter: drop-shadow(0 0 18px oklch(82% var(--w-c) var(--w-h) / 0.45));
}
.mentor-copy {
  position: relative;
  z-index: 1;
  min-width: 0;
}
.mentor-eyebrow {
  margin-bottom: 6px;
  color: var(--w-bright);
}
.mentor-title {
  font-family: var(--font-display);
  font-size: 18px;
  line-height: 1.05;
  font-weight: 700;
  margin-bottom: 8px;
}
.mentor-text {
  color: var(--ink-200);
  font-size: 12px;
  line-height: 1.45;
  margin-bottom: 12px;
}
.mentor-loop {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
  margin-bottom: 12px;
}
.mentor-loop span {
  min-width: 0;
  padding: 5px 7px;
  border-radius: 999px;
  border: 1px solid oklch(85% var(--w-c) var(--w-h) / 0.18);
  background: oklch(85% var(--w-c) var(--w-h) / 0.08);
  color: var(--ink-100);
  font-family: var(--font-mono);
  font-size: 9px;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.mentor-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.learning-compass {
  padding: 18px;
}
.learning-compass-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 18px;
  margin-bottom: 16px;
}
.learning-compass-score {
  text-align: right;
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1;
}
.learning-compass-score span {
  display: block;
  font-size: 34px;
  color: var(--w-bright);
}
.learning-compass-score small {
  color: var(--ink-300);
  font-family: var(--font-mono);
  font-size: 10px;
}
.learning-stage-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 8px;
}
.learning-stage {
  min-width: 0;
  display: flex;
  gap: 9px;
  padding: 11px;
  border-radius: 13px;
  border: 1px solid var(--ink-line);
  background: rgba(255, 255, 255, 0.035);
}
.learning-stage.active {
  border-color: var(--w-primary);
  background: var(--w-tint);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
}
.learning-stage.done {
  border-color: oklch(72% 0.16 160 / 0.32);
  background: oklch(72% 0.16 160 / 0.08);
}
.learning-stage.locked {
  opacity: 0.58;
}
.learning-stage-dot {
  width: 26px;
  height: 26px;
  flex: 0 0 26px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-glass-strong);
  color: var(--ink-100);
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 11px;
}
.learning-stage.active .learning-stage-dot {
  color: #0a0820;
  background: var(--w-primary);
}
.learning-stage.done .learning-stage-dot {
  color: #061510;
  background: oklch(72% 0.16 160);
}
.learning-stage-body {
  min-width: 0;
}
.learning-stage-title {
  font-family: var(--font-display);
  font-size: 13px;
  line-height: 1.1;
  font-weight: 700;
  margin-bottom: 3px;
}
.learning-stage-range {
  color: var(--ink-300);
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 6px;
}
.learning-stage-promise {
  color: var(--ink-300);
  font-size: 11px;
  line-height: 1.35;
}
.next-move-lab {
  position: relative;
  display: grid;
  grid-template-columns: 116px minmax(0, 1fr) minmax(280px, 0.72fr);
  gap: 18px;
  align-items: center;
  padding: 18px;
  overflow: hidden;
  border-color: oklch(82% 0.14 205 / 0.22);
  background:
    radial-gradient(circle at 82px 52px, oklch(82% 0.18 205 / 0.18), transparent 44%),
    radial-gradient(circle at 72% 20%, oklch(86% 0.14 72 / 0.1), transparent 38%),
    var(--bg-glass);
}
.next-move-lab::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.045), transparent);
  opacity: 0.6;
  pointer-events: none;
}
.next-move-art,
.next-move-main,
.next-move-proof {
  position: relative;
  z-index: 1;
}
.next-move-art {
  width: 106px;
  height: 106px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 24px;
  background:
    radial-gradient(circle, oklch(82% 0.18 205 / 0.13), transparent 68%),
    rgba(255, 255, 255, 0.035);
  border: 1px solid oklch(82% 0.14 205 / 0.16);
}
.next-move-art img {
  width: 118px;
  height: 118px;
  object-fit: contain;
  filter: drop-shadow(0 0 18px oklch(82% 0.18 205 / 0.42));
}
.next-move-kicker {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  align-items: center;
  margin-bottom: 8px;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.next-move-kicker span {
  color: oklch(84% 0.14 205);
}
.next-move-kicker strong {
  color: oklch(88% 0.14 72);
}
.next-move-title {
  max-width: 720px;
  color: var(--ink-100);
  font-family: var(--font-display);
  font-size: clamp(22px, 2.1vw, 34px);
  font-weight: 800;
  line-height: 1.05;
  margin-bottom: 9px;
}
.next-move-copy {
  max-width: 720px;
  margin: 0 0 12px;
  color: var(--ink-200);
  font-size: 14px;
  line-height: 1.48;
}
.next-move-loop {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 7px;
  max-width: 600px;
}
.next-move-loop span {
  min-width: 0;
  padding: 7px 9px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.045);
  border: 1px solid var(--ink-line);
  color: var(--ink-200);
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 800;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.next-move-proof {
  display: grid;
  gap: 8px;
}
.next-move-stat-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}
.next-move-stat-row > div,
.next-move-card {
  min-width: 0;
  padding: 9px 10px;
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.24);
  border: 1px solid var(--ink-line);
}
.next-move-stat-row span,
.next-move-card span {
  display: block;
  margin-bottom: 4px;
  color: oklch(84% 0.14 205);
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.next-move-stat-row strong {
  display: block;
  color: var(--ink-100);
  font-family: var(--font-display);
  font-size: 16px;
  line-height: 1.05;
  overflow-wrap: anywhere;
}
.next-move-card p {
  margin: 0;
  color: var(--ink-200);
  font-size: 11.5px;
  line-height: 1.4;
}
.next-move-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.practice-coach {
  position: relative;
  display: grid;
  grid-template-columns: 88px minmax(0, 0.7fr) minmax(0, 1.4fr);
  gap: 16px;
  align-items: center;
  padding: 18px;
  margin-bottom: 28px;
  overflow: hidden;
  border-color: oklch(82% 0.14 205 / 0.22);
  background:
    radial-gradient(circle at 64px 46px, oklch(82% 0.18 205 / 0.14), transparent 46%),
    radial-gradient(circle at 74% 0%, oklch(86% 0.14 72 / 0.09), transparent 40%),
    var(--bg-glass);
}
.practice-coach::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.04), transparent);
  pointer-events: none;
}
.practice-coach-art,
.practice-coach-main,
.practice-coach-picks {
  position: relative;
  z-index: 1;
}
.practice-coach-art {
  width: 78px;
  height: 78px;
  border-radius: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(circle, oklch(82% 0.18 205 / 0.13), transparent 70%),
    rgba(255, 255, 255, 0.035);
  border: 1px solid oklch(82% 0.14 205 / 0.16);
}
.practice-coach-art img {
  width: 92px;
  height: 92px;
  object-fit: contain;
  filter: drop-shadow(0 0 16px oklch(82% 0.18 205 / 0.38));
}
.practice-coach-main h2 {
  margin: 6px 0 8px;
}
.practice-coach-main p {
  margin: 0;
  color: var(--ink-200);
  font-size: 13px;
  line-height: 1.45;
}
.practice-coach-picks {
  display: grid;
  gap: 8px;
}
.practice-pick {
  min-width: 0;
  width: 100%;
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) 18px;
  gap: 10px;
  align-items: center;
  padding: 11px;
  border-radius: 13px;
  border: 1px solid oklch(78% var(--w-c) var(--w-h) / 0.24);
  background:
    radial-gradient(circle at 0% 0%, oklch(78% var(--w-c) var(--w-h) / 0.12), transparent 52%),
    rgba(255, 255, 255, 0.045);
  color: var(--ink-100);
  cursor: pointer;
  font-family: inherit;
  text-align: left;
}
.practice-pick-rank {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #080615;
  background: oklch(82% var(--w-c) var(--w-h));
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 800;
}
.practice-pick-body {
  min-width: 0;
}
.practice-pick-role {
  margin-bottom: 2px;
  color: oklch(86% var(--w-c) var(--w-h));
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.practice-pick-title {
  color: var(--ink-100);
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 700;
  line-height: 1.12;
}
.practice-pick-meta {
  margin-top: 3px;
  color: var(--ink-300);
  font-size: 11px;
  line-height: 1.25;
}
.practice-pick-reason {
  margin-top: 5px;
  color: var(--ink-300);
  font-size: 11px;
  line-height: 1.35;
}
.skill-roadmap-brief {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(220px, 0.45fr);
  gap: 16px;
  align-items: center;
  padding: 18px;
  margin-bottom: 20px;
  background:
    radial-gradient(circle at 0% 0%, oklch(82% 0.18 205 / 0.1), transparent 55%),
    var(--bg-glass);
}
.skill-roadmap-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(72px, 1fr));
  gap: 8px;
}
.skill-roadmap-stats div,
.skill-roadmap-current {
  min-width: 0;
  padding: 10px 12px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.045);
  border: 1px solid var(--ink-line);
}
.skill-roadmap-stats span {
  display: block;
  color: var(--ink-100);
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 800;
  line-height: 1;
}
.skill-roadmap-stats small {
  color: var(--ink-300);
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.skill-roadmap-current {
  cursor: pointer;
  color: var(--ink-100);
  font-family: inherit;
  text-align: left;
}
.skill-roadmap-current span {
  display: block;
  margin-bottom: 4px;
  color: oklch(84% 0.14 205);
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.skill-roadmap-current strong {
  display: block;
  font-family: var(--font-display);
  font-size: 16px;
  line-height: 1.12;
}
.skill-roadmap-current small {
  display: block;
  margin-top: 4px;
  color: var(--ink-300);
  font-size: 11px;
}
.mission-briefing {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 290px;
  gap: 18px;
  padding: 22px;
  border-color: oklch(85% var(--w-c) var(--w-h) / 0.18);
  background:
    radial-gradient(circle at 0% 0%, var(--w-tint), transparent 55%),
    var(--bg-glass);
}
.mission-briefing-title {
  margin: 8px 0 10px;
}
.mission-briefing-text {
  max-width: 720px;
  margin: 0 0 16px;
  color: var(--ink-200);
  font-size: 15px;
  line-height: 1.5;
}
.mission-loop-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
}
.mission-loop-grid span {
  min-width: 0;
  padding: 9px 10px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.045);
  border: 1px solid var(--ink-line);
  color: var(--ink-200);
  font-family: var(--font-mono);
  font-size: 10px;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.python-mission-prep {
  margin-top: 12px;
  padding: 12px;
  border-radius: 14px;
  background:
    radial-gradient(circle at 0% 0%, oklch(82% 0.14 205 / 0.12), transparent 56%),
    rgba(0, 0, 0, 0.18);
  border: 1px solid oklch(82% 0.12 205 / 0.2);
}
.python-mission-prep-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 9px;
}
.python-mission-prep-head span {
  color: oklch(88% 0.14 72);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.07em;
}
.python-mission-prep-head strong {
  color: var(--ink-100);
  font-family: var(--font-display);
  font-size: 13px;
  line-height: 1.15;
  text-align: right;
}
.python-mission-prep-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}
.python-mission-prep-card {
  min-width: 0;
  padding: 9px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.045);
  border: 1px solid var(--ink-line);
}
.python-mission-prep-card span {
  display: block;
  margin-bottom: 5px;
  color: oklch(86% 0.14 205);
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.07em;
}
.python-mission-prep-card p {
  margin: 0;
  color: var(--ink-200);
  font-size: 11.5px;
  line-height: 1.38;
}
.python-mission-prep-note {
  margin-top: 9px;
  color: var(--ink-300);
  font-size: 11.5px;
  line-height: 1.4;
}
.mission-briefing-side {
  padding: 16px;
  border-radius: 14px;
  background: rgba(0, 0, 0, 0.24);
  border: 1px solid var(--ink-line);
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.mission-vet-copy {
  color: var(--ink-200);
  font-size: 13px;
  line-height: 1.45;
}
.mission-reward-note {
  color: var(--ink-300);
  font-size: 11px;
  line-height: 1.4;
}
.victory-debrief {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin-bottom: 12px;
  text-align: left;
}
.victory-debrief-card {
  position: relative;
  overflow: hidden;
  padding: 15px;
  border-radius: 14px;
  background:
    radial-gradient(circle at 0% 0%, var(--w-tint), transparent 58%),
    rgba(255, 255, 255, 0.045);
  border: 1px solid var(--ink-line);
}
.victory-debrief-card::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 18%, rgba(255, 255, 255, 0.12) 45%, transparent 72%);
  transform: translateX(-120%);
  animation: fx-sweep 2.8s ease-in-out 0.3s both;
  pointer-events: none;
}
.victory-debrief-card.unlock {
  border-color: oklch(82% 0.16 60 / 0.28);
  background:
    radial-gradient(circle at 100% 0%, oklch(82% 0.16 60 / 0.16), transparent 58%),
    rgba(255, 255, 255, 0.045);
}
.victory-debrief-title {
  margin: 7px 0 6px;
  color: var(--w-bright);
  font-family: var(--font-display);
  font-size: 18px;
  line-height: 1.1;
  font-weight: 700;
}
.victory-debrief-copy {
  color: var(--ink-200);
  font-size: 12px;
  line-height: 1.42;
}

@media (max-width: 980px) {
  .learning-stage-grid {
    grid-template-columns: 1fr;
  }
  .next-move-lab {
    grid-template-columns: 90px minmax(0, 1fr);
    align-items: start;
  }
  .next-move-art {
    width: 86px;
    height: 86px;
    border-radius: 20px;
  }
  .next-move-art img {
    width: 98px;
    height: 98px;
  }
  .next-move-proof {
    grid-column: 1 / -1;
  }
  .practice-coach {
    grid-template-columns: 76px minmax(0, 1fr);
  }
  .practice-coach-art {
    width: 72px;
    height: 72px;
  }
  .practice-coach-art img {
    width: 86px;
    height: 86px;
  }
  .practice-coach-picks {
    grid-column: 1 / -1;
  }
  .skill-roadmap-brief {
    grid-template-columns: 1fr;
  }
  .skill-roadmap-stats {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .mission-briefing {
    grid-template-columns: 1fr;
  }
  .mission-loop-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .python-mission-prep-grid {
    grid-template-columns: 1fr;
  }
  .victory-debrief {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 720px) {
  .teacher-topnav {
    flex-wrap: wrap;
    gap: 10px;
    padding: 12px 14px;
  }
  .teacher-topnav .brand {
    min-width: 0;
    flex: 1 1 auto;
  }
  .teacher-topnav .brand > span:first-of-type {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .teacher-topnav .nav-spacer {
    display: none;
  }
  .teacher-signout-btn {
    padding: 7px 10px;
    font-size: 11px;
    flex: 0 0 auto;
  }
  .teacher-avatar {
    width: 30px;
    height: 30px;
    flex: 0 0 auto;
    cursor: default;
  }
  .teacher-mobile-nav {
    flex: 0 0 100%;
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 4px;
    min-width: 0;
  }
  .teacher-mobile-nav .nav-pill {
    width: 100%;
    min-width: 0;
    padding: 8px 4px;
    border: 1px solid var(--ink-line);
    background: rgba(255, 255, 255, 0.035);
    font-size: 10.5px;
    line-height: 1.1;
    letter-spacing: 0;
  }
  .teacher-mobile-nav .nav-pill.active {
    border-color: var(--ink-line-strong);
    background: var(--bg-glass-strong);
  }
  .teacher-mobile-label {
    display: block;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .teacher-mobile-nav .teacher-nav-badge {
    margin-left: 4px;
    padding: 0 4px;
    font-size: 9px;
  }
  .learning-compass {
    padding: 14px;
  }
  .learning-compass-head {
    align-items: flex-start;
  }
  .next-move-lab {
    grid-template-columns: 72px minmax(0, 1fr);
    gap: 12px;
    padding: 14px;
  }
  .next-move-art {
    width: 68px;
    height: 68px;
    border-radius: 18px;
  }
  .next-move-art img {
    width: 82px;
    height: 82px;
  }
  .next-move-title {
    font-size: 21px;
  }
  .next-move-copy {
    font-size: 13px;
  }
  .next-move-loop {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .next-move-actions .btn {
    justify-content: center;
    flex: 1 1 120px;
  }
  .practice-coach {
    grid-template-columns: 62px minmax(0, 1fr);
    gap: 12px;
    padding: 14px;
    margin-bottom: 22px;
  }
  .practice-coach-art {
    width: 58px;
    height: 58px;
    border-radius: 17px;
  }
  .practice-coach-art img {
    width: 72px;
    height: 72px;
  }
  .practice-pick {
    grid-template-columns: 32px minmax(0, 1fr) 16px;
    padding: 10px;
  }
  .practice-pick-rank {
    width: 32px;
    height: 32px;
  }
  .skill-roadmap-brief {
    padding: 14px;
  }
  .skill-roadmap-stats {
    gap: 6px;
  }
  .skill-roadmap-stats div,
  .skill-roadmap-current {
    padding: 9px;
  }
  .skill-roadmap-stats span {
    font-size: 20px;
  }
  .mission-briefing {
    padding: 16px;
  }
  .mission-loop-grid {
    grid-template-columns: 1fr;
  }
  .python-mission-prep-head {
    align-items: flex-start;
    flex-direction: column;
  }
  .python-mission-prep-head strong {
    text-align: left;
  }
}

/* World icon (abstract glyph) */
.world-glyph {
  width: 56px;
  height: 56px;
  border-radius: var(--r-md);
  background:
    radial-gradient(circle at 30% 30%, var(--w-bright), var(--w-deep));
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  color: rgba(255, 255, 255, 0.9);
  position: relative;
  box-shadow: 0 6px 20px -6px var(--w-glow);
  flex-shrink: 0;
}
.world-glyph::after {
  content: "";
  position: absolute;
  inset: 1px;
  border-radius: inherit;
  border: 1px solid rgba(255, 255, 255, 0.2);
}

/* Generic util scroll-snap row */
.snap-row {
  display: flex;
  gap: var(--space-4);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: 8px;
}
.snap-row > * {
  scroll-snap-align: start;
  flex-shrink: 0;
}

/* Animated halo */
@keyframes halo {
  0%, 100% { opacity: 0.4; transform: scale(1); }
  50% { opacity: 0.7; transform: scale(1.05); }
}
.halo { animation: halo 4s ease-in-out infinite; will-change: transform, opacity; }

/* Compact mode tightens */
[data-density="compact"] {
  --d: 0.7;
}
[data-density="compact"] .display-xl { font-size: clamp(32px, 4.5vw, 60px); }
[data-density="compact"] .display-lg { font-size: clamp(26px, 3.5vw, 44px); }
[data-density="compact"] .display-md { font-size: clamp(20px, 2.5vw, 30px); }

/* ===== WorldMap perf: compositor-owned transitions =====
   These classes replace inline style objects rebuilt on every hover so that
   opacity and box-shadow transitions run on the compositor thread with zero
   JS overhead per frame. */

/* Nebula blobs — opacity is the only thing that changes on hover. */
.world-nebula {
  opacity: 0.5;
  transition: opacity 0.4s;
}
.world-nebula--active {
  opacity: 1;
}

/* World node inner square — box-shadow variant swapped via class toggle. */
.world-node-inner {
  box-shadow: none;
}
.world-node-inner--unlocked {
  box-shadow: 0 0 20px oklch(80% var(--node-chroma) var(--node-hue) / 0.4);
}
.world-node-inner--unlocked.world-node-inner--active {
  box-shadow: 0 0 40px oklch(80% var(--node-chroma) var(--node-hue) / 0.7);
}

/* =====================================================================
   Lesson FX — shared animation vocabulary for the ten lesson games.
   Consumed by lesson-fx.jsx and the per-lesson modules. Transform/opacity
   only (GPU-cheap); one-shot unless a lesson deliberately loops one.
   ===================================================================== */
@keyframes fx-spark {
  /* particle burst — --dx/--dy are set inline per spark */
  from { transform: translate(0, 0) scale(1); opacity: 1; }
  to   { transform: translate(var(--dx), var(--dy)) scale(0.25); opacity: 0; }
}
@keyframes fx-rise {
  from { opacity: 0; transform: translateY(9px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes fx-pop {
  0%   { opacity: 0; transform: scale(0.82); }
  60%  { opacity: 1; transform: scale(1.05); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes fx-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-7px); }
  40% { transform: translateX(7px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(4px); }
}
@keyframes fx-flash-fade {
  from { opacity: 1; }
  to   { opacity: 0; }
}
@keyframes fx-glow-pulse {
  0%, 100% { opacity: 0.45; }
  50%      { opacity: 1; }
}
@keyframes fx-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-6px); }
}
@keyframes fx-sweep {
  from { transform: translateX(-120%); }
  to   { transform: translateX(120%); }
}
@keyframes guide-talk {
  0%, 18% { background-position: 0% 0%; }
  24%, 42% { background-position: 100% 0%; }
  48%, 66% { background-position: 0% 100%; }
  72%, 100% { background-position: 100% 100%; }
}
@keyframes guide-breathe {
  0%, 100% { transform: translateY(0) scale(1); }
  50% { transform: translateY(-2px) scale(1.02); }
}
@keyframes guide-scanline {
  0% { transform: translateY(-120%); opacity: 0; }
  15%, 75% { opacity: 0.45; }
  100% { transform: translateY(120%); opacity: 0; }
}

/* one-shot helper classes the lessons can drop straight onto an element */
.fx-shake     { animation: fx-shake 380ms cubic-bezier(.36,.07,.19,.97) both; }
.fx-pop       { animation: fx-pop 320ms cubic-bezier(.2,.7,.3,1) both; }
.fx-rise      { animation: fx-rise 380ms cubic-bezier(.2,.7,.3,1) both; }

.fx-flash-good, .fx-flash-bad {
  position: relative;
}
.fx-flash-good::after, .fx-flash-bad::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  will-change: opacity;
}
.fx-flash-good::after {
  background-color: oklch(72% 0.18 150 / 0.40);
  animation: fx-flash-fade 720ms ease-out forwards;
}
.fx-flash-bad::after {
  background-color: oklch(65% 0.21 25 / 0.40);
  animation: fx-flash-fade 720ms ease-out forwards;
}

@media (prefers-reduced-motion: reduce) {
  .fx-shake, .fx-pop, .fx-rise { animation: none; }
  .fx-flash-good::after, .fx-flash-bad::after { animation: none; }
}

/* --- Lesson guide portrait: generated 2x2 talking sprite sheet. --- */
.lesson-guide {
  position: relative;
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 152px;
  padding: 5px 12px 5px 6px;
  border: 1px solid oklch(85% var(--w-c) var(--w-h) / 0.22);
  border-radius: var(--r-full);
  background:
    radial-gradient(circle at 24px 22px, oklch(85% var(--w-c) var(--w-h) / 0.2), transparent 58%),
    rgba(255, 255, 255, 0.045);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.08);
  overflow: hidden;
}
.lesson-guide::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 0%, rgba(255,255,255,0.16) 50%, transparent 100%);
  animation: guide-scanline 3.4s ease-in-out infinite;
  pointer-events: none;
}
.lesson-guide-sprite {
  width: 42px;
  height: 42px;
  flex: 0 0 42px;
  border-radius: 50%;
  background-image: url("assets/mentor-guide-talk.webp?v=2");
  background-repeat: no-repeat;
  background-size: 200% 200%;
  background-position: 0% 0%;
  animation:
    guide-talk 2.2s steps(1, end) infinite,
    guide-breathe 3.2s ease-in-out infinite;
  filter: drop-shadow(0 0 10px oklch(82% var(--w-c) var(--w-h) / 0.45));
}
.lesson-guide-copy {
  position: relative;
  z-index: 1;
  display: grid;
  min-width: 0;
  line-height: 1;
}
.lesson-guide-kicker {
  color: var(--ink-400);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.lesson-guide-name {
  color: var(--ink-100);
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 700;
  max-width: 86px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
@media (max-width: 860px) {
  .lesson-guide { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .lesson-guide::after,
  .lesson-guide-sprite {
    animation: none;
  }
}

/* --- Challenger World avatars: positioned imperatively by the rAF loop. --- */
.chal-avatar {
  position: absolute; left: 0; top: 0; width: 0; height: 0;
  will-change: transform;
}
.chal-nametag {
  position: absolute; left: 0; top: -56px;
  transform: translateX(-50%); white-space: nowrap;
  padding: 2px 8px; border-radius: 999px;
  font-family: var(--font-display); font-weight: 700; font-size: 11px;
}
.chal-sprite {
  position: absolute; left: 0; top: 0;
  transform: translate(-50%, -50%);
}
.chal-avatar[data-facing="left"] .chal-sprite {
  transform: translate(-50%, -50%) scaleX(-1);
}
.chal-bob { animation: chal-bob 2.6s ease-in-out infinite; }
@keyframes chal-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-3px); }
}
@media (prefers-reduced-motion: reduce) {
  .chal-bob { animation: none; }
}

/* Task 1: Short-viewport scroll fallback */
@media (max-height: 600px) {
  html, body {
    height: auto !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
  }
  #root {
    height: auto !important;
    min-height: 100vh !important;
    min-height: 100dvh !important;
  }
  .app-shell {
    height: auto !important;
    min-height: 100vh !important;
    min-height: 100dvh !important;
    overflow-y: visible !important;
    overflow-x: hidden !important;
  }
  .scroll-area {
    overflow-y: visible !important;
  }
}

/* Task 3: Circuit Board Sizing */
.circuit-board-svg {
  width: 100%;
  max-width: 460px;
}

/* ═══════════ Platform polish layer ═══════════
   Shared motion, focus, and layout utilities used across the student hub,
   teacher console, and lesson chrome. Everything here degrades gracefully:
   reduced-motion users get instant state changes, keyboard users get a
   consistent ring on every interactive element. */

/* Consistent focus ring on every interactive element (buttons already
   covered above — this extends the same treatment to form fields, links
   and anything made focusable with tabIndex). */
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
a:focus-visible,
[role="button"]:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--w-bright, oklch(80% 0.16 280));
  outline-offset: 2px;
  border-radius: 4px;
}

/* Entrance: sections rise in once as they mount. Cheap (opacity+transform),
   GPU-composited, and a single non-looping run. */
.rise-in {
  animation: riseIn 0.55s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.stagger > * {
  animation: riseIn 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.stagger > *:nth-child(1) { animation-delay: 0.03s; }
.stagger > *:nth-child(2) { animation-delay: 0.09s; }
.stagger > *:nth-child(3) { animation-delay: 0.15s; }
.stagger > *:nth-child(4) { animation-delay: 0.21s; }
.stagger > *:nth-child(5) { animation-delay: 0.27s; }
.stagger > *:nth-child(6) { animation-delay: 0.33s; }
@keyframes riseIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Student hub — journey path. A row of planet nodes per tier, connected by a
   line. The node ring is painted with a conic-gradient (progress %); cleared
   worlds go solid green with a check; locked ones dim out. */
.jpath-row {
  display: flex;
  align-items: flex-start;
  overflow-x: auto;
  padding: 10px 2px 6px;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
.jnode {
  position: relative;
  flex: 1 0 auto;
  min-width: 72px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 2px 4px 4px;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--ink-200);
  font-family: inherit;
  transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}
/* Connector line between nodes, drawn behind the orbs. */
.jnode::before {
  content: "";
  position: absolute;
  top: 27px;
  right: 50%;
  width: 100%;
  height: 2px;
  background: var(--ink-line);
  z-index: 0;
  pointer-events: none;
}
.jnode:first-child::before { display: none; }
.jnode:not(.locked):hover { transform: translateY(-2px); color: var(--ink-100); }
.jnode-orb {
  position: relative;
  z-index: 1;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.jnode-core {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  background:
    radial-gradient(circle at 32% 30%, oklch(45% calc(var(--w-c, 0.12) * 1.2) var(--w-h, 280) / 0.9), oklch(22% var(--w-c, 0.12) var(--w-h, 280))),
    #0a0820;
  color: var(--ink-100);
  border: 1px solid rgba(255,255,255,0.12);
}
.jnode.locked { cursor: not-allowed; opacity: 0.45; }
.jnode.locked .jnode-core { filter: grayscale(0.8); }
.jnode.current .jnode-orb {
  box-shadow: 0 0 18px oklch(75% 0.16 var(--w-h, 280) / 0.7);
  animation: halo 2.4s ease-in-out infinite;
}
.jnode.current .jnode-label { color: var(--ink-100); font-weight: 600; }
.jnode-label {
  font-size: 9.5px;
  line-height: 1.25;
  text-align: center;
  max-width: 76px;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.jnode-here {
  position: absolute;
  top: -7px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  font-family: var(--font-mono);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.08em;
  padding: 2px 7px;
  border-radius: 999px;
  background: oklch(80% 0.15 var(--w-h, 280));
  color: #0a0820;
  white-space: nowrap;
}

/* ═══════════ Multiverse map — tier galaxies ═══════════
   Three calm sections (curriculum tiers), each a breathing grid of planets.
   The detail inspector docks as a sticky side panel. */
.map-grid {
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 22px;
  align-items: start;
}
.map-inspector { position: sticky; top: 18px; }
@media (max-width: 980px) {
  .map-grid { grid-template-columns: 1fr; }
  .map-inspector { position: static; }
}

.galaxy {
  --gx-h: 280;
  border: 1px solid oklch(60% 0.1 var(--gx-h) / 0.28);
  border-radius: 18px;
  padding: 15px 18px 20px;
  background:
    radial-gradient(130% 150% at 0% 0%, oklch(50% 0.13 var(--gx-h) / 0.10), transparent 58%),
    var(--bg-glass);
}
.galaxy-head { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.galaxy-num {
  font-family: var(--font-display); font-weight: 700; font-size: 24px; line-height: 1;
  color: oklch(86% 0.13 var(--gx-h)); width: 24px; flex-shrink: 0; text-align: center;
}
.galaxy-name { font-family: var(--font-display); font-weight: 600; font-size: 15px; margin-bottom: 7px; }
.galaxy-bar {
  height: 4px; border-radius: 999px; max-width: 340px;
  background: rgba(255, 255, 255, 0.07); overflow: hidden;
}
.galaxy-bar > i {
  display: block; height: 100%; border-radius: inherit; transform-origin: left center;
  background: linear-gradient(90deg, oklch(60% 0.16 var(--gx-h)), oklch(82% 0.16 var(--gx-h)));
  transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}
.galaxy-count {
  font-family: var(--font-mono); font-size: 14px; font-weight: 700; flex-shrink: 0;
  color: oklch(86% 0.12 var(--gx-h));
}
.galaxy-row {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(106px, 1fr));
  gap: 8px 2px;
  justify-items: center;
}

.mplanet {
  --w-h: 280;
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  width: 100%; padding: 16px 4px 10px;
  border: none; background: none; cursor: pointer;
  color: var(--ink-100); font-family: inherit; border-radius: 14px;
  transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1), background-color 0.2s;
  animation: mplanetIn 0.5s cubic-bezier(0.22, 1, 0.36, 1) backwards;
}
.mplanet:hover { background: rgba(255, 255, 255, 0.04); }
.mplanet.active { transform: translateY(-3px); }
.mplanet.locked { cursor: default; }
@keyframes mplanetIn {
  from { opacity: 0; transform: translateY(10px) scale(0.92); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.mplanet-orb {
  position: relative; display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.mplanet-ring { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); }
.mplanet-body {
  border-radius: 50%; display: flex; align-items: center; justify-content: center;
  font-size: 22px; color: rgba(255, 255, 255, 0.95);
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.5));
  box-shadow: inset -6px -8px 16px rgba(5, 2, 18, 0.7), 0 0 22px oklch(72% 0.16 var(--w-h) / 0.42);
  transition: box-shadow 0.3s;
}
.mplanet.active .mplanet-body { box-shadow: inset -6px -8px 16px rgba(5, 2, 18, 0.7), 0 0 32px oklch(74% 0.16 var(--w-h) / 0.65); }
.mplanet.locked .mplanet-body {
  color: rgba(255, 255, 255, 0.32); filter: none;
  box-shadow: inset -6px -8px 16px rgba(0, 0, 0, 0.72);
}
.mplanet-badge {
  position: absolute; left: -2px; bottom: -2px;
  width: 21px; height: 21px; border-radius: 50%; border: 2px solid #07060f;
  display: flex; align-items: center; justify-content: center;
  font: 700 10px/1 var(--font-mono);
}
.mplanet-py {
  position: absolute; right: -8px; top: -7px; min-width: 26px; height: 20px; padding: 0 6px;
  border-radius: 999px; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, oklch(84% 0.15 205), oklch(88% 0.15 72));
  color: #07101d; border: 2px solid #07060f; font: 900 9px/1 var(--font-mono); letter-spacing: 0.02em;
}
.mplanet.current .mplanet-orb::before {
  content: ""; position: absolute; left: 50%; top: 50%; width: 138%; height: 138%;
  transform: translate(-50%, -50%); border-radius: 50%; pointer-events: none; z-index: -1;
  background: radial-gradient(circle, oklch(85% 0.16 75 / 0.4), transparent 70%);
  animation: halo 3s ease-in-out infinite;
}
.mplanet-here {
  position: absolute; top: 0; left: 50%; transform: translateX(-50%); z-index: 3;
  padding: 2px 8px; border-radius: 999px; white-space: nowrap;
  background: oklch(85% 0.15 75); color: #0a0820;
  font: 700 8px/1 var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
}
.mplanet-name {
  font-family: var(--font-display); font-weight: 600; font-size: 11.5px; margin-top: 3px;
  max-width: 100px; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mplanet.locked .mplanet-name { color: var(--ink-300); }
.mplanet-sub {
  font-family: var(--font-mono); font-size: 8.5px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--ink-400); max-width: 100px; text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mplanet.current .mplanet-sub { color: oklch(86% 0.15 75); }

/* Teacher console — tab rail */
.tab-rail {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  gap: 4px;
  align-items: flex-end;
  background: linear-gradient(180deg, rgba(10, 8, 32, 0.97), rgba(10, 8, 32, 0.94));
  border-bottom: 1px solid var(--ink-line);
  margin-bottom: 18px;
}
.seg-tab {
  position: relative;
  padding: 11px 20px 13px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 14px;
  color: var(--ink-300);
  background: transparent;
  border: none;
  cursor: pointer;
  border-radius: 10px 10px 0 0;
  transition: color 0.2s, background-color 0.2s;
}
.seg-tab:hover { color: var(--ink-100); background: var(--bg-glass); }
.seg-tab.active { color: var(--ink-100); }
.seg-tab.active::after {
  content: "";
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: -1px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--iris-1), var(--iris-2));
}
.tab-badge {
  margin-left: 8px;
  padding: 1px 7px;
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  background: var(--bg-glass-strong);
  color: var(--ink-200);
}
.tab-badge.alert {
  background: oklch(75% 0.2 20);
  color: #0a0820;
}

/* Teacher console — action queue cards */
.queue-card {
  --act-h: 60;
  border-radius: 14px;
  border: 1px solid oklch(72% 0.15 var(--act-h) / 0.3);
  background: oklch(60% 0.15 var(--act-h) / 0.07);
  overflow: hidden;
  transition: border-color 0.25s, box-shadow 0.25s;
}
.queue-card.expanded {
  border-color: oklch(78% 0.16 var(--act-h) / 0.6);
  box-shadow: 0 0 24px -10px oklch(70% 0.18 var(--act-h) / 0.5);
}
.queue-head {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 12px 14px;
  background: transparent;
  border: none;
  color: var(--ink-100);
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
  text-align: left;
  min-height: 44px;
}
.queue-count {
  min-width: 24px;
  height: 24px;
  padding: 0 7px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 12px;
  background: oklch(75% 0.17 var(--act-h) / 0.9);
  color: #0a0820;
  flex-shrink: 0;
}
.queue-body {
  padding: 2px 14px 14px;
}

/* Teacher insights — vertical bar columns (activity, histogram) */
.pulse-cols {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  height: 56px;
}
.pulse-cols > i {
  flex: 1;
  display: block;
  border-radius: 4px 4px 2px 2px;
  background: linear-gradient(180deg, oklch(78% 0.14 200), oklch(55% 0.13 230));
  min-height: 3px;
  transition: height 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Reduced-motion: collapse the polish-layer motion to instant state changes. */
@media (prefers-reduced-motion: reduce) {
  .rise-in, .stagger > * { animation: none; }
  .page { animation: none; }
  .jnode, .queue-card, .seg-tab, .lift { transition: none; }
  .jnode.current .jnode-orb { animation: none; }
  .mplanet { animation: none; }
  .mplanet.current .mplanet-orb::before { animation: none; }
  .galaxy-bar > i { transition: none; }
  .pulse-cols > i, .progress-fill { transition: none; }
}

/* ── Print: Class Report & Official Register → PDF ────────────────────
   When the teacher prints the Class Report or Official School Register,
   we hide the app shell and show only the printable sheet.
   The Official Register defaults to landscape orientation and is strictly
   compacted so all 30 students + masthead + signatures fit onto ONE page. */
@media print {
  html, body {
    height: 100% !important;
    max-height: 100vh !important;
    margin: 0 !important;
    padding: 0 !important;
    overflow: hidden !important;
    background: #fff !important;
  }
  body * { visibility: hidden !important; }
  .report-sheet, .report-sheet *,
  .register-sheet, .register-sheet * { visibility: visible !important; }
  .report-sheet, .register-sheet {
    position: absolute !important;
    left: 0 !important;
    top: 0 !important;
    width: 100% !important;
    max-width: 100% !important;
    margin: 0 !important;
    padding: 0 !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    background: #fff !important;
    page-break-inside: avoid !important;
    break-inside: avoid !important;
    page-break-after: avoid !important;
    break-after: avoid !important;
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }
  .register-sheet {
    font-size: 7pt !important;
  }
  .register-sheet .reg-masthead {
    margin-bottom: 2px !important;
    padding-bottom: 2px !important;
    border-bottom: 1.5px solid #000 !important;
  }
  .register-sheet .reg-masthead-title {
    font-size: 11px !important;
    line-height: 1.1 !important;
  }
  .register-sheet .reg-masthead-sub {
    font-size: 8px !important;
    line-height: 1.1 !important;
  }
  .register-sheet .reg-masthead-month {
    font-size: 12px !important;
    line-height: 1.1 !important;
  }
  .register-sheet table {
    width: 100% !important;
    border-collapse: collapse !important;
    page-break-inside: avoid !important;
    break-inside: avoid !important;
  }
  .register-sheet tr {
    page-break-inside: avoid !important;
    break-inside: avoid !important;
  }
  .register-sheet .reg-thead-row th {
    padding: 1px 1px !important;
    font-size: 6.8pt !important;
    line-height: 1 !important;
  }
  .register-sheet .reg-row-am,
  .register-sheet .reg-row-pm {
    height: 7.8pt !important;
    max-height: 8pt !important;
    line-height: 7.8pt !important;
  }
  .register-sheet td,
  .register-sheet th {
    padding: 0 1px !important;
    line-height: 1 !important;
    font-size: 6.5pt !important;
  }
  .register-sheet .reg-student-name {
    font-size: 7pt !important;
    line-height: 1 !important;
    max-width: 120px !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
  }
  .register-sheet .reg-totals-row {
    height: 11pt !important;
    font-size: 7pt !important;
    line-height: 11pt !important;
  }
  .register-sheet .reg-footer {
    margin-top: 3px !important;
    padding-top: 2px !important;
    font-size: 7.5pt !important;
    border-top: 1px solid #000 !important;
    page-break-inside: avoid !important;
    break-inside: avoid !important;
  }
  .no-print { display: none !important; }
  @page {
    size: landscape;
    margin: 3mm 4mm;
  }
}

/* ═══════════ Accessibility & offline polish ═══════════ */

/* Skip link: visible only when focused by keyboard. */
.skip-link {
  position: fixed; left: 12px; top: -64px; z-index: 100001;
  padding: 10px 16px; border-radius: 10px;
  background: #f6f5ff; color: #0a0820; font-weight: 600; font-size: 14px;
  text-decoration: none; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  transition: top 0.12s ease-out;
}
.skip-link:focus, .skip-link:focus-visible { top: 12px; outline: 3px solid #7c5cff; outline-offset: 2px; }

/* Visible focus ring on every interactive control, including ones that rely on
   the browser default being suppressed elsewhere (summary, labels-as-buttons,
   custom roles, mission rows and accordion headers now rendered as buttons). */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
[role="button"]:focus-visible,
[role="tab"]:focus-visible,
[role="link"]:focus-visible,
.mission-row:focus-visible,
.lift:focus-visible {
  outline: 2px solid var(--w-bright, oklch(80% 0.16 280));
  outline-offset: 3px;
}
/* Programmatic focus targets (route change heading, main region) are not
   keyboard stops and should not draw a ring. */
#main-content:focus,
#main-content:focus-visible,
h1[tabindex="-1"]:focus,
h1[tabindex="-1"]:focus-visible { outline: none; }

button.mission-row:disabled { cursor: not-allowed; }

/* Results saved on this device that have not synced yet. */
.pending-sync-pill {
  position: fixed; left: 50%; bottom: 16px; transform: translateX(-50%);
  z-index: 90; max-width: min(92vw, 460px);
  padding: 9px 14px; border-radius: 999px;
  background: oklch(20% 0.08 250 / 0.94); color: var(--ink-100);
  border: 1px solid oklch(72% 0.15 250 / 0.45);
  font-size: 12.5px; line-height: 1.4; text-align: center;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.38); pointer-events: none;
}

.pending-sync-pill.in-lesson { bottom: auto; top: 8px; font-size: 11.5px; padding: 6px 12px; opacity: 0.92; }
