/* Buttons, pills, bubbles, blobs, forms — generic reusable components. */

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3xs);
  border: 0;
  border-radius: var(--radius-md);
  padding: var(--space-2xs) var(--space-sm);
  font-weight: 800;
  cursor: pointer;
  transition: transform var(--speed-fast) var(--ease-smooth), border-bottom-width var(--speed-fast) var(--ease-smooth);
}
.btn.small { padding: var(--space-3xs) var(--space-xs); font-size: 0.85em; }

.btn.primary {
  background: var(--c-primary-dark);
  color: #fff;
  border-bottom: 4px solid #064f68;
}
.btn.secondary {
  background: var(--bg-card);
  color: var(--text-primary);
  border: 2px solid var(--c-primary);
  border-bottom: 4px solid var(--c-primary-dark);
}
.btn.ghost {
  background: transparent;
  color: var(--c-primary-glow-text);
  border-bottom: 4px solid transparent;
}
.btn.install {
  background: var(--c-primary-dark);
  color: #fff;
  border-bottom: 4px solid #064f68;
}

.btn:active { transform: translateY(2px); border-bottom-width: 2px; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }


/* ---------- Blob cards (lesson cards, task boxes, stat cards) ---------- */
/* glassmorphism: frosted translucent fill + thin illuminated border + soft shadow, no heavy gradients */
.blob-card {
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--c-primary);
  box-shadow: var(--shadow-card), inset 0 1px 0 var(--glass-border);
  padding: var(--space-sm);
  border-radius: var(--blob-1);
}
.blob-card:nth-of-type(4n+2) { border-radius: var(--blob-2); }
.blob-card:nth-of-type(4n+3) { border-radius: var(--blob-3); }
.blob-card:nth-of-type(4n+4) { border-radius: var(--blob-4); }

.blob-card.accent-cyan   { border-color: var(--c-primary); }
.blob-card.accent-purple { border-color: var(--c-secondary); }
.blob-card.accent-green  { border-color: var(--c-success); }
.blob-card.accent-orange { border-color: var(--c-warning); }
.blob-card.accent-red    { border-color: var(--c-error); }

/* ---------- Circular bubble tiles (module/navigation tiles) ---------- */
.bubble-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--space-sm);
  justify-items: center;
}
.bubble-tile {
  width: 150px;
  height: 150px;
  border-radius: var(--radius-circle);
  border: 1.5px solid var(--c-primary);
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  display: grid;
  place-items: center;
  text-align: center;
  padding: var(--space-xs);
  cursor: pointer;
  box-shadow: 0 0 22px rgba(51, 214, 255, var(--glow-alpha));
  font-weight: 800;
  color: var(--c-primary-glow-text);
  text-shadow: 0 0 10px rgba(51, 214, 255, 0.6);
  transition: transform var(--speed-fast) var(--ease-smooth);
  animation: bubble-pulse 3.4s ease-in-out infinite;
}
.bubble-tile:hover { transform: translateY(-4px) scale(1.04); animation-play-state: paused; }
.bubble-tile.active {
  outline: 3px solid rgba(255, 255, 255, 0.35);
  animation: bubble-pulse-active 2.2s ease-in-out infinite;
}

.bubble-tile.accent-purple { border-color: var(--c-secondary); box-shadow: 0 0 22px rgba(139, 92, 246, var(--glow-alpha)); color: var(--c-secondary-glow-text); text-shadow: 0 0 10px rgba(139, 92, 246, 0.6); animation-name: bubble-pulse-purple; }
.bubble-tile.accent-green  { border-color: var(--c-success);   box-shadow: 0 0 22px rgba(61, 220, 151, var(--glow-alpha)); color: var(--c-success-glow-text);   text-shadow: 0 0 10px rgba(61, 220, 151, 0.6); animation-name: bubble-pulse-green; }
.bubble-tile.accent-orange { border-color: var(--c-warning);   box-shadow: 0 0 22px rgba(255, 179, 71, var(--glow-alpha)); color: var(--c-warning-glow-text);   text-shadow: 0 0 10px rgba(255, 179, 71, 0.6); animation-name: bubble-pulse-orange; }
.bubble-tile.accent-red    { border-color: var(--c-error);     box-shadow: 0 0 22px rgba(255, 93, 115, var(--glow-alpha)); color: var(--c-error-glow-text);     text-shadow: 0 0 10px rgba(255, 93, 115, 0.6); animation-name: bubble-pulse-red; }

@keyframes bubble-pulse {
  0%, 100% { box-shadow: 0 0 14px rgba(51, 214, 255, 0.3); transform: scale(0.96); }
  50% { box-shadow: 0 0 40px rgba(51, 214, 255, 0.8); transform: scale(1.08); }
}
@keyframes bubble-pulse-purple {
  0%, 100% { box-shadow: 0 0 14px rgba(139, 92, 246, 0.3); transform: scale(0.96); }
  50% { box-shadow: 0 0 40px rgba(139, 92, 246, 0.8); transform: scale(1.08); }
}
@keyframes bubble-pulse-green {
  0%, 100% { box-shadow: 0 0 14px rgba(61, 220, 151, 0.3); transform: scale(0.96); }
  50% { box-shadow: 0 0 40px rgba(61, 220, 151, 0.8); transform: scale(1.08); }
}
@keyframes bubble-pulse-orange {
  0%, 100% { box-shadow: 0 0 14px rgba(255, 179, 71, 0.3); transform: scale(0.96); }
  50% { box-shadow: 0 0 40px rgba(255, 179, 71, 0.8); transform: scale(1.08); }
}
@keyframes bubble-pulse-red {
  0%, 100% { box-shadow: 0 0 14px rgba(255, 93, 115, 0.3); transform: scale(0.96); }
  50% { box-shadow: 0 0 40px rgba(255, 93, 115, 0.8); transform: scale(1.08); }
}
@keyframes bubble-pulse-active {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.12); }
}

@media (max-width: 780px) {
  .bubble-tile { width: 108px; height: 108px; font-size: 0.85em; }
}

@media (prefers-reduced-motion: reduce) {
  .bubble-tile, .bubble-tile.active { animation: none; }
}

/* ---------- Background bokeh texture ---------- */
.bokeh { position: absolute; inset: 0; overflow: hidden; z-index: 0; pointer-events: none; }
.bokeh span {
  position: absolute;
  border-radius: var(--radius-circle);
  filter: blur(22px);
  opacity: 0.35;
}

/* ---------- Forms ---------- */
.field { display: flex; flex-direction: column; gap: var(--space-3xs); margin-bottom: var(--space-sm); }
.field label { font-weight: 700; color: var(--text-secondary); font-size: 0.9em; }
.field input, .field select, .field textarea {
  background: var(--bg-main);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  padding: var(--space-2xs) var(--space-xs);
  color: var(--text-primary);
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: 2px solid var(--c-primary);
  outline-offset: 1px;
}

/* ---------- Level tiles (Grade/Year level selector) ----------
   Rounded glass cards with an animated chemistry icon badge on top and the label/tag below,
   unclipped - text sits in normal flow instead of inside a jagged shape, so it always fits. */
.level-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: var(--space-md);
  padding: var(--space-sm) 0;
}
/* No border - a translucent fill plus the accent glow below is enough to separate tiles, and lets
   the starfield background show through instead of the tile reading as an opaque boxed panel. */
.level-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-2xs);
  padding: var(--space-md) var(--space-sm);
  border-radius: var(--radius-lg);
  background: rgba(20, 22, 34, 0.4);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: none;
  cursor: pointer;
  transition: transform var(--speed-fast) var(--ease-smooth), box-shadow var(--speed-fast) var(--ease-smooth);
  animation: level-tile-enter 0.5s var(--ease-smooth) both;
}
.level-tile:hover:not(:disabled) { transform: translateY(-4px); }
.level-tile:disabled, .level-tile.empty { cursor: not-allowed; opacity: 0.55; }
.level-tile:disabled .level-icon-svg, .level-tile.empty .level-icon-svg { animation-play-state: paused; }

.level-icon-badge {
  width: 104px;
  height: 104px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-circle);
  background: var(--bg-surface);
  flex-shrink: 0;
  transition: transform var(--speed-fast) var(--ease-smooth), box-shadow var(--speed-fast) var(--ease-smooth);
}
.level-icon-svg { width: 80px; height: 80px; overflow: visible; }
.level-tile:hover .level-icon-badge, .level-tile:focus-visible .level-icon-badge {
  transform: scale(1.08);
  box-shadow: 0 0 20px rgba(255, 255, 255, 0.08);
}
.level-label { font-weight: 800; font-size: 1em; line-height: 1.2; }
.level-tag { font-weight: 700; color: var(--text-secondary); font-size: 0.78em; text-transform: uppercase; letter-spacing: 0.04em; }

.level-tile.accent-cyan   { box-shadow: 0 0 26px rgba(51, 214, 255, 0.22); }
.level-tile.accent-purple { box-shadow: 0 0 26px rgba(139, 92, 246, 0.22); }
.level-tile.accent-green  { box-shadow: 0 0 26px rgba(61, 220, 151, 0.22); }
.level-tile.accent-orange { box-shadow: 0 0 26px rgba(255, 179, 71, 0.22); }
.level-tile.accent-red    { box-shadow: 0 0 26px rgba(255, 93, 115, 0.22); }

/* ---------- Level icon animations - each level gets a distinct, chemistry-themed motion ---------- */
@keyframes ice-cube-melt {
  0%, 15% { transform: scaleY(1) translateY(0); opacity: 0.9; }
  60%, 85% { transform: scaleY(0.5) translateY(11px); opacity: 0.6; }
  100% { transform: scaleY(1) translateY(0); opacity: 0.9; }
}
@keyframes ice-puddle-grow {
  0%, 15% { transform: scaleX(0.35); opacity: 0.15; }
  60%, 85% { transform: scaleX(1); opacity: 0.45; }
  100% { transform: scaleX(0.35); opacity: 0.15; }
}
@keyframes ice-drop-fall {
  0%, 20% { opacity: 0; transform: translateY(-2px); }
  32% { opacity: 1; transform: translateY(0); }
  55% { opacity: 0; transform: translateY(10px); }
  100% { opacity: 0; }
}
.ice-melt .ice-cube { transform-box: fill-box; transform-origin: 50% 0%; animation: ice-cube-melt 4s ease-in-out infinite; }
.ice-melt .ice-puddle { transform-box: fill-box; transform-origin: 50% 100%; animation: ice-puddle-grow 4s ease-in-out infinite; }
.ice-melt .ice-drop { animation: ice-drop-fall 4s ease-in-out infinite; }

@keyframes vapor-rise-anim {
  0% { transform: translateY(6px); opacity: 0; }
  30% { opacity: 0.9; }
  100% { transform: translateY(-11px); opacity: 0; }
}
.vapor-rise .vapor-line { animation: vapor-rise-anim 2.6s ease-in-out infinite; }
.vapor-rise .v2 { animation-delay: 0.6s; }
.vapor-rise .v3 { animation-delay: 1.2s; }

@keyframes bubble-up-anim {
  0% { transform: translateY(0); opacity: 0; }
  15% { opacity: 0.9; }
  100% { transform: translateY(-26px); opacity: 0; }
}
.bubble-rise .bubble { animation: bubble-up-anim 2.2s ease-in infinite; }
.bubble-rise .b2 { animation-delay: 0.5s; }
.bubble-rise .b3 { animation-delay: 1s; }

.atom-orbit .orbit { opacity: 0.55; transform-box: fill-box; transform-origin: center; }

@keyframes molecule-pulse-anim {
  0%, 100% { transform: scale(0.85); filter: drop-shadow(0 0 0 transparent); }
  50% { transform: scale(1.45); filter: drop-shadow(0 0 6px var(--c-error)); }
}
@keyframes molecule-bond-pulse {
  0%, 100% { opacity: 0.5; }
  50% { opacity: 1; }
}
.molecule-pulse .atom-node { transform-box: fill-box; transform-origin: center; animation: molecule-pulse-anim 1.8s ease-in-out infinite; }
.molecule-pulse .a2 { animation-delay: 0.3s; }
.molecule-pulse .a3 { animation-delay: 0.6s; }
.molecule-pulse .bond { animation: molecule-bond-pulse 1.8s ease-in-out infinite; }

@keyframes drip-fall-anim {
  0% { transform: translateY(0); opacity: 0; }
  10% { opacity: 1; }
  60% { transform: translateY(20px); opacity: 0; }
  100% { opacity: 0; }
}
@keyframes titration-color-shift {
  0%, 70% { fill: var(--c-secondary); }
  85%, 100% { fill: var(--c-error); }
}
.titration-drip .drip { animation: drip-fall-anim 2.4s ease-in infinite; }
.titration-drip .titration-liquid { animation: titration-color-shift 6s ease-in-out infinite; }

/* Hovering (or focusing, for keyboard users) speeds every animation on that tile way up, so the
   level picker feels responsive/interactive rather than just quietly looping in the background. */
.level-tile:hover .ice-cube, .level-tile:focus-visible .ice-cube { animation-duration: 1.1s; }
.level-tile:hover .ice-puddle, .level-tile:focus-visible .ice-puddle { animation-duration: 1.1s; }
.level-tile:hover .ice-drop, .level-tile:focus-visible .ice-drop { animation-duration: 1.1s; }
.level-tile:hover .vapor-line, .level-tile:focus-visible .vapor-line { animation-duration: 0.9s; }
.level-tile:hover .bubble, .level-tile:focus-visible .bubble { animation-duration: 0.7s; }
.level-tile:hover .atom-node, .level-tile:focus-visible .atom-node { animation-duration: 0.8s; }
.level-tile:hover .bond, .level-tile:focus-visible .bond { animation-duration: 0.8s; }
.level-tile:hover .drip, .level-tile:focus-visible .drip { animation-duration: 0.8s; }
.level-tile:hover .orbit, .level-tile:focus-visible .orbit { animation: orbit-spin 2.5s linear infinite; }
@keyframes orbit-spin { to { transform: rotate(360deg); } }

/* Tiles fade/rise in with a short stagger on first render (delay set inline per-tile in JS) -
   the one-time "page just came alive" moment; the icons' own loops carry the motion after that. */
