/* learner-decks.jsx — learner view of presentations published from the Educator Studio.
   Renders uploaded decks (image slides) in a full viewer with the same
   notes / follow / Q&A panel + trainer indicator, and a gamification layer
   (XP per slide + completion celebration) when the educator enabled it. */

function UploadedDecks({ t, toast }) {
  const [decks, setDecks] = React.useState(null);
  const [active, setActive] = React.useState(null);

  React.useEffect(() => {load();}, []);
  async function load() {
    try {const d = await window.DeckStore.list();setDecks((d || []).sort((a, b) => b.created - a.created));}
    catch (e) {setDecks([]);}
  }

  return (
    <div className="vh-in">
      <PageHead eyebrow="Trainer uploads" title="Studio Presentations"
      sub="Live presentations your trainer published from the Presentation Studio. Open one to follow along — gamified decks earn you XP." />

      {decks === null ?
      <div className="card" style={{ padding: 40, textAlign: "center", color: "var(--ink-3)" }}>Loading…</div> :
      decks.length === 0 ?
      <div className="card" style={{ padding: 40, textAlign: "center" }}>
          <div style={{ width: 60, height: 60, borderRadius: 16, background: "var(--surface-2)", display: "grid", placeItems: "center", margin: "0 auto 16px" }}>
            <Icon name="pptx" size={28} style={{ color: "var(--ink-3)" }} />
          </div>
          <div style={{ fontFamily: "var(--display)", fontWeight: 700, fontSize: 18, color: "var(--ink)", marginBottom: 6 }}>No presentations yet</div>
          <p style={{ fontSize: 14, color: "var(--ink-2)", maxWidth: 420, margin: "0 auto" }}>When your trainer uploads and publishes a presentation in the Studio, it will appear here for you to view.</p>
        </div> :
      <>
        {(() => {
          const grouped = {},standalone = [];
          decks.forEach((d) => {
            if (d.group) {
              if (!grouped[d.group]) grouped[d.group] = { title: d.groupTitle || d.title, decks: [] };
              grouped[d.group].decks.push(d);
            } else standalone.push(d);
          });
          Object.values(grouped).forEach((g) => g.decks.sort((a, b) => (a.part || 0) - (b.part || 0)));

          function deckCard(d, compact) {
            return (
              <button key={d.id} onClick={() => setActive(d)} className="card"
              style={{ padding: 0, overflow: "hidden", textAlign: "left", cursor: "pointer", border: "1px solid var(--line)" }}
              onMouseEnter={(e) => e.currentTarget.style.boxShadow = "var(--shadow-lg)"}
              onMouseLeave={(e) => e.currentTarget.style.boxShadow = "var(--shadow-sm)"}>
                <div style={{ aspectRatio: d.ratio || 16 / 9, background: "#000", position: "relative" }}>
                  <img src={d.slides[0]} alt={d.title} style={{ width: "100%", height: "100%", objectFit: "contain" }} />
                  <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", background: "rgba(10,18,32,.25)", opacity: 0, transition: "opacity .15s" }}
                  onMouseEnter={(e) => e.currentTarget.style.opacity = 1} onMouseLeave={(e) => e.currentTarget.style.opacity = 0}>
                    <div style={{ width: compact ? 40 : 56, height: compact ? 40 : 56, borderRadius: "50%", background: "rgba(255,255,255,.92)", display: "grid", placeItems: "center" }}><Icon name="play" size={compact ? 16 : 24} style={{ color: "var(--vh-navy)" }} /></div>
                  </div>
                  {d.gamified && <span style={{ position: "absolute", top: 8, left: 8, display: "inline-flex", alignItems: "center", gap: 4, background: "rgba(249,157,37,.95)", color: "#231f20", fontSize: 11, fontWeight: 800, padding: "3px 8px", borderRadius: 999 }}><Icon name="bolt" size={11} />Gamified</span>}
                  {d.part && <span style={{ position: "absolute", bottom: 6, left: 8, fontSize: 11, fontWeight: 700, color: "#fff", background: "rgba(18,129,196,.85)", borderRadius: 5, padding: "2px 8px" }}>Part {d.part}</span>}
                </div>
                <div style={{ padding: compact ? "10px 12px" : "14px 16px" }}>
                  <div style={{ fontWeight: 700, fontSize: compact ? 13.5 : 15.5, color: "var(--ink)", marginBottom: 2, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{d.title}</div>
                  <div className="dim" style={{ fontSize: 12 }}>{d.slides.length} slides{!compact && " · published " + new Date(d.created).toLocaleDateString("en-GB", { day: "numeric", month: "short" })}</div>
                </div>
              </button>);

          }

          const groups = Object.values(grouped);
          return (
            <div style={{ display: "flex", flexDirection: "column", gap: 20 }}>
              {groups.map((g) =>
              <div key={g.title} className="card" style={{ padding: 20 }}>
                  <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 14, flexWrap: "wrap" }}>
                    <div style={{ fontFamily: "var(--display)", fontWeight: 800, fontSize: 18, color: "var(--ink)" }}>{g.title}</div>
                    <span className="dim" style={{ fontSize: 13 }}>{g.decks.length} sections · {g.decks.reduce((s, d) => s + d.slides.length, 0)} slides total</span>
                    {g.decks.some((d) => d.gamified) &&
                  <span style={{ display: "inline-flex", alignItems: "center", gap: 4, background: "rgba(249,157,37,.15)", color: "#c97010", fontSize: 12, fontWeight: 700, padding: "4px 10px", borderRadius: 999, marginLeft: "auto" }}>
                        <Icon name="bolt" size={12} />Gamified
                      </span>
                  }
                  </div>
                  <div style={{ display: "grid", gridTemplateColumns: "repeat(" + Math.min(g.decks.length, 4) + ",1fr)", gap: 14 }}>
                    {g.decks.map((d) => deckCard(d, true))}
                  </div>
                </div>
              )}
              {standalone.length > 0 &&
              <div style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 18 }}>
                  {standalone.map((d) => deckCard(d, false))}
                </div>
              }
            </div>);

        })()}
      </>}

      {active && <UploadedDeckViewer deck={active} toast={toast} onClose={() => setActive(null)} />}
    </div>);

}

