// ===== vol-lms.jsx =====
// Volunteer-side LMS — replaces window.VolTraining.
//
// Surfaces:
//   - "My learning" landing (required-now / in-progress / catalog teaser / certificates)
//   - Course catalog (filter by program, format, duration)
//   - Course detail (modules, prereqs, instructor, related)
//   - Player view (video + transcript + module sidebar)
//   - Quiz view (single-question stepper + instant feedback, end-of-quiz review)
//   - Certificate wallet (issued, expiring, downloadable)
//   - Learning history (audit-grade record of every attempt)

const {
  React,
  Card, Btn, IconBtn, StatusChip, Avatar, Kpi, Progress, Field, Input, Textarea, Select, Checkbox, Toggle, Tabs, Empty, SectionHead, TopBar,
  IconPlus, IconCheck, IconX, IconArrow, IconArrowL, IconDownload, IconUpload,
  IconBook, IconClock, IconUsers, IconAward, IconShield, IconSearch, IconFilter, IconBell,
  IconStar, IconEdit, IconExternal, IconChevron, IconChevronD, IconEye, IconMore, IconCal,
  IconClipboard,
} = window;
const { useState: useVL, useMemo: useVLM, useEffect: useVLE, useRef: useVLR } = React;

const vl_over = { fontSize: 11, letterSpacing: "0.12em", textTransform: "uppercase", color: "var(--fg-3)", fontWeight: 500 };
const vl_meta = { fontSize: 11, color: "var(--fg-3)" };

// ============================================================
// CATALOG
// ============================================================
const VOL_COURSES = [
  {
    id: "co-camp-orient", title: "Camp host orientation", program: "State parks",
    time: "45 min", modules: 6, format: "Video + quiz", thumbColor: "var(--coral-700)",
    required: true, status: "complete", completed: "Apr 14, 2026", score: 92,
    instructor: "Aliyah Chen", instrRole: "Camp host coordinator",
    desc: "What CPW camp hosts do, how reservations work, when to call your park manager, and what \"good\" looks like in your first week on site.",
    prereqs: [], cert: null,
    moduleList: [
      { id: "m1", title: "Welcome from the camp host program",   type: "video", time: 4,  done: true },
      { id: "m2", title: "A typical morning at the campground",  type: "video", time: 8,  done: true },
      { id: "m3", title: "Reservation system overview",          type: "video", time: 6,  done: true },
      { id: "m4", title: "Handling difficult guests",            type: "video", time: 7,  done: true },
      { id: "m5", title: "Reference: emergency contacts",        type: "doc",   time: 5,  done: true },
      { id: "m6", title: "Knowledge check (10 questions)",       type: "quiz",  time: 15, done: true, score: 92 },
    ],
  },
  {
    id: "co-reservation", title: "Reservation system basics", program: "State parks",
    time: "20 min", modules: 4, format: "Video + quiz", thumbColor: "var(--sage-700)",
    required: true, status: "complete", completed: "Apr 14, 2026", score: 100,
    instructor: "Devon Park", instrRole: "Park manager · Boyd Lake",
    desc: "Look up a reservation, find the right site number, walk a camper through the kiosk, and what to do if the system is down.",
    prereqs: ["co-camp-orient"], cert: null,
    moduleList: [
      { id: "m1", title: "The system at a glance",         type: "video", time: 5, done: true },
      { id: "m2", title: "Looking up a reservation",       type: "video", time: 6, done: true },
      { id: "m3", title: "When the system is down",        type: "text",  time: 4, done: true },
      { id: "m4", title: "Quiz (5 questions)",             type: "quiz",  time: 5, done: true, score: 100 },
    ],
  },
  {
    id: "co-first-aid", title: "First aid refresher", program: "All programs",
    time: "30 min", modules: 5, format: "Video + exam", thumbColor: "var(--crimson-500)",
    required: true, status: "in-progress", progress: 60, dueBy: "May 24, 2026",
    instructor: "Red Cross (external)", instrRole: "Certified instructor",
    desc: "Recertify your CPW field first aid skills. Bleeding control, CPR positioning, when to call 911 vs. radio your manager. Renewal valid 1 year.",
    prereqs: [], cert: "cert-first-aid",
    moduleList: [
      { id: "m1", title: "When to step in (and when not to)",       type: "video", time: 6, done: true },
      { id: "m2", title: "Bleeding control + tourniquets",          type: "video", time: 7, done: true },
      { id: "m3", title: "CPR positioning",                          type: "video", time: 8, done: true, current: true },
      { id: "m4", title: "Wildlife-specific scenarios",              type: "video", time: 5, done: false },
      { id: "m5", title: "Exam (20 questions · 80% to pass)",        type: "exam",  time: 15, done: false, locked: true },
    ],
  },
  {
    id: "co-wildlife", title: "Wildlife encounter protocols", program: "All programs",
    time: "15 min", modules: 4, format: "Video + quiz", thumbColor: "var(--sage-500)",
    required: false, status: "not-started",
    instructor: "Marcus Chen", instrRole: "Regional coordinator",
    desc: "Bears, mountain lions, snakes, moose. The standing protocol for each, who to radio, and what NOT to do for a photo.",
    prereqs: [], cert: null,
    moduleList: [
      { id: "m1", title: "Bear protocol",                  type: "video", time: 5, done: false },
      { id: "m2", title: "Mountain lion encounters",       type: "video", time: 4, done: false },
      { id: "m3", title: "Snakes and moose",               type: "video", time: 3, done: false },
      { id: "m4", title: "Knowledge check (5 questions)",  type: "quiz",  time: 5, done: false },
    ],
  },
  {
    id: "co-trail-101", title: "Trail building 101", program: "State parks",
    time: "45 min", modules: 5, format: "Video", thumbColor: "var(--amber-600)",
    required: false, status: "not-started",
    instructor: "Priya Sandoval", instrRole: "Regional coordinator · NE",
    desc: "How CPW maintains 1,000+ miles of trail. Drainage, tread, sustainability — and how to think about a piece of trail as a small piece of a larger system.",
    prereqs: [], cert: null,
    moduleList: [
      { id: "m1", title: "What trails do (more than you'd think)", type: "video", time: 8, done: false },
      { id: "m2", title: "Reading water on the land",              type: "video", time: 12, done: false },
      { id: "m3", title: "Tread, slope, and outsloping",            type: "video", time: 10, done: false },
      { id: "m4", title: "Common mistakes",                          type: "video", time: 8, done: false },
      { id: "m5", title: "Discussion + reflection prompts",          type: "text",  time: 7, done: false },
    ],
  },
  {
    id: "co-naturalist", title: "Wildlife identification: birds", program: "Education",
    time: "30 min", modules: 4, format: "Interactive", thumbColor: "var(--iris-600)",
    required: false, status: "not-started",
    instructor: "Audubon Colorado (external)", instrRole: "Partner",
    desc: "Common Colorado birds, by song and sight. Built with Audubon Colorado.",
    prereqs: [], cert: null,
    moduleList: [
      { id: "m1", title: "Five birds you'll see this week", type: "video", time: 7, done: false },
      { id: "m2", title: "By song",                          type: "interactive", time: 12, done: false },
      { id: "m3", title: "By silhouette",                    type: "interactive", time: 8, done: false },
      { id: "m4", title: "Quiz",                              type: "quiz",  time: 5, done: false },
    ],
  },
  {
    id: "co-lnt", title: "Leave No Trace for volunteers", program: "All programs",
    time: "20 min", modules: 3, format: "Video", thumbColor: "var(--stone-700)",
    required: false, status: "not-started",
    instructor: "Leave No Trace (external)", instrRole: "Partner",
    desc: "What we teach visitors. Useful to know yourself.",
    prereqs: [], cert: null,
    moduleList: [
      { id: "m1", title: "The seven principles",  type: "video", time: 12, done: false },
      { id: "m2", title: "Apply to a CPW site",   type: "text",  time: 5, done: false },
      { id: "m3", title: "Quiz",                   type: "quiz",  time: 3, done: false },
    ],
  },
];

