// SCK CEN — engine
// Reads window.LEERPAD_CONFIG (defined by a content-*.jsx file loaded before this engine).
// Renders the entire learning path: welcome → tips → overview → modules → completion.

const { useState, useEffect, useMemo } = React;

if (!window.LEERPAD_CONFIG) {
  throw new Error("engine.jsx: window.LEERPAD_CONFIG is missing. Load a content-<client>.jsx file before engine.jsx.");
}
const C = window.LEERPAD_CONFIG;
const MODULES = C.modules;
const TIPS = C.tips.items;

// Set page title
if (C.pageTitle) document.title = C.pageTitle;

// Apply theme tokens to :root
(() => {
  const root = document.documentElement;
  const t = C.theme || {};
  if (t.dark) root.style.setProperty("--dark", t.dark);
  if (t.bright) root.style.setProperty("--bright", t.bright);
  if (t.bright2) root.style.setProperty("--bright-2", t.bright2);
  if (t.soft) root.style.setProperty("--soft", t.soft);
  if (t.cream) root.style.setProperty("--cream", t.cream);
  if (t.pager) root.style.setProperty("--pager", t.pager);
})();


/* ──────────── MASCOT + ICONS ──────────── */
const MASCOT_CELLS = [[3, 0], [2, 1], [3, 1], [4, 1], [0, 1], [7, 1], [1, 2], [2, 2], [4, 2], [5, 2], [0, 3], [1, 3], [6, 3], [7, 3], [0, 4], [1, 4], [6, 4], [7, 4], [1, 5], [2, 5], [4, 5], [5, 5], [2, 6], [3, 6], [4, 6], [0, 6], [7, 6], [3, 7]];
function Mascot({ size = 120 }) {
  const grid = 8,cell = size / grid;
  return (
    <svg className="mascot" width={size} height={size} viewBox={`0 0 ${size} ${size}`} aria-hidden="true">
      {MASCOT_CELLS.map(([c, r], i) =>
      <rect key={i} x={c * cell + 1} y={r * cell + 1} width={cell - 2} height={cell - 2} rx={1} />
      )}
      <rect x={cell * 3 + 1} y={cell * 3 + 1} width={cell * 2 - 2} height={cell * 2 - 2} rx={3} fill="white" />
    </svg>);

}
const I = {
  flag: <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M4 22V4h12l-2 4 2 4H6" /><line x1="4" y1="4" x2="4" y2="22" /></svg>,
  arrowUp: <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><line x1="12" y1="19" x2="12" y2="5" /><polyline points="5 12 12 5 19 12" /></svg>,
  arrowLeft: <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="20" y1="12" x2="4" y2="12" /><polyline points="10 6 4 12 10 18" /></svg>,
  arrowRight: <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><line x1="4" y1="12" x2="20" y2="12" /><polyline points="14 6 20 12 14 18" /></svg>,
  up: <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 14 12 8 18 14" /></svg>,
  down: <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 10 12 16 18 10" /></svg>,
  check: <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12" /></svg>,
  checkBig: <svg width="56" height="56" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12" /></svg>,
  play: <svg width="36" height="36" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z" /></svg>,
  info: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M3 4h14a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H9l-5 4z" /><line x1="11" y1="9.5" x2="11" y2="9.5" /><line x1="11" y1="12" x2="11" y2="14.5" /></svg>,
  chev: <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="9 18 15 12 9 6" /></svg>,
  iMap: <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><polygon points="2 6 9 3 15 6 22 3 22 19 15 22 9 19 2 22 2 6" /><line x1="9" y1="3" x2="9" y2="19" /><line x1="15" y1="6" x2="15" y2="22" /><circle cx="9" cy="11" r="2" fill="currentColor" /></svg>,
  iRank: <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><rect x="9" y="9" width="6" height="12" /><rect x="3" y="14" width="6" height="7" /><rect x="15" y="6" width="6" height="15" /><circle cx="12" cy="4" r="2" /></svg>,
  iTip: <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M3 5h14a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H9l-5 4z" /><polygon points="11 8 12 11 15 11 12.5 13 13.5 16 11 14 8.5 16 9.5 13 7 11 10 11" /></svg>,
  trophy: <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M6 9H4a2 2 0 0 1-2-2V5h4" /><path d="M18 9h2a2 2 0 0 0 2-2V5h-4" /><path d="M6 2v7a6 6 0 0 0 12 0V2" /><line x1="6" y1="2" x2="18" y2="2" /><path d="M9 22h6" /><path d="M12 17v5" /></svg>
};
const TIP_ICONS = { map: I.iMap, rank: I.iRank, tip: I.iTip };

/* ───────────────────────────────────────────────────────────────────
   DYNAMIC DECORATION COMPONENTS
   ────────────────────────────────────────────────────────────────── */

// Background decoration layer — floating shapes that drift behind everything.
// Activates based on :root data-bg attribute (set via Tweaks).
function BgDeco({ variant = "dots", reward = false }) {
  const shapes = useMemo(() => {
    if (variant === "none") return [];
    const kinds = ["ring", "dot", "square"];
    return Array.from({ length: reward ? 14 : 10 }, (_, i) => ({
      kind: kinds[i % 3],
      size: 28 + i * 37 % 80,
      top: i * 73 % 90 + 4,
      left: i * 113 % 92 + 2,
      dur: 10 + i * 5 % 14,
      delay: -(i * 1.7 % 12)
    }));
  }, [variant, reward]);
  return (
    <div className="bg-deco" aria-hidden="true">
      {shapes.map((s, i) =>
      <div key={i} className={"float-shape " + s.kind}
      style={{
        width: s.size, height: s.size,
        top: s.top + "%", left: s.left + "%",
        animationDuration: s.dur + "s",
        animationDelay: s.delay + "s"
      }} />
      )}
    </div>);

}

