"use client";

import { useState, useCallback } from "react";
import { Card } from "@/components/ui/card";
import { ClientOnly } from "@/components/ui/client-only";
import { StepControls } from "./step-controls";
import { MathDisplay } from "@/components/math/math-display";
import { shuffle } from "@/lib/utils";

type Mode = "number-line" | "order" | "compare";
type Direction = "asc" | "desc";
type Tone = "start" | "highlight" | "muted";

const MIN_VAL = -20;
const MAX_VAL = 20;
const RANGE = MAX_VAL - MIN_VAL;

interface Marker {
  value: number;
  label?: string;
  tone?: Tone;
}

interface OrderChips {
  pool: number[];
  ordered: number[];
  total: number;
}

interface Step {
  label: string;
  math: string;
  markers: Marker[];
  order?: OrderChips;
}

// Real-world contexts for the "Number Line" mode
const CONTEXTS = {
  number: {
    emoji: "🔢",
    label: "Number",
    describe: (n: number) =>
      n === 0
        ? "0 is neither positive nor negative — it separates the two sides."
        : `${n} is ${Math.abs(n)} step${Math.abs(n) === 1 ? "" : "s"} to the ${n < 0 ? "LEFT" : "RIGHT"} of zero.`,
  },
  thermometer: {
    emoji: "🌡️",
    label: "Temperature",
    describe: (n: number) =>
      n === 0
        ? "0 °C is freezing point — the boundary between warm and cold."
        : `${n} °C means ${Math.abs(n)} degree${Math.abs(n) === 1 ? "" : "s"} ${n < 0 ? "BELOW" : "ABOVE"} freezing.`,
  },
  money: {
    emoji: "💰",
    label: "Money",
    describe: (n: number) =>
      n === 0
        ? "$0 means you have nothing and owe nothing."
        : n < 0
          ? `−$${Math.abs(n)} means you OWE $${Math.abs(n)} (an overdraft).`
          : `+$${n} means you HAVE $${n} in the bank.`,
  },
  sea: {
    emoji: "🌊",
    label: "Sea level",
    describe: (n: number) =>
      n === 0
        ? "0 m is exactly at sea level."
        : `${n} m means ${Math.abs(n)} metre${Math.abs(n) === 1 ? "" : "s"} ${n < 0 ? "BELOW" : "ABOVE"} sea level.`,
  },
} as const;

type ContextKey = keyof typeof CONTEXTS;

function buildNumberLineSteps(n: number, ctx: ContextKey): Step[] {
  const context = CONTEXTS[ctx];
  const typeWord = n === 0 ? "zero" : n < 0 ? "a NEGATIVE integer" : "a POSITIVE integer";
  return [
    {
      label: "Zero sits in the middle. Negative numbers are to its LEFT, positive numbers to its RIGHT.",
      math: `\\ldots -3,\\ -2,\\ -1,\\ 0,\\ 1,\\ 2,\\ 3 \\ldots`,
      markers: [{ value: 0, label: "0", tone: "start" }],
    },
    {
      label: `Find ${n} on the number line and mark it.`,
      math: `\\text{Mark } ${n}`,
      markers: [
        { value: 0, tone: "muted" },
        { value: n, label: `${n}`, tone: "highlight" },
      ],
    },
    {
      label: `${context.emoji} ${context.describe(n)}`,
      math: `${n}`,
      markers: [{ value: n, label: `${n}`, tone: "start" }],
    },
    {
      label: `So ${n} is ${typeWord}.`,
      math: n === 0 ? `0` : `${n} \\text{ is } ${n < 0 ? "<" : ">"} 0`,
      markers: [{ value: n, label: `${n}`, tone: "start" }],
    },
  ];
}