const VOL_CERTS = [
  {
    id: "cert-camp-host", name: "Camp host certified",
    issued: "Apr 14, 2026", expires: "—", course: "co-camp-orient",
    status: "active", issuer: "Colorado Parks & Wildlife",
  },
  {
    id: "cert-first-aid-prev", name: "First aid / CPR (Red Cross)",
    issued: "May 12, 2024", expires: "May 12, 2026", course: "co-first-aid",
    status: "expiring", issuer: "American Red Cross",
  },
];

// ============================================================
// ROOT
// ============================================================
const VolTraining = ({ go }) => {
  const [view, setView] = useVL("home"); // home | catalog | detail | player | quiz | certs | history
  const [activeCourseId, setActiveCourseId] = useVL(null);
  const [activeModuleId, setActiveModuleId] = useVL(null);

  const openCourse = (id) => { setActiveCourseId(id); setView("detail"); };
  const openPlayer = (courseId, moduleId) => {
    setActiveCourseId(courseId);
    setActiveModuleId(moduleId);
    const mod = VOL_COURSES.find(c => c.id === courseId)?.moduleList.find(m => m.id === moduleId);
    setView(mod?.type === "quiz" || mod?.type === "exam" ? "quiz" : "player");
  };

  const course = VOL_COURSES.find(c => c.id === activeCourseId);

  if (view === "player" && course) return <PlayerView course={course} activeModuleId={activeModuleId} setActiveModuleId={setActiveModuleId} onBack={() => setView("detail")} onNextModule={(mid) => openPlayer(course.id, mid)} />;
  if (view === "quiz" && course)   return <QuizView course={course} activeModuleId={activeModuleId} onBack={() => setView("detail")} onComplete={() => setView("detail")} />;

  return (
    <>
      {view === "home"    && <Home    setView={setView} openCourse={openCourse} openPlayer={openPlayer} />}
      {view === "catalog" && <Catalog setView={setView} openCourse={openCourse} />}
      {view === "detail" && course && <CourseDetail course={course} onBack={() => setView("home")} openPlayer={openPlayer} setView={setView} />}
      {view === "certs"   && <Certs   setView={setView} />}
      {view === "history" && <History setView={setView} openCourse={openCourse} />}
    </>
  );
};

// ============================================================
// HOME
// ============================================================
const Home = ({ setView, openCourse, openPlayer }) => {
  const required = VOL_COURSES.filter(c => c.required);
  const inProgress = VOL_COURSES.filter(c => c.status === "in-progress");
  const recommended = VOL_COURSES.filter(c => !c.required && c.status === "not-started").slice(0, 3);

  return (
    <>
      <TopBar
        title="Your learning"
        subtitle={`${VOL_COURSES.filter(c => c.status === "complete").length} courses complete · 1 due before next shift · ${VOL_CERTS.length} certifications`}
        secondary={<Btn kind="secondary" icon={IconAward} onClick={() => setView("certs")}>Certificates</Btn>} />
      <div style={{ flex: 1, overflow: "auto", padding: "20px 32px 56px" }}>
        {inProgress.length > 0 && (
          <>
            <SectionHead title="Pick up where you left off" />
            {inProgress.map(c => <PickUpCard key={c.id} c={c} openPlayer={openPlayer} openCourse={openCourse} />)}
          </>
        )}

        <SectionHead title="Required for your active roles" action={<button onClick={() => setView("history")} style={{ background: "none", border: "none", color: "var(--coral-700)", fontSize: 12, fontWeight: 500, cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 4 }}>Learning history <IconArrow size={12} /></button>} />
        <Card padded={false} style={{ marginBottom: 24 }}>
          {required.map((c, i, arr) => (
            <RequiredRow key={c.id} c={c} last={i === arr.length - 1} onOpen={() => openCourse(c.id)} />
          ))}
        </Card>

        <SectionHead title="Recommended for you" action={<button onClick={() => setView("catalog")} style={{ background: "none", border: "none", color: "var(--coral-700)", fontSize: 12, fontWeight: 500, cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 4 }}>Browse catalog <IconArrow size={12} /></button>} />
        <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 14, marginBottom: 24 }}>
          {recommended.map(c => <CourseCard key={c.id} c={c} onOpen={() => openCourse(c.id)} />)}
        </div>

        <Card>
          <div style={{ display: "grid", gridTemplateColumns: "minmax(0, 1fr) auto", gap: 18, alignItems: "center" }}>
            <div>
              <div style={{ ...vl_over, marginBottom: 6 }}>Certifications</div>
              <div style={{ fontSize: 17, fontWeight: 500, color: "var(--ink)", marginBottom: 4 }}>1 active · 1 expiring in 14 days</div>
              <div style={{ fontSize: 13, color: "var(--fg-2)" }}>Your First aid certification expires May 24. Complete the refresher to renew.</div>
            </div>
            <Btn kind="secondary" iconRight={IconArrow} onClick={() => setView("certs")}>Open wallet</Btn>
          </div>
        </Card>
      </div>
    </>
  );
};

const PickUpCard = ({ c, openPlayer, openCourse }) => {
  const nextMod = c.moduleList.find(m => m.current) || c.moduleList.find(m => !m.done);
  return (
    <Card style={{ background: "var(--ink)", color: "var(--paper)", border: "none", marginBottom: 22 }}>
      <div style={{ display: "grid", gridTemplateColumns: "minmax(0, 1.4fr) auto", gap: 18, alignItems: "center" }}>
        <div>
          <div style={{ fontSize: 10, letterSpacing: "0.12em", textTransform: "uppercase", opacity: 0.75, marginBottom: 6 }}>In progress · {c.progress}% complete</div>
          <div style={{ fontFamily: "var(--font-display)", fontSize: 26, lineHeight: 1.15, marginBottom: 6 }}>{c.title}</div>
          <div style={{ fontSize: 13, opacity: 0.85, marginBottom: 14 }}>Next: {nextMod?.title} · {nextMod?.time} min</div>
          <div style={{ height: 5, background: "rgba(255,255,255,0.2)", borderRadius: 999, marginBottom: 14 }}>
            <div style={{ height: "100%", width: `${c.progress}%`, background: "var(--coral-500)", borderRadius: 999 }} />
          </div>
          <div style={{ display: "flex", gap: 8 }}>
            <Btn icon={IconArrow} onClick={() => openPlayer(c.id, nextMod?.id)}>Resume</Btn>
            <Btn kind="ghost" onClick={() => openCourse(c.id)} style={{ color: "var(--paper)" }}>Course outline</Btn>
          </div>
        </div>
        <div style={{ width: 120, height: 120, borderRadius: 12, background: c.thumbColor, display: "flex", alignItems: "center", justifyContent: "center" }}>
          <IconBook size={36} style={{ color: "rgba(255,255,255,0.6)" }} />
        </div>
      </div>
    </Card>
  );
};