// Confetti burst — rendered on completion screen.
function Confetti({ count = 80 }) {
  const pieces = useMemo(() => {
    const colors = ["var(--bright)", "var(--reward)", "var(--soft)", "var(--dark)", "#FFFFFF"];
    return Array.from({ length: count }, (_, i) => ({
      left: Math.random() * 100,
      dur: 2.6 + Math.random() * 2,
      delay: Math.random() * 1.5,
      color: colors[i % colors.length],
      size: 6 + Math.random() * 8,
      rot: Math.random() * 360
    }));
  }, [count]);
  return (
    <div className="confetti-wrap" aria-hidden="true">
      {pieces.map((p, i) =>
      <span key={i} className="confetti-piece" style={{
        left: p.left + "%",
        background: p.color,
        width: p.size, height: p.size * 1.5,
        animationDuration: p.dur + "s",
        animationDelay: p.delay + "s",
        transform: `rotate(${p.rot}deg)`
      }} />
      )}
    </div>);

}

// Halo rings pulsing out from a central point (reward screen).
function RewardHalo({ enabled = true }) {
  if (!enabled) return null;
  return (
    <>
      <div className="reward-halo" style={{ left: "50%", top: "38%" }} />
      <div className="reward-halo delay-1" style={{ left: "50%", top: "38%" }} />
      <div className="reward-halo delay-2" style={{ left: "50%", top: "38%" }} />
    </>);

}


const DIFF_LABEL = { easy: "Eenvoudig", medium: "Gemiddeld", hard: "Uitdagend" };
const TYPE_LABEL = { quiz: "Meerkeuze", blank: "Aanvullen", dragdrop: "Sorteren", match: "Verbinden", order: "Volgorde", hotspot: "Foutdetectie" };

/* ──────────── TOP BAR ──────────── */
function TopBar({ progress, score, flash, currentModuleTitle }) {
  const [pop, setPop] = useState(false);
  const prevScore = React.useRef(score);
  useEffect(() => {
    if (score > prevScore.current) {
      setPop(true);
      const tm = setTimeout(() => setPop(false), 600);
      prevScore.current = score;
      return () => clearTimeout(tm);
    }
    prevScore.current = score;
  }, [score]);
  return (
    <div className="top-bar">
      <div className="brand-cell">
        <div className="brand-mark"><Mascot size={36} /></div>
        <div className="brand-text">
          <div className="brand-app">{C.branding.appName}</div>
          <div className="brand-sub">{currentModuleTitle || C.branding.moduleName}</div>
        </div>
      </div>
      <div className="flag-bar" role="progressbar" aria-valuenow={progress}>
        <div className="fill" style={{ width: `calc(${progress}% - 6px)` }}></div>
        {flash && progress > 0 && <div className="pulse" style={{ left: `calc(${progress}% - 4px)`, top: "50%" }}></div>}
        <div className="flag-end">{I.flag}</div>
      </div>
      <div className="right-cell">
        <div className={"score-pill" + (pop ? " pop" : "")}>
          {(flash || pop) && <span className="up">{I.arrowUp}</span>}
          <span>{score}</span>
        </div>
        <div className="user-chip">
          <span className="user-avatar">{C.branding.userInitials}</span>
          <span>{C.branding.userName}</span>
        </div>
      </div>
    </div>);

}

/* ──────────── EXERCISE HEADER (shared) ──────────── */
function ExHead({ exercise, exIdx, exTotal, timer }) {
  return (
    <div className="ex-head">
      <span className={"diff-badge " + exercise.difficulty}>● {DIFF_LABEL[exercise.difficulty]}</span>
      <span className="ex-type-label">{TYPE_LABEL[exercise.type]} · oefening {exIdx + 1} van {exTotal}</span>
      {timer != null && <TimerBadge seconds={timer.seconds} total={timer.total} expired={timer.expired} />}
    </div>);
}

/* TimerBadge: countdown pill with colour-shift as time runs out */
function TimerBadge({ seconds, total, expired }) {
  const pct = Math.max(0, Math.min(1, seconds / total));
  let cls = "timer-badge";
  if (expired) cls += " expired";else
  if (pct < 0.25) cls += " critical";else
  if (pct < 0.5) cls += " warn";
  const mm = Math.floor(seconds / 60);
  const ss = Math.max(0, seconds % 60).toString().padStart(2, "0");
  return (
    <span className={cls}>
      <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
        <circle cx="12" cy="13" r="8" /><polyline points="12 9 12 13 14 15" /><line x1="9" y1="3" x2="15" y2="3" />
      </svg>
      <span>{expired ? "Tijd op" : `${mm}:${ss}`}</span>
    </span>);
}

/* useExerciseTimer: counts down when exercise.timeLimit is set, pauses when submitted */
function useExerciseTimer(exercise, submitted, onExpire) {
  const total = exercise.timeLimit;
  const [seconds, setSeconds] = useState(total || 0);
  const expiredRef = React.useRef(false);
  useEffect(() => {
    if (!total) return;
    if (submitted) return;
    if (seconds <= 0) {
      if (!expiredRef.current) {
        expiredRef.current = true;
        onExpire && onExpire();
      }
      return;
    }
    const t = setTimeout(() => setSeconds((s) => s - 1), 1000);
    return () => clearTimeout(t);
  }, [total, seconds, submitted]);
  if (!total) return null;
  return { seconds, total, expired: seconds <= 0 };
}
function ExFeedback({ isCorrect, explain }) {
  return (
    <div className={"ex-feedback " + (isCorrect ? "correct" : "wrong")}>
      <b>{isCorrect ? "Juist." : "Niet helemaal."}</b>
      {explain}
    </div>);

}