@keyframes level-tile-enter {
  from { opacity: 0; transform: translateY(14px) scale(0.96); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@media (max-width: 780px) {
  .level-icon-badge { width: 88px; height: 88px; }
  .level-icon-svg { width: 68px; height: 68px; }
}
@media (prefers-reduced-motion: reduce) {
  .level-tile { animation: none; }
}

/* ---------- Lesson shell (fullscreen lesson/quiz overlay) ---------- */
.lesson-shell {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 50;
  background: var(--bg-surface);
  padding: var(--space-md);
  overflow-y: auto;
}
.lesson-shell.active { display: flex; align-items: flex-start; justify-content: center; }
.lesson-shell-panel {
  width: 100%;
  max-width: 760px;
  margin-top: var(--space-md);
  background: var(--bg-surface);
  border: 1px solid var(--c-primary);
  box-shadow: var(--shadow-card), 0 0 32px rgba(51, 214, 255, 0.12), inset 0 1px 0 var(--glass-border);
  border-radius: var(--radius-lg);
  padding: var(--space-md);
}
/* Full-bleed on phones - a real fullscreen page, not a card floating over visible background. */
@media (max-width: 640px) {
  .lesson-shell { padding: 0; }
  .lesson-shell-panel { max-width: 100%; margin-top: 0; min-height: 100vh; border-radius: 0; border-left: none; border-right: none; border-top: none; }
}

/* ---------- Game mode: a vibrant, colourful backdrop instead of the flat near-black lesson
   background. Lessons stay calm/low-distraction for reading; games get an actual "arena" feel -
   layered colour glows drifting slowly across a dark base, never a flat single tone. Toggled by
   openGameShell()/closeGameShell() and startCrosswordGame() adding/removing "game-mode" on
   #lessonShell - never add this class to a plain lesson. */
.lesson-shell.game-mode,
.lesson-shell.game-mode .lesson-shell-panel {
  background:
    radial-gradient(1.5px 1.5px at 12% 22%, rgba(255, 255, 255, 0.9), transparent 60%),
    radial-gradient(1px 1px at 68% 8%, rgba(255, 255, 255, 0.7), transparent 60%),
    radial-gradient(1px 1px at 40% 65%, rgba(200, 220, 255, 0.6), transparent 60%),
    radial-gradient(1.5px 1.5px at 88% 48%, rgba(255, 255, 255, 0.8), transparent 60%),
    radial-gradient(1px 1px at 24% 88%, rgba(255, 255, 255, 0.55), transparent 60%),
    radial-gradient(1px 1px at 92% 92%, rgba(200, 220, 255, 0.65), transparent 60%),
    radial-gradient(1.5px 1.5px at 55% 40%, rgba(255, 255, 255, 0.5), transparent 60%),
    radial-gradient(circle at 12% 8%, rgba(139, 92, 246, 0.22), transparent 36%),
    radial-gradient(circle at 90% 12%, rgba(51, 214, 255, 0.2), transparent 38%),
    radial-gradient(circle at 15% 92%, rgba(255, 79, 163, 0.13), transparent 42%),
    radial-gradient(circle at 92% 88%, rgba(255, 210, 63, 0.11), transparent 42%),
    linear-gradient(180deg, #06040F 0%, #040309 55%, #010102 100%);
  background-size:
    180px 180px, 210px 210px, 190px 190px, 230px 230px, 170px 170px, 200px 200px, 220px 220px,
    140% 140%, 140% 140%, 140% 140%, 140% 140%, 100% 100%;
  background-repeat: repeat, repeat, repeat, repeat, repeat, repeat, repeat, no-repeat, no-repeat, no-repeat, no-repeat, no-repeat;
  animation: game-bg-drift 22s ease-in-out infinite alternate;
}
@keyframes game-bg-drift {
  0% {
    background-position:
      0 0, 0 0, 0 0, 0 0, 0 0, 0 0, 0 0,
      0% 0%, 100% 0%, 0% 100%, 100% 100%, 0 0;
  }
  100% {
    background-position:
      0 0, 0 0, 0 0, 0 0, 0 0, 0 0, 0 0,
      8% 6%, 92% 8%, 6% 94%, 94% 92%, 0 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  .lesson-shell.game-mode, .lesson-shell.game-mode .lesson-shell-panel { animation: none; }
}
/* Every game is fullscreen at any viewport width, not just on phones (the plain-lesson shell
   still uses the centred card - see the max-width:640px rule above for that path). A game is a
   real "arena", not a card floating over visible background. */
.lesson-shell.game-mode { padding: 0; }
.lesson-shell.game-mode .lesson-shell-panel {
  max-width: 100%; margin-top: 0; min-height: 100vh;
  border: none; border-radius: 0; box-shadow: none;
}
.lesson-shell.game-mode .lesson-shell-topbar { border-bottom: none; }
.lesson-shell.game-mode .lesson-bottom-bar { border-top: none; }
/* Hearts/streak/best/hint chips blend in everywhere, not just Equilibrium Shift and Potion Lab
   (see .eq-shift-stats/.potion-stats below, now redundant with this but left as-is) - just
   icon+text floating on the arena background, no bordered pill chip. */
.lesson-shell.game-mode .game-stat, .lesson-shell.game-mode .game-hearts, .lesson-shell.game-mode .game-streak {
  background: none; border: none; padding: 6px 4px;
}
/* Game screens skip the glass-card frame around each activity entirely - content floats directly
   on the vibrant arena background, not inside another dark box on top of it (matching what the
   per-game overrides below - .lm-card, .csc-card, .potion-card, .er-card, .eq-shift-card - already
   do; this just makes it the default instead of something each game had to opt into). */
.lesson-shell.game-mode .activity-card {
  background: none;
  border-color: transparent;
  box-shadow: none;
}

/* ---------- Game-mode vibrancy for every other game ----------
   Every game reuses these same shared components (.reactants-box, .reaction-type-option,
   .md-candidate, .et-source, .pth-tile, .mm-tray-atom/.mm-group). Regular lessons ALSO use several
   of these (balance-equation/reaction-type questions), so every rule here is scoped under
   ".lesson-shell.game-mode" - lessons keep their current plain look untouched; only an actual game
   screen gets the vibrant gradient/glow treatment, replacing flat dashed/solid boxes. */
.lesson-shell.game-mode .reactants-box {
  border: none;
  background: linear-gradient(160deg, rgba(51, 214, 255, 0.14), rgba(139, 92, 246, 0.1));
  box-shadow: 0 0 22px rgba(51, 214, 255, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.08);
}
.lesson-shell.game-mode .reaction-type-option {
  background: linear-gradient(160deg, rgba(139, 92, 246, 0.28), rgba(18, 14, 32, 0.5));
  border-color: rgba(139, 92, 246, 0.55);
  box-shadow: 0 0 12px rgba(139, 92, 246, 0.2);
}
.lesson-shell.game-mode .reaction-type-option.selected { border-color: var(--c-primary); box-shadow: 0 0 16px rgba(51, 214, 255, 0.4); }
.lesson-shell.game-mode .reaction-type-option.correct { background: var(--c-success-dark); border-color: var(--c-success); box-shadow: 0 0 18px rgba(61, 220, 151, 0.5); }
.lesson-shell.game-mode .reaction-type-option.wrong { background: var(--c-error-dark); border-color: var(--c-error); box-shadow: 0 0 18px rgba(255, 93, 115, 0.5); }
.lesson-shell.game-mode .md-candidate {
  background: linear-gradient(160deg, rgba(255, 79, 163, 0.22), rgba(30, 12, 24, 0.5));
  border-color: rgba(255, 79, 163, 0.5);
  box-shadow: 0 0 12px rgba(255, 79, 163, 0.18);
}
.lesson-shell.game-mode .md-candidate.correct { background: var(--c-success-dark); border-color: var(--c-success); box-shadow: 0 0 18px rgba(61, 220, 151, 0.5); }
.lesson-shell.game-mode .md-candidate.wrong { background: var(--c-error-dark); border-color: var(--c-error); box-shadow: 0 0 18px rgba(255, 93, 115, 0.5); }
/* color-mix() needs Chrome 111+/Safari 16.2+ (2023) - the plain background/border-color/box-shadow
   declared first is the fallback for anything older; browsers that can't parse the color-mix()
   value simply keep that earlier declaration for the same property. */
.lesson-shell.game-mode .et-source {
  background: rgba(51, 214, 255, 0.16);
  background: linear-gradient(160deg, color-mix(in srgb, var(--tile-color, var(--c-primary)) 24%, transparent), rgba(10, 12, 22, 0.55));
  border-color: var(--tile-color, var(--border-default));
  box-shadow: 0 0 14px rgba(51, 214, 255, 0.3);
  box-shadow: 0 0 14px color-mix(in srgb, var(--tile-color, var(--c-primary)) 35%, transparent);
}
/* Plain, uniform tiles like .crossword-cell - a different colour per element was too busy/
   distracting on a full periodic table; only the tapped tile should stand out (via .selected). */
.lesson-shell.game-mode .pth-tile { background: var(--bg-main); border-color: var(--border-default); }
.lesson-shell.game-mode .pth-tile.correct { background: var(--c-success-dark); border-color: var(--c-success); box-shadow: 0 0 18px rgba(61, 220, 151, 0.55); }
.lesson-shell.game-mode .pth-tile.wrong { background: var(--c-error-dark); border-color: var(--c-error); box-shadow: 0 0 18px rgba(255, 93, 115, 0.55); }
/* The tile the player actually tapped gets a stronger "attached" halo on top of its correct/wrong
   colour, so the pick itself reads as selected - not just correct-vs-wrong. */
.lesson-shell.game-mode .pth-tile.selected {
  transform: scale(1.08);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.8), 0 0 22px 4px rgba(255, 255, 255, 0.45);
}
/* Neon-green pulse for a correct pick - brighter/more saturated than the --c-success token
   (which is a muted mint) specifically for this "yes!" moment. */
.lesson-shell.game-mode .pth-tile.selected.correct {
  border-color: #39FF6A;
  animation: pth-correct-pulse 0.9s ease-in-out infinite alternate;
}
.lesson-shell.game-mode .pth-tile.selected.wrong { box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.85), 0 0 26px 6px rgba(255, 93, 115, 0.65); }
@keyframes pth-correct-pulse {
  0% { box-shadow: 0 0 0 3px rgba(140, 255, 170, 0.9), 0 0 20px 4px rgba(57, 255, 106, 0.75), 0 0 40px 10px rgba(57, 255, 106, 0.4); }
  100% { box-shadow: 0 0 0 4px rgba(180, 255, 200, 1), 0 0 36px 10px rgba(57, 255, 106, 0.95), 0 0 64px 18px rgba(57, 255, 106, 0.55); }
}
@media (prefers-reduced-motion: reduce) {
  .lesson-shell.game-mode .pth-tile.selected.correct {
    animation: none;
    box-shadow: 0 0 0 3px rgba(160, 255, 185, 0.95), 0 0 28px 6px rgba(57, 255, 106, 0.8);
  }
}
.lesson-shell.game-mode .mm-tray-atom { box-shadow: 0 0 10px rgba(61, 220, 151, 0.25); }
.lesson-shell.game-mode .mm-group {
  background: linear-gradient(160deg, rgba(51, 214, 255, 0.18), rgba(10, 14, 24, 0.5));
  border-color: rgba(51, 214, 255, 0.4);
}
.lesson-shell.game-mode .mm-group.is-center { border-color: var(--c-gold); box-shadow: 0 0 16px rgba(255, 210, 63, 0.35); }
.lesson-shell.game-mode .mm-beaker { box-shadow: inset 0 0 32px rgba(111, 60, 207, 0.25), 0 0 20px rgba(111, 60, 207, 0.15); }
.lesson-shell.game-mode .lm-mission-item.current { text-shadow: 0 0 10px rgba(245, 247, 255, 0.4); }
.lesson-shell.game-mode .lm-mission-item.done { text-shadow: 0 0 8px rgba(61, 220, 151, 0.4); }
.lesson-shell.game-mode .csc-evidence-list li strong { text-shadow: 0 0 8px rgba(255, 93, 115, 0.4); }

.lesson-options { display: flex; flex-direction: column; gap: var(--space-2xs); margin: var(--space-sm) 0; }
.lesson-options button:disabled, #lessonFillSubmit:disabled { opacity: 0.6; cursor: default; }

/* sticky-feeling top row: back + breadcrumb + avatar, mirrors the app topbar so a
   learner never loses their place while inside the overlay */
.lesson-shell-topbar { display: flex; align-items: center; gap: var(--space-sm); margin-bottom: var(--space-md); padding-bottom: var(--space-sm); border-bottom: 1px solid var(--border-default); flex-wrap: wrap; }
.lesson-back-btn {
  width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; flex-shrink: 0;
  background: var(--glass-bg-surface); border: 1px solid var(--glass-border); color: var(--text-primary); cursor: pointer;
}
.lesson-back-btn svg { width: 18px; height: 18px; }
.lesson-shell-breadcrumb { color: var(--text-secondary); font-size: 0.8em; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; flex: 1; min-width: 120px; }
.lesson-shell-breadcrumb span { color: var(--c-secondary-glow-text); }
.lesson-shell-stats { display: flex; align-items: center; gap: var(--space-sm); flex-shrink: 0; margin-left: auto; }
.lesson-shell-stats .avatar { width: 30px; height: 30px; font-size: 0.8em; }

/* per-question head: step label + big title + subtitle, with a numbered progress-circle
   track alongside showing position within the unit (not the question count below). */
.lesson-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-md); margin-bottom: var(--space-md); flex-wrap: wrap; }
.lesson-head-text { flex: 1; min-width: 200px; }
.lesson-step-label { color: var(--text-secondary); font-size: 0.85em; font-weight: 700; margin-bottom: var(--space-3xs); }
.lesson-title { font-size: 1.5em; margin-bottom: var(--space-3xs); }
.lesson-subtitle { color: var(--text-secondary); font-size: 0.9em; }
.lesson-progress-circles { display: flex; flex-direction: column; align-items: center; gap: var(--space-3xs); flex-shrink: 0; }
.progress-circle-track { display: flex; align-items: center; }
.progress-circle-track .circle-link { width: 22px; height: 2px; background: var(--border-default); flex-shrink: 0; }
.progress-circle-track .circle-node {
  width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center;
  background: var(--bg-main); border: 2px solid var(--border-default); color: var(--text-disabled); font-size: 0.75em; font-weight: 800; flex-shrink: 0;
}
.progress-circle-track .circle-node.answered { background: var(--c-primary-dark); border-color: var(--c-primary); color: #fff; }
.progress-circle-track .circle-node.current { border-color: var(--c-primary); color: var(--c-primary-glow-text); box-shadow: 0 0 12px rgba(51, 214, 255, 0.6); }
.progress-circle-label { color: var(--text-secondary); font-size: 0.7em; text-transform: uppercase; letter-spacing: 0.04em; white-space: nowrap; }

/* activity card: icon badge + mascot + prompt. Primary cyan - this IS the active lesson. */
.activity-card {
  border: 1px solid var(--c-primary);
  background: var(--glass-bg-surface);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  box-shadow: 0 0 24px rgba(51, 214, 255, 0.1), inset 0 1px 0 var(--glass-border);
  border-radius: var(--radius-lg);
  padding: var(--space-md);
  margin-bottom: var(--space-sm);
}
.activity-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-sm); margin-bottom: var(--space-sm); }
.activity-icon-badge {
  width: 44px; height: 44px; border-radius: var(--radius-md);
  border: 1px solid var(--c-secondary); background: var(--glass-bg-surface);
  display: grid; place-items: center; flex-shrink: 0;
  box-shadow: 0 0 14px rgba(139, 92, 246, 0.35);
  animation: activity-icon-pulse 2.6s ease-in-out infinite;
}
@keyframes activity-icon-pulse {
  0%, 100% { box-shadow: 0 0 14px rgba(139, 92, 246, 0.35); transform: scale(1); }
  50% { box-shadow: 0 0 28px rgba(139, 92, 246, 0.75); transform: scale(1.06); }
}