const RequiredRow = ({ c, last, onOpen }) => {
  const isComplete = c.status === "complete";
  const isInProgress = c.status === "in-progress";
  return (
    <div onClick={onOpen} style={{
      display: "grid", gridTemplateColumns: "auto 1fr auto auto auto", gap: 14, padding: "14px 18px", alignItems: "center",
      borderBottom: last ? "none" : "1px solid var(--border-soft)", cursor: "pointer",
    }}>
      <div style={{ width: 32, height: 32, borderRadius: 8, background: isComplete ? "var(--sage-100)" : isInProgress ? "var(--coral-100)" : "var(--paper-deep)", color: isComplete ? "var(--sage-700)" : isInProgress ? "var(--coral-700)" : "var(--fg-3)", display: "flex", alignItems: "center", justifyContent: "center" }}>
        {isComplete ? <IconCheck size={14} /> : <IconBook size={14} />}
      </div>
      <div>
        <div style={{ fontSize: 14, fontWeight: 500, color: "var(--ink)" }}>{c.title}</div>
        <div style={{ ...vl_meta, marginTop: 3 }}>
          {isComplete ? `Completed ${c.completed} · score ${c.score}` :
           isInProgress ? `${c.progress}% · Due ${c.dueBy}` :
           `${c.time} · ${c.modules} modules`}
        </div>
      </div>
      {isInProgress && <div style={{ width: 120 }}><Progress value={c.progress} max={100} /></div>}
      {isComplete && <span style={{ fontSize: 11, color: "var(--sage-700)", fontWeight: 500 }}>Score: {c.score}%</span>}
      <span style={{ fontSize: 11, color: "var(--fg-3)" }}>Required</span>
      <Btn size="sm" kind={isComplete ? "secondary" : "primary"}>{isComplete ? "Review" : isInProgress ? "Resume" : "Start"}</Btn>
    </div>
  );
};

const CourseCard = ({ c, onOpen }) => (
  <Card padded={false} style={{ cursor: "pointer" }} onClick={onOpen}>
    <div style={{ aspectRatio: "16/9", background: c.thumbColor, position: "relative", padding: 14, display: "flex", alignItems: "flex-end" }}>
      <div style={{ color: "#fff" }}>
        <div style={{ fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", opacity: 0.85, marginBottom: 4 }}>{c.program}</div>
        <div style={{ fontFamily: "var(--font-display)", fontSize: 20, lineHeight: 1.15 }}>{c.title}</div>
      </div>
    </div>
    <div style={{ padding: 14 }}>
      <div style={{ fontSize: 12, color: "var(--fg-2)", lineHeight: 1.5, marginBottom: 10, minHeight: 36 }}>{c.desc}</div>
      <div style={{ display: "flex", gap: 10, fontSize: 11, color: "var(--fg-3)", marginBottom: 10 }}>
        <span>{c.time}</span><span>·</span><span>{c.modules} modules</span><span>·</span><span>{c.format}</span>
      </div>
      <Btn size="sm" kind="secondary" full>Open</Btn>
    </div>
  </Card>
);

// ============================================================
// CATALOG
// ============================================================
const Catalog = ({ setView, openCourse }) => {
  const [q, setQ] = useVL("");
  const [program, setProgram] = useVL("all");
  const [format, setFormat] = useVL("all");

  const filtered = VOL_COURSES.filter(c => {
    if (q && !(c.title + " " + c.desc).toLowerCase().includes(q.toLowerCase())) return false;
    if (program !== "all" && c.program !== program && c.program !== "All programs") return false;
    if (format !== "all" && !c.format.toLowerCase().includes(format)) return false;
    return true;
  });

  return (
    <>
      <TopBar title="Course catalog"
        breadcrumb={["Your learning", "Catalog"]} onBack={() => setView("home")}
        subtitle={`${VOL_COURSES.length} courses · find something to learn`} />
      <div style={{ flex: 1, overflow: "auto", padding: "20px 32px 56px" }}>
        <Card style={{ padding: 14, marginBottom: 18 }}>
          <div style={{ display: "grid", gridTemplateColumns: "minmax(180px, 1.6fr) 200px 200px auto", gap: 10, alignItems: "end" }}>
            <Field label="Search">
              <div style={{ position: "relative" }}>
                <Input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Wildlife, first aid, …" style={{ paddingLeft: 32 }} />
                <IconSearch size={14} style={{ position: "absolute", left: 12, top: 12, color: "var(--fg-3)" }} />
              </div>
            </Field>
            <Field label="Program">
              <Select value={program} onChange={(e) => setProgram(e.target.value)}
                options={[
                  { value: "all", label: "All programs" },
                  { value: "State parks", label: "State parks" },
                  { value: "Wildlife", label: "Wildlife" },
                  { value: "Education", label: "Education" },
                  { value: "Hunter Outreach", label: "Hunter Outreach" },
                ]} />
            </Field>
            <Field label="Format">
              <Select value={format} onChange={(e) => setFormat(e.target.value)}
                options={[
                  { value: "all",   label: "Any format" },
                  { value: "video", label: "Video" },
                  { value: "quiz",  label: "Quiz / exam" },
                  { value: "interactive", label: "Interactive" },
                ]} />
            </Field>
            <Btn kind="ghost" size="sm" onClick={() => { setQ(""); setProgram("all"); setFormat("all"); }}>Reset</Btn>
          </div>
        </Card>
        <div style={{ ...vl_meta, marginBottom: 10 }}>{filtered.length} of {VOL_COURSES.length} courses</div>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 14 }}>
          {filtered.map(c => <CourseCard key={c.id} c={c} onOpen={() => openCourse(c.id)} />)}
        </div>
        {filtered.length === 0 && <Empty title="No courses match" body="Try widening filters or clearing search." icon={IconBook} />}
      </div>
    </>
  );
};