/* ──────────── EXERCISE: QUIZ ──────────── */
function ExQuiz({ exercise, exIdx, exTotal, onResult, onNext }) {
  const [picked, setPicked] = useState(null);
  const submitted = picked != null;
  return (
    <>
      <div className="canvas">
        <div className="ex-frame">
          <ExHead exercise={exercise} exIdx={exIdx} exTotal={exTotal} />
          <div className="ex-q">{exercise.q}</div>
          <div className="quiz-options">
            {exercise.options.map((opt, i) => {
              let state = "";
              if (submitted) {
                if (i === exercise.correct) state = "is-correct";else
                if (i === picked) state = "is-wrong";else
                state = "is-dim";
              }
              return (
                <button key={i} className={"quiz-opt " + state} disabled={submitted}
                onClick={() => {setPicked(i);onResult(i === exercise.correct);}}>
                  <span className="opt-letter">{String.fromCharCode(65 + i)}</span>
                  <span>{opt}</span>
                </button>);

            })}
          </div>
          {submitted && <ExFeedback isCorrect={picked === exercise.correct} explain={exercise.explain} />}
        </div>
      </div>
      <div className="foot">
        <span className="foot-pager">Oefening {exIdx + 1} / {exTotal}</span>
        <button className={"btn-pill" + (submitted ? "" : " disabled")} disabled={!submitted} onClick={onNext}>
          {exIdx < exTotal - 1 ? "Volgende oefening" : "Resultaat module"} {I.arrowRight}
        </button>
      </div>
    </>);

}

/* ──────────── EXERCISE: BLANK ──────────── */
function ExBlank({ exercise, exIdx, exTotal, onResult, onNext }) {
  const [val, setVal] = useState("");
  const [submitted, setSubmitted] = useState(false);
  const [isCorrect, setIsCorrect] = useState(false);
  const check = () => {
    const norm = val.trim().toLowerCase();
    const valid = [exercise.answer, ...(exercise.alts || [])].map((s) => s.toLowerCase());
    const ok = valid.includes(norm);
    setIsCorrect(ok);
    setSubmitted(true);
    onResult(ok);
  };
  return (
    <>
      <div className="canvas">
        <div className="ex-frame">
          <ExHead exercise={exercise} exIdx={exIdx} exTotal={exTotal} />
          <div className="blank-sentence">
            <span>{exercise.before}</span>
            <input className={"blank-input" + (submitted ? isCorrect ? " is-correct" : " is-wrong" : "")}
            value={val} onChange={(e) => setVal(e.target.value)}
            onKeyDown={(e) => {if (e.key === "Enter" && !submitted && val.trim()) check();}}
            disabled={submitted} placeholder="…" aria-label="vul aan" />
            <span>{exercise.after}</span>
          </div>
          {!submitted &&
          <div className="ex-submit">
              <button className={"btn-pill" + (val.trim() ? "" : " disabled")} disabled={!val.trim()} onClick={check}>
                Controleren {I.arrowRight}
              </button>
            </div>
          }
          {submitted && <ExFeedback isCorrect={isCorrect} explain={exercise.explain} />}
        </div>
      </div>
      {submitted &&
      <div className="foot">
          <span className="foot-pager">Oefening {exIdx + 1} / {exTotal}</span>
          <button className="btn-pill" onClick={onNext}>
            {exIdx < exTotal - 1 ? "Volgende oefening" : "Resultaat module"} {I.arrowRight}
          </button>
        </div>
      }
    </>);

}

/* ──────────── EXERCISE: DRAG-DROP (click to place) ──────────── */
function ExDragDrop({ exercise, exIdx, exTotal, onResult, onNext }) {
  const [selected, setSelected] = useState(null);
  const [placement, setPlacement] = useState({}); // itemId -> binId
  const [submitted, setSubmitted] = useState(false);
  const [isCorrect, setIsCorrect] = useState(false);

  const placeIn = (binId) => {
    if (!selected || submitted) return;
    setPlacement((p) => ({ ...p, [selected]: binId }));
    setSelected(null);
  };
  const unplace = (itemId) => {
    if (submitted) return;
    setPlacement((p) => {const n = { ...p };delete n[itemId];return n;});
  };

  const allPlaced = exercise.items.every((it) => placement[it.id]);
  const check = () => {
    if (submitted) return;
    const ok = exercise.items.every((it) => placement[it.id] === exercise.answer[it.id]);
    setIsCorrect(ok);
    setSubmitted(true);
    onResult(ok);
  };
  const timer = useExerciseTimer(exercise, submitted, () => check());
  const itemsInBin = (binId) => exercise.items.filter((it) => placement[it.id] === binId);
  const unplacedItems = exercise.items.filter((it) => !placement[it.id]);

  return (
    <>
      <div className="canvas">
        <div className="ex-frame">
          <ExHead exercise={exercise} exIdx={exIdx} exTotal={exTotal} timer={timer} />
          <div className="ex-q">{exercise.q}</div>
          <div className="dd-stage">
            <div className="dd-hint">{exercise.hint}</div>
            <div className="dd-items">
              {unplacedItems.length === 0 ?
              <div style={{ color: "var(--ink-muted)", fontSize: 13, padding: "8px 0" }}>
                  Alle items zijn gesleept. Druk op "Controleren".
                </div> :
              unplacedItems.map((it) =>
              <button key={it.id}
              className={"dd-item" + (it.image ? " dd-item-img" : "") + (selected === it.id ? " selected" : "")}
              onClick={() => setSelected((s) => s === it.id ? null : it.id)}
              disabled={submitted}>
                  {it.image && <img src={it.image} alt="" className="dd-img" />}
                  <span className="dd-item-label">{it.label}</span>
                </button>
              )}
            </div>
            <div className="dd-bins">
              {exercise.bins.map((bin) =>
              <div key={bin.id} className={"dd-bin" + (selected ? " target-ready" : "")}
              onClick={() => placeIn(bin.id)}>
                  <div className="dd-bin-label">{bin.label}</div>
                  <div className="dd-bin-items">
                    {itemsInBin(bin.id).map((it) => {
                    let cls = "";
                    if (submitted) cls = exercise.answer[it.id] === bin.id ? " correct-place" : " wrong-place";
                    return (
                      <button key={it.id} className={"dd-item" + (it.image ? " dd-item-img" : "") + cls} onClick={(e) => {e.stopPropagation();unplace(it.id);}} disabled={submitted}>
                          {it.image && <img src={it.image} alt="" className="dd-img" />}
                          <span className="dd-item-label">{it.label}</span>
                        </button>);

                  })}
                  </div>
                </div>
              )}
            </div>
          </div>
          {!submitted &&
          <div className="ex-submit">
              <button className={"btn-pill" + (allPlaced ? "" : " disabled")} disabled={!allPlaced} onClick={check}>
                Controleren {I.arrowRight}
              </button>
            </div>
          }
          {submitted && <ExFeedback isCorrect={isCorrect} explain={exercise.explain} />}
        </div>
      </div>
      {submitted &&
      <div className="foot">
          <span className="foot-pager">Oefening {exIdx + 1} / {exTotal}</span>
          <button className="btn-pill" onClick={onNext}>
            {exIdx < exTotal - 1 ? "Volgende oefening" : "Resultaat module"} {I.arrowRight}
          </button>
        </div>
      }
    </>);

}

