import { useEffect, useState, useRef } from "react";
import { Navigate, useNavigate } from "react-router-dom";
import { BlockMath, InlineMath } from "react-katex";
import {
  Binary,
  Calculator,
  Check,
  Loader2,
  LogOut,
  Unplug,
  Play,
  ChevronLeft,
  Menu,
  X,
  Bookmark,
  BookMarked,
  BookOpen,
  ZoomIn,
  ZoomOut,
  Eye,
  EyeOff,
  Highlighter,
} from "lucide-react";

import { api } from "../../../utils/api";
import { useAuthStore } from "../../../stores/authStore";
import type { Question } from "../../../types/sheet";
import { useSatExam } from "../../../stores/useSatExam";
import { useSatTimer } from "../../../hooks/useSatTimer";
import type {
  SessionModuleQuestions,
  SubmitAnswer,
} from "../../../types/session";
import { useAuthToken } from "../../../hooks/useAuthToken";
import { renderQuestionText } from "../../../components/RenderQuestionText";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "../../../components/ui/dropdown-menu";
import {
  Dialog,
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "../../../components/ui/dialog";
import { Drawer } from "vaul";
import { useExamNavigationGuard } from "../../../hooks/useExamNavGuard";
import { useExamConfigStore } from "../../../stores/useExamConfigStore";
import { useResults } from "../../../stores/useResults";
import { GraphCalculatorModal } from "../../../components/Calculator";

// ─── Shared Style Constants ───────────────────────────────────────────────────
const COLORS = {
  bg: "#fffbf4",
  primary: "#a855f7",
  primaryDark: "#7c3aed",
  accent: "#f97316",
  accentDark: "#c2560e",
  text: "#1e1b4b",
  textMuted: "#6b7280",
  textLight: "#9ca3af",
  border: "#f3f4f6",
  borderPurple: "#c4b5fd",
  success: "#22c55e",
  error: "#ef4444",
  blob1: "#fde68a",
  blob2: "#a5f3c0",
  blob3: "#fbcfe8",
  blob4: "#bfdbfe",
};

const DOTS = [
  { size: 12, color: "#f97316", top: "8%", left: "6%", delay: "0s" },
  { size: 8, color: "#a855f7", top: "22%", left: "2%", delay: "1s" },
  { size: 10, color: "#22c55e", top: "55%", left: "4%", delay: "0.5s" },
  { size: 14, color: "#3b82f6", top: "10%", right: "5%", delay: "1.5s" },
  { size: 8, color: "#f43f5e", top: "40%", right: "3%", delay: "0.8s" },
  { size: 10, color: "#eab308", top: "70%", right: "7%", delay: "0.3s" },
];

// ─── Global Styles ────────────────────────────────────────────────────────────
const GLOBAL_STYLES = `
  @import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800;900&family=Nunito+Sans:wght@400;600;700&display=swap');

  :root { --content-max: 1100px; }

  .test-screen {
    min-height: 100vh;
    background: ${COLORS.bg};
    font-family: 'Nunito', sans-serif;
    position: relative;
    overflow-x: hidden;
  }

  .t-blob { position:fixed;pointer-events:none;z-index:0;filter:blur(48px);opacity:0.35; }
  .t-blob-1 { width:240px;height:240px;background:${COLORS.blob1};top:-80px;left:-80px;border-radius:60% 40% 70% 30%/50% 60% 40% 50%;animation:tWobble1 14s ease-in-out infinite; }
  .t-blob-2 { width:190px;height:190px;background:${COLORS.blob2};bottom:-50px;left:6%;border-radius:40% 60% 30% 70%/60% 40% 60% 40%;animation:tWobble2 16s ease-in-out infinite; }
  .t-blob-3 { width:210px;height:210px;background:${COLORS.blob3};top:15%;right:-60px;border-radius:70% 30% 50% 50%/40% 60% 40% 60%;animation:tWobble1 18s ease-in-out infinite reverse; }
  .t-blob-4 { width:150px;height:150px;background:${COLORS.blob4};bottom:12%;right:2%;border-radius:50% 50% 30% 70%/60% 40% 60% 40%;animation:tWobble2 12s ease-in-out infinite; }

  @keyframes tWobble1 {
    0%,100%{border-radius:60% 40% 70% 30%/50% 60% 40% 50%;transform:translate(0,0) rotate(0deg);}
    50%{border-radius:40% 60% 30% 70%/60% 40% 60% 40%;transform:translate(12px,16px) rotate(8deg);}
  }
  @keyframes tWobble2 {
    0%,100%{border-radius:40% 60% 30% 70%/60% 40% 60% 40%;transform:translate(0,0) rotate(0deg);}
    50%{border-radius:60% 40% 70% 30%/40% 60% 40% 60%;transform:translate(-10px,12px) rotate(-6deg);}
  }

  .t-dot { position:fixed;border-radius:50%;pointer-events:none;z-index:0;opacity:0.3;animation:tFloat 6s ease-in-out infinite; }
  @keyframes tFloat { 0%,100%{transform:translateY(0) rotate(0deg);}50%{transform:translateY(-14px) rotate(180deg);} }

  @keyframes tPopIn {
    from{opacity:0;transform:scale(0.92) translateY(10px);}
    to{opacity:1;transform:scale(1) translateY(0);}
  }
  .t-anim   { animation:tPopIn 0.4s cubic-bezier(0.34,1.56,0.64,1) both; }
  .t-anim-1 { animation-delay:0.05s; }
  .t-anim-2 { animation-delay:0.1s; }
  .t-anim-3 { animation-delay:0.15s; }

  /* 3D buttons */
  .t-btn-3d { font-family:'Nunito',sans-serif;font-weight:800;border:none;border-radius:100px;cursor:pointer;transition:transform 0.1s ease,box-shadow 0.1s ease; }
  .t-btn-3d:hover  { transform:translateY(-2px); }
  .t-btn-3d:active { transform:translateY(2px); }

  .t-btn-primary { background:${COLORS.primary};color:white;box-shadow:0 4px 0 ${COLORS.primaryDark},0 6px 16px rgba(168,85,247,0.3); }
  .t-btn-primary:hover  { box-shadow:0 6px 0 ${COLORS.primaryDark},0 10px 20px rgba(168,85,247,0.35); }
  .t-btn-primary:active { box-shadow:0 2px 0 ${COLORS.primaryDark},0 3px 8px rgba(168,85,247,0.2); }

  .t-btn-accent { background:${COLORS.accent};color:white;box-shadow:0 4px 0 ${COLORS.accentDark},0 6px 16px rgba(249,115,22,0.3); }
  .t-btn-accent:hover  { box-shadow:0 6px 0 ${COLORS.accentDark},0 10px 20px rgba(249,115,22,0.35); }
  .t-btn-accent:active { box-shadow:0 2px 0 ${COLORS.accentDark},0 3px 8px rgba(249,115,22,0.2); }

  .t-btn-outline { background:white;color:${COLORS.text};border:2.5px solid ${COLORS.border};box-shadow:0 3px 10px rgba(0,0,0,0.06); }
  .t-btn-outline:hover { border-color:${COLORS.borderPurple};box-shadow:0 6px 14px rgba(0,0,0,0.08); }

  /* Bookmark button */
  .t-bookmark-btn {
    display:flex;align-items:center;justify-content:center;
    width:44px;height:44px;border-radius:50%;border:2.5px solid ${COLORS.border};
    background:white;cursor:pointer;
    box-shadow:0 3px 10px rgba(0,0,0,0.06);
    transition:all 0.15s cubic-bezier(0.34,1.56,0.64,1);
    flex-shrink:0;
  }
  .t-bookmark-btn:hover { border-color:#fde68a;background:#fffbeb;transform:scale(1.08); }
  .t-bookmark-btn:active { transform:scale(0.92); }
  .t-bookmark-btn.marked {
    background:linear-gradient(135deg,#fbbf24,#f59e0b);
    border-color:#f59e0b;
    box-shadow:0 4px 0 #d97706,0 6px 14px rgba(251,191,36,0.35);
  }
  .t-bookmark-btn.marked:hover { box-shadow:0 6px 0 #d97706,0 8px 18px rgba(251,191,36,0.4); }

  /* Cards */
  .t-card { background:white;border:2.5px solid ${COLORS.border};border-radius:22px;box-shadow:0 4px 14px rgba(0,0,0,0.05); }
  .t-card-purple { border-color:${COLORS.borderPurple};box-shadow:0 4px 16px rgba(167,139,250,0.12); }

  .t-section-title { font-size:1.2rem;font-weight:900;color:${COLORS.text};letter-spacing:-0.01em; }
  .t-timer { font-size:2.5rem;font-weight:900;color:${COLORS.text};letter-spacing:-0.03em;line-height:1; }
  .t-q-badge { background:linear-gradient(135deg,${COLORS.primary},${COLORS.primaryDark});color:white;font-weight:800;font-size:0.75rem;padding:0.4rem 0.9rem;border-radius:100px; }

  /* Mark-for-review badge on q-badge */
  .t-q-badge.reviewing { background:linear-gradient(135deg,#fbbf24,#f59e0b); }

  /* Options */
  .t-option {
    width:100%;text-align:start;font-family:'Nunito',sans-serif;font-weight:700;font-size:1rem;
    padding:1rem 1.25rem;background:white;border:2.5px solid ${COLORS.border};border-radius:18px;
    cursor:pointer;transition:all 0.15s ease;display:flex;align-items:center;gap:0.75rem;
  }
  .t-option:hover:not(:disabled) { border-color:${COLORS.borderPurple};transform:translateY(-1px);box-shadow:0 4px 12px rgba(0,0,0,0.06); }
  .t-option.selected  { background:linear-gradient(135deg,${COLORS.primary},${COLORS.primaryDark});border-color:${COLORS.primaryDark};color:white; }
  .t-option.correct   { background:linear-gradient(135deg,#22c55e,#16a34a);border-color:#16a34a;color:white; }
  .t-option.incorrect { background:linear-gradient(135deg,#ef4444,#dc2626);border-color:#dc2626;color:white; }
  .t-option.eliminated { opacity:0.5;text-decoration:line-through; }

  .t-option-letter { width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:50%;font-weight:800;font-size:0.85rem;flex-shrink:0; }
  .t-option:not(.selected) .t-option-letter { background:${COLORS.primary};color:white; }
  .t-option.selected .t-option-letter { background:white;color:${COLORS.primary}; }

  .t-eliminate-btn { width:32px;height:32px;border-radius:50%;border:2.5px solid ${COLORS.border};background:white;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all 0.15s ease;flex-shrink:0; }
  .t-eliminate-btn:hover { border-color:#ef4444;background:#fef2f2; }
  .t-eliminate-btn.active { background:#ef4444;border-color:#ef4444;color:white; }

  .t-textarea { width:100%;min-height:120px;padding:1rem 1.25rem;background:white;border:2.5px solid ${COLORS.border};border-radius:18px;font-family:'Nunito',sans-serif;font-size:1rem;font-weight:600;color:${COLORS.text};resize:vertical;transition:border-color 0.2s ease,box-shadow 0.2s ease; }
  .t-textarea:focus { outline:none;border-color:${COLORS.borderPurple};box-shadow:0 4px 16px rgba(167,139,250,0.15); }
  .t-textarea::placeholder { color:${COLORS.textLight}; }

  /* Retry banner */
  .t-retry-banner { background:linear-gradient(90deg,${COLORS.accent},#ea580c);position:fixed;width:100%;color:white;padding:0.75rem 1rem;font-weight:700;font-size:0.9rem;display:flex;align-items:center;justify-content:center;gap:0.5rem; }

  /* XP badge */
  .t-xp-badge { position:absolute;top:-8px;right:-8px;background:linear-gradient(135deg,#fbbf24,#f59e0b);color:white;font-size:0.7rem;font-weight:800;padding:0.25rem 0.6rem;border-radius:100px;box-shadow:0 2px 8px rgba(251,191,36,0.4);animation:tBounce 0.5s ease; }
  @keyframes tBounce { 0%,100%{transform:scale(1);}50%{transform:scale(1.2);} }

  /* Vaul drawer */
  [data-vaul-drawer] { background:white !important;border-top:2.5px solid ${COLORS.border} !important;border-radius:24px 24px 0 0 !important; }
  [data-vaul-drawer-handle] { background:${COLORS.border} !important;width:48px !important;height:5px !important;border-radius:3px !important; }

  /* Navigator grid */
  .t-nav-grid { display:grid;grid-template-columns:repeat(5,1fr);gap:0.5rem; }
  .t-nav-item { aspect-ratio:1;display:flex;align-items:center;justify-content:center;border-radius:12px;font-weight:800;font-size:0.9rem;border:2.5px solid ${COLORS.border};background:white;cursor:pointer;transition:all 0.15s ease;position:relative; }
  .t-nav-item:hover { border-color:${COLORS.borderPurple};transform:scale(1.05); }
  .t-nav-item.current  { background:linear-gradient(135deg,${COLORS.primary},${COLORS.primaryDark});border-color:${COLORS.primaryDark};color:white; }
  .t-nav-item.answered { background:#dcfce7;border-color:#22c55e;color:#16a34a; }
  .t-nav-item.marked   { background:#fffbeb;border-color:#f59e0b;color:#d97706; }
  .t-nav-item.current.marked { background:linear-gradient(135deg,#fbbf24,#f59e0b);border-color:#d97706;color:white; }

  /* Bookmark dot indicator on nav item */
  .t-nav-bookmark-dot {
    position:absolute;top:-4px;right:-4px;
    width:10px;height:10px;border-radius:50%;
    background:#f59e0b;border:2px solid white;
  }

  /* Review warning dialog custom */
  .t-review-warning {
    background:linear-gradient(135deg,#fffbeb,white);
    border:2.5px solid #fde68a;
  }

  /* Reference sheet modal */
  .t-ref-modal-img {
    width:100%;border-radius:16px;
    border:2.5px solid ${COLORS.border};
    user-select:none;
    transition:transform 0.2s ease;
  }
  .t-ref-zoom-bar {
    display:flex;align-items:center;justify-content:center;gap:0.75rem;
    padding:0.65rem;background:#f9fafb;border-top:2px solid ${COLORS.border};
    flex-shrink:0;
  }
  .t-ref-zoom-btn {
    width:34px;height:34px;border-radius:50%;border:2.5px solid ${COLORS.border};
    background:white;cursor:pointer;display:flex;align-items:center;justify-content:center;
    font-weight:800;transition:all 0.15s ease;box-shadow:0 2px 6px rgba(0,0,0,0.05);
  }
  .t-ref-zoom-btn:hover { border-color:${COLORS.borderPurple};background:#fdf4ff; }
  .t-ref-zoom-label { font-family:'Nunito',sans-serif;font-size:0.75rem;font-weight:800;color:#9ca3af;min-width:36px;text-align:center; }

  /* Incorrect flash */
  @keyframes tFlashRed { 0%,100%{background:transparent;}50%{background:rgba(239,68,68,0.15);} }
  .t-flash-red { animation:tFlashRed 0.6s ease; }

  /* Highlighting */
  .t-highlight {
    background: rgba(251, 191, 36, 0.42);
    border-radius: 6px;
    padding: 0 2px;
    box-shadow: inset 0 -1px 0 rgba(217, 119, 6, 0.25);
  }

  /* Desktop / wide tweaks */
  @media (min-width: 900px) {
    .t-blob-1 { left: calc((100vw - var(--content-max)) / 2 - 120px); top: -120px; width: 300px; height: 300px; }
    .t-blob-2 { left: calc((100vw - var(--content-max)) / 2 + 20px); bottom: -80px; width: 220px; height: 220px; }
    .t-blob-3 { right: calc((100vw - var(--content-max)) / 2 - 40px); top: 10%; width: 260px; height: 260px; }
    .t-blob-4 { right: calc((100vw - var(--content-max)) / 2 + 10px); bottom: 6%; width: 180px; height: 180px; }

    /* Desktop split layout */
    .t-desktop-shell {
      max-width: var(--content-max);
      margin: 0 auto;
    }
    .t-split-layout {
      display: flex;
      align-items: stretch;
    }
    .t-split-left {
      display: flex;
      flex-direction: column;
      gap: 1.5rem;
    }
    .t-split-right {
      display: flex;
      flex-direction: column;
      gap: 1.5rem;
      min-width: 0;
    }
    .t-split-divider {
      position: relative;
      width: 10px;
      cursor: col-resize;
      flex-shrink: 0;
    }
    .t-split-divider-bar {
      position: absolute;
      top: 0;
      bottom: 0;
      left: 50%;
      width: 3px;
      transform: translateX(-50%);
      border-radius: 999px;
      background: #e5e7eb;
    }
    .t-split-divider-handle {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: 26px;
      height: 26px;
      border-radius: 999px;
      border: 2px solid #e5e7eb;
      background: white;
      box-shadow: 0 4px 12px rgba(15,23,42,0.12);
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .t-split-divider-dots {
      width: 3px;
      height: 14px;
      border-radius: 999px;
      background: linear-gradient(to bottom, #c4b5fd, #a855f7);
    }
    .t-split-divider:hover .t-split-divider-bar {
      background: #c4b5fd;
    }
    .t-split-divider:hover .t-split-divider-handle {
      border-color: #c4b5fd;
      box-shadow: 0 6px 18px rgba(129,140,248,0.3);
    }

    /* Directions button (desktop only) */
    .t-directions-btn {
      font-weight: 900;
      font-size: 0.78rem;
      padding: 0.35rem 0.9rem;
      border-radius: 999px;
      border: 2.5px solid ${COLORS.border};
      background: white;
      color: ${COLORS.text};
      box-shadow: 0 3px 10px rgba(0,0,0,0.06);
    }
    .t-directions-btn:hover {
      border-color: ${COLORS.borderPurple};
      background: #fdf4ff;
      box-shadow: 0 6px 14px rgba(0,0,0,0.08);
      transform: translateY(-1px);
    }
    .t-directions-btn.active {
      background: linear-gradient(135deg, ${COLORS.primary}, ${COLORS.primaryDark});
      border-color: ${COLORS.primaryDark};
      color: white;
      box-shadow: 0 4px 0 ${COLORS.primaryDark}, 0 8px 18px rgba(168,85,247,0.28);
    }
    .t-directions-btn.active:hover {
      box-shadow: 0 6px 0 ${COLORS.primaryDark}, 0 12px 22px rgba(168,85,247,0.32);
      transform: translateY(-1px);
    }
  }
`;

// ─── Confetti ─────────────────────────────────────────────────────────────────
interface ConfettiParticle {
  id: number;
  x: number;
  color: string;
  size: number;
  delay: number;
  duration: number;
  rotation: number;
}

type FeedbackState = {
  show: boolean;
  correct: boolean;
  xpGained?: number;
  selectedOptionId?: string;
} | null;
interface IncorrectEntry {
  questionId: string;
  originalIndex: number;
}

type HighlightRange = { start: number; end: number };
type HighlightsByField = Record<string, HighlightRange[]>;

const Confetti = ({ active }: { active: boolean }) => {
  const [particles, setParticles] = useState<ConfettiParticle[]>([]);
  useEffect(() => {
    if (!active) {
      setParticles([]);
      return;
    }
    const colors = [
      "#a855f7",
      "#ec4899",
      "#f59e0b",
      "#10b981",
      "#3b82f6",
      "#f97316",
      "#eab308",
    ];
    setParticles(
      Array.from({ length: 60 }, (_, i) => ({
        id: i,
        x: Math.random() * 100,
        color: colors[Math.floor(Math.random() * colors.length)],
        size: Math.random() * 8 + 4,
        delay: Math.random() * 0.5,
        duration: Math.random() * 1.5 + 1.5,
        rotation: Math.random() * 360,
      })),
    );
  }, [active]);
  if (!active || !particles.length) return null;
  return (
    <div className="fixed inset-0 pointer-events-none z-50 overflow-hidden">
      <style>{`@keyframes confetti-fall{0%{transform:translateY(-20px) rotate(0deg);opacity:1;}100%{transform:translateY(110vh) rotate(720deg);opacity:0;}}.confetti-piece{position:absolute;top:-20px;border-radius:2px;animation:confetti-fall linear forwards;}`}</style>
      {particles.map((p) => (
        <div
          key={p.id}
          className="confetti-piece"
          style={{
            left: `${p.x}%`,
            width: p.size,
            height: p.size * 0.6,
            backgroundColor: p.color,
            animationDuration: `${p.duration}s`,
            animationDelay: `${p.delay}s`,
            transform: `rotate(${p.rotation}deg)`,
          }}
        />
      ))}
    </div>
  );
};

const XPPopup = ({ xp, show }: { xp: number; show: boolean }) => {
  if (!show) return null;
  return (
    <div
      className="fixed top-1/2 left-1/2 z-50 pointer-events-none"
      style={{ transform: "translate(-50%,-60%)" }}
    >
      <style>{`@keyframes xp-popup{0%{opacity:0;transform:translateY(20px) scale(0.8);}20%{opacity:1;transform:translateY(0px) scale(1.1);}70%{opacity:1;transform:translateY(-10px) scale(1);}100%{opacity:0;transform:translateY(-40px) scale(0.9);}}.xp-popup-anim{animation:xp-popup 2s ease-out forwards;}`}</style>
      <div className="xp-popup-anim flex flex-col items-center gap-1">
        <div className="text-5xl font-black text-transparent bg-clip-text bg-linear-to-br from-yellow-300 via-amber-400 to-orange-500 drop-shadow-lg">
          +{xp} XP
        </div>
        <div className="text-black font-bold text-lg tracking-widest drop-shadow-md">
          🎉 CORRECT!
        </div>
      </div>
    </div>
  );
};

// ─── Reference Sheet Modal ────────────────────────────────────────────────────
// Placeholder image — swap the src for a real URL or imported asset when ready
const REFERENCE_SHEET_URL =
  "https://placehold.co/800x1000/fffbf4/1e1b4b?text=SAT+Reference+Sheet";

const ReferenceSheetModal = ({
  open,
  onClose,
}: {
  open: boolean;
  onClose: () => void;
}) => {
  const [zoom, setZoom] = useState(100);
  if (!open) return null;
  return (
    <div
      className="fixed inset-0 z-50 flex items-center justify-center p-4"
      style={{ background: "rgba(0,0,0,0.55)", backdropFilter: "blur(6px)" }}
      onClick={onClose}
    >
      <div
        className="t-card flex flex-col"
        style={{
          width: "100%",
          maxWidth: 580,
          maxHeight: "90vh",
          overflow: "hidden",
        }}
        onClick={(e) => e.stopPropagation()}
      >
        {/* Header */}
        <div
          style={{
            display: "flex",
            alignItems: "center",
            justifyContent: "space-between",
            padding: "1rem 1.25rem",
            borderBottom: "2px solid #f3f4f6",
            flexShrink: 0,
          }}
        >
          <div style={{ display: "flex", alignItems: "center", gap: "0.6rem" }}>
            <div
              style={{
                width: 34,
                height: 34,
                borderRadius: 10,
                background: "#fdf4ff",
                border: "2px solid #e9d5ff",
                display: "flex",
                alignItems: "center",
                justifyContent: "center",
              }}
            >
              <BookOpen size={16} color="#a855f7" />
            </div>
            <div>
              <p
                style={{
                  fontWeight: 900,
                  fontSize: "0.92rem",
                  color: "#1e1b4b",
                  lineHeight: 1.1,
                }}
              >
                Reference Sheet
              </p>
              <p
                style={{
                  fontFamily: "'Nunito Sans',sans-serif",
                  fontSize: "0.68rem",
                  fontWeight: 600,
                  color: "#9ca3af",
                }}
              >
                SAT Math formulas &amp; constants
              </p>
            </div>
          </div>
          <button
            onClick={onClose}
            style={{
              width: 30,
              height: 30,
              borderRadius: "50%",
              border: "2.5px solid #f3f4f6",
              background: "white",
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
              cursor: "pointer",
            }}
          >
            <X size={13} color="#9ca3af" />
          </button>
        </div>

        {/* Scrollable image area */}
        <div
          style={{
            flex: 1,
            overflowY: "auto",
            overflowX: "auto",
            padding: "1rem",
          }}
        >
          <img
            src={REFERENCE_SHEET_URL}
            alt="SAT Reference Sheet"
            className="t-ref-modal-img"
            style={{
              transform: `scale(${zoom / 100})`,
              transformOrigin: "top left",
              width: `${10000 / zoom}%`,
            }}
            draggable={false}
          />
        </div>

        {/* Zoom controls */}
        <div className="t-ref-zoom-bar">
          <button
            className="t-ref-zoom-btn"
            onClick={() => setZoom((z) => Math.max(50, z - 25))}
          >
            <ZoomOut size={15} color="#6b7280" />
          </button>
          <span className="t-ref-zoom-label">{zoom}%</span>
          <button
            className="t-ref-zoom-btn"
            onClick={() => setZoom((z) => Math.min(200, z + 25))}
          >
            <ZoomIn size={15} color="#6b7280" />
          </button>
          <button
            style={{
              marginLeft: "0.5rem",
              padding: "0.3rem 0.85rem",
              borderRadius: 100,
              border: "2.5px solid #f3f4f6",
              background: "white",
              fontFamily: "'Nunito',sans-serif",
              fontSize: "0.72rem",
              fontWeight: 800,
              color: "#9ca3af",
              cursor: "pointer",
            }}
            onClick={() => setZoom(100)}
          >
            Reset
          </button>
        </div>
      </div>
    </div>
  );
};

// ─── Review Warning Dialog ────────────────────────────────────────────────────
const ReviewWarningDialog = ({
  open,
  markedCount,
  onReview,
  onFinish,
}: {
  open: boolean;
  markedCount: number;
  onReview: () => void;
  onFinish: () => void;
}) => {
  if (!open) return null;
  return (
    <div
      className="fixed inset-0 z-50 flex items-center justify-center p-4"
      style={{ background: "rgba(0,0,0,0.4)", backdropFilter: "blur(6px)" }}
    >
      <div
        className="t-card t-review-warning p-6 flex flex-col gap-4"
        style={{ width: "100%", maxWidth: 360 }}
      >
        <div style={{ textAlign: "center" }}>
          <span
            style={{
              fontSize: "2.5rem",
              display: "block",
              marginBottom: "0.5rem",
            }}
          >
            🔖
          </span>
          <h2
            style={{
              fontWeight: 900,
              fontSize: "1.15rem",
              color: "#1e1b4b",
              marginBottom: "0.35rem",
            }}
          >
            {markedCount} question{markedCount !== 1 ? "s" : ""} marked for
            review
          </h2>
          <p
            style={{
              fontFamily: "'Nunito Sans',sans-serif",
              fontSize: "0.82rem",
              fontWeight: 600,
              color: "#9ca3af",
              lineHeight: 1.5,
            }}
          >
            You've bookmarked questions you wanted to revisit. Would you like to
            go back and review them, or finish the exam now?
          </p>
        </div>
        <div style={{ display: "flex", gap: "0.65rem" }}>
          <button
            onClick={onReview}
            className="t-btn-3d t-btn-outline"
            style={{ flex: 1, padding: "0.75rem" }}
          >
            🔖 Review
          </button>
          <button
            onClick={onFinish}
            className="t-btn-3d t-btn-accent"
            style={{ flex: 1, padding: "0.75rem" }}
          >
            Finish Anyway
          </button>
        </div>
      </div>
    </div>
  );
};

// ─── Shared Background ────────────────────────────────────────────────────────
const BgLayer = () => (
  <>
    <div className="t-blob t-blob-1" />
    <div className="t-blob t-blob-2" />
    <div className="t-blob t-blob-3" />
    <div className="t-blob t-blob-4" />
    {DOTS.map((d, i) => (
      <div
        key={i}
        className="t-dot"
        style={
          {
            width: d.size,
            height: d.size,
            background: d.color,
            top: d.top,
            left: d.left,
            right: d.right,
            animationDelay: d.delay,
            animationDuration: `${3.5 + i * 0.4}s`,
          } as React.CSSProperties
        }
      />
    ))}
  </>
);

// ─── Main Component ───────────────────────────────────────────────────────────
export const Test = () => {
  const sheetId = localStorage.getItem("activePracticeSheetId");
  const blocker = useExamNavigationGuard();
  const navigate = useNavigate();
  const { user } = useAuthStore();
  const token = useAuthToken();

  // ── Core state ──────────────────────────────────────────────────────────────
  const [eliminated, setEliminated] = useState<Record<string, Set<string>>>({});
  const [markedForReview, setMarkedForReview] = useState<Set<string>>(
    new Set(),
  );
  const [answers, setAnswers] = useState<Record<string, string>>({});
  const [showNavigator, setShowNavigator] = useState(false);
  const [showExitDialog, setShowExitDialog] = useState(false);
  const [showRefSheet, setShowRefSheet] = useState(false);
  const [showReviewWarning, setShowReviewWarning] = useState(false);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [sessionId, setSessionId] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [calcOpen, setCalcOpen] = useState(false);
  const [menuOpen, setMenuOpen] = useState(false);
  const [feedback, setFeedback] = useState<FeedbackState>(null);
  const [showConfetti, setShowConfetti] = useState(false);
  const [showDirections, setShowDirections] = useState(false);
  const [timerVisible, setTimerVisible] = useState(true);
  const [leftColumnWidth, setLeftColumnWidth] = useState(350); // desktop only (re-centered on mount)
  const dragRef = useRef<{ startX: number; startWidth: number } | null>(null);
  const [isDraggingDivider, setIsDraggingDivider] = useState(false);
  const userAdjustedSplitRef = useRef(false);
  const desktopShellRef = useRef<HTMLDivElement | null>(null);
  const [isMdUp, setIsMdUp] = useState(false);
  const HIGHLIGHTS_STORAGE_KEY = "edbridge_highlights_v1";
  const [highlightMode, setHighlightMode] = useState(false);
  const [highlightsByField, setHighlightsByField] = useState<HighlightsByField>(
    {},
  );
  const [showIncorrectFlash, setShowIncorrectFlash] = useState(false);

  // ── Retry / targeted state ──────────────────────────────────────────────────
  const incorrectQueueRef = useRef<IncorrectEntry[]>([]);
  const correctedRef = useRef<Set<string>>(new Set());
  const [retryMode, setRetryMode] = useState(false);
  const [retryQueue, setRetryQueue] = useState<IncorrectEntry[]>([]);
  const [retryIndex, setRetryIndex] = useState(0);

  // ── Exam store ──────────────────────────────────────────────────────────────
  const examMode = useExamConfigStore((s) => s.payload?.mode);
  const isTargeted = examMode === "TARGETED";
  const time = useSatTimer();
  const phase = useSatExam((s) => s.phase);
  const currentModule = useSatExam((s) => s.currentModuleQuestions);
  const questionIndex = useSatExam((s) => s.questionIndex);
  const resetExam = useSatExam((s) => s.resetExam);
  const nextQuestion = useSatExam((s) => s.nextQuestion);
  const prevQuestion = useSatExam((s) => s.prevQuestion);
  const goToQuestion = useSatExam((s) => s.goToQuestion);
  const finishExam = useSatExam((s) => s.finishExam);
  const quitExam = useSatExam((s) => s.quitExam);
  const setResults = useResults((s) => s.setResults);

  const currentQuestion = retryMode
    ? currentModule?.questions[retryQueue[retryIndex]?.originalIndex]
    : currentModule?.questions[questionIndex];

  // close directions when question changes
  useEffect(() => {
    setShowDirections(false);
  }, [currentQuestion?.id]);

  // Handle separator drag (desktop only)
  const handleSeparatorMouseDown = (e: React.MouseEvent) => {
    if (e.button !== 0) return;
    e.preventDefault(); // prevent text selection kick-off
    userAdjustedSplitRef.current = true;
    dragRef.current = {
      startX: e.clientX,
      startWidth: leftColumnWidth,
    };
    setIsDraggingDivider(true);
  };

  // Center the splitter on initial desktop load (and on resize until user drags)
  useEffect(() => {
    const centerSplit = () => {
      if (userAdjustedSplitRef.current) return;
      if (typeof window === "undefined") return;
      if (window.innerWidth < 768) return; // md breakpoint
      const shell = desktopShellRef.current;
      if (!shell) return;
      const w = shell.getBoundingClientRect().width;
      // Account for divider+margin so the handle lands near visual center.
      const target = Math.round((w - 40) / 2);
      setLeftColumnWidth(Math.max(300, Math.min(600, target)));
    };

    centerSplit();
    window.addEventListener("resize", centerSplit);
    return () => window.removeEventListener("resize", centerSplit);
  }, []);

  // True responsive check (portals ignore parent display:none)
  useEffect(() => {
    if (typeof window === "undefined") return;
    const mq = window.matchMedia("(min-width: 768px)");
    const update = () => setIsMdUp(mq.matches);
    update();
    mq.addEventListener("change", update);
    return () => mq.removeEventListener("change", update);
  }, []);

  // Highlights persistence (desktop/web feature; safe on mobile too)
  useEffect(() => {
    try {
      const raw = localStorage.getItem(HIGHLIGHTS_STORAGE_KEY);
      if (!raw) return;
      const parsed = JSON.parse(raw) as HighlightsByField;
      if (parsed && typeof parsed === "object") setHighlightsByField(parsed);
    } catch {
      // ignore corrupted storage
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => {
    try {
      localStorage.setItem(
        HIGHLIGHTS_STORAGE_KEY,
        JSON.stringify(highlightsByField),
      );
    } catch {
      // ignore quota / private mode issues
    }
  }, [HIGHLIGHTS_STORAGE_KEY, highlightsByField]);

  useEffect(() => {
    const handleMouseMove = (e: MouseEvent) => {
      if (!dragRef.current) return;
      const delta = e.clientX - dragRef.current.startX;
      const newWidth = Math.max(
        300,
        Math.min(600, dragRef.current.startWidth + delta),
      );
      setLeftColumnWidth(newWidth);
    };
    const handleMouseUp = () => {
      dragRef.current = null;
      setIsDraggingDivider(false);
    };
    window.addEventListener("mousemove", handleMouseMove);
    window.addEventListener("mouseup", handleMouseUp);
    return () => {
      window.removeEventListener("mousemove", handleMouseMove);
      window.removeEventListener("mouseup", handleMouseUp);
    };
  }, []);

  // Prevent text selection while dragging divider
  useEffect(() => {
    if (!isDraggingDivider) return;
    const prevUserSelect = document.body.style.userSelect;
    const prevCursor = document.body.style.cursor;
    document.body.style.userSelect = "none";
    document.body.style.cursor = "col-resize";
    return () => {
      document.body.style.userSelect = prevUserSelect;
      document.body.style.cursor = prevCursor;
    };
  }, [isDraggingDivider]);

  const currentAnswer = currentQuestion
    ? (answers[currentQuestion.id] ?? "")
    : "";
  const isCurrentMarked =
    !!currentQuestion && markedForReview.has(currentQuestion.id);
  const isMCQ = !!currentQuestion?.options?.length;
  const isFirstQuestion = retryMode ? true : questionIndex === 0;
  const isLastQuestion =
    !retryMode && questionIndex === (currentModule?.questions.length ?? 1) - 1;

  // ── Blocker ─────────────────────────────────────────────────────────────────
  useEffect(() => {
    if (blocker.state === "blocked") setShowExitDialog(true);
  }, [blocker.state]);
  useEffect(() => {
    return () => {
      resetExam();
    };
  }, []);
  useEffect(() => {
    if (phase === "FINISHED") {
      const t = setTimeout(
        () =>
          navigate(`/student/practice/${sheetId}/test/results`, {
            replace: true,
          }),
        3000,
      );
      return () => clearTimeout(t);
    }
  }, [phase]);

  // ── Exam start ──────────────────────────────────────────────────────────────
  const startExam = async () => {
    if (!user) return;
    const payload = useExamConfigStore.getState().payload;
    try {
      const response = await api.startSession(token as string, payload);
      setSessionId(response.id);
      await loadSessionQuestions(response.id);
      useSatExam.getState().startExam();
    } catch (err) {
      setError(`Failed to start exam session: ${err}`);
    }
  };

  const loadSessionQuestions = async (sid: string) => {
    if (!token) return;
    const data = await api.fetchSessionQuestions(token, sid);
    const module: SessionModuleQuestions = {
      module_id: data.module_id,
      module_title: data.module_title,
      time_limit_minutes: data.time_limit_minutes * 60,
      questions: data.questions.map((q: Question) => ({
        id: q.id,
        text: q.text,
        context: q.context,
        context_image_url: q.context_image_url,
        type: q.type,
        section: q.section,
        image_url: q.image_url,
        index: q.index,
        difficulty: q.difficulty,
        correct_answer: q.correct_answer,
        explanation: q.explanation,
        topics: q.topics,
        options: q.options,
      })),
    };
    useSatExam.getState().setModuleQuestions(module);
  };

  // ── Toggle bookmark ──────────────────────────────────────────────────────────
  const toggleMark = () => {
    if (!currentQuestion) return;
    setMarkedForReview((prev) => {
      const next = new Set(prev);
      next.has(currentQuestion.id)
        ? next.delete(currentQuestion.id)
        : next.add(currentQuestion.id);
      return next;
    });
  };

  // ── Handle Next ──────────────────────────────────────────────────────────────
  const handleNext = async () => {
    if (isTargeted) {
      await submitTargetedAnswer();
      return;
    }
    if (!currentQuestion || !sessionId) return;

    // If last question and there are marked questions, warn first
    if (isLastQuestion && markedForReview.size > 0) {
      setShowReviewWarning(true);
      return;
    }
    await submitAndAdvance();
  };

  const submitAndAdvance = async () => {
    if (!currentQuestion || !sessionId) return;
    const userAnswer = answers[currentQuestion.id] ?? "";
    const answerText = currentQuestion.options?.length
      ? (currentQuestion.options.find((o) => o.id === userAnswer)?.text ?? "")
      : userAnswer;
    const payload: SubmitAnswer = {
      question_id: currentQuestion.id,
      answer_text: answerText,
      time_spent_seconds: 3,
    };
    try {
      setIsSubmitting(true);
      await api.submitAnswer(token!, sessionId, payload);
    } catch (err) {
      console.error(err);
    } finally {
      setIsSubmitting(false);
    }

    if (!isLastQuestion) {
      nextQuestion();
      return;
    }
    const next = await api.fetchNextModule(token!, sessionId);
    if (next?.status === "COMPLETED") {
      setResults(next.results);
      finishExam();
    } else {
      await loadSessionQuestions(sessionId);
      useSatExam.getState().startBreak();
    }
  };

  // ── Review warning actions ───────────────────────────────────────────────────
  const handleGoReview = () => {
    setShowReviewWarning(false);
    // Jump to first marked question
    const firstMarked = currentModule?.questions.findIndex((q) =>
      markedForReview.has(q.id),
    );
    if (firstMarked !== undefined && firstMarked >= 0)
      goToQuestion(firstMarked);
    setShowNavigator(true);
  };
  const handleFinishAnyway = async () => {
    setShowReviewWarning(false);
    setMarkedForReview(new Set()); // clear marks so we don't re-trigger
    await submitAndAdvance();
  };

  // ── Targeted submit ──────────────────────────────────────────────────────────
  const showAnswerFeedback = (
    correct: boolean,
    xpGained?: number,
    selectedOptionId?: string,
  ) => {
    setFeedback({ show: true, correct, xpGained, selectedOptionId });
    if (correct) {
      setShowConfetti(true);
      setTimeout(() => setShowConfetti(false), 2500);
    } else {
      setShowIncorrectFlash(true);
      setTimeout(() => setShowIncorrectFlash(false), 1300);
    }
  };

  const advanceRetry = async () => {
    setFeedback(null);
    const remaining = retryQueue.filter(
      (e) => !correctedRef.current.has(e.questionId),
    );
    if (!remaining.length) {
      const next = await api.fetchNextModule(token!, sessionId);
      if (next.status === "COMPLETED") finishExam();
      return;
    }
    const nextIdx = retryIndex + 1;
    if (nextIdx >= retryQueue.length) {
      const still = incorrectQueueRef.current.filter(
        (e) => !correctedRef.current.has(e.questionId),
      );
      setRetryQueue(still);
      setRetryIndex(0);
      goToQuestion(still[0].originalIndex);
    } else {
      setRetryIndex(nextIdx);
      goToQuestion(retryQueue[nextIdx].originalIndex);
    }
  };

  const submitTargetedAnswer = async () => {
    if (!currentQuestion || !sessionId) return;
    const userAnswer = answers[currentQuestion.id] ?? "";
    const answerText = currentQuestion.options?.length
      ? (currentQuestion.options.find((o) => o.id === userAnswer)?.text ?? "")
      : userAnswer;
    const payload: SubmitAnswer = {
      question_id: currentQuestion.id,
      answer_text: answerText,
      time_spent_seconds: 3,
    };
    try {
      setIsSubmitting(true);
      const result = await api.submitAnswer(token!, sessionId, payload);
      const isCorrect = result?.feedback.is_correct ?? false;
      showAnswerFeedback(isCorrect, 2, userAnswer);
      if (isCorrect) {
        correctedRef.current.add(currentQuestion.id);
        incorrectQueueRef.current = incorrectQueueRef.current.filter(
          (e) => e.questionId !== currentQuestion.id,
        );
      } else {
        if (
          !incorrectQueueRef.current.some(
            (e) => e.questionId === currentQuestion.id,
          )
        ) {
          incorrectQueueRef.current.push({
            questionId: currentQuestion.id,
            originalIndex: retryMode
              ? retryQueue[retryIndex].originalIndex
              : questionIndex,
          });
        }
        correctedRef.current.delete(currentQuestion.id);
      }
      setTimeout(
        async () => {
          setFeedback(null);
          if (retryMode) {
            advanceRetry();
            return;
          }
          const isLast = questionIndex === currentModule!.questions.length - 1;
          if (!isLast) {
            nextQuestion();
            return;
          }
          if (incorrectQueueRef.current.length > 0) {
            const queue = [...incorrectQueueRef.current];
            setRetryQueue(queue);
            setRetryIndex(0);
            setRetryMode(true);
            goToQuestion(queue[0].originalIndex);
            return;
          }
          await proceedAfterLastQuestion();
        },
        isCorrect ? 2200 : 1500,
      );
    } catch (err) {
      console.error(err);
    } finally {
      setIsSubmitting(false);
    }
  };

  const proceedAfterLastQuestion = async () => {
    if (!sessionId) return;
    const next = await api.fetchNextModule(token!, sessionId);
    if (next?.status === "COMPLETED") {
      setResults(next.results);
      finishExam();
    } else {
      await loadSessionQuestions(sessionId);
      useSatExam.getState().startBreak();
    }
  };

  const handleQuitExam = () => {
    useExamConfigStore.getState().clearPayload();
    quitExam();
  };

  const toggleEliminate = (questionId: string, optionId: string) => {
    setEliminated((prev) => {
      const cur = new Set(prev[questionId] ?? []);
      cur.has(optionId) ? cur.delete(optionId) : cur.add(optionId);
      return { ...prev, [questionId]: cur };
    });
  };

  const formatTime = (s: number) =>
    `${Math.floor(s / 60)}:${String(s % 60).padStart(2, "0")}`;

  const mergeHighlightRanges = (ranges: HighlightRange[]) => {
    const sorted = ranges
      .filter((r) => Number.isFinite(r.start) && Number.isFinite(r.end))
      .map((r) => ({ start: Math.max(0, r.start), end: Math.max(0, r.end) }))
      .filter((r) => r.end > r.start)
      .sort((a, b) => a.start - b.start);

    const merged: HighlightRange[] = [];
    for (const r of sorted) {
      const last = merged[merged.length - 1];
      if (!last || r.start > last.end) merged.push(r);
      else last.end = Math.max(last.end, r.end);
    }
    return merged;
  };

  const addHighlight = (fieldKey: string, start: number, end: number) => {
    const s = Math.min(start, end);
    const e = Math.max(start, end);
    if (!fieldKey || s === e) return;

    setHighlightsByField((prev) => {
      const cur = prev[fieldKey] ?? [];
      const next = mergeHighlightRanges([...cur, { start: s, end: e }]);
      return { ...prev, [fieldKey]: next };
    });
  };

  const renderQuestionTextWithHighlights = (
    text: string,
    highlights: HighlightRange[],
  ) => {
    const merged = mergeHighlightRanges(highlights);
    const parts = text.split(/(\$\$.*?\$\$|\$.*?\$)/g);
    let pos = 0;
    let pieceIdx = 0;

    const renderPlain = (plain: string, basePos: number) => {
      const segStart = basePos;
      const segEnd = basePos + plain.length;
      const overlapping = merged.filter(
        (h) => h.end > segStart && h.start < segEnd,
      );
      if (!overlapping.length) {
        const key = `p-${pieceIdx++}`;
        return <span key={key}>{plain}</span>;
      }

      const nodes: React.ReactNode[] = [];
      let cursor = 0;
      for (const h of overlapping) {
        const localStart = Math.max(0, h.start - segStart);
        const localEnd = Math.min(plain.length, h.end - segStart);
        if (localStart > cursor) {
          nodes.push(
            <span key={`t-${pieceIdx++}`}>
              {plain.slice(cursor, localStart)}
            </span>,
          );
        }
        nodes.push(
          <mark key={`m-${pieceIdx++}`} className="t-highlight">
            {plain.slice(localStart, localEnd)}
          </mark>,
        );
        cursor = Math.max(cursor, localEnd);
      }
      if (cursor < plain.length) {
        nodes.push(<span key={`t-${pieceIdx++}`}>{plain.slice(cursor)}</span>);
      }
      return <span key={`w-${pieceIdx++}`}>{nodes}</span>;
    };

    return (
      <>
        {parts.map((part, index) => {
          if (part.startsWith("$$")) {
            const inner = part.slice(2, -2);
            const len = inner.length;
            const hasOverlap = merged.some(
              (h) => h.end > pos && h.start < pos + len,
            );
            const node = <BlockMath key={index}>{inner}</BlockMath>;
            pos += len;
            if (!hasOverlap) return node;
            return (
              <span key={index} className="t-highlight">
                {node}
              </span>
            );
          }
          if (part.startsWith("$")) {
            const inner = part.slice(1, -1);
            const len = inner.length;
            const hasOverlap = merged.some(
              (h) => h.end > pos && h.start < pos + len,
            );
            const node = <InlineMath key={index}>{inner}</InlineMath>;
            pos += len;
            if (!hasOverlap) return node;
            return (
              <span key={index} className="t-highlight">
                {node}
              </span>
            );
          }
          const base = pos;
          pos += part.length;
          return <span key={index}>{renderPlain(part, base)}</span>;
        })}
      </>
    );
  };

  const HighlightableRichText = ({
    fieldKey,
    text,
    className,
  }: {
    fieldKey: string;
    text: string;
    className?: string;
  }) => {
    const rootRef = useRef<HTMLDivElement | null>(null);
    const highlights = highlightsByField[fieldKey] ?? [];

    return (
      <div
        ref={rootRef}
        className={className}
        onMouseUp={() => {
          if (!highlightMode) return;
          const root = rootRef.current;
          if (!root) return;
          const sel = window.getSelection();
          if (!sel || sel.rangeCount === 0 || sel.isCollapsed) return;
          const range = sel.getRangeAt(0);
          if (
            !root.contains(range.startContainer) ||
            !root.contains(range.endContainer)
          )
            return;
          const selected = range.toString();
          if (!selected.trim()) return;

          const pre = document.createRange();
          pre.selectNodeContents(root);
          pre.setEnd(range.startContainer, range.startOffset);
          const start = pre.toString().length;
          addHighlight(fieldKey, start, start + selected.length);
        }}
      >
        {renderQuestionTextWithHighlights(text, highlights)}
      </div>
    );
  };

  // ── Render helpers ───────────────────────────────────────────────────────────
  const renderOptions = (question?: Question) => {
    if (!question?.options?.length) return null;
    const eliminatedSet = eliminated[question.id] ?? new Set();
    return (
      <div className="flex flex-col gap-3 w-full">
        {question.options.map((option, index) => {
          const isSelected = currentAnswer === option.id;
          const isEliminated = eliminatedSet.has(option.id);
          const feedbackLocked = isTargeted && !!feedback?.show;
          let cls = "t-option";
          if (isSelected) cls += " selected";
          if (isEliminated && !feedbackLocked) cls += " eliminated";
          if (feedbackLocked && isSelected)
            cls += feedback!.correct ? " correct" : " incorrect";
          return (
            <div key={option.id} className="flex items-center gap-2">
              <button
                className={`t-eliminate-btn ${isEliminated ? "active" : ""}`}
                onClick={(e) => {
                  e.stopPropagation();
                  if (!feedbackLocked) toggleEliminate(question.id, option.id);
                }}
                disabled={feedbackLocked}
              >
                <X size={14} />
              </button>
              <div className="relative flex-1">
                <button
                  className={cls}
                  onClick={() => {
                    if (feedbackLocked) return;
                    setAnswers((p) => ({ ...p, [question.id]: option.id }));
                  }}
                  disabled={feedbackLocked}
                >
                  <span className="t-option-letter">{"ABCD"[index]}</span>
                  <span className="flex-1">
                    {renderQuestionText(option.text)}
                  </span>
                </button>
                {isTargeted &&
                  feedback?.show &&
                  feedback.correct &&
                  feedback.xpGained &&
                  isSelected && (
                    <div className="t-xp-badge">+{feedback.xpGained} XP ⭐</div>
                  )}
              </div>
            </div>
          );
        })}
      </div>
    );
  };

  const renderShortAnswer = (question?: Question) => {
    if (!question || question.options?.length) return null;
    return (
      <div className="flex flex-col gap-3 pt-4">
        <textarea
          value={currentAnswer}
          onChange={(e) =>
            setAnswers((p) => ({ ...p, [question.id]: e.target.value }))
          }
          placeholder="Type your answer here..."
          disabled={isTargeted && !!feedback?.show}
          className="t-textarea"
        />
      </div>
    );
  };

  const RetryBanner = () => {
    if (!retryMode) return null;
    const remaining = retryQueue.filter(
      (e) => !correctedRef.current.has(e.questionId),
    ).length;
    return (
      <div className="t-retry-banner">
        <span>🔁 Review Mode</span>
        <span className="opacity-80">—</span>
        <span>
          {remaining} question{remaining !== 1 ? "s" : ""} left to correct
        </span>
        <span className="ml-2 bg-white/20 px-2 py-0.5 rounded-full text-xs">
          {retryIndex + 1}/{retryQueue.length}
        </span>
      </div>
    );
  };

  // ─── IDLE ─────────────────────────────────────────────────────────────────────
  if (phase === "IDLE") {
    if (error)
      return (
        <div className="test-screen">
          <style>{GLOBAL_STYLES}</style>
          <BgLayer />
          <main className="relative z-10 min-h-screen flex flex-col items-center justify-center px-6 py-8">
            <div className="t-card t-card-purple p-8 max-w-md w-full t-anim">
              <div className="flex flex-col items-center gap-6 text-center">
                <div className="w-20 h-20 rounded-full bg-red-100 flex items-center justify-center">
                  <Unplug size={40} className="text-red-500" />
                </div>
                <div>
                  <h2 className="t-section-title mb-2">Connection Error</h2>
                  <p className="text-gray-500 font-semibold">{error}</p>
                </div>
              </div>
            </div>
            <div className="flex gap-4 mt-6 w-full max-w-md">
              <button
                onClick={() => {
                  useExamConfigStore.getState().clearPayload();
                  navigate("/student/home");
                }}
                className="t-btn-3d t-btn-outline flex-1 py-4"
              >
                Go Back
              </button>
              <button
                onClick={startExam}
                className="t-btn-3d t-btn-primary flex-1 py-4"
              >
                Retry
              </button>
            </div>
          </main>
        </div>
      );

    return (
      <div className="test-screen">
        <style>{GLOBAL_STYLES}</style>
        <BgLayer />
        <main className="relative z-10 min-h-screen flex flex-col items-center justify-center px-6 py-8">
          <div className="t-card p-8 max-w-lg w-full t-anim">
            <div className="text-center mb-8">
              <span className="text-5xl mb-4 block">🚀</span>
              <h1 className="text-3xl font-black text-[#1e1b4b] mb-2">
                Ready to begin?
              </h1>
              <p className="text-gray-500 font-semibold">
                Let's crush this practice test!
              </p>
            </div>
            <div className="space-y-4 mb-8">
              {[
                ["Full-screen mode for distraction-free focus"],
                [`Press Esc to exit anytime`],
                ["Progress saves automatically"],
              ].map(([text], i) => (
                <div
                  key={i}
                  className="flex items-center gap-4 p-4 bg-gray-50 rounded-2xl border-2 border-gray-100"
                >
                  <div className="w-10 h-10 rounded-full bg-purple-100 flex items-center justify-center shrink-0">
                    <Check size={20} className="text-purple-600" />
                  </div>
                  <span className="font-bold text-gray-700">{text}</span>
                </div>
              ))}
              {isTargeted && (
                <div className="flex items-center gap-4 p-4 bg-linear-to-r from-purple-50 to-orange-50 rounded-2xl border-2 border-purple-200">
                  <span className="text-3xl">🎯</span>
                  <div>
                    <p className="font-bold text-purple-800">Targeted Mode</p>
                    <p className="text-sm text-purple-600 font-semibold">
                      Instant feedback + XP rewards! Incorrect questions loop
                      until you get them right.
                    </p>
                  </div>
                </div>
              )}
            </div>
            <button
              onClick={startExam}
              className="t-btn-3d t-btn-accent w-full py-5 text-lg"
            >
              <Play size={20} className="inline mr-2" fill="white" />
              Start Test
            </button>
          </div>
        </main>
      </div>
    );
  }

  // ─── MODULE ───────────────────────────────────────────────────────────────────
  if (phase === "MODULE")
    return (
      <div className={`test-screen ${showIncorrectFlash ? "t-flash-red" : ""}`}>
        <style>{GLOBAL_STYLES}</style>
        <Confetti active={showConfetti} />
        {isTargeted && feedback?.show && feedback.correct && (
          <XPPopup xp={feedback.xpGained ?? 0} show={true} />
        )}
        <RetryBanner />
        <BgLayer />

        {/* Review warning overlay */}
        <ReviewWarningDialog
          open={showReviewWarning}
          markedCount={markedForReview.size}
          onReview={handleGoReview}
          onFinish={handleFinishAnyway}
        />

        {/* Reference sheet modal */}
        <ReferenceSheetModal
          open={showRefSheet}
          onClose={() => setShowRefSheet(false)}
        />

        <section className="relative z-10 flex flex-col min-h-screen">
          {/* Fixed header */}
          <header
            className={`fixed left-0 right-0 bg-white/95 backdrop-blur-sm border-b-2 border-purple-100 px-4 pt-6 pb-4 z-20 ${retryMode ? "top-10" : "top-0"}`}
          >
            <div className="mx-auto max-w-2xl md:max-w-(--content-max)">
              {/* Mobile header (unchanged) */}
              <div className="md:hidden">
                <div className="flex items-center justify-between mb-3">
                  <div className="flex items-center gap-3">
                    <span
                      className={`t-q-badge ${isCurrentMarked ? "reviewing" : ""}`}
                    >
                      {isCurrentMarked ? "🔖 " : ""}Q
                      {retryMode ? retryIndex + 1 : questionIndex + 1}
                    </span>
                    <span className="text-sm font-bold text-gray-400">
                      of {currentModule?.questions.length}
                    </span>
                  </div>
                  <div className="flex flex-col items-center">
                    <div className="t-timer">
                      {timerVisible
                        ? `${Math.floor(time / 60)}:${String(time % 60).padStart(2, "0")}`
                        : "--:--"}
                    </div>
                    <button
                      className="mt-1 text-xs text-gray-500 hover:text-gray-700"
                      onClick={() => setTimerVisible((v) => !v)}
                    >
                      {timerVisible ? <EyeOff size={16} /> : <Eye size={16} />}
                    </button>
                  </div>
                </div>
                <h1 className="text-center font-bold">
                  {currentModule?.module_title}
                </h1>
              </div>

              {/* Desktop header (web only) */}
              <div className="hidden md:flex items-start justify-between gap-6 relative">
                {/* Left: section/module + directions */}
                <div className="flex flex-col">
                  <div className="text-sm font-semibold text-gray-700">
                    {currentQuestion?.section || ""}
                  </div>
                  <div className="text-base font-bold text-gray-700">
                    {currentModule?.module_title}
                  </div>
                  <button
                    className={`mt-2 t-btn-3d t-directions-btn ${showDirections ? "active" : ""}`}
                    onClick={() => setShowDirections((v) => !v)}
                  >
                    Directions
                  </button>
                </div>

                {/* Middle: time + hide + question number (perfectly centered) */}
                <div className="flex flex-col items-center absolute left-1/2 -translate-x-1/2 top-0">
                  <div className="flex flex-col items-center">
                    <div className="t-timer">
                      {timerVisible
                        ? `${Math.floor(time / 60)}:${String(time % 60).padStart(2, "0")}`
                        : "--:--"}
                    </div>
                    <button
                      className="mt-1 text-xs text-gray-500 hover:text-gray-700"
                      onClick={() => setTimerVisible((v) => !v)}
                    >
                      {timerVisible ? <EyeOff size={16} /> : <Eye size={16} />}
                    </button>
                  </div>
                  <div
                    className="mt-2 flex items-center gap-2 cursor-pointer"
                    onClick={() => setShowNavigator(true)}
                  >
                    <span
                      className={`t-q-badge ${isCurrentMarked ? "reviewing" : ""}`}
                    >
                      {isCurrentMarked ? "🔖 " : ""}Q
                      {retryMode ? retryIndex + 1 : questionIndex + 1}
                    </span>
                    <span className="text-sm font-bold text-gray-400">
                      of {currentModule?.questions.length}
                    </span>
                  </div>
                </div>

                {/* Right: highlights */}
                <div className="flex items-start">
                  <button
                    onClick={() => setHighlightMode((v) => !v)}
                    className={`t-btn-3d px-5 py-3 flex items-center gap-2 ${
                      highlightMode ? "t-btn-primary" : "t-btn-outline"
                    }`}
                    title="Highlights & Notes"
                  >
                    <Highlighter size={18} />
                    <span className="font-black">Highlights &amp; Notes</span>
                  </button>
                </div>
              </div>

              {isTargeted && retryMode && (
                <p className="text-center text-orange-500 font-bold text-sm mt-2">
                  🔥 Reviewing incorrect answers — get them right to finish!
                </p>
              )}
            </div>
          </header>

          {/* Question content */}
          <section
            className={`flex-1 px-4 ${isMCQ ? "pb-110" : "pb-32"} ${retryMode ? "pt-36 md:pt-52" : "pt-28 md:pt-44"}`}
          >
            {/* Mobile layout (unchanged) */}
            <div className="block md:hidden">
              <div className="max-w-2xl mx-auto pt-4">
                <div className="space-y-6">
                  {showDirections ? (
                    <div className="t-card p-6 flex-1">
                      <p className="font-semibold text-gray-700 leading-relaxed">
                        {renderQuestionText(currentQuestion?.explanation || "")}
                      </p>
                    </div>
                  ) : (
                    <>
                      {currentQuestion?.context && (
                        <div className="t-card p-6">
                          <p className="font-semibold text-gray-700 leading-relaxed">
                            {renderQuestionText(currentQuestion.context)}
                          </p>
                        </div>
                      )}
                      <div className="t-card t-card-purple p-6">
                        <p className="font-bold text-lg text-[#1e1b4b] leading-relaxed">
                          {currentQuestion?.text &&
                            renderQuestionText(currentQuestion.text)}
                        </p>
                      </div>
                      {!isMCQ && renderShortAnswer(currentQuestion)}
                    </>
                  )}
                </div>
              </div>
            </div>

            {/* Desktop layout with draggable separator */}
            <div className="hidden md:block">
              <div
                ref={desktopShellRef}
                className="t-desktop-shell pt-8"
                style={{ paddingBottom: 160 }}
              >
                <div className="t-split-layout">
                  {/* Left column: passage / directions */}
                  <div
                    className="t-split-left"
                    style={{
                      width: leftColumnWidth,
                      minWidth: 300,
                      maxWidth: 600,
                    }}
                  >
                    {showDirections ? (
                      <div className="t-card p-6 flex-1">
                        <HighlightableRichText
                          fieldKey={`${currentQuestion?.id ?? "unknown"}:explanation`}
                          text={currentQuestion?.explanation || ""}
                          className="font-semibold text-gray-700 leading-relaxed"
                        />
                      </div>
                    ) : (
                      <>
                        {currentQuestion?.context && (
                          <div className="t-card p-6">
                            <HighlightableRichText
                              fieldKey={`${currentQuestion?.id ?? "unknown"}:context`}
                              text={currentQuestion.context}
                              className="font-semibold text-gray-700 leading-relaxed"
                            />
                          </div>
                        )}
                      </>
                    )}
                  </div>

                  {/* Draggable divider */}
                  <div
                    className="t-split-divider mx-3"
                    onMouseDown={handleSeparatorMouseDown}
                    onDragStart={(e) => e.preventDefault()}
                  >
                    <div className="t-split-divider-bar" />
                    <div className="t-split-divider-handle">
                      <div className="t-split-divider-dots" />
                    </div>
                  </div>

                  {/* Right column: question + options/answer */}
                  <div className="t-split-right flex-1">
                    <div className="t-card t-card-purple p-6 mt-4">
                      {currentQuestion?.text && (
                        <HighlightableRichText
                          fieldKey={`${currentQuestion.id}:text`}
                          text={currentQuestion.text}
                          className="font-bold text-lg text-[#1e1b4b] leading-relaxed"
                        />
                      )}
                    </div>
                    {!isMCQ && renderShortAnswer(currentQuestion)}
                    {isMCQ && renderOptions(currentQuestion)}
                  </div>
                </div>
              </div>
            </div>
          </section>
        </section>

        {/* Fixed bottom bar */}
        <section
          className="fixed bottom-0 left-0 right-0 bg-white border-t-2 border-gray-100 py-4 px-4"
          style={{ zIndex: 20 }}
        >
          <div className="mx-auto max-w-2xl md:max-w-(--content-max) flex items-center justify-between gap-3">
            {/* Back button (non-targeted) */}
            {!isTargeted && (
              <button
                disabled={isFirstQuestion}
                onClick={prevQuestion}
                className="t-btn-3d t-btn-outline px-5 py-3 disabled:opacity-40 flex items-center gap-2"
              >
                <ChevronLeft size={18} />
                <span className="hidden md:inline font-black">Previous</span>
              </button>
            )}

            {/* Menu */}
            <DropdownMenu open={menuOpen} onOpenChange={setMenuOpen}>
              <DropdownMenuTrigger asChild>
                <button className="t-btn-3d t-btn-outline px-5 py-3 flex items-center gap-2">
                  <Menu size={18} />
                  <span className="hidden md:inline font-black">Menu</span>
                </button>
              </DropdownMenuTrigger>
              <DropdownMenuContent className="rounded-2xl border-2 border-gray-100 p-2">
                <DropdownMenuGroup>
                  {!isTargeted && (
                    <DropdownMenuItem
                      className="rounded-xl font-bold py-3 px-4 cursor-pointer"
                      onClick={() => setShowNavigator(true)}
                    >
                      <Binary size={18} className="mr-2" /> Go To Question
                    </DropdownMenuItem>
                  )}
                  {!isTargeted && (
                    <DropdownMenuItem
                      className="rounded-xl font-bold py-3 px-4 cursor-pointer"
                      onSelect={(e) => {
                        e.preventDefault();
                        setMenuOpen(false);
                        setCalcOpen(true);
                      }}
                    >
                      <Calculator size={18} className="mr-2" /> Calculator
                    </DropdownMenuItem>
                  )}
                  {/* Reference Sheet — always available */}
                  <DropdownMenuItem
                    className="rounded-xl font-bold py-3 px-4 cursor-pointer"
                    onSelect={(e) => {
                      e.preventDefault();
                      setMenuOpen(false);
                      setShowRefSheet(true);
                    }}
                  >
                    <BookOpen size={18} className="mr-2" /> Reference Sheet
                  </DropdownMenuItem>
                </DropdownMenuGroup>
                <DropdownMenuSeparator />
                <Dialog>
                  <DialogTrigger asChild>
                    <DropdownMenuItem
                      className="rounded-xl font-bold py-3 px-4 cursor-pointer text-red-600 focus:text-red-600 focus:bg-red-50"
                      onSelect={(e) => e.preventDefault()}
                    >
                      <LogOut size={18} className="mr-2" /> Quit Test
                    </DropdownMenuItem>
                  </DialogTrigger>
                  <DialogContent className="rounded-3xl border-2 border-gray-100 max-w-sm">
                    <DialogHeader>
                      <DialogTitle className="font-black text-xl text-[#1e1b4b]">
                        Want to quit?
                      </DialogTitle>
                      <DialogDescription className="font-semibold text-gray-500">
                        Your progress will be saved and you can resume later.
                      </DialogDescription>
                    </DialogHeader>
                    <div className="flex gap-3 mt-6">
                      <DialogClose asChild>
                        <button className="t-btn-3d t-btn-outline flex-1 py-3">
                          Stay
                        </button>
                      </DialogClose>
                      <button
                        onClick={handleQuitExam}
                        className="t-btn-3d bg-red-500 text-white flex-1 py-3 shadow-[0_4px_0_#dc2626] hover:shadow-[0_6px_0_#dc2626] active:shadow-[0_2px_0_#dc2626]"
                      >
                        Quit
                      </button>
                    </div>
                  </DialogContent>
                </Dialog>
              </DropdownMenuContent>
            </DropdownMenu>

            <GraphCalculatorModal
              open={calcOpen}
              onClose={() => setCalcOpen(false)}
            />

            {/* ── Mark for Review button (non-targeted) ── */}
            {!isTargeted && (
              <>
                {/* Mobile: keep existing icon-only button */}
                {!isMdUp ? (
                  <button
                    className={`t-bookmark-btn ${isCurrentMarked ? "marked" : ""}`}
                    onClick={toggleMark}
                    title={
                      isCurrentMarked ? "Remove review mark" : "Mark for review"
                    }
                  >
                    {isCurrentMarked ? (
                      <BookMarked size={18} color="white" />
                    ) : (
                      <Bookmark size={18} color="#9ca3af" />
                    )}
                  </button>
                ) : (
                  /* Desktop/web: icon + text */
                  <button
                    onClick={toggleMark}
                    className={`t-btn-3d px-5 py-3 flex items-center gap-2 ${
                      isCurrentMarked ? "t-btn-primary" : "t-btn-outline"
                    }`}
                    title={
                      isCurrentMarked ? "Remove review mark" : "Mark for review"
                    }
                  >
                    {isCurrentMarked ? (
                      <BookMarked size={18} color="white" />
                    ) : (
                      <Bookmark size={18} color="#9ca3af" />
                    )}
                    <span className="font-black">
                      {isCurrentMarked
                        ? "Marked for review"
                        : "Mark for review"}
                    </span>
                  </button>
                )}
              </>
            )}

            {/* Question navigator dialog */}
            {!isTargeted && (
              <Dialog open={showNavigator} onOpenChange={setShowNavigator}>
                <DialogContent className="rounded-3xl border-2 border-gray-100 max-w-sm max-h-[80vh]">
                  <DialogHeader>
                    <DialogTitle className="font-black text-xl text-[#1e1b4b]">
                      Go to Question
                    </DialogTitle>
                    <DialogDescription className="font-semibold text-gray-500">
                      Select a question to jump to it directly.
                    </DialogDescription>
                  </DialogHeader>

                  {/* Legend */}
                  <div className="flex items-center gap-3 mb-4 text-xs flex-wrap">
                    <div className="flex items-center gap-1.5">
                      <div className="w-4 h-4 rounded bg-purple-500 border-2 border-purple-600" />
                      <span className="font-semibold text-gray-600">
                        Current
                      </span>
                    </div>
                    <div className="flex items-center gap-1.5">
                      <div className="w-4 h-4 rounded bg-green-100 border-2 border-green-400" />
                      <span className="font-semibold text-gray-600">
                        Answered
                      </span>
                    </div>
                    <div className="flex items-center gap-1.5">
                      <div className="w-4 h-4 rounded bg-amber-50 border-2 border-amber-400" />
                      <span className="font-semibold text-gray-600">
                        Marked
                      </span>
                    </div>
                  </div>

                  {/* Marked summary */}
                  {markedForReview.size > 0 && (
                    <div
                      style={{
                        background: "#fffbeb",
                        border: "2px solid #fde68a",
                        borderRadius: 14,
                        padding: "0.6rem 0.85rem",
                        marginBottom: "0.75rem",
                      }}
                    >
                      <p
                        style={{
                          fontFamily: "'Nunito',sans-serif",
                          fontSize: "0.75rem",
                          fontWeight: 800,
                          color: "#d97706",
                        }}
                      >
                        🔖 {markedForReview.size} question
                        {markedForReview.size !== 1 ? "s" : ""} marked for
                        review
                      </p>
                    </div>
                  )}

                  <div className="t-nav-grid">
                    {currentModule?.questions.map((q, idx) => {
                      const isCurrent = idx === questionIndex;
                      const isAnswered = !!answers[q.id];
                      const isMarked = markedForReview.has(q.id);
                      let cls = "t-nav-item";
                      if (isCurrent && isMarked) cls += " current marked";
                      else if (isCurrent) cls += " current";
                      else if (isMarked) cls += " marked";
                      else if (isAnswered) cls += " answered";
                      return (
                        <button
                          key={q.id}
                          className={cls}
                          onClick={() => {
                            goToQuestion(idx);
                            setShowNavigator(false);
                          }}
                        >
                          {idx + 1}
                          {isMarked && !isCurrent && (
                            <span className="t-nav-bookmark-dot" />
                          )}
                        </button>
                      );
                    })}
                  </div>
                </DialogContent>
              </Dialog>
            )}

            {/* Exit dialog triggered by navigation blocker */}
            <Dialog open={showExitDialog} onOpenChange={setShowExitDialog}>
              <DialogContent className="rounded-3xl border-2 border-gray-100 max-w-sm">
                <DialogHeader>
                  <DialogTitle className="font-black text-xl text-[#1e1b4b]">
                    Want to quit?
                  </DialogTitle>
                  <DialogDescription className="font-semibold text-gray-500">
                    Your progress will be saved and you can resume later.
                  </DialogDescription>
                </DialogHeader>
                <div className="flex gap-3 mt-6">
                  <button
                    onClick={() => {
                      setShowExitDialog(false);
                      blocker.reset?.();
                    }}
                    className="t-btn-3d t-btn-outline flex-1 py-3"
                  >
                    Stay
                  </button>
                  <button
                    onClick={() => {
                      finishExam();
                      blocker.proceed?.();
                    }}
                    className="t-btn-3d bg-red-500 text-white flex-1 py-3 shadow-[0_4px_0_#dc2626] hover:shadow-[0_6px_0_#dc2626] active:shadow-[0_2px_0_#dc2626]"
                  >
                    Quit Test
                  </button>
                </div>
              </DialogContent>
            </Dialog>

            {/* Next / Submit */}
            <button
              disabled={
                isSubmitting ||
                (isTargeted && !!feedback?.show) ||
                !currentAnswer
              }
              onClick={handleNext}
              className="t-btn-3d t-btn-primary px-8 py-3 flex items-center gap-2 disabled:opacity-50"
            >
              {isSubmitting ? (
                <Loader2 size={20} className="animate-spin" />
              ) : isTargeted ? (
                <>
                  <Check size={18} /> Submit
                </>
              ) : isLastQuestion && markedForReview.size > 0 ? (
                <>
                  <BookMarked size={16} /> Finish
                </>
              ) : (
                <>
                  Next <ChevronLeft size={18} className="rotate-180" />
                </>
              )}
            </button>
          </div>
        </section>

        {/* MCQ Options Drawer (mobile only) */}
        {isMCQ && !isMdUp && (
          <Drawer.Root
            modal={false}
            snapPoints={[0.35, 0.6, 0.95]}
            defaultOpen={true}
          >
            <Drawer.Portal>
              <Drawer.Content
                className="fixed flex flex-col bg-white border-t-2 border-gray-100 rounded-t-[24px] bottom-0 left-0 right-0 h-[85vh]"
                style={{ zIndex: 10 }}
              >
                <div className="flex justify-center pt-4 pb-2 shrink-0 cursor-grab active:cursor-grabbing">
                  <div className="w-12 h-1.5 rounded-full bg-gray-300" />
                </div>
                <Drawer.Title className="font-bold text-sm text-gray-400 text-center pb-4 pointer-events-none">
                  Choose your answer
                </Drawer.Title>
                <div className="flex-1 overflow-y-auto px-5 pb-40">
                  {renderOptions(currentQuestion)}
                </div>
              </Drawer.Content>
            </Drawer.Portal>
          </Drawer.Root>
        )}
      </div>
    );

  // ─── BREAK ────────────────────────────────────────────────────────────────────
  if (phase === "BREAK")
    return (
      <div className="test-screen">
        <style>{GLOBAL_STYLES}</style>
        <BgLayer />
        <main className="relative z-10 min-h-screen flex flex-col items-center justify-center px-6 py-8">
          <span className="text-6xl mb-4 animate-bounce">🎉</span>
          <h1 className="text-4xl font-black text-[#1e1b4b] mb-2 text-center">
            You're doing <span className="text-orange-500">great!</span>
          </h1>
          <p className="text-gray-500 font-semibold mb-8">
            Take a breather — next module coming up
          </p>
          <div className="t-card p-6 mb-8 text-center min-w-[200px]">
            <p className="text-xs font-bold text-gray-400 uppercase tracking-widest mb-2">
              Next module in
            </p>
            <p className="t-timer">{formatTime(time)}</p>
          </div>
          <div className="flex gap-3 mb-8 flex-wrap justify-center">
            {["💧 Drink water", "🙆 Stretch", "😮‍💨 Breathe"].map((t) => (
              <span
                key={t}
                className="bg-white border-2 border-gray-100 rounded-full px-4 py-2 text-sm font-bold text-gray-600 shadow-sm"
              >
                {t}
              </span>
            ))}
          </div>
          <button
            onClick={() => useSatExam.getState().skipBreak()}
            className="t-btn-3d t-btn-accent px-8 py-4"
          >
            Skip Break →
          </button>
        </main>
      </div>
    );

  // ─── FINISHED ─────────────────────────────────────────────────────────────────
  if (phase === "FINISHED")
    return (
      <div className="test-screen">
        <style>{GLOBAL_STYLES}</style>
        <BgLayer />
        <main className="relative z-10 min-h-screen flex flex-col items-center justify-center px-6 py-8">
          <span className="text-6xl mb-4">⏰</span>
          <h1 className="text-4xl font-black text-[#1e1b4b] mb-2 text-center">
            Time's <span className="text-orange-500">up!</span>
          </h1>
          <p className="text-gray-500 font-semibold mb-8">
            You crushed it — let's see how you did
          </p>
          <div className="flex gap-4 mb-8 flex-wrap justify-center">
            {[
              ["✏️", "Done", "Section"],
              ["🏆", "Nice!", "Results"],
              ["🔥", "100%", "Effort"],
            ].map(([e, v, l]) => (
              <div key={l} className="t-card p-4 text-center min-w-[100px]">
                <span className="text-2xl block mb-1">{e}</span>
                <span className="font-black text-lg text-[#1e1b4b]">{v}</span>
                <span className="text-xs font-bold text-gray-400 uppercase block">
                  {l}
                </span>
              </div>
            ))}
          </div>
          <div className="flex items-center gap-3 bg-white border-2 border-gray-100 rounded-full px-6 py-3 shadow-sm">
            <Loader2 size={18} className="animate-spin text-orange-500" />
            <span className="font-bold text-gray-600">
              Redirecting to results...
            </span>
          </div>
        </main>
      </div>
    );

  if (phase === "QUIT") return <Navigate to="/student/home" replace />;
  return null;
};