/* One-shot reaction the moment an answer is submitted - since the site has no sound effects,
   this is what stands in for the "ding"/"buzz" feedback: a quick, energetic red shake-and-flash
   for wrong answers, a calmer green glow-pulse for correct ones. Class is added in JS right when
   advance(correct) fires and removed once the animation finishes. */
@keyframes answer-flash-wrong {
  0% { box-shadow: 0 0 24px rgba(51, 214, 255, 0.1); border-color: var(--c-primary); transform: translateX(0); }
  10% { box-shadow: 0 0 55px rgba(255, 93, 115, 0.9), inset 0 0 45px rgba(255, 93, 115, 0.3); border-color: var(--c-error); }
  20%, 40%, 60% { transform: translateX(-8px); }
  30%, 50%, 70% { transform: translateX(8px); }
  85% { box-shadow: 0 0 55px rgba(255, 93, 115, 0.5); border-color: var(--c-error); }
  100% { box-shadow: 0 0 24px rgba(51, 214, 255, 0.1); border-color: var(--c-primary); transform: translateX(0); }
}
.activity-card.answer-flash-wrong { animation: answer-flash-wrong 1.4s ease-out; }

@keyframes answer-flash-correct {
  0% { box-shadow: 0 0 24px rgba(51, 214, 255, 0.1); border-color: var(--c-primary); transform: scale(1); }
  25% { box-shadow: 0 0 55px rgba(61, 220, 151, 0.85); border-color: var(--c-success); transform: scale(1.02); }
  100% { box-shadow: 0 0 24px rgba(51, 214, 255, 0.1); border-color: var(--c-primary); transform: scale(1); }
}
.activity-card.answer-flash-correct { animation: answer-flash-correct 1s ease-out; }
.activity-icon-badge svg { width: 22px; height: 22px; stroke: var(--c-secondary-glow-text); }
.activity-card h3, .activity-heading { color: var(--c-secondary-glow-text); font-size: 1.1em; margin-bottom: var(--space-2xs); }
.activity-instructions { margin: 0 0 var(--space-sm); padding-left: 1.2em; color: var(--text-secondary); font-size: 0.92em; }
.activity-instructions li { margin-bottom: 2px; }

.mascot-flask { width: 76px; height: 88px; flex-shrink: 0; display: block; }

/* ---------- Mascot idle animation: gentle bob, occasional blink, rising sparkle bubbles.
   The bob animates a plain <span> wrapper (not the <svg> root) - transform-box: view-box on an
   SVG root has flaky support on older mobile Safari and silently no-ops there, so the wrapper
   sidesteps that entirely; inner fill-box transforms on the eyes/spark/liquid are safer since
   they're simple per-element transforms with much longer-standing support. ---------- */
@keyframes mascot-bob {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50% { transform: translateY(-5px) rotate(-2deg); }
}
.mascot-flask-idle { display: block; flex-shrink: 0; animation: mascot-bob 3.2s ease-in-out infinite; }

@keyframes mascot-blink {
  0%, 90%, 100% { transform: scaleY(1); }
  95% { transform: scaleY(0.15); }
}
.mascot-flask-idle .mascot-eye { transform-box: fill-box; transform-origin: 50% 50%; animation: mascot-blink 4.5s ease-in-out infinite; }

@keyframes mascot-spark-rise {
  0% { transform: translateY(0); opacity: 0; }
  20% { opacity: 0.9; }
  100% { transform: translateY(-16px); opacity: 0; }
}
.mascot-flask-idle .mascot-spark { animation: mascot-spark-rise 2.4s ease-in infinite; }
.mascot-flask-idle .ms2 { animation-delay: 0.9s; }

@keyframes mascot-liquid-wobble {
  0%, 100% { transform: scaleY(1); }
  50% { transform: scaleY(1.08); }
}
.mascot-flask-idle .mascot-liquid { transform-box: fill-box; transform-origin: 50% 100%; animation: mascot-liquid-wobble 3.2s ease-in-out infinite; }

@media (prefers-reduced-motion: reduce) {
  .mascot-flask-idle, .mascot-flask-idle .mascot-eye, .mascot-flask-idle .mascot-spark, .mascot-flask-idle .mascot-liquid { animation: none; }
}

.mascot-bubble {
  position: relative;
  background: var(--glass-bg-surface);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-sm);
  padding: var(--space-2xs) var(--space-xs);
  font-size: 0.78em;
  color: var(--c-primary-glow-text);
  text-shadow: 0 0 8px rgba(51, 214, 255, 0.6);
  max-width: 170px;
  opacity: 1;
  transition: opacity 0.5s ease;
}
.mascot-bubble.mascot-bubble-hidden { opacity: 0; pointer-events: none; }
.mascot-row { display: flex; align-items: center; gap: var(--space-2xs); justify-content: flex-end; }

/* reactants/products display box */
.reactants-box {
  border: 1px dashed var(--glass-border);
  border-radius: var(--radius-md);
  padding: var(--space-sm);
  margin-bottom: var(--space-sm);
}
.reactants-box-label { display: block; color: var(--text-secondary); font-size: 0.75em; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: var(--space-2xs); }
.equation-row { display: flex; align-items: center; gap: var(--space-2xs); flex-wrap: wrap; font-size: 1.2em; font-weight: 800; margin: 0; }
.equation-row.small { font-size: 1em; margin-bottom: var(--space-2xs); }
.equation-formula sub { font-size: 0.7em; }
.equation-arrow { color: var(--text-secondary); font-weight: 400; }
.equation-blank { display: inline-block; width: 0.7em; border-bottom: 2px solid var(--c-secondary); margin-right: 2px; }

/* two-column activity layout: type selection / balance check side by side above 640px */
.activity-columns { display: grid; grid-template-columns: 1fr; gap: var(--space-md); }
@media (min-width: 640px) {
  .activity-columns.two-col { grid-template-columns: 1fr 1fr; }
}
.activity-column-label { font-size: 0.9em; font-weight: 700; margin-bottom: var(--space-2xs); }
.activity-column-placeholder { color: var(--text-disabled); font-size: 0.85em; font-style: italic; }

/* element balance-check rows: colored letter badge + count either side + equals/not-equals */
.element-check-rows { display: flex; flex-direction: column; gap: var(--space-2xs); }
.element-check-row { display: flex; align-items: center; gap: var(--space-sm); padding: var(--space-2xs) var(--space-sm); border: 1px solid var(--glass-border); border-radius: var(--radius-sm); background: var(--bg-main); }
.element-badge { width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; font-size: 0.75em; font-weight: 800; flex-shrink: 0; border: 1px solid var(--glass-border); }
.element-badge.tone-secondary { background: rgba(139, 92, 246, 0.15); border-color: var(--c-secondary); color: var(--c-secondary-glow-text); }
.element-badge.tone-primary { background: rgba(51, 214, 255, 0.15); border-color: var(--c-primary); color: var(--c-primary-glow-text); }
.element-badge.tone-error { background: rgba(255, 93, 115, 0.15); border-color: var(--c-error); color: var(--c-error-glow-text); }
.element-badge.tone-warning { background: rgba(255, 179, 71, 0.15); border-color: var(--c-warning); color: var(--c-warning-glow-text); }
.element-badge.tone-success { background: rgba(61, 220, 151, 0.15); border-color: var(--c-success); color: var(--c-success-glow-text); }
.element-count-value { font-weight: 800; flex: 1; text-align: center; }
.element-check-eq { color: var(--text-secondary); font-weight: 700; }
.element-check-row.match .element-check-eq { color: var(--c-success-glow-text); }
.element-check-row.mismatch .element-check-eq { color: var(--c-error-glow-text); }
.element-check-rows.compact { flex-direction: row; flex-wrap: wrap; gap: var(--space-3xs); }
.element-check-rows.compact .element-check-row { padding: 2px 8px; gap: 6px; }
.element-check-rows.compact .element-badge { width: 20px; height: 20px; font-size: 0.68em; }
.element-check-rows.compact .element-count-value { font-size: 0.82em; }

.balance-choices { display: flex; flex-direction: column; gap: var(--space-xs); margin: var(--space-sm) 0; }
.balance-choice {
  display: flex; flex-direction: column; gap: var(--space-2xs);
  border: 2px solid var(--border-default); border-radius: var(--radius-md);
  padding: var(--space-2xs) var(--space-sm); cursor: pointer; background: var(--bg-main); text-align: left;
}
.balance-choice.selected { border-color: var(--c-primary); }
.balance-choice:disabled { cursor: default; }
.balance-choice-eq { font-weight: 800; }

.reaction-type-list { display: flex; flex-direction: column; gap: var(--space-2xs); margin: 0; }
.reaction-type-option {
  border: 2px solid var(--border-default); border-radius: var(--radius-md);
  padding: var(--space-2xs) var(--space-sm); cursor: pointer; background: var(--bg-main); text-align: left; font-weight: 700;
}
.reaction-type-option.selected { border-color: var(--c-primary); }
.reaction-type-option:disabled { cursor: default; }

/* feedback panel: success green = correct, error red = wrong (spec-exact) */
.feedback-panel { border-radius: var(--radius-md); padding: var(--space-sm); margin-top: var(--space-sm); border: 1px solid var(--c-success); background: var(--glass-bg-surface); backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur); box-shadow: 0 0 20px rgba(61, 220, 151, 0.12); }
.feedback-panel.incorrect { border-color: var(--c-error); box-shadow: 0 0 20px rgba(255, 93, 115, 0.12); }
.feedback-panel-top { display: flex; align-items: center; justify-content: space-between; gap: var(--space-sm); flex-wrap: wrap; margin-bottom: var(--space-2xs); }
.feedback-panel-head { display: flex; align-items: center; gap: var(--space-2xs); font-weight: 800; }
.feedback-panel-head svg { width: 20px; height: 20px; stroke: var(--c-success-glow-text); }
.feedback-panel.incorrect .feedback-panel-head svg { stroke: var(--c-error-glow-text); }
.explanation-toggle {
  display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0;
  background: var(--glass-bg-surface); border: 1px solid var(--glass-border); border-radius: var(--radius-sm);
  padding: 4px 10px; color: var(--text-primary); font-weight: 700; font-size: 0.85em; cursor: pointer;
}
.explanation-box { margin-top: var(--space-2xs); padding-top: var(--space-2xs); border-top: 1px dashed var(--border-default); }
.explanation-box ol { padding-left: 1.2em; margin: var(--space-2xs) 0 0; }
.explanation-box li { margin-bottom: var(--space-3xs); color: var(--text-secondary); font-size: 0.9em; }

/* bottom bar: Explain concept (left) - progress dots (true center) - Continue (right) */
.lesson-bottom-bar { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: var(--space-sm); margin-top: var(--space-md); padding-top: var(--space-sm); border-top: 1px solid var(--border-default); }
.lesson-bottom-bar .bottom-bar-end { justify-self: end; }
.lesson-progress-dots { display: flex; align-items: center; gap: 6px; justify-self: center; }
.lesson-progress-dots .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--border-default); }
.lesson-progress-dots .dot.answered { background: var(--c-primary); }
.lesson-progress-dots .dot.current { background: var(--c-primary); box-shadow: 0 0 8px rgba(51, 214, 255, 0.8); transform: scale(1.3); }
.lesson-progress-bar-track { height: 8px; border-radius: var(--radius-pill); background: var(--border-default); overflow: hidden; width: 140px; justify-self: center; }
.lesson-progress-bar-fill { height: 100%; background: var(--c-primary); }

.concept-panel { margin-top: var(--space-sm); padding: var(--space-sm); border: 1px solid var(--glass-border); border-radius: var(--radius-md); background: var(--glass-bg-surface); backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur); font-size: 0.9em; }
.concept-panel h4 { font-size: 0.95em; margin-bottom: var(--space-2xs); }


/* ---------- Review challenge ("game" checkpoint node + in-lesson theming) ----------
   Laboratory Orange (--c-warning) is the token spec reserves for practice/optional/timer
   content, so the review game uses it throughout to read as visually distinct from a real
   lesson (cyan) or a unit header (purple), without inventing a new color.

   Sized to match the regular lesson nodes (104px, not smaller) and kept visibly orange even
   while locked (not the same pure grey/disabled treatment as a locked lesson) - it needs to
   read as "a game exists here, come back once you unlock it" rather than fade into the
   background as an inert decoration, which is what a too-small, too-dim node does in practice. */
.review-node { margin-bottom: var(--space-lg); }
.review-circle {
  position: relative;
  width: 104px;
  height: 104px;
  border-radius: 50%;
  background: var(--glass-bg);
  border: 2px solid var(--c-warning-dark);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  cursor: pointer;
  color: var(--c-warning-glow-text);
  box-shadow: 0 0 14px rgba(255, 179, 71, 0.25);
  transition: box-shadow var(--speed-med) var(--ease-smooth);
}
.review-node.state-available .review-circle {
  border-color: var(--c-warning);
  box-shadow: 0 0 24px rgba(255, 179, 71, 0.6);
  animation: review-node-pulse 1.8s ease-in-out infinite;
}
.review-node.state-done .review-circle { border-color: var(--c-success); color: var(--c-success-glow-text); box-shadow: 0 0 18px rgba(61, 220, 151, 0.4); }
.review-node.state-locked .review-circle {
  cursor: not-allowed;
  color: var(--c-warning-glow-text);
  opacity: 0.65;
  box-shadow: none;
}
@keyframes review-node-pulse {
  0%, 100% { box-shadow: 0 0 18px rgba(255, 179, 71, 0.45); transform: scale(1); }
  50% { box-shadow: 0 0 34px rgba(255, 179, 71, 0.85); transform: scale(1.05); }
}
@media (prefers-reduced-motion: reduce) {
  .review-node.state-available .review-circle { animation: none; }
}
.node-review-icon { width: 26px; height: 26px; }
.node-review-icon svg { width: 100%; height: 100%; }
.review-circle .node-label { font-size: 0.66em; font-weight: 800; text-transform: uppercase; letter-spacing: 0.03em; }
.review-circle .node-badge { position: absolute; bottom: 2px; right: 2px; }