// ============================================================
// COURSE DETAIL
// ============================================================
const CourseDetail = ({ course, onBack, openPlayer, setView }) => {
  const c = course;
  const isComplete = c.status === "complete";
  const isInProgress = c.status === "in-progress";
  const completedCount = c.moduleList.filter(m => m.done).length;
  const totalMins = c.moduleList.reduce((a, m) => a + m.time, 0);
  const completedMins = c.moduleList.filter(m => m.done).reduce((a, m) => a + m.time, 0);
  const nextMod = c.moduleList.find(m => m.current) || c.moduleList.find(m => !m.done);

  return (
    <>
      <TopBar title={c.title}
        breadcrumb={["Your learning", c.title]} onBack={onBack}
        subtitle={`${c.program} · ${c.time} · ${c.format} · taught by ${c.instructor}`} />
      <div style={{ flex: 1, overflow: "auto" }}>
        {/* Hero */}
        <div style={{ background: c.thumbColor, color: "#fff", padding: "32px 32px" }}>
          <div style={{ maxWidth: 960, margin: "0 auto", display: "grid", gridTemplateColumns: "minmax(0, 1.4fr) minmax(280px, 1fr)", gap: 30, alignItems: "center" }}>
            <div>
              <div style={{ fontSize: 11, letterSpacing: "0.14em", textTransform: "uppercase", opacity: 0.85, marginBottom: 10 }}>{c.program}{c.required ? " · required" : ""}</div>
              <div style={{ fontFamily: "var(--font-display)", fontSize: 36, lineHeight: 1.1, marginBottom: 14 }}>{c.title}</div>
              <div style={{ fontSize: 15, lineHeight: 1.55, opacity: 0.9, maxWidth: 540 }}>{c.desc}</div>
              <div style={{ display: "flex", gap: 8, marginTop: 22 }}>
                {isComplete
                  ? <Btn kind="secondary" icon={IconCheck} onClick={() => openPlayer(c.id, c.moduleList[0].id)}>Review course</Btn>
                  : isInProgress
                  ? <Btn icon={IconArrow} onClick={() => openPlayer(c.id, nextMod.id)}>Resume — {nextMod.title}</Btn>
                  : <Btn icon={IconArrow} onClick={() => openPlayer(c.id, c.moduleList[0].id)}>Start course</Btn>}
                <Btn kind="ghost" style={{ color: "#fff" }}>Save for later</Btn>
              </div>
            </div>
            <Card style={{ background: "rgba(0,0,0,0.25)", border: "1px solid rgba(255,255,255,0.2)", color: "#fff" }}>
              <div style={{ ...vl_over, color: "rgba(255,255,255,0.8)", marginBottom: 12 }}>Your progress</div>
              <div style={{ fontFamily: "var(--font-display)", fontSize: 38, lineHeight: 1, marginBottom: 6 }}>{isComplete ? "100" : (c.progress || 0)}<span style={{ fontSize: 14, opacity: 0.7 }}>%</span></div>
              <div style={{ fontSize: 12, opacity: 0.85, marginBottom: 16 }}>{completedCount} of {c.moduleList.length} modules · {completedMins} of {totalMins} min</div>
              {c.dueBy && <div style={{ fontSize: 12, opacity: 0.85, marginBottom: 8 }}>Due {c.dueBy}</div>}
              {isComplete && <div style={{ fontSize: 12, opacity: 0.85 }}>Completed {c.completed} · score {c.score}%</div>}
            </Card>
          </div>
        </div>

        {/* Body */}
        <div style={{ maxWidth: 960, margin: "0 auto", padding: "32px 32px 64px", display: "grid", gridTemplateColumns: "minmax(0, 1.4fr) minmax(280px, 1fr)", gap: 28 }}>
          <div>
            <SectionHead title="Modules" />
            <Card padded={false}>
              {c.moduleList.map((m, i, arr) => (
                <ModuleRow key={m.id} m={m} num={i + 1} last={i === arr.length - 1}
                  onOpen={() => !m.locked && openPlayer(c.id, m.id)} />
              ))}
            </Card>

            <SectionHead title="What you'll learn" />
            <Card>
              <ul style={{ margin: 0, paddingLeft: 18, fontSize: 14, color: "var(--fg-1)", lineHeight: 1.7 }}>
                <li>The standing protocol for each common encounter</li>
                <li>When to use the radio vs. when to step back</li>
                <li>How to keep yourself, the wildlife, and visitors safe</li>
                <li>Where to find the field reference card after the course</li>
              </ul>
            </Card>

            {c.prereqs.length > 0 && (
              <>
                <SectionHead title="Prerequisites" />
                <Card padded={false}>
                  {c.prereqs.map(pid => {
                    const p = VOL_COURSES.find(x => x.id === pid);
                    if (!p) return null;
                    return (
                      <div key={pid} style={{ display: "flex", gap: 12, padding: "12px 16px", alignItems: "center", borderBottom: "1px solid var(--border-soft)" }}>
                        <div style={{ width: 28, height: 28, borderRadius: 6, background: "var(--sage-100)", color: "var(--sage-700)", display: "flex", alignItems: "center", justifyContent: "center" }}><IconCheck size={14} /></div>
                        <div style={{ flex: 1 }}>
                          <div style={{ fontSize: 13, fontWeight: 500 }}>{p.title}</div>
                          <div style={{ ...vl_meta, marginTop: 2 }}>Completed</div>
                        </div>
                      </div>
                    );
                  })}
                </Card>
              </>
            )}
          </div>

          <div style={{ display: "flex", flexDirection: "column", gap: 18 }}>
            <Card>
              <div style={{ ...vl_over, marginBottom: 12 }}>Instructor</div>
              <div style={{ display: "flex", gap: 12, alignItems: "center" }}>
                <div style={{ width: 44, height: 44, borderRadius: 999, background: "var(--coral-100)", color: "var(--coral-700)", display: "flex", alignItems: "center", justifyContent: "center", fontWeight: 600 }}>
                  {c.instructor.split(" ").map(w => w[0]).join("").slice(0, 2).toUpperCase()}
                </div>
                <div>
                  <div style={{ fontSize: 14, fontWeight: 500 }}>{c.instructor}</div>
                  <div style={{ ...vl_meta, marginTop: 2 }}>{c.instrRole}</div>
                </div>
              </div>
            </Card>

            <Card>
              <div style={{ ...vl_over, marginBottom: 12 }}>Issues a certification</div>
              {c.cert ? (
                <>
                  <div style={{ display: "flex", gap: 8, alignItems: "center", marginBottom: 8 }}>
                    <div style={{ width: 32, height: 32, borderRadius: 8, background: "var(--amber-100)", color: "var(--amber-600)", display: "flex", alignItems: "center", justifyContent: "center" }}><IconAward size={16} /></div>
                    <div style={{ fontSize: 13, fontWeight: 500 }}>First aid / CPR · 1-year validity</div>
                  </div>
                  <div style={{ fontSize: 12, color: "var(--fg-2)", lineHeight: 1.5 }}>Passing this course renews your active CPW first-aid certification for one year.</div>
                </>
              ) : (
                <div style={{ fontSize: 12, color: "var(--fg-3)" }}>No formal certification for this course.</div>
              )}
            </Card>

            <Card>
              <div style={{ ...vl_over, marginBottom: 12 }}>Recommended next</div>
              {VOL_COURSES.filter(x => x.id !== c.id).slice(0, 3).map(x => (
                <div key={x.id} style={{ display: "flex", gap: 10, alignItems: "center", padding: "8px 0", borderTop: "1px dashed var(--border-soft)", cursor: "pointer" }} onClick={() => setView("detail")}>
                  <div style={{ width: 36, height: 36, borderRadius: 6, background: x.thumbColor, flexShrink: 0 }} />
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 13, fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{x.title}</div>
                    <div style={{ ...vl_meta }}>{x.time} · {x.program}</div>
                  </div>
                </div>
              ))}
            </Card>
          </div>
        </div>
      </div>
    </>
  );
};

