// Test flow: mode chooser, sample/mock test UI, PDF scan upload
const { useState: useState_T, useEffect: useEffect_T, useRef: useRef_T } = React;

// ---------- Sample questions (placeholder) ----------
// NOTE: actual questions are supplied by user's code later.
// This is a design-time placeholder with representative shape.
const PLACEHOLDER_QUESTIONS = [
  {
    id: 1, topicId: 1,
    en: "Calculate: 348 + 276 − 149",
    ko: "계산하세요: 348 + 276 − 149",
    options: ["475", "485", "475", "575"],
    optionsLabeled: ["365", "475", "485", "575"],
    correct: 1,
    solutionEn: "348 + 276 = 624. Then 624 − 149 = 475.",
    solutionKo: "348 + 276 = 624. 이어서 624 − 149 = 475.",
  },
  {
    id: 2, topicId: 3,
    en: "Which of these is a common factor of 24 and 36?",
    ko: "24와 36의 공약수는 어느 것입니까?",
    optionsLabeled: ["5", "7", "12", "16"],
    correct: 2,
    solutionEn: "Factors of 24: 1, 2, 3, 4, 6, 8, 12, 24. Factors of 36: 1, 2, 3, 4, 6, 9, 12, 18, 36. Common factors include 12.",
    solutionKo: "24의 약수: 1, 2, 3, 4, 6, 8, 12, 24. 36의 약수: 1, 2, 3, 4, 6, 9, 12, 18, 36. 공약수 중 12가 포함됩니다.",
  },
  {
    id: 3, topicId: 4,
    en: "What is 3/4 written as a decimal?",
    ko: "3/4을 소수로 나타내면?",
    optionsLabeled: ["0.25", "0.34", "0.75", "0.8"],
    correct: 2,
    solutionEn: "3 ÷ 4 = 0.75.",
    solutionKo: "3 ÷ 4 = 0.75.",
  },
  {
    id: 4, topicId: 5,
    en: "A coat costs £80. In a sale it is reduced by 25%. What is the sale price?",
    ko: "코트가 £80입니다. 세일에서 25% 할인되면 판매가는?",
    optionsLabeled: ["£20", "£55", "£60", "£65"],
    correct: 2,
    solutionEn: "25% of 80 = 20. 80 − 20 = £60.",
    solutionKo: "80의 25% = 20. 80 − 20 = £60.",
  },
  {
    id: 5, topicId: 9,
    en: "A train leaves at 09:47 and the journey takes 1 hour 25 minutes. What time does it arrive?",
    ko: "열차가 09:47에 출발하고 1시간 25분 걸립니다. 도착 시각은?",
    optionsLabeled: ["10:12", "11:02", "11:12", "11:22"],
    correct: 2,
    solutionEn: "09:47 + 1h = 10:47. Then +25 min = 11:12.",
    solutionKo: "09:47 + 1시간 = 10:47. 거기에 25분 더하면 11:12.",
  },
  {
    id: 6, topicId: 7,
    en: "The numbers 6, 8, 11, 3, 7 have what mean?",
    ko: "6, 8, 11, 3, 7의 평균은?",
    optionsLabeled: ["5", "7", "8", "9"],
    correct: 1,
    solutionEn: "Sum = 35. Mean = 35 ÷ 5 = 7.",
    solutionKo: "합 = 35. 평균 = 35 ÷ 5 = 7.",
  },
  {
    id: 7, topicId: 11,
    en: "A rectangle is 8 cm long and 5 cm wide. What is its area?",
    ko: "가로 8cm, 세로 5cm인 직사각형의 넓이는?",
    optionsLabeled: ["13 cm²", "26 cm²", "40 cm²", "45 cm²"],
    correct: 2,
    solutionEn: "Area = length × width = 8 × 5 = 40 cm².",
    solutionKo: "넓이 = 가로 × 세로 = 8 × 5 = 40 cm².",
  },
  {
    id: 8, topicId: 6,
    en: "If 3n + 4 = 19, what is n?",
    ko: "3n + 4 = 19 일 때, n은?",
    optionsLabeled: ["3", "5", "6", "7"],
    correct: 1,
    solutionEn: "3n = 19 − 4 = 15. n = 15 ÷ 3 = 5.",
    solutionKo: "3n = 19 − 4 = 15. n = 15 ÷ 3 = 5.",
  },
  {
    id: 9, topicId: 13,
    en: "A bag has 3 red and 7 blue marbles. The probability of drawing red?",
    ko: "빨간 구슬 3개와 파란 구슬 7개. 빨간 구슬을 뽑을 확률은?",
    optionsLabeled: ["3/10", "7/10", "1/3", "3/7"],
    correct: 0,
    solutionEn: "Total = 10. P(red) = 3/10.",
    solutionKo: "전체 = 10. P(빨강) = 3/10.",
  },
  {
    id: 10, topicId: 14,
    en: "Point A is at (2, 3). After translation (+3, −1), where is A?",
    ko: "점 A는 (2, 3)입니다. (+3, −1) 평행이동 후 위치는?",
    optionsLabeled: ["(5, 4)", "(5, 2)", "(−1, 2)", "(2, 2)"],
    correct: 1,
    solutionEn: "(2+3, 3−1) = (5, 2).",
    solutionKo: "(2+3, 3−1) = (5, 2).",
  },
];