/* ──────────── EXERCISE: MATCH PAIRS ──────────── */
function ExMatch({ exercise, exIdx, exTotal, onResult, onNext }) {
  // shuffle right column deterministically
  const rightOrder = useMemo(() => {
    const arr = exercise.pairs.map((p, i) => ({ ...p, origIdx: i }));
    // Fisher-Yates with seed for stability
    for (let i = arr.length - 1; i > 0; i--) {
      const j = (i * 7 + 3) % (i + 1); // deterministic
      [arr[i], arr[j]] = [arr[j], arr[i]];
    }
    return arr;
  }, [exercise]);

  const [selectedLeft, setSelectedLeft] = useState(null);
  const [pairs, setPairs] = useState({}); // leftIdx -> rightIdx (origIdx)
  const [submitted, setSubmitted] = useState(false);
  const [isCorrect, setIsCorrect] = useState(false);

  const dotColors = ["#C745CC", "#1F7A4C", "#C9A227", "#4A5AE0", "#B3322B", "#0EA5B7"];

  const pickLeft = (i) => {
    if (submitted) return;
    setSelectedLeft((s) => s === i ? null : i);
  };
  const pickRight = (origIdx) => {
    if (submitted || selectedLeft == null) return;
    // remove any existing pairing involving this right
    setPairs((p) => {
      const n = { ...p };
      Object.keys(n).forEach((k) => {if (n[k] === origIdx) delete n[k];});
      n[selectedLeft] = origIdx;
      return n;
    });
    setSelectedLeft(null);
  };

  const allPaired = Object.keys(pairs).length === exercise.pairs.length;
  const check = () => {
    const ok = exercise.pairs.every((_, i) => pairs[i] === i);
    setIsCorrect(ok);
    setSubmitted(true);
    onResult(ok);
  };

  const pairedRights = new Set(Object.values(pairs));

  return (
    <>
      <div className="canvas">
        <div className="ex-frame">
          <ExHead exercise={exercise} exIdx={exIdx} exTotal={exTotal} />
          <div className="ex-q">{exercise.q}</div>
          <div className="dd-hint">{exercise.hint}</div>
          <div className="match-stage">
            <div className="match-col">
              {exercise.pairs.map((p, i) => {
                const dotIdx = pairs[i];
                let stateCls = "";
                if (submitted) stateCls = pairs[i] === i ? " correct" : " wrong";else
                if (selectedLeft === i) stateCls = " selected";else
                if (dotIdx != null) stateCls = " paired";
                return (
                  <button key={i} className={"match-row" + stateCls} onClick={() => pickLeft(i)} disabled={submitted}>
                    {dotIdx != null && <span className="pair-dot" style={{ background: dotColors[i % dotColors.length] }}></span>}
                    <span>{p.left}</span>
                  </button>);

              })}
            </div>
            <div className="match-col">
              {rightOrder.map((r) => {
                const leftIdx = Object.keys(pairs).find((k) => pairs[k] === r.origIdx);
                let stateCls = "";
                if (submitted) {
                  if (leftIdx != null) stateCls = Number(leftIdx) === r.origIdx ? " correct" : " wrong";
                } else if (pairedRights.has(r.origIdx)) stateCls = " paired";
                return (
                  <button key={r.origIdx} className={"match-row" + stateCls}
                  onClick={() => pickRight(r.origIdx)}
                  disabled={submitted || selectedLeft == null}>
                    {leftIdx != null && <span className="pair-dot" style={{ background: dotColors[Number(leftIdx) % dotColors.length] }}></span>}
                    <span>{r.right}</span>
                  </button>);

              })}
            </div>
          </div>
          {!submitted &&
          <div className="ex-submit">
              <button className={"btn-pill" + (allPaired ? "" : " disabled")} disabled={!allPaired} onClick={check}>
                Controleren {I.arrowRight}
              </button>
            </div>
          }
          {submitted && <ExFeedback isCorrect={isCorrect} explain={exercise.explain} />}
        </div>
      </div>
      {submitted &&
      <div className="foot">
          <span className="foot-pager">Oefening {exIdx + 1} / {exTotal}</span>
          <button className="btn-pill" onClick={onNext}>
            {exIdx < exTotal - 1 ? "Volgende oefening" : "Resultaat module"} {I.arrowRight}
          </button>
        </div>
      }
    </>);

}