.review-head { align-items: center; }
.review-step-label { color: var(--c-warning-glow-text); display: flex; align-items: center; gap: 6px; }
.review-step-label svg { width: 14px; height: 14px; }
.review-streak-badge {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--space-2xs) var(--space-sm);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-default);
  background: var(--glass-bg);
  min-width: 64px;
}
.review-streak-badge.hot { border-color: var(--c-warning); box-shadow: 0 0 14px rgba(255, 179, 71, 0.4); }
.review-streak-value { font-family: var(--font-heading); font-weight: 800; font-size: 1.3em; color: var(--c-warning-glow-text); }
.review-streak-caption { font-size: 0.68em; color: var(--text-secondary); white-space: nowrap; }
.review-card { border-color: var(--c-warning-dark); }
.review-icon-badge { background: rgba(255, 179, 71, 0.14); color: var(--c-warning); }
.review-hearts { display: flex; gap: 4px; margin-top: 6px; }
.review-heart { width: 18px; height: 18px; color: var(--c-error); transition: transform var(--speed-fast) var(--ease-smooth); }
.review-heart.empty { color: var(--text-disabled); opacity: 0.5; }
.review-heart svg { width: 100%; height: 100%; }
.review-timer-track { height: 6px; border-radius: var(--radius-pill); background: var(--border-default); overflow: hidden; margin-top: var(--space-sm); }
.review-timer-fill { height: 100%; background: var(--c-warning); transition: width 1s linear; }

.crossword-card { display: flex; flex-direction: column; gap: var(--space-md); }
/* Fixes real overflow bug: the grid used to be `1fr` columns + per-cell aspect-ratio with no
   fixed height reference, so a wide word could push cells past the viewport with no way to
   reach them (no scroll). Cells now have one fixed, always-tappable size; if the puzzle is wider
   than the screen, THIS wrapper scrolls horizontally on its own - the page itself never does. */
.crossword-grid-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; padding-bottom: 4px; }
.crossword-grid {
  --cw-cell: 32px;
  display: grid;
  gap: 2px;
  width: fit-content;
  margin: 0 auto;
}
@media (max-width: 400px) {
  .crossword-grid { --cw-cell: 28px; }
}
.crossword-cell {
  position: relative;
  width: var(--cw-cell, 32px);
  height: var(--cw-cell, 32px);
  background: var(--bg-main);
  border: 1px solid var(--border-default);
  border-radius: 3px;
}
.crossword-cell.blank { background: transparent; border: none; }
.crossword-number { position: absolute; top: 1px; left: 2px; font-size: 0.55em; font-weight: 800; line-height: 1.3; z-index: 1; padding: 0 3px; border-radius: 5px; }
/* Six-colour rotation (by clue number) instead of one flat muted tone, matching every other
   game's vivid accent treatment. */
.crossword-number.cw-num-1 { color: #1a0b2e; background: var(--c-secondary-glow-text); }
.crossword-number.cw-num-2 { color: #06222b; background: var(--c-primary-glow-text); }
.crossword-number.cw-num-3 { color: #052e1c; background: var(--c-success-glow-text); }
.crossword-number.cw-num-4 { color: #3a2400; background: var(--c-warning-glow-text); }
.crossword-number.cw-num-5 { color: #3a0a20; background: var(--c-pink-glow-text); }
.crossword-number.cw-num-0 { color: #3a2f00; background: var(--c-gold-glow-text); }
.crossword-input {
  width: 100%;
  height: 100%;
  background: transparent;
  border: none;
  text-align: center;
  color: var(--text-primary);
  font-weight: 800;
  font-size: 1em;
  text-transform: uppercase;
  padding: 0;
}
.crossword-input:focus { outline: 2px solid var(--c-primary); outline-offset: -2px; border-radius: 3px; }
.crossword-input.solved { color: var(--c-success-glow-text); background: rgba(61, 220, 151, 0.12); }
.crossword-clues { display: grid; grid-template-columns: 1fr; gap: var(--space-md); }
@media (min-width: 640px) {
  .crossword-clues { grid-template-columns: 1fr 1fr; }
}
.crossword-clues h4 { color: var(--c-warning-glow-text); font-size: 0.85em; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: var(--space-2xs); }
.crossword-clues ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 6px; }
.crossword-clues li { font-size: 0.85em; color: var(--text-secondary); }
.crossword-clues li strong { color: var(--text-primary); }
.crossword-clues li.solved { color: var(--c-success-glow-text); text-decoration: line-through; opacity: 0.7; }

.crossword-stats-row { display: flex; align-items: center; gap: var(--space-2xs); flex-wrap: wrap; margin-bottom: var(--space-sm); }
.crossword-stat {
  display: flex; align-items: center; gap: 6px; font-weight: 700; color: var(--text-secondary); font-size: 0.85em;
  padding: 6px var(--space-xs); border-radius: var(--radius-pill);
  background: var(--bg-card); border: 1px solid var(--border-default);
}
.crossword-stat-icon { font-size: 1.1em; }
.crossword-progress-stat { flex: 1; min-width: 140px; display: flex; flex-direction: column; gap: 4px; padding: 6px var(--space-xs); }
.crossword-progress-track { height: 6px; border-radius: var(--radius-pill); background: var(--border-default); overflow: hidden; }
.crossword-progress-fill { height: 100%; background: var(--c-primary); transition: width var(--speed-med) var(--ease-smooth); }
.pill-count { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; background: var(--c-warning); color: #0d1117; font-size: 0.75em; font-weight: 800; margin-left: 4px; }

.clue-number { color: var(--c-secondary-glow-text); }

.crossword-input.wrong-flash { background: rgba(255, 93, 115, 0.25); color: var(--c-error); }

.crossword-gameover { text-align: center; border-color: var(--c-error); }
.crossword-gameover-sign {
  font-family: var(--font-heading);
  font-weight: 900;
  font-size: 2em;
  letter-spacing: 0.04em;
  color: var(--c-error);
  text-shadow: 0 0 24px rgba(255, 93, 115, 0.6);
  margin: var(--space-sm) 0 0;
}

/* ---------- Auth (login/register/forgot/reset) ---------- */
.auth-screen { display: flex; justify-content: center; padding: var(--space-xl) 0; }
.auth-card { width: min(420px, 100%); }
.auth-subtitle { color: var(--text-secondary); margin-top: -4px; margin-bottom: var(--space-md); }
.auth-form { display: flex; flex-direction: column; gap: var(--space-md); }
.auth-field { display: flex; flex-direction: column; gap: 6px; font-weight: 600; font-size: 0.9em; }
.auth-field input {
  padding: 12px 14px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
  color: var(--text-primary);
  font: inherit;
}
.auth-field input:focus { outline: none; border-color: var(--c-primary); box-shadow: 0 0 0 3px rgba(51, 214, 255, 0.18); }
.auth-form button { margin-top: var(--space-xs); }
.auth-links { display: flex; flex-direction: column; gap: var(--space-xs); margin-top: var(--space-md); align-items: flex-start; }
.link-btn { background: none; border: none; color: var(--c-primary-glow-text); cursor: pointer; font: inherit; padding: 0; text-decoration: underline; }
.auth-error { padding: var(--space-sm); border-radius: var(--radius-md); background: rgba(255, 90, 90, 0.12); border: 1px solid rgba(255, 90, 90, 0.4); color: #ff9b9b; margin-bottom: var(--space-md); }
.auth-notice { padding: var(--space-sm); border-radius: var(--radius-md); background: rgba(51, 214, 255, 0.1); border: 1px solid var(--c-primary-dark); color: var(--c-primary-glow-text); margin-bottom: var(--space-md); }
.auth-actions { display: flex; gap: var(--space-sm); margin-top: var(--space-md); }

/* ---------- Subscribe ---------- */
.subscribe-screen { display: flex; flex-direction: column; gap: var(--space-lg); }
.subscribe-intro p { color: var(--text-secondary); margin-top: var(--space-xs); }
.plan-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--space-md); }
.plan-card { display: flex; flex-direction: column; gap: var(--space-sm); }
.plan-card-bundle { grid-column: 1 / -1; }
.plan-price { font-family: var(--font-heading); font-size: 1.4em; font-weight: 800; }
.plan-price span { font-family: var(--font-body); font-size: 0.55em; font-weight: 500; color: var(--text-secondary); }
.subscribe-terms { display: flex; align-items: flex-start; gap: var(--space-xs); color: var(--text-secondary); }
.subscribe-terms input { margin-top: 3px; }
.subscribe-note { font-size: 0.85em; color: var(--text-secondary); }
.subscribe-owned-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-sm); padding: 6px 0; }

/* ---------- Legal ---------- */
.legal-screen { display: flex; flex-direction: column; gap: var(--space-md); max-width: 760px; }
.legal-tabs { display: flex; gap: var(--space-xs); flex-wrap: wrap; }
.legal-tab {
  padding: 8px 14px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-default);
  background: var(--glass-bg);
  color: var(--text-secondary);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.legal-tab.active { border-color: var(--c-primary); color: var(--c-primary-glow-text); }
.legal-content h2 { margin-top: 0; }
.legal-content h3 { margin-top: var(--space-lg); margin-bottom: var(--space-2xs); }
.legal-updated { color: var(--text-secondary); font-size: 0.85em; margin-top: -4px; }
.legal-list { padding-left: 1.2em; display: flex; flex-direction: column; gap: 6px; }
.legal-content a { color: var(--c-primary-glow-text); }

.node-course-tag {
  display: block;
  text-align: center;
  font-size: 0.68em;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--text-secondary);
  margin-top: 6px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--glass-bg);
  border: 1px solid var(--border-default);
  white-space: nowrap;
}

/* ---------- Profile ---------- */
.profile-screen { display: flex; flex-direction: column; gap: var(--space-lg); }
.profile-identity { display: flex; align-items: center; gap: var(--space-md); flex-wrap: wrap; }
.profile-avatar { width: 56px; height: 56px; font-size: 1.4em; }
.profile-meta { color: var(--text-secondary); font-size: 0.9em; }
.profile-identity > button { margin-left: auto; }
.profile-stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: var(--space-md); }
.profile-stat { align-items: center; text-align: center; gap: 4px; }
.profile-stat-value { font-family: var(--font-heading); font-size: 1.6em; font-weight: 800; color: var(--c-primary-glow-text); }
.profile-stat-label { font-size: 0.8em; color: var(--text-secondary); }
.leaderboard-table, .admin-table { width: 100%; border-collapse: collapse; }
.leaderboard-table th, .leaderboard-table td, .admin-table th, .admin-table td {
  text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--border-default); font-size: 0.9em;
}
.leaderboard-table tr.is-you { background: rgba(51, 214, 255, 0.08); }

/* ---------- Admin ---------- */
.admin-screen { display: flex; flex-direction: column; gap: var(--space-lg); }
.admin-tabs { display: flex; gap: var(--space-xs); flex-wrap: wrap; }
.admin-tab {
  padding: 8px 14px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-default);
  background: var(--glass-bg);
  color: var(--text-secondary);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.admin-tab.active { border-color: var(--c-primary); color: var(--c-primary-glow-text); }
.admin-summary-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: var(--space-md); }
.admin-lessons-card { display: flex; flex-direction: column; gap: var(--space-sm); }
.admin-lessons-head { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: var(--space-sm); }
.admin-course-filter { padding: 8px 10px; border-radius: var(--radius-md); border: 1px solid var(--border-default); background: var(--bg-surface); color: var(--text-primary); font: inherit; }
.admin-table-wrap { overflow-x: auto; }
.admin-row-actions { display: flex; gap: 6px; white-space: nowrap; }
.status-pill { padding: 3px 9px; border-radius: 999px; font-size: 0.75em; font-weight: 700; text-transform: capitalize; }
.status-approved { background: rgba(94, 214, 138, 0.15); color: #7fe3a4; }
.status-rejected { background: rgba(255, 90, 90, 0.15); color: #ff9b9b; }
.status-pending { background: rgba(255, 179, 71, 0.15); color: var(--c-warning-glow-text); }

.admin-preview-overlay {
  position: fixed;
  inset: 0;
  background: rgba(5, 8, 14, 0.72);
  backdrop-filter: blur(6px);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 60;
  padding: var(--space-md);
}
.admin-preview-overlay.active { display: flex; }
.admin-preview-panel {
  width: min(720px, 100%);
  max-height: 86vh;
  display: flex;
  flex-direction: column;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}
.admin-preview-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-sm) var(--space-md);
  border-bottom: 1px solid var(--border-default);
}
.admin-preview-title { font-weight: 700; color: var(--text-secondary); font-size: 0.85em; text-transform: uppercase; letter-spacing: 0.04em; }
.admin-preview-body { padding: var(--space-md); overflow-y: auto; }
.admin-preview-section { margin-top: var(--space-md); }
.admin-preview-section h4 { color: var(--c-primary-glow-text); font-size: 0.85em; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: var(--space-2xs); }
.admin-preview-notes { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 6px; }
.admin-preview-question { padding: var(--space-sm) 0; border-top: 1px solid var(--border-default); }
.admin-preview-question:first-child { border-top: none; padding-top: 0; }
.admin-preview-q-num { color: var(--text-secondary); font-size: 0.8em; font-weight: 700; text-transform: uppercase; margin-bottom: 4px; }
.admin-preview-options { list-style: none; padding: 0; margin: var(--space-2xs) 0 0; display: flex; flex-direction: column; gap: 4px; }
.admin-preview-options li { padding: 6px 10px; border-radius: var(--radius-sm); background: var(--bg-card); font-size: 0.9em; }
.admin-preview-correct { color: var(--c-success-glow-text); border: 1px solid var(--c-success-dark); }

.admin-reset-row { display: flex; gap: var(--space-2xs); flex-wrap: wrap; }
.admin-reset-row input {
  flex: 1;
  min-width: 220px;
  padding: 8px 10px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
  color: var(--text-primary);
  font: inherit;
}

.admin-grant-row { display: flex; gap: var(--space-2xs); flex-wrap: wrap; }
.admin-grant-row input, .admin-grant-row select {
  padding: 8px 10px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
  color: var(--text-primary);
  font: inherit;
}
.admin-grant-row input { flex: 1; min-width: 220px; }
.admin-grant-row select { min-width: 160px; }
.admin-grant-row select#adminGrantEmail { flex: 1; min-width: 260px; }
.admin-grant-row select#adminCancelEmail { flex: 1; min-width: 260px; }
.admin-check { display: flex; align-items: center; gap: 8px; font-size: 0.85em; color: var(--text-secondary); cursor: pointer; }

/* ---------- Games Arcade ---------- */
.games-arcade-screen { display: flex; flex-direction: column; gap: var(--space-md); }
.games-arcade-kicker { color: var(--c-success-glow-text); font-size: 0.8em; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; }
.games-arcade-title { font-family: var(--font-heading); font-weight: var(--weight-heading); font-size: 1.6em; margin: 0; }
.games-arcade-subtitle { color: var(--text-secondary); margin: 0 0 var(--space-sm); }