function buildOrderSteps(values: number[], direction: Direction): Step[] {
  const sorted = [...values].sort((a, b) => (direction === "asc" ? a - b : b - a));
  const sizeWord = direction === "asc" ? "smallest" : "largest";
  const posWord = direction === "asc" ? "furthest LEFT" : "furthest RIGHT";
  const total = values.length;

  const steps: Step[] = [
    {
      label: "Here are the numbers we need to put in order.",
      math: `\\{\\, ${values.join(",\\ ")} \\,\\}`,
      markers: values.map((v) => ({ value: v, tone: "muted" as Tone })),
      order: { pool: [...values], ordered: [], total },
    },
    {
      label: "Place every number on the number line. Smaller numbers sit further left.",
      math: `\\text{left = smaller} \\qquad \\text{right = larger}`,
      markers: values.map((v) => ({ value: v, tone: "highlight" as Tone })),
      order: { pool: [...values], ordered: [], total },
    },
  ];

  const pool = [...values];
  const ordered: number[] = [];
  for (let i = 0; i < sorted.length; i++) {
    const pick = sorted[i];
    pool.splice(pool.indexOf(pick), 1);
    ordered.push(pick);
    steps.push({
      label: `The ${sizeWord} number still to place is the one ${posWord}: ${pick}.`,
      math: `${ordered.join(direction === "asc" ? " < " : " > ")}${pool.length ? "\\ \\ldots" : ""}`,
      markers: [
        ...ordered.map((v) => ({ value: v, tone: "start" as Tone })),
        ...pool.map((v) => ({ value: v, tone: "muted" as Tone })),
      ],
      order: { pool: [...pool], ordered: [...ordered], total },
    });
  }

  steps.push({
    label:
      direction === "asc"
        ? "Done! In ascending order: least → greatest."
        : "Done! In descending order: greatest → least.",
    math: `${sorted.join(direction === "asc" ? " < " : " > ")}`,
    markers: sorted.map((v) => ({ value: v, tone: "start" as Tone })),
    order: { pool: [], ordered: [...sorted], total },
  });

  return steps;
}

function buildCompareSteps(a: number, b: number): Step[] {
  const symbol = a < b ? "<" : a > b ? ">" : "=";
  const steps: Step[] = [
    {
      label: `Put both numbers on the number line.`,
      math: `${a} \\;\\square\\; ${b}`,
      markers: [
        { value: a, label: `${a}`, tone: "highlight" },
        { value: b, label: `${b}`, tone: "highlight" },
      ],
    },
  ];

  if (symbol === "=") {
    steps.push({
      label: "Both numbers land on the same spot, so they are equal.",
      math: `${a} = ${b}`,
      markers: [{ value: a, label: `${a}`, tone: "start" }],
    });
    return steps;
  }

  const larger = a > b ? a : b;
  const smaller = a > b ? b : a;
  steps.push(
    {
      label: `The number further RIGHT is always larger. ${larger} is to the right of ${smaller}.`,
      math: `${larger} \\text{ is larger}`,
      markers: [
        { value: smaller, label: `${smaller}`, tone: "muted" },
        { value: larger, label: `${larger}`, tone: "start" },
      ],
    },
    {
      label: `The open mouth of the sign always points to the LARGER number.`,
      math: `${a} ${symbol} ${b}`,
      markers: [
        { value: a, label: `${a}`, tone: a === larger ? "start" : "muted" },
        { value: b, label: `${b}`, tone: b === larger ? "start" : "muted" },
      ],
    },
  );
  return steps;
}

