// ─────────────────────────────────────────────────────────
// ChefVerse · Training player (video + transcript + chapters + notes)
// ─────────────────────────────────────────────────────────
const { useState: useStatePl, useEffect: useEffectPl, useRef: useRefPl } = React;

function fmtTime(s) {
  const m = Math.floor(s / 60);
  const ss = String(Math.floor(s % 60)).padStart(2, "0");
  return `${m}:${ss}`;
}

function Player({ locale, courseId, moduleIdx, onBack, onOpenBriefs, onOpenModule, profile, lessonMode }) {
  // lessonMode (optional): { title:{locale}, intro:{locale}, backLabel, onComplete }
  // When present, the player is driven by a curriculum video lesson: it shows the
  // lesson's title/intro, a custom back target, and fires onComplete instead of
  // auto-advancing through courses. All video mechanics (chapters, scrubber ticks,
  // animation, resources, notes) are unchanged.
  const v2 = true;
  const t = window.I18N[locale];
  const tp = t.player;
  const course = window.COURSES.find(c => c.id === courseId) || window.COURSES[0];
  const courseModules = (window.COURSE_MODULES_BY_ID && window.COURSE_MODULES_BY_ID[course.id]) || [];
  const progress = window.useCourseProgress();
  const activeIdx = (moduleIdx == null) ? progress.firstUnlockedUnfinished(course.id) : moduleIdx;
  const courseMod = courseModules[activeIdx] || null;
  const ms = window.MOD_STRINGS ? window.MOD_STRINGS[locale] : null;
  const moduleStatus = progress.moduleStatus(course.id, activeIdx);
  const moduleLocked = moduleStatus === "locked";
  // The full demo video data (transcript, chapters) only exists for one module.
  // For any other module we re-use it as the playable content but keep the surrounding
  // chrome (title, breadcrumb, up-next) tied to the user's selected module.
  // CRITICAL: chapter count must match progress.chapterCount(courseId, moduleIdx)
  // so the auto-complete loop and the store stay in sync.
  const storeChapterCount = progress.chapterCount(course.id, activeIdx);
  const baseChapters = window.ACTIVE_MODULE.chapters; // 6 entries
  const baseDuration = window.ACTIVE_MODULE.duration;
  // Map the store's chapter count onto a chapter list of that length.
  // Always span the full duration evenly so 90% auto-complete maths works.
  const playerChapters = (() => {
    if (storeChapterCount === baseChapters.length) {
      return baseChapters;
    }
    // Synthesize an N-chapter timeline using existing labels where we can,
    // and divide the duration evenly across N slots.
    const slot = baseDuration / storeChapterCount;
    return Array.from({ length: storeChapterCount }, (_, i) => {
      // Pull the closest available source label so chapter titles still feel real
      const srcIdx = Math.min(baseChapters.length - 1, Math.floor(i * baseChapters.length / storeChapterCount));
      const src = baseChapters[srcIdx];
      return { t: i * slot, en: src.en, de: src.de, id: src.id };
    });
  })();
  const mod = {
    ...window.ACTIVE_MODULE,
    chapters: playerChapters,
    index: activeIdx,
    total: courseModules.length || window.ACTIVE_MODULE.total,
    title: lessonMode ? lessonMode.title : (courseMod ? courseMod.title : window.ACTIVE_MODULE.title),
  };
  const chapterCount = mod.chapters.length;
  const transcriptForLocale = mod.transcript[locale] || mod.transcript.en;
  const upNext = activeIdx + 1 < courseModules.length ? courseModules[activeIdx + 1] : null;
  const upNextStatus = upNext ? progress.moduleStatus(course.id, activeIdx + 1) : null;

  // Resume position: start of the first unfinished chapter
  const resumeChapterIdx = useStatePl(() => {
    for (let i = 0; i < chapterCount; i++) {
      if (!progress.isChapterDone(course.id, activeIdx, i)) return i;
    }
    return Math.max(0, chapterCount - 1);
  })[0];
  const initialTime = mod.chapters[resumeChapterIdx]?.t ?? 0;

  const [playing, setPlaying] = useStatePl(true);
  const [mobileSettingsOpen, setMobileSettingsOpen] = useStatePl(false);
  const [isFullscreen, setIsFullscreen] = useStatePl(false);
  const videoFrameRef = useRefPl(null);
  const toggleFullscreen = () => {
    const el = videoFrameRef.current;
    if (!el) return;
    if (!document.fullscreenElement) {
      const req = el.requestFullscreen || el.webkitRequestFullscreen || el.msRequestFullscreen;
      if (req) req.call(el).catch(() => {});
    } else {
      const exit = document.exitFullscreen || document.webkitExitFullscreen || document.msExitFullscreen;
      if (exit) exit.call(document).catch(() => {});
    }
  };
  useEffectPl(() => {
    const onFsChange = () => setIsFullscreen(!!document.fullscreenElement);
    document.addEventListener("fullscreenchange", onFsChange);
    document.addEventListener("webkitfullscreenchange", onFsChange);
    return () => {
      document.removeEventListener("fullscreenchange", onFsChange);
      document.removeEventListener("webkitfullscreenchange", onFsChange);
    };
  }, []);
  const [time, setTime] = useStatePl(initialTime);
  const [tab, setTab] = useStatePl(() => {
    try {
      const d = window.__CV_DEEPLINK;
      if (d && d.tab && ["chapters", "notes", "transcript"].includes(d.tab)) return d.tab;
    } catch (e) {}
    return "chapters";
  });
  // Deep-link: scroll to a named section (#module-player/apply | /resources) once
  // the player has rendered. Consumes and clears the one-shot deep-link signal.
  useEffectPl(() => {
    let d = null;
    try { d = window.__CV_DEEPLINK; } catch (e) {}
    if (!d || !d.section) return;
    const sel = d.section;
    const id = setTimeout(() => {
      const el = document.querySelector('[data-anchor="' + sel + '"]');
      if (el) el.scrollIntoView({ behavior: "smooth", block: "center" });
      try { window.__CV_DEEPLINK = { tab: null, section: null }; } catch (e) {}
    }, 120);
    return () => clearTimeout(id);
  }, []);
  const [captionLocale, setCaptionLocale] = useStatePl(locale);
  const [speed, setSpeed] = useStatePl(1);
  const [notes, setNotes] = useStatePl([
    { t: 56, text: locale === "de" ? "Wichtig: Tellerrand-Höhe für Side-Light." : locale === "id" ? "Penting: tinggi bibir piring untuk side-light." : "Key: phone at rim height, then 10° down." },
    { t: 248, text: locale === "de" ? "3 Gerichte in einem Frame = Serie." : locale === "id" ? "3 piring dalam 1 frame = jadi seri." : "Plate 3 dishes in same frame = series." },
  ]);
  const [noteDraft, setNoteDraft] = useStatePl("");
  const transcriptRef = useRefPl(null);

  // Tick the timeline forward when playing
  useEffectPl(() => {
    if (!playing || moduleLocked) return;
    const id = setInterval(() => {
      setTime(s => Math.min(mod.duration, s + (0.5 * speed)));
    }, 500);
    return () => clearInterval(id);
  }, [playing, speed, moduleLocked]);

  // Auto-scroll transcript
  useEffectPl(() => {
    const el = transcriptRef.current;
    if (!el) return;
    const active = el.querySelector(".tr-line.active");
    if (active) active.scrollIntoView({ block: "center", behavior: "smooth" });
  }, [time, tab]);

  const currentChapterIdx = mod.chapters.reduce((acc, c, i) => time >= c.t ? i : acc, 0);
  const currentLineIdx = transcriptForLocale.reduce((acc, l, i) => time >= l.t ? i : acc, 0);

  // Lesson mode: mark the curriculum lesson done when the video effectively ends,
  // regardless of the (course-keyed) chapter store state.
  const lessonDoneRef = useRefPl(false);
  useEffectPl(() => {
    if (!lessonMode || lessonDoneRef.current) return;
    if (time >= mod.duration * 0.99) {
      lessonDoneRef.current = true;
      if (lessonMode.onComplete) lessonMode.onComplete();
    }
  }, [time]);
  const progressPct = (time / mod.duration) * 100;

  const seek = (sec) => { setTime(sec); };
  const addNote = () => {
    if (!noteDraft.trim()) return;
    setNotes(prev => [...prev, { t: Math.floor(time), text: noteDraft.trim() }].sort((a, b) => a.t - b.t));
    setNoteDraft("");
  };
  const removeNote = (idx) => setNotes(prev => prev.filter((_, i) => i !== idx));

  // ─── Auto-completion: a chapter is "watched" when ≥90% of its span has played
  const [toast, setToast] = useStatePl(null); // { kind: "chapter" | "module", text, sub }
  const justCompletedRef = useRefPl({}); // { [chapterIdx]: true } per render
  useEffectPl(() => {
    if (moduleLocked) return;
    for (let i = 0; i < mod.chapters.length; i++) {
      if (progress.isChapterDone(course.id, activeIdx, i)) continue;
      const start = mod.chapters[i].t;
      const end = i + 1 < mod.chapters.length ? mod.chapters[i + 1].t : mod.duration;
      const span = end - start;
      const watched = Math.min(Math.max(time - start, 0), span);
      if (span > 0 && watched / span >= 0.9 && !justCompletedRef.current[i]) {
        justCompletedRef.current[i] = true;
        progress.markChapterDone(course.id, activeIdx, i);
        // Was this the LAST chapter? → module-complete celebration
        const nowDone = progress.moduleChaptersDone(course.id, activeIdx).done + 1;
        if (nowDone >= mod.chapters.length) {
          setPlaying(false);
          // Curriculum lesson mode: mark the lesson done, don't auto-advance through courses
          if (lessonMode) {
            if (lessonMode.onComplete) lessonMode.onComplete();
            setToast({
              kind: "module",
              text: ms?.toastModuleDone || "Lesson complete",
              sub: "",
            });
            setTimeout(() => setToast(null), 2600);
          } else {
            setToast({
              kind: "module",
              text: ms?.toastModuleDone || "Module complete",
              sub: ms?.toastModuleSub || "Up next is unlocked.",
            });
            // Auto-advance after a beat
            if (upNext) {
              setTimeout(() => {
                if (onOpenModule) onOpenModule(course.id, activeIdx + 1);
              }, 2400);
            } else {
              setTimeout(() => setToast(null), 3000);
            }
          }
        } else {
          setToast({
            kind: "chapter",
            text: ms?.toastChapterDone || "Chapter complete",
            sub: mod.chapters[i + 1] ? mod.chapters[i + 1][locale] : "",
          });
          setTimeout(() => setToast(null), 2200);
        }
      }
    }
  }, [time, activeIdx]);

  return (
    <div className="page page-player">

      {/* Mobile video-settings sheet */}
      {mobileSettingsOpen && (
        <>
          <div className="vc-sheet-backdrop" onClick={() => setMobileSettingsOpen(false)} />
          <div className="vc-sheet" role="dialog" aria-label="Video settings">
            <div className="vc-sheet-handle" />
            <div className="vc-sheet-section">
              <div className="vc-sheet-label">{tp.captions || "Captions"}</div>
              <div className="vc-sheet-langs">
                {[
                  { c: "en", flag: "🇬🇧", lab: "English (UK)" },
                  { c: "de", flag: "🇩🇪", lab: "Deutsch" },
                  { c: "id", flag: "🇮🇩", lab: "Bahasa" },
                  { c: "off", flag: "✕", lab: "Off" },
                ].map(l => (
                  <button key={l.c} className={"vc-sheet-opt " + (captionLocale === l.c ? "on" : "")}
                    onClick={() => { setCaptionLocale(l.c); }}>
                    <span className="vc-sheet-flag">{l.flag}</span>
                    <span>{l.lab}</span>
                    {captionLocale === l.c && <Icon name="check" size={14} />}
                  </button>
                ))}
              </div>
            </div>
            <div className="vc-sheet-section">
              <div className="vc-sheet-label">{tp.speed || "Playback speed"}</div>
              <div className="vc-sheet-speeds">
                {[0.5, 0.75, 1, 1.25, 1.5, 2].map(s => (
                  <button key={s} className={"vc-sheet-opt " + (speed === s ? "on" : "")}
                    onClick={() => { setSpeed(s); }}>
                    <span>{s}×</span>
                    {speed === s && <Icon name="check" size={14} />}
                  </button>
                ))}
              </div>
            </div>
            <div className="vc-sheet-section">
              <button className="vc-sheet-action">
                <Icon name="bookmark" size={16} />
                <span>{tp.bookmark || "Add bookmark"}</span>
              </button>
            </div>
            <button className="vc-sheet-close" onClick={() => setMobileSettingsOpen(false)}>Close</button>
          </div>
        </>
      )}

      {/* Module-complete toast (subtle) */}
      {toast && (
        <div className={"player-toast " + toast.kind}>
          <div className="player-toast-icon">
            <Icon name={toast.kind === "module" ? "award" : "check"} size={18} />
          </div>
          <div>
            <div className="player-toast-h">{toast.text}</div>
            {toast.sub && <div className="player-toast-sub display-italic">{toast.sub}</div>}
          </div>
        </div>
      )}
      {/* Player breadcrumb */}
      <div className="player-crumbs">
        <button className="link-btn" onClick={onBack}><Icon name="chevron-left" size={12} /> {lessonMode ? lessonMode.backLabel : (locale === "de" ? "Schulungen" : locale === "id" ? "Pelatihan" : "Trainings")}</button>
        {!lessonMode && <>
        <span className="crumb-sep">/</span>
        <span className="display-italic" style={{ color: "var(--smoke)" }}>Module {mod.index + 1} {tp.transcript === "Transkript" ? "von" : tp.transcript === "Transkrip" ? "dari" : "of"} {mod.total}</span></>}
      </div>

      <div className="player-grid">
        {/* LEFT: video + below */}
        <div className="player-main">
          <div className="video-frame private" ref={videoFrameRef}>
            {(
              <div className="video-private-bar">
                <div className="vpb-l">
                  <Icon name="lock" size={11} />
                  <span>{locale === "de" ? "Privat · UFS-gehostet · DRM-geschützt" : locale === "id" ? "Privat · Hosting UFS · DRM-protected" : "Private · UFS-hosted · DRM-protected"}</span>
                </div>
                <div className="vpb-r">
                  <Icon name="captions" size={11} />
                  <span>3 {locale === "de" ? "Sprachen" : locale === "id" ? "bahasa" : "languages"}</span>
                </div>
              </div>
            )}
            {/* Mock video stage — animated placeholder */}
            <div className="video-stage">
              <div className="video-bg" />
              <div className="video-vignette" />
              {profile && (
                <div className="video-watermark">
                  <span>ChefVerse · {profile.name} · {profile.initials}-2026</span>
                </div>
              )}
              <div className="video-overlay-text">
                <div className="vot-eyebrow display-italic">{mod.chapters[currentChapterIdx][locale]}</div>
                <div className="vot-h">{mod.title[locale]}</div>
                <div className="vot-instructor display-italic">with {course.instructor}</div>
              </div>
              {/* Burned-in caption preview */}
              <div className="video-caption">
                <div className="vc-pill display-italic">
                  <Icon name="captions" size={10} /> {window.I18N[captionLocale].locale}
                </div>
                <div className="vc-line">
                  {(mod.transcript[captionLocale] || mod.transcript.en)[currentLineIdx]?.s || ""}
                </div>
              </div>
              {!playing && (
                <button className="video-play-big" onClick={() => setPlaying(true)}>
                  <Icon name="play" size={36} style={{ marginLeft: 4 }} />
                </button>
              )}
            </div>

            {/* Controls */}
            <div className="video-controls">
              <div className="vc-scrub" onClick={(e) => {
                const rect = e.currentTarget.getBoundingClientRect();
                const pct = (e.clientX - rect.left) / rect.width;
                seek(pct * mod.duration);
              }}>
                {/* Chapter ticks */}
                {mod.chapters.map((c, i) => (
                  <div key={i} className="vc-tick" style={{ left: `${(c.t / mod.duration) * 100}%` }} title={c[locale]} />
                ))}
                <div className="vc-track">
                  <div className="vc-progress" style={{ width: `${progressPct}%` }} />
                </div>
                <div className="vc-thumb" style={{ left: `${progressPct}%` }} />
              </div>
              <div className="vc-row">
                <span className="vc-time vc-time-mobile">{fmtTime(time)} <span style={{ color: "var(--smoke)" }}>/ {fmtTime(mod.duration)}</span></span>
                <div className="vc-row-l vc-play-zone">
                  <button className="icon-btn ghost" onClick={() => seek(Math.max(0, time - 10))}><Icon name="skip-back" size={16} /></button>
                  <button className="icon-btn solid" onClick={() => setPlaying(p => !p)}>
                    <Icon name={playing ? "pause" : "play"} size={16} />
                  </button>
                  <button className="icon-btn ghost" onClick={() => seek(Math.min(mod.duration, time + 10))}><Icon name="skip-forward" size={16} /></button>
                  <span className="vc-time vc-time-desktop">{fmtTime(time)} <span style={{ color: "var(--smoke)" }}>/ {fmtTime(mod.duration)}</span></span>
                </div>
                <div className="vc-row-r vc-row-desktop">
                  <CaptionsMenu locale={captionLocale} onChange={setCaptionLocale} />
                  <SpeedMenu speed={speed} onChange={setSpeed} label={tp.speed} />
                  <button className="icon-btn ghost" title={tp.bookmark}><Icon name="bookmark" size={14} /></button>
                  <button className="icon-btn ghost" title="Fullscreen" onClick={toggleFullscreen}>
                    <Icon name={isFullscreen ? "minimize" : "maximize"} size={14} />
                  </button>
                </div>
                <div className="vc-mobile-right">
                  <button className="icon-btn ghost vc-fs-mobile" onClick={toggleFullscreen} aria-label="Fullscreen">
                    <Icon name={isFullscreen ? "minimize" : "maximize"} size={16} />
                  </button>
                  <button className="icon-btn ghost vc-settings-mobile" onClick={() => setMobileSettingsOpen(true)} aria-label="Video settings">
                    <Icon name="settings" size={18} />
                  </button>
                </div>
              </div>
            </div>
          </div>

          {/* Below video: title + actions */}
          <div className="player-meta">
            <span className="eyebrow player-meta-eyebrow">{lessonMode ? (lessonMode.eyebrow || "") : `${locale === "de" ? "SCHULUNG" : locale === "id" ? "PELATIHAN" : "TRAINING"} ${mod.index + 1} ${locale === "de" ? "VON" : locale === "id" ? "DARI" : "OF"} ${courseModules.length || mod.total}`}</span>
            <div className="player-meta-title-row">
              <h2 className="player-title">{mod.title[locale]}</h2>
              <div className="player-meta-actions">
                <window.SaveBtn kind="module" id={`${course.id}-${activeIdx}`} label={tp.save || "Save"} savedLabel={tp.saved || "Saved"} />
                {lessonMode && lessonMode.onNext && progressPct >= 90 && (
                  <button className="btn btn-primary player-next-lesson" onClick={lessonMode.onNext}>
                    {lessonMode.nextLabel || (locale === "de" ? "N\u00E4chste Lektion" : locale === "id" ? "Pelajaran berikutnya" : "Next lesson")} <Icon name="arrow-right" size={14} />
                  </button>
                )}
              </div>
            </div>
            {(() => {
              const introObj = window.__MOD_INTROS__ && (window.__MOD_INTROS__[course.id] || [])[mod.index];
              const introText = lessonMode ? (lessonMode.intro && (lessonMode.intro[locale] || lessonMode.intro.en)) : (introObj ? (introObj[locale] || introObj.en) : null);
              return introText ? (
                <p className="body-text player-intro">{introText}</p>
              ) : null;
            })()}
            {/* Module progress strip */}
            <div className="player-progress-strip">
              <div className="player-progress-meta">
                <span className="player-progress-num">
                  <Icon name="check-circle" size={13} />
                  {progress.moduleChaptersDone(course.id, activeIdx).done} / {mod.chapters.length} {ms?.chaptersDone || "chapters complete"}
                </span>
                <span className="player-progress-pct">{Math.round(progress.modulePct(course.id, activeIdx) * 100)}%</span>
              </div>
              <div className="player-progress-track">
                <div className="player-progress-fill" style={{ width: `${progress.modulePct(course.id, activeIdx) * 100}%` }} />
              </div>
            </div>
          </div>

          {!lessonMode && (
          <div className="player-applybar" data-anchor="apply">
            <div className="applybar-icon"><Icon name="flame" size={18} style={{ color: "var(--ufs-orange)" }} /></div>
            <div className="applybar-body">
              <div className="applybar-h">{tp.brief_cta}</div>
              <div className="subtle">Knorr Professional · 30s broth ritual · {window.BRIEFS[0].payout[locale]}</div>
            </div>
            <button className="btn btn-primary applybar-cta" onClick={onOpenBriefs}>
              {t.briefs.details} <Icon name="arrow-right" size={12} />
            </button>
          </div>
          )}

          {/* Learning Path — full module list (hidden in v2 flat mode) */}
          {!v2 && courseModules.length > 0 && ms && (
            <div className="player-path">
              <h3 className="player-path-h">{locale === "de" ? "Lernpfad" : locale === "id" ? "Jalur belajar" : "Learning path"}</h3>
              <div className="player-path-list">
                {courseModules.map((m, i) => {
                  const status = progress.moduleStatus(course.id, i);
                  const isActive = i === activeIdx;
                  const isDone = status === "completed";
                  const isLocked = status === "locked";
                  const isNext = status === "next";
                  const chCount = progress.chapterCount(course.id, i);
                  const chDone = progress.moduleChaptersDone(course.id, i).done;
                  const pct = chCount > 0 ? (chDone / chCount) * 100 : 0;
                  const minutes = Math.floor(m.dur / 60);
                  return (
                    <button
                      key={m.id}
                      className={"path-item " + (isActive ? "is-active " : "") + (isDone ? "is-done " : "") + (isLocked ? "is-locked " : "") + (isNext ? "is-next " : "")}
                      onClick={() => !isLocked && onOpenModule && onOpenModule(course.id, i)}
                      disabled={isLocked}
                    >
                      <div className="path-num">
                        {isDone ? <Icon name="check" size={14} /> : isLocked ? <Icon name="lock" size={12} /> : String(i + 1).padStart(2, "0")}
                      </div>
                      <div className="path-body">
                        <div className="path-title">{m.title[locale]}</div>
                        <div className="path-meta">
                          <span><Icon name="clock" size={11} /> {minutes} {ms.minutes}</span>
                          <span className="path-meta-dot">·</span>
                          <span>{chDone} / {chCount} {locale === "de" ? "Kapitel" : locale === "id" ? "bab" : "chapters"}</span>
                          {isActive && !isDone && (
                            <span className="path-pill in-progress">{locale === "de" ? "LÄUFT" : locale === "id" ? "BERLANGSUNG" : "IN PROGRESS"}</span>
                          )}
                          {isDone && !isActive && (
                            <span className="path-pill done"><Icon name="check" size={10} /> {locale === "de" ? "FERTIG" : locale === "id" ? "SELESAI" : "DONE"}</span>
                          )}
                          {isNext && !isActive && (
                            <span className="path-pill next">{ms.nextLab.toUpperCase()} <Icon name="arrow-right" size={10} /></span>
                          )}
                          {isLocked && (
                            <span className="path-pill locked"><Icon name="lock" size={10} /> {ms.lockedLab.toUpperCase()}</span>
                          )}
                        </div>
                        <div className="path-track">
                          <div className={"path-fill " + (isDone ? "done " : "") + (isActive ? "active " : "")} style={{ width: `${pct}%` }} />
                        </div>
                      </div>
                      {!isLocked && <Icon name="chevron-right" size={14} style={{ color: "var(--smoke)", flexShrink: 0 }} />}
                    </button>
                  );
                })}
              </div>
            </div>
          )}
        </div>

        {/* RIGHT: panel with tabs */}
        <div className="player-side">
          <div className="player-side-card">
          <div className="side-tabs">
            {[
              { id: "chapters", label: tp.chapters, icon: "list-video" },
              { id: "notes", label: tp.notes, icon: "edit-3" },
              { id: "transcript", label: tp.transcript, icon: "file-text" },
            ].map(b => (
              <button key={b.id} className={"side-tab " + (tab === b.id ? "on" : "")} onClick={() => setTab(b.id)}>
                <Icon name={b.icon} size={13} />
                <span>{b.label}</span>
              </button>
            ))}
          </div>

          <div className="side-content">
            {tab === "transcript" && (
              <div className="tr-scroll" ref={transcriptRef}>
                <div className="tr-list">
                  {transcriptForLocale.map((line, i) => (
                    <button key={i} className={"tr-line " + (i === currentLineIdx ? "active" : "")} onClick={() => seek(line.t)}>
                      <span className="tr-time">{fmtTime(line.t)}</span>
                      <span className="tr-text">{line.s}</span>
                    </button>
                  ))}
                </div>
              </div>
            )}

            {tab === "chapters" && (
              <div className="ch-list">
                {mod.chapters.map((c, i) => {
                  const isDone = progress.isChapterDone(course.id, activeIdx, i);
                  const isCurrent = currentChapterIdx === i && !isDone;
                  return (
                    <button key={i} className={"ch-item " + (isCurrent ? "on" : "") + (isDone ? " done" : "")} onClick={() => seek(c.t)}>
                      <div className="ch-num">
                        {isDone ? <Icon name="check" size={12} /> : isCurrent ? <Icon name="play" size={10} style={{ marginLeft: 2 }} /> : i + 1}
                      </div>
                      <div className="ch-body">
                        <div className="ch-title">{c[locale]}</div>
                        <div className="subtle">{fmtTime(c.t)}</div>
                      </div>
                    </button>
                  );
                })}
              </div>
            )}

            {tab === "notes" && (
              <div className="notes-panel">
                <div className="note-input">
                  <Icon name="edit-3" size={13} style={{ color: "var(--smoke)", flexShrink: 0 }} />
                  <textarea
                    value={noteDraft}
                    onChange={e => setNoteDraft(e.target.value)}
                    placeholder={`${tp.add_note} (${fmtTime(time)})`}
                    rows={2}
                  />
                  <button className="btn btn-primary btn-sm" onClick={addNote} disabled={!noteDraft.trim()}>
                    <Icon name="plus" size={12} /> Save
                  </button>
                </div>

                <div className="note-saved-h">
                  <span className="eyebrow">{tp.saved_notes.toUpperCase()}</span>
                  <span className="subtle">{notes.length}</span>
                </div>
                <div className="notes-list">
                  {notes.map((n, i) => (
                    <div key={i} className="note">
                      <button className="note-time" onClick={() => seek(n.t)}>{fmtTime(n.t)}</button>
                      <div className="note-text">{n.text}</div>
                      <button className="note-x" onClick={() => removeNote(i)}><Icon name="x" size={12} /></button>
                    </div>
                  ))}
                </div>
              </div>
            )}

          </div>
        </div>

        {/* RESOURCES — under the tabbed box, in the right column */}
        <div className="player-resources" data-anchor="resources">
          <div className="player-resources-head">
            <span className="eyebrow">{tp.resources?.toUpperCase() || "RESOURCES"}</span>
          </div>
          <div className="res-list">
            <ResRow icon="file-text" name="Module 4 — recap.pdf" sub="3 pages · 480 KB" />
            <ResRow icon="file-text" name="Lighting cheat-sheet.pdf" sub="1 page · 220 KB" />
            <ResRow icon="upload" name="Practice brief — top-down sauce" sub="30s · vertical · CC required" cta="Open" />
            <ResRow icon="external-link" name="UFS Future Menus 2026 (extract)" sub="Borderless brunch chapter" cta="Open" />
          </div>
        </div>
        </div>

      </div>
    </div>
  );
}