.games-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: var(--space-md);
}
.game-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  text-align: left;
  padding: var(--space-md);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-default);
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  color: var(--text-primary);
  cursor: pointer;
  transition: transform var(--speed-fast) var(--ease-smooth), border-color var(--speed-fast) var(--ease-smooth), box-shadow var(--speed-fast) var(--ease-smooth);
}
.game-tile:hover { transform: translateY(-2px); border-color: var(--border-glow); }
.game-tile:disabled { cursor: not-allowed; opacity: 0.6; }
.game-tile-number {
  position: absolute; top: var(--space-xs); right: var(--space-sm);
  font-family: var(--font-heading); font-weight: 800; font-size: 0.85em; color: var(--text-disabled);
}
.game-tile-icon { font-size: 1.8em; line-height: 1; }
.game-tile-name { font-family: var(--font-heading); font-weight: 700; font-size: 1.05em; }
.game-tile-tagline { color: var(--text-secondary); font-size: 0.85em; line-height: 1.35; }

.game-tile.accent-cyan   { border-color: var(--c-primary);   box-shadow: 0 0 18px rgba(51, 214, 255, 0.12); }
.game-tile.accent-purple { border-color: var(--c-secondary); box-shadow: 0 0 18px rgba(139, 92, 246, 0.12); }
.game-tile.accent-green  { border-color: var(--c-success);   box-shadow: 0 0 18px rgba(61, 220, 151, 0.12); }
.game-tile.accent-orange { border-color: var(--c-warning);   box-shadow: 0 0 18px rgba(255, 179, 71, 0.12); }
.game-tile.accent-red    { border-color: var(--c-error);     box-shadow: 0 0 18px rgba(255, 93, 115, 0.12); }
.game-tile.accent-pink   { border-color: var(--c-pink);      box-shadow: 0 0 18px rgba(255, 79, 163, 0.12); }
.game-tile.accent-gold   { border-color: var(--c-gold);      box-shadow: 0 0 18px rgba(255, 210, 63, 0.12); }
.game-tile.accent-cyan   .game-tile-icon { color: var(--c-primary-glow-text); }
.game-tile.accent-purple .game-tile-icon { color: var(--c-secondary-glow-text); }
.game-tile.accent-green  .game-tile-icon { color: var(--c-success-glow-text); }
.game-tile.accent-orange .game-tile-icon { color: var(--c-warning-glow-text); }
.game-tile.accent-red    .game-tile-icon { color: var(--c-error-glow-text); }
.game-tile.accent-pink   .game-tile-icon { color: var(--c-pink-glow-text); }
.game-tile.accent-gold   .game-tile-icon { color: var(--c-gold-glow-text); }

/* shared in-game stats row (hearts / streak / hint / timer) reused by every game - rendered as
   bordered pill chips, matching the reference mockups' "STREAK 12 / Best 0" chip look. */
.game-stats-row { display: flex; align-items: center; gap: var(--space-2xs); flex-wrap: wrap; margin-bottom: var(--space-sm); }
.game-stat {
  display: flex; align-items: center; gap: 6px; font-weight: 700; color: var(--text-secondary); font-size: 0.85em;
  padding: 6px var(--space-xs); border-radius: var(--radius-pill);
  background: var(--bg-card); border: 1px solid var(--border-default);
}
.game-stat-icon { font-size: 1.1em; }
.game-hearts { gap: 4px; }
.game-heart { font-size: 1.3em; line-height: 1; display: inline-block; }
/* Vivid, pulsing neon red instead of a flat static glyph - a strike lost should feel like it. */
.game-heart.filled {
  color: #FF2D55;
  text-shadow: 0 0 6px rgba(255, 45, 85, 0.85), 0 0 14px rgba(255, 45, 85, 0.55);
  animation: game-heart-pulse 1.1s ease-in-out infinite;
}
.game-heart.empty { color: var(--text-disabled); }
@keyframes game-heart-pulse {
  0%, 100% { transform: scale(1); text-shadow: 0 0 6px rgba(255, 45, 85, 0.8), 0 0 14px rgba(255, 45, 85, 0.5); }
  50% { transform: scale(1.2); text-shadow: 0 0 10px rgba(255, 45, 85, 1), 0 0 26px rgba(255, 45, 85, 0.85); }
}
@media (prefers-reduced-motion: reduce) {
  .game-heart.filled { animation: none; text-shadow: 0 0 8px rgba(255, 45, 85, 0.9), 0 0 18px rgba(255, 45, 85, 0.6); }
}
.game-streak { border-color: var(--c-gold); background: rgba(255, 210, 63, 0.08); }
.game-streak .game-stat-icon { color: var(--c-gold); }

/* Level + round chip (Easy -> Medium -> Hard, "Round 3/8"). Keeps its tinted pill even in
   game-mode, where the other stat chips drop their frame, so the current level always reads. */
.game-level, .lesson-shell.game-mode .game-level { gap: 8px; padding: 6px var(--space-xs); border: 1px solid; }
.game-level-name { text-transform: uppercase; letter-spacing: 0.06em; }
.game-level-round { font-weight: 600; opacity: 0.85; }
.game-level-easy, .lesson-shell.game-mode .game-level-easy { color: var(--c-success-glow-text); border-color: var(--c-success); background: rgba(61, 220, 151, 0.12); }
.game-level-medium, .lesson-shell.game-mode .game-level-medium { color: var(--c-warning-glow-text); border-color: var(--c-warning); background: rgba(255, 179, 71, 0.12); }
.game-level-hard, .lesson-shell.game-mode .game-level-hard { color: var(--c-error-glow-text); border-color: var(--c-error); background: rgba(255, 93, 115, 0.12); }
.game-level-up { animation: game-level-up-pop 0.9s ease-out 2; }
@keyframes game-level-up-pop {
  0%, 100% { transform: scale(1); box-shadow: none; }
  40% { transform: scale(1.12); box-shadow: 0 0 22px currentColor; }
}
@media (prefers-reduced-motion: reduce) {
  .game-level-up { animation: none; box-shadow: 0 0 14px currentColor; }
}

/* shared win / lose screens */
/* A red danger-flash across the whole screen (fixed, so it covers the viewport regardless of the
   game shell's own scroll position), pulsing three times with a glowing red edge vignette. Simpler
   and more legible than an illustrated explosion, and reads instantly regardless of screen size. */
.strikeout-flash {
  position: fixed; inset: 0; z-index: 9999; pointer-events: none;
  animation: strikeout-flash-pulse 0.45s ease-in-out 3;
}
@keyframes strikeout-flash-pulse {
  0%, 100% { background: rgba(255, 45, 85, 0); box-shadow: inset 0 0 0 0 rgba(255, 45, 85, 0); }
  50% { background: rgba(255, 45, 85, 0.55); box-shadow: inset 0 0 110px 40px rgba(255, 45, 85, 1); }
}
/* Reduced motion still needs to read as "three flashes", not one static held tint (which is all a
   single non-animating frame can ever look like) - opacity-only pulsing has no scale/size change
   and no large-scale movement, which is what "reduced motion" actually cares about avoiding, so
   this stays within that preference while still counting to three. */
@media (prefers-reduced-motion: reduce) {
  .strikeout-flash {
    background: rgba(255, 45, 85, 0.45);
    box-shadow: inset 0 0 110px 40px rgba(255, 45, 85, 0.9);
    animation: strikeout-flash-pulse-simple 0.45s ease-in-out 3;
  }
}
@keyframes strikeout-flash-pulse-simple {
  0%, 100% { opacity: 0; }
  50% { opacity: 1; }
}
/* Holds at (roughly) the pulse's peak look instead of fading away right before the round-over
   card appears - the red glow becomes that screen's backdrop, not something that just vanished
   a moment before the message explaining why it happened. Cleared by closeGameShell() once the
   player actually leaves the screen. */
.strikeout-flash-frozen {
  animation: none;
  opacity: 1;
  background: rgba(255, 45, 85, 0.32);
  box-shadow: inset 0 0 110px 40px rgba(255, 45, 85, 0.75);
  transition: background 0.4s ease, box-shadow 0.4s ease;
}
/* The board fades out once the flashing stops, then the round-over card fades back in through the
   same class being removed - a crossfade instead of the content just cutting straight from board
   to end screen the instant the flashes finish. */
#lessonShellBody.lesson-body-fadeout { opacity: 0; transition: opacity 0.4s ease; }
#lessonShellBody { transition: opacity 0.4s ease; }
.game-end-card { text-align: center; display: flex; flex-direction: column; align-items: center; gap: var(--space-2xs); }
.game-end-badge { font-size: 2.2em; line-height: 1; margin-bottom: var(--space-2xs); }
.game-end-sign {
  font-family: var(--font-heading);
  font-weight: 900;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 0.85em;
}
.game-end-win .game-end-sign { color: var(--c-success-glow-text); }
.game-end-lose .game-end-sign { color: var(--c-error-glow-text); }
.game-end-lose { border-color: var(--c-error); }
.game-end-xp { color: var(--c-gold-glow-text); font-weight: 800; font-size: 1.1em; }

/* ---------- Bond Battle ----------
   Mobile-first "VS arena": the two atoms MUST stay side-by-side with VS between them on a phone
   screen, never stack vertically - that's the whole visual point of a "battle". Widths below are
   sized so two sides + the VS glyph fit inside a 320px viewport with room to spare. */
.bond-battle-arena { display: flex; align-items: center; justify-content: center; gap: var(--space-sm); margin: var(--space-md) 0; }
/* No card/box around each atom - it floats directly on the vibrant arena background. The atom's
   own colour (via the glow) is what marks it as "a side", not a bordered rectangle. */