const ModuleRow = ({ m, num, last, onOpen }) => {
  const icon = m.type === "video" ? <IconEye size={13} /> :
               m.type === "quiz"  ? <IconClipboard size={13} /> :
               m.type === "exam"  ? <IconShield size={13} /> :
               m.type === "interactive" ? <IconStar size={13} /> :
               <IconBook size={13} />;
  return (
    <div onClick={!m.locked ? onOpen : null} style={{
      display: "grid", gridTemplateColumns: "30px 32px 1fr 80px 36px 90px", gap: 12, padding: "12px 16px", alignItems: "center",
      borderBottom: last ? "none" : "1px solid var(--border-soft)",
      background: m.current ? "var(--coral-50)" : "transparent",
      cursor: m.locked ? "not-allowed" : "pointer",
      opacity: m.locked ? 0.55 : 1,
    }}>
      <span style={{ fontFamily: "var(--font-display)", fontSize: 16, color: "var(--fg-3)", fontVariantNumeric: "tabular-nums" }}>{num}</span>
      <div style={{ width: 28, height: 28, borderRadius: 6, background: m.done ? "var(--sage-100)" : "var(--paper-deep)", color: m.done ? "var(--sage-700)" : "var(--fg-2)", display: "flex", alignItems: "center", justifyContent: "center" }}>
        {m.done ? <IconCheck size={13} /> : icon}
      </div>
      <div>
        <div style={{ fontSize: 13, fontWeight: 500, color: "var(--ink)" }}>{m.title}</div>
        <div style={{ ...vl_meta, marginTop: 2, textTransform: "capitalize" }}>{m.type}{m.score != null ? ` · score ${m.score}%` : ""}{m.locked ? " · prerequisite required" : ""}</div>
      </div>
      <span style={{ ...vl_meta }}>{m.time} min</span>
      <span>{m.current && <span style={{ fontSize: 10, padding: "2px 7px", borderRadius: 4, background: "var(--coral-100)", color: "var(--coral-700)", fontWeight: 500 }}>NOW</span>}</span>
      <Btn size="sm" kind={m.done ? "ghost" : "secondary"} disabled={m.locked}>{m.done ? "Review" : m.current ? "Resume" : "Start"}</Btn>
    </div>
  );
};