function CaptionsMenu({ locale, onChange }) {
  const [open, setOpen] = useStatePl(false);
  const ref = useRefPl(null);
  useEffectPl(() => {
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, []);
  return (
    <div className="cc-menu" ref={ref}>
      <button className="vc-btn" onClick={() => setOpen(!open)}>
        <Icon name="captions" size={14} />
        <span>CC · {window.I18N[locale].flag}</span>
        <Icon name="chevron-up" size={11} />
      </button>
      {open && (
        <div className="cc-pop">
          {["en", "de", "id"].map(k => (
            <button key={k} className={"cc-opt " + (locale === k ? "on" : "")} onClick={() => { onChange(k); setOpen(false); }}>
              <span className="flag">{window.I18N[k].flag}</span>
              <span>{window.I18N[k].locale}</span>
              {locale === k && <Icon name="check" size={12} style={{ color: "var(--ufs-orange)", marginLeft: "auto" }} />}
            </button>
          ))}
          <button className="cc-opt" onClick={() => { onChange(null); setOpen(false); }}>
            <span style={{ width: 18 }} />
            <span>Off</span>
          </button>
        </div>
      )}
    </div>
  );
}

function SpeedMenu({ speed, onChange, label }) {
  const [open, setOpen] = useStatePl(false);
  const ref = useRefPl(null);
  useEffectPl(() => {
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, []);
  return (
    <div className="cc-menu" ref={ref}>
      <button className="vc-btn" onClick={() => setOpen(!open)}>
        <span>{speed}×</span>
        <Icon name="chevron-up" size={11} />
      </button>
      {open && (
        <div className="cc-pop sm">
          {[0.75, 1, 1.25, 1.5, 2].map(s => (
            <button key={s} className={"cc-opt " + (speed === s ? "on" : "")} onClick={() => { onChange(s); setOpen(false); }}>
              <span>{s}×</span>
              {speed === s && <Icon name="check" size={12} style={{ color: "var(--ufs-orange)", marginLeft: "auto" }} />}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

function ResRow({ icon, name, sub, cta = "Download" }) {
  return (
    <div className="res-row">
      <div className="res-icon"><Icon name={icon} size={14} /></div>
      <div className="res-body">
        <div className="res-name">{name}</div>
        <div className="subtle">{sub}</div>
      </div>
      <button className="btn btn-ghost btn-sm">{cta}</button>
    </div>
  );
}

window.Player = Player;