function NumberLine({ markers }: { markers: Marker[] }) {
  return (
    <div className="mx-auto w-full max-w-2xl select-none">
      <div className="relative h-28 px-4">
        {/* Markers above the line */}
        {markers.map((m, i) => {
          const x = ((m.value - MIN_VAL) / RANGE) * 100;
          const tone = m.tone ?? "highlight";
          const bg =
            tone === "start" ? "bg-unit-5" : tone === "muted" ? "bg-muted/70" : "bg-correct";
          return (
            <div
              key={`${m.value}-${i}`}
              className="absolute bottom-14 -translate-x-1/2 transition-all duration-500"
              style={{ left: `calc(${x}% + 16px)` }}
            >
              <div className="flex flex-col items-center">
                {m.label !== undefined && (
                  <span
                    className={`rounded-full ${bg} px-2 py-0.5 text-[10px] font-bold text-white shadow-md`}
                  >
                    {m.label}
                  </span>
                )}
                <div className={`h-3 w-0.5 ${bg}`} />
              </div>
            </div>
          );
        })}

        {/* Number line */}
        <div className="absolute bottom-8 left-4 right-4">
          <div className="h-0.5 bg-foreground/40" />
          {Array.from({ length: RANGE + 1 }, (_, i) => {
            const val = MIN_VAL + i;
            const x = (i / RANGE) * 100;
            const isZero = val === 0;
            const marked = markers.some((m) => m.value === val);
            return (
              <div key={val} className="absolute -translate-x-1/2" style={{ left: `${x}%` }}>
                <div
                  className={`h-3 w-0.5 -translate-y-1.5 transition-colors duration-300 ${
                    marked
                      ? "h-4 bg-unit-5"
                      : isZero
                        ? "bg-foreground"
                        : "bg-foreground/30"
                  }`}
                />
                {(val % 5 === 0 || marked) && (
                  <span
                    className={`mt-1 block text-center text-[10px] transition-all duration-300 ${
                      marked
                        ? "font-extrabold text-unit-5"
                        : isZero
                          ? "font-bold text-foreground"
                          : "text-muted/70"
                    }`}
                  >
                    {val}
                  </span>
                )}
              </div>
            );
          })}
        </div>

        {/* Edge labels */}
        <div className="absolute bottom-0 left-2 right-2 flex justify-between text-xs text-muted/50">
          <span>← negative</span>
          <span>positive →</span>
        </div>
      </div>
    </div>
  );
}

function OrderChipsView({ order, direction }: { order: OrderChips; direction: Direction }) {
  const emptySlots = order.total - order.ordered.length;
  return (
    <div className="w-full space-y-3">
      <div>
        <p className="mb-1.5 text-xs font-bold uppercase tracking-wider text-muted">Still to place</p>
        <div className="flex min-h-9 flex-wrap gap-2">
          {order.pool.length === 0 ? (
            <span className="text-sm text-muted/50">— all placed —</span>
          ) : (
            order.pool.map((v, i) => (
              <span
                key={`${v}-${i}`}
                className="rounded-lg border-2 border-border bg-surface px-3 py-1.5 text-sm font-bold text-muted"
              >
                {v}
              </span>
            ))
          )}
        </div>
      </div>
      <div>
        <p className="mb-1.5 text-xs font-bold uppercase tracking-wider text-unit-5">
          Ordered ({direction === "asc" ? "small → large" : "large → small"})
        </p>
        <div className="flex flex-wrap items-center gap-2">
          {order.ordered.map((v, i) => (
            <span key={`${v}-${i}`} className="flex items-center gap-2">
              {i > 0 && <span className="text-sm font-bold text-unit-5">{direction === "asc" ? "<" : ">"}</span>}
              <span className="rounded-lg border-2 border-unit-5 bg-unit-5-light px-3 py-1.5 text-sm font-extrabold text-unit-5-dark">
                {v}
              </span>
            </span>
          ))}
          {Array.from({ length: emptySlots }, (_, i) => (
            <span key={`empty-${i}`} className="flex items-center gap-2">
              {(order.ordered.length > 0 || i > 0) && (
                <span className="text-sm font-bold text-muted/40">{direction === "asc" ? "<" : ">"}</span>
              )}
              <span className="h-9 w-11 rounded-lg border-2 border-dashed border-border" />
            </span>
          ))}
        </div>
      </div>
    </div>
  );
}

// ── Quick practice ───────────────────────────────────────────────────────────

const SEED_PAIRS: [number, number][] = [
  [-5, 5],
  [4, -16],
  [-6, -11],
  [0, -3],
  [8, -1],
];

