/* prototype/views/library.jsx
   LerenLibraryView — bibliotheek met tabs, filter-chips, upload en empty-state.
   libraryMode prop ('list' | 'upload' | 'empty') bepaalt de weergave — aangestuurd door app.jsx.
   Alle componenten komen van window-globals (shared.jsx, leren-shared.jsx,
   leren-components.jsx, leren-bibliotheek-frames.jsx).
*/

(function () {
  const { useState } = React;

  /* ─── Mock data ─────────────────────────────────────────── */
  const MOCK_KB_ITEMS = [
    // Gecertificeerd
    {
      id: 'bio-h3', subject: 'biologie', method: 'Biologie voor jou',
      level: 'havo-3', chapterNo: 'H3', title: 'Cellen en celdeling',
      masteryLevel: 2, progress: 35, state: 'NU BEZIG',
      deadline: 'TOETS VRIJDAG', certified: true, lastTouched: 'vandaag · 12:14',
      rating: { avg: 4.7, count: 612 }, useCount: 2840, masteryRate: 78, pulseVerified: true,
    },
    {
      id: 'wis-h4', subject: 'wiskunde', method: 'Getal & Ruimte',
      level: 'havo-3', chapterNo: 'H4', title: 'Lineaire vergelijkingen oplossen',
      masteryLevel: 3, progress: 82, state: 'BIJNA KLAAR', certified: true,
      lastTouched: 'gisteren · 19:32',
      rating: { avg: 4.5, count: 488 }, useCount: 1980, masteryRate: 82, pulseVerified: true,
    },
    {
      id: 'eng-u5', subject: 'engels', method: 'Stepping Up',
      level: 'havo-3', chapterNo: 'U5', title: 'Past tenses & onregelmatige werkwoorden',
      masteryLevel: 2, progress: 60, state: 'NU BEZIG', certified: true,
      lastTouched: '2 dagen geleden',
      rating: { avg: 4.6, count: 920 }, useCount: 3520, masteryRate: 85, pulseVerified: true,
    },
    {
      id: 'bio-h4', subject: 'biologie', method: 'Biologie voor jou',
      level: 'havo-3', chapterNo: 'H4', title: 'DNA en erfelijkheid',
      masteryLevel: 0, progress: 0, state: 'NIEUW', certified: true,
      lastTouched: 'nog niet begonnen',
      rating: { avg: 4.4, count: 340 }, useCount: 1240, masteryRate: 71, pulseVerified: true,
    },
    {
      id: 'gesch-h7', subject: 'geschiedenis', method: 'Feniks',
      level: 'havo-3', chapterNo: 'H7', title: 'De Industriële Revolutie',
      masteryLevel: 1, progress: 18, state: 'GESTART', certified: true,
      lastTouched: 'vorige week',
      rating: { avg: 4.3, count: 215 }, useCount: 890, masteryRate: 68, pulseVerified: true,
    },
    {
      id: 'bio-h2', subject: 'biologie', method: 'Biologie voor jou',
      level: 'havo-3', chapterNo: 'H2', title: 'Stofwisseling',
      masteryLevel: 4, progress: 100, state: 'AFGEROND', certified: true,
      lastTouched: '2 weken geleden',
      rating: { avg: 4.8, count: 712 }, useCount: 2410, masteryRate: 89, pulseVerified: true,
    },
    // Eigen content
    {
      id: 'fra-u2', subject: 'frans', method: 'Eigen samenvatting',
      level: 'havo-3', chapterNo: 'U2', title: 'Le passé composé — uploaded.pdf',
      masteryLevel: 1, progress: 12, state: 'EIGEN MATERIAAL', certified: false,
      lastTouched: '4 dagen geleden',
      shared: 'private',
    },
    {
      id: 'eng-idioms', subject: 'engels', method: 'Eigen flashcards-set',
      level: 'havo-3', chapterNo: '–', title: 'Idioms & phrasal verbs',
      masteryLevel: 2, progress: 48, state: 'EIGEN MATERIAAL', certified: false,
      lastTouched: 'vorige week',
      shared: 'public',
      rating: { avg: 4.2, count: 18 }, useCount: 47, masteryRate: 64,
    },
  ];

  // Community: door andere studenten gemaakt en gedeeld
  const MOCK_COMMUNITY = [
    {
      id: 'com-bio-h3-mit', subject: 'biologie', method: 'Biologie voor jou · H3 — eigen aanvulling',
      level: 'havo-3', chapterNo: 'H3', title: 'Mitose & meiose — extra schema\'s en ezelsbruggetjes',
      author: 'cell_master_42', daysOld: 6,
      rating: { avg: 4.8, count: 184 }, useCount: 612, masteryRate: 81, pulseVerified: true,
    },
    {
      id: 'com-wis-h4-tip', subject: 'wiskunde', method: 'Eigen samenvatting',
      level: 'havo-3', chapterNo: 'H4', title: 'ABC-formule snelkoppelingen + 12 voorbeelden',
      author: 'mathfreak_19', daysOld: 12,
      rating: { avg: 4.6, count: 92 }, useCount: 318, masteryRate: 76, pulseVerified: true,
    },
    {
      id: 'com-fra-grammar', subject: 'frans', method: 'Eigen samenvatting',
      level: 'havo-3', chapterNo: 'U2-U4', title: 'Frans — alle tijden tot havo-3 in één overzicht',
      author: 'parlons_fr', daysOld: 28,
      rating: { avg: 4.9, count: 245 }, useCount: 870, masteryRate: 87, pulseVerified: true,
    },
    {
      id: 'com-gesch-rev', subject: 'geschiedenis', method: 'Eigen flashcards-set',
      level: 'havo-3', chapterNo: 'H7-H8', title: 'Revoluties 1789-1848 — kernconcepten',
      author: 'klio_history', daysOld: 4,
      rating: { avg: 4.4, count: 38 }, useCount: 124, masteryRate: 70, pulseVerified: false,
      isNew: true,
    },
    {
      id: 'com-eng-idioms-extra', subject: 'engels', method: 'Eigen flashcards-set',
      level: 'havo-3', chapterNo: 'U5', title: 'Engelse idioms — die je écht moet kennen voor de toets',
      author: 'studious_sam', daysOld: 19,
      rating: { avg: 4.5, count: 156 }, useCount: 522, masteryRate: 79, pulseVerified: true,
    },
    {
      id: 'com-bio-orgaan', subject: 'biologie', method: 'Eigen samenvatting',
      level: 'havo-2', chapterNo: 'H5', title: 'Organellen voor leerlingen — uitleg in eigen woorden',
      author: 'biojunkie', daysOld: 2,
      rating: { avg: 4.2, count: 14 }, useCount: 47, masteryRate: 65, pulseVerified: false,
      isNew: true,
    },
  ];

  const EERDER_GEUPLOAD = [
    {
      subject: 'frans', source: 'le-passe-compose.pdf',
      title: 'Le passé composé', masteryLevel: 1,
      pages: "4 pagina's · 18 kaarten", addedAgo: '4 dagen geleden',
    },
    {
      subject: 'engels', source: 'idioms-set.txt',
      title: 'Idioms & phrasal verbs', masteryLevel: 2,
      pages: '32 zinnen · 32 kaarten', addedAgo: 'vorige week',
    },
    {
      subject: 'aardrijkskunde', source: 'klimaat-fotos.jpg',
      title: 'Klimaatzones — schoolbord-foto', masteryLevel: 0,
      pages: '1 foto · 8 kaarten', addedAgo: '2 weken geleden',
    },
  ];

  const TABS = [
    { id: 'eigen',     label: 'Eigen content',  icon: 'upload',      count: null },
    { id: 'community', label: 'Community',      icon: 'users',       count: null },
    { id: 'cert',      label: 'Gecertificeerd', icon: 'badge-check', count: null },
  ];

  const COMMUNITY_SORTS = [
    { id: 'top',     label: 'Top gewaardeerd', icon: 'star' },
    { id: 'used',    label: 'Meest gebruikt',  icon: 'users' },
    { id: 'level',   label: 'Voor jouw niveau', icon: 'target' },
    { id: 'new',     label: 'Nieuw',           icon: 'sparkles' },
  ];

  /* ─── Sub-components ─────────────────────────────────────── */

  /* Subject categorieën — patroon uit Snapsnelds quiz-filter */
  const MIJN_VAKKEN = ['biologie', 'wiskunde', 'engels', 'geschiedenis'];
  const SUBJECT_CATEGORIES = [
    { id: 'mine',  label: 'Mijn vakken', subjects: MIJN_VAKKEN },
    { id: 'talen', label: 'Talen',        subjects: ['engels', 'frans', 'duits', 'nederlands'] },
    { id: 'exact', label: 'Exact',        subjects: ['wiskunde', 'natuurkunde', 'scheikunde', 'biologie', 'informatica'] },
    { id: 'mens',  label: 'Maatschappij', subjects: ['geschiedenis', 'aardrijkskunde', 'economie'] },
    { id: 'alle',  label: 'Alle',         subjects: ['biologie', 'wiskunde', 'engels', 'geschiedenis', 'frans', 'duits', 'nederlands', 'natuurkunde', 'scheikunde', 'informatica', 'aardrijkskunde', 'economie'] },
  ];

  const NIVEAUS = ['vmbo-3', 'vmbo-4', 'havo-3', 'havo-4', 'havo-5', 'vwo-3', 'vwo-4', 'vwo-5', 'vwo-6'];

  function FilterBar({ t, filters, setFilters }) {
    const { useState: useS, useRef: useR, useEffect: useE } = React;
    const [vakSheetOpen, setVakSheetOpen] = useS(false);
    const [vakCategory, setVakCategory] = useS('mine');
    const [niveauOpen, setNiveauOpen] = useS(false);
    const vakRef = useR(null);
    const niveauRef = useR(null);
    const dark = t.mode === 'dark';

    // Close on outside click
    useE(() => {
      function handleClick(e) {
        if (vakRef.current && !vakRef.current.contains(e.target)) setVakSheetOpen(false);
        if (niveauRef.current && !niveauRef.current.contains(e.target)) setNiveauOpen(false);
      }
      document.addEventListener('mousedown', handleClick);
      return () => document.removeEventListener('mousedown', handleClick);
    }, []);

    function toggleFilter(key) {
      setFilters(prev => ({ ...prev, [key]: !prev[key] }));
    }
    function setVak(s) {
      setFilters(prev => ({ ...prev, vak: s }));
      setVakSheetOpen(false);
    }
    function clearVak() { setFilters(prev => ({ ...prev, vak: null })); }
    function setNiveau(n) {
      setFilters(prev => ({ ...prev, niveau: n }));
      setNiveauOpen(false);
    }
    function clearNiveau() { setFilters(prev => ({ ...prev, niveau: null })); }

    /* Filter-pill (dropdown trigger) */
    function FilterPill({ pillRef, icon, label, value, onClear, active, onClick, chevron = true }) {
      return (
        <span
          ref={pillRef}
          onClick={onClick}
          style={{
            display: 'inline-flex', alignItems: 'center', gap: 6,
            padding: active ? '5px 6px 5px 11px' : '5px 11px',
            borderRadius: 999,
            background: active
              ? (dark ? 'rgba(0,180,216,0.14)' : 'rgba(0,150,199,0.10)')
              : t.cardSunken,
            color: active ? t.primary : t.fgDim,
            border: `1px solid ${active
              ? (dark ? 'rgba(0,180,216,0.35)' : 'rgba(0,150,199,0.32)')
              : t.border}`,
            fontSize: 11.5, fontWeight: 800, cursor: 'pointer',
            whiteSpace: 'nowrap', userSelect: 'none',
            position: 'relative',
          }}
        >
          {icon && <PI name={icon} size={12} color={active ? t.primary : t.fgMute} strokeWidth={2.4} />}
          <span style={{ textTransform: value ? 'capitalize' : 'none' }}>{value || label}</span>
          {active && onClear ? (
            <span
              onClick={(e) => { e.stopPropagation(); onClear(); }}
              style={{
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                width: 17, height: 17, borderRadius: 999,
                background: dark ? 'rgba(255,255,255,0.10)' : 'rgba(15,23,42,0.06)',
                marginLeft: 2,
              }}
            >
              <PI name="x" size={10} color={active ? t.primary : t.fgMute} strokeWidth={2.6} />
            </span>
          ) : chevron ? (
            <PI name="chevron-down" size={11} color={active ? t.primary : t.fgMute} strokeWidth={2.4} />
          ) : null}
        </span>
      );
    }

    /* Toggle pill (no dropdown) */
    function TogglePill({ icon, label, active, onClick }) {
      return (
        <span
          onClick={onClick}
          style={{
            display: 'inline-flex', alignItems: 'center', gap: 5,
            padding: '5px 11px', borderRadius: 999,
            background: active ? t.fg : t.cardSunken,
            color: active ? t.bg : t.fgDim,
            border: `1px solid ${active ? t.fg : t.border}`,
            fontSize: 11.5, fontWeight: 800, cursor: 'pointer',
            whiteSpace: 'nowrap', userSelect: 'none',
          }}>
          {icon && <PI name={icon} size={11} color={active ? t.bg : t.fgMute} strokeWidth={2.4} />}
          {label}
        </span>
      );
    }

    /* Subject sheet (dropdown popover) */
    const currentCategory = SUBJECT_CATEGORIES.find(c => c.id === vakCategory) || SUBJECT_CATEGORIES[0];
    const SheetPopover = vakSheetOpen && (
      <div style={{
        position: 'absolute', top: 'calc(100% + 6px)', left: 0, zIndex: 200,
        width: 440, background: t.card, border: `1px solid ${t.border}`,
        borderRadius: 12, overflow: 'hidden',
        boxShadow: dark
          ? '0 16px 48px rgba(0,0,0,0.55), 0 4px 12px rgba(0,0,0,0.30)'
          : '0 16px 48px rgba(15,23,42,0.18), 0 4px 12px rgba(15,23,42,0.08)',
      }}>
        {/* Header */}
        <div style={{
          padding: '14px 16px 10px',
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        }}>
          <span style={{ fontFamily: 'Fredoka One', fontSize: 14, color: t.fg }}>Kies een vak</span>
          <button
            onClick={() => setVakSheetOpen(false)}
            style={{
              width: 24, height: 24, borderRadius: 999,
              background: t.cardSunken, border: `1px solid ${t.border}`,
              color: t.fgMute, cursor: 'pointer',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>
            <PI name="x" size={11} strokeWidth={2.6} />
          </button>
        </div>
        {/* Subject grid */}
        <div style={{
          padding: '8px 16px 14px',
          display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8,
        }}>
          {currentCategory.subjects.map(s => {
            const hex = (window.SUBJECTS && window.SUBJECTS[s]) || '#64748B';
            const isMine = MIJN_VAKKEN.includes(s);
            const isActive = filters.vak === s;
            return (
              <button
                key={s}
                onClick={() => setVak(s)}
                style={{
                  display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6,
                  padding: '10px 8px', borderRadius: 10,
                  background: isActive ? hexToRgba(hex, 0.14) : t.cardSunken,
                  border: `1px solid ${isActive ? hex : t.border}`,
                  cursor: 'pointer',
                  position: 'relative',
                }}>
                {isMine && (
                  <span style={{
                    position: 'absolute', top: 4, right: 4, width: 6, height: 6,
                    borderRadius: 999, background: t.primary,
                  }} title="Een van jouw vakken" />
                )}
                <SubjectChip t={t} subject={s} size="md" iconOnly />
                <span style={{
                  fontSize: 11, fontWeight: 800, color: t.fg,
                  textTransform: 'capitalize', textAlign: 'center', lineHeight: 1.2,
                }}>{s}</span>
              </button>
            );
          })}
        </div>
        {/* Category tabs */}
        <div className="hide-scrollbar" style={{
          display: 'flex', gap: 2,
          padding: '6px 8px', borderTop: `1px solid ${t.border}`,
          background: t.cardSunken,
          overflowX: 'auto',
          scrollbarWidth: 'none',
          msOverflowStyle: 'none',
        }}>
          {SUBJECT_CATEGORIES.map(cat => {
            const isActive = vakCategory === cat.id;
            return (
              <button
                key={cat.id}
                onClick={() => setVakCategory(cat.id)}
                style={{
                  padding: '6px 11px', borderRadius: 999,
                  background: isActive ? t.card : 'transparent',
                  border: `1px solid ${isActive ? t.border : 'transparent'}`,
                  color: isActive ? t.fg : t.fgDim,
                  fontSize: 11, fontWeight: 800, cursor: 'pointer',
                  whiteSpace: 'nowrap',
                }}>
                {cat.label}
              </button>
            );
          })}
        </div>
      </div>
    );

    /* Niveau dropdown */
    const NiveauPopover = niveauOpen && (
      <div style={{
        position: 'absolute', top: 'calc(100% + 6px)', left: 0, zIndex: 200,
        width: 240, background: t.card, border: `1px solid ${t.border}`,
        borderRadius: 12, overflow: 'hidden',
        boxShadow: dark
          ? '0 16px 48px rgba(0,0,0,0.55)'
          : '0 16px 48px rgba(15,23,42,0.18)',
        padding: 6,
      }}>
        {NIVEAUS.map(n => {
          const isActive = filters.niveau === n;
          const isMine = n === 'havo-3';
          return (
            <button
              key={n}
              onClick={() => setNiveau(n)}
              style={{
                display: 'flex', alignItems: 'center', gap: 8,
                width: '100%', padding: '8px 10px', borderRadius: 8,
                background: isActive ? t.primaryDim : 'transparent',
                color: isActive ? t.primary : t.fg,
                border: 'none', cursor: 'pointer', textAlign: 'left',
                fontSize: 12.5, fontWeight: 700, fontFamily: 'Nunito',
                textTransform: 'capitalize',
              }}>
              {isActive && <PI name="check" size={12} color={t.primary} strokeWidth={2.6} />}
              {!isActive && <span style={{ width: 12 }} />}
              <span style={{ flex: 1 }}>{n}</span>
              {isMine && (
                <span style={{
                  fontSize: 9, fontWeight: 800, letterSpacing: 0.4, textTransform: 'uppercase',
                  padding: '1px 6px', borderRadius: 4,
                  background: t.primaryDim, color: t.primary,
                }}>jouw niveau</span>
              )}
            </button>
          );
        })}
      </div>
    );

    const anyFilterActive = filters.vak || filters.niveau || filters.achterstand || filters.recent;

    return (
      <div style={{
        display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap',
        padding: '12px 16px', background: t.card,
        border: `1px solid ${t.border}`, borderRadius: 10,
      }}>
        <span style={{
          fontSize: 10.5, color: t.fgMute, fontWeight: 800,
          letterSpacing: 0.4, textTransform: 'uppercase',
        }}>Filter</span>

        <div style={{ position: 'relative' }} ref={vakRef}>
          <FilterPill
            icon="book-marked"
            label="Vakken"
            value={filters.vak}
            active={!!filters.vak}
            onClick={() => { setVakSheetOpen(o => !o); setNiveauOpen(false); }}
            onClear={clearVak}
          />
          {SheetPopover}
        </div>

        <div style={{ position: 'relative' }} ref={niveauRef}>
          <FilterPill
            icon="graduation-cap"
            label="Niveau"
            value={filters.niveau}
            active={!!filters.niveau}
            onClick={() => { setNiveauOpen(o => !o); setVakSheetOpen(false); }}
            onClear={clearNiveau}
          />
          {NiveauPopover}
        </div>

        <span style={{ width: 1, height: 22, background: t.border }} />

        <TogglePill
          icon="alert-circle"
          label="Achterstand"
          active={filters.achterstand}
          onClick={() => toggleFilter('achterstand')}
        />
        <TogglePill
          icon="clock"
          label="Recent gezien"
          active={filters.recent}
          onClick={() => toggleFilter('recent')}
        />

        <span style={{ flex: 1 }} />

        {anyFilterActive && (
          <button
            onClick={() => setFilters({ vak: null, niveau: null, achterstand: false, recent: false })}
            style={{
              display: 'inline-flex', alignItems: 'center', gap: 6,
              padding: '6px 10px', borderRadius: 8,
              background: 'transparent', border: 'none',
              color: t.fgMute, fontSize: 11, fontWeight: 700, cursor: 'pointer',
              whiteSpace: 'nowrap',
            }}>
            <PI name="x" size={11} />
            Filter wissen
          </button>
        )}
      </div>
    );
  }

  function LibraryRow({ t, item, navigate, first, tab, onShareClick }) {
    const dark = t.mode === 'dark';
    const stateColor = (() => {
      switch (item.state) {
        case 'NU BEZIG':        return t.primary;
        case 'BIJNA KLAAR':     return dark ? '#FBBF24' : '#B45309';
        case 'AFGEROND':        return dark ? '#22C55E' : '#15803D';
        case 'EIGEN MATERIAAL': return dark ? '#9D4EDD' : '#7C3AED';
        default:                return t.fgMute;
      }
    })();

    const isCommunity = tab === 'community';
    const isEigen = tab === 'eigen';
    const isCert = tab === 'cert';

    return (
      <div
        onClick={() => navigate({ name: 'chapter', chapterId: item.id })}
        style={{
          display: 'grid',
          gridTemplateColumns: '36px 1fr auto auto',
          gap: 14, alignItems: 'center',
          padding: '14px 22px',
          borderTop: first ? 'none' : `1px solid ${t.border}`,
          cursor: 'pointer',
          transition: 'background 0.12s',
        }}
        onMouseEnter={e => { e.currentTarget.style.background = dark ? 'rgba(255,255,255,0.03)' : 'rgba(15,23,42,0.02)'; }}
        onMouseLeave={e => { e.currentTarget.style.background = 'transparent'; }}
      >
        <SubjectChip t={t} subject={item.subject} size="lg" iconOnly />

        <div style={{ minWidth: 0, display: 'flex', flexDirection: 'column', gap: 4 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
            <span style={{
              fontSize: 10.5, color: t.fgMute, fontWeight: 800,
              letterSpacing: 0.3, textTransform: 'uppercase',
            }}>
              {item.method} · {item.level} · {item.chapterNo}
            </span>
            {isCert && item.certified && (
              <span style={{
                display: 'inline-flex', alignItems: 'center', gap: 3,
                fontSize: 9.5, color: dark ? '#22C55E' : '#15803D', fontWeight: 800,
                letterSpacing: 0.3, textTransform: 'uppercase',
              }}>
                <PI name="badge-check" size={10} color={dark ? '#22C55E' : '#15803D'} strokeWidth={2.6} />
                Gecert.
              </span>
            )}
            {isCommunity && item.author && (
              <span style={{
                display: 'inline-flex', alignItems: 'center', gap: 4,
                fontSize: 10.5, color: dark ? '#A78BFA' : '#7C3AED', fontWeight: 800,
              }}>
                <PI name="user" size={10} color={dark ? '#A78BFA' : '#7C3AED'} strokeWidth={2.6} />
                {item.author}
              </span>
            )}
            {isCommunity && item.isNew && (
              <span style={{
                fontSize: 9.5, color: dark ? '#FBBF24' : '#B45309', fontWeight: 800,
                letterSpacing: 0.4, textTransform: 'uppercase',
                padding: '1px 6px', borderRadius: 4,
                background: dark ? 'rgba(251,191,36,0.14)' : 'rgba(180,83,9,0.10)',
                border: `1px solid ${dark ? 'rgba(251,191,36,0.32)' : 'rgba(180,83,9,0.28)'}`,
              }}>NIEUW</span>
            )}
            {item.pulseVerified && (
              <span title="Door Pulse gecheckt op kwaliteit" style={{
                display: 'inline-flex', alignItems: 'center', gap: 3,
                fontSize: 9.5, color: t.primary, fontWeight: 800,
                letterSpacing: 0.3, textTransform: 'uppercase',
              }}>
                <PI name="sparkles" size={10} color={t.primary} strokeWidth={2.4} />
                Pulse
              </span>
            )}
            {isEigen && item.shared === 'public' && (
              <span style={{
                display: 'inline-flex', alignItems: 'center', gap: 3,
                fontSize: 9.5, color: dark ? '#22C55E' : '#15803D', fontWeight: 800,
                letterSpacing: 0.3, textTransform: 'uppercase',
                padding: '1px 6px', borderRadius: 4,
                background: dark ? 'rgba(34,197,94,0.12)' : 'rgba(21,128,61,0.08)',
                border: `1px solid ${dark ? 'rgba(34,197,94,0.28)' : 'rgba(21,128,61,0.22)'}`,
              }}>
                <PI name="globe" size={10} color={dark ? '#22C55E' : '#15803D'} strokeWidth={2.6} />
                Publiek
              </span>
            )}
            {isEigen && (item.shared === 'private' || !item.shared) && (
              <span style={{
                display: 'inline-flex', alignItems: 'center', gap: 3,
                fontSize: 9.5, color: t.fgMute, fontWeight: 800,
                letterSpacing: 0.3, textTransform: 'uppercase',
                padding: '1px 6px', borderRadius: 4,
                background: t.cardSunken, border: `1px solid ${t.border}`,
              }}>
                <PI name="lock" size={10} color={t.fgMute} strokeWidth={2.6} />
                Privé
              </span>
            )}
          </div>
          <div style={{
            fontFamily: 'Nunito', fontSize: 14.5, color: t.fg, fontWeight: 800,
            letterSpacing: '-0.005em',
            overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
          }}>{item.title}</div>
          <div style={{
            display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap',
            fontSize: 11, color: t.fgDim, fontWeight: 600,
          }}>
            {item.rating && item.rating.count > 0 && (
              <>
                <StarRating t={t} avg={item.rating.avg} count={item.rating.count} size="sm" />
                <span style={{ color: t.fgMute }}>·</span>
              </>
            )}
            {item.useCount > 0 && (
              <>
                <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
                  <PI name="users" size={11} color={t.fgMute} strokeWidth={2.4} />
                  {item.useCount.toLocaleString('nl-NL')}
                </span>
                <span style={{ color: t.fgMute }}>·</span>
              </>
            )}
            {item.masteryRate != null && (
              <>
                <span title="% gebruikers dat mastery haalt" style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
                  <PI name="trending-up" size={11} color={t.fgMute} strokeWidth={2.4} />
                  {item.masteryRate}%
                </span>
                <span style={{ color: t.fgMute }}>·</span>
              </>
            )}
            {item.state && (isEigen || isCert) && (
              <>
                <span style={{
                  color: stateColor, fontWeight: 800,
                  letterSpacing: 0.3, textTransform: 'uppercase', fontSize: 10,
                }}>{item.state}</span>
                <span style={{ color: t.fgMute }}>·</span>
              </>
            )}
            <span>
              {isCommunity && item.daysOld != null
                ? (item.daysOld === 0 ? 'vandaag' : item.daysOld === 1 ? 'gisteren' : `${item.daysOld} dagen geleden`)
                : item.lastTouched}
            </span>
            {item.deadline && (
              <>
                <span style={{ color: t.fgMute }}>·</span>
                <span style={{
                  display: 'inline-flex', alignItems: 'center', gap: 4,
                  color: dark ? '#F472B6' : '#BE185D',
                  fontWeight: 800, letterSpacing: 0.3, textTransform: 'uppercase', fontSize: 10,
                }}>
                  <PI name="alert-circle" size={10} color={dark ? '#F472B6' : '#BE185D'} strokeWidth={2.6} />
                  {item.deadline}
                </span>
              </>
            )}
          </div>
        </div>

        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 4 }}>
          {(isEigen || isCert) && item.masteryLevel != null && (
            <>
              <MasteryDots t={t} level={item.masteryLevel} size="sm" />
              {item.progress != null && (
                <span style={{ fontSize: 10.5, color: t.fgMute, fontWeight: 800 }}>
                  {item.progress}% gelezen
                </span>
              )}
            </>
          )}
          {isEigen && onShareClick && (
            <button
              onClick={(e) => { e.stopPropagation(); onShareClick(item); }}
              style={{
                display: 'inline-flex', alignItems: 'center', gap: 5,
                padding: '5px 10px', borderRadius: 999,
                background: item.shared === 'public' ? t.cardSunken : (dark ? 'rgba(0,180,216,0.12)' : 'rgba(0,150,199,0.10)'),
                color: item.shared === 'public' ? t.fgDim : t.primary,
                border: `1px solid ${item.shared === 'public' ? t.border : (dark ? 'rgba(0,180,216,0.28)' : 'rgba(0,150,199,0.24)')}`,
                fontSize: 10.5, fontWeight: 800, cursor: 'pointer',
                marginTop: 4,
              }}
            >
              <PI name={item.shared === 'public' ? 'lock' : 'share-2'} size={10}
                color={item.shared === 'public' ? t.fgDim : t.primary} strokeWidth={2.4} />
              {item.shared === 'public' ? 'Maak privé' : 'Deel'}
            </button>
          )}
        </div>

        <PI name="chevron-right" size={16} color={t.fgMute} strokeWidth={2.4} />
      </div>
    );
  }

  function UploadTegel({ t, item }) {
    const fmtIcon = item.source.endsWith('.pdf') ? 'file-text'
                  : (item.source.endsWith('.jpg') || item.source.endsWith('.png')) ? 'image'
                  : 'type';
    return (
      <div style={{
        background: t.card, border: `1px solid ${t.border}`,
        borderRadius: 10, padding: 14,
        display: 'flex', flexDirection: 'column', gap: 10,
        cursor: 'pointer',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <SubjectChip t={t} subject={item.subject} size="sm" iconOnly />
          <span style={{
            fontSize: 10, color: t.fgMute, fontWeight: 800,
            letterSpacing: 0.3, textTransform: 'uppercase',
            display: 'inline-flex', alignItems: 'center', gap: 4,
          }}>
            <PI name={fmtIcon} size={10} color={t.fgMute} strokeWidth={2.4} />
            {item.source}
          </span>
        </div>
        <div style={{
          fontFamily: 'Nunito', fontSize: 13.5, color: t.fg, fontWeight: 800,
          lineHeight: 1.3, minHeight: 36,
          overflow: 'hidden', display: '-webkit-box',
          WebkitLineClamp: 2, WebkitBoxOrient: 'vertical',
        }}>{item.title}</div>
        <MasteryDots t={t} level={item.masteryLevel} size="sm" />
        <div style={{
          paddingTop: 6, borderTop: `1px dashed ${t.border}`,
          fontSize: 10.5, color: t.fgMute, fontWeight: 700,
          display: 'flex', justifyContent: 'space-between',
        }}>
          <span>{item.pages}</span>
          <span>{item.addedAgo}</span>
        </div>
      </div>
    );
  }

  /* ─── Mode: list ─────────────────────────────────────────── */
  function ModeList({ t, navigate, tab, setTab, filters, setFilters, setMode, communitySort, setCommunitySort, onShareClick }) {
    const dark = t.mode === 'dark';

    const isEigenItem = item =>
      item.method === 'Eigen samenvatting' ||
      item.method === 'Eigen flashcards-set' ||
      item.state === 'EIGEN MATERIAAL';

    // Source list per tab
    const sourceItems = tab === 'community' ? MOCK_COMMUNITY : MOCK_KB_ITEMS;

    const filteredItems = sourceItems.filter(item => {
      if (tab === 'eigen' && !isEigenItem(item)) return false;
      if (tab === 'cert' && !item.certified) return false;
      // Community: alle MOCK_COMMUNITY zijn al community-items
      if (filters.vak && item.subject !== filters.vak) return false;
      if (filters.achterstand && item.masteryLevel != null && item.masteryLevel >= 2) return false;
      if (filters.recent && tab !== 'community' && item.lastTouched !== 'vandaag · 12:14' && item.lastTouched !== 'gisteren · 19:32') return false;
      return true;
    });

    // Apply community sort
    if (tab === 'community') {
      filteredItems.sort((a, b) => {
        if (communitySort === 'top')   return (b.rating?.avg || 0) - (a.rating?.avg || 0);
        if (communitySort === 'used')  return (b.useCount || 0) - (a.useCount || 0);
        if (communitySort === 'level') {
          // Mock: prioritize havo-3 (jouw niveau)
          const aMatch = a.level === 'havo-3' ? 0 : 1;
          const bMatch = b.level === 'havo-3' ? 0 : 1;
          if (aMatch !== bMatch) return aMatch - bMatch;
          return (b.rating?.avg || 0) - (a.rating?.avg || 0);
        }
        if (communitySort === 'new')   return (a.daysOld || 0) - (b.daysOld || 0);
        return 0;
      });
    }

    const tabsWithCounts = TABS.map(tabItem => ({
      ...tabItem,
      count: (() => {
        if (tabItem.id === 'eigen') return MOCK_KB_ITEMS.filter(isEigenItem).length;
        if (tabItem.id === 'cert') return MOCK_KB_ITEMS.filter(i => i.certified).length;
        if (tabItem.id === 'community') return MOCK_COMMUNITY.length;
        return null;
      })(),
    }));

    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
        <FilterBar t={t} filters={filters} setFilters={setFilters} />

        <div style={{
          background: t.card, border: `1px solid ${t.border}`,
          borderRadius: 10, overflow: 'hidden',
        }}>
          {/* Tabs */}
          <div style={{ padding: '0 22px' }}>
            <div style={{
              display: 'flex', gap: 4,
              borderBottom: `1px solid ${t.border}`,
            }}>
              {tabsWithCounts.map(tabItem => {
                const isActive = tabItem.id === tab;
                const c = t.primary;
                return (
                  <div
                    key={tabItem.id}
                    onClick={() => setTab(tabItem.id)}
                    style={{
                      padding: '12px 18px',
                      borderBottom: `2px solid ${isActive ? c : 'transparent'}`,
                      marginBottom: -1,
                      display: 'inline-flex', alignItems: 'center', gap: 8,
                      cursor: 'pointer',
                    }}
                  >
                    {tabItem.icon && (
                      <PI name={tabItem.icon} size={14}
                        color={isActive ? c : t.fgMute} strokeWidth={2.4} />
                    )}
                    <span style={{
                      fontFamily: 'Nunito', fontSize: 13, fontWeight: 800,
                      color: isActive ? t.fg : t.fgMute,
                      whiteSpace: 'nowrap',
                    }}>{tabItem.label}</span>
                    {tabItem.count != null && (
                      <span style={{
                        fontSize: 10.5, fontWeight: 800,
                        padding: '2px 7px', borderRadius: 999,
                        background: isActive
                          ? `color-mix(in srgb, ${c} 14%, transparent)`
                          : t.cardSunken,
                        color: isActive ? c : t.fgMute,
                        border: `1px solid ${isActive
                          ? `color-mix(in srgb, ${c} 28%, transparent)`
                          : t.border}`,
                      }}>{tabItem.count}</span>
                    )}
                  </div>
                );
              })}
            </div>
          </div>

          {/* Counter bar */}
          <div style={{
            padding: '14px 22px',
            borderBottom: `1px solid ${t.border}`,
            display: 'flex', alignItems: 'center', gap: 12,
          }}>
            <span style={{
              fontSize: 11.5, color: t.fgMute, fontWeight: 800,
              letterSpacing: 0.4, textTransform: 'uppercase',
            }}>
              {filteredItems.length} {filteredItems.length === 1 ? 'item' : 'items'}
              {tab === 'eigen' ? ' · eigen content' : tab === 'cert' ? ' · gecertificeerd' : tab === 'community' ? ' · community' : ''}
              {filters.vak && ` · ${filters.vak.charAt(0).toUpperCase() + filters.vak.slice(1)}`}
            </span>
            <span style={{ flex: 1 }} />
            {tab === 'eigen' && (
              <button
                onClick={() => navigate('ai-creator')}
                style={{
                  display: 'inline-flex', alignItems: 'center', gap: 6,
                  padding: '6px 12px', borderRadius: 8,
                  background: 'transparent', border: `1px solid ${t.border}`,
                  color: t.fgDim,
                  fontSize: 11.5, fontWeight: 800, cursor: 'pointer',
                  fontFamily: 'Nunito', whiteSpace: 'nowrap',
                }}
              >
                <PI name="sparkles" size={12} color={t.fgDim} strokeWidth={2.4} />
                + Materiaal toevoegen
              </button>
            )}
          </div>

          {/* Eigen content disclaimer */}
          {tab === 'eigen' && (
            <div style={{
              padding: '10px 22px',
              borderBottom: `1px solid ${t.border}`,
              display: 'flex', alignItems: 'center', gap: 8,
            }}>
              <PI name="lock" size={12} color={t.fgMute} strokeWidth={2.2} />
              <span style={{ fontSize: 11.5, color: t.fgMute, fontWeight: 600 }}>
                Privé tenzij jij het deelt. Klik 'Deel' om publiek te maken — andere leerlingen kunnen het dan vinden via Community.
              </span>
            </div>
          )}

          {/* Community sort-bar + Pulse aanbeveling */}
          {tab === 'community' && (
            <>
              <div style={{
                padding: '12px 22px',
                borderBottom: `1px solid ${t.border}`,
                display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap',
              }}>
                <span style={{
                  fontSize: 10.5, color: t.fgMute, fontWeight: 800,
                  letterSpacing: 0.4, textTransform: 'uppercase',
                }}>Sorteer</span>
                {COMMUNITY_SORTS.map(s => {
                  const active = communitySort === s.id;
                  return (
                    <button
                      key={s.id}
                      onClick={() => setCommunitySort(s.id)}
                      style={{
                        display: 'inline-flex', alignItems: 'center', gap: 5,
                        padding: '5px 10px', borderRadius: 999,
                        background: active ? t.fg : t.cardSunken,
                        color: active ? t.bg : t.fgDim,
                        border: `1px solid ${active ? t.fg : t.border}`,
                        fontSize: 11, fontWeight: 800, cursor: 'pointer',
                        fontFamily: 'Nunito', whiteSpace: 'nowrap',
                      }}
                    >
                      <PI name={s.icon} size={11} color={active ? t.bg : t.fgMute} strokeWidth={2.4} />
                      {s.label}
                    </button>
                  );
                })}
              </div>

              {/* Pulse aanbeveling */}
              <div style={{
                margin: '14px 22px 0',
                padding: '12px 14px', borderRadius: 10,
                background: dark ? 'rgba(157,78,221,0.10)' : 'rgba(124,58,237,0.06)',
                border: `1px solid ${dark ? 'rgba(157,78,221,0.24)' : 'rgba(124,58,237,0.20)'}`,
                display: 'flex', alignItems: 'center', gap: 12,
              }}>
                <PulseMascot size={32} mood="curious" />
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 13, color: t.fg, fontWeight: 800, lineHeight: 1.3 }}>
                    Klasgenoten van havo-3 vinden deze top
                  </div>
                  <div style={{ fontSize: 11.5, color: t.fgDim, fontWeight: 600, marginTop: 2 }}>
                    Pulse heeft 3 hoofdstukken voor jouw niveau geselecteerd. Klik 'Voor jouw niveau' om ze bovenaan te zetten.
                  </div>
                </div>
              </div>
            </>
          )}

          {/* Rows */}
          {filteredItems.length > 0 ? (
            <div>
              {filteredItems.map((item, i) => (
                <LibraryRow
                  key={item.id} t={t} item={item} navigate={navigate} first={i === 0}
                  tab={tab} onShareClick={onShareClick}
                />
              ))}
            </div>
          ) : (
            <div style={{
              padding: '40px 22px',
              display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 12,
              textAlign: 'center',
            }}>
              <PulseMascot size={56} mood="curious" />
              <div style={{ fontFamily: 'Fredoka One', fontSize: 18, color: t.fg }}>
                Geen hoofdstukken gevonden
              </div>
              <div style={{ fontSize: 13, color: t.fgDim, fontWeight: 600 }}>
                Pas de filters aan of voeg een nieuw hoofdstuk toe.
              </div>
            </div>
          )}
        </div>

        {/* Pulse entry */}
        <div style={{
          background: t.card, border: `1px solid ${t.border}`,
          borderRadius: 10, padding: '16px 18px',
          display: 'flex', alignItems: 'center', gap: 14,
        }}>
          <PulseMascot size={36} mood="thinking" />
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontFamily: 'Fredoka One', fontSize: 15, color: t.fg, lineHeight: 1.25 }}>
              Niet zeker wat je zoekt?
            </div>
            <div style={{ fontSize: 12, color: t.fgDim, fontWeight: 600, marginTop: 4 }}>
              Beschrijf het onderwerp — Pulse vindt het hoofdstuk in je bibliotheek.
            </div>
          </div>
          <button
            onClick={() => console.log('Vraag aan Pulse')}
            style={{
              display: 'inline-flex', alignItems: 'center', gap: 6,
              padding: '9px 14px', borderRadius: 999,
              background: dark ? 'rgba(157,78,221,0.16)' : 'rgba(124,58,237,0.10)',
              color: dark ? '#9D4EDD' : '#7C3AED',
              border: `1px solid ${dark ? 'rgba(157,78,221,0.30)' : 'rgba(124,58,237,0.28)'}`,
              fontSize: 12.5, fontWeight: 800, cursor: 'pointer',
              whiteSpace: 'nowrap',
            }}
          >
            <PI name="message-circle" size={13} color={dark ? '#9D4EDD' : '#7C3AED'} strokeWidth={2.4} />
            Vraag aan Pulse
          </button>
        </div>
      </div>
    );
  }

  /* ─── Mode: upload ───────────────────────────────────────── */
  function ModeUpload({ t, setMode }) {
    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
        {/* Breadcrumb / back */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11.5, color: t.fgMute, fontWeight: 700 }}>
          <span
            onClick={() => setMode('list')}
            style={{ cursor: 'pointer', color: t.primary }}
          >Bibliotheek</span>
          <PI name="chevron-right" size={12} color={t.fgMute} />
          <span style={{ color: t.fgDim }}>Eigen materiaal toevoegen</span>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 300px', gap: 20, maxWidth: 1180 }}>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
            {/* Drop zone */}
            <div style={{
              background: t.card,
              border: `2px dashed ${t.fgMute}`,
              borderRadius: 12, padding: '40px 24px',
              display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 14,
              textAlign: 'center',
            }}>
              <div style={{
                width: 56, height: 56, borderRadius: 999,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                background: t.cardSunken, border: `1px solid ${t.border}`,
                color: t.primary,
              }}>
                <PI name="upload-cloud" size={26} strokeWidth={2.2} />
              </div>
              <div style={{
                fontFamily: 'Fredoka One', fontSize: 20, color: t.fg,
                lineHeight: 1.2, letterSpacing: '-0.01em',
              }}>Sleep een bestand hier of klik om te kiezen</div>
              <div style={{
                fontSize: 13, color: t.fgDim, fontWeight: 500, lineHeight: 1.55,
                maxWidth: 460,
              }}>
                PDF, foto of tekst. Pulse bouwt er een volledig leer-hoofdstuk van —
                samenvatting, flashcards, mindmap, je eigen Pulse-tutor en test-vragen.
              </div>

              {/* Output preview tegels */}
              <div style={{
                display: 'grid', gridTemplateColumns: 'repeat(5, auto)', gap: 8, marginTop: 6,
                justifyContent: 'center',
              }}>
                {[
                  { icon: 'file-text',     label: 'Samenvatting' },
                  { icon: 'git-branch',    label: 'Mindmap' },
                  { icon: 'layers',        label: 'Flashcards' },
                  { icon: 'message-circle', label: 'Vraag aan Pulse' },
                  { icon: 'brain',         label: 'Test jezelf' },
                ].map((o, i) => (
                  <span key={i} style={{
                    display: 'inline-flex', alignItems: 'center', gap: 5,
                    padding: '4px 9px', borderRadius: 999,
                    background: t.primaryDim, color: t.primary,
                    border: `1px solid ${t.mode === 'dark' ? 'rgba(0,180,216,0.28)' : 'rgba(0,150,199,0.24)'}`,
                    fontSize: 10.5, fontWeight: 800, whiteSpace: 'nowrap',
                  }}>
                    <PI name={o.icon} size={10} color={t.primary} strokeWidth={2.4} />
                    {o.label}
                  </span>
                ))}
              </div>
              <div style={{ display: 'flex', gap: 8, marginTop: 4, flexWrap: 'wrap', justifyContent: 'center' }}>
                {[
                  { icon: 'file-text', label: 'PDF' },
                  { icon: 'image',     label: 'Foto' },
                  { icon: 'type',      label: 'Plak tekst' },
                ].map(f => (
                  <span key={f.label} style={{
                    display: 'inline-flex', alignItems: 'center', gap: 5,
                    padding: '5px 10px', borderRadius: 999,
                    background: t.cardSunken, color: t.fgDim,
                    border: `1px solid ${t.border}`,
                    fontSize: 11, fontWeight: 700, whiteSpace: 'nowrap',
                  }}>
                    <PI name={f.icon} size={11} color={t.fgMute} strokeWidth={2.4} />
                    {f.label}
                  </span>
                ))}
              </div>
            </div>

            {/* Previously uploaded */}
            <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <PI name="folder-open" size={14} color={t.fgDim} strokeWidth={2.4} />
                <span style={{ fontFamily: 'Fredoka One', fontSize: 14, color: t.fg }}>Eerder geüpload</span>
                <span style={{ flex: 1 }} />
                <span style={{ fontSize: 11, color: t.fgMute, fontWeight: 700 }}>
                  {EERDER_GEUPLOAD.length} bestanden
                </span>
              </div>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12 }}>
                {EERDER_GEUPLOAD.map((item, i) => (
                  <UploadTegel key={i} t={t} item={item} />
                ))}
              </div>
            </div>
          </div>

          {/* Right rail */}
          <aside style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            {/* Pulse hint */}
            <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 }}>
                <PulseMascot size={32} mood="encouraging" />
                <span style={{ fontFamily: 'Fredoka One', fontSize: 14, color: t.fg, lineHeight: 1.25 }}>
                  Goeie aanvulling.
                </span>
              </div>
              <div style={{ fontSize: 12, color: t.fgDim, fontWeight: 600, lineHeight: 1.55 }}>
                Hoe meer Pulse van jou ziet, hoe beter we kunnen plannen. Eigen samenvattingen, schoolbord-foto's, of een PDF van de docent — alles werkt.
              </div>
            </div>

            {/* Formats card */}
            <div style={{
              background: t.card, border: `1px solid ${t.border}`,
              borderRadius: 10, padding: 16,
              display: 'flex', flexDirection: 'column', gap: 12,
            }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <PI name="info" size={14} color={t.fgDim} strokeWidth={2.4} />
                <span style={{ fontFamily: 'Fredoka One', fontSize: 14, color: t.fg }}>Wat kun je uploaden?</span>
              </div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
                {[
                  { icon: 'file-text', label: 'PDF', sub: 'Hoofdstuk-PDF, samenvatting' },
                  { icon: 'image',     label: 'Foto', sub: 'Schoolbord, schrift, schermafbeelding' },
                  { icon: 'type',      label: 'Tekst', sub: 'Plak tekst direct in' },
                  { icon: 'mic',       label: 'Spraak (binnenkort)', sub: 'Lees voor — Pulse zet om' },
                ].map((it, i) => (
                  <div key={i} style={{ display: 'flex', alignItems: 'flex-start', gap: 10 }}>
                    <PI name={it.icon} size={14} color={t.fgDim} strokeWidth={2.4}
                      style={{ marginTop: 2, flexShrink: 0 }} />
                    <div style={{ minWidth: 0 }}>
                      <div style={{ fontSize: 12.5, color: t.fg, fontWeight: 800 }}>{it.label}</div>
                      <div style={{ fontSize: 11, color: t.fgMute, fontWeight: 600, lineHeight: 1.4 }}>{it.sub}</div>
                    </div>
                  </div>
                ))}
              </div>
            </div>
          </aside>
        </div>

        <button
          onClick={() => setMode('list')}
          style={{
            alignSelf: 'flex-start',
            display: 'inline-flex', alignItems: 'center', gap: 6,
            padding: '8px 14px', borderRadius: 8,
            background: 'transparent', border: `1px solid ${t.border}`,
            color: t.fgDim, fontSize: 12, fontWeight: 800, cursor: 'pointer',
            fontFamily: 'Nunito',
          }}
        >
          <PI name="arrow-left" size={13} color={t.fgDim} strokeWidth={2.4} />
          Terug naar lijst
        </button>
      </div>
    );
  }

  /* ─── Mode: empty ────────────────────────────────────────── */
  function ModeEmpty({ t, setMode, navigate }) {
    const dark = t.mode === 'dark';
    return (
      <div style={{ display: 'flex', justifyContent: 'center', padding: '60px 20px' }}>
        <div style={{
          background: t.card, border: `1px solid ${t.border}`,
          borderRadius: 10, padding: '56px 48px',
          maxWidth: 560, width: '100%',
          display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 18,
          textAlign: 'center',
        }}>
          <PulseMascot size={140} mood="curious" />

          <h1 style={{
            margin: 0, fontFamily: 'Fredoka One', fontSize: 26,
            color: t.fg, lineHeight: 1.15, letterSpacing: '-0.01em',
          }}>Nog niets in je bibliotheek</h1>

          <p style={{
            margin: 0, fontSize: 14, color: t.fgDim,
            lineHeight: 1.6, fontWeight: 500, maxWidth: 420,
          }}>
            Voeg je eerste hoofdstuk toe of upload eigen materiaal — dan begint Pulse met plannen.
          </p>

          <div style={{
            display: 'flex', gap: 10, marginTop: 8, flexWrap: 'wrap',
            justifyContent: 'center',
          }}>
            <button
              onClick={() => console.log('Hoofdstuk toevoegen')}
              style={{
                display: 'inline-flex', alignItems: 'center', gap: 6,
                padding: '10px 18px', borderRadius: 999,
                background: t.primary, border: 'none',
                color: dark ? '#0A0F1E' : '#FFFFFF',
                fontSize: 13, fontWeight: 800, cursor: 'pointer',
                fontFamily: 'Nunito',
              }}
            >
              <PI name="book-plus" size={15} color={dark ? '#0A0F1E' : '#FFFFFF'} strokeWidth={2.4} />
              Hoofdstuk toevoegen
            </button>
            <button
              onClick={() => navigate && navigate('ai-creator')}
              style={{
                display: 'inline-flex', alignItems: 'center', gap: 6,
                padding: '10px 18px', borderRadius: 999,
                background: 'transparent',
                border: `1px solid ${t.border}`,
                color: t.fgDim, fontSize: 13, fontWeight: 800, cursor: 'pointer',
                fontFamily: 'Nunito',
              }}
            >
              <PI name="sparkles" size={15} color={t.fgDim} strokeWidth={2.4} />
              Materiaal toevoegen
            </button>
          </div>

          <div style={{
            paddingTop: 14, marginTop: 8, borderTop: `1px dashed ${t.border}`,
            width: '100%', display: 'flex', flexDirection: 'column', gap: 8,
            alignItems: 'center',
          }}>
            <span style={{
              fontSize: 10.5, color: t.fgMute, fontWeight: 800,
              letterSpacing: 0.4, textTransform: 'uppercase',
            }}>Hoe Pulse helpt</span>
            <div style={{
              display: 'flex', gap: 18, flexWrap: 'wrap', justifyContent: 'center',
              fontSize: 11.5, color: t.fgDim, fontWeight: 600,
            }}>
              {[
                { icon: 'book',     label: 'Methodes uit jouw klas' },
                { icon: 'upload',   label: "Eigen PDF's en foto's" },
                { icon: 'calendar', label: 'Plant op basis van toetsen' },
              ].map(item => (
                <span key={item.label} style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
                  <PI name={item.icon} size={13} color={t.fgMute} strokeWidth={2.4} />
                  {item.label}
                </span>
              ))}
            </div>
          </div>
        </div>
      </div>
    );
  }

  /* ─── Root view ──────────────────────────────────────────── */
  function LerenLibraryView({ t, navigate, chapters, libraryMode: libraryModeProp, hasFeature }) {
    const { useEffect } = React;
    const dark = t.mode === 'dark';
    const [mode, setMode] = useState(libraryModeProp || 'list');

    // Sync local state when parent prop changes (proto-header mode-switcher)
    useEffect(() => {
      if (libraryModeProp && libraryModeProp !== mode) {
        setMode(libraryModeProp);
      }
    }, [libraryModeProp]);
    const [tab, setTab] = useState('eigen');
    const [filters, setFilters] = useState({ vak: null, achterstand: false, recent: false });
    const [communitySort, setCommunitySort] = useState('top');
    const [shareModalItem, setShareModalItem] = useState(null);

    const canAICreate = hasFeature ? hasFeature('ai-create') : true;

    const subtitle = mode === 'upload'
      ? 'Eigen materiaal toevoegen aan je bibliotheek'
      : 'Eigen content · Community · Gecertificeerd';

    const aiContentBtn = (
      <button
        onClick={() => canAICreate ? navigate('ai-creator') : null}
        style={{
          display: 'inline-flex', alignItems: 'center', gap: 6,
          padding: '7px 14px', borderRadius: 8,
          background: canAICreate ? t.primary : t.cardSunken,
          border: canAICreate ? 'none' : `1px solid ${t.border}`,
          color: canAICreate ? (dark ? '#0A0F1E' : '#FFFFFF') : t.fgMute,
          fontSize: 12, fontWeight: 800, cursor: canAICreate ? 'pointer' : 'not-allowed',
          fontFamily: 'Nunito', whiteSpace: 'nowrap', opacity: canAICreate ? 1 : 0.7,
        }}
      >
        {!canAICreate && <PI name="lock" size={12} color={t.fgMute} strokeWidth={2.4} />}
        {canAICreate && <PI name="sparkles" size={12} color={dark ? '#0A0F1E' : '#FFFFFF'} strokeWidth={2.4} />}
        + AI Content
      </button>
    );

    return (
      <LerenPage
        t={t}
        title="Bibliotheek"
        subtitle={subtitle}
        snaps={1240}
        streak={12}
        level={7}
        url={mode === 'upload' ? 'snapsnel.nl/leren/bibliotheek/upload' : 'snapsnel.nl/leren/bibliotheek'}
        rightExtra={aiContentBtn}
      >
        {mode === 'list' && (
          <ModeList
            t={t}
            navigate={navigate}
            tab={tab}
            setTab={setTab}
            filters={filters}
            setFilters={setFilters}
            setMode={setMode}
            communitySort={communitySort}
            setCommunitySort={setCommunitySort}
            onShareClick={(item) => setShareModalItem(item)}
          />
        )}
        {mode === 'upload' && (
          <ModeUpload t={t} setMode={setMode} />
        )}
        {mode === 'empty' && (
          <ModeEmpty t={t} setMode={setMode} navigate={navigate} />
        )}

        {shareModalItem && (
          <ShareModal
            t={t}
            item={shareModalItem}
            onClose={() => setShareModalItem(null)}
            onConfirm={() => {
              // toggle shared (mock)
              shareModalItem.shared = shareModalItem.shared === 'public' ? 'private' : 'public';
              if (shareModalItem.shared === 'public' && !shareModalItem.rating) {
                shareModalItem.rating = { avg: 0, count: 0 };
                shareModalItem.useCount = 0;
                shareModalItem.author = 'sam_b'; // mock pseudoniem
              }
              setShareModalItem(null);
            }}
          />
        )}
      </LerenPage>
    );
  }

  /* ─── ShareModal ─────────────────────────────────────────────
     Confirmeren bij privé→publiek (of andersom).
     Disclaimer copyright + Snaps-incentive uitgelegd.
     ──────────────────────────────────────────────────────────── */
  function ShareModal({ t, item, onClose, onConfirm }) {
    const dark = t.mode === 'dark';
    const isMakingPublic = item.shared !== 'public';
    return (
      <div
        onClick={onClose}
        style={{
          position: 'fixed', inset: 0, zIndex: 9999,
          background: 'rgba(0,0,0,0.50)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          padding: 20,
        }}
      >
        <div
          onClick={(e) => e.stopPropagation()}
          style={{
            background: t.card, border: `1px solid ${t.border}`,
            borderRadius: 14, padding: '24px 26px',
            maxWidth: 460, width: '100%',
            display: 'flex', flexDirection: 'column', gap: 16,
            boxShadow: '0 24px 70px rgba(0,0,0,0.40)',
          }}
        >
          <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
            <PulseMascot size={48} mood={isMakingPublic ? 'encouraging' : 'thinking'} />
            <div style={{ flex: 1 }}>
              <div style={{ fontFamily: 'Fredoka One', fontSize: 20, color: t.fg, lineHeight: 1.2 }}>
                {isMakingPublic ? 'Deel met de community' : 'Maak weer privé'}
              </div>
              <div style={{ fontSize: 12, color: t.fgDim, fontWeight: 600, marginTop: 4 }}>
                {item.title}
              </div>
            </div>
            <button onClick={onClose} style={{
              width: 28, height: 28, borderRadius: 8, background: t.cardSunken,
              border: `1px solid ${t.border}`, color: t.fgMute, cursor: 'pointer',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>
              <PI name="x" size={13} strokeWidth={2.4} />
            </button>
          </div>

          {isMakingPublic && (
            <>
              <div style={{
                padding: '12px 14px', borderRadius: 10,
                background: dark ? 'rgba(251,191,36,0.10)' : 'rgba(180,83,9,0.06)',
                border: `1px solid ${dark ? 'rgba(251,191,36,0.28)' : 'rgba(180,83,9,0.22)'}`,
                fontSize: 12.5, color: t.fgDim, fontWeight: 600, lineHeight: 1.55,
                display: 'flex', alignItems: 'flex-start', gap: 10,
              }}>
                <PI name="alert-circle" size={14} color={dark ? '#FBBF24' : '#B45309'} strokeWidth={2.4} style={{ marginTop: 1, flexShrink: 0 }} />
                <span>
                  <b style={{ color: t.fg }}>Let op — geen copyright-beschermde content</b><br/>
                  Deel alleen je eigen samenvattingen, schema's of aantekeningen. Direct gekopieerde uitgevers-content (Malmberg, Noordhoff, etc.) mag niet publiek.
                </span>
              </div>

              <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                <div style={{ fontSize: 11, color: t.fgMute, fontWeight: 800, letterSpacing: 0.4, textTransform: 'uppercase' }}>
                  Wat krijg je terug?
                </div>
                {[
                  { icon: 'zap',         label: '+50 Snaps',  sub: 'voor je eerste publicatie' },
                  { icon: 'users',       label: '+10 Snaps',  sub: 'per nieuwe gebruiker die het oppakt' },
                  { icon: 'star',        label: '+100 Snaps', sub: 'als je gemiddelde rating ≥ 4 sterren is' },
                  { icon: 'trending-up', label: 'Top contributor-badge', sub: 'na een handvol top-rated stukken' },
                ].map((row, i) => (
                  <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                    <div style={{
                      width: 26, height: 26, borderRadius: 8, flexShrink: 0,
                      background: t.primaryDim, color: t.primary,
                      display: 'flex', alignItems: 'center', justifyContent: 'center',
                    }}>
                      <PI name={row.icon} size={12} color={t.primary} strokeWidth={2.4} />
                    </div>
                    <div>
                      <div style={{ fontSize: 12.5, color: t.fg, fontWeight: 800 }}>{row.label}</div>
                      <div style={{ fontSize: 11, color: t.fgMute, fontWeight: 600 }}>{row.sub}</div>
                    </div>
                  </div>
                ))}
              </div>

              <div style={{
                padding: '10px 12px', borderRadius: 8,
                background: t.cardSunken, border: `1px solid ${t.border}`,
                fontSize: 11.5, color: t.fgMute, fontWeight: 600, lineHeight: 1.5,
                display: 'flex', alignItems: 'flex-start', gap: 8,
              }}>
                <PI name="user" size={12} color={t.fgMute} strokeWidth={2.4} style={{ marginTop: 2, flexShrink: 0 }} />
                <span>Je verschijnt als <b style={{ color: t.fgDim }}>sam_b</b> — niet je echte naam. Pas je nickname aan in profiel.</span>
              </div>
            </>
          )}

          {!isMakingPublic && (
            <div style={{
              padding: '12px 14px', borderRadius: 10,
              background: t.cardSunken, border: `1px solid ${t.border}`,
              fontSize: 12.5, color: t.fgDim, fontWeight: 600, lineHeight: 1.55,
            }}>
              Andere studenten die dit hoofdstuk gebruiken houden hun voortgang. Hun ratings blijven zichtbaar — alleen jouw item verdwijnt uit Community.
            </div>
          )}

          <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end', marginTop: 4 }}>
            <button onClick={onClose} style={{
              padding: '9px 16px', borderRadius: 999,
              background: 'transparent', border: `1px solid ${t.border}`,
              color: t.fgDim, fontSize: 13, fontWeight: 800, cursor: 'pointer',
              fontFamily: 'Nunito',
            }}>Annuleren</button>
            <button onClick={onConfirm} style={{
              padding: '9px 18px', borderRadius: 999,
              background: t.primary, border: 'none',
              color: dark ? '#0A0F1E' : '#FFFFFF',
              fontSize: 13, fontWeight: 800, cursor: 'pointer',
              fontFamily: 'Nunito',
              display: 'inline-flex', alignItems: 'center', gap: 6,
            }}>
              <PI name={isMakingPublic ? 'globe' : 'lock'} size={13}
                color={dark ? '#0A0F1E' : '#FFFFFF'} strokeWidth={2.4} />
              {isMakingPublic ? 'Ja, deel publiek' : 'Ja, maak privé'}
            </button>
          </div>
        </div>
      </div>
    );
  }

  window.LerenLibraryView = LerenLibraryView;
})();