function UploadedDeckViewer({ deck, toast, onClose }) {
  const TOTAL = deck.slides.length;
  const [idx, setIdx] = React.useState(0);
  const [notes, setNotes] = React.useState({});
  const [qText, setQText] = React.useState("");
  const [questions, setQuestions] = React.useState([]);
  const [panel, setPanel] = React.useState("notes");
  const [follow, setFollow] = React.useState(null);
  const [followStats, setFollowStats] = React.useState({ yes: 16, less: 5, no: 2 });
  const [elapsed, setElapsed] = React.useState(0);
  const [trainerSlide, setTrainerSlide] = React.useState(Math.min(1, TOTAL - 1));
  const [followMode, setFollowMode] = React.useState(false);
  const [xp, setXp] = React.useState(0);
  const [seen, setSeen] = React.useState(() => ({ 0: true }));
  const [done, setDone] = React.useState(false);
  const followRef = React.useRef(false);
  const fxRef = React.useRef(null);
  const enhMap = deck.enhance || {};
  const curEnh = enhMap[idx] || enhMap[String(idx)];
  const [gameAwarded, setGameAwarded] = React.useState({});
  function awardGame(amt) {if (gameAwarded[idx]) return;setGameAwarded((a) => ({ ...a, [idx]: true }));setXp((x) => x + amt);toast && toast("+" + amt + " XP", "bolt");}

  const AI_DEFAULT_Q = "Can you simplify what's being explained here?";
  const [aiQ, setAiQ] = React.useState(AI_DEFAULT_Q);
  const [aiAns, setAiAns] = React.useState("");
  const [aiBusy, setAiBusy] = React.useState(false);
  async function askAI() {
    if (aiBusy || !aiQ.trim()) return;
    if (!window.claude || !window.claude.complete) { toast && toast("AI runs in the live preview environment", "x"); return; }
    setAiBusy(true); setAiAns("");
    let content = "";
    if (curEnh && curEnh.html) content = curEnh.html.replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim().slice(0, 700);
    else content = [curEnh && curEnh.title && ("title: " + curEnh.title), curEnh && curEnh.caption && ("caption: " + curEnh.caption)].filter(Boolean).join("; ");
    const prompt = [
      'A learner is studying slide ' + (idx + 1) + ' of ' + TOTAL + ' in the training presentation "' + deck.title + '".',
      content ? ("Slide content: " + content) : "No machine-readable slide text is available.",
      'Learner question: "' + aiQ.trim() + '"',
      "Answer helpfully and concisely (max ~4 sentences), in clear plain language for a learner.",
      "Important: never ask for or mention an image or attachment. If specific slide text is unavailable, give your best helpful answer based on the deck title and topic, and keep it practical.",
    ].join("\n");
    try {
      const out = await window.claude.complete(prompt);
      setAiAns((out || "").trim() || "No answer returned.");
    } catch (e) { setAiAns("Sorry — couldn't get an answer right now."); }
    setAiBusy(false);
  }

  function go(n) {setIdx(Math.max(0, Math.min(TOTAL - 1, n)));}

  // timer
  React.useEffect(() => {const t = setInterval(() => setElapsed((e) => e + 1), 1000);return () => clearInterval(t);}, []);
  // simulated trainer
  React.useEffect(() => {
    const ts = Math.min(TOTAL - 1, 1 + Math.floor(elapsed / 32));
    setTrainerSlide(ts);
    if (followRef.current) setIdx(ts);
  }, [elapsed]);
  // keyboard
  React.useEffect(() => {
    function k(e) {if (e.key === "ArrowRight") go(idx + 1);else if (e.key === "ArrowLeft") go(idx - 1);else if (e.key === "Escape") onClose();}
    window.addEventListener("keydown", k);return () => window.removeEventListener("keydown", k);
  }, [idx]);
  // gamification: award XP for newly-seen slides
  React.useEffect(() => {
    if (!deck.gamified) return;
    setSeen((prev) => {
      if (prev[idx]) return prev;
      const nxt = { ...prev, [idx]: true };
      setXp((x) => x + 20);
      toast && toast("+20 XP", "bolt");
      if (Object.keys(nxt).length === TOTAL && !done) {setDone(true);setTimeout(celebrate, 200);}
      return nxt;
    });
  }, [idx]);

  function fmt(s) {return `${String(Math.floor(s / 3600)).padStart(2, "0")}:${String(Math.floor(s % 3600 / 60)).padStart(2, "0")}:${String(s % 60).padStart(2, "0")}`;}

  function sendFollow(v) {
    if (follow) return;
    setFollow(v);setFollowStats((s) => ({ ...s, [v]: s[v] + 1 }));
    toast && toast(v === "yes" ? "Great — marked as understood ✓" : "Feedback sent to trainer", "check");
  }
  function sendQ() {if (!qText.trim()) return;setQuestions((q) => [...q, { text: qText.trim(), time: fmt(elapsed) }]);setQText("");toast && toast("Question sent to trainer", "check");}

  function celebrate() {
    var cv = fxRef.current;if (!cv) return;
    var cx = cv.getContext("2d");cv.width = window.innerWidth;cv.height = window.innerHeight;cv.style.display = "block";
    var ps = [],cols = ["#f99d25", "#3bc1ce", "#1281c4", "#fff", "#26890c"];
    for (var i = 0; i < 120; i++) ps.push({ x: Math.random() * cv.width, y: -20 - Math.random() * 300, vx: (Math.random() - .5) * 6, vy: 3 + Math.random() * 4, c: cols[Math.floor(Math.random() * cols.length)], w: 8 + Math.random() * 12, h: 5 + Math.random() * 7, r: Math.random() * 360, vr: (Math.random() - .5) * 9 });
    (function draw() {cx.clearRect(0, 0, cv.width, cv.height);ps.forEach(function (p) {cx.save();cx.translate(p.x, p.y);cx.rotate(p.r * Math.PI / 180);cx.fillStyle = p.c;cx.fillRect(-p.w / 2, -p.h / 2, p.w, p.h);cx.restore();p.x += p.vx;p.y += p.vy;p.r += p.vr;p.vy += .12;});ps = ps.filter(function (p) {return p.y < cv.height + 40;});if (ps.length) requestAnimationFrame(draw);else {cx.clearRect(0, 0, cv.width, cv.height);cv.style.display = "none";}})();
  }

  const totalFollow = followStats.yes + followStats.less + followStats.no;
  const fBtn = (label, v, col) =>
  <button key={v} onClick={() => sendFollow(v)} style={{ fontSize: 12.5, padding: "7px 12px", borderRadius: 8, border: "1.5px solid " + (follow === v ? col : "#1e2e4a"), background: follow === v ? col + "22" : "rgba(255,255,255,.05)", color: follow === v ? col : "#6b88b0", fontFamily: "var(--body)", fontWeight: 700, cursor: follow ? "default" : "pointer", transition: "all .15s" }}>{label}</button>;


  return ReactDOM.createPortal(
    <div style={{ position: "fixed", inset: 0, zIndex: 700, background: "#0d1521", display: "flex", flexDirection: "column", fontFamily: "var(--body)" }}>
      <canvas ref={fxRef} style={{ position: "fixed", inset: 0, pointerEvents: "none", zIndex: 710, display: "none" }} />

      {/* TOP BAR */}
      <div style={{ height: 52, flex: "none", background: "#0a1220", borderBottom: "1px solid #1e2e4a", display: "flex", alignItems: "center", gap: 12, padding: "0 16px" }}>
        <button onClick={onClose} style={{ display: "flex", alignItems: "center", gap: 6, fontSize: 13, padding: "7px 12px", borderRadius: 8, background: "rgba(255,255,255,.08)", color: "#adc5e8", border: "none", cursor: "pointer", fontFamily: "var(--body)", fontWeight: 600 }}><Icon name="chevL" size={15} />Exit</button>
        <div style={{ flex: 1, fontSize: 14, fontWeight: 600, color: "#adc5e8", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{deck.title}</div>
        <div style={{ fontSize: 13, color: "#6b88b0", fontWeight: 600 }}>Slide {idx + 1} / {TOTAL}</div>
        <button onClick={() => go(trainerSlide)} title="Jump to trainer's slide" style={{ display: "flex", alignItems: "center", gap: 7, padding: "6px 13px", borderRadius: 8, border: "1px solid " + (idx === trainerSlide ? "rgba(249,157,37,.5)" : "rgba(249,157,37,.25)"), background: idx === trainerSlide ? "rgba(249,157,37,.2)" : "rgba(249,157,37,.07)", color: idx === trainerSlide ? "#f99d25" : "#c98020", fontFamily: "var(--body)", fontSize: 13, fontWeight: 700, cursor: "pointer", whiteSpace: "nowrap" }}>
          <span style={{ width: 7, height: 7, borderRadius: "50%", background: "#f99d25", display: "inline-block", boxShadow: idx === trainerSlide ? "0 0 0 3px rgba(249,157,37,.3)" : "none" }} />Trainer · Slide {trainerSlide + 1}<Tip text="Click to jump to the slide the trainer is currently presenting" />
        </button>
        <button onClick={() => {const nv = !followMode;setFollowMode(nv);followRef.current = nv;if (nv) go(trainerSlide);}} style={{ padding: "6px 12px", borderRadius: 8, border: "1px solid " + (followMode ? "rgba(249,157,37,.5)" : "rgba(255,255,255,.12)"), background: followMode ? "rgba(249,157,37,.15)" : "rgba(255,255,255,.05)", color: followMode ? "#f99d25" : "#5a7aaa", fontFamily: "var(--body)", fontSize: 13, fontWeight: 700, cursor: "pointer", whiteSpace: "nowrap" }}>{followMode ? "● Following" : "Follow trainer"}<Tip text="Auto-sync your view with the trainer — your slides follow theirs in real time" /></button>
        {deck.gamified && <span style={{ display: "flex", alignItems: "center", gap: 6, background: "rgba(249,157,37,.16)", border: "1px solid rgba(249,157,37,.3)", borderRadius: 999, padding: "5px 13px", fontFamily: "var(--display)", fontWeight: 800, fontSize: 14, color: "#f99d25" }}><Icon name="bolt" size={14} />{xp} XP<Tip text="Earn XP by viewing new slides — complete the deck for a celebration!" /></span>}
        <div style={{ display: "flex", alignItems: "center", gap: 6, background: "rgba(255,255,255,.07)", borderRadius: 8, padding: "5px 12px" }}><Icon name="clock" size={14} style={{ color: "var(--vh-teal)" }} /><span style={{ fontFamily: "var(--display)", fontWeight: 700, fontSize: 14, color: "var(--vh-teal)" }}>{fmt(elapsed)}</span></div>
      </div>

      {/* MAIN */}
      <div style={{ flex: 1, display: "flex", minHeight: 0 }}>
        <div style={{ flex: 1, minWidth: 0, position: "relative", display: "grid", placeItems: "center", padding: 24, background: "#06101e" }}>
          <div style={{ position: "relative", display: "flex", flexDirection: "column", alignItems: "center", gap: 16, maxWidth: "100%", maxHeight: "100%" }}>
            <div style={{ position: "relative", display: "inline-block", lineHeight: 0 }}>
              {curEnh && curEnh.html ?
              <DeckHtmlSlide html={curEnh.html} ratio={deck.ratio || 16 / 9} maxW="68vw" maxH={curEnh && curEnh.game ? "calc(100vh - 430px)" : "calc(100vh - 180px)"} /> :
              <img src={deck.slides[idx]} alt={"Slide " + (idx + 1)} style={{ maxWidth: "100%", maxHeight: curEnh && curEnh.game ? "calc(100vh - 430px)" : "calc(100vh - 180px)", objectFit: "contain", display: "block", borderRadius: 6, boxShadow: "0 20px 60px rgba(0,0,0,.6)" }} />}
              <DeckEnhanceLayer enh={curEnh} />
              {idx === trainerSlide && <div style={{ position: "absolute", inset: 0, pointerEvents: "none", border: "3px solid rgba(249,157,37,.6)", borderRadius: 6 }} />}
            </div>
            {curEnh && curEnh.game && <DeckGameGate game={curEnh.game} onAward={awardGame} live={true} />}
          </div>
          {/* click zones */}
          <button onClick={() => go(idx - 1)} style={{ position: "absolute", left: 0, top: 0, bottom: 0, width: "10%", background: "none", border: "none", cursor: idx === 0 ? "default" : "pointer", opacity: 0 }} disabled={idx === 0} />
          <button onClick={() => go(idx + 1)} style={{ position: "absolute", right: 0, top: 0, bottom: 0, width: "10%", background: "none", border: "none", cursor: idx === TOTAL - 1 ? "default" : "pointer", opacity: 0 }} disabled={idx === TOTAL - 1} />
        </div>

        {/* Right panel */}
        <div style={{ width: 272, flex: "none", background: "#0d1929", borderLeft: "1px solid #1e2e4a", display: "flex", flexDirection: "column" }}>
          <div style={{ display: "flex", borderBottom: "1px solid #1e2e4a", flex: "none" }}>
            {[["notes", "Notes"], ["questions", "Questions"]].map(([id, lbl]) =>
            <button key={id} onClick={() => setPanel(id)} style={{ flex: 1, padding: "11px 0", fontSize: 13, fontWeight: 600, border: "none", cursor: "pointer", color: panel === id ? "#fff" : "#5a7aaa", background: panel === id ? "rgba(255,255,255,.06)" : "none", borderBottom: panel === id ? "2px solid var(--vh-orange)" : "2px solid transparent" }}>{lbl}</button>
            )}
          </div>
          {panel === "notes" &&
          <div style={{ flex: 1, display: "flex", flexDirection: "column", minHeight: 0 }}>
              <div style={{ flex: 2, display: "flex", flexDirection: "column", padding: 12, gap: 8, minHeight: 0 }}>
              <div style={{ fontSize: 11.5, color: "#4a6080", fontWeight: 600 }}>Slide {idx + 1} notes</div>
              <textarea value={notes[idx] || ""} onChange={(e) => setNotes((n) => ({ ...n, [idx]: e.target.value }))} placeholder="Type your notes here…" style={{ flex: 1, resize: "none", background: "rgba(255,255,255,.05)", border: "1px solid #1e2e4a", borderRadius: 8, color: "#c8d8f0", fontSize: 13, padding: 10, outline: "none", fontFamily: "var(--body)", lineHeight: 1.6 }} />
              <button onClick={() => toast && toast("Notes saved for slide " + (idx + 1), "check")} style={{ fontSize: 12, background: "rgba(255,255,255,.08)", color: "#adc5e8", border: "none", borderRadius: 8, padding: "9px 0", cursor: "pointer", fontFamily: "var(--body)", fontWeight: 600 }}>Save note</button>
              {deck.gamified &&
            <div style={{ borderTop: "1px solid #1e2e4a", paddingTop: 12, marginTop: 4 }}>
                  <div style={{ fontSize: 10.5, fontWeight: 700, letterSpacing: ".1em", textTransform: "uppercase", color: "#f99d25", marginBottom: 8 }}>⚡ Gamified deck</div>
                  <div style={{ fontSize: 12.5, color: "#6b88b0", marginBottom: 8 }}>{Object.keys(seen).length} / {TOTAL} slides viewed · {xp} XP earned</div>
                  <div style={{ height: 5, borderRadius: 999, background: "#1e2e4a", overflow: "hidden" }}><div style={{ height: "100%", width: Math.round(Object.keys(seen).length / TOTAL * 100) + "%", background: "linear-gradient(90deg,var(--vh-orange),var(--vh-teal))", transition: "width .4s" }} /></div>
                </div>
            }
              </div>

              {/* ASK AI — bottom third */}
              <div style={{ flex: 1, minHeight: 168, borderTop: "1px solid #1e2e4a", background: "rgba(59,193,206,.06)", display: "flex", flexDirection: "column", padding: 12, gap: 8 }}>
                <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                  <span style={{ fontSize: 13 }}>✨</span>
                  <span style={{ fontSize: 11, fontWeight: 800, letterSpacing: ".08em", textTransform: "uppercase", color: "var(--vh-teal)" }}>Ask AI about this slide</span>
                </div>
                {(aiAns || aiBusy) &&
                <div className="scroll" style={{ flex: 1, overflowY: "auto", fontSize: 12.5, color: "#c8d8f0", lineHeight: 1.55, background: "rgba(255,255,255,.04)", border: "1px solid #1e2e4a", borderRadius: 8, padding: "8px 10px", whiteSpace: "pre-wrap" }}>{aiBusy ? "Thinking…" : aiAns}</div>
                }
                <textarea value={aiQ} onChange={(e) => setAiQ(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) { e.preventDefault(); askAI(); } }} rows={2} placeholder="Ask anything about this slide…" style={{ resize: "none", background: "rgba(255,255,255,.06)", border: "1px solid #1e2e4a", borderRadius: 8, color: "#c8d8f0", fontSize: 12.5, padding: "8px 10px", outline: "none", fontFamily: "var(--body)", lineHeight: 1.5 }} />
                <button onClick={askAI} disabled={aiBusy} style={{ fontSize: 12.5, fontWeight: 700, background: aiBusy ? "rgba(255,255,255,.08)" : "var(--vh-teal)", color: aiBusy ? "#5a7aaa" : "#08323a", border: "none", borderRadius: 8, padding: "9px 0", cursor: aiBusy ? "default" : "pointer", fontFamily: "var(--body)" }}>{aiBusy ? "Thinking…" : "Ask AI"}</button>
              </div>
            </div>
          }
          {panel === "questions" &&
          <div style={{ flex: 1, display: "flex", flexDirection: "column", padding: 12, gap: 8, minHeight: 0 }}>
              <div style={{ flex: 1, overflowY: "auto", display: "flex", flexDirection: "column", gap: 8 }} className="scroll">
                {questions.length === 0 && <div style={{ fontSize: 13, color: "#4a6080", textAlign: "center", marginTop: 24, lineHeight: 1.6 }}>No questions yet.<br />Ask your trainer below.</div>}
                {questions.map((q, i) => <div key={i} style={{ background: "rgba(255,255,255,.06)", border: "1px solid #1e2e4a", borderRadius: 8, padding: "8px 10px" }}><div style={{ fontSize: 13, color: "#c8d8f0", lineHeight: 1.5 }}>{q.text}</div><div style={{ fontSize: 10.5, color: "#4a6080", marginTop: 4 }}>Sent at {q.time}</div></div>)}
              </div>
              <div style={{ display: "flex", gap: 6 }}>
                <input value={qText} onChange={(e) => setQText(e.target.value)} onKeyDown={(e) => e.key === "Enter" && sendQ()} placeholder="Ask the trainer…" style={{ flex: 1, background: "rgba(255,255,255,.06)", border: "1px solid #1e2e4a", borderRadius: 8, color: "#c8d8f0", fontSize: 13, padding: "8px 10px", outline: "none", fontFamily: "var(--body)" }} />
                <button onClick={sendQ} style={{ fontSize: 12, background: "var(--vh-blue-500)", color: "#fff", border: "none", borderRadius: 8, padding: "8px 12px", cursor: "pointer" }}><Icon name="arrowR" size={14} /></button>
              </div>
            </div>
          }
        </div>
      </div>

      {/* BOTTOM BAR */}
      <div style={{ height: 62, flex: "none", background: "#0a1220", borderTop: "1px solid #1e2e4a", display: "flex", alignItems: "center", gap: 12, padding: "0 18px" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
          <button onClick={() => go(idx - 1)} disabled={idx === 0} style={{ display: "flex", alignItems: "center", gap: 6, fontSize: 13, padding: "8px 14px", borderRadius: 9, background: "rgba(255,255,255,.08)", color: "#adc5e8", border: "none", cursor: idx === 0 ? "default" : "pointer", opacity: idx === 0 ? .35 : 1, fontFamily: "var(--body)", fontWeight: 600 }}><Icon name="chevL" size={15} />Prev</button>
          <div style={{ position: "relative", height: 5, width: 120, background: "rgba(255,255,255,.1)", borderRadius: 9 }}>
            <div style={{ position: "absolute", height: "100%", width: (idx + 1) / TOTAL * 100 + "%", background: "rgba(59,193,206,.7)", borderRadius: 9, transition: "width .3s" }} />
            <div title="Trainer" style={{ position: "absolute", top: "50%", left: (trainerSlide + 0.5) / TOTAL * 100 + "%", transform: "translate(-50%,-50%)", width: 13, height: 13, borderRadius: "50%", background: "#f99d25", border: "2.5px solid #0a1220", boxShadow: "0 0 0 2.5px rgba(249,157,37,.4)", transition: "left .6s ease" }} />
          </div>
          <button onClick={() => go(idx + 1)} disabled={idx === TOTAL - 1} style={{ display: "flex", alignItems: "center", gap: 6, fontSize: 13, padding: "8px 14px", borderRadius: 9, background: "rgba(255,255,255,.08)", color: "#adc5e8", border: "none", cursor: idx === TOTAL - 1 ? "default" : "pointer", opacity: idx === TOTAL - 1 ? .35 : 1, fontFamily: "var(--body)", fontWeight: 600 }}>Next<Icon name="arrowR" size={15} /></button>
        </div>
        <div style={{ flex: 1 }} />
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
          <span style={{ fontSize: 12.5, color: "#6b88b0", fontWeight: 600, whiteSpace: "nowrap" }}>Do you follow?</span><Tip text="Let the trainer know if you can keep up — results are anonymous and shown live" />
          {fBtn("✓ Yes", "yes", "var(--vh-teal)")}{fBtn("~ Less", "less", "var(--vh-orange)")}{fBtn("✗ No", "no", "#c0392b")}
          <div style={{ display: "flex", gap: 4, alignItems: "flex-end", height: 34, paddingBottom: 2, marginLeft: 4 }}>
            {[["yes", "var(--vh-teal)"], ["less", "var(--vh-orange)"], ["no", "#c0392b"]].map(([k, col]) => {const pct = Math.round(followStats[k] / totalFollow * 100);return <div key={k} style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 2 }}><span style={{ fontSize: 9.5, color: col, fontWeight: 700 }}>{pct}%</span><div style={{ width: 10, background: col, borderRadius: "3px 3px 0 0", height: Math.max(2, Math.round(pct / 3.5)) + "px", transition: "height .4s" }} /></div>;})}
          </div>
        </div>
      </div>
    </div>,
    document.body);
}

Object.assign(window, { UploadedDecks, UploadedDeckViewer });