function randInt(min: number, max: number) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function makePair(): [number, number] {
  if (Math.random() < 0.4) return SEED_PAIRS[Math.floor(Math.random() * SEED_PAIRS.length)];
  const a = randInt(-15, 15);
  let b = randInt(-15, 15);
  if (a === b) b = a + 1;
  return [a, b];
}

function makeOrderValues(): number[] {
  const set = new Set<number>();
  while (set.size < 4) set.add(randInt(-12, 12));
  return shuffle([...set]);
}

function ComparePractice({ onScore }: { onScore: (correct: boolean) => void }) {
  const [pair, setPair] = useState<[number, number]>(() => makePair());
  const [feedback, setFeedback] = useState<"correct" | "incorrect" | null>(null);

  const [a, b] = pair;
  const answer = a < b ? "<" : ">";

  function pick(sign: "<" | ">") {
    if (feedback === "correct") return;
    const correct = sign === answer;
    setFeedback(correct ? "correct" : "incorrect");
    if (correct) onScore(true);
    else onScore(false);
  }

  function next() {
    setPair(makePair());
    setFeedback(null);
  }

  return (
    <div className="space-y-4 text-center">
      <p className="text-sm text-muted">Which sign makes it true?</p>
      <div className="flex items-center justify-center gap-4 text-3xl font-extrabold">
        <span>{a}</span>
        <span className="inline-flex h-11 w-11 items-center justify-center rounded-xl border-2 border-dashed border-unit-5/50 text-unit-5">
          ?
        </span>
        <span>{b}</span>
      </div>
      <div className="flex justify-center gap-3">
        {(["<", ">"] as const).map((sign) => (
          <button
            key={sign}
            onClick={() => pick(sign)}
            disabled={feedback === "correct"}
            className={`h-14 w-14 rounded-xl border-2 text-2xl font-extrabold transition-colors ${
              feedback === "correct" && sign === answer
                ? "border-correct bg-correct-light text-correct"
                : feedback === "incorrect" && sign !== answer
                  ? "border-border text-muted"
                  : "border-unit-5/40 text-unit-5 hover:bg-unit-5-light disabled:opacity-50"
            }`}
          >
            {sign}
          </button>
        ))}
      </div>
      {feedback === "correct" && (
        <div className="space-y-2">
          <p className="text-sm font-bold text-correct">Correct! {a} {answer} {b}</p>
          <button onClick={next} className="rounded-lg bg-foreground px-5 py-2 text-sm font-bold text-background hover:bg-foreground/80">
            Next →
          </button>
        </div>
      )}
      {feedback === "incorrect" && (
        <p className="text-sm font-bold text-incorrect">Not quite — remember, further right means larger. Try again.</p>
      )}
    </div>
  );
}

function OrderPractice({ onScore }: { onScore: (correct: boolean) => void }) {
  const [values, setValues] = useState<number[]>(() => makeOrderValues());
  const [placed, setPlaced] = useState<number[]>([]);
  const [wrong, setWrong] = useState<number | null>(null);
  const [mistakes, setMistakes] = useState(0);
  const [done, setDone] = useState(false);

  const sorted = [...values].sort((a, b) => a - b);
  const nextExpected = sorted[placed.length];

  function clickChip(v: number) {
    if (done || placed.includes(v)) return;
    if (v === nextExpected) {
      const nextPlaced = [...placed, v];
      setPlaced(nextPlaced);
      setWrong(null);
      if (nextPlaced.length === sorted.length) {
        setDone(true);
        onScore(mistakes === 0);
      }
    } else {
      setWrong(v);
      setMistakes((m) => m + 1);
      setTimeout(() => setWrong((w) => (w === v ? null : w)), 500);
    }
  }

  function next() {
    setValues(makeOrderValues());
    setPlaced([]);
    setWrong(null);
    setMistakes(0);
    setDone(false);
  }

  return (
    <div className="space-y-4 text-center">
      <p className="text-sm text-muted">Click the numbers in ascending order (smallest first).</p>
      <div className="flex flex-wrap justify-center gap-2">
        {values.map((v) => {
          const isPlaced = placed.includes(v);
          const isWrong = wrong === v;
          return (
            <button
              key={v}
              onClick={() => clickChip(v)}
              disabled={isPlaced || done}
              className={`h-12 w-14 rounded-xl border-2 text-lg font-extrabold transition-all ${
                isPlaced
                  ? "border-correct bg-correct-light text-correct"
                  : isWrong
                    ? "border-incorrect bg-incorrect-light text-incorrect"
                    : "border-unit-5/40 text-unit-5-dark hover:bg-unit-5-light"
              }`}
            >
              {v}
            </button>
          );
        })}
      </div>
      <div className="flex items-center justify-center gap-2 text-lg font-bold text-unit-5">
        {placed.map((v, i) => (
          <span key={v}>
            {i > 0 && <span className="mr-2 text-muted">{"<"}</span>}
            {v}
          </span>
        ))}
        {placed.length < sorted.length && <span className="text-muted/40">…</span>}
      </div>
      {done && (
        <div className="space-y-2">
          <p className="text-sm font-bold text-correct">
            {mistakes === 0 ? "Perfect ordering!" : `Ordered — with ${mistakes} slip${mistakes === 1 ? "" : "s"}.`}
          </p>
          <button onClick={next} className="rounded-lg bg-foreground px-5 py-2 text-sm font-bold text-background hover:bg-foreground/80">
            Next →
          </button>
        </div>
      )}
    </div>
  );
}

