:root {
  color-scheme: light;
  --background: #f4f6fa;
  --surface: #ffffff;
  --surface-muted: #f8f9fc;
  --ink: #18212f;
  --muted: #5f6b7a;
  --border: #dce2ea;
  --grid: #dfe4eb;
  --axis: #546170;
  --curve: #1459a6;
  --curve-alt: #8a3e91;
  --accent: #285fc7;
  --accent-dark: #174695;
  --success: #16734a;
  --success-bg: #ecf8f2;
  --error: #a13c32;
  --error-bg: #fff1ef;
  --warning: #8a5a00;
  --focus: #f2b134;
  --shadow: 0 14px 35px rgba(28, 40, 61, 0.08);
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { max-width: 100%; overflow-x: hidden; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--background);
  color: var(--ink);
}

button, input { font: inherit; }
button { touch-action: manipulation; }

button:focus-visible, input:focus-visible, summary:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--accent) 35%, transparent);
  outline-offset: 2px;
}

.app-header {
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: 24px 24px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

h1, h2, h3, p { margin-top: 0; }
h1 { margin-bottom: 0; font-size: clamp(1.55rem, 3vw, 2.25rem); letter-spacing: 0; }
h2 { margin-bottom: 8px; }

.eyebrow, .question-label {
  margin-bottom: 5px;
  color: var(--accent-dark);
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0;
  text-transform: uppercase;
}

.header-actions, .card-heading-row, .dialog-heading-row, .dialog-actions, .feedback-actions, .animation-controls {
  display: flex;
  align-items: center;
  gap: 10px;
}

.header-actions { flex-wrap: wrap; justify-content: flex-end; }

button {
  border: 1px solid transparent;
  border-radius: 8px;
  padding: 10px 15px;
  cursor: pointer;
  font-weight: 700;
}

.primary-button {
  background: var(--accent);
  color: white;
}
.primary-button:hover { background: var(--accent-dark); }

.secondary-button, .special-answer-buttons button, .choice-answer-area button, .mobile-keypad button {
  background: var(--surface);
  border-color: var(--border);
  color: var(--ink);
}
.secondary-button:hover, .special-answer-buttons button:hover, .choice-answer-area button:hover, .mobile-keypad button:hover {
  border-color: var(--accent);
  background: #f3f6ff;
}

.text-button {
  padding: 5px 8px;
  background: transparent;
  color: var(--muted);
  font-weight: 650;
}

.danger-button { background: #8f2e27; color: white; }
.icon-button { padding: 3px 10px; font-size: 1.8rem; line-height: 1; background: transparent; color: var(--muted); }

.app-shell {
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 24px 40px;
  display: grid;
  grid-template-columns: minmax(0, 1.45fr) minmax(330px, 0.75fr);
  /* The graph spans both rows. With two auto rows its extra height was split between them,
     which left the answer card floating far below the question. The flexible second row
     absorbs that height instead. */
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "graph question"
    "graph answer"
    "debug debug";
  gap: 20px;
  align-items: start;
}
.app-shell > * { min-width: 0; }

.graph-card, .question-strip, .answer-card, .debug-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: var(--shadow);
}

.graph-card { grid-area: graph; padding: 22px; overflow: hidden; }
.question-strip { grid-area: question; padding: 22px 26px 12px; }
.answer-card { grid-area: answer; padding: 12px 26px 24px; align-self: start; }
.card-heading-row, .dialog-heading-row { justify-content: space-between; align-items: flex-start; }
.card-heading-row p { margin-bottom: 0; color: var(--muted); }

.graph-panels { display: grid; gap: 12px; }
.graph-panels.multi-panel { grid-template-columns: 1fr; gap: 18px; }
.graph-panel { min-width: 0; }
.graph-panel-heading { margin: 8px 0 5px; font-size: 0.85rem; font-weight: 800; color: var(--muted); }
.graph-frame {
  position: relative;
  margin-top: 14px;
  width: 100%;
  overflow: hidden;
  background: #fcfdff;
  border: 1px solid var(--border);
  border-radius: 8px;
  aspect-ratio: 900 / 520;
}

.graph-frame svg { display: block; width: 100%; height: 100%; }
.animation-controls { margin-top: 12px; justify-content: center; }

.question-math {
  min-height: 58px;
  display: flex;
  align-items: center;
  margin-bottom: 4px;
  font-family: "STIX Two Math", "Cambria Math", serif;
  font-size: clamp(1.35rem, 3vw, 2rem);
  overflow-x: auto;
  /* overflow-x: auto forces the y-axis to auto too, and the limit subscript's descent
     produced a stray vertical scrollbar beside every limit question. */
  overflow-y: hidden;
  white-space: nowrap;
}
.question-math math { font-size: 1.15em; }
.question-math.question-continuity,
.question-math.question-classification {
  display: block;
  white-space: normal;
  overflow: visible;
  font-size: clamp(1.3rem, 2.4vw, 1.6rem);
  font-weight: 400;
  line-height: 1.35;
}
.question-math.question-continuity math,
.question-math.question-classification math { font-size: 1em; }
.question-tail { white-space: nowrap; }
.question-math.question-composition,
.question-math.question-limitLaw { font-size: 1.45rem; overflow: visible; }
.question-math.question-composition math,
.question-math.question-limitLaw math { font-size: 1em; max-width: 100%; }
.question-prompt { color: var(--muted); margin-bottom: 0; line-height: 1.4; }
.question-prompt::before { content: "Hint: "; font-weight: 800; color: var(--accent-dark); }

label { font-weight: 700; }
.answer-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; margin-top: 8px; }