/* ──────────── EXERCISE: ORDER ──────────── */
function ExOrder({ exercise, exIdx, exTotal, onResult, onNext }) {
  // start order = reversed of answer (or shuffled deterministically)
  const initial = useMemo(() => {
    const arr = [...exercise.items];
    // simple deterministic reorder: reverse
    return arr.reverse();
  }, [exercise]);

  const [list, setList] = useState(initial);
  const [submitted, setSubmitted] = useState(false);
  const [isCorrect, setIsCorrect] = useState(false);

  const move = (idx, delta) => {
    if (submitted) return;
    const target = idx + delta;
    if (target < 0 || target >= list.length) return;
    const next = [...list];
    [next[idx], next[target]] = [next[target], next[idx]];
    setList(next);
  };

  const check = () => {
    const ok = list.every((it, i) => it.id === exercise.answer[i]);
    setIsCorrect(ok);
    setSubmitted(true);
    onResult(ok);
  };

  return (
    <>
      <div className="canvas">
        <div className="ex-frame">
          <ExHead exercise={exercise} exIdx={exIdx} exTotal={exTotal} />
          <div className="ex-q">{exercise.q}</div>
          <div className="dd-hint">{exercise.hint}</div>
          <div className="order-list">
            {list.map((it, i) => {
              let cls = "";
              if (submitted) cls = it.id === exercise.answer[i] ? " correct" : " wrong";
              return (
                <div key={it.id} className={"order-row" + cls}>
                  <div className="order-num">{i + 1}</div>
                  <div>{it.label}</div>
                  <div className="order-arrows">
                    <button className="order-arrow" onClick={() => move(i, -1)} disabled={submitted || i === 0} aria-label="omhoog">{I.up}</button>
                    <button className="order-arrow" onClick={() => move(i, +1)} disabled={submitted || i === list.length - 1} aria-label="omlaag">{I.down}</button>
                  </div>
                </div>);

            })}
          </div>
          {!submitted &&
          <div className="ex-submit">
              <button className="btn-pill" onClick={check}>Controleren {I.arrowRight}</button>
            </div>
          }
          {submitted && <ExFeedback isCorrect={isCorrect} explain={exercise.explain} />}
        </div>
      </div>
      {submitted &&
      <div className="foot">
          <span className="foot-pager">Oefening {exIdx + 1} / {exTotal}</span>
          <button className="btn-pill" onClick={onNext}>
            {exIdx < exTotal - 1 ? "Volgende oefening" : "Resultaat module"} {I.arrowRight}
          </button>
        </div>
      }
    </>);

}

/* ──────────── EXERCISE: HOTSPOT (klik AI-fouten aan) ──────────── */
function ExHotspot({ exercise, exIdx, exTotal, onResult, onNext }) {
  const [clicks, setClicks] = useState([]); // {x, y, hotspotIdx | null}
  const [submitted, setSubmitted] = useState(false);
  const [isCorrect, setIsCorrect] = useState(false);
  const imgRef = React.useRef(null);

  const TOLERANCE_PCT = 8; // click within 8% of hotspot center counts

  const handleClick = (e) => {
    if (submitted) return;
    if (clicks.length >= (exercise.maxClicks || exercise.hotspots.length + 1)) return;
    const rect = imgRef.current.getBoundingClientRect();
    const x = (e.clientX - rect.left) / rect.width * 100;
    const y = (e.clientY - rect.top) / rect.height * 100;
    // Did we hit a not-yet-found hotspot?
    const foundIdxs = new Set(clicks.filter((c) => c.hotspotIdx != null).map((c) => c.hotspotIdx));
    let hit = null;
    exercise.hotspots.forEach((h, i) => {
      if (foundIdxs.has(i)) return;
      const dx = x - h.x,dy = y - h.y;
      if (Math.sqrt(dx * dx + dy * dy) <= TOLERANCE_PCT) hit = i;
    });
    setClicks((cs) => [...cs, { x, y, hotspotIdx: hit }]);
  };

  const foundCount = clicks.filter((c) => c.hotspotIdx != null).length;
  const totalHotspots = exercise.hotspots.length;

  const check = () => {
    if (submitted) return;
    const ok = foundCount >= (exercise.minToWin || totalHotspots);
    setIsCorrect(ok);
    setSubmitted(true);
    onResult(ok);
  };
  const timer = useExerciseTimer(exercise, submitted, () => check());

  return (
    <>
      <div className="canvas">
        <div className="ex-frame">
          <ExHead exercise={exercise} exIdx={exIdx} exTotal={exTotal} timer={timer} />
          <div className="ex-q">{exercise.q}</div>
          <div className="dd-hint">{exercise.hint}</div>
          <div className="hs-counter">
            Gevonden: <b>{foundCount} / {totalHotspots}</b>
          </div>
          <div className="hs-frame">
            <div className={"hs-stage" + (submitted ? " submitted" : "")}>
              <img ref={imgRef} src={exercise.image} alt="" onClick={handleClick} draggable="false" />
              {clicks.map((c, i) => {
                if (c.hotspotIdx != null) {
                  // correct click
                  const h = exercise.hotspots[c.hotspotIdx];
                  return (
                    <div key={i} className="hs-marker correct" style={{ left: h.x + "%", top: h.y + "%" }}>
                      ✓
                      {submitted && <span className="hs-label">{h.label}</span>}
                    </div>);

                }
                if (submitted) {
                  return (
                    <div key={i} className="hs-marker click-miss" style={{ left: c.x + "%", top: c.y + "%" }}>✕</div>);

                }
                // pre-submit miss-click: just a dim ring
                return (
                  <div key={i} className="hs-marker" style={{ left: c.x + "%", top: c.y + "%", opacity: 0.4 }}>?</div>);

              })}
              {submitted && exercise.hotspots.map((h, i) => {
                const foundIdxs = new Set(clicks.filter((c) => c.hotspotIdx != null).map((c) => c.hotspotIdx));
                if (foundIdxs.has(i)) return null;
                return (
                  <div key={"missed-" + i} className="hs-marker missed" style={{ left: h.x + "%", top: h.y + "%" }}>
                    !
                    <span className="hs-label">{h.label}</span>
                  </div>);

              })}
            </div>
          </div>
          {!submitted &&
          <div className="ex-submit">
              <button className={"btn-pill" + (foundCount > 0 ? "" : " disabled")} disabled={foundCount === 0} onClick={check}>
                {foundCount >= totalHotspots ? "Klaar — controleren" : `Inleveren (${foundCount}/${totalHotspots})`} {I.arrowRight}
              </button>
            </div>
          }
          {submitted && <ExFeedback isCorrect={isCorrect} explain={exercise.explain} />}
        </div>
      </div>
      {submitted &&
      <div className="foot">
          <span className="foot-pager">Oefening {exIdx + 1} / {exTotal}</span>
          <button className="btn-pill" onClick={onNext}>
            {exIdx < exTotal - 1 ? "Volgende oefening" : "Resultaat module"} {I.arrowRight}
          </button>
        </div>
      }
    </>);

}