// ---------- Mode chooser ----------
function ModeChooser({ onPick, onCancel, paperName }) {
  const { t, lang } = useT();
  const [selected, setSelected] = useState_T(null);
  return (
    <div style={{
      position: "fixed", inset: 0, zIndex: 100,
      background: "color-mix(in oklab, var(--ink-1) 45%, transparent)",
      display: "flex", alignItems: "center", justifyContent: "center",
      padding: 24,
    }} onClick={onCancel}>
      <div onClick={(e) => e.stopPropagation()} style={{
        background: "var(--paper)", borderRadius: 16,
        maxWidth: 720, width: "100%", padding: 36, boxShadow: "var(--shadow-lg)",
      }}>
        <div className="mono" style={{ fontSize: 11, color: "var(--ink-3)", letterSpacing: "0.08em", textTransform: "uppercase" }}>
          {paperName}
        </div>
        <h2 style={{ fontSize: 28, marginTop: 6 }}>{t("mode_title")}</h2>
        <p style={{ color: "var(--ink-3)", fontSize: 14, marginTop: 8 }}>{t("mode_sub")}</p>

        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14, marginTop: 24 }}>
          {[
            {
              id: "online", title: t("mode_online"), desc: t("mode_online_desc"), recommended: true,
              icon: (
                <svg width="36" height="36" viewBox="0 0 40 40" fill="none">
                  <rect x="4" y="8" width="32" height="22" rx="2" stroke="var(--ink-1)" strokeWidth="1.5" fill="var(--indigo-tint)" />
                  <path d="M16 30v4M24 30v4M12 34h16" stroke="var(--ink-1)" strokeWidth="1.5" strokeLinecap="round" />
                  <path d="M10 14h20M10 18h14" stroke="var(--ink-1)" strokeWidth="1.2" />
                </svg>
              )
            },
            {
              id: "paper", title: t("mode_paper"), desc: t("mode_paper_desc"),
              icon: (
                <svg width="36" height="36" viewBox="0 0 40 40" fill="none">
                  <rect x="8" y="6" width="24" height="30" rx="1.5" stroke="var(--ink-1)" strokeWidth="1.5" fill="var(--amber-tint)" />
                  <path d="M12 13h16M12 17h16M12 21h10" stroke="var(--ink-1)" strokeWidth="1.2" />
                  <circle cx="14" cy="28" r="1.5" fill="var(--ink-1)" />
                  <circle cx="20" cy="28" r="1.5" fill="var(--ink-1)" />
                  <circle cx="26" cy="28" r="1.5" fill="var(--ink-1)" />
                </svg>
              )
            },
          ].map((opt) => (
            <button key={opt.id} onClick={() => setSelected(opt.id)}
              style={{
                textAlign: "left", padding: 20, borderRadius: 12,
                border: "2px solid " + (selected === opt.id ? "var(--ink-1)" : "var(--line)"),
                background: selected === opt.id ? "var(--paper-2)" : "white",
                cursor: "pointer", fontFamily: "inherit",
                position: "relative",
              }}>
              {opt.recommended && (
                <span className="pill" style={{
                  position: "absolute", top: 14, right: 14,
                  color: "var(--emerald)", background: "var(--emerald-tint)",
                  borderColor: "color-mix(in oklab, var(--emerald) 25%, transparent)"
                }}>{t("mode_recommended")}</span>
              )}
              <div style={{ marginBottom: 14 }}>{opt.icon}</div>
              <div style={{ fontFamily: "var(--font-serif)", fontSize: 20 }}>{opt.title}</div>
              <div style={{ fontSize: 13, color: "var(--ink-3)", marginTop: 6, lineHeight: 1.5 }}>{opt.desc}</div>
            </button>
          ))}
        </div>

        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 28 }}>
          <button className="btn btn-ghost" onClick={onCancel}>{lang === "ko" ? "취소" : "Cancel"}</button>
          <button className="btn btn-primary" disabled={!selected} style={{ opacity: selected ? 1 : 0.4 }}
            onClick={() => onPick(selected)}>
            {t("mode_go")}
          </button>
        </div>
      </div>
    </div>
  );
}