// ============================================================
// PLAYER VIEW
// ============================================================
const PlayerView = ({ course, activeModuleId, setActiveModuleId, onBack, onNextModule }) => {
  const mod = course.moduleList.find(m => m.id === activeModuleId) || course.moduleList[0];
  const idx = course.moduleList.findIndex(m => m.id === mod.id);
  const next = course.moduleList[idx + 1];
  const prev = course.moduleList[idx - 1];
  const [progress, setProgress] = useVL(mod.done ? 100 : 32);
  const [playing, setPlaying] = useVL(false);

  useVLE(() => {
    setProgress(mod.done ? 100 : 32);
    setPlaying(false);
  }, [mod.id]);

  useVLE(() => {
    if (!playing) return;
    const i = setInterval(() => setProgress(p => Math.min(100, p + 1.5)), 300);
    return () => clearInterval(i);
  }, [playing]);

  return (
    <>
      <TopBar title={course.title}
        breadcrumb={["Your learning", course.title, mod.title]} onBack={onBack}
        subtitle={`Module ${idx + 1} of ${course.moduleList.length} · ${mod.time} min`}
        secondary={<Btn kind="ghost" icon={IconClock}>Save & exit</Btn>} />
      <div style={{ flex: 1, display: "grid", gridTemplateColumns: "1fr 320px", gap: 0, minHeight: 0, borderTop: "1px solid var(--border-soft)" }}>
        {/* Main */}
        <div style={{ overflow: "auto", padding: "20px 32px 32px" }}>
          {/* Video player */}
          <div style={{ background: "var(--ink)", borderRadius: 12, overflow: "hidden", marginBottom: 18, aspectRatio: "16/9", position: "relative", display: "flex", alignItems: "center", justifyContent: "center" }}>
            {/* Placeholder thumbnail */}
            <div style={{ position: "absolute", inset: 0, background: course.thumbColor, opacity: playing ? 0.3 : 0.6 }} />
            {/* Title overlay */}
            <div style={{ position: "absolute", top: 20, left: 24, color: "rgba(255,255,255,0.8)", fontSize: 12, letterSpacing: "0.12em", textTransform: "uppercase" }}>{course.title}</div>
            <div style={{ position: "absolute", top: 44, left: 24, right: 24, color: "#FFFFFF", fontFamily: "var(--font-display)", fontSize: 28, lineHeight: 1.2 }}>{mod.title}</div>
            {/* Play button */}
            <button onClick={() => setPlaying(p => !p)} style={{
              position: "absolute", width: 80, height: 80, borderRadius: 999, background: "rgba(255,255,255,0.95)", color: "var(--ink)",
              border: "none", display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer",
            }}>
              {playing
                ? <div style={{ display: "flex", gap: 4 }}><div style={{ width: 6, height: 24, background: "var(--ink)", borderRadius: 1 }} /><div style={{ width: 6, height: 24, background: "var(--ink)", borderRadius: 1 }} /></div>
                : <div style={{ width: 0, height: 0, borderTop: "12px solid transparent", borderBottom: "12px solid transparent", borderLeft: "20px solid var(--ink)", marginLeft: 6 }} />}
            </button>
            {/* Controls bar */}
            <div style={{ position: "absolute", bottom: 0, left: 0, right: 0, padding: 12, background: "linear-gradient(180deg, transparent, rgba(0,0,0,0.6))", display: "flex", flexDirection: "column", gap: 8 }}>
              <div style={{ height: 4, background: "rgba(255,255,255,0.2)", borderRadius: 2, position: "relative" }}>
                <div style={{ position: "absolute", left: 0, top: 0, bottom: 0, width: `${progress}%`, background: "var(--coral-500)", borderRadius: 2 }} />
              </div>
              <div style={{ display: "flex", alignItems: "center", gap: 10, color: "rgba(255,255,255,0.9)", fontSize: 11, fontFamily: "var(--font-mono)" }}>
                <span>{Math.floor((mod.time * 60 * progress) / 100 / 60)}:{String(Math.floor((mod.time * 60 * progress) / 100 % 60)).padStart(2, "0")}</span>
                <span style={{ opacity: 0.6 }}>/ {mod.time}:00</span>
                <span style={{ marginLeft: "auto", display: "flex", gap: 12 }}>
                  <span>CC</span><span>1x</span><span>HD</span>
                </span>
              </div>
            </div>
          </div>

          {/* Tabs under video */}
          <div style={{ display: "flex", gap: 18, borderBottom: "1px solid var(--border)", marginBottom: 18 }}>
            {["Notes", "Transcript", "Resources", "Discussion"].map((t, i) => (
              <button key={t} style={{
                background: "transparent", border: "none", padding: "10px 0", fontSize: 13, fontWeight: 500,
                color: i === 1 ? "var(--ink)" : "var(--fg-2)", cursor: "pointer", fontFamily: "inherit",
                borderBottom: i === 1 ? "2px solid var(--coral-600)" : "2px solid transparent",
                marginBottom: -1,
              }}>{t}</button>
            ))}
          </div>

          {/* Transcript */}
          <div style={{ fontSize: 14, lineHeight: 1.7, color: "var(--fg-1)", maxWidth: 720 }}>
            <p style={{ marginTop: 0 }}><span style={{ fontFamily: "var(--font-mono)", color: "var(--fg-3)", fontSize: 11, marginRight: 8 }}>00:00</span>Welcome back. In this module we're going to walk through the standing CPR position — both for an adult on flat ground and for the situations you're more likely to see in our parks. A volunteer on a trail. A camper in a tent.</p>
            <p><span style={{ fontFamily: "var(--font-mono)", color: "var(--fg-3)", fontSize: 11, marginRight: 8 }}>00:42</span>The most important thing to remember is that <em>any</em> compression is better than none, even if your form isn't perfect. We see volunteers freeze up because they're worried about doing it wrong. The textbook answer doesn't matter if no one acts.</p>
            <p><span style={{ fontFamily: "var(--font-mono)", color: "var(--fg-3)", fontSize: 11, marginRight: 8 }}>01:24</span>That said, here's what good form looks like. Heel of the hand on the lower half of the sternum, between the nipples on most adults. Lock your elbows. Use your body weight, not your arms…</p>
            <p style={{ color: "var(--fg-3)" }}>(transcript continues — auto-scrolls to current playback position when audio plays)</p>
          </div>

          {/* Footer nav */}
          <div style={{ display: "flex", gap: 8, marginTop: 24, padding: "16px 0", borderTop: "1px solid var(--border-soft)", alignItems: "center" }}>
            {prev && <Btn kind="ghost" icon={IconArrowL} onClick={() => onNextModule(prev.id)}>Previous · {prev.title}</Btn>}
            <div style={{ marginLeft: "auto", display: "flex", gap: 8, alignItems: "center" }}>
              <Checkbox checked={progress >= 100} onChange={() => {}} label="Mark module complete" />
              {next ? (
                <Btn icon={IconArrow} onClick={() => onNextModule(next.id)} disabled={progress < 100}>Next · {next.title}</Btn>
              ) : (
                <Btn icon={IconCheck} disabled={progress < 100}>Finish course</Btn>
              )}
            </div>
          </div>
        </div>

        {/* Sidebar — module list */}
        <div style={{ borderLeft: "1px solid var(--border-soft)", background: "var(--paper-soft)", overflow: "auto" }}>
          <div style={{ padding: "16px 16px 10px" }}>
            <div style={{ ...vl_over, marginBottom: 4 }}>{course.title}</div>
            <div style={{ fontSize: 12, color: "var(--fg-2)" }}>{course.moduleList.filter(m => m.done).length} of {course.moduleList.length} complete</div>
            <div style={{ height: 4, background: "var(--paper-deep)", borderRadius: 2, marginTop: 8 }}>
              <div style={{ width: `${(course.moduleList.filter(m => m.done).length / course.moduleList.length) * 100}%`, height: "100%", background: "var(--coral-600)", borderRadius: 2 }} />
            </div>
          </div>
          <div style={{ padding: "4px 0 18px" }}>
            {course.moduleList.map((m, i) => {
              const active = m.id === mod.id;
              return (
                <button key={m.id} onClick={() => !m.locked && setActiveModuleId(m.id)} style={{
                  display: "grid", gridTemplateColumns: "30px 30px 1fr auto", gap: 8, width: "100%",
                  padding: "10px 14px", background: active ? "var(--paper)" : "transparent",
                  borderLeft: active ? "3px solid var(--coral-600)" : "3px solid transparent",
                  border: "none", textAlign: "left", cursor: m.locked ? "not-allowed" : "pointer",
                  fontFamily: "inherit", alignItems: "center",
                  opacity: m.locked ? 0.55 : 1,
                }}>
                  <span style={{ fontFamily: "var(--font-display)", fontSize: 14, color: "var(--fg-3)" }}>{i + 1}</span>
                  <div style={{ width: 22, height: 22, borderRadius: 4, background: m.done ? "var(--sage-100)" : "var(--paper-deep)", color: m.done ? "var(--sage-700)" : "var(--fg-3)", display: "flex", alignItems: "center", justifyContent: "center" }}>
                    {m.done ? <IconCheck size={11} /> : m.type === "video" ? <IconEye size={11} /> : m.type === "quiz" || m.type === "exam" ? <IconClipboard size={11} /> : <IconBook size={11} />}
                  </div>
                  <div style={{ fontSize: 12, color: active ? "var(--ink)" : "var(--fg-1)", fontWeight: active ? 500 : 400 }}>{m.title}</div>
                  <span style={{ ...vl_meta }}>{m.time} min</span>
                </button>
              );
            })}
          </div>
        </div>
      </div>
    </>
  );
};

// ============================================================
// QUIZ VIEW
// ============================================================
const QUIZ_QUESTIONS = [
  {
    q: "When you start compressions on an adult, what's the correct hand position?",
    options: [
      "Heel of the hand on the lower half of the sternum, between the nipples",
      "Top of the chest, just below the collarbone",
      "On the stomach, just above the belly button",
      "It doesn't matter — any pressure helps",
    ],
    correct: 0,
    explanation: "Lower half of the sternum, between the nipples on most adults. Lock your elbows and use your body weight.",
  },
  {
    q: "How fast should chest compressions be?",
    options: [
      "60–80 per minute (slower is steadier)",
      "100–120 per minute (about the beat of \"Stayin' Alive\")",
      "As fast as you possibly can",
      "Match the patient's previous heart rate if you know it",
    ],
    correct: 1,
    explanation: "100–120 per minute is the AHA recommendation. \"Stayin' Alive\" is famously close to the right tempo.",
  },
  {
    q: "A volunteer on a backcountry trail is unconscious. Cell signal is weak. What's the first thing to do?",
    options: [
      "Start compressions immediately",
      "Send someone for help, then start compressions",
      "Wait until you've confirmed cell signal to call 911",
      "Check airway, breathing, and pulse before doing anything else",
    ],
    correct: 1,
    explanation: "Time is the critical resource. Send for help first (someone runs for signal or the radio), then begin compressions. Don't delay either step.",
  },
];