.bond-battle-side {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  flex: 1 1 0;
  min-width: 0;
  max-width: 140px;
}
.bond-battle-orb {
  width: 76px; height: 76px; border-radius: 50%; display: grid; place-items: center; flex-shrink: 0;
  box-shadow:
    0 0 0 2px rgba(255, 255, 255, 0.3) inset,
    0 -10px 16px rgba(0, 0, 0, 0.4) inset,
    0 0 8px 2px var(--orb-color, transparent),
    0 0 34px 10px var(--orb-color, transparent),
    0 10px 20px rgba(0, 0, 0, 0.5);
  filter: saturate(1.45) brightness(1.1);
  animation: bond-orb-pulse 3.6s ease-in-out infinite;
}
.bond-battle-side.side-b .bond-battle-orb { animation-delay: -1.8s; }
@keyframes bond-orb-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.045); }
}
@media (prefers-reduced-motion: reduce) { .bond-battle-orb { animation: none; } }
.bond-battle-symbol {
  font-family: var(--font-heading); font-weight: 900; font-size: 1.5em;
  color: var(--text-primary); text-shadow: 0 1px 3px var(--bg-main), 0 -1px 3px var(--bg-main);
}
.bond-battle-name { color: var(--text-primary); font-weight: 700; font-size: 0.85em; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.bond-battle-vs {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  font-family: var(--font-heading); font-weight: 900; font-size: 1.15em; color: var(--text-primary); flex-shrink: 0;
  text-shadow: 0 0 10px rgba(155, 235, 255, 0.7);
}
/* A real jagged electric bolt (SVG, not an emoji) with a white-hot core fading to electric blue,
   plus a flicker/surge animation - a smooth pulse reads as "glowing", a flicker reads as
   "electric". */
.bond-battle-vs-bolt-svg {
  width: 38px; height: 38px;
  filter: drop-shadow(0 0 4px #fff) drop-shadow(0 0 14px #9BEBFF) drop-shadow(0 0 26px rgba(51, 214, 255, 0.85));
  animation: bond-bolt-flicker 1.6s ease-in-out infinite;
}
@keyframes bond-bolt-flicker {
  0%, 100% { opacity: 1; filter: drop-shadow(0 0 4px #fff) drop-shadow(0 0 14px #9BEBFF) drop-shadow(0 0 26px rgba(51, 214, 255, 0.85)); }
  42% { opacity: 0.8; }
  48% { opacity: 1; filter: drop-shadow(0 0 7px #fff) drop-shadow(0 0 22px #C7F5FF) drop-shadow(0 0 40px rgba(51, 214, 255, 1)); }
  54% { opacity: 0.88; }
}
@media (prefers-reduced-motion: reduce) { .bond-battle-vs-bolt-svg { animation: none; } }
.bond-battle-question { text-align: center; color: var(--c-primary-glow-text); margin-bottom: var(--space-sm); font-size: 0.95em; }
/* Single row of 4, matching the reference - not a 2x2 grid. Compact padding/font + word-break
   so "HYDROGEN BOND" can wrap onto its own second line inside a narrow phone-width column.
   Each bond type gets its own vibrant gradient + glow (not a flat dark box with a thin cyan
   outline) so the options read as game chips, not form fields. */
.bond-battle-options { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.bond-battle-options .btn {
  width: 100%; padding: 8px 2px; font-size: 0.6em; line-height: 1.2;
  white-space: normal; overflow-wrap: normal; min-height: 44px;
  border: 2px solid var(--border-default); border-bottom: 2px solid var(--border-default);
  background: var(--bg-card); color: var(--text-primary);
}
.bond-battle-options .btn[data-bond-type="Ionic Bond"] {
  background: linear-gradient(160deg, rgba(139, 92, 246, 0.5), rgba(20, 12, 36, 0.55));
  border-color: var(--c-secondary); box-shadow: 0 0 16px rgba(139, 92, 246, 0.4);
}
.bond-battle-options .btn[data-bond-type="Covalent Bond"] {
  background: linear-gradient(160deg, rgba(51, 214, 255, 0.5), rgba(6, 26, 34, 0.55));
  border-color: var(--c-primary); box-shadow: 0 0 16px rgba(51, 214, 255, 0.4);
}
.bond-battle-options .btn[data-bond-type="Metallic Bond"] {
  background: linear-gradient(160deg, rgba(255, 210, 63, 0.5), rgba(38, 30, 6, 0.55));
  border-color: var(--c-gold); box-shadow: 0 0 16px rgba(255, 210, 63, 0.4);
}
.bond-battle-options .btn[data-bond-type="Hydrogen Bond"] {
  background: linear-gradient(160deg, rgba(255, 79, 163, 0.5), rgba(38, 8, 26, 0.55));
  border-color: var(--c-pink); box-shadow: 0 0 16px rgba(255, 79, 163, 0.4);
}
.bond-battle-options .btn.correct { background: var(--c-success-dark); border-color: var(--c-success); box-shadow: 0 0 20px rgba(61, 220, 151, 0.55); }
.bond-battle-options .btn.wrong { background: var(--c-error-dark); border-color: var(--c-error); box-shadow: 0 0 20px rgba(255, 93, 115, 0.55); }
.bond-battle-notation {
  margin-top: var(--space-sm); text-align: center; font-family: var(--font-heading); font-weight: 800;
  font-size: 1.05em; color: var(--text-primary); min-height: 1.4em;
}
.bond-battle-notation sup { color: var(--c-gold-glow-text); font-size: 0.7em; }
.bond-battle-feedback { margin-top: var(--space-sm); text-align: center; font-weight: 700; }
.bond-battle-feedback.correct { color: var(--c-success-glow-text); }
.bond-battle-feedback.wrong { color: var(--c-error-glow-text); }
@media (max-width: 360px) {
  .bond-battle-orb { width: 62px; height: 62px; }
  .bond-battle-symbol { font-size: 1.25em; }
}

/* ---------- Molecule Detective ---------- */
/* No panel - clues and structure float directly on the game-mode space background instead of
   sitting in their own bordered boxes (same treatment as Equilibrium Shift/Electron Rush).
   Specificity note: .lesson-shell.game-mode .activity-card/.reactants-box are 2-3 classes deep
   and win over a bare .md-card rule, so this has to match/beat that to actually take effect. */
.lesson-shell.game-mode .md-card { border-color: transparent; background: none; box-shadow: none; }
.lesson-shell.game-mode .md-card .reactants-box { background: none; box-shadow: none; padding: 0; }
.md-layout { display: grid; grid-template-columns: 1fr; gap: var(--space-md); }
@media (min-width: 640px) { .md-layout { grid-template-columns: 1.4fr 1fr; } }
.md-clue-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.md-clue-list li { font-size: 0.9em; color: var(--text-primary); padding-left: 14px; position: relative; }
/* A coloured tick mark instead of a magnifying-glass emoji - no clip-art symbols. */
.md-clue-list li::before {
  content: ""; position: absolute; left: 0; top: 0.5em; width: 7px; height: 7px;
  border-radius: 50%; background: var(--c-pink); box-shadow: 0 0 6px rgba(255, 79, 163, 0.7);
}
.md-structure-box { border: none; padding: var(--space-sm) 0 0; display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; }
.md-structure {
  font-family: var(--font-heading); font-weight: 800; font-size: 1.2em; color: var(--c-pink-glow-text); margin: 0;
  text-shadow: 0 0 10px rgba(255, 79, 163, 0.6), 0 0 20px rgba(255, 79, 163, 0.3);
  animation: md-structure-pulse 2.2s ease-in-out infinite;
}
@keyframes md-structure-pulse {
  0%, 100% { text-shadow: 0 0 8px rgba(255, 79, 163, 0.5), 0 0 16px rgba(255, 79, 163, 0.25); }
  50% { text-shadow: 0 0 14px rgba(255, 79, 163, 0.85), 0 0 28px rgba(255, 79, 163, 0.45); }
}
@media (prefers-reduced-motion: reduce) {
  .md-structure { animation: none; }
}
/* Timer urgency - calm chip until 5s left, then bigger, red, and shaking (same treatment as
   Electron Rush's countdown). */
.md-timer-urgent {
  color: var(--c-error-glow-text); background: rgba(255, 93, 115, 0.14); border: 1px solid var(--c-error);
  transform: scale(1.3); font-size: 1.05em; font-weight: 900;
  animation: md-timer-shake 0.4s ease-in-out infinite;
}
@keyframes md-timer-shake {
  0%, 100% { transform: scale(1.3) translateX(0); }
  25% { transform: scale(1.3) translateX(-2px) rotate(-3deg); }
  75% { transform: scale(1.3) translateX(2px) rotate(3deg); }
}

/* A distant planet drifting slowly across the sky - ambient, not tied to any game event. Crosses
   over roughly the first half of the (long) animation cycle, then sits off-screen for the rest,
   so it reads as an occasional flyby rather than something constantly happening. */
.md-planet {
  position: fixed; top: 12vh; left: -18vw; width: 46px; height: 46px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #C9B8FF 0%, #8B5CF6 45%, #4527A0 100%);
  box-shadow: 0 0 24px 6px rgba(139, 92, 246, 0.4), inset -10px -6px 14px rgba(0, 0, 0, 0.35);
  /* .lesson-shell (the fullscreen game overlay) is z-index:50 - this needs to clear that to
     actually render in front of the game screen instead of silently sitting behind it (same
     z-index as .er-meteor/.eq-shooting-star, the other "appended to body" ambient effects). */
  pointer-events: none; z-index: 999; animation: md-planet-drift 34s linear infinite;
}
.md-planet::after {
  content: ""; position: absolute; top: 50%; left: 50%; width: 78px; height: 16px;
  border: 2px solid rgba(201, 184, 255, 0.55); border-radius: 50%;
  transform: translate(-50%, -50%) rotate(-18deg);
}
@keyframes md-planet-drift {
  0% { left: -18vw; top: 12vh; opacity: 0; }
  4% { opacity: 1; }
  46% { opacity: 1; }
  50% { left: 108vw; top: 20vh; opacity: 0; }
  100% { left: 108vw; top: 20vh; opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .md-timer-urgent { animation: none; }
}
.md-candidates { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--space-2xs); margin-top: var(--space-sm); }
.md-candidate {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  border: 2px solid var(--border-default); border-radius: var(--radius-md);
  padding: var(--space-2xs) var(--space-sm); background: var(--bg-main); color: var(--text-primary); text-align: left; cursor: pointer;
}
.md-candidate-letter { font-family: var(--font-heading); font-weight: 800; color: var(--c-pink-glow-text); font-size: 0.8em; }
.md-candidate-name { font-weight: 700; }
.md-candidate-formula { color: var(--text-secondary); font-size: 0.82em; }
.md-candidate.correct { border-color: var(--c-success); background: rgba(61, 220, 151, 0.1); }
.md-candidate.wrong { border-color: var(--c-error); background: rgba(255, 93, 115, 0.1); }
.md-candidate.eliminated { opacity: 0.35; }
.md-candidate:disabled { cursor: default; }

/* ---------- Equilibrium Shift ---------- */
/* A warm/cool dual glow wash instead of the flat translucent default - this game's whole point is
   two sides pulling against each other, so the card itself should feel like it's between them. */
/* No panel at all - content floats directly on the game-mode space background instead of sitting
   in its own card, so nothing here reads as a separate box floating on top of another box.
   Specificity note: .lesson-shell.game-mode .activity-card (two classes) sets background/border/
   shadow, so a bare .eq-shift-card rule (one class) loses that fight - this has to match or beat
   it to actually take effect. */
.lesson-shell.game-mode .eq-shift-card {
  border-color: transparent;
  background: none;
  box-shadow: none;
}
/* No nested box for the reaction line - it sits straight on the card's own glow wash instead of
   inside yet another bordered/shadowed panel (the "cards within cards" complaint).
   Specificity note: same issue as the card border above - .lesson-shell.game-mode .reactants-box
   is three classes deep and was still winning over the plain two-class .eq-shift-card version. */
.lesson-shell.game-mode .eq-shift-card .reactants-box {
  background: none;
  box-shadow: none;
  padding: 0 0 var(--space-sm);
}
/* Same rule for Equilibrium Shift's stat chips - the only borders left anywhere on this screen
   should be the interactive controls (Next Wave, Left, Right, No Change). */
.eq-shift-stats .game-stat, .eq-shift-stats .game-hearts {
  background: none;
  border: none;
  padding: 6px 4px;
}
/* Bold, glowing, gently pulsing - no bounding box (the reaction box above is already one). */
.eq-shift-banner {
  text-align: center; font-family: var(--font-heading); font-weight: 900; font-size: 1.3em;
  letter-spacing: 0.01em; color: var(--c-gold-glow-text); margin: 0 0 4px;
  text-shadow: 0 0 10px rgba(255, 210, 63, 0.6), 0 0 22px rgba(255, 210, 63, 0.35);
  animation: eq-banner-pulse 2s ease-in-out infinite;
}
@keyframes eq-banner-pulse {
  0%, 100% { text-shadow: 0 0 8px rgba(255, 210, 63, 0.5), 0 0 18px rgba(255, 210, 63, 0.28); transform: scale(1); }
  50% { text-shadow: 0 0 14px rgba(255, 210, 63, 0.85), 0 0 30px rgba(255, 210, 63, 0.5); transform: scale(1.035); }
}
.eq-shift-hint { text-align: center; font-size: 0.8em; color: var(--text-muted); font-style: italic; margin-bottom: var(--space-sm); }

/* The balance scale: an idle "sway" group (always gently rocking, purely for life/energy) wraps
   the beam group that the drag actually drives - keeping the two animations on separate elements
   means the JS-driven tilt and the ambient CSS keyframe never fight over the same transform. */
.eq-scale-wrap { display: flex; justify-content: center; margin: 0 0 var(--space-sm); }
.eq-scale { width: 200px; height: auto; overflow: visible; }
.eq-scale-halo { fill: url(#eqHaloGrad); animation: eq-halo-pulse 2.2s ease-in-out infinite; }
@keyframes eq-halo-pulse { 0%, 100% { opacity: 0.35; } 50% { opacity: 0.7; } }
.eq-scale-base, .eq-scale-pole { fill: var(--text-disabled); }
.eq-scale-pivot { fill: var(--c-gold); filter: drop-shadow(0 0 6px rgba(255, 210, 63, 0.85)); }
.eq-scale-beam { fill: var(--text-secondary); }
.eq-scale-chain { stroke: var(--text-disabled); stroke-width: 2; }
.eq-scale-pan-left { fill: url(#eqPanLeftGrad); filter: drop-shadow(0 0 10px rgba(255, 138, 61, 0.6)); }
.eq-scale-pan-right { fill: url(#eqPanRightGrad); filter: drop-shadow(0 0 10px rgba(51, 214, 255, 0.6)); }
.eq-scale-sway { transform-origin: 150px 40px; animation: eq-scale-sway 3.6s ease-in-out infinite; }
@keyframes eq-scale-sway { 0%, 100% { transform: rotate(-2deg); } 50% { transform: rotate(2deg); } }
.eq-scale-beam-group { transform-origin: 150px 40px; transition: transform 0.55s cubic-bezier(0.34, 1.56, 0.64, 1); }
@media (prefers-reduced-motion: reduce) {
  .eq-scale-sway, .eq-scale-halo { animation: none; }
}

/* A quick comet streaking across the sky on every answer tap - see spawnEquilibriumShootingStar(). */
.eq-shooting-star {
  position: fixed; width: 3px; height: 3px; border-radius: 50%; background: #fff;
  box-shadow: 0 0 6px 2px rgba(255, 255, 255, 0.9), 0 0 16px 4px rgba(150, 210, 255, 0.65);
  pointer-events: none; z-index: 999; animation: eq-shooting-star-fly 900ms ease-out forwards;
}
.eq-shooting-star::before {
  content: ""; position: absolute; top: 50%; right: 100%; width: 90px; height: 2px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.75));
  transform-origin: right center; transform: translateY(-50%) rotate(24deg);
}
@keyframes eq-shooting-star-fly {
  0% { transform: translate(0, 0) scale(0.4); opacity: 0; }
  12% { opacity: 1; }
  78% { opacity: 1; }
  100% { transform: translate(78vw, 34vh) scale(1); opacity: 0; }
}

.eq-shift-row { display: flex; align-items: stretch; gap: var(--space-2xs); }
/* Flat vibrant fills, no border/box - tap any of the three to answer. */
.eq-shift-handle, .eq-shift-none {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; padding: var(--space-2xs) var(--space-3xs); border: none; border-radius: var(--radius-md);
  font-weight: 800; font-size: 0.9em; text-align: center; line-height: 1.25; color: var(--text-primary);
  cursor: pointer; user-select: none;
  transition: box-shadow var(--speed-fast) var(--ease-smooth);
}
.eq-shift-handle small, .eq-shift-none { font-weight: 400; opacity: 0.85; }
.eq-shift-handle { background: linear-gradient(160deg, var(--handle-color-a), var(--handle-color-b)); animation: eq-handle-glow 1.8s ease-in-out infinite; }
.eq-shift-left { --handle-color-a: #FFB35C; --handle-color-b: #FF6A1E; --handle-glow: rgba(255, 138, 61, 0.55); }
.eq-shift-right { --handle-color-a: #6FE9FF; --handle-color-b: #12B8E8; --handle-glow: rgba(51, 214, 255, 0.55); }
@keyframes eq-handle-glow {
  0%, 100% { box-shadow: 0 0 12px var(--handle-glow); }
  50% { box-shadow: 0 0 24px var(--handle-glow); }
}
.eq-shift-arrow { font-size: 1.3em; animation: eq-shift-nudge 1.4s ease-in-out infinite; }
.eq-shift-left .eq-shift-arrow { animation-name: eq-shift-nudge-left; }
.eq-shift-right .eq-shift-arrow { animation-name: eq-shift-nudge-right; }
@keyframes eq-shift-nudge-left { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(-5px); } }
@keyframes eq-shift-nudge-right { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(5px); } }
/* flex-basis 0 keeps "No Change" narrower than the two pull handles - it's a tap, not a gesture. */
.eq-shift-none { flex: 0 1 84px; background: var(--bg-card); }
/* The glow itself only ever existed inside the eq-handle-glow keyframe - disabling the animation
   for reduced-motion left NO box-shadow at all instead of a dimmer static one, which is exactly
   the "handles lost their vibrancy" regression this fixes. */
@media (prefers-reduced-motion: reduce) {
  .eq-shift-arrow, .eq-shift-banner { animation: none; }
  .eq-shift-handle { animation: none; box-shadow: 0 0 18px var(--handle-glow); }
}
[data-shift].correct { background: var(--c-success-dark) !important; box-shadow: 0 0 18px rgba(61, 220, 151, 0.55) !important; animation: none !important; }
[data-shift].wrong { background: var(--c-error-dark) !important; box-shadow: 0 0 18px rgba(255, 93, 115, 0.55) !important; animation: none !important; }

/* ---------- Potion Lab ---------- */
.reaction-type-option.correct { border-color: var(--c-success); background: rgba(61, 220, 151, 0.1); }
.reaction-type-option.wrong { border-color: var(--c-error); background: rgba(255, 93, 115, 0.1); }
/* No panel - the target box floats directly on the game-mode space background instead of sitting
   in its own bordered panel (same treatment as the other reworked games).
   Specificity note: .lesson-shell.game-mode .activity-card/.reactants-box are 2-3 classes deep
   and win over a bare .potion-card rule, so this has to match/beat that to actually take effect. */
.lesson-shell.game-mode .potion-card { border-color: transparent; background: none; box-shadow: none; }
.lesson-shell.game-mode .potion-card .reactants-box { background: none; box-shadow: none; padding: 0 0 var(--space-sm); }
/* Hearts/streak/best also blend in - no bordered pill chips, just icon+text floating on the
   background (same treatment as Equilibrium Shift's stats row). */
.potion-stats .game-stat, .potion-stats .game-hearts, .potion-stats .game-streak {
  background: none; border: none; padding: 6px 4px;
}

/* The cauldron IS the round timer: it sits top-right and a drip of poison grows down the whole
   screen over POTION_LAB_TIME_SECONDS: (30s) - reaching the bottom means time's up. Re-rendered
   fresh with every round (not appended once to body like the ambient effects elsewhere), so it
   naturally resets each question. top:58px clears the avatar/back-button row at the very top;
   the drip's real deadline is a JS setTimeout (see renderPotionLabRound), NOT this animation's
   completion, so the round still times out correctly even when the animation itself is disabled
   under prefers-reduced-motion. */
.potion-timer-cauldron { position: fixed; top: 58px; right: 10px; width: 100px; height: 92px; z-index: 999; pointer-events: none; }
/* Ominous pulsing green haze behind the whole thing - "menacing", not a tidy little icon. */
.potion-cauldron-glow {
  position: absolute; top: 8px; left: 8px; width: 84px; height: 60px; border-radius: 50%;
  background: radial-gradient(circle, rgba(139, 255, 60, 0.55), transparent 70%);
  filter: blur(6px); animation: potion-glow-pulse 2.4s ease-in-out infinite;
}
@keyframes potion-glow-pulse { 0%, 100% { opacity: 0.6; transform: scale(1); } 50% { opacity: 1; transform: scale(1.15); } }
.potion-cauldron-svg { position: absolute; inset: 0; width: 100%; height: 100%; filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.55)); }
.potion-mini-liquid {
  position: absolute; top: 12px; left: 14px; width: 71px; height: 18px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #BAFF5C, #4CAF1E 60%, #1F6B0A 100%);
  box-shadow: 0 0 16px 5px rgba(139, 255, 60, 0.65);
  overflow: hidden;
}
/* Real bubbling texture, not a flat blob - reuses the tiled-radial-gradient trick from the
   game-mode starfield background, scaled to this liquid's size. */
.potion-mini-liquid::before {
  content: ""; position: absolute; inset: 0;
  background-image:
    radial-gradient(circle, rgba(255, 255, 255, 0.9) 2px, transparent 3px),
    radial-gradient(circle, rgba(255, 255, 255, 0.6) 1.4px, transparent 3px);
  background-size: 11px 11px, 16px 16px;
  animation: potion-fizz 1.1s linear infinite;
}
@keyframes potion-fizz {
  from { background-position: 0 0, 0 0; }
  to { background-position: 0 -22px, 0 -32px; }
}
/* Belches of poison that pop up above the rim and fall back - the "spewing", on top of the
   continuous drip below. */
.potion-belch {
  position: absolute; top: 8px; width: 13px; height: 13px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #D4FF9E, #6FBF2E);
  box-shadow: 0 0 10px rgba(139, 255, 60, 0.75);
  opacity: 0; animation: potion-belch-pop 2.8s ease-in infinite;
}
.potion-belch-1 { left: 30px; animation-delay: 0s; }
.potion-belch-2 { left: 58px; width: 10px; height: 10px; animation-delay: 1.4s; }
@keyframes potion-belch-pop {
  0% { transform: translateY(0) scale(0.5); opacity: 0; }
  20% { opacity: 1; }
  50% { transform: translateY(-16px) scale(1.15); opacity: 1; }
  100% { transform: translateY(6px) scale(0.7); opacity: 0; }
}
.potion-drip {
  position: fixed; top: 70px; right: 32px; width: 7px; height: calc(100vh - 70px);
  background: linear-gradient(180deg, #8FE050, #4CAF1E 40%, #1F6B0A 100%);
  border-radius: 4px; box-shadow: 0 0 10px rgba(139, 255, 60, 0.55);
  transform-origin: top; transform: scaleY(0);
  animation: potion-drip-fall 30s linear forwards;
  z-index: 999; pointer-events: none;
}
@keyframes potion-drip-fall {
  to { transform: scaleY(1); }
}
@media (prefers-reduced-motion: reduce) {
  .potion-drip { animation: none; transform: scaleY(0.04); }
  .potion-cauldron-glow, .potion-mini-liquid::before, .potion-belch { animation: none; }
  .potion-belch { opacity: 0; }
}

/* ---------- Reaction Chain ---------- */
/* ---------- Reaction Chain (drag-and-drop) ---------- */
.chain-track { display: flex; flex-direction: column; align-items: stretch; margin-bottom: var(--space-sm); }
/* The connector is the "chain" itself - a vibrant pulsing bar linking each reaction link to the
   next. Dim/static while it leads to a still-locked step; lights up once that link is reachable. */
.chain-connector { width: 5px; height: 20px; margin: 2px auto; border-radius: var(--radius-pill); align-self: center; background: var(--border-default); }
.chain-connector.active {
  background: var(--gradient-primary);
  box-shadow: 0 0 10px rgba(155, 92, 255, 0.6);
  animation: chain-connector-pulse 1.4s ease-in-out infinite;
}
@keyframes chain-connector-pulse {
  0%, 100% { opacity: 0.7; box-shadow: 0 0 8px rgba(155, 92, 255, 0.5); }
  50% { opacity: 1; box-shadow: 0 0 18px rgba(155, 92, 255, 0.95); }
}
.chain-link {
  display: flex; flex-direction: column; gap: 2px; padding: var(--space-2xs) var(--space-sm);
  border-radius: var(--radius-sm); border: 1px solid var(--border-default); background: var(--bg-main);
}
.chain-link-label { font-size: 0.78em; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-secondary); }
.chain-link-eq { font-family: var(--font-heading); font-weight: 700; color: var(--text-primary); }
.chain-link.locked { opacity: 0.45; }
.chain-link.done { border-color: var(--c-success); background: rgba(61, 220, 151, 0.08); }
.chain-link.done .chain-link-label { color: var(--c-success-glow-text); }
.chain-link.done.was-wrong { border-color: var(--c-warning); background: rgba(255, 179, 71, 0.08); }
.chain-link.done.was-wrong .chain-link-label { color: var(--c-warning-glow-text); }
/* The one open slot - dashed, glowing, unmistakably "drop it here". */
.chain-link.current {
  border: 2px dashed var(--c-primary);
  background: rgba(51, 214, 255, 0.08);
  animation: chain-zone-pulse 1.6s ease-in-out infinite;
}
.chain-link.current .chain-link-placeholder { color: var(--c-primary-glow-text); font-style: italic; font-size: 0.9em; }
.chain-link.current.drag-over { border-color: var(--c-gold); background: rgba(255, 210, 63, 0.16); box-shadow: 0 0 22px rgba(255, 210, 63, 0.5); animation: none; }
@keyframes chain-zone-pulse {
  0%, 100% { box-shadow: 0 0 8px rgba(51, 214, 255, 0.35); }
  50% { box-shadow: 0 0 20px rgba(51, 214, 255, 0.75); }
}
.chain-link.just-filled { animation: chain-link-solve-flash 0.7s ease-out; }
@keyframes chain-link-solve-flash {
  0% { box-shadow: 0 0 0 rgba(61, 220, 151, 0); background: rgba(61, 220, 151, 0.35); }
  100% { box-shadow: 0 0 24px rgba(61, 220, 151, 0.4); background: rgba(61, 220, 151, 0.08); }
}
.chain-link.wrong-flash { animation: chain-link-wrong-flash 0.7s ease-out; }
@keyframes chain-link-wrong-flash {
  0% { box-shadow: 0 0 0 rgba(255, 93, 115, 0); background: rgba(255, 93, 115, 0.35); }
  100% { box-shadow: 0 0 18px rgba(255, 93, 115, 0.3); background: rgba(255, 179, 71, 0.08); }
}
@media (prefers-reduced-motion: reduce) {
  .chain-connector.active, .chain-link.current { animation: none; }
}

/* The three draggable "puzzle piece" reactions waiting to be placed. */
.reaction-chain-tray { display: flex; flex-direction: column; gap: var(--space-2xs); margin-top: var(--space-sm); }
.chain-card {
  padding: var(--space-2xs) var(--space-sm); border-radius: var(--radius-sm);
  border: 1px solid var(--border-default); background: var(--bg-card); color: var(--text-primary);
  font-weight: 700; cursor: grab; touch-action: none; user-select: none;
  transition: box-shadow var(--speed-fast) var(--ease-smooth);
}
.chain-card:active { cursor: grabbing; }
.chain-card.dragging { box-shadow: 0 12px 28px rgba(0, 0, 0, 0.45), 0 0 20px rgba(155, 92, 255, 0.4); opacity: 0.95; }
.chain-card.placed-correct { border-color: var(--c-success); background: var(--c-success-dark); opacity: 0.5; }
.chain-card.placed-wrong { border-color: var(--c-error); background: var(--c-error-dark); opacity: 0.5; }

/* ---------- Electron Rush ---------- */
/* No panel - target configuration and orbital boxes float directly on the game-mode space
   background instead of sitting in their own card (same treatment as Equilibrium Shift).
   Specificity note: .lesson-shell.game-mode .activity-card/.reactants-box are 2-3 classes deep
   and win over a bare .er-card rule, so this has to match/beat that to actually take effect. */
.lesson-shell.game-mode .er-card { border-color: transparent; background: none; box-shadow: none; }
.lesson-shell.game-mode .er-card .reactants-box { background: none; box-shadow: none; padding: 0 0 var(--space-sm); }

.er-subshells { display: flex; flex-direction: column; gap: var(--space-2xs); margin: var(--space-sm) 0; }
.er-subshell-row { display: flex; align-items: center; gap: var(--space-sm); }
.er-subshell-label { width: 36px; flex-shrink: 0; font-weight: 800; color: var(--c-primary-glow-text); }
.er-boxes { display: flex; gap: 4px; }
.er-box {
  width: 34px; height: 34px; border-radius: var(--radius-sm);
  border: 2px solid var(--border-default); background: var(--bg-main);
  /* The default <button> UA padding (~6px sides) left only 30px for content - "up-down" arrows
     at 1.1em need 36px, so they overflowed the box on both sides. Zero padding + flex centering
     + a touch of negative letter-spacing brings both glyphs comfortably inside the 34px box. */
  padding: 0; display: flex; align-items: center; justify-content: center;
  font-size: 1em; line-height: 1; letter-spacing: -2px; cursor: pointer;
  /* Neon arrow glyphs - electric cyan, glowing, instead of plain white text. */
  color: var(--c-primary-glow-text);
  text-shadow: 0 0 6px rgba(51, 214, 255, 0.85), 0 0 14px rgba(51, 214, 255, 0.55);
}
.er-box:hover { border-color: var(--c-primary); }

/* Timer urgency - calm chip until 5s left, then it takes over: bigger, red, shaking, growing
   further still inside the last 2s, then an actual "blow up" burst the instant it hits 0 (held
   briefly before the round-over screen appears, so the burst is actually seen, not skipped past). */
.er-timer-urgent {
  color: var(--c-error-glow-text); background: rgba(255, 93, 115, 0.14); border: 1px solid var(--c-error);
  transform: scale(1.3); font-size: 1.05em; font-weight: 900;
  animation: er-timer-shake 0.4s ease-in-out infinite;
}
.er-timer-critical {
  transform: scale(1.75); font-size: 1.3em;
  animation: er-timer-shake-critical 0.25s ease-in-out infinite;
}
@keyframes er-timer-shake {
  0%, 100% { transform: scale(1.3) translateX(0); }
  25% { transform: scale(1.3) translateX(-2px) rotate(-3deg); }
  75% { transform: scale(1.3) translateX(2px) rotate(3deg); }
}
@keyframes er-timer-shake-critical {
  0%, 100% { transform: scale(1.75) translateX(0) rotate(0); }
  25% { transform: scale(1.85) translateX(-3px) rotate(-5deg); }
  75% { transform: scale(1.85) translateX(3px) rotate(5deg); }
}
.er-timer-blowup {
  animation: er-timer-blowup 0.45s ease-out forwards;
  z-index: 5;
}
@keyframes er-timer-blowup {
  0% { transform: scale(1.75); opacity: 1; }
  40% { transform: scale(2.6); opacity: 1; }
  100% { transform: scale(4.5); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .er-timer-urgent, .er-timer-critical { animation: none; }
  .er-timer-blowup { animation: er-timer-blowup-fade 0.3s ease-out forwards; }
}
@keyframes er-timer-blowup-fade {
  0% { opacity: 1; }
  100% { opacity: 0; }
}

/* Fiery meteor streaking in from the right as the countdown gets dangerous - see
   spawnElectronRushMeteor(). Distinct orange/red trail vs. Equilibrium Shift's white comet. */
.er-meteor {
  position: fixed; width: 4px; height: 4px; border-radius: 50%; background: #FFD9A0;
  box-shadow: 0 0 8px 3px rgba(255, 138, 61, 0.9), 0 0 18px 6px rgba(255, 61, 61, 0.6);
  pointer-events: none; z-index: 999; animation: er-meteor-fly 850ms ease-in forwards;
}
.er-meteor::before {
  content: ""; position: absolute; top: 50%; left: 100%; width: 100px; height: 3px;
  background: linear-gradient(90deg, rgba(255, 138, 61, 0.85), transparent);
  transform-origin: left center; transform: translateY(-50%) rotate(336deg);
}
@keyframes er-meteor-fly {
  0% { transform: translate(0, 0) scale(0.5); opacity: 0; }
  12% { opacity: 1; }
  80% { opacity: 1; }
  100% { transform: translate(-72vw, 32vh) scale(1.1); opacity: 0; }
}

/* ---------- Electron Thief ---------- */
.et-target-panel { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-md); }
.et-target-info { flex: 1; min-width: 180px; }
.et-target-info p { margin: 4px 0 0; color: var(--text-secondary); }
.et-target-info strong { color: var(--c-primary-glow-text); font-size: 1.1em; }
.et-target-diagram { width: 150px; flex-shrink: 0; margin: 0 auto; }
.et-sources { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: var(--space-2xs); margin-top: var(--space-sm); }
.et-source {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  border: 2px solid var(--border-default); border-radius: var(--radius-md);
  padding: var(--space-sm); background: var(--bg-main); color: var(--text-primary); cursor: pointer;
}
.et-source:hover { border-color: var(--c-primary); }
.et-source-symbol { font-family: var(--font-heading); font-weight: 900; font-size: 1.4em; color: var(--c-primary-glow-text); }
.et-source-available { color: var(--text-secondary); font-size: 0.8em; }

/* ---------- Periodic Table Heist ---------- */
/* Portrait phones can't show all 17 Period-4 tiles at once - a plain text nudge to rotate,
   shown only while actually in portrait (auto-hides the instant the phone is turned, no JS). */
.pth-rotate-hint {
  display: none; align-items: center; gap: 6px; margin: 0 0 var(--space-sm);
  font-size: 0.8em; color: var(--c-warning-glow-text); font-weight: 700;
}
@media (orientation: portrait) {
  .pth-rotate-hint { display: flex; }
}
/* Period 4 (17 tiles) is wider than any phone screen, so .pth-grid scrolls horizontally as one
   unit (all periods shift together, keeping columns aligned) - never the page itself. The wrap's
   right-edge fade is the only cue that there's more table to the right; without it a scrollable
   row that just stops mid-tile at the card edge reads as a cut-off/broken table, not "swipe me". */
.pth-grid-wrap { position: relative; margin: var(--space-sm) 0; }
.pth-grid-wrap::after {
  content: ""; position: absolute; top: 0; right: 0; bottom: 0; width: 26px;
  background: linear-gradient(90deg, transparent, rgba(13, 16, 30, 0.9));
  pointer-events: none; border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.pth-grid { display: flex; flex-direction: column; gap: 3px; overflow-x: auto; -webkit-overflow-scrolling: touch; padding-bottom: 2px; }
.pth-row { display: flex; gap: 3px; }
/* Flat, sharp-edged blocks like .crossword-cell - not rounded card/button chips. */
.pth-tile {
  width: 40px; height: 40px; flex-shrink: 0; border-radius: 3px;
  border: 1px solid var(--border-default); background: var(--bg-main); color: var(--text-primary);
  font-weight: 800; cursor: pointer; transition: transform var(--speed-fast) var(--ease-smooth);
}
.pth-tile:hover { border-color: var(--c-warning); }
.pth-tile.correct { border-color: var(--c-success); background: rgba(61, 220, 151, 0.15); }
.pth-tile.wrong { border-color: var(--c-error); background: rgba(255, 93, 115, 0.15); }
.pth-tile:disabled { cursor: default; }

/* ---------- Molecule Mix ---------- */
.mm-tray { display: flex; flex-wrap: wrap; gap: 6px; margin: var(--space-2xs) 0 var(--space-sm); }
.mm-tray-atom {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px 6px 8px; border-radius: var(--radius-pill); border: 2px solid var(--c-success);
  background: var(--bg-main); color: var(--c-success-glow-text); font-weight: 800; cursor: pointer;
}
.mm-tray-atom:hover { background: rgba(61, 220, 151, 0.12); }
.mm-tray-dot { width: 14px; height: 14px; border-radius: 50%; flex-shrink: 0; box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.15) inset; }
.mm-beaker {
  display: flex; align-items: center; justify-content: center; min-height: 160px;
  border: 1px solid var(--border-glow); border-radius: var(--radius-lg);
  background: radial-gradient(circle at 50% 30%, rgba(111, 60, 207, 0.12), transparent 70%);
  box-shadow: inset 0 0 24px rgba(111, 60, 207, 0.12);
  margin: var(--space-sm) 0;
}
.mm-workspace { display: flex; flex-wrap: wrap; gap: var(--space-2xs); min-height: 48px; }
.mm-group {
  display: flex; align-items: center; gap: 6px; padding: 6px 10px;
  border: 2px solid var(--border-default); border-radius: var(--radius-md); background: var(--bg-main);
}
.mm-group.is-center { border-color: var(--c-gold); box-shadow: 0 0 12px rgba(255, 210, 63, 0.2); }
.mm-group-symbol { font-family: var(--font-heading); font-weight: 900; }
.mm-group-count { color: var(--text-secondary); }

/* ---------- Shared: electron shell / molecule SVG diagrams ---------- */
.shell-diagram { width: 100%; max-width: 150px; }
.shell-ring { fill: none; stroke: var(--border-default); stroke-width: 1.5; }
.shell-nucleus { fill: var(--c-secondary-dark); stroke: var(--c-secondary); stroke-width: 1.5; }
.shell-nucleus-label { fill: var(--text-primary); font-size: 11px; font-weight: 800; font-family: var(--font-heading); }
.shell-electron { fill: var(--c-primary); stroke: var(--c-primary-glow-text); stroke-width: 1; }
.shell-electron-empty { fill: transparent; stroke: var(--text-disabled); stroke-width: 1.5; stroke-dasharray: 2 2; }

.molecule-diagram { width: 100%; max-width: 200px; }
/* A single flat-colour line read as a dull wire diagram - a wider dark rod underneath plus a
   thinner light stripe on top gives the bond a cylindrical, "real model kit" look instead. */
.molecule-bond-shadow { stroke: rgba(0, 0, 0, 0.35); stroke-width: 5; stroke-linecap: round; }
.molecule-bond { stroke: var(--text-secondary); stroke-width: 2; stroke-linecap: round; }
.molecule-atom { filter: drop-shadow(0 3px 4px rgba(0, 0, 0, 0.45)); }
.molecule-atom-label {
  fill: var(--text-primary); stroke: var(--bg-main); stroke-width: 3px; paint-order: stroke;
  font-size: 12px; font-weight: 800; font-family: var(--font-heading); pointer-events: none;
}
.molecule-atom-center { stroke: var(--c-gold); stroke-width: 2; }

/* ---------- Lab Master ---------- */
.lesson-shell.game-mode .lm-card { border-color: transparent; background: none; box-shadow: none; }
.lm-mission-list { display: flex; flex-direction: column; gap: 4px; margin-bottom: var(--space-sm); }
.lm-mission-item { display: flex; align-items: center; gap: var(--space-2xs); font-size: 0.9em; color: var(--text-disabled); }
.lm-mission-item.done { color: var(--c-success-glow-text); }
.lm-mission-item.current { color: var(--text-primary); font-weight: 700; }
.lm-explanation { color: var(--text-secondary); font-size: 0.85em; margin-top: 4px; }
.lm-answers { display: flex; flex-direction: column; gap: var(--space-2xs); margin: var(--space-2xs) 0 var(--space-sm); }
.lm-experiment-label { color: var(--c-secondary-glow-text); font-size: 0.75em; text-transform: uppercase; letter-spacing: 0.04em; font-weight: 700; margin: 0 0 2px; }
.lm-experiment-title { font-weight: 700; margin: 0 0 var(--space-sm); }
#lmRunTestBtn { display: block; margin: 0 auto var(--space-sm); }

/* Simulation starts hidden (unlit flame, empty tube, blank plate) - .lm-sim-run is added on
   "Run test" to actually play it. Effects mirror .csc-illustration-svg's static rendering but
   animated in, so the very first time a student sees a given test they watch it happen instead
   of predicting blind. */
.lm-sim-liquid, .lm-sim-precipitate, .lm-sim-streak { opacity: 0; }
.lm-sim-flame { opacity: 0; transform-origin: 70px 140px; transform: scaleY(0.15); }
.lm-sim-bubble { fill: rgba(255, 255, 255, 0.85); opacity: 0; animation: none; }
.lm-sim-warm { opacity: 0; }
.lm-sim-steam { opacity: 0; animation: none; }
.lm-sim-run .lm-sim-liquid { opacity: 0.9; transition: opacity 0.6s ease-out; }
.lm-sim-run .lm-sim-precipitate { animation: lm-precipitate-settle 0.7s ease-out 0.5s both; }
.lm-sim-run .lm-sim-flame { opacity: 1; transform: scaleY(1); transition: opacity 0.4s ease-out 0.1s, transform 0.4s ease-out 0.1s; }
.lm-sim-run .lm-sim-streak { animation: lm-streak-wipe 0.6s ease-out 0.3s both; }
.lm-sim-run .lm-sim-bubble { animation: csc-bubble-rise 1.6s ease-in infinite; }
.lm-sim-run .lm-sim-warm { animation: heat-shimmer 1.8s ease-in-out infinite; }
.lm-sim-run .lm-sim-steam { animation: steam-rise 2.4s ease-out infinite; }
@keyframes lm-precipitate-settle {
  0% { opacity: 0; transform: translateY(-10px); }
  100% { opacity: 1; transform: translateY(0); }
}
@keyframes lm-streak-wipe {
  0% { opacity: 0; stroke-dasharray: 40; stroke-dashoffset: 40; }
  100% { opacity: 1; stroke-dasharray: 40; stroke-dashoffset: 0; }
}
/* Real heat has no colour - the wavy-air convention (a hot road, a cup of tea) is what actually
   reads as "warm" without implying a colour change that isn't really there. */
.csc-warm { opacity: 0.7; animation: heat-shimmer 1.8s ease-in-out infinite; }
.csc-warm-2 { animation-delay: -0.6s; }
.csc-warm-3 { animation-delay: -1.2s; }
@keyframes heat-shimmer {
  0%, 100% { transform: translateY(0); opacity: 0.5; }
  50% { transform: translateY(-3px); opacity: 0.9; }
}
/* Steam rises and dissipates (convection - hot vapour is less dense than the surrounding air, so
   it floats up and thins out) rather than spreading outward, and each wisp loops on its own timer
   so they don't all puff up in lockstep. */
.csc-steam { opacity: 0; animation: steam-rise 2.4s ease-out infinite; }
.csc-steam-2 { animation-delay: -0.8s; }
.csc-steam-3 { animation-delay: -1.6s; }
@keyframes steam-rise {
  0% { transform: translateY(6px) scale(0.8); opacity: 0; }
  25% { opacity: 0.65; }
  100% { transform: translateY(-16px) scale(1.3); opacity: 0; }
}
/* Real flame motion is abrupt and irregular, not a smooth sway - a fast, no-easing step between
   jittered skew/scale states reads as flicker instead of a pendulum. Runs continuously (not just
   on "Run test") since Crime Scene Chemistry's static reveal has no run step to gate it on. */
.chem-flame-flicker { transform-box: fill-box; transform-origin: center bottom; animation: chem-flame-jitter 0.5s steps(1, end) infinite; }
@keyframes chem-flame-jitter {
  0%   { transform: skewX(0deg) scaleY(1) translateX(0); }
  14%  { transform: skewX(-2.5deg) scaleY(1.03) translateX(-1px); }
  28%  { transform: skewX(2deg) scaleY(0.97) translateX(0.5px); }
  42%  { transform: skewX(-1.5deg) scaleY(1.04) translateX(-0.5px); }
  57%  { transform: skewX(2.5deg) scaleY(0.95) translateX(1px); }
  71%  { transform: skewX(-2deg) scaleY(1.02) translateX(-0.8px); }
  85%  { transform: skewX(1deg) scaleY(0.98) translateX(0.3px); }
  100% { transform: skewX(0deg) scaleY(1) translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
  .lm-sim-run .lm-sim-liquid { transition: none; }
  .lm-sim-run .lm-sim-precipitate, .lm-sim-run .lm-sim-streak { animation: none; opacity: 1; }
  .lm-sim-run .lm-sim-flame { transition: none; }
  .lm-sim-run .lm-sim-bubble { animation: none; opacity: 0.6; }
  .lm-sim-run .lm-sim-warm { animation: none; opacity: 0.7; }
  .csc-warm { animation: none; opacity: 0.7; }
  .lm-sim-run .lm-sim-steam { animation: none; opacity: 0.5; }
  .csc-steam { animation: none; opacity: 0.5; }
  .chem-flame-flicker { animation: none; }
}

/* ---------- Crime Scene Chemistry ---------- */
.lesson-shell.game-mode .csc-card { border-color: transparent; background: none; box-shadow: none; }
.csc-case-file { color: var(--text-primary); margin: 0 0 var(--space-sm); }

/* Portrait-only nudge - the evidence list and the sample illustration are meant to sit side by
   side (like a real case file), which only fits comfortably in landscape on a phone. */
.csc-rotate-hint {
  display: none; align-items: center; gap: 6px; margin: 0 0 var(--space-sm);
  font-size: 0.8em; color: var(--c-error-glow-text); font-weight: 700;
}
@media (orientation: portrait) {
  .csc-rotate-hint { display: flex; }
}

.csc-layout { display: flex; flex-direction: column; gap: var(--space-md); margin-bottom: var(--space-sm); }
@media (orientation: landscape) {
  .csc-layout { flex-direction: row; align-items: flex-start; }
  .csc-evidence-col { flex: 1.3; }
  .csc-illustration-col { flex: 1; }
}

.csc-evidence-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2xs); }
.csc-evidence-list li { display: flex; align-items: flex-start; gap: var(--space-2xs); font-size: 0.9em; color: var(--text-primary); }
.csc-evidence-list li strong { color: var(--c-error-glow-text); display: block; }
.csc-evidence-icon { flex-shrink: 0; width: 20px; height: 20px; margin-top: 2px; color: var(--c-error-glow-text); }
.csc-evidence-icon svg { width: 100%; height: 100%; }

/* The sample: a real test tube (precipitate settled / liquid coloured / bubbling), a flame test
   on a splint, or a streak plate - whichever the evidence actually used, not a generic beaker for
   everything. Colours come straight from each scenario's verified real-chemistry "visual" field. */
.csc-illustration-col { display: flex; flex-direction: column; align-items: center; gap: var(--space-2xs); }
.csc-illustration-svg { width: 100px; height: 130px; filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.4)); }
.csc-illustration-label { font-size: 0.8em; color: var(--text-secondary); text-align: center; font-weight: 700; }
.csc-bubble { fill: rgba(255, 255, 255, 0.8); animation: csc-bubble-rise 1.6s ease-in infinite; }
.csc-bubble-2 { animation-delay: 0.4s; }
.csc-bubble-3 { animation-delay: 0.9s; }
@keyframes csc-bubble-rise {
  0% { transform: translateY(0); opacity: 0; }
  15% { opacity: 1; }
  100% { transform: translateY(-46px); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .csc-bubble { animation: none; opacity: 0.6; }
}

/* Lettered options as a clean list (radio-style), matching the reference - not big pill buttons. */
.csc-options { display: flex; flex-direction: column; gap: var(--space-2xs); margin: var(--space-sm) 0; }
.csc-option {
  display: flex; align-items: center; gap: var(--space-sm); text-align: left; cursor: pointer;
  padding: var(--space-2xs) var(--space-sm); border-radius: var(--radius-md);
  border: 1px solid var(--border-default); background: var(--bg-card); color: var(--text-primary);
}
.csc-option-letter {
  flex-shrink: 0; width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
  border: 1.5px solid var(--border-default); font-weight: 800; font-size: 0.85em; color: var(--text-secondary);
}
.csc-option-label { flex: 1; font-weight: 600; }
.csc-option-check { flex-shrink: 0; opacity: 0; color: var(--c-success); font-weight: 900; }
.csc-option.correct { border-color: var(--c-success); background: rgba(61, 220, 151, 0.12); }
.csc-option.correct .csc-option-letter { border-color: var(--c-success); background: var(--c-success); color: #04150c; }
.csc-option.correct .csc-option-check { opacity: 1; }
.csc-option.wrong { border-color: var(--c-error); background: rgba(255, 93, 115, 0.12); }
.csc-option.wrong .csc-option-letter { border-color: var(--c-error); background: var(--c-error); color: #1a0507; }
.csc-option.eliminated { opacity: 0.35; text-decoration: line-through; }
.csc-option:disabled { cursor: default; }