// ---------- Test taking UI ----------
function TestUI({ questions, isSample, paperName, durationMin = 50, onFinish, onExit, initialState, stateRef }) {
  const { t, lang } = useT();
  const [idx, setIdx] = useState_T(() => initialState?.idx ?? 0);
  const [answers, setAnswers] = useState_T(() => {
    if (initialState?.answers && initialState.answers.length === questions.length) return initialState.answers;
    return questions.map(() => null);
  });
  const [flagged, setFlagged] = useState_T(() => new Set());
  const [timeLeft, setTimeLeft] = useState_T(() => initialState?.timeLeft ?? durationMin * 60);
  const q = questions[idx];

  useEffect_T(() => {
    const id = setInterval(() => setTimeLeft(t => Math.max(0, t - 1)), 1000);
    return () => clearInterval(id);
  }, []);

  // Auto-submit when timer reaches zero (sample + mock).
  const submittedRef = useRef_T(false);
  useEffect_T(() => {
    if (timeLeft === 0 && !submittedRef.current) {
      submittedRef.current = true;
      onFinish(answers, flagged);
    }
  }, [timeLeft]);

  // 5-minute warning banner (sample + mock).
  const [warn5Shown, setWarn5Shown] = useState_T(false);
  const [warnVisible, setWarnVisible] = useState_T(false);
  useEffect_T(() => {
    if (timeLeft === 300 && !warn5Shown) { setWarn5Shown(true); setWarnVisible(true); }
  }, [timeLeft]);

  // Auto-save progress to localStorage on every answer/navigation change (mock only).
  useEffect_T(() => {
    if (!paperName || isSample) return;
    try { localStorage.setItem(`epl_inprogress_${paperName}`, JSON.stringify({ idx, answers, timeLeft })); } catch {}
  }, [answers, idx]);

  // Expose current state to parent so the Save-progress flow can snapshot it.
  useEffect_T(() => {
    if (stateRef) stateRef.current = { idx, answers, timeLeft };
  }, [idx, answers, timeLeft, stateRef]);
  if (!q) return null;
  const mm = String(Math.floor(timeLeft / 60)).padStart(2, "0");
  const ss = String(timeLeft % 60).padStart(2, "0");

  const pick = (opt) => setAnswers(a => { const c = [...a]; c[idx] = opt; return c; });
  const toggleFlag = () => setFlagged(f => { const n = new Set(f); n.has(idx) ? n.delete(idx) : n.add(idx); return n; });
  const stem = lang === "ko" ? q.ko : q.en;
  const useHtml = !!q._html;
  const diagramHtml = q._diagramHtml || "";
  const followHtml = q._questionHtml || "";

  return (
    <div style={{ minHeight: "100vh", display: "flex", flexDirection: "column", background: "var(--paper)" }}>
      {/* Top bar */}
      <div style={{
        borderBottom: "1px solid var(--line)", padding: "14px 28px",
        display: "flex", alignItems: "center", gap: 20, background: "white",
      }}>
        <Logo size={20} />
        <div className="pill" style={{
          color: isSample ? "var(--amber)" : "var(--indigo)",
          background: isSample ? "var(--amber-tint)" : "var(--indigo-tint)",
          borderColor: "transparent"
        }}>
          <span className="dot" />
          {isSample ? (lang === "ko" ? "샘플 · 비공개" : "SAMPLE · UNGRADED") : paperName}
        </div>
        <div style={{ flex: 1 }} />
        <div style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 13, color: "var(--ink-2)" }}>
          <svg width="14" height="14" viewBox="0 0 20 20" fill="none">
            <circle cx="10" cy="10" r="7" stroke="var(--ink-1)" strokeWidth="1.5" />
            <path d="M10 6v4l3 2" stroke="var(--ink-1)" strokeWidth="1.5" strokeLinecap="round" />
          </svg>
          <span>{t("test_time")}</span>
          <span className="mono tabular" style={{ fontSize: 15, color: timeLeft < 120 ? "var(--rose)" : "var(--ink-1)" }}>
            {mm}:{ss}
          </span>
        </div>
        <button className="btn btn-ghost" onClick={onExit} style={{ padding: "6px 12px", fontSize: 13 }}>
          {lang === "ko" ? "나가기" : "Exit"}
        </button>
      </div>
      {warnVisible && (
        <div style={{
          background: "var(--amber-tint)", borderBottom: "1px solid var(--amber)",
          padding: "10px 28px", display: "flex", alignItems: "center", gap: 12, fontSize: 14,
        }}>
          <span style={{ color: "var(--amber)", fontWeight: 600 }}>⏰</span>
          <span style={{ flex: 1, color: "var(--ink-1)" }}>
            {lang === "ko" ? "시험 종료 5분 전입니다." : "5 minutes remaining."}
          </span>
          <button onClick={() => setWarnVisible(false)} style={{
            border: "none", background: "transparent", cursor: "pointer",
            fontSize: 13, color: "var(--ink-2)", fontFamily: "inherit",
          }}>
            {lang === "ko" ? "확인" : "OK"}
          </button>
        </div>
      )}

      <div style={{ flex: 1, display: "grid", gridTemplateColumns: "1fr 280px", gap: 0, maxWidth: 1240, margin: "0 auto", width: "100%" }}>
        {/* Question area */}
        <div style={{ padding: "48px 40px", maxWidth: 760 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
            <div className="mono tabular" style={{ fontSize: 13, color: "var(--ink-3)" }}>
              {t("test_q")} <span style={{ color: "var(--ink-1)" }}>{idx + 1}</span> {t("test_of")} {questions.length}
            </div>
            <button onClick={toggleFlag} style={{
              border: "1px solid " + (flagged.has(idx) ? "var(--amber)" : "var(--line)"),
              background: flagged.has(idx) ? "var(--amber-tint)" : "transparent",
              color: flagged.has(idx) ? "var(--amber)" : "var(--ink-3)",
              padding: "4px 10px", borderRadius: 999, fontSize: 12,
              cursor: "pointer", display: "flex", alignItems: "center", gap: 6,
              fontFamily: "inherit",
            }}>
              <svg width="11" height="11" viewBox="0 0 20 20" fill={flagged.has(idx) ? "var(--amber)" : "none"} stroke="currentColor" strokeWidth="1.8">
                <path d="M5 3v15M5 3h10l-2.5 3.5L15 10H5" />
              </svg>
              {flagged.has(idx) ? t("test_flagged") : t("test_flag")}
            </button>
          </div>

          {useHtml ? (
            <h2 className="q-stem" style={{ fontFamily: "var(--font-serif)", fontSize: 24, marginTop: 18, lineHeight: 1.5, letterSpacing: "-0.01em", textWrap: "pretty", fontWeight: 400 }}
              dangerouslySetInnerHTML={{ __html: stem }} />
          ) : (
            <h2 style={{ fontFamily: "var(--font-serif)", fontSize: 26, marginTop: 18, lineHeight: 1.4, letterSpacing: "-0.01em", textWrap: "pretty", fontWeight: 400 }}>
              {stem}
            </h2>
          )}

          {diagramHtml && (
            <div className="sutton-diagram" dangerouslySetInnerHTML={{ __html: diagramHtml }} />
          )}
          {followHtml && (
            <div className="q-follow" dangerouslySetInnerHTML={{ __html: followHtml }} />
          )}

          <div style={{ display: "grid", gap: 10, marginTop: 28 }}>
            {q.optionsLabeled.map((opt, i) => {
              const active = answers[idx] === i;
              return (
                <button key={i} onClick={() => pick(i)} style={{
                  textAlign: "left", padding: "16px 18px", borderRadius: 10,
                  border: "1.5px solid " + (active ? "var(--ink-1)" : "var(--line)"),
                  background: active ? "var(--paper-2)" : "white",
                  cursor: "pointer", fontFamily: "inherit", fontSize: 16,
                  display: "flex", alignItems: "center", gap: 14,
                  transition: "all .12s ease",
                }}>
                  <span style={{
                    width: 28, height: 28, borderRadius: 6,
                    background: active ? "var(--ink-1)" : "var(--paper-2)",
                    color: active ? "var(--paper)" : "var(--ink-3)",
                    border: "1px solid " + (active ? "var(--ink-1)" : "var(--line)"),
                    display: "flex", alignItems: "center", justifyContent: "center",
                    fontFamily: "var(--font-mono)", fontSize: 12,
                  }}>{String.fromCharCode(65 + i)}</span>
                  {useHtml
                    ? <span style={{ fontFamily: "var(--font-serif)" }} dangerouslySetInnerHTML={{ __html: opt }} />
                    : <span style={{ fontFamily: "var(--font-serif)" }}>{opt}</span>
                  }
                </button>
              );
            })}
          </div>

          <div style={{ display: "flex", justifyContent: "space-between", marginTop: 40, paddingTop: 20, borderTop: "1px solid var(--line)" }}>
            <button className="btn btn-ghost" disabled={idx === 0} onClick={() => setIdx(i => Math.max(0, i - 1))} style={{ opacity: idx === 0 ? 0.4 : 1 }}>
              ← {t("test_prev")}
            </button>
            {idx < questions.length - 1
              ? <button className="btn btn-primary" onClick={() => setIdx(i => i + 1)}>{t("test_next")} →</button>
              : <button className="btn btn-primary" onClick={() => onFinish(answers, flagged)}>
                  {isSample ? (lang === "ko" ? "샘플 끝내기" : "Finish sample") : t("test_submit")}
                </button>
            }
          </div>
        </div>

        {/* Navigator sidebar */}
        <aside style={{
          borderLeft: "1px solid var(--line)", background: "var(--paper-2)",
          padding: "32px 24px",
        }}>
          <div className="mono" style={{ fontSize: 11, color: "var(--ink-3)", letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 14 }}>
            {lang === "ko" ? "문제 이동" : "Navigator"}
          </div>
          <div style={{
            display: "grid", gridTemplateColumns: "repeat(5, 1fr)", gap: 6,
          }}>
            {questions.map((_, i) => {
              const answered = answers[i] !== null;
              const isFlag = flagged.has(i);
              const current = i === idx;
              const bg = current
                ? "var(--ink-1)"
                : answered ? "var(--indigo-tint)" : "white";
              const bd = current
                ? "var(--ink-1)"
                : answered ? "var(--indigo)" : "var(--line-2)";
              const fg = current
                ? "var(--paper)"
                : answered ? "var(--indigo)" : "var(--ink-4)";
              return (
                <button key={i} onClick={() => setIdx(i)} style={{
                  aspectRatio: "1 / 1", borderRadius: 6,
                  border: "1.5px solid " + bd,
                  background: bg,
                  color: fg,
                  fontFamily: "var(--font-mono)", fontSize: 12, fontWeight: answered ? 500 : 400,
                  cursor: "pointer", position: "relative",
                }}>
                  {answered && !current && (
                    <svg width="9" height="9" viewBox="0 0 10 10" style={{ position: "absolute", bottom: 3, right: 3 }}>
                      <path d="M1.5 5.5L4 8L8.5 2.5" fill="none" stroke="var(--indigo)" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
                    </svg>
                  )}
                  {i + 1}
                  {isFlag && (
                    <span style={{
                      position: "absolute", top: -4, right: -4,
                      width: 8, height: 8, borderRadius: "50%", background: "var(--amber)", border: "1.5px solid white"
                    }} />
                  )}
                </button>
              );
            })}
          </div>
          <div style={{ marginTop: 24, display: "grid", gap: 8, fontSize: 12, color: "var(--ink-3)" }}>
            <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
              <div style={{ width: 12, height: 12, borderRadius: 3, background: "var(--ink-1)" }} />
              {lang === "ko" ? "현재 문제" : "Current"}
            </div>
            <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
              <div style={{ width: 12, height: 12, borderRadius: 3, background: "var(--indigo-tint)", border: "1.5px solid var(--indigo)", position: "relative" }}>
                <svg width="8" height="8" viewBox="0 0 10 10" style={{ position: "absolute", top: 1, left: 1 }}>
                  <path d="M1.5 5.5L4 8L8.5 2.5" fill="none" stroke="var(--indigo)" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
              </div>
              {lang === "ko" ? "답 선택함" : "Answered"}
            </div>
            <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
              <div style={{ width: 12, height: 12, borderRadius: 3, background: "white", border: "1.5px solid var(--line-2)" }} />
              {lang === "ko" ? "미완료" : "Unanswered"}
            </div>
            <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
              <div style={{ width: 8, height: 8, borderRadius: "50%", background: "var(--amber)" }} />
              {lang === "ko" ? "표시됨" : "Flagged"}
            </div>
          </div>
          {isSample && (
            <div style={{
              marginTop: 24, padding: 14, borderRadius: 8,
              background: "var(--amber-tint)", fontSize: 12, color: "var(--ink-2)", lineHeight: 1.55,
              border: "1px solid color-mix(in oklab, var(--amber) 25%, transparent)"
            }}>
              {lang === "ko" ? "샘플은 결과/해설 보려면 가입이 필요합니다. 무료예요." : "Sample: register (free) to unlock worked solutions at the end."}
            </div>
          )}
        </aside>
      </div>
    </div>
  );
}