const QuizView = ({ course, activeModuleId, onBack, onComplete }) => {
  const mod = course.moduleList.find(m => m.id === activeModuleId);
  const [step, setStep] = useVL(0);
  const [answers, setAnswers] = useVL({});
  const [submitted, setSubmitted] = useVL(false);
  const [reviewing, setReviewing] = useVL(false);

  const total = QUIZ_QUESTIONS.length;
  const current = QUIZ_QUESTIONS[step];
  const userAnswer = answers[step];
  const correctCount = Object.entries(answers).filter(([i, a]) => QUIZ_QUESTIONS[+i].correct === a).length;
  const passingScore = Math.round((correctCount / total) * 100);
  const passed = passingScore >= 80;

  if (submitted) {
    return (
      <>
        <TopBar title={course.title}
          breadcrumb={["Your learning", course.title, mod.title]} onBack={onBack}
          subtitle={`Result · ${passed ? "Passed" : "Did not pass"}`} />
        <div style={{ flex: 1, overflow: "auto", padding: "32px 32px 56px" }}>
          <div style={{ maxWidth: 720, margin: "0 auto" }}>
            <Card>
              <div style={{ textAlign: "center", padding: "20px 0 14px" }}>
                <div style={{ width: 64, height: 64, borderRadius: 999, background: passed ? "var(--sage-100)" : "var(--amber-100)", color: passed ? "var(--sage-700)" : "var(--amber-600)", display: "flex", alignItems: "center", justifyContent: "center", margin: "0 auto 18px" }}>
                  {passed ? <IconCheck size={28} /> : <IconArrowL size={28} />}
                </div>
                <div style={{ fontFamily: "var(--font-display)", fontSize: 36, color: "var(--ink)" }}>{passingScore}%</div>
                <div style={{ fontSize: 14, color: "var(--fg-2)", marginTop: 6 }}>
                  {correctCount} of {total} correct · {passed ? "passed (80% required)" : "needs 80% to pass — review and try again"}
                </div>
              </div>
              <div style={{ display: "flex", gap: 8, justifyContent: "center", marginTop: 14 }}>
                <Btn kind="secondary" onClick={() => { setReviewing(true); setSubmitted(false); setStep(0); }}>Review answers</Btn>
                {passed
                  ? <Btn icon={IconCheck} onClick={onComplete}>Continue course</Btn>
                  : <Btn icon={IconArrow} onClick={() => { setAnswers({}); setSubmitted(false); setStep(0); }}>Retake quiz</Btn>}
              </div>
            </Card>
            {passed && mod.type === "exam" && (
              <Card style={{ marginTop: 14, background: "var(--sage-100)", color: "var(--sage-700)", border: "none" }}>
                <div style={{ display: "flex", gap: 14, alignItems: "center" }}>
                  <IconAward size={28} />
                  <div>
                    <div style={{ fontSize: 14, fontWeight: 500, color: "var(--ink)" }}>Your first aid certification is renewed.</div>
                    <div style={{ fontSize: 12, color: "var(--fg-1)", marginTop: 3 }}>Valid through May 24, 2027. Find it in your certificate wallet.</div>
                  </div>
                </div>
              </Card>
            )}
          </div>
        </div>
      </>
    );
  }

  return (
    <>
      <TopBar title={course.title}
        breadcrumb={["Your learning", course.title, mod.title]} onBack={onBack}
        subtitle={`${reviewing ? "Reviewing" : "Question"} ${step + 1} of ${total}${reviewing ? " · review mode" : ""}`} />
      <div style={{ flex: 1, overflow: "auto", padding: "32px 32px 56px" }}>
        <div style={{ maxWidth: 720, margin: "0 auto" }}>
          <div style={{ height: 4, background: "var(--paper-deep)", borderRadius: 2, marginBottom: 28 }}>
            <div style={{ width: `${((step + 1) / total) * 100}%`, height: "100%", background: "var(--coral-600)", borderRadius: 2 }} />
          </div>
          <div style={{ fontFamily: "var(--font-display)", fontSize: 26, color: "var(--ink)", lineHeight: 1.3, marginBottom: 22 }}>{current.q}</div>
          <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
            {current.options.map((opt, i) => {
              const isPicked = userAnswer === i;
              const isCorrect = current.correct === i;
              const showFeedback = reviewing && (isPicked || isCorrect);
              return (
                <button
                  key={i}
                  onClick={() => !reviewing && setAnswers({ ...answers, [step]: i })}
                  style={{
                    padding: "14px 18px", borderRadius: 12, textAlign: "left", cursor: reviewing ? "default" : "pointer",
                    background: showFeedback
                      ? isCorrect ? "var(--sage-100)" : isPicked ? "var(--crimson-100)" : "var(--paper)"
                      : isPicked ? "var(--coral-50)" : "var(--paper)",
                    border: "1px solid " + (showFeedback
                      ? isCorrect ? "var(--sage-500)" : isPicked ? "var(--crimson-500)" : "var(--border-soft)"
                      : isPicked ? "var(--coral-500)" : "var(--border-soft)"),
                    borderWidth: (isPicked || (showFeedback && isCorrect)) ? 2 : 1,
                    fontFamily: "inherit", fontSize: 14, color: "var(--ink)",
                    display: "grid", gridTemplateColumns: "28px 1fr auto", gap: 12, alignItems: "center",
                  }}
                >
                  <span style={{ width: 24, height: 24, borderRadius: 999, border: "2px solid " + (isPicked ? "var(--coral-600)" : "var(--border)"), display: "flex", alignItems: "center", justifyContent: "center" }}>
                    {isPicked && !showFeedback && <span style={{ width: 10, height: 10, borderRadius: 999, background: "var(--coral-600)" }} />}
                    {showFeedback && isCorrect && <IconCheck size={14} style={{ color: "var(--sage-700)" }} />}
                    {showFeedback && isPicked && !isCorrect && <IconX size={14} style={{ color: "var(--crimson-600)" }} />}
                  </span>
                  <span>{opt}</span>
                  {showFeedback && isCorrect && <span style={{ fontSize: 11, color: "var(--sage-700)", fontWeight: 500 }}>Correct</span>}
                  {showFeedback && isPicked && !isCorrect && <span style={{ fontSize: 11, color: "var(--crimson-600)", fontWeight: 500 }}>Your answer</span>}
                </button>
              );
            })}
          </div>

          {reviewing && (
            <div style={{ marginTop: 16, padding: 14, background: "var(--paper-deep)", borderRadius: 10, fontSize: 13, color: "var(--fg-1)", lineHeight: 1.6 }}>
              <div style={{ ...vl_over, marginBottom: 6 }}>Explanation</div>
              {current.explanation}
            </div>
          )}

          <div style={{ display: "flex", gap: 8, marginTop: 28, alignItems: "center" }}>
            {step > 0 && <Btn kind="ghost" icon={IconArrowL} onClick={() => setStep(step - 1)}>Previous</Btn>}
            <div style={{ marginLeft: "auto", display: "flex", gap: 8 }}>
              {step < total - 1 && <Btn iconRight={IconArrow} onClick={() => setStep(step + 1)} disabled={!reviewing && userAnswer == null}>Next question</Btn>}
              {step === total - 1 && !reviewing && <Btn icon={IconCheck} onClick={() => setSubmitted(true)} disabled={Object.keys(answers).length < total}>Submit quiz</Btn>}
              {reviewing && step === total - 1 && <Btn icon={IconCheck} onClick={() => setSubmitted(true)}>Done reviewing</Btn>}
            </div>
          </div>
        </div>
      </div>
    </>
  );
};

