/* prototype/views/review.jsx
   LerenReviewView — stateful spaced-repetition session flow.
   5 phases: front → back → post-grade → paused → rapport
   SRS-state: grade beïnvloedt post-grade messaging, kaart-volgorde en sessie-rapport.
*/

(function () {
  const { useState, useEffect, useRef } = React;

  /* ─── Mock card data (met difficulty + lastSeen) ─────────── */
  const BASE_CARDS = [
    { id: 'c1',  subject: 'biologie',     source: 'Biologie voor jou · havo-3 · H3',     front: 'Wat is mitose?',                     back: 'Een vorm van celdeling waarbij uit één moedercel twee identieke dochtercellen ontstaan.',              note: 'Het DNA wordt eerst verdubbeld vóór de deling.', difficulty: 2, lastSeenDaysAgo: 3 },
    { id: 'c2',  subject: 'biologie',     source: 'Biologie voor jou · havo-3 · H3',     front: 'Wat is meiose?',                     back: 'Een speciale vorm van celdeling die geslachtscellen produceert; halveert het aantal chromosomen.',    note: null,                                            difficulty: 3, lastSeenDaysAgo: 5 },
    { id: 'c3',  subject: 'biologie',     source: 'Biologie voor jou · havo-3 · H3',     front: 'Wat is osmose?',                     back: 'Diffusie van water door een semipermeabel membraan, van lage naar hoge opgeloste-stof-concentratie.', note: null,                                            difficulty: 1, lastSeenDaysAgo: 7 },
    { id: 'c4',  subject: 'biologie',     source: 'Biologie voor jou · havo-3 · H3',     front: 'Verschil plant- vs diercel?',        back: 'Plantencellen hebben celwand, bladgroenkorrels en vacuole. Dierlijke cellen hebben een centriool.',   note: null,                                            difficulty: 2, lastSeenDaysAgo: 2 },
    { id: 'c5',  subject: 'biologie',     source: 'Biologie voor jou · havo-3 · H3',     front: 'Wat doet een ribosoom?',             back: 'Eiwitten aanmaken op basis van instructies van het DNA.',                                            note: null,                                            difficulty: 1, lastSeenDaysAgo: 1 },
    { id: 'c6',  subject: 'engels',       source: 'Stepping Stones · U5',                front: 'Past perfect: vorm',                 back: 'had + voltooid deelwoord — bv. "had eaten", "had walked"',                                          note: null,                                            difficulty: 2, lastSeenDaysAgo: 4 },
    { id: 'c7',  subject: 'engels',       source: 'Stepping Stones · U5',                front: '"I had already left" — wat drukt dit uit?', back: 'Een actie die afgerond was vóór een ander verleden moment.',                                  note: null,                                            difficulty: 3, lastSeenDaysAgo: 6 },
    { id: 'c8',  subject: 'engels',       source: 'Stepping Stones · U5',                front: 'Irregular verb: "go"',               back: 'go / went / gone',                                                                                  note: null,                                            difficulty: 1, lastSeenDaysAgo: 1 },
    { id: 'c9',  subject: 'engels',       source: 'Stepping Stones · U5',                front: 'Irregular verb: "see"',              back: 'see / saw / seen',                                                                                  note: null,                                            difficulty: 1, lastSeenDaysAgo: 2 },
    { id: 'c10', subject: 'wiskunde',     source: 'Getal & Ruimte · H4',                 front: 'Wat is een asymptoot?',              back: 'Een lijn die de grafiek van een functie nadert, maar niet raakt of snijdt.',                        note: null,                                            difficulty: 2, lastSeenDaysAgo: 3 },
    { id: 'c11', subject: 'wiskunde',     source: 'Getal & Ruimte · H4',                 front: 'Kwadratische formule abc',           back: 'x = (−b ± √(b² − 4ac)) / 2a',                                                                     note: null,                                            difficulty: 3, lastSeenDaysAgo: 8 },
    { id: 'c12', subject: 'geschiedenis', source: 'Geschiedeniswerkplaats · H7',          front: 'Wanneer begon de Industriële Revolutie?', back: 'Circa 1760 in Engeland, door stoomkracht en mechanisering van de textielindustrie.',           note: null,                                            difficulty: 2, lastSeenDaysAgo: 5 },
  ];

  const VERDELING_TEMPLATE = [
    { subject: 'biologie',     total: 5 },
    { subject: 'engels',       total: 4 },
    { subject: 'wiskunde',     total: 2 },
    { subject: 'geschiedenis', total: 1 },
  ];

  function buildVerdeling(cardIdx) {
    let remaining = cardIdx;
    return VERDELING_TEMPLATE.map(v => {
      const done = Math.min(remaining, v.total);
      remaining -= done;
      return { ...v, done };
    });
  }

  /* ─── SRS helper: next review date per grade ─────────────── */
  function nextReviewFor(grade, baseDate) {
    const d = baseDate ? new Date(baseDate) : new Date();
    const pad = n => String(n).padStart(2, '0');
    const fmt = dt => `${pad(dt.getDate())}-${pad(dt.getMonth() + 1)}`;
    const addDays = n => { const r = new Date(d); r.setDate(r.getDate() + n); return r; };

    switch (grade) {
      case 'vergeten':  return { label: 'nog deze sessie',  date: null, days: 0 };
      case 'moeilijk':  return { label: 'vanavond',         date: null, days: 0 };
      case 'goed':      return { label: 'morgen',           date: fmt(addDays(1)), days: 1 };
      case 'makkelijk': return { label: `over 4 dagen`,     date: fmt(addDays(4)), days: 4 };
      default:          return { label: 'morgen',           date: fmt(addDays(1)), days: 1 };
    }
  }

  /* ─── PulseSpinner ───────────────────────────────────────── */
  function PulseSpinner({ color }) {
    return (
      <span style={{
        display: 'inline-block', width: 10, height: 10, borderRadius: 999,
        border: `2px solid ${color}`, borderTopColor: 'transparent',
        animation: 'pulseSpin 0.9s linear infinite',
      }}>
        <style>{`@keyframes pulseSpin{from{transform:rotate(0)}to{transform:rotate(360deg)}}`}</style>
      </span>
    );
  }

  /* ─── SessieVoortgangsBalk (with recovery indicator) ────── */
  function SessieVoortgangsBalk({ t, idx, total, verdeling, recoveryCount }) {
    return (
      <div style={{
        background: t.card, border: `1px solid ${t.border}`,
        borderRadius: 10, padding: '14px 16px',
        display: 'flex', flexDirection: 'column', gap: 10,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <span style={{ fontFamily: 'Fredoka One', fontSize: 14, color: t.fg }}>
            Kaart {idx} / {total}
          </span>
          <span style={{ flex: 1 }} />
          {recoveryCount > 0 && (
            <span style={{
              display: 'inline-flex', alignItems: 'center', gap: 5,
              fontSize: 10.5, color: t.mode === 'dark' ? '#FBBF24' : '#B45309',
              fontWeight: 800,
              background: t.mode === 'dark' ? 'rgba(251,191,36,0.12)' : 'rgba(180,83,9,0.07)',
              border: `1px solid ${t.mode === 'dark' ? 'rgba(251,191,36,0.28)' : 'rgba(180,83,9,0.22)'}`,
              padding: '2px 8px', borderRadius: 999,
            }}>
              <PI name="refresh-cw" size={10} strokeWidth={2.4} />
              {recoveryCount} kaart{recoveryCount > 1 ? 'en komen' : ' komt'} nog terug
            </span>
          )}
          <span style={{ fontSize: 11, color: t.fgMute, fontWeight: 700 }}>
            ~ {Math.max(1, Math.round((total - idx) * 0.6))} min resterend
          </span>
        </div>

        <div style={{
          display: 'flex', height: 6, borderRadius: 999,
          overflow: 'hidden', background: t.cardSunken, border: `1px solid ${t.border}`,
        }}>
          {verdeling.map((v, i) => {
            const c = (window.SUBJECTS && window.SUBJECTS[v.subject]) || t.fgMute;
            return (
              <div key={i} style={{
                flex: v.total, display: 'flex',
                borderRight: i < verdeling.length - 1 ? `1px solid ${t.bg}` : 'none',
              }}>
                <div style={{ background: c, flex: v.done }} />
                <div style={{ flex: v.total - v.done }} />
              </div>
            );
          })}
        </div>

        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 12 }}>
          {verdeling.map((v, i) => {
            const c = (window.SUBJECTS && window.SUBJECTS[v.subject]) || t.fgMute;
            return (
              <div key={i} style={{
                display: 'inline-flex', alignItems: 'center', gap: 6,
                fontSize: 11, color: t.fgDim, fontWeight: 700,
              }}>
                <span style={{ width: 8, height: 8, borderRadius: 999, background: c }} />
                <SubjectChip t={t} subject={v.subject} size="sm" iconOnly />
                <span>{v.done} / {v.total}</span>
              </div>
            );
          })}
        </div>
      </div>
    );
  }

  /* ─── Phase: Front ───────────────────────────────────────── */
  function PhaseFront({ t, card, cardIdx, totalCards, verdeling, recoveryCount, onShowAnswer, onPause }) {
    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
        <SessieVoortgangsBalk t={t} idx={cardIdx} total={totalCards} verdeling={verdeling} recoveryCount={recoveryCount} />

        <div>
          <FlashcardDeck
            t={t}
            card={card}
            flipped={false}
            idx={cardIdx}
            total={totalCards}
            showStackHint
            flipCtaSub="Probeer eerst zelf het antwoord te formuleren."
            onGrade={onShowAnswer}
          />
        </div>

        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6 }}>
          <BtnPrimary t={t} icon="repeat-2" onClick={onShowAnswer}>
            Toon antwoord
          </BtnPrimary>
          <span style={{ fontSize: 11.5, color: t.fgMute, fontWeight: 600 }}>
            Probeer eerst zelf het antwoord te formuleren.
          </span>
        </div>

        <div style={{
          display: 'flex', alignItems: 'center', gap: 10,
          padding: '11px 14px', borderRadius: 10,
          background: t.cardSunken, border: `1px solid ${t.border}`,
        }}>
          <PulseMascot size={26} mood="thinking" />
          <span style={{ fontSize: 12, color: t.fgMute, fontWeight: 600, lineHeight: 1.5, flex: 1 }}>
            Neem even de tijd. Hardop zeggen helpt.
          </span>
        </div>
      </div>
    );
  }

  /* ─── Phase: Back (grade) ────────────────────────────────── */
  function PhaseBack({ t, card, cardIdx, totalCards, verdeling, recoveryCount, onGrade, onPause }) {
    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
        <SessieVoortgangsBalk t={t} idx={cardIdx} total={totalCards} verdeling={verdeling} recoveryCount={recoveryCount} />

        <div>
          <FlashcardDeck
            t={t}
            card={card}
            flipped={true}
            idx={cardIdx}
            total={totalCards}
            showStackHint
            onGrade={onGrade}
          />
        </div>

        <div style={{
          display: 'flex', alignItems: 'center', gap: 10,
          padding: '11px 14px', borderRadius: 8,
          background: t.cardSunken, border: `1px solid ${t.border}`,
        }}>
          <PulseMascot size={26} mood="thinking" />
          <span style={{ fontSize: 12, color: t.fgMute, fontWeight: 600, lineHeight: 1.5, flex: 1 }}>
            Geen druk — kies eerlijk hoe het ging. We plannen op basis hiervan wanneer je deze kaart weer ziet.
          </span>
        </div>
      </div>
    );
  }

  /* ─── SRS feedback illustrations per grade ───────────────── */
  function SrsFeedback({ t, grade, card }) {
    const dark = t.mode === 'dark';
    const now = new Date();
    const next = nextReviewFor(grade, now);

    const timeStr = (() => {
      const h = now.getHours();
      const evening = h < 18 ? '19:00' : '21:00';
      if (grade === 'moeilijk') return `vanavond rond ${evening}`;
      if (grade === 'goed') return `morgen rond 16:00`;
      if (grade === 'makkelijk') return `over 4 dagen (${next.date})`;
      return null;
    })();

    if (grade === 'vergeten') {
      return (
        <div style={{
          display: 'flex', alignItems: 'center', gap: 12,
          padding: '12px 14px', borderRadius: 10,
          background: dark ? 'rgba(248,113,113,0.08)' : 'rgba(220,38,38,0.05)',
          border: `1px solid ${dark ? 'rgba(248,113,113,0.24)' : 'rgba(220,38,38,0.18)'}`,
        }}>
          {/* Mini card-stack illustratie */}
          <div style={{ position: 'relative', width: 44, height: 38, flexShrink: 0 }}>
            {[2, 1, 0].map(i => (
              <div key={i} style={{
                position: 'absolute', width: 36, height: 26,
                left: i * 3, top: i * 3,
                background: t.card,
                border: `1.5px solid ${dark ? 'rgba(248,113,113,0.50)' : 'rgba(220,38,38,0.35)'}`,
                borderRadius: 5,
                boxShadow: dark ? '0 2px 6px rgba(0,0,0,0.30)' : '0 1px 4px rgba(0,0,0,0.08)',
              }} />
            ))}
            <div style={{
              position: 'absolute', left: 0, top: 0,
              width: 36, height: 26,
              background: dark ? 'rgba(248,113,113,0.16)' : 'rgba(220,38,38,0.10)',
              border: `1.5px solid ${dark ? '#F87171' : '#DC2626'}`,
              borderRadius: 5,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>
              <PI name="refresh-cw" size={12} color={dark ? '#F87171' : '#DC2626'} strokeWidth={2.4} />
            </div>
          </div>
          <span style={{ fontSize: 12.5, color: dark ? '#FCA5A5' : '#991B1B', fontWeight: 700, lineHeight: 1.45, flex: 1 }}>
            Deze kaart komt <b>later in deze sessie</b> nog een keer terug.
          </span>
        </div>
      );
    }

    if (grade === 'moeilijk') {
      return (
        <div style={{
          display: 'flex', alignItems: 'center', gap: 12,
          padding: '12px 14px', borderRadius: 10,
          background: dark ? 'rgba(251,191,36,0.08)' : 'rgba(180,83,9,0.05)',
          border: `1px solid ${dark ? 'rgba(251,191,36,0.24)' : 'rgba(180,83,9,0.18)'}`,
        }}>
          <div style={{
            width: 36, height: 36, borderRadius: 8, flexShrink: 0,
            background: dark ? 'rgba(251,191,36,0.16)' : 'rgba(180,83,9,0.10)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>
            <PI name="moon" size={16} color={dark ? '#FCD34D' : '#B45309'} strokeWidth={2.2} />
          </div>
          <span style={{ fontSize: 12.5, color: dark ? '#FDE68A' : '#92400E', fontWeight: 700, lineHeight: 1.45, flex: 1 }}>
            We zien deze kaart <b>{timeStr}</b> opnieuw.
          </span>
        </div>
      );
    }

    if (grade === 'goed') {
      return (
        <div style={{
          display: 'flex', alignItems: 'center', gap: 12,
          padding: '12px 14px', borderRadius: 10,
          background: dark ? 'rgba(34,197,94,0.08)' : 'rgba(21,128,61,0.05)',
          border: `1px solid ${dark ? 'rgba(34,197,94,0.24)' : 'rgba(21,128,61,0.18)'}`,
        }}>
          <div style={{
            width: 36, height: 36, borderRadius: 8, flexShrink: 0,
            background: dark ? 'rgba(34,197,94,0.16)' : 'rgba(21,128,61,0.10)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>
            <PI name="sun" size={16} color={dark ? '#22C55E' : '#15803D'} strokeWidth={2.2} />
          </div>
          <span style={{ fontSize: 12.5, color: dark ? '#86EFAC' : '#14532D', fontWeight: 700, lineHeight: 1.45, flex: 1 }}>
            Volgende keer: <b>{timeStr}</b>.
          </span>
        </div>
      );
    }

    if (grade === 'makkelijk') {
      const pad = n => String(n).padStart(2, '0');
      const today = new Date();
      const days = Array.from({ length: 7 }, (_, i) => {
        const d = new Date(today); d.setDate(d.getDate() + i);
        return { label: ['zo','ma','di','wo','do','vr','za'][d.getDay()], isTarget: i === 4 };
      });
      return (
        <div style={{
          display: 'flex', alignItems: 'center', gap: 12,
          padding: '12px 14px', borderRadius: 10,
          background: dark ? 'rgba(34,211,238,0.08)' : 'rgba(3,105,161,0.05)',
          border: `1px solid ${dark ? 'rgba(34,211,238,0.24)' : 'rgba(3,105,161,0.18)'}`,
        }}>
          {/* Mini kalender */}
          <div style={{
            display: 'flex', flexDirection: 'column', gap: 4, flexShrink: 0,
            padding: '6px 8px', borderRadius: 8,
            background: dark ? 'rgba(34,211,238,0.12)' : 'rgba(3,105,161,0.08)',
            border: `1px solid ${dark ? 'rgba(34,211,238,0.24)' : 'rgba(3,105,161,0.18)'}`,
          }}>
            <div style={{ fontSize: 9, fontWeight: 800, color: dark ? '#7DD3FC' : '#0369A1', textAlign: 'center', letterSpacing: 0.4, textTransform: 'uppercase' }}>
              week
            </div>
            <div style={{ display: 'flex', gap: 3 }}>
              {days.map((d, i) => (
                <div key={i} style={{
                  width: 18, height: 20, borderRadius: 4,
                  display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
                  background: d.isTarget ? (dark ? '#22D3EE' : '#0369A1') : 'transparent',
                  border: d.isTarget ? 'none' : `1px solid ${dark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.07)'}`,
                }}>
                  <span style={{ fontSize: 7.5, fontWeight: 800, color: d.isTarget ? (dark ? '#0A0F1E' : '#fff') : t.fgMute, lineHeight: 1 }}>
                    {d.label}
                  </span>
                </div>
              ))}
            </div>
          </div>
          <span style={{ fontSize: 12.5, color: dark ? '#A5F3FC' : '#075985', fontWeight: 700, lineHeight: 1.45, flex: 1 }}>
            Volgende keer: <b>{timeStr}</b>.
          </span>
        </div>
      );
    }

    return null;
  }

  /* ─── Phase: Post-grade ──────────────────────────────────── */
  function PhasePostGrade({ t, card, cardIdx, totalCards, gradeChoice, verdeling, recoveryCount }) {
    const dark = t.mode === 'dark';
    const greenTint = dark ? 'rgba(34,197,94,0.10)' : 'rgba(21,128,61,0.06)';
    const greenBorder = dark ? 'rgba(34,197,94,0.32)' : 'rgba(21,128,61,0.28)';
    const greenInk = dark ? '#22C55E' : '#15803D';

    const gradeLabels = {
      vergeten: 'Vergeten',
      moeilijk: 'Moeilijk',
      goed: 'Goed gedaan',
      makkelijk: 'Makkelijk — toptijmen!',
    };

    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
        <SessieVoortgangsBalk t={t} idx={cardIdx} total={totalCards} verdeling={verdeling} recoveryCount={recoveryCount} />

        <div style={{
          background: greenTint,
          border: `1px solid ${greenBorder}`,
          borderRadius: 10, padding: '24px 26px',
          display: 'flex', flexDirection: 'column', gap: 14,
        }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <SubjectChip t={t} subject={card.subject} size="sm" iconOnly />
            <span style={{ fontSize: 11.5, color: t.fgDim, fontWeight: 700 }}>{card.source}</span>
            <span style={{ flex: 1 }} />
            <span style={{ fontSize: 11, color: t.fgMute, fontWeight: 800, letterSpacing: 0.3 }}>
              Kaart {cardIdx} / {totalCards}
            </span>
          </div>

          <div style={{
            display: 'flex', alignItems: 'center', gap: 12,
            padding: '14px 16px', borderRadius: 10,
            background: dark ? 'rgba(34,197,94,0.16)' : 'rgba(21,128,61,0.10)',
            border: `1px solid ${greenBorder}`,
          }}>
            <div style={{
              width: 32, height: 32, borderRadius: 999,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              background: greenInk, color: dark ? '#0A0F1E' : '#FFFFFF',
              flexShrink: 0,
            }}>
              <PI name="check" size={18} strokeWidth={3} />
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{
                fontFamily: 'Fredoka One', fontSize: 17, color: greenInk,
                lineHeight: 1.2, letterSpacing: '-0.005em',
              }}>{gradeLabels[gradeChoice] || 'Goed gedaan'}</div>
              <div style={{ fontSize: 12, color: t.fgDim, fontWeight: 600, marginTop: 3 }}>
                {card.front.length > 40 ? card.front.slice(0, 40) + '…' : card.front}
              </div>
            </div>
          </div>

          {/* SRS-differentiated scheduling feedback */}
          {gradeChoice && <SrsFeedback t={t} grade={gradeChoice} card={card} />}

          <div style={{
            paddingTop: 12, borderTop: `1px dashed ${t.border}`,
            display: 'flex', alignItems: 'center', gap: 10,
          }}>
            <PulseMascot size={28} mood="happy" />
            <span style={{ fontSize: 12.5, color: t.fgDim, fontWeight: 600, lineHeight: 1.5, flex: 1 }}>
              {gradeChoice === 'vergeten'
                ? 'Geen zorgen — we oefenen hem nog een keer.'
                : gradeChoice === 'moeilijk'
                  ? 'Goed eerlijk zijn! Vanavond nog even herhalen.'
                  : 'Lekker bezig. Volgende kaart komt eraan.'}
            </span>
            <span style={{
              display: 'inline-flex', alignItems: 'center', gap: 6,
              fontSize: 11, color: t.fgMute, fontWeight: 700, fontStyle: 'italic',
            }}>
              <PulseSpinner color={t.fgMute} />
              Volgende kaart…
            </span>
          </div>
        </div>
      </div>
    );
  }

  /* ─── Phase: Paused (modal overlay) ─────────────────────── */
  function PhasePaused({ t, cardIdx, totalCards, verdeling, recoveryCount, card, onResume, onStop }) {
    return (
      <div style={{ position: 'relative' }}>
        <div style={{
          display: 'flex', flexDirection: 'column', gap: 18,
          opacity: 0.35, pointerEvents: 'none', filter: 'blur(0.5px)',
        }}>
          <SessieVoortgangsBalk t={t} idx={cardIdx} total={totalCards} verdeling={verdeling} recoveryCount={recoveryCount} />
          <FlashcardDeck t={t} card={card} flipped idx={cardIdx} total={totalCards} showStackHint />
        </div>

        <div style={{
          position: 'absolute', inset: -4, borderRadius: 12,
          background: t.mode === 'dark' ? 'rgba(8,12,24,0.55)' : 'rgba(15,23,42,0.18)',
          backdropFilter: 'blur(1px)',
          pointerEvents: 'none',
        }} />

        <div style={{
          position: 'absolute', top: '50%', left: '50%',
          transform: 'translate(-50%, -50%)',
          width: 'min(440px, calc(100% - 32px))',
          background: t.card, border: `1px solid ${t.borderStrong}`,
          borderRadius: 14, padding: '22px 24px',
          boxShadow: t.mode === 'dark'
            ? '0 24px 60px rgba(0,0,0,0.55), 0 4px 12px rgba(0,0,0,0.3)'
            : '0 20px 50px rgba(15,23,42,0.18), 0 4px 12px rgba(15,23,42,0.08)',
          display: 'flex', flexDirection: 'column', gap: 14,
          zIndex: 10,
        }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <div style={{
              width: 32, height: 32, borderRadius: 10,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              background: t.cardSunken, border: `1px solid ${t.border}`,
              color: t.fgDim,
            }}>
              <PI name="pause" size={15} strokeWidth={2.6} />
            </div>
            <h2 style={{
              margin: 0, fontFamily: 'Fredoka One', fontSize: 20,
              color: t.fg, lineHeight: 1.15, letterSpacing: '-0.01em',
            }}>Sessie pauzeren?</h2>
          </div>

          <p style={{
            margin: 0, fontSize: 13.5, color: t.fgDim,
            lineHeight: 1.6, fontWeight: 500,
          }}>
            Je hebt {cardIdx - 1} van {totalCards} kaarten gedaan. Je voortgang blijft bewaard — Pulse onthoudt waar je gebleven was.
          </p>

          <div style={{
            display: 'flex', gap: 10, justifyContent: 'flex-end',
            paddingTop: 6, flexWrap: 'wrap',
          }}>
            <BtnGhost t={t} icon="log-out" onClick={onStop}>
              Pauzeren en stoppen
            </BtnGhost>
            <BtnPrimary t={t} icon="play" onClick={onResume}>
              Doorgaan
            </BtnPrimary>
          </div>
        </div>
      </div>
    );
  }

  /* ─── Rapport: morgen-weer section ──────────────────────── */
  function MorgenWeerSection({ t, gradeLog, cards }) {
    const dark = t.mode === 'dark';
    const morgenCards = Object.entries(gradeLog)
      .filter(([, g]) => g === 'moeilijk' || g === 'vergeten')
      .map(([id, grade]) => ({ ...cards.find(c => c.id === id), grade }))
      .filter(c => c.front);

    if (morgenCards.length === 0) return null;

    return (
      <div style={{
        background: t.card, border: `1px solid ${t.border}`,
        borderRadius: 10, padding: '16px 18px',
        display: 'flex', flexDirection: 'column', gap: 12,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <PI name="sun" size={14} color={t.fgDim} strokeWidth={2.4} />
          <span style={{ fontFamily: 'Fredoka One', fontSize: 14, color: t.fg }}>
            Wat zien we morgen weer?
          </span>
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
          {morgenCards.map((c, i) => {
            const next = nextReviewFor(c.grade, new Date());
            const isVergeten = c.grade === 'vergeten';
            const accent = isVergeten
              ? (dark ? '#F87171' : '#DC2626')
              : (dark ? '#FBBF24' : '#B45309');
            return (
              <div key={i} style={{
                display: 'flex', alignItems: 'center', gap: 10,
                padding: '8px 10px', borderRadius: 8,
                background: t.cardSunken, border: `1px solid ${t.border}`,
              }}>
                <SubjectChip t={t} subject={c.subject} size="sm" iconOnly />
                <span style={{ fontSize: 12.5, color: t.fg, fontWeight: 700, flex: 1, lineHeight: 1.3 }}>
                  {c.front.length > 44 ? c.front.slice(0, 44) + '…' : c.front}
                </span>
                <span style={{
                  fontSize: 10.5, fontWeight: 800, color: accent,
                  background: dark ? `${accent}18` : `${accent}12`,
                  border: `1px solid ${accent}30`,
                  padding: '2px 7px', borderRadius: 999, whiteSpace: 'nowrap',
                }}>
                  {isVergeten ? 'hersessie vandaag' : next.label}
                </span>
              </div>
            );
          })}
        </div>
      </div>
    );
  }

  /* ─── Rapport: week-calendar section ────────────────────── */
  function WeekCalendarSection({ t, gradeLog, cards }) {
    const dark = t.mode === 'dark';
    const today = new Date();

    // Build days 0..6 with dot-counts per grade
    const dayBuckets = Array.from({ length: 7 }, (_, i) => {
      const d = new Date(today); d.setDate(d.getDate() + i);
      return {
        label: ['Zo','Ma','Di','Wo','Do','Vr','Za'][d.getDay()],
        dateNum: d.getDate(),
        isToday: i === 0,
        dots: [],
      };
    });

    Object.entries(gradeLog).forEach(([id, grade]) => {
      const card = cards.find(c => c.id === id);
      if (!card) return;
      const next = nextReviewFor(grade, today);
      if (next.days >= 0 && next.days < 7) {
        dayBuckets[next.days].dots.push(card.subject);
      }
    });

    const subjectColor = s => (window.SUBJECTS && window.SUBJECTS[s]) || '#94A3B8';

    return (
      <div style={{
        background: t.card, border: `1px solid ${t.border}`,
        borderRadius: 10, padding: '16px 18px',
        display: 'flex', flexDirection: 'column', gap: 12,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <PI name="calendar" size={14} color={t.fgDim} strokeWidth={2.4} />
          <span style={{ fontFamily: 'Fredoka One', fontSize: 14, color: t.fg }}>
            Wat verwachten we deze week?
          </span>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 6 }}>
          {dayBuckets.map((day, i) => (
            <div key={i} style={{
              display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
              padding: '8px 4px', borderRadius: 8,
              background: day.isToday ? t.primaryDim : t.cardSunken,
              border: `1px solid ${day.isToday ? `color-mix(in srgb, ${t.primary} 30%, transparent)` : t.border}`,
            }}>
              <span style={{ fontSize: 9, fontWeight: 800, color: day.isToday ? t.primary : t.fgMute, textTransform: 'uppercase', letterSpacing: 0.3 }}>
                {day.label}
              </span>
              <span style={{ fontSize: 11, fontWeight: 800, color: day.isToday ? t.primary : t.fg }}>
                {day.dateNum}
              </span>
              {day.dots.length > 0 ? (
                <div style={{ display: 'flex', gap: 2, flexWrap: 'wrap', justifyContent: 'center' }}>
                  {day.dots.slice(0, 4).map((s, j) => (
                    <span key={j} style={{
                      width: 6, height: 6, borderRadius: 999,
                      background: subjectColor(s),
                    }} />
                  ))}
                </div>
              ) : (
                <span style={{ width: 6, height: 6 }} />
              )}
            </div>
          ))}
        </div>
      </div>
    );
  }

  /* ─── Mastery-delta-card (variant B only) ───────────────── */
  function MasteryDeltaCard({ t }) {
    const dark = t.mode === 'dark';
    const subkopjes = [
      { subject: 'biologie', label: 'Celdeling — mitose & meiose', from: 3, to: 4 },
      { subject: 'biologie', label: 'Celstructuren & organellen',  from: 3, to: 4 },
      { subject: 'biologie', label: 'Transport — osmose & diffusie', from: 3, to: 4 },
      { subject: 'biologie', label: 'Plant- vs dierlijke cel',      from: 3, to: 4 },
    ];
    const green = dark ? '#22C55E' : '#15803D';
    return (
      <div style={{
        background: t.card, border: `1px solid ${t.border}`,
        borderRadius: 10, padding: '16px 18px',
        display: 'flex', flexDirection: 'column', gap: 12,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <PI name="bookmark" size={14} color={t.fgDim} strokeWidth={2.4} />
          <span style={{ fontFamily: 'Fredoka One', fontSize: 14, color: t.fg }}>
            Hoofdstuk-voortgang
          </span>
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
          {subkopjes.map((s, i) => (
            <div key={i} style={{
              display: 'flex', alignItems: 'center', gap: 10,
              padding: '8px 10px', borderRadius: 8,
              background: t.cardSunken, border: `1px solid ${t.border}`,
            }}>
              <SubjectChip t={t} subject={s.subject} size="sm" iconOnly />
              <span style={{ fontSize: 12.5, color: t.fg, fontWeight: 700, flex: 1, lineHeight: 1.3 }}>{s.label}</span>
              <span style={{
                display: 'inline-flex', alignItems: 'center', gap: 4,
                fontSize: 11.5, fontWeight: 800,
                color: green, whiteSpace: 'nowrap',
              }}>
                {s.from}/4 → {s.to}/4 ✓
              </span>
            </div>
          ))}
        </div>
        <div style={{ fontSize: 12, color: t.fgMute, fontWeight: 600, lineHeight: 1.5 }}>
          Pulse plant onderhouds-herhalingen — ongeveer 1× per week, 3 minuten.
        </div>
      </div>
    );
  }

  /* ─── Phase: Rapport ─────────────────────────────────────── */
  function PhaseRapport({ t, totalCards, gradeLog, cards, onBack, onAgain, onOefenen, chapterMastered }) {
    const dark = t.mode === 'dark';
    const [bounceReady, setBounceReady] = useState(false);
    useEffect(() => { setBounceReady(true); }, []);

    const grades = Object.values(gradeLog);
    const goedCount = grades.filter(g => g === 'goed' || g === 'makkelijk').length;
    const moeiteCount = grades.filter(g => g === 'vergeten' || g === 'moeilijk').length;
    const displayedTotal = Math.max(totalCards, grades.length);

    const onderwerpen = [
      { subject: 'biologie',     count: 5, topic: 'Mitose, organellen, osmose' },
      { subject: 'engels',       count: 4, topic: 'Past tenses & onregelmatige werkwoorden' },
      { subject: 'wiskunde',     count: 2, topic: 'Vergelijkingen oplossen' },
      { subject: 'geschiedenis', count: 1, topic: 'Industriële Revolutie — start' },
    ];

    const pillarBlue = dark ? '#00B4D8' : '#0096C7';
    const oefenenGreen = dark ? '#22C55E' : '#15803D';

    /* ── Variant B — Hoofdstuk gemastered ── */
    if (chapterMastered) {
      const heroBg = dark ? 'rgba(0,180,216,0.08)' : 'rgba(0,150,199,0.06)';
      const heroBorder = dark ? 'rgba(0,180,216,0.22)' : 'rgba(0,150,199,0.18)';
      const masteredStats = [
        { icon: 'check-circle', label: 'Vlot gekend',  value: '12 / 12',  sub: '100% — perfect ritme',                       accent: null },
        { icon: 'clock',        label: 'Tijd',          value: '8 min',    sub: 'gemiddeld 40 sec per kaart',                  accent: null },
        { icon: 'zap',          label: 'XP verdiend',   value: '+45 XP',   sub: 'level 7 · 136 / 272 naar level 8',            accent: 'primary' },
        { icon: 'sparkles',     label: 'Snaps',         value: '+75 Snaps', sub: 'incl. mastery-bonus · streak 12 → 13',       accent: 'gold' },
      ];

      return (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
          <style>{`@keyframes rapportBounce{0%{transform:scale(0.85);opacity:0}60%{transform:scale(1.06);opacity:1}100%{transform:scale(1);opacity:1}}`}</style>

          {/* Hero — mastered */}
          <div style={{
            background: heroBg, border: `1px solid ${heroBorder}`,
            borderRadius: 10, padding: '22px 24px',
            display: 'flex', alignItems: 'center', gap: 18,
          }}>
            <div style={bounceReady ? { animation: 'rapportBounce 420ms ease-out both' } : { opacity: 0 }}>
              <PulseMascot size={80} mood="celebrating" />
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{
                fontSize: 11, color: pillarBlue, fontWeight: 800,
                letterSpacing: 1, textTransform: 'uppercase', marginBottom: 5,
              }}>HOOFDSTUK BEHEERST</div>
              <h1 style={{
                margin: 0, fontFamily: 'Fredoka One', fontSize: 24,
                color: t.fg, lineHeight: 1.15, letterSpacing: '-0.01em',
              }}>Je kent dit hoofdstuk!</h1>
              <p style={{
                margin: '8px 0 0', fontSize: 13.5, color: t.fgDim,
                lineHeight: 1.6, fontWeight: 500,
              }}>
                De Gouden Eeuw — alle 4 subkopjes op mastery.
              </p>
            </div>
          </div>

          {/* 4-stat grid — mastered values */}
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
            {masteredStats.map((stat, i) => {
              const accentColor = stat.accent === 'primary' ? t.primary
                                : stat.accent === 'gold' ? t.gold
                                : t.fgDim;
              return (
                <div key={i} style={{
                  background: t.card, border: `1px solid ${t.border}`,
                  borderRadius: 10, padding: 16,
                  display: 'flex', flexDirection: 'column', gap: 6,
                }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                    <PI name={stat.icon} size={14} color={accentColor} strokeWidth={2.4} />
                    <span style={{ fontSize: 11, color: t.fgMute, fontWeight: 800, letterSpacing: 0.4, textTransform: 'uppercase' }}>
                      {stat.label}
                    </span>
                  </div>
                  <div style={{
                    fontFamily: 'Fredoka One', fontSize: 22,
                    color: stat.accent ? accentColor : t.fg,
                    letterSpacing: '-0.005em', lineHeight: 1.1,
                  }}>{stat.value}</div>
                  <div style={{ fontSize: 11.5, color: t.fgDim, fontWeight: 600, lineHeight: 1.5 }}>{stat.sub}</div>
                </div>
              );
            })}
          </div>

          {/* Mastery-delta-card */}
          <MasteryDeltaCard t={t} />

          {/* HandoffCard prominent */}
          <HandoffCard
            t={t}
            pillar="oefenen"
            direction="to"
            title="Klaar om te oefenen?"
            subtitle="Je beheerst de stof. In Oefenen ga je 'm toepassen op echte toetsvragen — daar leer je 'm écht vasthouden onder druk."
            mascot={<PulseMascot size={40} mood="encouraging" />}
            hideArrow
          >
            <button
              onClick={onOefenen}
              style={{
                width: '100%', padding: '11px 16px', borderRadius: 10,
                background: oefenenGreen, border: 'none',
                color: '#FFFFFF', fontFamily: 'Nunito', fontSize: 13.5,
                fontWeight: 800, cursor: 'pointer', letterSpacing: 0.1,
                display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
              }}
            >
              <PI name="target" size={15} strokeWidth={2.4} />
              Start Oefenen — toets-mini-quiz
            </button>
          </HandoffCard>

          {/* Secondary ghost row */}
          <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end', flexWrap: 'wrap' }}>
            <BtnGhost t={t} icon="arrow-left" onClick={onBack}>
              Terug naar Leren
            </BtnGhost>
            <BtnGhost t={t} icon="calendar" onClick={() => { /* log */ }}>
              Onderhoudsherhaling plannen
            </BtnGhost>
          </div>
        </div>
      );
    }

    /* ── Variant A — Standaard ── */
    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
        {/* Hero */}
        <div style={{
          background: t.card, border: `1px solid ${t.border}`,
          borderRadius: 10, padding: '22px 24px',
          display: 'flex', alignItems: 'center', gap: 18,
        }}>
          <style>{`@keyframes rapportBounce{0%{transform:scale(0.85);opacity:0}60%{transform:scale(1.06);opacity:1}100%{transform:scale(1);opacity:1}}`}</style>
          <div style={bounceReady ? { animation: 'rapportBounce 420ms ease-out both' } : { opacity: 0 }}>
            <PulseMascot size={64} mood="celebrating" />
          </div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{
              fontSize: 10.5, color: t.primary, fontWeight: 800,
              letterSpacing: 0.6, textTransform: 'uppercase', marginBottom: 4,
            }}>Sessie afgerond</div>
            <h1 style={{
              margin: 0, fontFamily: 'Fredoka One', fontSize: 24,
              color: t.fg, lineHeight: 1.15, letterSpacing: '-0.01em',
            }}>Klaar voor vandaag — netjes door {displayedTotal} kaarten.</h1>
            <p style={{
              margin: '8px 0 0', fontSize: 13.5, color: t.fgDim,
              lineHeight: 1.6, fontWeight: 500,
            }}>
              {moeiteCount > 0
                ? `${moeiteCount} kaart${moeiteCount > 1 ? 'en zaten' : ' zat'} lastig — die zien we snel terug. De rest mag nu even rusten.`
                : 'Alles vlot gegaan — deze kaarten hoeven een tijdje niet terug.'}
            </p>
          </div>
        </div>

        {/* 4-stat grid */}
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
          {[
            { icon: 'check-circle', label: 'Vlot gekend',   value: `${goedCount} / ${displayedTotal}`, sub: `${moeiteCount} snel terug`,            accent: null },
            { icon: 'clock',        label: 'Tijd',           value: '8 min',   sub: 'gemiddeld 40 sec per kaart',        accent: null },
            { icon: 'zap',          label: 'XP verdiend',    value: '+18 XP',  sub: 'level 7 · 91 / 272 naar level 8',   accent: 'primary' },
            { icon: 'sparkles',     label: 'Snaps',          value: '+24 Snaps', sub: 'totaal 1.264 · streak 12 → 13',   accent: 'gold' },
          ].map((stat, i) => {
            const accentColor = stat.accent === 'primary' ? t.primary
                              : stat.accent === 'gold' ? t.gold
                              : t.fgDim;
            return (
              <div key={i} style={{
                background: t.card, border: `1px solid ${t.border}`,
                borderRadius: 10, padding: 16,
                display: 'flex', flexDirection: 'column', gap: 6,
              }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <PI name={stat.icon} size={14} color={accentColor} strokeWidth={2.4} />
                  <span style={{ fontSize: 11, color: t.fgMute, fontWeight: 800, letterSpacing: 0.4, textTransform: 'uppercase' }}>
                    {stat.label}
                  </span>
                </div>
                <div style={{
                  fontFamily: 'Fredoka One', fontSize: 22,
                  color: stat.accent ? accentColor : t.fg,
                  letterSpacing: '-0.005em', lineHeight: 1.1,
                }}>{stat.value}</div>
                <div style={{ fontSize: 11.5, color: t.fgDim, fontWeight: 600, lineHeight: 1.5 }}>{stat.sub}</div>
              </div>
            );
          })}
        </div>

        {/* Wat zat er in */}
        <div style={{
          background: t.card, border: `1px solid ${t.border}`,
          borderRadius: 10, padding: '16px 18px',
          display: 'flex', flexDirection: 'column', gap: 12,
        }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <PI name="bookmark" size={14} color={t.fgDim} strokeWidth={2.4} />
            <span style={{ fontFamily: 'Fredoka One', fontSize: 14, color: t.fg }}>
              Wat zat er in deze sessie?
            </span>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {onderwerpen.map((o, i) => (
              <div key={i} style={{
                display: 'flex', alignItems: 'center', gap: 10,
                padding: '8px 10px', borderRadius: 8,
                background: t.cardSunken, border: `1px solid ${t.border}`,
              }}>
                <SubjectChip t={t} subject={o.subject} size="sm" iconOnly />
                <span style={{ fontSize: 12.5, color: t.fg, fontWeight: 700, flex: 1 }}>{o.topic}</span>
                <span style={{ fontSize: 11, color: t.fgMute, fontWeight: 800, whiteSpace: 'nowrap' }}>
                  {o.count} kaart{o.count > 1 ? 'en' : ''}
                </span>
              </div>
            ))}
          </div>
        </div>

        {/* Morgen weer — alleen als er moeilijke/vergeten kaarten zijn */}
        <MorgenWeerSection t={t} gradeLog={gradeLog} cards={cards} />

        {/* Week-overzicht */}
        <WeekCalendarSection t={t} gradeLog={gradeLog} cards={cards} />

        {/* CTA row */}
        <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end', flexWrap: 'wrap' }}>
          <BtnGhost t={t} icon="arrow-left" onClick={onBack}>
            Terug naar Leren
          </BtnGhost>
          <BtnGhost t={t} icon="repeat" onClick={onAgain}>
            Nóg een rondje
          </BtnGhost>
          <BtnPrimary t={t} icon="arrow-right" onClick={onOefenen}>
            Naar Oefenen — toets-mini-quiz
          </BtnPrimary>
        </div>
      </div>
    );
  }

  /* ─── LerenReviewView ────────────────────────────────────── */
  function LerenReviewView({ t, navigate, reviewCards }) {
    const baseCards = (reviewCards && reviewCards.length > 0)
      ? reviewCards.map((c, i) => ({ ...BASE_CARDS[i % BASE_CARDS.length], ...c }))
      : BASE_CARDS;

    // Session queue: starts as baseCards; vergeten-cards get appended at end
    const [sessionQueue, setSessionQueue] = useState(() => baseCards.map(c => ({ ...c })));
    const [cardIdx, setCardIdx] = useState(0);
    const [phase, setPhase] = useState('front');
    const [gradeChoice, setGradeChoice] = useState(null);
    // Map<id, grade> for rapport
    const [gradeLog, setGradeLog] = useState({});
    const prevPhaseRef = useRef('front');

    // Chapter mastered state — auto-derived at session end; dev-toggle available in rapport
    const [chapterMastered, setChapterMastered] = useState(false);

    const totalCards = sessionQueue.length;
    const currentCard = sessionQueue[cardIdx] || sessionQueue[0];
    const verdeling = buildVerdeling(cardIdx);

    // Count recovery cards (vergeten ones appended after original end)
    const recoveryCount = sessionQueue.filter((c, i) => i >= baseCards.length).length;

    /* Auto-advance from post-grade */
    useEffect(() => {
      if (phase !== 'post-grade') return;
      const tid = setTimeout(() => {
        const nextIdx = cardIdx + 1;
        if (nextIdx >= sessionQueue.length) {
          // Derive mastery: all original base cards graded 'goed' or 'makkelijk'
          const allMastered = baseCards.every(c => {
            const g = gradeLog[c.id];
            return g === 'goed' || g === 'makkelijk';
          }) && Object.keys(gradeLog).length >= baseCards.length;
          setChapterMastered(allMastered);
          setPhase('rapport');
        } else {
          setCardIdx(nextIdx);
          setGradeChoice(null);
          setPhase('front');
        }
      }, 1400);
      return () => clearTimeout(tid);
    }, [phase, cardIdx, sessionQueue.length]);

    function handleShowAnswer() {
      prevPhaseRef.current = 'front';
      setPhase('back');
    }

    function handleGrade(grade) {
      const card = sessionQueue[cardIdx];
      // Log grade
      setGradeLog(prev => ({ ...prev, [card.id]: grade }));

      // For 'vergeten': append card copy at end of queue
      if (grade === 'vergeten') {
        setSessionQueue(prev => [...prev, { ...card, id: card.id + '_r' + Date.now() }]);
      }

      setGradeChoice(grade);
      prevPhaseRef.current = 'back';
      setPhase('post-grade');
    }

    function handlePause() {
      prevPhaseRef.current = phase;
      setPhase('paused');
    }

    function handleResume() {
      setPhase(prevPhaseRef.current === 'paused' ? 'front' : prevPhaseRef.current);
    }

    function handleStop() { navigate('dashboard'); }
    function handleBack() { navigate('dashboard'); }
    function handleAgain() {
      setSessionQueue(baseCards.map(c => ({ ...c })));
      setCardIdx(0);
      setGradeChoice(null);
      setGradeLog({});
      setChapterMastered(false);
      setPhase('front');
    }
    function handleOefenen() { navigate('oefenen'); }

    const isRapport = phase === 'rapport';
    const subtitle = isRapport
      ? `Sessie afgerond · ${baseCards.length} kaarten · 8 min`
      : `${baseCards.length} kaarten · 4 vakken · ~ 8 min`;

    // Dev-toggle pill shown only in rapport phase (prototype-only, not user-facing)
    const rapportDevToggle = isRapport ? (
      <button
        onClick={() => setChapterMastered(v => !v)}
        style={{
          display: 'inline-flex', alignItems: 'center', gap: 6,
          padding: '4px 12px', borderRadius: 999,
          background: chapterMastered
            ? (t.mode === 'dark' ? 'rgba(0,180,216,0.18)' : 'rgba(0,150,199,0.12)')
            : t.cardSunken,
          border: `1px solid ${chapterMastered
            ? (t.mode === 'dark' ? 'rgba(0,180,216,0.40)' : 'rgba(0,150,199,0.35)')
            : t.border}`,
          color: chapterMastered
            ? (t.mode === 'dark' ? '#00B4D8' : '#0096C7')
            : t.fgMute,
          fontSize: 10.5, fontWeight: 800, cursor: 'pointer',
          fontFamily: 'Nunito', letterSpacing: 0.3, whiteSpace: 'nowrap',
        }}
      >
        <PI name="star" size={10} strokeWidth={2.4} />
        Variant: {chapterMastered ? 'mastered' : 'standard'}
      </button>
    ) : null;

    function renderPhase() {
      switch (phase) {
        case 'front':
          return (
            <PhaseFront
              t={t} card={currentCard}
              cardIdx={cardIdx + 1} totalCards={totalCards}
              verdeling={verdeling} recoveryCount={recoveryCount}
              onShowAnswer={handleShowAnswer} onPause={handlePause}
            />
          );
        case 'back':
          return (
            <PhaseBack
              t={t} card={currentCard}
              cardIdx={cardIdx + 1} totalCards={totalCards}
              verdeling={verdeling} recoveryCount={recoveryCount}
              onGrade={handleGrade} onPause={handlePause}
            />
          );
        case 'post-grade':
          return (
            <PhasePostGrade
              t={t} card={currentCard}
              cardIdx={cardIdx + 1} totalCards={totalCards}
              gradeChoice={gradeChoice} verdeling={verdeling}
              recoveryCount={recoveryCount}
            />
          );
        case 'paused':
          return (
            <PhasePaused
              t={t} card={currentCard}
              cardIdx={cardIdx + 1} totalCards={totalCards}
              verdeling={verdeling} recoveryCount={recoveryCount}
              onResume={handleResume} onStop={handleStop}
            />
          );
        case 'rapport':
          return (
            <PhaseRapport
              t={t} totalCards={totalCards}
              gradeLog={gradeLog} cards={sessionQueue}
              onBack={handleBack} onAgain={handleAgain} onOefenen={handleOefenen}
              chapterMastered={chapterMastered}
            />
          );
        default:
          return null;
      }
    }

    return (
      <LerenPage t={t}
        title="Herhaling"
        subtitle={subtitle}
        url="snapsnel.nl/leren/herhaling"
        rightExtra={
          phase !== 'rapport' && phase !== 'paused' ? (
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <BtnGhost t={t} icon="pause" onClick={handlePause}>Pauzeer</BtnGhost>
              <BtnGhost t={t} icon="x" onClick={handleStop}>Stop sessie</BtnGhost>
            </div>
          ) : rapportDevToggle
        }
      >
        {renderPhase()}
      </LerenPage>
    );
  }

  /* ─── Override FlashcardDeck to wire grade buttons ─────── */
  window.FlashcardDeck = function FlashcardDeckInteractive({
    t, card, flipped, idx, total, showStackHint, flipCtaSub, onGrade,
  }) {
    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <div style={{
          display: 'flex', alignItems: 'center', gap: 10,
          fontSize: 11.5, color: t.fgDim, fontWeight: 700,
        }}>
          <SubjectChip t={t} subject={card.subject} size="sm" iconOnly />
          <span>{card.source}</span>
          <span style={{ flex: 1 }} />
          <span style={{ color: t.fgMute, fontWeight: 800, letterSpacing: 0.3 }}>
            Kaart {idx} / {total}
          </span>
        </div>

        <div style={{ position: 'relative' }}>
          {showStackHint && (
            <>
              <div style={{
                position: 'absolute', left: 18, right: 18, top: 8,
                height: 24, background: t.card, border: `1px solid ${t.border}`,
                borderRadius: 8, opacity: 0.5, zIndex: 0,
              }} />
              <div style={{
                position: 'absolute', left: 10, right: 10, top: 4,
                height: 24, background: t.card, border: `1px solid ${t.border}`,
                borderRadius: 8, opacity: 0.7, zIndex: 0,
              }} />
            </>
          )}

          <div style={{
            position: 'relative', zIndex: 1,
            background: t.card, border: `1px solid ${t.border}`,
            borderRadius: 12, padding: '28px 28px 24px',
            minHeight: 240, display: 'flex', flexDirection: 'column', gap: 14,
          }}>
            <div style={{
              display: 'inline-flex', alignSelf: 'flex-start',
              padding: '3px 10px', borderRadius: 999,
              background: flipped ? t.primaryDim : t.cardSunken,
              color: flipped ? t.primary : t.fgMute,
              fontSize: 9.5, fontWeight: 800, letterSpacing: 0.6, textTransform: 'uppercase',
              border: `1px solid ${flipped
                ? `color-mix(in srgb, ${t.primary} 28%, transparent)`
                : t.border}`,
            }}>
              {flipped ? 'Antwoord' : 'Vraag'}
            </div>

            <div style={{
              fontFamily: 'Fredoka One', fontSize: 22, color: t.fg,
              lineHeight: 1.3, letterSpacing: '-0.005em',
            }}>{card.front}</div>

            {flipped && (
              <div style={{
                paddingTop: 14, borderTop: `1px dashed ${t.border}`,
                display: 'flex', flexDirection: 'column', gap: 10,
              }}>
                <div style={{ fontSize: 14.5, color: t.fg, fontWeight: 600, lineHeight: 1.6 }}>
                  {card.back}
                </div>
                {card.note && (
                  <div style={{
                    display: 'flex', alignItems: 'flex-start', gap: 8,
                    padding: '10px 12px', borderRadius: 8,
                    background: t.cardSunken, border: `1px solid ${t.border}`,
                  }}>
                    <PI name="lightbulb" size={13} color={t.gold} strokeWidth={2.4}
                      fill="currentColor" style={{ marginTop: 2, flexShrink: 0 }} />
                    <span style={{ fontSize: 12, color: t.fgDim, fontWeight: 600, lineHeight: 1.5 }}>
                      {card.note}
                    </span>
                  </div>
                )}
              </div>
            )}
          </div>
        </div>

        {flipped ? (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
              <h3 style={{
                margin: 0, fontFamily: 'Nunito', fontSize: 14.5, fontWeight: 800,
                color: t.fg, letterSpacing: '-0.005em',
              }}>Hoe goed kende je deze kaart?</h3>
              <span style={{ fontSize: 11.5, color: t.fgMute, fontWeight: 600, lineHeight: 1.5 }}>
                Pulse plant op basis hiervan wanneer je 'm weer ziet.
              </span>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8 }}>
              {[
                { grade: 'vergeten',  label: 'Vergeten',  due: 'zo weer' },
                { grade: 'moeilijk', label: 'Moeilijk',   due: 'later vandaag' },
                { grade: 'goed',     label: 'Goed',       due: 'morgen' },
                { grade: 'makkelijk', label: 'Makkelijk', due: 'over 4 dagen' },
              ].map(({ grade, label, due }) => {
                const dark = t.mode === 'dark';
                const palette = {
                  vergeten:  { c: dark ? '#F87171' : '#DC2626', bg: dark ? 'rgba(248,113,113,0.12)' : 'rgba(220,38,38,0.06)' },
                  moeilijk:  { c: dark ? '#FBBF24' : '#B45309', bg: dark ? 'rgba(251,191,36,0.12)' : 'rgba(180,83,9,0.06)' },
                  goed:      { c: dark ? '#22C55E' : '#15803D', bg: dark ? 'rgba(34,197,94,0.12)' : 'rgba(21,128,61,0.06)' },
                  makkelijk: { c: dark ? '#22D3EE' : '#0369A1', bg: dark ? 'rgba(34,211,238,0.12)' : 'rgba(3,105,161,0.06)' },
                }[grade];
                return (
                  <button key={grade}
                    onClick={() => onGrade && onGrade(grade)}
                    style={{
                      display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 3,
                      padding: '11px 8px', borderRadius: 10,
                      background: palette.bg,
                      border: `1px solid ${palette.c}40`,
                      color: palette.c, cursor: 'pointer', fontFamily: 'Nunito',
                    }}>
                    <span style={{ fontSize: 13, fontWeight: 800, color: t.fg, whiteSpace: 'nowrap', lineHeight: 1.2 }}>
                      {label}
                    </span>
                    <span style={{ fontSize: 11, fontWeight: 700, color: t.fgMute, whiteSpace: 'nowrap', lineHeight: 1.2 }}>
                      {due}
                    </span>
                  </button>
                );
              })}
            </div>
          </div>
        ) : null}
      </div>
    );
  };

  window.LerenReviewView = LerenReviewView;
})();