function QuickPractice() {
  const [kind, setKind] = useState<"compare" | "order">("compare");
  const [score, setScore] = useState({ correct: 0, total: 0 });

  const record = useCallback((correct: boolean) => {
    setScore((s) => ({ correct: s.correct + (correct ? 1 : 0), total: s.total + 1 }));
  }, []);

  return (
    <Card className="space-y-4">
      <div className="flex items-center justify-between">
        <div className="flex gap-1.5">
          {(["compare", "order"] as const).map((k) => (
            <button
              key={k}
              onClick={() => setKind(k)}
              className={`rounded-full px-3 py-1 text-xs font-bold transition-colors ${
                kind === k ? "bg-unit-5 text-white" : "text-unit-5 hover:bg-unit-5-light"
              }`}
            >
              {k === "compare" ? "Compare" : "Order"}
            </button>
          ))}
        </div>
        <span className="rounded-full bg-unit-5-light px-3 py-1 text-xs font-bold text-unit-5-dark">
          {score.correct}/{score.total}
        </span>
      </div>
      {kind === "compare" ? (
        <ComparePractice key={`c-${score.total}`} onScore={record} />
      ) : (
        <OrderPractice key={`o-${score.total}`} onScore={record} />
      )}
    </Card>
  );
}

// ── Main explorer ────────────────────────────────────────────────────────────