// ---------- PDF upload / scan flow ----------
function ScanUpload({ paperName, onDone, onCancel, printUrl, durationMin = 50, previewQuestions = null }) {
  const { t, lang } = useT();
  const [files, setFiles] = useState_T([]);
  const printedKey = `epl_printed_${paperName}`;
  const alreadyPrinted = (() => {
    try { return localStorage.getItem(printedKey) === "1"; } catch { return false; }
  })();
  const [phase, setPhase] = useState_T(alreadyPrinted ? "idle" : "print"); // print | idle | marking
  const [step, setStep] = useState_T(0);
  const inputRef = useRef_T(null);

  const markPrinted = () => {
    try { localStorage.setItem(printedKey, "1"); } catch {}
    setPhase("idle");
  };

  useEffect_T(() => {
    if (phase !== "marking") return;
    const steps = [1200, 1400, 1200];
    let i = 0;
    const advance = () => {
      if (i >= steps.length) { onDone(); return; }
      setStep(i);
      setTimeout(() => { i++; advance(); }, steps[i]);
    };
    advance();
  }, [phase]);

  const addFiles = (fileList) => {
    const arr = Array.from(fileList).slice(0, 6).map((f, i) => ({
      name: f.name || `sheet-${i + 1}.jpg`,
      size: f.size ? `${Math.round(f.size / 1024)} KB` : "~340 KB"
    }));
    setFiles(f => [...f, ...arr]);
  };

  if (phase === "print") {
    return (
      <div style={{ minHeight: "100vh", padding: "40px 28px", background: "var(--paper)" }}>
        <div style={{ maxWidth: 960, margin: "0 auto" }}>
          <button className="btn btn-ghost" onClick={onCancel} style={{ marginBottom: 20, padding: "6px 12px", fontSize: 13 }}>
            ← {lang === "ko" ? "돌아가기" : "Back"}
          </button>
          <div className="mono" style={{ fontSize: 11, color: "var(--ink-3)", letterSpacing: "0.08em", textTransform: "uppercase" }}>
            {paperName} · {lang === "ko" ? "1단계 / 2" : "Step 1 of 2"}
          </div>
          <h1 style={{ fontSize: 36, marginTop: 8, letterSpacing: "-0.02em" }}>
            {lang === "ko" ? "시험지를 출력하세요" : "Print the paper"}
          </h1>
          <p style={{ color: "var(--ink-2)", fontSize: 15, marginTop: 10, maxWidth: 640 }}>
            {lang === "ko"
              ? "시험지와 답안지를 출력해 주세요. 아이가 답안지를 작성한 뒤, 그 답안지를 스캔해서 올리면 채점해 드립니다."
              : "Print the question paper and the answer sheet. Your child fills it in on paper — we mark the scanned answer sheet."}
          </p>

          <div style={{
            marginTop: 28, display: "grid", gridTemplateColumns: "1fr 380px", gap: 28, alignItems: "start",
          }}>
            {/* PDF preview */}
            <div style={{
              background: "white", border: "1px solid var(--line)", borderRadius: 12,
              padding: 28, boxShadow: "var(--shadow-sm)", position: "relative",
              minHeight: 520,
            }}>
              <div className="mono" style={{ position: "absolute", top: 14, right: 18, fontSize: 10, color: "var(--ink-4)", letterSpacing: "0.08em" }}>
                PREVIEW · PDF
              </div>
              <div style={{ borderBottom: "1px solid var(--line)", paddingBottom: 18, marginBottom: 18 }}>
                <div className="mono" style={{ fontSize: 10, color: "var(--ink-3)", letterSpacing: "0.1em", textTransform: "uppercase" }}>Daddy's Lab 11+</div>
                <div style={{ fontFamily: "var(--font-serif)", fontSize: 24, marginTop: 6 }}>{paperName}</div>
                <div style={{ display: "flex", gap: 24, marginTop: 10, fontSize: 12, color: "var(--ink-3)" }}>
                  <span>{lang === "ko" ? "50문제" : "50 questions"}</span>
                  <span>{lang === "ko" ? `${durationMin}분` : `${durationMin} minutes`}</span>
                  <span className="mono">v2.1</span>
                </div>
              </div>
              <div style={{ display: "grid", gap: 12 }}>
                {previewQuestions ? previewQuestions.map((q, n) => (
                  <div key={n} style={{ display: "grid", gridTemplateColumns: "28px 1fr", gap: 8, alignItems: "start", borderTop: n > 0 ? "1px solid var(--line)" : "none", paddingTop: n > 0 ? 10 : 0 }}>
                    <div className="mono tabular" style={{ fontSize: 11, color: "var(--ink-3)", paddingTop: 2 }}>{n + 1}.</div>
                    <div>
                      {q.en && (
                        <div style={{ fontSize: 11, color: "var(--ink-2)", lineHeight: 1.5, marginBottom: 3 }}
                             dangerouslySetInnerHTML={{ __html: q.en }} />
                      )}
                      {q._questionHtml && (
                        <div style={{ fontSize: 11, color: "var(--ink-1)", fontWeight: 500, lineHeight: 1.5, marginBottom: 4 }}
                             dangerouslySetInnerHTML={{ __html: q._questionHtml }} />
                      )}
                      {q._diagramHtml && (
                        <div style={{ fontSize: 10, color: "var(--ink-4)", fontStyle: "italic", marginBottom: 4 }}>
                          {lang === "ko" ? "[도형 포함]" : "[diagram]"}
                        </div>
                      )}
                      <div style={{ display: "flex", gap: 6, marginTop: 4 }}>
                        {["A","B","C","D","E"].map(x => (
                          <div key={x} style={{
                            width: 18, height: 18, borderRadius: "50%", border: "1px solid var(--line-2)",
                            display: "flex", alignItems: "center", justifyContent: "center",
                            fontFamily: "var(--font-mono)", fontSize: 9, color: "var(--ink-3)",
                          }}>{x}</div>
                        ))}
                      </div>
                    </div>
                  </div>
                )) : [1,2,3,4,5].map(n => (
                  <div key={n} style={{ display: "grid", gridTemplateColumns: "28px 1fr", gap: 10, alignItems: "start" }}>
                    <div className="mono tabular" style={{ fontSize: 12, color: "var(--ink-3)", paddingTop: 2 }}>{n}.</div>
                    <div>
                      <div style={{ height: 10, background: "var(--paper-2)", borderRadius: 2, width: `${60 + (n * 7) % 35}%` }} />
                      <div style={{ height: 10, background: "var(--paper-2)", borderRadius: 2, width: `${40 + (n * 11) % 40}%`, marginTop: 6 }} />
                      <div style={{ display: "flex", gap: 8, marginTop: 8 }}>
                        {["A","B","C","D"].map(x => (
                          <div key={x} style={{
                            width: 22, height: 22, borderRadius: "50%", border: "1px solid var(--line-2)",
                            display: "flex", alignItems: "center", justifyContent: "center",
                            fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--ink-3)",
                          }}>{x}</div>
                        ))}
                      </div>
                    </div>
                  </div>
                ))}
                <div style={{ fontSize: 12, color: "var(--ink-4)", textAlign: "center", marginTop: 8, fontStyle: "italic" }}>
                  {lang === "ko" ? "… 45문제 더" : "… 45 more questions"}
                </div>
              </div>
            </div>

            {/* Action card */}
            <div style={{
              background: "var(--ink-1)", color: "var(--paper)", borderRadius: 14, padding: 24,
              position: "sticky", top: 20,
            }}>
              <div className="mono" style={{ fontSize: 11, letterSpacing: "0.08em", opacity: 0.6, textTransform: "uppercase" }}>
                {lang === "ko" ? "포함 내용" : "Included"}
              </div>
              <div style={{ marginTop: 12, display: "grid", gap: 10 }}>
                {[
                  { en: "Question paper (12 pp.)", ko: "시험지 (12쪽)" },
                  { en: "Answer sheet (1 p.)", ko: "답안지 (1쪽)" },
                  { en: "Parent instructions", ko: "학부모 안내문" },
                ].map((it, i) => (
                  <div key={i} style={{ display: "flex", gap: 10, alignItems: "center", fontSize: 13 }}>
                    <svg width="14" height="14" viewBox="0 0 16 16" fill="none">
                      <path d="M3 8l3.5 3.5L13 5" stroke="var(--emerald)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                    </svg>
                    <span style={{ opacity: 0.9 }}>{lang === "ko" ? it.ko : it.en}</span>
                  </div>
                ))}
              </div>
              <button onClick={() => {
                if (printUrl) { window.open(printUrl, "_blank"); markPrinted(); }
                else { window.print(); markPrinted(); }
              }} className="btn" style={{
                width: "100%", marginTop: 20, padding: "14px 16px",
                background: "var(--paper)", color: "var(--ink-1)", fontSize: 14, fontWeight: 500,
                justifyContent: "center",
              }}>
                <svg width="16" height="16" viewBox="0 0 20 20" fill="none">
                  <path d="M6 4V2h8v2M4 8h12v6h-2v4H6v-4H4V8zM6 14h8M8 17h4" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
                {lang === "ko" ? "PDF 출력하기" : "Print PDF"}
              </button>
              <button onClick={markPrinted} style={{
                width: "100%", marginTop: 10, padding: "10px 14px",
                background: "transparent", color: "var(--paper)",
                border: "1px solid color-mix(in oklab, white 20%, transparent)",
                borderRadius: 8, fontSize: 13, cursor: "pointer", fontFamily: "inherit",
              }}>
                {lang === "ko" ? "이미 출력했어요 →" : "I've already printed it →"}
              </button>
              <div style={{ marginTop: 16, fontSize: 12, opacity: 0.65, lineHeight: 1.55 }}>
                {lang === "ko"
                  ? "출력 후 스캔 화면으로 넘어갑니다. 다음번에 다시 열어도 스캔 화면부터 시작해요."
                  : "After printing you'll go to the scan step. Next time you'll jump straight there."}
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }

  if (phase === "marking") {
    const steps = [t("scan_step_1"), t("scan_step_2"), t("scan_step_3")];
    return (
      <div style={{ minHeight: "100vh", display: "flex", alignItems: "center", justifyContent: "center", padding: 40 }}>
        <div style={{ maxWidth: 520, width: "100%", textAlign: "center" }}>
          <div style={{
            width: 72, height: 72, borderRadius: 18,
            background: "var(--indigo-tint)", display: "inline-flex",
            alignItems: "center", justifyContent: "center", marginBottom: 18
          }}>
            <svg width="32" height="32" viewBox="0 0 40 40" fill="none">
              <rect x="6" y="8" width="28" height="24" rx="2" stroke="var(--indigo)" strokeWidth="1.5" />
              <circle cx="20" cy="20" r="5" stroke="var(--indigo)" strokeWidth="1.5" />
              <circle cx="20" cy="20" r="1.5" fill="var(--indigo)" />
            </svg>
          </div>
          <h2 style={{ fontSize: 28, letterSpacing: "-0.01em" }}>{t("scan_marking")}</h2>
          <div style={{ marginTop: 32, display: "grid", gap: 12, textAlign: "left" }}>
            {steps.map((s, i) => (
              <div key={i} style={{
                display: "flex", alignItems: "center", gap: 12,
                padding: "14px 16px", borderRadius: 10,
                background: i === step ? "var(--indigo-tint)" : "var(--paper-2)",
                border: "1px solid " + (i === step ? "color-mix(in oklab, var(--indigo) 25%, transparent)" : "var(--line)"),
                opacity: i > step ? 0.5 : 1,
              }}>
                <div style={{
                  width: 22, height: 22, borderRadius: "50%",
                  background: i < step ? "var(--emerald)" : i === step ? "var(--indigo)" : "var(--paper-3)",
                  color: i < step || i === step ? "white" : "var(--ink-3)",
                  display: "flex", alignItems: "center", justifyContent: "center",
                  fontFamily: "var(--font-mono)", fontSize: 11,
                }}>
                  {i < step ? "✓" : i + 1}
                </div>
                <div style={{ flex: 1, fontSize: 14 }}>{s}</div>
                {i === step && (
                  <div style={{
                    width: 14, height: 14, borderRadius: "50%",
                    border: "2px solid var(--indigo)", borderTopColor: "transparent",
                    animation: "spin 0.8s linear infinite"
                  }} />
                )}
              </div>
            ))}
          </div>
          <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>
        </div>
      </div>
    );
  }

  return (
    <div style={{ minHeight: "100vh", padding: "40px 28px" }}>
      <div style={{ maxWidth: 720, margin: "0 auto" }}>
        <button className="btn btn-ghost" onClick={onCancel} style={{ marginBottom: 20, padding: "6px 12px", fontSize: 13 }}>
          ← {lang === "ko" ? "돌아가기" : "Back"}
        </button>
        <div className="mono" style={{ fontSize: 11, color: "var(--ink-3)", letterSpacing: "0.08em", textTransform: "uppercase" }}>
          {paperName} · {lang === "ko" ? "2단계 / 2" : "Step 2 of 2"}
        </div>
        <h1 style={{ fontSize: 36, marginTop: 8, letterSpacing: "-0.02em" }}>{t("scan_title")}</h1>
        <p style={{ color: "var(--ink-2)", fontSize: 15, marginTop: 10 }}>{t("scan_sub")}</p>

        {alreadyPrinted && (
          <button onClick={() => setPhase("print")} style={{
            marginTop: 10, background: "transparent", border: "none",
            color: "var(--indigo)", fontSize: 13, cursor: "pointer", padding: 0,
            fontFamily: "inherit", textDecoration: "underline",
          }}>
            {lang === "ko" ? "PDF 다시 출력하기" : "Re-print the PDF"}
          </button>
        )}

        {/* Disclaimer */}
        <div style={{
          marginTop: 18, padding: 16, borderRadius: 10,
          background: "var(--amber-tint)", border: "1px solid color-mix(in oklab, var(--amber) 25%, transparent)",
          display: "flex", gap: 12, fontSize: 13, color: "var(--ink-2)", lineHeight: 1.55,
        }}>
          <svg width="18" height="18" viewBox="0 0 20 20" fill="none" style={{ flexShrink: 0, marginTop: 1 }}>
            <path d="M10 2L2 17h16L10 2z" stroke="var(--amber)" strokeWidth="1.5" strokeLinejoin="round" fill="color-mix(in oklab, var(--amber) 15%, transparent)" />
            <path d="M10 8v4M10 14.5v.01" stroke="var(--amber)" strokeWidth="1.5" strokeLinecap="round" />
          </svg>
          <div>{t("scan_disclaimer")}</div>
        </div>

        {/* Dropzone */}
        <div
          onClick={() => inputRef.current?.click()}
          onDragOver={(e) => e.preventDefault()}
          onDrop={(e) => { e.preventDefault(); addFiles(e.dataTransfer.files); }}
          style={{
            marginTop: 20, padding: "56px 32px",
            border: "2px dashed var(--line-2)", borderRadius: 14,
            background: "var(--paper-2)", textAlign: "center", cursor: "pointer",
            transition: "all .15s",
          }}>
          <input ref={inputRef} type="file" accept="image/*,application/pdf" multiple style={{ display: "none" }}
            onChange={(e) => addFiles(e.target.files)} />
          <svg width="40" height="40" viewBox="0 0 40 40" fill="none" style={{ margin: "0 auto 12px" }}>
            <path d="M20 6v22M12 14l8-8 8 8M6 30v4h28v-4" stroke="var(--ink-2)" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
          </svg>
          <div style={{ fontSize: 15, color: "var(--ink-2)" }}>{t("scan_drop")}</div>
          <div className="mono" style={{ fontSize: 11, color: "var(--ink-4)", marginTop: 6, letterSpacing: "0.04em" }}>
            JPG · PNG · PDF · {lang === "ko" ? "최대 6장" : "up to 6 images"}
          </div>
        </div>

        {files.length > 0 && (
          <div style={{ marginTop: 18, display: "grid", gap: 8 }}>
            {files.map((f, i) => (
              <div key={i} style={{
                display: "flex", alignItems: "center", gap: 12,
                padding: "12px 16px", borderRadius: 10,
                background: "white", border: "1px solid var(--line)",
              }}>
                <div style={{
                  width: 40, height: 52, borderRadius: 4,
                  background: "var(--indigo-tint)", border: "1px solid color-mix(in oklab, var(--indigo) 20%, transparent)",
                  display: "flex", alignItems: "center", justifyContent: "center",
                  fontFamily: "var(--font-mono)", fontSize: 9, color: "var(--indigo)",
                }}>PAGE {i + 1}</div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 14, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{f.name}</div>
                  <div className="mono" style={{ fontSize: 11, color: "var(--ink-4)" }}>{f.size}</div>
                </div>
                <button onClick={() => setFiles(fs => fs.filter((_, j) => j !== i))}
                  style={{ border: "none", background: "transparent", color: "var(--ink-3)", cursor: "pointer", fontSize: 18 }}>×</button>
              </div>
            ))}
          </div>
        )}

        <div style={{ display: "flex", justifyContent: "flex-end", gap: 10, marginTop: 28 }}>
          <button className="btn btn-ghost" onClick={onCancel}>{lang === "ko" ? "취소" : "Cancel"}</button>
          <button className="btn btn-primary" disabled={files.length === 0}
            style={{ opacity: files.length === 0 ? 0.4 : 1 }}
            onClick={() => setPhase("marking")}>
            {lang === "ko" ? "채점 시작" : "Start marking"}
            <svg width="14" height="14" viewBox="0 0 20 20" fill="none"><path d="M5 10h10m0 0l-4-4m4 4l-4 4" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" /></svg>
          </button>
        </div>
      </div>
    </div>
  );
}