/* ──────────── SCREENS ──────────── */
function ScreenWelkom({ onNext }) {
  return <>
    <div className="canvas">
      <div className="welkom">
        <DotSymbol name="atom" className="sck-dots lg bright-fill" style={{ top: -20, left: -60 }} />
        <DotSymbol name="radiation" className="sck-dots md dark-fill dim" style={{ top: 40, right: -40 }} />
        <DotSymbol name="heart" className="sck-dots sm bright-fill faint" style={{ bottom: 20, left: 40 }} />
        <DotSymbol name="shield" className="sck-dots sm dark-fill dim" style={{ bottom: 60, right: 60 }} />
        <div className="logo-wrap"><Mascot size={160} /></div>
        <h1>{C.welcome.title}</h1>
        <p>{C.welcome.body}</p>
        <div className="pager">{C.welcome.pager}</div>
      </div>
    </div>
    <div className="foot">
      <span className="foot-left">{C.welcome.estimate}</span>
      <button className="btn-pill" onClick={onNext}>Ga verder {I.arrowRight}</button>
    </div>
  </>;
}

function ScreenTips({ onNext, onBack }) {
  return <>
    <div className="canvas">
      <div className="tips-screen">
        <div className="speech-row">
          <div className="speech-mascot"><Mascot size={84} /></div>
          <div className="speech-bubble">{C.tips.speech}</div>
        </div>
        <div className="tip-grid">
          {TIPS.map((t, i) =>
          <div className="tip-card" key={i}>
              <div className="tip-icon">{TIP_ICONS[t.icon]}</div>
              <div className="tip-body">
                <div className="tip-title">{t.title}</div>
                <div className="tip-desc">{t.desc}</div>
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
    <div className="foot">
      <button className="btn-ghost" onClick={onBack}>{I.arrowLeft} Vorige</button>
      <button className="btn-pill" onClick={onNext}>Naar de modules {I.arrowRight}</button>
    </div>
  </>;
}

function ScreenOverview({ progress, sparks, onPickModule, onBack }) {
  const doneCount = progress.filter((p) => p === "done").length;
  const nextIdx = progress.findIndex((p) => p !== "done");
  return <>
    <div className="canvas">
      <div className="overview">
        <DotSymbol name="knowledge" className="sck-dots lg bright-fill faint" style={{ top: -40, right: -80 }} />
        <DotSymbol name="hourglass" className="sck-dots sm dark-fill dim" style={{ bottom: 20, left: -30 }} />
        <div className="overview-head">
          <div className="eyebrow">{C.overview.eyebrow}</div>
          <h2>{C.overview.title}</h2>
          <div className="overview-progress">
            <span className="pn">{doneCount}/{MODULES.length}</span>
            <div className="bar"><div style={{ width: `${doneCount / MODULES.length * 100}%` }} /></div>
          </div>
        </div>
        <div className="mod-list">
          {MODULES.map((m, i) => {
            const status = progress[i] === "done" ? "done" : i === nextIdx ? "active" : "todo";
            return (
              <div className={"mod-row " + status} key={m.id} onClick={() => onPickModule(i)}>
                <div className="mod-num">{progress[i] === "done" ? I.check : i + 1}</div>
                <div>
                  <div className="mod-title">{m.title}</div>
                  <div className="mod-meta">{m.meta}</div>
                </div>
                <span style={{ color: "var(--bright)", opacity: 0.5 }}>{I.chev}</span>
              </div>);

          })}
        </div>
      </div>
    </div>
    <div className="foot">
      <button className="btn-ghost" onClick={onBack}>{I.arrowLeft} Vorige</button>
      <button className="btn-pill" onClick={() => onPickModule(nextIdx === -1 ? 0 : nextIdx)}>
        {doneCount === 0 ? "Module 1 starten" : doneCount === MODULES.length ? "Resultaat bekijken" : "Doorgaan"} {I.arrowRight}
      </button>
    </div>
  </>;
}

function ScreenVideo({ module, onNext, onBack }) {
  const [played, setPlayed] = useState(false);
  return <>
    <div className="canvas">
      <div className="video-screen">
        <div className="video-frame">
          {module.video ?
          <video src={module.video} controls playsInline preload="metadata" onPlay={() => setPlayed(true)} /> :

          <div className="video-play-btn" onClick={() => setPlayed(true)}>
              <div className="circle">{I.play}</div>
            </div>
          }
        </div>
        <div className="video-info">
          <h2>{module.videoTitle}<span className="info-icon">{I.info}</span></h2>
          <p>{module.videoBody}</p>
        </div>
      </div>
    </div>
    <div className="foot">
      <button className="btn-ghost" onClick={onBack}>{I.arrowLeft} Terug naar overzicht</button>
      <button className={"btn-pill" + (played ? "" : " disabled")} disabled={!played} onClick={onNext}>
        Naar de oefeningen {I.arrowRight}
      </button>
    </div>
  </>;
}

function ScreenReward({ module, sparksEarned, totalEx, sparks, onNext }) {
  const isAllCorrect = sparksEarned === totalEx && totalEx > 0;
  const sparkPts = useMemo(() => Array.from({ length: sparksEarned > 0 ? isAllCorrect ? 40 : 22 : 0 }, (_, i) => ({
    dx: (Math.random() - 0.5) * (isAllCorrect ? 800 : 500),
    dy: -120 - Math.random() * 240,
    delay: i * 0.04
  })), [sparksEarned, isAllCorrect]);
  const heading = isAllCorrect ? "Geweldig!" : sparksEarned > 0 ? "Goed bezig." : "Goed geprobeerd.";
  return <>
    <div className="canvas">
      <div className={"reward-screen" + (isAllCorrect ? " all-correct" : "")}>
        {sparksEarned > 0 && <Confetti count={isAllCorrect ? 140 : 60} />}
        <RewardHalo enabled={sparksEarned > 0} />
        <div className="reward-check">{I.check}</div>
        <h2 className="reward-h">{heading}</h2>
        <p className="reward-sub">
          Module {module.id} voltooid — {sparksEarned} van de {totalEx} oefeningen correct.
        </p>
        {sparksEarned > 0 &&
        <div className="reward-spark-pill">
          <span className="pill-spark-icon">⚡</span>
          +{sparksEarned} {sparksEarned === 1 ? "Spark" : "Sparks"} verdiend
        </div>
        }
        {sparkPts.map((s, i) =>
        <div className="spark-burst" key={i}
        style={{ left: "50%", top: "44%", "--dx": `${s.dx}px`, "--dy": `${s.dy}px`, animationDelay: `${s.delay}s` }}></div>
        )}
      </div>
    </div>
    <div className="foot">
      <span className="foot-pager" style={{ color: "rgba(255,255,255,0.55)" }}>Totaal: {sparks} {sparks === 1 ? "Spark" : "Sparks"}</span>
      <button className="btn-pill" onClick={onNext}>Volgende module {I.arrowRight}</button>
    </div>
  </>;
}

function ScreenPoll({ module, answers, onAnswer, onSubmit, onBack }) {
  const allAnswered = module.poll.every((_, i) => answers[i] != null);
  return <>
    <div className="canvas">
      <div className="poll-screen">
        <div className="poll-intro">
          <span className="badge">Anoniem · geen goed of fout</span>
          <h2>{module.title}</h2>
          <p>{module.pollIntro}</p>
        </div>
        {module.poll.map((q, i) =>
        <div className="poll-q" key={i}>
            <div className="q-num">Vraag {i + 1} van {module.poll.length}</div>
            <div className="q-text">{q.q}</div>
            <div className="poll-options">
              {q.options.map((opt, j) =>
            <button key={j} className={"poll-opt " + (answers[i] === j ? "picked" : "")}
            onClick={() => onAnswer(i, j)}>{opt}</button>
            )}
            </div>
          </div>
        )}
      </div>
    </div>
    <div className="foot">
      <button className="btn-ghost" onClick={onBack}>{I.arrowLeft} Terug naar overzicht</button>
      <button className={"btn-pill" + (allAnswered ? "" : " disabled")} disabled={!allAnswered} onClick={onSubmit}>
        Antwoorden indienen {I.arrowRight}
      </button>
    </div>
  </>;
}

function ScreenPollThanks({ onNext }) {
  return <>
    <div className="canvas">
      <div className="reward-screen">
        <div className="reward-check">{I.checkBig}</div>
        <h2 className="reward-h">{C.poll && C.poll.thanks && C.poll.thanks.title || "Bedankt."}</h2>
        <p className="reward-sub">{C.poll && C.poll.thanks && C.poll.thanks.body || "Je antwoorden stromen anoniem door naar het juiste team."}</p>
      </div>
    </div>
    <div className="foot">
      <span className="foot-pager" style={{ color: "rgba(255,255,255,0.55)" }}>Poll-modules leveren geen Sparks op</span>
      <button className="btn-pill" onClick={onNext}>Volgende module {I.arrowRight}</button>
    </div>
  </>;
}

function ScreenCompletion({ sparks, maxSparks, onRestart }) {
  const pct = maxSparks === 0 ? 0 : Math.round(sparks / maxSparks * 100);
  return <>
    <div className="canvas">
      <div className="completion">
        <DotSymbol name="atom" className="sck-dots lg reward-fill" style={{ top: 40, left: 40 }} />
        <DotSymbol name="heart" className="sck-dots md reward-fill" style={{ top: 80, right: 80 }} />
        <DotSymbol name="shield" className="sck-dots md reward-fill" style={{ bottom: 120, left: 80 }} />
        <DotSymbol name="radiation" className="sck-dots md reward-fill" style={{ bottom: 60, right: 120 }} />
        <Confetti count={90} />
        <div className="trophy">{I.trophy}</div>
        <h1>{C.completion.title}</h1>
        <p className="sub">{C.completion.body}</p>
        <div className="score-grid">
          <div className="score-cell correct"><div className="num">{sparks}/{maxSparks}</div><div className="lbl">correct</div></div>
          <div className="score-cell spark"><div className="num">{sparks}</div><div className="lbl">Sparks</div></div>
          <div className="score-cell pct"><div className="num">{pct}%</div><div className="lbl">score</div></div>
        </div>
      </div>
    </div>
    <div className="foot">
      <button className="btn-ghost" onClick={onRestart}>Pad opnieuw starten</button>
      <button className="btn-pill">{C.completion.cta || "Terug naar SuccessFactors"} {I.arrowRight}</button>
    </div>
  </>;
}

/* ──────────── APP ──────────── */
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "energy": "standard",
  "bg": "bloom",
  "mascotAnim": true,
  "rewardAnim": true,
  "confetti": true
} /*EDITMODE-END*/;

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [screen, setScreen] = useState("welkom");
  const [moduleIdx, setModuleIdx] = useState(0);
  const [phase, setPhase] = useState("video"); // lesson: video | ex (with exIdx) | reward | poll: poll | thanks
  const [exIdx, setExIdx] = useState(0);
  const [progress, setProgress] = useState(Array(MODULES.length).fill("todo"));
  const [moduleSparks, setModuleSparks] = useState(Array(MODULES.length).fill(0)); // sparks earned per module
  const [currentModuleSparks, setCurrentModuleSparks] = useState(0); // accumulator during module
  const [pollAnswers, setPollAnswers] = useState({});

  const sparks = moduleSparks.reduce((a, b) => a + b, 0);
  const maxSparks = MODULES.filter((m) => m.kind === "lesson").reduce((a, m) => a + m.exercises.length, 0);

  const currentModule = MODULES[moduleIdx];

  const overallProgress = useMemo(() => {
    if (screen === "welkom" || screen === "tips") return 0;
    if (screen === "overview") return progress.filter((p) => p === "done").length / MODULES.length * 100;
    if (screen === "completion") return 100;
    const baseDone = progress.filter((p) => p === "done").length;
    let sub = 0;
    if (phase === "video" || phase === "poll") sub = 0.2;else
    if (phase === "ex") sub = 0.4 + 0.4 * (exIdx / (currentModule.exercises?.length || 1));else
    sub = 1; // reward/thanks
    return Math.min(100, (baseDone + sub) / MODULES.length * 100);
  }, [screen, phase, exIdx, progress, currentModule]);

  const goPickModule = (i) => {
    if (i === -1) {
      if (progress.every((p) => p === "done")) setScreen("completion");
      return;
    }
    setModuleIdx(i);
    setExIdx(0);
    setCurrentModuleSparks(0);
    const mod = MODULES[i];
    setPhase(mod.kind === "lesson" ? mod.noVideo ? "ex" : "video" : "poll");
    setScreen("module");
  };

  const finishModule = (sparksEarned) => {
    setProgress((prev) => {const n = [...prev];n[moduleIdx] = "done";return n;});
    setModuleSparks((prev) => {const n = [...prev];n[moduleIdx] = sparksEarned;return n;});
  };

  const nextAfterModule = () => {
    const allDone = progress.every((p, i) => i === moduleIdx ? true : p === "done");
    if (allDone) setScreen("completion");else
    setScreen("overview");
  };

  const onExerciseResult = (isCorrect) => {
    if (isCorrect) setCurrentModuleSparks((c) => c + 1);
  };
  const onExerciseNext = () => {
    if (exIdx < currentModule.exercises.length - 1) {
      setExIdx(exIdx + 1);
    } else {
      finishModule(currentModuleSparks);
      setPhase("reward");
    }
  };

  const renderModule = () => {
    if (currentModule.kind === "lesson") {
      if (phase === "video") return <ScreenVideo module={currentModule} onBack={() => setScreen("overview")} onNext={() => {setPhase("ex");setExIdx(0);}} />;
      if (phase === "ex") {
        const ex = currentModule.exercises[exIdx];
        const props = { exercise: ex, exIdx, exTotal: currentModule.exercises.length, onResult: onExerciseResult, onNext: onExerciseNext, key: `${moduleIdx}-${exIdx}` };
        if (ex.type === "quiz") return <ExQuiz {...props} />;
        if (ex.type === "blank") return <ExBlank {...props} />;
        if (ex.type === "dragdrop") return <ExDragDrop {...props} />;
        if (ex.type === "match") return <ExMatch {...props} />;
        if (ex.type === "order") return <ExOrder {...props} />;
        if (ex.type === "hotspot") return <ExHotspot {...props} />;
      }
      if (phase === "reward") {
        return <ScreenReward module={currentModule} sparksEarned={moduleSparks[moduleIdx]} totalEx={currentModule.exercises.length} sparks={sparks} onNext={nextAfterModule} />;
      }
    } else {
      if (phase === "poll") return <ScreenPoll module={currentModule} answers={pollAnswers}
      onAnswer={(qi, oi) => setPollAnswers((p) => ({ ...p, [qi]: oi }))}
      onBack={() => setScreen("overview")}
      onSubmit={() => {finishModule(0);setPhase("thanks");}} />;
      if (phase === "thanks") return <ScreenPollThanks onNext={nextAfterModule} />;
    }
    return null;
  };

  const renderScreen = () => {
    switch (screen) {
      case "welkom":return <ScreenWelkom onNext={() => setScreen("tips")} />;
      case "tips":return <ScreenTips onNext={() => setScreen("overview")} onBack={() => setScreen("welkom")} />;
      case "overview":return <ScreenOverview progress={progress} sparks={sparks} onBack={() => setScreen("tips")} onPickModule={goPickModule} />;
      case "module":return renderModule();
      case "completion":return <ScreenCompletion sparks={sparks} maxSparks={maxSparks}
        onRestart={() => {setProgress(Array(MODULES.length).fill("todo"));setModuleSparks(Array(MODULES.length).fill(0));setPollAnswers({});setCurrentModuleSparks(0);setScreen("welkom");}} />;
      default:return null;
    }
  };

  const onDarkBg = screen === "completion" || screen === "module" && (phase === "reward" || phase === "thanks");

  // Apply tweak data attributes to :root so CSS can react.
  useEffect(() => {
    const r = document.documentElement;
    r.dataset.energy = t.energy;
    r.dataset.bg = t.bg;
    r.dataset.mascotAnim = t.mascotAnim ? "on" : "off";
    r.dataset.rewardAnim = t.rewardAnim ? "on" : "off";
    r.dataset.confetti = t.confetti ? "on" : "off";
  }, [t.energy, t.bg, t.mascotAnim, t.rewardAnim, t.confetti]);
  const screenLabel = screen === "module" ?
  `Module ${currentModule.id} · ${phase}${phase === "ex" ? " " + (exIdx + 1) : ""}` :
  screen.charAt(0).toUpperCase() + screen.slice(1);
  const currentModuleTitle = screen === "module" ? `Module ${currentModule.id} · ${currentModule.title}` : null;

  return (
    <div className={"desktop-app" + (onDarkBg ? " reward-bg" : "")} data-screen-label={screenLabel}>
      <BgDeco variant={t.bg} reward={onDarkBg} />
      <TopBar
        progress={overallProgress}
        score={sparks}
        flash={screen === "module" && phase === "reward" && moduleSparks[moduleIdx] > 0}
        currentModuleTitle={currentModuleTitle} />
      
      <div className="content" key={screen + ":" + phase + ":" + exIdx}>
        {renderScreen()}
      </div>

      <TweaksPanel title="Tweaks">
        <TweakSection label="Energie" />
        <TweakRadio
          label="Niveau"
          value={t.energy}
          options={["calm", "standard", "playful"]}
          optionLabels={["Rustig", "Standaard", "Speels"]}
          onChange={(v) => setTweak("energy", v)} />
        
        <TweakSection label="Achtergrond" />
        <TweakRadio
          label="Patroon"
          value={t.bg}
          options={["none", "dots", "bloom"]}
          optionLabels={["Geen", "Stippen", "Bloom"]}
          onChange={(v) => setTweak("bg", v)} />
        
        <TweakSection label="Animaties" />
        <TweakToggle
          label="Mascotte beweegt"
          value={t.mascotAnim}
          onChange={(v) => setTweak("mascotAnim", v)} />
        
        <TweakToggle
          label="Reward-effecten"
          value={t.rewardAnim}
          onChange={(v) => setTweak("rewardAnim", v)} />
        
        <TweakToggle
          label="Confetti bij voltooien"
          value={t.confetti}
          onChange={(v) => setTweak("confetti", v)} />
        
      </TweaksPanel>
    </div>);

}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);