export function IntegerOrderCompareExplorer() {
  const [mode, setMode] = useState<Mode>("number-line");

  // number-line mode
  const [nlInput, setNlInput] = useState("-7");
  const [context, setContext] = useState<ContextKey>("thermometer");

  // order mode
  const [orderInput, setOrderInput] = useState("-8, -10, -4, -3, -6, 5");
  const [direction, setDirection] = useState<Direction>("asc");

  // compare mode
  const [cmpA, setCmpA] = useState("-5");
  const [cmpB, setCmpB] = useState("5");

  const [error, setError] = useState("");
  const [steps, setSteps] = useState<Step[] | null>(null);
  const [currentStep, setCurrentStep] = useState(0);
  const [isPlaying, setIsPlaying] = useState(false);

  const done = steps ? currentStep >= steps.length - 1 : false;

  const reset = useCallback(() => {
    setSteps(null);
    setCurrentStep(0);
    setIsPlaying(false);
  }, []);

  function switchMode(m: Mode) {
    setMode(m);
    setError("");
    reset();
  }

  function handleGo() {
    setError("");
    try {
      if (mode === "number-line") {
        const n = parseInt(nlInput, 10);
        if (isNaN(n)) return setError("Enter a valid integer.");
        if (n < MIN_VAL || n > MAX_VAL) return setError(`Keep the number between ${MIN_VAL} and ${MAX_VAL}.`);
        setSteps(buildNumberLineSteps(n, context));
      } else if (mode === "order") {
        const parts = orderInput
          .split(",")
          .map((s) => s.trim())
          .filter((s) => s.length > 0);
        const nums = parts.map((s) => parseInt(s, 10));
        if (nums.some((n) => isNaN(n))) return setError("Use whole numbers separated by commas, e.g. -8, -10, 5.");
        if (nums.length < 3 || nums.length > 6) return setError("Enter between 3 and 6 numbers.");
        if (nums.some((n) => n < MIN_VAL || n > MAX_VAL)) return setError(`Keep every number between ${MIN_VAL} and ${MAX_VAL}.`);
        setSteps(buildOrderSteps(nums, direction));
      } else {
        const a = parseInt(cmpA, 10);
        const b = parseInt(cmpB, 10);
        if (isNaN(a) || isNaN(b)) return setError("Enter two valid integers.");
        if ([a, b].some((n) => n < MIN_VAL || n > MAX_VAL)) return setError(`Keep both numbers between ${MIN_VAL} and ${MAX_VAL}.`);
        setSteps(buildCompareSteps(a, b));
      }
      setCurrentStep(0);
      setIsPlaying(false);
    } catch {
      setError("Could not build the steps. Check your input.");
    }
  }

  const stepForward = useCallback(() => {
    if (!steps || currentStep >= steps.length - 1) return;
    setCurrentStep((s) => s + 1);
    if (currentStep + 1 >= steps.length - 1) setIsPlaying(false);
  }, [steps, currentStep]);

  const stepBack = useCallback(() => {
    if (currentStep <= 0) return;
    setCurrentStep((s) => s - 1);
  }, [currentStep]);

  const togglePlay = useCallback(() => setIsPlaying((p) => !p), []);

  const step = steps ? steps[currentStep] : null;

  return (
    <div className="space-y-4">
      {/* Mode toggle */}
      <div className="flex flex-wrap gap-2">
        {(["number-line", "order", "compare"] as Mode[]).map((m) => (
          <button
            key={m}
            onClick={() => switchMode(m)}
            className={`rounded-full border-2 px-4 py-2 text-sm font-semibold transition-colors ${
              mode === m
                ? "border-unit-5 bg-unit-5 text-white"
                : "border-unit-5/40 text-unit-5 hover:bg-unit-5-light"
            }`}
          >
            {m === "number-line" ? "Number Line" : m === "order" ? "Order" : "Compare"}
          </button>
        ))}
      </div>

      {/* Input card */}
      <Card>
        {mode === "number-line" && (
          <>
            <p className="mb-3 text-xs font-bold uppercase tracking-wider text-unit-5">
              Place an integer on the number line
            </p>
            <div className="mb-3 flex flex-wrap gap-2">
              {(Object.keys(CONTEXTS) as ContextKey[]).map((key) => (
                <button
                  key={key}
                  onClick={() => {
                    setContext(key);
                    reset();
                  }}
                  className={`rounded-full border-2 px-3 py-1.5 text-xs font-semibold transition-colors ${
                    context === key
                      ? "border-unit-5-dark bg-unit-5-dark text-white"
                      : "border-unit-5/30 text-unit-5-dark hover:bg-unit-5-light"
                  }`}
                >
                  {CONTEXTS[key].emoji} {CONTEXTS[key].label}
                </button>
              ))}
            </div>
            <div className="flex flex-wrap items-center gap-3">
              <input
                type="number"
                value={nlInput}
                onChange={(e) => setNlInput(e.target.value)}
                className="w-24 rounded-lg border-2 border-border bg-surface px-3 py-2 text-center text-lg font-bold outline-none focus:border-unit-5"
                aria-label="Integer"
              />
              <button
                onClick={handleGo}
                className="rounded-lg bg-unit-5 px-6 py-2.5 text-sm font-bold text-white transition-colors hover:bg-unit-5-dark"
              >
                Go →
              </button>
            </div>
          </>
        )}

        {mode === "order" && (
          <>
            <p className="mb-3 text-xs font-bold uppercase tracking-wider text-unit-5">
              Enter 3–6 integers to order
            </p>
            <div className="mb-3 flex flex-wrap gap-2">
              {(["asc", "desc"] as Direction[]).map((d) => (
                <button
                  key={d}
                  onClick={() => {
                    setDirection(d);
                    reset();
                  }}
                  className={`rounded-full border-2 px-4 py-1.5 text-xs font-semibold transition-colors ${
                    direction === d
                      ? "border-unit-5-dark bg-unit-5-dark text-white"
                      : "border-unit-5/30 text-unit-5-dark hover:bg-unit-5-light"
                  }`}
                >
                  {d === "asc" ? "Ascending (small → large)" : "Descending (large → small)"}
                </button>
              ))}
            </div>
            <div className="flex flex-wrap items-center gap-3">
              <input
                type="text"
                value={orderInput}
                onChange={(e) => setOrderInput(e.target.value)}
                className="min-w-[16rem] flex-1 rounded-lg border-2 border-border bg-surface px-3 py-2 text-center text-lg font-bold outline-none focus:border-unit-5"
                aria-label="Comma-separated integers"
              />
              <button
                onClick={handleGo}
                className="rounded-lg bg-unit-5 px-6 py-2.5 text-sm font-bold text-white transition-colors hover:bg-unit-5-dark"
              >
                Go →
              </button>
            </div>
          </>
        )}

        {mode === "compare" && (
          <>
            <p className="mb-3 text-xs font-bold uppercase tracking-wider text-unit-5">
              Compare two integers with &lt; or &gt;
            </p>
            <div className="flex flex-wrap items-center gap-3">
              <input
                type="number"
                value={cmpA}
                onChange={(e) => setCmpA(e.target.value)}
                className="w-20 rounded-lg border-2 border-border bg-surface px-3 py-2 text-center text-lg font-bold outline-none focus:border-unit-5"
                aria-label="First integer"
              />
              <span className="text-xl font-bold text-muted">?</span>
              <input
                type="number"
                value={cmpB}
                onChange={(e) => setCmpB(e.target.value)}
                className="w-20 rounded-lg border-2 border-border bg-surface px-3 py-2 text-center text-lg font-bold outline-none focus:border-unit-5"
                aria-label="Second integer"
              />
              <button
                onClick={handleGo}
                className="rounded-lg bg-unit-5 px-6 py-2.5 text-sm font-bold text-white transition-colors hover:bg-unit-5-dark"
              >
                Go →
              </button>
            </div>
          </>
        )}
        {error && <p className="mt-2 text-sm text-incorrect">{error}</p>}
      </Card>

      {/* Display card */}
      <Card className="flex min-h-[280px] flex-col items-center justify-center gap-4 p-6">
        {!step ? (
          <p className="text-muted/50">
            Set up the numbers above and click <strong>Go</strong>
          </p>
        ) : (
          <>
            <p className="text-center text-sm font-medium text-muted">{step.label}</p>
            <MathDisplay math={step.math} className="text-2xl" />
            <NumberLine markers={step.markers} />
            {step.order && <OrderChipsView order={step.order} direction={direction} />}
          </>
        )}
      </Card>

      {/* Controls */}
      <Card className="p-4">
        <StepControls
          currentStep={currentStep + 1}
          totalSteps={steps?.length ?? 0}
          isPlaying={isPlaying}
          onStepForward={stepForward}
          onStepBack={stepBack}
          onTogglePlay={togglePlay}
          onReset={reset}
          canStepForward={!!steps && !done}
          canStepBack={!!steps && currentStep > 0}
        />
      </Card>

      {/* Quick practice */}
      <ClientOnly fallback={<Card className="min-h-[220px]" />}>
        <QuickPractice />
      </ClientOnly>
    </div>
  );
}