// ---------- Sutton → design shape adapter ----------
// Transforms window.SuttonEngine output (from sutton_core.js) into the shape
// TestUI, ResultsView and QuestionReview expect: { id, topicId, en, ko, optionsLabeled, correct, solutionEn, solutionKo }.
// Marks each question with `_html: true` so renderers pipe content through dangerouslySetInnerHTML.
function buildSuttonQuestions(count) {
  const engine = window.SuttonEngine;
  if (!engine) return PLACEHOLDER_QUESTIONS.slice(0, count || PLACEHOLDER_QUESTIONS.length);
  const all = engine.generateAll();
  const slice = count ? all.slice(0, count) : all;
  return slice.map((s) => {
    const idx = s.choices ? s.choices.findIndex(c => c.value === s.answerKey) : 0;
    const correct = idx < 0 ? 0 : idx;
    const options = s.choices ? s.choices.map(c => c.html) : ["—", "—", "—", "—", "—"];
    const solution = `Answer: ${s.answerHtml}`;
    const solutionKo = `정답: ${s.answerHtml}`;
    return {
      id: s.id,
      topicId: s.topicId,
      _html: true,
      _diagramHtml: s.diagramHtml,
      _questionHtml: s.questionHtml,
      en: s.promptHtml,
      ko: s.promptHtml,
      optionsLabeled: options,
      correct,
      solutionEn: solution,
      solutionKo,
    };
  });
}

Object.assign(window, { PLACEHOLDER_QUESTIONS, ModeChooser, TestUI, ScanUpload, buildSuttonQuestions });