// ============================================================
// CERTIFICATES WALLET
// ============================================================
const Certs = ({ setView }) => (
  <>
    <TopBar title="Certifications"
      breadcrumb={["Your learning", "Certifications"]} onBack={() => setView("home")}
      subtitle={`${VOL_CERTS.length} certifications · 1 expiring in 14 days`} />
    <div style={{ flex: 1, overflow: "auto", padding: "20px 32px 56px" }}>
      <SectionHead title="Active certifications" />
      <div style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 14 }}>
        {VOL_CERTS.map(c => <CertCard key={c.id} c={c} />)}
      </div>

      <SectionHead title="Renewals & history" />
      <Card padded={false}>
        {[
          { name: "First aid / CPR (Red Cross)", issued: "May 12, 2022", expires: "May 12, 2024", state: "expired" },
          { name: "First aid / CPR (Red Cross)", issued: "May 14, 2020", expires: "May 12, 2022", state: "renewed" },
          { name: "Camp host orientation",       issued: "Apr 10, 2024", expires: "—",            state: "superseded" },
        ].map((h, i, arr) => (
          <div key={i} style={{ display: "grid", gridTemplateColumns: "1fr 130px 130px 110px", gap: 14, padding: "13px 18px", alignItems: "center", borderBottom: i === arr.length - 1 ? "none" : "1px solid var(--border-soft)", fontSize: 13 }}>
            <span style={{ fontWeight: 500 }}>{h.name}</span>
            <span style={{ ...vl_meta }}>Issued {h.issued}</span>
            <span style={{ ...vl_meta }}>Expired {h.expires}</span>
            <StatusChip status={h.state === "expired" ? "expired" : "draft"} size="sm" label={h.state === "expired" ? "Expired" : h.state === "renewed" ? "Renewed" : "Superseded"} />
          </div>
        ))}
      </Card>
    </div>
  </>
);

const CertCard = ({ c }) => {
  const expiring = c.status === "expiring";
  return (
    <Card style={{ overflow: "hidden", padding: 0 }}>
      <div style={{
        padding: "22px 22px 18px",
        background: expiring ? "var(--amber-100)" : "var(--sage-100)",
        borderBottom: "1px solid " + (expiring ? "var(--amber-500)" : "var(--sage-500)"),
      }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "start", marginBottom: 18 }}>
          <div style={{ width: 44, height: 44, borderRadius: 8, background: "rgba(0,0,0,0.06)", display: "flex", alignItems: "center", justifyContent: "center", color: expiring ? "var(--amber-600)" : "var(--sage-700)" }}>
            <IconAward size={20} />
          </div>
          {expiring && <StatusChip status="info" size="sm" label="Expiring · 14 days" />}
        </div>
        <div style={{ fontFamily: "var(--font-display)", fontSize: 22, color: "var(--ink)", lineHeight: 1.2 }}>{c.name}</div>
        <div style={{ ...vl_meta, marginTop: 6 }}>Issued by {c.issuer}</div>
      </div>
      <div style={{ padding: "16px 22px 18px", display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
        <div>
          <div style={{ ...vl_over, marginBottom: 4 }}>Issued</div>
          <div style={{ fontSize: 13, color: "var(--ink)" }}>{c.issued}</div>
        </div>
        <div>
          <div style={{ ...vl_over, marginBottom: 4 }}>Expires</div>
          <div style={{ fontSize: 13, color: expiring ? "var(--amber-600)" : "var(--ink)" }}>{c.expires}</div>
        </div>
      </div>
      <div style={{ padding: "0 22px 18px", display: "flex", gap: 6 }}>
        <Btn size="sm" kind="secondary" icon={IconDownload}>PDF</Btn>
        {expiring
          ? <Btn size="sm" icon={IconArrow}>Renew now</Btn>
          : <Btn size="sm" kind="ghost" icon={IconExternal}>Verify</Btn>}
      </div>
    </Card>
  );
};

// ============================================================
// LEARNING HISTORY
// ============================================================
const History = ({ setView, openCourse }) => (
  <>
    <TopBar title="Learning history"
      breadcrumb={["Your learning", "History"]} onBack={() => setView("home")}
      subtitle="Every course you've started or completed · downloadable for your records" />
    <div style={{ flex: 1, overflow: "auto", padding: "20px 32px 56px" }}>
      <div style={{ display: "flex", gap: 8, marginBottom: 18, alignItems: "center" }}>
        <Btn size="sm" kind="ghost">All time</Btn>
        <Btn size="sm" kind="ghost">2026 only</Btn>
        <div style={{ marginLeft: "auto" }}><Btn size="sm" kind="secondary" icon={IconDownload}>Export</Btn></div>
      </div>
      <Card padded={false}>
        <div style={{ display: "grid", gridTemplateColumns: "minmax(220px, 1.6fr) 110px 130px 130px 110px 36px", gap: 14, padding: "12px 18px", fontSize: 11, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--fg-3)", borderBottom: "1px solid var(--border)" }}>
          <span>Course</span><span>Program</span><span>Started</span><span>Completed</span><span>Score</span><span />
        </div>
        {[
          ...VOL_COURSES.filter(c => c.status === "complete").map(c => ({ ...c, started: "Apr 14, 2026" })),
          { id: "co-first-aid-2024", title: "First aid refresher (2024)", program: "All programs", started: "May 8, 2024",  completed: "May 12, 2024", score: 88, status: "complete" },
          { id: "co-camp-orient-2024", title: "Camp host orientation (2024)", program: "State parks", started: "Apr 5, 2024", completed: "Apr 10, 2024", score: 84, status: "complete" },
          { id: "co-natu-attempt", title: "Wildlife identification: birds", program: "Education", started: "Feb 14, 2026", completed: null, score: null, status: "dropped" },
        ].map((h, i, arr) => (
          <div key={i} style={{ display: "grid", gridTemplateColumns: "minmax(220px, 1.6fr) 110px 130px 130px 110px 36px", gap: 14, padding: "13px 18px", alignItems: "center", borderBottom: i === arr.length - 1 ? "none" : "1px solid var(--border-soft)", fontSize: 13 }}>
            <span style={{ fontWeight: 500, cursor: "pointer" }} onClick={() => openCourse(h.id)}>{h.title}</span>
            <span style={{ ...vl_meta }}>{h.program}</span>
            <span style={{ ...vl_meta }}>{h.started}</span>
            <span style={{ ...vl_meta }}>{h.completed || "—"}</span>
            {h.status === "complete" ? <span style={{ fontSize: 13, color: "var(--ink)" }}>{h.score}%</span> : <StatusChip status="draft" size="sm" label="Dropped" />}
            <IconBtn icon={IconExternal} size={28} />
          </div>
        ))}
      </Card>
    </div>
  </>
);

// ============================================================
Object.assign(window, { VolTraining });