#answerInput {
  width: 100%;
  min-height: 48px;
  border: 2px solid var(--border);
  border-radius: 8px;
  padding: 9px 12px;
  font-size: 1.2rem;
}
#answerInput:focus { border-color: var(--accent); }
.submit-button { min-width: 92px; }
.help-text { margin: 8px 0 12px; color: var(--muted); font-size: 0.88rem; line-height: 1.45; }

.special-answer-buttons { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.special-answer-buttons button { font-size: 1.05rem; }

.mobile-keypad {
  display: none;
  grid-template-columns: repeat(4, 1fr);
  gap: 7px;
  margin-top: 12px;
}
.mobile-keypad button { min-height: 45px; padding: 8px; }
.mobile-keypad .keypad-submit { background: var(--accent); color: white; border-color: var(--accent); }

.choice-answer-area { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.choice-answer-area.classification-choices { grid-template-columns: 1fr; }
.choice-answer-area button { min-height: 48px; text-align: left; }
.choice-answer-area button.choice-eliminated {
  cursor: not-allowed;
  color: var(--muted);
  background: var(--surface-muted);
  text-decoration: line-through;
}

.feedback-panel {
  margin-top: 20px;
  border-radius: 8px;
  padding: 16px;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 13px;
  border: 1px solid;
}
.feedback-panel.correct { background: var(--success-bg); border-color: #acd8c5; }
.feedback-panel.incorrect { background: var(--error-bg); border-color: #efb9b3; }
.feedback-panel.explanation { background: #fff8e5; border-color: #e8cb84; }
.feedback-panel h3 { margin-bottom: 5px; font-size: 1rem; }
.feedback-panel p { margin-bottom: 10px; line-height: 1.5; }
.feedback-icon { width: 25px; height: 25px; border-radius: 50%; display: grid; place-items: center; font-weight: 900; }
.correct .feedback-icon::after { content: "✓"; color: white; }
.correct .feedback-icon { background: var(--success); }
.incorrect .feedback-icon::after { content: "!"; color: white; }
.incorrect .feedback-icon { background: var(--error); }
.explanation .feedback-icon::after { content: "→"; color: white; }
.explanation .feedback-icon { background: var(--warning); }
.feedback-actions { flex-wrap: wrap; }

.app-dialog {
  width: min(720px, calc(100vw - 28px));
  max-height: calc(100vh - 28px);
  overflow: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 24px;
  box-shadow: 0 24px 80px rgba(21, 31, 48, 0.24);
}
.app-dialog::backdrop { background: rgba(20, 29, 43, 0.45); backdrop-filter: blur(2px); }
.app-dialog fieldset { margin: 18px 0; border: 1px solid var(--border); border-radius: 8px; padding: 16px; }
.app-dialog legend { padding: 0 7px; font-weight: 800; }
.dialog-text-input {
  display: block;
  width: 100%;
  min-height: 44px;
  margin-top: 8px;
  border: 2px solid var(--border);
  border-radius: 8px;
  padding: 8px 11px;
}
.dialog-text-input:focus { border-color: var(--accent); }
.seed-option-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; align-items: end; }
.seed-option-row .secondary-button { min-height: 44px; white-space: nowrap; }

/* The verdict has to land where the student is looking. On a phone the keypad pushes the
   feedback panel off-screen, so the answer region itself carries the immediate signal. */
#limitAnswerArea, .choice-answer-area {
  border-radius: 12px;
  outline: 3px solid transparent;
  outline-offset: 6px;
}
@keyframes answer-pulse-correct-frames {
  0% { outline-color: transparent; background-color: transparent; }
  22% { outline-color: var(--success); background-color: var(--success-bg); }
  100% { outline-color: transparent; background-color: transparent; }
}
@keyframes answer-pulse-incorrect-frames {
  0% { outline-color: transparent; background-color: transparent; }
  22% { outline-color: var(--error); background-color: var(--error-bg); }
  100% { outline-color: transparent; background-color: transparent; }
}
.answer-pulse-correct { animation: answer-pulse-correct-frames 1100ms ease-out 1; }
.answer-pulse-incorrect { animation: answer-pulse-incorrect-frames 1100ms ease-out 1; }
/* Reduced motion keeps the verdict but drops the movement: a held tint, no flash.
   These carry the #limitAnswerArea id because the base rule above sets a transparent
   outline through that id; a keyframed pulse outranks it, but a plain declaration does not. */
.answer-pulse-static { animation: none !important; }
#limitAnswerArea.answer-pulse-static.answer-pulse-correct,
.choice-answer-area.answer-pulse-static.answer-pulse-correct {
  outline-color: var(--success);
  background-color: var(--success-bg);
}
#limitAnswerArea.answer-pulse-static.answer-pulse-incorrect,
.choice-answer-area.answer-pulse-static.answer-pulse-incorrect {
  outline-color: var(--error);
  background-color: var(--error-bg);
}
.checkbox-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 11px 18px; }
.checkbox-grid label { display: flex; gap: 9px; align-items: flex-start; font-weight: 550; }
.checkbox-grid input { margin-top: 3px; }
.range-row { display: grid; grid-template-columns: auto minmax(130px, 1fr) auto; align-items: center; gap: 12px; font-size: 0.85rem; color: var(--muted); }
.range-row input { width: 100%; }
.dialog-actions { margin-top: 20px; justify-content: flex-end; flex-wrap: wrap; }
.form-error { color: var(--error); min-height: 1.3em; }

.progress-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
  margin: 18px 0;
}
.summary-stat { background: var(--surface-muted); border: 1px solid var(--border); border-radius: 8px; padding: 14px; }
.summary-stat strong { display: block; font-size: 1.5rem; }
.summary-stat span { color: var(--muted); font-size: 0.82rem; }
.progress-skills { display: grid; gap: 9px; }
.skill-row { border-top: 1px solid var(--border); padding-top: 10px; display: grid; grid-template-columns: minmax(130px, 1fr) 1.8fr auto; gap: 12px; align-items: center; }
.skill-name { font-weight: 700; }
.skill-bar { height: 9px; background: #e5e9ef; border-radius: 999px; overflow: hidden; }
.skill-bar > span { display: block; height: 100%; background: var(--accent); }
.skill-stat { color: var(--muted); font-size: 0.85rem; white-space: nowrap; }

.debug-panel { grid-area: debug; padding: 12px 18px; }
.debug-panel pre { white-space: pre-wrap; overflow-wrap: anywhere; }

/* SVG styling */
.graph-grid { stroke: var(--grid); stroke-width: 1; }
.graph-axis { stroke: var(--axis); stroke-width: 2; }
.graph-tick { stroke: var(--axis); stroke-width: 1.3; }
.graph-label { fill: var(--muted); font-size: 16px; font-family: inherit; }
.graph-fractional-label { font-size: 12px; opacity: 0.78; }
.graph-axis-label { fill: var(--ink); font-size: 20px; font-style: italic; font-family: Georgia, serif; }
.graph-curve { fill: none; stroke: var(--curve); stroke-width: 4; stroke-linecap: round; stroke-linejoin: round; }
.graph-curve-g { stroke: #8a3e91; stroke-dasharray: 12 9; stroke-linecap: butt; }
.graph-legend-swatch { stroke-width: 6; }
.graph-legend-swatch.graph-curve-g { stroke-dasharray: 9 8; }
.graph-function-label, .graph-function-label-g { font-size: 26px; }
.graph-function-label { fill: var(--curve); }
.graph-open-point-g { stroke: #8a3e91; }
.graph-closed-point-g { fill: #8a3e91; }
.graph-function-label-g { fill: #8a3e91 !important; }
.graph-continuation { fill: var(--curve); stroke: white; stroke-width: 2; }
.graph-continuation-g { fill: #8a3e91; }
.graph-open-point { fill: white; stroke: var(--curve); stroke-width: 4; }
.graph-closed-point { fill: var(--curve); stroke: white; stroke-width: 2; }
.graph-asymptote { stroke: #9b6b20; stroke-width: 2; stroke-dasharray: 8 8; opacity: 0.8; }
.graph-horizontal-asymptote { stroke-dasharray: 10 7; }
.graph-asymptote-label {
  fill: #8a5f1c;
  font-size: 17px;
  font-weight: 700;
  paint-order: stroke;
  stroke: var(--surface);
  stroke-width: 4px;
}
.animation-focus { stroke: var(--focus); stroke-width: 6; opacity: 0.32; }
.animation-guide-left { stroke: #7c3a91; stroke-width: 3; stroke-dasharray: 8 6; }
.animation-guide-right { stroke: #0c7289; stroke-width: 3; stroke-dasharray: 2 6; }
.animation-point-left { fill: #7c3a91; stroke: white; stroke-width: 2; }
.animation-point-right { fill: #0c7289; stroke: white; stroke-width: 2; }
.animation-target { fill: none; stroke: var(--focus); stroke-width: 7; }
.animation-label { fill: var(--ink); font-size: 22px; font-weight: 800; paint-order: stroke; stroke: white; stroke-width: 5px; }
.animation-banner { fill: white; stroke: var(--border); stroke-width: 2; }
.animation-phase-banner { fill: rgba(255, 255, 255, 0.94); stroke: var(--border); stroke-width: 1.5; }
.animation-phase-label { fill: var(--muted); font-size: 18px; font-weight: 800; paint-order: stroke; stroke: white; stroke-width: 4px; }
.animation-direction-badge { fill: var(--accent-dark); font-size: 26px; font-weight: 900; paint-order: stroke; stroke: white; stroke-width: 5px; }
.animation-oscillation-band { fill: rgba(138, 62, 145, 0.13); stroke: #8a3e91; stroke-width: 2; stroke-dasharray: 7 5; }
.animation-final-note { fill: #fff8e5; stroke: #d9b85f; stroke-width: 2; }
.mastery-label { font-size: 0.78rem; font-weight: 800; }
.mastery-strong { color: var(--success); }
.mastery-developing { color: var(--warning); }
.mastery-needs-practice { color: var(--error); }
.progress-misconceptions { margin-top: 20px; }
.progress-misconceptions h3 { margin-bottom: 8px; }
.misconception-row { display: flex; justify-content: space-between; gap: 16px; border-top: 1px solid var(--border); padding: 9px 0; }

/* Guided tour */
.tour-button { min-width: 44px; padding-inline: 12px; font-size: 1.05rem; }
.tour-root { position: fixed; inset: 0; z-index: 50; }
.tour-spotlight {
  position: fixed;
  border-radius: 12px;
  box-shadow: 0 0 0 200vmax rgba(20, 29, 43, 0.55);
  outline: 3px solid var(--focus);
  outline-offset: 0;
  pointer-events: none;
  transition: top 280ms ease, left 280ms ease, width 280ms ease, height 280ms ease;
}
.tour-centered .tour-spotlight { outline: none; }
.tour-card {
  position: fixed;
  width: min(380px, calc(100vw - 32px));
  padding: 20px 22px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 24px 80px rgba(21, 31, 48, 0.3);
}
.tour-centered .tour-card { top: 50%; left: 50%; transform: translate(-50%, -50%); width: min(460px, calc(100vw - 32px)); }
.tour-reduced-motion .tour-spotlight { transition: none; }
.tour-progress { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 6px; }
.tour-step-count { margin-bottom: 0; }
.tour-card h2 { font-size: 1.25rem; margin-bottom: 8px; }
.tour-body { color: var(--ink); line-height: 1.5; }
.tour-body p { margin-bottom: 10px; }
.tour-body math { font-size: 1.1em; }
.tour-nowrap { white-space: nowrap; }
.tour-body .tour-key {
  display: inline-block;
  padding: 0 6px;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--surface-muted);
  font-weight: 700;
  white-space: nowrap;
}
.tour-dots { display: flex; gap: 6px; }
.tour-dots span { width: 7px; height: 7px; border-radius: 50%; background: var(--border); }
.tour-dots .tour-dot-done { background: color-mix(in srgb, var(--accent) 45%, var(--border)); }
.tour-dots .tour-dot-current { background: var(--accent); width: 18px; border-radius: 999px; }
.tour-actions { display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin-top: 6px; }
.tour-actions #tourSkipButton { margin-right: auto; padding-left: 0; }
.tour-annotation { fill: var(--ink); font-size: 20px; font-weight: 800; paint-order: stroke; stroke: white; stroke-width: 5px; }
.tour-annotation-open { fill: var(--curve); }

@media (max-width: 850px) {
  .app-header { align-items: flex-start; }
  .app-shell {
    grid-template-columns: 1fr;
    grid-template-rows: none;
    grid-template-areas: "question" "graph" "answer" "debug";
  }
  .question-strip { position: sticky; top: 0; z-index: 4; box-shadow: 0 8px 20px rgba(28, 40, 61, 0.1); }
  .graph-card { padding: 14px; }
  .question-strip { padding: 12px 20px 10px; }
  .answer-card { padding: 16px 20px 20px; }
}

@media (max-width: 620px) {
  .app-header { padding: 16px 14px 12px; display: block; }
  .header-actions { margin-top: 13px; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* A fourth grid column squeezed New problem onto two lines, so the tour button sits beside
     the title instead. */
  .app-header { position: relative; }
  .app-header h1 { padding-right: 52px; }
  .header-actions .tour-button { position: absolute; top: 14px; right: 14px; width: 44px; min-height: 40px; }
  /* On a phone the card becomes a bottom sheet; the tour scrolls its target into the band
     between the sticky question strip and the sheet. */
  .tour-root:not(.tour-centered) .tour-card {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    border-radius: 14px 14px 0 0;
    padding: 16px 16px calc(14px + env(safe-area-inset-bottom));
  }
  .tour-card h2 { font-size: 1.1rem; }
  .tour-body { font-size: 0.93rem; }
  .tour-annotation { font-size: 32px; stroke-width: 7px; }
  .header-actions button { width: 100%; min-width: 0; max-width: 100%; padding: 9px 4px; font-size: 0.82rem; white-space: normal; overflow: hidden; }
  .app-shell { padding: 0 10px 24px; gap: 12px; }
  .app-header h1 { font-size: 1.45rem; }
  .app-header .eyebrow { display: none; }
  .question-label { margin-bottom: 2px; }
  .question-math { min-height: 40px; font-size: 1.3rem; }
  .question-math.question-composition,
  .question-math.question-limitLaw { font-size: 1.08rem; }
  .question-prompt { font-size: 0.84rem; }
  .card-heading-row { display: block; }
  .card-heading-row p { overflow-wrap: anywhere; }
  /* Side by side, the nowrap button left the seed field about six characters wide, which is
     unusable for a 21-character seed. */
  .seed-option-row { grid-template-columns: 1fr; }
  /* Keeps Save and start reachable without scrolling the whole dialog. */
  .app-dialog .dialog-actions {
    position: sticky;
    bottom: 0;
    margin-top: 12px;
    padding: 12px 0 2px;
    background: var(--surface);
    border-top: 1px solid var(--border);
  }
  /* The SVG letterboxes inside any frame taller than its viewBox, so a 1.25 frame drew the
     same size graph as this one and simply wasted ~28% of the card height. */
  .graph-frame { margin-top: 6px; aspect-ratio: 900 / 520; }
  .graph-panel-heading { margin-top: 3px; }

  /* Graph text is sized in viewBox units. On a phone the drawing scales to roughly 0.38,
     which rendered the axis numbers at about 6px. These keep them legible on the device the
     graph is actually read on. */
  .graph-label { font-size: 32px; }
  .graph-asymptote-label { font-size: 30px; stroke-width: 7px; }
  .graph-function-label, .graph-function-label-g { font-size: 36px; }
  /* At phone scale these rendered at 8.3px with only 2.1px between neighbours on the x-axis,
     which reads as noise along the axis rather than as numbers. No font size fixes that at
     this viewBox, so the half-unit gridlines carry the scale and the integer labels anchor
     it. */
  .graph-fractional-label { display: none; }
  .graph-axis-label { font-size: 36px; }
  .animation-label { font-size: 34px; stroke-width: 7px; }
  .animation-phase-label { font-size: 30px; stroke-width: 6px; }
  .graph-curve { stroke-width: 6; }
  .graph-curve-g { stroke-dasharray: 6 8; stroke-linecap: butt; }
  .graph-legend-swatch.graph-curve-g { stroke-dasharray: 7 8; }
  .graph-open-point, .graph-closed-point { r: 13; stroke-width: 5; }
  .animation-focus { stroke-width: 10; }
  .mobile-keypad { display: grid; }
  .answer-row { grid-template-columns: 1fr; }
  .answer-row .submit-button { display: none; }
  #answerInput { font-size: 18px; background: var(--surface); caret-color: transparent; }
  .answer-card label { font-size: 0.86rem; }
  .answer-card .help-text { display: none; }
  /* 44px is the smallest comfortable touch target; these were landing at 43.3px. */
  .special-answer-buttons { margin-top: 8px; }
  .special-answer-buttons button { min-height: 46px; }
  .checkbox-grid { grid-template-columns: 1fr; }
  .range-row { grid-template-columns: 1fr; }
  .progress-summary { grid-template-columns: 1fr; }
  .skill-row { grid-template-columns: 1fr auto; }
  .skill-bar { grid-column: 1 / -1; grid-row: 2; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; transition-duration: 0.001ms !important; animation-duration: 0.001ms !important; }
}
