// tgp-personal.jsx v3 — Personal Plan redesign
// Keeps only the header shell (Personal Plan / subtitle / tabs); rebuilds tab content
// using folder-tab task cards (Ongoing/Future/Done), editorial media feed, and clean event rail.

// ─── Shared: status-tab folder card (inspired by Ongoing/Future screenshots) ──
const StatusFolderCard = ({ status, statusIcon, creator, creatorImg, thumb, title, progress, dark, onMenu }) => {
  const DARK = dark;
  const surface = DARK ? '#020100' : '#FFFFFF';
  const textCol = DARK ? '#FFFFFF' : '#020100';
  const muted   = DARK ? 'rgba(255,255,255,0.5)' : '#8E8E93';
  const barBg   = DARK ? 'rgba(255,255,255,0.15)' : 'rgba(116,116,128,0.18)';
  const barFg   = DARK ? '#FFFFFF' : '#020100';

  return (
    <div style={{ position:'relative', paddingTop:30, marginTop:2 }}>
      {/* Left tab: status */}
      <div style={{
        position:'absolute', top:0, left:10, zIndex:3,
        background:surface, borderRadius:'14px 14px 0 0',
        padding:'6px 12px 14px 10px',
        display:'flex', alignItems:'center', gap:7,
      }}>
        <span style={{
          width:22, height:22, borderRadius:7,
          background: DARK ? 'rgba(255,255,255,0.08)' : 'rgba(116,116,128,0.14)',
          display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0,
        }}>{statusIcon}</span>
        <span style={{
          fontSize:12, fontWeight:600, color:textCol,
          fontFamily:'Inter,system-ui,sans-serif', letterSpacing:'-0.1px',
        }}>{status}</span>
      </div>

      {/* Right tab: creator */}
      <div style={{
        position:'absolute', top:0, right:10, zIndex:3,
        background:surface, borderRadius:'14px 14px 0 0',
        padding:'6px 10px 14px 12px',
        display:'flex', alignItems:'center', gap:7,
      }}>
        <span style={{ fontSize:11, color:muted, fontFamily:'Inter,system-ui,sans-serif' }}>Toegewezen</span>
        <span style={{ fontSize:11, fontWeight:700, color:textCol, fontFamily:'Inter,system-ui,sans-serif' }}>{creator}</span>
        <img src={creatorImg} alt="" style={{ width:20, height:20, borderRadius:'50%', objectFit:'cover' }} />
      </div>

      {/* Body */}
      <div style={{
        position:'relative', background:surface, borderRadius:18, zIndex:2,
        padding:'14px 16px 14px 14px',
        boxShadow: DARK ? '0 4px 18px rgba(0,0,0,0.25)' : '0 2px 10px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.04)',
      }}>
        <button onClick={onMenu} style={{
          position:'absolute', top:14, right:14, border:'none', background:'transparent',
          cursor:'pointer', padding:4, display:'flex', gap:3,
        }}>
          {[0,1,2].map(i=><span key={i} style={{ width:3, height:3, borderRadius:'50%', background: DARK?'rgba(255,255,255,0.4)':'rgba(0,0,0,0.35)' }} />)}
        </button>

        <div style={{ display:'flex', alignItems:'center', gap:13 }}>
          <div style={{
            width:52, height:52, borderRadius:'50%', overflow:'hidden', flexShrink:0,
            background:'rgba(116,116,128,0.12)',
          }}>
            <img src={thumb} alt="" style={{ width:'100%', height:'100%', objectFit:'cover' }} />
          </div>
          <div style={{ flex:1, minWidth:0, paddingRight:22 }}>
            <div style={{
              fontSize:15, fontWeight:700, color:textCol,
              fontFamily:'Inter,system-ui,sans-serif', letterSpacing:'-0.2px',
              lineHeight:1.3, marginBottom:8,
              overflow:'hidden', textOverflow:'ellipsis',
              display:'-webkit-box', WebkitLineClamp:2, WebkitBoxOrient:'vertical',
            }}>{title}</div>
            <div style={{ background:barBg, borderRadius:9, height:4, overflow:'hidden' }}>
              <div style={{ width:`${progress}%`, height:'100%', background:barFg, borderRadius:9, transition:'width 0.4s' }} />
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

// ─── Personal events — shared between Taken (summary) and Events tab ─────
const PERSONAL_EVENTS = [
  {
    month:'Mrt', date:'20', day:'Do', title:'Bosgym Bouwdag',
    time:'09:00–14:00', timeShort:'Do · 09:00', loc:'Leusderhei', type:'Fysiek', typeColor:'#020100',
    img:'#cGym', attendingKeys:['lisa','mark','sara','tom'], count:12,
    cost:'Gratis',
    description:'We bouwen samen de basis van de bosgym in Leusderhei — pull-up bar, parallel bars en klimtouw. Iedereen kan meedoen, ervaring niet nodig.',
    takeaways:[
      'Eerste ervaring met outdoor bouwen met alleen natuurlijke materialen.',
      'Toegang tot de gym voor de hele zomer — kom trainen wanneer je wil.',
      'Verbinding met 10+ mensen uit het Eigen Gym Bouwen-collectief.',
    ],
    host:{ name:'Kees Jan', role:'Oprichter Eigen Gym Bouwen', srcKey:'lisa' },
    address:'Leusderhei parkeerplaats P2 (naast informatiebord)',
    transport:'Per auto via A28 afrit 10; per fiets 40 min vanuit Amersfoort.',
    bring:['Werkhandschoenen','Stevige schoenen','1.5 L water','Lunchpakket'],
    agenda:[
      { time:'09:00', item:'Koffie & kennismaking bij parkeerplaats' },
      { time:'09:30', item:'Plek scouten en markeren' },
      { time:'10:00', item:'Materialen naar locatie dragen' },
      { time:'10:30', item:'Pull-up bar installeren' },
      { time:'12:00', item:'Gezamenlijke lunch' },
      { time:'12:30', item:'Parallel bars opzetten' },
      { time:'13:30', item:'Klimtouw ophangen' },
      { time:'14:00', item:'Test-sessie + afsluiting' },
    ],
    prepare:['Laad route in je telefoon','Check weerbericht vooraf','Eet stevig ontbijt voor vertrek'],
    questions:[
      { text:'Gaat het ook door bij regen?',              by:'Joep' },
      { text:'Mag ik mijn dochter (12) meenemen?',        by:'Eva'  },
    ],
  },
  {
    month:'Mrt', date:'22', day:'Za', title:'Begeleide OBE-sessie',
    time:'20:00–21:30', timeShort:'Za · 20:00', loc:'Online — Google Meet', type:'Digitaal', typeColor:'#007AFF',
    img:'#cOBE', attendingKeys:['nina','joep','eva'], count:6,
    cost:'Gratis',
    description:'Online begeleide sessie waarin we samen een body scan doen en een eerste exit-techniek proberen. Beginners zijn meer dan welkom — we nemen het rustig.',
    takeaways:[
      'Eerste gestructureerde oefening met de rope-techniek van Monroe.',
      'Audio-opname van de sessie achteraf om zelf te herhalen.',
      'Journal-template die we samen doornemen.',
      'Onderdeel worden van een maandelijkse OBE-cirkel.',
    ],
    host:{ name:'Melissa', role:'Facilitator OBE Nederland', srcKey:'nina' },
    meetLink:'https://meet.google.com/obx-ned-zat',
    meetPlatform:'Google Meet',
    techCheck:['Koptelefoon (belangrijk voor diepgang)','Rustige kamer zonder onderbrekingen','Camera mag uit, mic aan bij check-in','Stabiele internetverbinding'],
    agenda:[
      { time:'20:00', item:'Check-in & intentie zetten' },
      { time:'20:15', item:'Body scan — begeleid, 25 min' },
      { time:'20:40', item:'Exit-techniek proberen' },
      { time:'20:55', item:'Ervaringen delen (optioneel)' },
      { time:'21:30', item:'Sluiting' },
    ],
    prepare:['Eet lichte maaltijd 2 uur vooraf','Zorg dat je niet gestoord wordt','Leg pen en papier naast je voor journal'],
    questions:[
      { text:'Wat als ik in slaap val tijdens de body scan?', by:'Kevin' },
      { text:'Kan ik achteraf 1-op-1 vragen stellen?',        by:'Joep'  },
    ],
  },
  {
    month:'Mrt', date:'24', day:'Ma', title:'Workshop: Holacracy 101',
    time:'18:00–20:00', timeShort:'Ma · 18:00', loc:'Impact Hub, Utrecht', type:'Fysiek', typeColor:'#020100',
    img:'#cHolacracy', attendingKeys:['anna','lisa'], count:18,
    cost:'€25 incl. soep',
    description:'Hands-on introductie in Holacracy voor ondernemers. We draaien een échte tactical meeting zodat je voelt hoe het werkt — niet alleen theorie.',
    takeaways:[
      'Het verschil tussen rollen en functies — concreet snappen.',
      'Eén rol voor jouw eigen werk volledig uitgeschreven.',
      'Kennen hoe een tactical meeting verloopt.',
      'Werkboek + voorbeelden om thuis direct mee te kunnen.',
    ],
    host:{ name:'Joep', role:'Facilitator Holacracy Ondernemen', srcKey:'tom' },
    address:'Impact Hub Utrecht — Neude 5, 3512 AD Utrecht',
    transport:'Station Utrecht CS — 5 min lopen. Fietsparkeer in Catharijnesingel.',
    bring:['Laptop of notitieboek','Voorbeeld van je eigen werk'],
    agenda:[
      { time:'18:00', item:'Inloop + soep' },
      { time:'18:30', item:'Introductie en principes' },
      { time:'19:00', item:'Rollen uitschrijven — eigen oefening' },
      { time:'19:30', item:'Tactical meeting demonstratie' },
      { time:'19:45', item:'Zelf draaien in 3-tallen' },
      { time:'20:00', item:'Reflectie en afsluiting' },
    ],
    prepare:['Schrijf kort op wat je deze maand doet','Lees intro-hoofdstuk van Robertson (optioneel)'],
    questions:[
      { text:'Werkt het ook bij 2 oprichters zonder team?', by:'Sara' },
      { text:'Hoe zwaar is de leercurve voor nieuwe teams?', by:'Anna' },
    ],
  },
  {
    month:'Apr', date:'01', day:'Di', title:'Homeschool Meet-up Q2',
    time:'10:00–12:00', timeShort:'Di · 10:00', loc:'De Wilde Tuin, Utrecht', type:'Fysiek', typeColor:'#020100',
    img:'#cHomeschool', attendingKeys:['tom','mark','sara','joep','eva'], count:34,
    cost:'€5 p.p. (voor locatie)',
    description:'Kwartaalontmoeting voor homeschool-gezinnen. Kinderen spelen in de tuin, ouders wisselen ervaringen uit rond het thema "dagritme".',
    takeaways:[
      'Concrete tips uit andere homeschool-gezinnen.',
      'Je kind maakt 2–3 nieuwe vriendjes.',
      'Ruil-moment voor werkboeken en lesmateriaal.',
      'Volgende meet-up: optie om zelf te hosten.',
    ],
    host:{ name:'Jelle', role:'Oprichter Homeschooling NL', srcKey:'mark' },
    address:'De Wilde Tuin — Lageweide 10, Utrecht',
    transport:'Bus 29 vanaf Utrecht CS; fiets via Amsterdam-Rijnkanaal.',
    bring:['Iets voor gezamenlijke lunch (vegetarisch)','Lesmateriaal dat je wilt ruilen','Zonnebrand','Picknickkleed'],
    agenda:[
      { time:'10:00', item:'Welkom + koffie' },
      { time:'10:20', item:'Kinderen vrij spel in de tuin' },
      { time:'10:30', item:'Ouder-rondetafel: dagritme' },
      { time:'11:30', item:'Gezamenlijke lunch' },
      { time:'12:00', item:'Open uitwisseling + afsluiting' },
    ],
    prepare:['Denk na over wat voor jou werkt in dagritme','Leg eventueel materiaal apart om te ruilen'],
    questions:[
      { text:'Hoe oud zijn de kinderen die er komen?',     by:'Melissa' },
      { text:'Is de locatie toegankelijk met rolstoel?',   by:'Anna'    },
    ],
  },
];

// Resolve IMG keys (since PERSONAL_EVENTS is declared at module load,
// but IMG lookups need to resolve once IMG is available — which it is
// because tgp-shared.jsx loads first).
const resolvePersonalEvent = (e) => ({
  ...e,
  img: IMG[e.img?.replace('#','') || ''] || e.img,
  attending: (e.attendingKeys || []).map(k => IMG[k]).filter(Boolean),
  host: e.host ? { ...e.host, src: IMG[e.host.srcKey] || e.host.src } : undefined,
});

// ─── Taken — persoonlijke to-do's per dagdeel ─────────────────────────────
const TakenTab = () => {
  const [filter, setFilter] = React.useState('Alle taken');
  const [activeEvent, setActiveEvent] = React.useState(null);
  const [tasks, setTasks] = React.useState([
    { id:1, project:'bosgym',       task:'plek-inspectie in bos — schaduw en bodem checken', min:50, done:false },
    { id:2, project:'obe',          task:'journal-template uitwerken voor sessie-groep',     min:45, done:false },
    { id:3, project:'holacracy',    task:'intro-deck reviewen voor workshop',          min:30, done:true  },
    { id:4, project:'bosgym',       task:'materialenlijst afmaken (hout, touw, bout)', min:25, done:false },
    { id:5, project:'tinyhouse',    task:'plattegrond v2 — keuken herindelen',         min:60, done:false },
    { id:6, project:'holacracy',    task:'twee voorbeeld-rollen uitwerken',            min:45, done:false },
    { id:7, project:'lesmodule1',   task:'werkboek hoofdstuk 2 reviewen',              min:45, done:false },
    { id:8, project:'obe',          task:'audio-cue opnemen voor body scan',           min:30, done:true  },
  ]);
  const toggle = (id)=>setTasks(ts=>ts.map(t=>t.id===id?{...t,done:!t.done}:t));

  // Opkomende events samenvatting — gekoppeld aan volledige event-data
  const upcoming = PERSONAL_EVENTS.slice(0, 3).map(resolvePersonalEvent);

  const filters = ['Alle taken','Op project','Completed'];
  let visible = tasks;
  if (filter==='Completed') visible = tasks.filter(t=>t.done);
  // For 'Op project' we group below; other filters render flat.
  const grouped = {};
  visible.forEach(t=>{ (grouped[t.project] = grouped[t.project] || []).push(t); });

  const TaskRow = (t) => (
    <div key={t.id} onClick={()=>toggle(t.id)} style={{
      display:'flex', alignItems:'center', gap:12, padding:'12px 14px',
      background:'rgba(116,116,128,0.08)', borderRadius:14, cursor:'pointer',
      opacity: t.done ? 0.5 : 1, transition:'opacity 0.2s',
    }}>
      <div style={{
        width:20, height:20, borderRadius:'50%', flexShrink:0,
        border: t.done ? 'none' : '1.5px solid rgba(2,1,0,0.25)',
        background: t.done ? '#020100' : 'transparent',
        display:'flex', alignItems:'center', justifyContent:'center',
      }}>
        {t.done && <Ico.Check size={11} color="#fff" />}
      </div>
      <div style={{
        flex:1, minWidth:0, fontSize:13.5, lineHeight:1.4,
        color:'#020100', fontFamily:'Inter,system-ui,sans-serif',
        textDecoration: t.done ? 'line-through' : 'none',
      }}>
        <b style={{ fontWeight:700 }}>@{t.project}:</b> <span style={{ color:'rgba(2,1,0,0.75)' }}>{t.task}</span>
      </div>
      <span style={{
        fontSize:11, padding:'3px 9px', borderRadius:999, flexShrink:0,
        background:'rgba(255,255,255,0.85)', color:'#8E8E93',
        fontFamily:'Inter,system-ui,sans-serif', fontWeight:500,
      }}>{t.min} min</span>
    </div>
  );

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:18 }}>

      {/* Opkomende events — compacte rail bovenaan */}
      <div>
        <div style={{
          display:'flex', alignItems:'baseline', justifyContent:'space-between',
          marginBottom:8, paddingLeft:2,
        }}>
          <span style={{ fontFamily:'"Instrument Serif",Georgia,serif', fontWeight:400, fontSize:22, color:'#020100', letterSpacing:'-0.4px', lineHeight:1 }}>
            Events
          </span>
          <span style={{ fontSize:12, color:'#007AFF', fontFamily:'Inter,system-ui,sans-serif', fontWeight:500, cursor:'pointer' }}>Alle</span>
        </div>
        <div style={{ display:'flex', gap:10, overflowX:'auto', scrollbarWidth:'none', margin:'0 -16px', padding:'4px 16px 10px' }}>
          {upcoming.map(ev => {
            const mTearX = 58;
            const mNotchR = 9;
            const mMaskImages = [
              `radial-gradient(circle ${mNotchR}px at ${mTearX}px 0, transparent ${mNotchR - 0.5}px, #000 ${mNotchR + 0.5}px)`,
              `radial-gradient(circle ${mNotchR}px at ${mTearX}px 100%, transparent ${mNotchR - 0.5}px, #000 ${mNotchR + 0.5}px)`,
            ].join(', ');
            const mMaskProps = {
              WebkitMaskImage: mMaskImages,
              maskImage: mMaskImages,
              WebkitMaskSize: '100% 50%, 100% 50%',
              maskSize: '100% 50%, 100% 50%',
              WebkitMaskPosition: 'top, bottom',
              maskPosition: 'top, bottom',
              WebkitMaskRepeat: 'no-repeat, no-repeat',
              maskRepeat: 'no-repeat, no-repeat',
            };
            return (
            <div key={ev.title} onClick={()=>setActiveEvent(ev)} style={{
              flexShrink:0, cursor:'pointer',
              filter:'drop-shadow(0 1px 2px rgba(0,0,0,0.05)) drop-shadow(0 6px 12px rgba(0,0,0,0.07))',
            }}>
              <div style={{
                display:'flex', alignItems:'stretch',
                width:200, minHeight:74,
                background:'linear-gradient(145deg, #FEFEFB 0%, #F8F7F1 100%)',
                borderRadius:12,
                position:'relative',
                ...mMaskProps,
              }}>
                {/* Dashed inner frame */}
                <div aria-hidden="true" style={{
                  position:'absolute', top:6, bottom:6, left:6, right:6,
                  border:'1px dashed rgba(0,0,0,0.18)', borderRadius:7,
                  pointerEvents:'none',
                }} />
                {/* Perforated tear line */}
                <div aria-hidden="true" style={{
                  position:'absolute', left:mTearX - 1,
                  top:mNotchR + 6, bottom:mNotchR + 6, width:2,
                  backgroundImage:'radial-gradient(circle, rgba(0,0,0,0.42) 0.9px, transparent 1.2px)',
                  backgroundSize:'2px 5px', backgroundRepeat:'repeat-y',
                  pointerEvents:'none',
                }} />
                {/* Left stub — date */}
                <div style={{
                  width:mTearX, flexShrink:0, display:'flex', flexDirection:'column',
                  alignItems:'center', justifyContent:'center', padding:'10px 6px',
                }}>
                  <div style={{ fontSize:9, color:'#8E8E93', fontFamily:'Inter,system-ui,sans-serif', textTransform:'uppercase', fontWeight:700, letterSpacing:'0.08em' }}>{ev.month}</div>
                  <div style={{ fontFamily:'"Instrument Serif",Georgia,serif', fontWeight:400, fontSize:22, color:'#020100', lineHeight:1, letterSpacing:'-0.6px', textShadow:'0 1px 0 rgba(255,255,255,0.9)' }}>{ev.date}</div>
                </div>
                {/* Body */}
                <div style={{
                  flex:1, minWidth:0, display:'flex', flexDirection:'column', justifyContent:'center', gap:3,
                  padding:'10px 12px 10px 16px',
                }}>
                  <div style={{
                    fontFamily:'"Instrument Serif",Georgia,serif', fontWeight:400,
                    fontSize:14, color:'#020100', letterSpacing:'-0.2px', lineHeight:1.1,
                    overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap',
                  }}>{ev.title}</div>
                  <div style={{ fontSize:10, color:'#6B6B70', fontFamily:'Inter,system-ui,sans-serif' }}>{ev.timeShort || ev.time}</div>
                  <span style={{
                    alignSelf:'flex-start', marginTop:1, fontSize:8, padding:'2px 7px', borderRadius:999,
                    background:`linear-gradient(145deg, ${ev.typeColor}1f, ${ev.typeColor}10)`,
                    color:ev.typeColor, fontFamily:'Inter,system-ui,sans-serif', fontWeight:700,
                    border:`1px solid ${ev.typeColor}28`, letterSpacing:'0.06em', textTransform:'uppercase',
                  }}>{ev.type}</span>
                </div>
              </div>
            </div>
            );
          })}
        </div>
      </div>

      {/* Taken sectie titel */}
      <div style={{ marginTop:4, marginBottom:-8 }}>
        <span style={{ fontFamily:'"Instrument Serif",Georgia,serif', fontWeight:400, fontSize:22, color:'#020100', letterSpacing:'-0.4px', lineHeight:1 }}>
          Taken
        </span>
      </div>

      {/* Filter pills */}
      <div style={{ display:'flex', gap:8, overflowX:'auto', scrollbarWidth:'none' }}>
        {filters.map(f => (
          <Pill key={f} active={filter===f} onClick={()=>setFilter(f)}>{f}</Pill>
        ))}
      </div>

      {filter==='Op project' ? (
        Object.keys(grouped).map(proj => (
          <section key={proj}>
            <div style={{
              fontSize:11, fontWeight:700, color:'#8E8E93',
              textTransform:'uppercase', letterSpacing:'0.08em',
              fontFamily:'Inter,system-ui,sans-serif', marginBottom:9, paddingLeft:2,
            }}>@{proj}</div>
            <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
              {grouped[proj].map(TaskRow)}
            </div>
          </section>
        ))
      ) : (
        <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
          {visible.map(TaskRow)}
        </div>
      )}

      <button style={{
        width:'100%', padding:'14px 0', borderRadius:16,
        border:'1.5px dashed rgba(116,116,128,0.3)', background:'transparent',
        color:'#8E8E93', fontSize:14, fontWeight:500, cursor:'pointer',
        fontFamily:'Inter,system-ui,sans-serif',
        display:'flex', alignItems:'center', justifyContent:'center', gap:6,
      }}>
        <Ico.Plus size={16} /> Nieuwe persoonlijke taak
      </button>

      <EventDetail event={activeEvent} isOpen={!!activeEvent} onClose={()=>setActiveEvent(null)} />
    </div>
  );
};

// ─── Practicals — Real folder-shape grid (inspired by folder/invoice app) ──

// Book-inspired shape (Knowledge): rounded cover, visible spine on left, stacked page edges on right/bottom
const BookShape = ({ stroke='rgba(0,0,0,0.08)' }) => (
  <svg viewBox="0 0 200 170" preserveAspectRatio="none" style={{ position:'absolute', inset:0, width:'100%', height:'100%' }}>
    <defs>
      <linearGradient id="bookCover" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0%" stopColor="#FAF8F4" />
        <stop offset="100%" stopColor="#E8E5DE" />
      </linearGradient>
      <linearGradient id="bookSpine" x1="0" y1="0" x2="1" y2="0">
        <stop offset="0%" stopColor="#CFC9BC" />
        <stop offset="100%" stopColor="#E8E5DE" />
      </linearGradient>
    </defs>
    {/* stacked page edges on the right (just inside the cover edge) */}
    <rect x="188" y="30" width="6" height="130" fill="#F2EFE8" stroke={stroke} strokeWidth="0.5" />
    <line x1="190" y1="34" x2="190" y2="156" stroke="rgba(0,0,0,0.06)" strokeWidth="1" />
    <line x1="192" y1="34" x2="192" y2="156" stroke="rgba(0,0,0,0.04)" strokeWidth="1" />
    {/* stacked page edges along the bottom */}
    <rect x="18" y="158" width="170" height="5" fill="#F2EFE8" stroke={stroke} strokeWidth="0.5" />
    <line x1="22" y1="160" x2="184" y2="160" stroke="rgba(0,0,0,0.05)" strokeWidth="1" />
    {/* cover body (no tab — book has no folder tab) */}
    <path d="M 8 28 Q 8 18 18 18 L 188 18 Q 194 18 194 28 L 194 156 Q 194 162 188 162 L 18 162 Q 8 162 8 156 Z" fill="url(#bookCover)" stroke={stroke} strokeWidth="1" />
    {/* spine on left */}
    <path d="M 8 28 Q 8 18 18 18 L 26 18 L 26 162 L 18 162 Q 8 162 8 156 Z" fill="url(#bookSpine)" stroke={stroke} strokeWidth="0.5" />
    {/* spine raised bands */}
    <line x1="10" y1="48" x2="26" y2="48" stroke="rgba(0,0,0,0.09)" strokeWidth="1" />
    <line x1="10" y1="132" x2="26" y2="132" stroke="rgba(0,0,0,0.09)" strokeWidth="1" />
  </svg>
);

// Toolbox-inspired shape (Building): folder body with a handle on top and two latches on the front
const ToolboxShape = ({ stroke='rgba(0,0,0,0.08)' }) => (
  <svg viewBox="0 0 200 170" preserveAspectRatio="none" style={{ position:'absolute', inset:0, width:'100%', height:'100%' }}>
    <defs>
      <linearGradient id="toolboxBody" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0%" stopColor="#FAF8F4" />
        <stop offset="100%" stopColor="#E8E5DE" />
      </linearGradient>
      <linearGradient id="toolboxHandle" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0%" stopColor="#C7C0B1" />
        <stop offset="100%" stopColor="#9E978A" />
      </linearGradient>
    </defs>
    {/* Handle — rounded arch centered on top */}
    <path d="M 78 10 Q 78 2 86 2 L 114 2 Q 122 2 122 10 L 122 22 L 116 22 L 116 12 Q 116 8 112 8 L 88 8 Q 84 8 84 12 L 84 22 L 78 22 Z"
          fill="url(#toolboxHandle)" stroke={stroke} strokeWidth="1" />
    {/* Body */}
    <path d="M 6 28 Q 6 20 14 20 L 186 20 Q 194 20 194 28 L 194 156 Q 194 164 186 164 L 14 164 Q 6 164 6 156 Z"
          fill="url(#toolboxBody)" stroke={stroke} strokeWidth="1" />
    {/* Lid seam across the body */}
    <line x1="6" y1="54" x2="194" y2="54" stroke="rgba(0,0,0,0.09)" strokeWidth="1" />
    {/* Two latches on the seam */}
    <rect x="38" y="48" width="16" height="12" rx="2" fill="#CFC9BC" stroke={stroke} strokeWidth="1" />
    <circle cx="46" cy="54" r="1.2" fill="rgba(0,0,0,0.35)" />
    <rect x="146" y="48" width="16" height="12" rx="2" fill="#CFC9BC" stroke={stroke} strokeWidth="1" />
    <circle cx="154" cy="54" r="1.2" fill="rgba(0,0,0,0.35)" />
    {/* Bottom metal foot band */}
    <line x1="6" y1="154" x2="194" y2="154" stroke="rgba(0,0,0,0.07)" strokeWidth="1" />
  </svg>
);

// Small image-frame icon used on media papers
const ImgIcon = ({ size=8, color='rgba(0,0,0,0.45)' }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink:0 }}>
    <rect x="3" y="3" width="18" height="18" rx="2"/>
    <circle cx="8.5" cy="8.5" r="1.5"/>
    <polyline points="21 15 16 10 5 21"/>
  </svg>
);

// A single paper sticking out the top — either a to-do list OR a list of media references
const FolderPaper = ({ left, top, rotate, kind = 'todos', todos, media, badge }) => (
  <div style={{
    position:'absolute', left, top, width:'46%', height:'42%',
    transform:`rotate(${rotate}deg)`, transformOrigin:'bottom center',
    background:'#FFFFFF', borderRadius:'10px 10px 6px 6px',
    boxShadow:'0 1px 3px rgba(0,0,0,0.08), 0 0 0 1px rgba(0,0,0,0.03)',
    padding:'7px 8px 6px', zIndex:1,
    display:'flex', flexDirection:'column', gap:3,
    overflow:'hidden',
  }}>
    {badge && (
      <div style={{ position:'absolute', top:5, right:5 }}>{badge}</div>
    )}
    {kind === 'todos' && todos && todos.map((t, i) => (
      <div key={i} style={{
        display:'flex', alignItems:'center', gap:4,
        fontSize:8, lineHeight:1.2,
        fontFamily:'Inter,system-ui,sans-serif', fontWeight:500,
        color: t.done ? 'rgba(0,0,0,0.28)' : 'rgba(0,0,0,0.55)',
      }}>
        <span style={{
          width:7, height:7, borderRadius:2, flexShrink:0,
          border: t.done ? '1px solid rgba(0,0,0,0.25)' : '1px solid rgba(0,0,0,0.35)',
          background: t.done ? 'rgba(0,0,0,0.25)' : 'transparent',
          display:'flex', alignItems:'center', justifyContent:'center',
        }}>
          {t.done && <svg width="5" height="5" viewBox="0 0 5 5"><path d="M0.8 2.6 L2 3.7 L4.3 1.1" stroke="#fff" strokeWidth="1" strokeLinecap="round" strokeLinejoin="round" fill="none"/></svg>}
        </span>
        <span style={{
          textDecoration: t.done ? 'line-through' : 'none',
          overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap', minWidth:0,
        }}>{t.text}</span>
      </div>
    ))}
    {kind === 'media' && media && media.map((m, i) => (
      <div key={i} style={{
        display:'flex', alignItems:'center', gap:4,
        fontSize:8, lineHeight:1.2,
        fontFamily:'Inter,system-ui,sans-serif', fontWeight:500,
        color:'rgba(0,0,0,0.55)',
      }}>
        <ImgIcon size={8} />
        <span style={{ overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap', minWidth:0 }}>{m}</span>
      </div>
    ))}
  </div>
);

// ─── Practical detail overlay (click on folder) ───────────────────────────
const PD_SERIF = { fontFamily:'"Instrument Serif",Georgia,serif', fontWeight:400, letterSpacing:'-0.4px' };
const PD_SANS  = { fontFamily:'Inter,system-ui,sans-serif' };

const PDSectionTitle = ({ children }) => (
  <h3 style={{ ...PD_SERIF, fontSize:22, color:'#020100', margin:'0 0 10px', lineHeight:1.1 }}>{children}</h3>
);

const PracticalDetail = ({ practical, isOpen, onClose }) => {
  const p = practical || {};
  const achieve    = p.achieve   || [];
  const budget     = p.budget    || { amount:'Variabel', note:'afhankelijk van aanpak' };
  const people     = p.people    || { count:'1+',        note:'flexibel' };
  const steps      = p.steps     || (p.papers?.[0]?.todos || []).map(t => ({ title:t.text, desc:'' }));
  const video      = p.video;
  const challenges = p.challenges || [];
  const typeCol    = p.type==='Knowledge' ? '#007AFF' : '#FF4D1A';

  const stop = (e) => e.stopPropagation();
  return (
    <>
      <div onClick={(e)=>{ e.stopPropagation(); onClose(e); }} style={{
        position:'absolute', inset:0, zIndex:350,
        background:'rgba(20,18,16,0.55)',
        backdropFilter:'blur(4px)', WebkitBackdropFilter:'blur(4px)',
        opacity: isOpen?1:0, pointerEvents: isOpen?'auto':'none',
        transition:'opacity 0.25s',
      }} />
      <div onClick={stop} style={{
        position:'absolute', top:28, left:12, right:12, bottom:28,
        background:'#fff', borderRadius:26, zIndex:360, overflow:'hidden',
        transform: isOpen ? 'translateY(0) scale(1)' : 'translateY(20px) scale(0.96)',
        opacity: isOpen?1:0, pointerEvents: isOpen?'auto':'none',
        transition:'all 0.32s cubic-bezier(0.2,0.9,0.25,1)',
        boxShadow:'0 24px 60px rgba(0,0,0,0.28), 0 0 0 1px rgba(0,0,0,0.04)',
      }}>
        <button onClick={(e)=>{ e.stopPropagation(); onClose(e); }} style={{
          position:'absolute', top:14, right:14, zIndex:10,
          width:32, height:32, borderRadius:'50%',
          background:'rgba(116,116,128,0.15)', border:'none',
          display:'flex', alignItems:'center', justifyContent:'center', cursor:'pointer',
        }}>
          <Ico.X size={14} />
        </button>

        <div style={{ height:'100%', overflowY:'auto', scrollbarWidth:'none', WebkitOverflowScrolling:'touch' }}>
          {/* Hero */}
          <div style={{ padding:'26px 22px 18px' }}>
            {p.type && (
              <span style={{
                ...PD_SANS, fontSize:10, fontWeight:700, color:typeCol,
                padding:'3px 10px', borderRadius:999,
                background:`${typeCol}18`,
                textTransform:'uppercase', letterSpacing:'0.08em',
                display:'inline-block', marginBottom:10,
              }}>{p.type}</span>
            )}
            <h1 style={{ ...PD_SERIF, fontSize:32, color:'#020100', margin:'0 0 10px', lineHeight:1.05 }}>{p.title}</h1>
            {p.manifest && (
              <p style={{ ...PD_SERIF, fontStyle:'italic', fontSize:17, color:'rgba(2,1,0,0.65)', lineHeight:1.4, margin:'0 0 14px' }}>"{p.manifest}"</p>
            )}
            {p.creator && p.creatorImg && (
              <div style={{ display:'flex', alignItems:'center', gap:8 }}>
                <img src={p.creatorImg} alt="" style={{ width:28, height:28, borderRadius:'50%', objectFit:'cover' }} />
                <span style={{ ...PD_SANS, fontSize:12.5, color:'rgba(2,1,0,0.55)' }}>door <b style={{ color:'#020100', fontWeight:600 }}>{p.creator}</b></span>
              </div>
            )}
          </div>

          <div style={{ padding:'0 18px 36px', display:'flex', flexDirection:'column', gap:14 }}>
            {/* Wat je kan behalen */}
            {achieve.length > 0 && (
              <div style={{ background:'rgba(116,116,128,0.08)', borderRadius:18, padding:16 }}>
                <PDSectionTitle>Wat je ermee kan behalen</PDSectionTitle>
                <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
                  {achieve.map((a,i)=>(
                    <div key={i} style={{ display:'flex', gap:10, alignItems:'flex-start' }}>
                      <span style={{
                        width:20, height:20, flexShrink:0, marginTop:1,
                        borderRadius:'50%', background:'rgba(52,199,89,0.15)',
                        display:'flex', alignItems:'center', justifyContent:'center',
                      }}>
                        <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="#34C759" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
                      </span>
                      <span style={{ ...PD_SANS, fontSize:13.5, color:'rgba(2,1,0,0.8)', lineHeight:1.45, flex:1 }}>{a}</span>
                    </div>
                  ))}
                </div>
              </div>
            )}

            {/* Benodigdheden */}
            <div style={{ background:'rgba(116,116,128,0.08)', borderRadius:18, padding:16 }}>
              <PDSectionTitle>Benodigdheden</PDSectionTitle>
              <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:8 }}>
                <div style={{ background:'#fff', borderRadius:13, padding:'13px 14px' }}>
                  <div style={{ display:'flex', alignItems:'center', gap:6, marginBottom:5 }}>
                    <span style={{ fontSize:15 }}>💰</span>
                    <span style={{ ...PD_SANS, fontSize:10, fontWeight:700, color:'rgba(2,1,0,0.45)', textTransform:'uppercase', letterSpacing:'0.08em' }}>Budget</span>
                  </div>
                  <div style={{ ...PD_SERIF, fontSize:22, color:'#020100', lineHeight:1, marginBottom:3 }}>{budget.amount}</div>
                  <div style={{ ...PD_SANS, fontSize:11, color:'rgba(2,1,0,0.55)', lineHeight:1.35 }}>{budget.note}</div>
                </div>
                <div style={{ background:'#fff', borderRadius:13, padding:'13px 14px' }}>
                  <div style={{ display:'flex', alignItems:'center', gap:6, marginBottom:5 }}>
                    <span style={{ fontSize:15 }}>👥</span>
                    <span style={{ ...PD_SANS, fontSize:10, fontWeight:700, color:'rgba(2,1,0,0.45)', textTransform:'uppercase', letterSpacing:'0.08em' }}>Mensen</span>
                  </div>
                  <div style={{ ...PD_SERIF, fontSize:22, color:'#020100', lineHeight:1, marginBottom:3 }}>{people.count}</div>
                  <div style={{ ...PD_SANS, fontSize:11, color:'rgba(2,1,0,0.55)', lineHeight:1.35 }}>{people.note}</div>
                </div>
              </div>
            </div>

            {/* To-do's */}
            {steps.length > 0 && (
              <div style={{ background:'rgba(116,116,128,0.08)', borderRadius:18, padding:16 }}>
                <PDSectionTitle>To-do's</PDSectionTitle>
                <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
                  {steps.map((s,i)=>(
                    <div key={i} style={{ display:'flex', gap:11, alignItems:'flex-start', background:'#fff', borderRadius:13, padding:'11px 13px' }}>
                      <span style={{
                        ...PD_SERIF, fontSize:19, color:'rgba(2,1,0,0.3)',
                        width:26, flexShrink:0, textAlign:'right', lineHeight:1.1,
                      }}>{String(i+1).padStart(2,'0')}</span>
                      <div style={{ flex:1, minWidth:0 }}>
                        <div style={{ ...PD_SANS, fontSize:13.5, fontWeight:600, color:'#020100', lineHeight:1.3, marginBottom: s.desc ? 3 : 0 }}>{s.title}</div>
                        {s.desc && <div style={{ ...PD_SANS, fontSize:12, color:'rgba(2,1,0,0.6)', lineHeight:1.45 }}>{s.desc}</div>}
                      </div>
                    </div>
                  ))}
                </div>
              </div>
            )}

            {/* Video cursus */}
            {video && (
              <div style={{ background:'rgba(116,116,128,0.08)', borderRadius:18, padding:16 }}>
                <PDSectionTitle>Video cursus</PDSectionTitle>
                <div style={{ borderRadius:14, overflow:'hidden', cursor:'pointer', background:'#020100' }}>
                  <div style={{
                    aspectRatio:'16/9',
                    background: video.thumb ? `url(${video.thumb}) center/cover` : 'linear-gradient(145deg, #1A1A1A, #020100)',
                    position:'relative',
                  }}>
                    <div style={{ position:'absolute', inset:0, background:'rgba(0,0,0,0.32)' }} />
                    <div style={{
                      position:'absolute', inset:0,
                      display:'flex', alignItems:'center', justifyContent:'center',
                    }}>
                      <div style={{
                        width:54, height:54, borderRadius:'50%',
                        background:'rgba(255,255,255,0.95)',
                        display:'flex', alignItems:'center', justifyContent:'center',
                        boxShadow:'0 4px 14px rgba(0,0,0,0.35)',
                      }}>
                        <svg width="20" height="20" viewBox="0 0 24 24" fill="#020100"><path d="M8 5v14l11-7z"/></svg>
                      </div>
                    </div>
                  </div>
                  <div style={{ padding:'12px 14px' }}>
                    <div style={{ ...PD_SANS, fontSize:13.5, fontWeight:700, color:'#fff', marginBottom:3, letterSpacing:'-0.2px' }}>{video.title}</div>
                    <div style={{ ...PD_SANS, fontSize:11, color:'rgba(255,255,255,0.55)' }}>
                      {video.duration}{video.lessons ? ` · ${video.lessons}` : ''}
                    </div>
                  </div>
                </div>
              </div>
            )}

            {/* Challenges */}
            {challenges.length > 0 && (
              <div style={{ background:'rgba(116,116,128,0.08)', borderRadius:18, padding:16 }}>
                <PDSectionTitle>Challenges</PDSectionTitle>
                <p style={{ ...PD_SANS, fontSize:12, color:'rgba(2,1,0,0.55)', margin:'-4px 0 12px', lineHeight:1.4 }}>Stel jezelf uitdagingen om dit echt eigen te maken.</p>
                <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
                  {challenges.map((c,i)=>{
                    const lvlCol = c.level==='Beginner' ? '#34C759' : c.level==='Gevorderd' ? '#FF9500' : '#FF3B30';
                    return (
                      <div key={i} style={{ background:'#fff', borderRadius:13, padding:'11px 13px', display:'flex', gap:10, alignItems:'flex-start' }}>
                        <span style={{
                          ...PD_SANS, fontSize:9.5, fontWeight:700, color:lvlCol,
                          padding:'3px 9px', borderRadius:999,
                          background:`${lvlCol}18`,
                          textTransform:'uppercase', letterSpacing:'0.04em',
                          flexShrink:0, whiteSpace:'nowrap',
                        }}>{c.level}</span>
                        <span style={{ ...PD_SANS, fontSize:13, color:'rgba(2,1,0,0.78)', lineHeight:1.4, flex:1 }}>{c.desc}</span>
                      </div>
                    );
                  })}
                </div>
              </div>
            )}
          </div>
        </div>
      </div>
    </>
  );
};

const PracticalFolder = (props) => {
  const { title, manifest, count, type, status, creator, creatorImg, papers } = props;
  const [detailOpen, setDetailOpen] = React.useState(false);
  // status: 'new' | 'warn' | 'done' | undefined
  const STATUS_COLOR = status==='warn' ? '#FF9500' : status==='done' ? '#34C759' : '#34C759';
  const hasBadge = status==='new' || status==='done';
  const Shape = type === 'Knowledge' ? BookShape : ToolboxShape;
  // Building uses a handle on top — push folder down more to reveal it
  const folderInsetTop = type === 'Knowledge' ? '14%' : '18%';

  return (
    <div onClick={()=>setDetailOpen(true)} style={{ display:'flex', flexDirection:'column', alignItems:'center', cursor:'pointer' }}>
      <div style={{ position:'relative', width:'100%', aspectRatio:'1.05 / 1', marginBottom:12 }}>
        {/* Papers sticking out the top (behind the folder) */}
        {papers && papers.map((p,i) => (
          <FolderPaper
            key={i}
            left={p.left}
            top={p.top}
            rotate={p.rotate}
            kind={p.kind || (p.todos ? 'todos' : 'media')}
            todos={p.todos}
            media={p.media}
            badge={p.badge && (
              <span style={{
                width:16, height:16, borderRadius:'50%',
                background: p.badge==='check' ? '#34C759' : p.badge==='warn' ? '#FF9500' : '#C7C7CC',
                display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0,
                boxShadow:'0 1px 2px rgba(0,0,0,0.15)',
              }}>
                {p.badge==='check' && (
                  <svg width="9" height="9" viewBox="0 0 9 9" fill="none"><path d="M1.5 4.5 L3.5 6.5 L7.5 2" stroke="#fff" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/></svg>
                )}
                {p.badge==='warn' && <span style={{ color:'#fff', fontSize:10, fontWeight:800 }}>!</span>}
              </span>
            )}
          />
        ))}

        {/* Folder / book / toolbox (front) */}
        <div style={{ position:'absolute', inset:`${folderInsetTop} 0 0 0`, zIndex:2 }}>
          <Shape />

          {/* Manifest — sits above the creator signature */}
          {manifest && (
            <div style={{
              position:'absolute',
              left: type==='Knowledge' ? '18%' : '10%',
              right:'10%',
              bottom: '30%',
              fontFamily:'"Instrument Serif",Georgia,serif', fontStyle:'italic',
              fontSize:13, color:'rgba(2,1,0,0.55)', letterSpacing:'-0.2px',
              lineHeight:1.25, textWrap:'pretty',
            }}>{manifest}</div>
          )}

          {/* Creator signature — bottom-right, consistent across folder types */}
          {creator && creatorImg && (
            <div style={{
              position:'absolute', right:'8%', bottom:'9%',
              display:'flex', alignItems:'center', gap:6, zIndex:4,
            }}>
              <img src={creatorImg} alt="" style={{
                width:20, height:20, borderRadius:'50%',
                objectFit:'cover', border:'1.5px solid #FFFFFF',
                boxShadow:'0 1px 2px rgba(0,0,0,0.1)',
              }} />
              <span style={{
                fontSize:10.5, fontWeight:600, color:'rgba(2,1,0,0.62)',
                fontFamily:'Inter,system-ui,sans-serif', letterSpacing:'-0.1px',
              }}>{creator}</span>
            </div>
          )}

          {/* Status dot, top-right */}
          {hasBadge && (
            <div style={{
              position:'absolute', top: type==='Knowledge' ? '10%' : '22%', right:'9%',
              width:20, height:20, borderRadius:'50%',
              background: STATUS_COLOR,
              display:'flex', alignItems:'center', justifyContent:'center',
              zIndex:4, boxShadow:'0 1px 2px rgba(0,0,0,0.12)',
            }}>
              <svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 5.2 L4 7 L8 2.5" stroke="#fff" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"/></svg>
            </div>
          )}
        </div>
      </div>

      <div style={{ display:'flex', alignItems:'baseline', gap:8, textAlign:'center', justifyContent:'center' }}>
        <span style={{
          fontSize:15, fontWeight:700, color:'#020100',
          fontFamily:'Inter,system-ui,sans-serif', letterSpacing:'-0.3px',
          lineHeight:1.25,
        }}>{title}</span>
        <span style={{
          fontSize:13, color:'#8E8E93', fontFamily:'Inter,system-ui,sans-serif', fontWeight:500,
        }}>{count}</span>
      </div>

      <PracticalDetail practical={props} isOpen={detailOpen} onClose={(e)=>{ e && e.stopPropagation && e.stopPropagation(); setDetailOpen(false); }} />
    </div>
  );
};

const PracticalsTab = () => {
  const [typeF, setTypeF] = React.useState('Alle');
  const items = [
    {
      id:1, title:'Bosgym opstelling',
      manifest:'Outdoor bewegen, natuurlijke materialen, elk seizoen.',
      count:8, type:'Building', status:'new',
      creator:'Kees Jan', creatorImg:IMG.lisa,
      papers:[
        { left:'8%',  top:'3%',  rotate:-8, badge:'check', kind:'todos', todos:[
          { text:'Plek in bos kiezen', done:true },
          { text:'Grondcheck (stabiel)', done:true },
          { text:'Pull-up bar monteren', done:false },
        ]},
        { left:'30%', top:'0%',  rotate:4,  badge:null, kind:'media', media:['Plattegrond','Inspiratie','Materialen-lijst'] },
      ],
      achieve:[
        'Gratis trainingsplek waar je lekker naar toe fietst of wandelt.',
        'Sterker en beweeglijker worden met alleen lichaamsgewicht.',
        'Stabiele opstelling die 10+ jaar meegaat in weer en wind.',
        'Eigen plek die je met buren of vrienden kunt delen.',
      ],
      budget:{ amount:'€80–250', note:'hout, touw, bouten, boor-huur' },
      people:{ count:'2–4', note:'bouwdag gaat sneller met extra handen' },
      steps:[
        { title:'Plek scouten', desc:'Zoek open plek met 2 stevige bomen, genoeg ruimte eromheen, niet pal in het zicht van pad.' },
        { title:'Toestemming regelen', desc:'Bij particulier bos: eigenaar vragen. In natuurgebied: beheerder checken.' },
        { title:'Materialen bestellen', desc:'Massief hout, dynamische touw (12–14mm), galvanische bouten, carabiners.' },
        { title:'Bouwdag plannen', desc:'Goed weer, vrienden, gereedschap, snacks. Reken op 4–6 uur.' },
        { title:'Pull-up bar monteren', desc:'Tussen twee bomen op 2.3m, test met 120 kg statisch voor eerste gebruik.' },
        { title:'Rings en touwen toevoegen', desc:'Gymnastic rings op 2.5m, klimtouw (optioneel) op 4m+.' },
        { title:'Onderhoud-ritme bepalen', desc:'Elke 2 maanden knopen checken, elk seizoen touw inspecteren.' },
      ],
      video:{ title:'Bosgym bouwen — complete cursus', duration:'1u 24m', lessons:'6 lessen', thumb:IMG.cGym },
      challenges:[
        { level:'Beginner',   desc:'30 dagen 3x per week — 10 pull-ups totaal per sessie (mag in sets).' },
        { level:'Gevorderd',  desc:'60 dagen — 1 muscle-up op rings, volledige range.' },
        { level:'Expert',     desc:'Eigen bosgym bouwen + 5 buurtgenoten trainen op je opstelling.' },
      ],
    },
    {
      id:2, title:'Holacracy leren',
      manifest:'Besluiten zonder baas, ieders stem telt evenveel.',
      count:5, type:'Knowledge', status:'new',
      creator:'Joep', creatorImg:IMG.tom,
      papers:[
        { left:'10%', top:'2%',  rotate:-6, badge:'check', kind:'todos', todos:[
          { text:'Rollen definiëren', done:true },
          { text:'Check-in ronde', done:true },
          { text:'Spanningen verwerken', done:false },
        ]},
        { left:'34%', top:'4%',  rotate:3, badge:null, kind:'media', media:['Rol-diagram','Voorbeeld-agenda','Leesgids'] },
      ],
      achieve:[
        'Vergaderingen waar iedereen bijdraagt in plaats van een paar dominante stemmen.',
        'Rol-structuur waarin verantwoordelijkheden helder zijn — geen grijze zones.',
        'Besluiten die snel door — via bezwaren in plaats van consensus.',
        'Organisch groeiende organisatie die met de praktijk meebeweegt.',
      ],
      budget:{ amount:'€0–300', note:'boek en optionele facilitator-training' },
      people:{ count:'3–15', note:'werkt pas echt vanaf 3 personen in één cirkel' },
      steps:[
        { title:'Grondprincipes lezen', desc:'Holacracy van Brian Robertson, eerste 4 hoofdstukken — neem een week.' },
        { title:'Pilot-cirkel kiezen', desc:'Begin met 1 klein team — geen hele organisatie tegelijk.' },
        { title:'Rollen in kaart brengen', desc:'Purpose, accountabilities, domein per rol. Schrijf het concreet.' },
        { title:'Tactical meeting draaien', desc:'Check-in, agenda, tensions, check-out. Eerste keer max 30 min.' },
        { title:'Governance meeting plannen', desc:'Maandelijks — daar evolueren rollen op basis van spanningen.' },
        { title:'Rol-evolutie toepassen', desc:'Elke maand rollen bijschaven op basis van wat je leert.' },
      ],
      video:{ title:'Holacracy in praktijk — van 0 naar werkend', duration:'2u 10m', lessons:'9 lessen', thumb:IMG.cHolacracy },
      challenges:[
        { level:'Beginner',   desc:'Draai 4 tactical meetings back-to-back in 2 weken tijd.' },
        { level:'Gevorderd',  desc:'Faciliteer een governance meeting waar 3 nieuwe rollen uit komen.' },
        { level:'Expert',     desc:'Transformeer een heel team (8+ mensen) naar Holacracy in 3 maanden.' },
      ],
    },
    {
      id:3, title:'OBE oefen-ritueel',
      manifest:'Vaste avondvolgorde — lichaam klaar, geest open.',
      count:6, type:'Knowledge', status:'warn',
      creator:'Sara', creatorImg:IMG.sara,
      papers:[
        { left:'6%',  top:'1%',  rotate:-10, badge:'warn', kind:'todos', todos:[
          { text:'Kamer verduisteren', done:false },
          { text:'Ademwerk 10 min', done:false },
          { text:'Exit-techniek', done:false },
        ]},
        { left:'32%', top:'3%',  rotate:6, badge:'check', kind:'media', media:['Audio-cue','Journaal-template','Leesgids'] },
      ],
      achieve:[
        'Consistent gevoel van vibraties en lichaamsloslating binnen 3–5 weken oefenen.',
        'Rustige aanpak van sleep paralysis — geen paniek meer bij het fenomeen.',
        'Eerste heldere exit ervaring — zelfs al is het maar 30 seconden.',
        'Dieper inzicht in de grens tussen droom, bewustzijn en lichaam.',
      ],
      budget:{ amount:'€0–40', note:'verduisteringsmaskering + optioneel audio-cue' },
      people:{ count:'Solo', note:'kan samen in groeps-intentie gedaan worden' },
      steps:[
        { title:'Kamer verduisteren', desc:'Helemaal donker. Ook geen led-lampjes van elektronica.' },
        { title:'Body scan 20 minuten', desc:'Van kruin tot tenen — bewust elke spier ontspannen.' },
        { title:'Ademwerk opbouwen', desc:'10 min trage buikademhaling, dan 5 min rustig ritme.' },
        { title:'Exit-techniek proberen', desc:'Rope-techniek (Monroe): verbeeld dat je aan een touw omhoog klimt.' },
        { title:'Vibraties ontvangen', desc:'Wanneer ze komen: niet reageren, niet springen. Observeer.' },
        { title:'Journal direct erna', desc:'Binnen 2 minuten opschrijven — anders vervagen details snel.' },
      ],
      video:{ title:'Eerste OBE — ritueel en technieken', duration:'1u 48m', lessons:'8 lessen', thumb:IMG.cOBE },
      challenges:[
        { level:'Beginner',   desc:'14 dagen op rij het hele ritueel doorlopen — ongeacht resultaat.' },
        { level:'Gevorderd',  desc:'Eerste bewuste vibratie-ervaring uitwerken in journal met 5 concrete observaties.' },
        { level:'Expert',     desc:'Drie succesvolle exits in één maand, elk langer dan 60 seconden.' },
      ],
    },
    {
      id:4, title:'Meditatie thuis',
      manifest:'Korte sessies, vast ritme, geen drempels.',
      count:4, type:'Knowledge', status:'done',
      creator:'Melissa', creatorImg:IMG.nina,
      papers:[
        { left:'8%',  top:'4%', rotate:-5, badge:'check', kind:'todos', todos:[
          { text:'Plek inrichten', done:true },
          { text:'Dagelijks 10 min', done:true },
          { text:'Logboek bijhouden', done:true },
        ]},
        { left:'34%', top:'2%', rotate:3, badge:'check', kind:'media', media:['Ademgids','Timer-setup','Ankerwoorden'] },
      ],
      achieve:[
        'Vaste ochtend-routine die na 3 weken vanzelf gaat — geen willpower meer nodig.',
        'Merkbaar rustigere reactie op stress en ongemak in het dagelijks leven.',
        'Een "thuisbasis" in je eigen hoofd waar je altijd naar kunt terugkeren.',
        'Scherper observatievermogen — herkennen van gedachten vs. identificatie.',
      ],
      budget:{ amount:'€0–50', note:'kussen, timer-app, evt. ritueel-kaars' },
      people:{ count:'Solo', note:'vaak sterker samen — maar hoeft niet' },
      steps:[
        { title:'Plek kiezen', desc:'Zelfde plek elke dag. Hoekje, kussen, misschien een plant of kaars.' },
        { title:'Tijdstip vastzetten', desc:'Ochtend direct na opstaan werkt het best — voor koffie, voor email.' },
        { title:'Timer op 10 min', desc:'Niet minder, niet meer. Begin klein zodat het niet overweldigend voelt.' },
        { title:'Simpele techniek', desc:'Adem tellen 1 tot 10, dan opnieuw. Afgedwaald? Gewoon terug naar 1.' },
        { title:'Logboek na de sessie', desc:'1 zin: hoe voelde het? Wat viel op?' },
        { title:'Na 30 dagen evalueren', desc:'Merk je verschil in je dag? Wil je langer? Andere techniek?' },
      ],
      video:{ title:'Thuis-meditatie van 0 tot gewoonte', duration:'54m', lessons:'5 lessen', thumb:IMG.cMeditatie },
      challenges:[
        { level:'Beginner',   desc:'7 dagen op rij, elke dag 10 minuten — zelfs op de dagen dat je geen zin hebt.' },
        { level:'Gevorderd',  desc:'30 dagen streak + 1 stille uren-sessie zonder timer.' },
        { level:'Expert',     desc:'90 dagen zonder onderbreking + 1 volledige dag in stilte (zelf-retraite).' },
      ],
    },
    {
      id:5, title:'Homeschool dagritme',
      manifest:'Gedragen structuur, ruimte voor eigen tempo.',
      count:3, type:'Knowledge', status:'new',
      creator:'Jelle', creatorImg:IMG.mark,
      papers:[
        { left:'10%', top:'2%', rotate:-7, badge:'check', kind:'todos', todos:[
          { text:'Blokken bepalen', done:true },
          { text:'Pauzes plannen', done:false },
          { text:'Weekplanning', done:false },
        ]},
      ],
      achieve:[
        'Dagritme waar kinderen zich veilig en productief in voelen.',
        'Leren-blokken met focus in plaats van versplinterde aandacht.',
        'Ruimte voor eigen tempo — snelle vakken versnellen, langzame lopen door.',
        'Ouder die niet aan het einde van elke dag uitgeput is.',
      ],
      budget:{ amount:'€50–200', note:'planner, werkboeken, lesmateriaal per kind' },
      people:{ count:'Gezin', note:'werkt vanaf 1 ouder + 1 kind' },
      steps:[
        { title:'Dagblokken bepalen', desc:'Bv. 8:30–10:00 focus, 10:00–10:30 pauze, 10:30–12:00 focus, middag vrij.' },
        { title:'Vaste opstart', desc:'Check-in met kinderen: wat leren we vandaag? Kleine intentie zetten.' },
        { title:'Vakken roteren', desc:'Niet 4 uur wiskunde. Liever 45 min wisk, 45 min taal, 45 min creatief.' },
        { title:'Echte pauzes', desc:'Buiten, water, bewegen. Geen schermen in pauzetijd.' },
        { title:'Middag vrijer', desc:'Natuur, hobby, sociale activiteit. School hoeft niet 8 uur te duren.' },
        { title:'Weekreflectie met kids', desc:'Wat werkte? Wat niet? Wat passen we aan volgende week?' },
      ],
      video:{ title:'Homeschool dagritme — werkend model', duration:'1u 12m', lessons:'6 lessen', thumb:IMG.cHomeschool },
      challenges:[
        { level:'Beginner',   desc:'1 week volgens vast blokken-ritme, elke dag dezelfde structuur.' },
        { level:'Gevorderd',  desc:'1 maand ritme volhouden en wekelijkse reflectie met kinderen doen.' },
        { level:'Expert',     desc:'Heel schooljaar werkend ritme + 1 andere homeschool-gezin coachen in ritme-setup.' },
      ],
    },
    {
      id:6, title:'Tinyhouse ontwerpen',
      manifest:'Minimaal oppervlak, maximaal comfort, lichte voetafdruk.',
      count:2, type:'Building', status:'new',
      creator:'Joep', creatorImg:IMG.tom,
      papers:[
        { left:'8%',  top:'3%', rotate:-6, badge:'check', kind:'todos', todos:[
          { text:'Plattegrond v1', done:true },
          { text:'Materialen kiezen', done:true },
          { text:'Vergunning', done:false },
        ]},
        { left:'32%', top:'1%', rotate:4, badge:null, kind:'media', media:['Plattegrond','Inspiratie-foto','Schema'] },
      ],
      achieve:[
        'Plattegrond waar je elk ding bewust plaatst — geen verspilde meters.',
        'Concrete materialenlijst waarmee je budget helder is vóór bouwen.',
        'Vergunning-traject op gang — kansen en struikelpunten in kaart.',
        'Zelfvertrouwen om daadwerkelijk te beginnen in plaats van alleen dromen.',
      ],
      budget:{ amount:'€35k–80k', note:'excl. grond — afhankelijk van DIY-niveau' },
      people:{ count:'1–2 + helpers', note:'ontwerpfase solo, bouw met 2+' },
      steps:[
        { title:'Dagritme vastleggen', desc:'Hoe woon je echt? Cook, werk, slaap — waar wil je hoeveel ruimte?' },
        { title:'Eerste schets', desc:'Met de hand, op papier. Niet digitaal. Voel de verhoudingen.' },
        { title:'Plattegrond v1', desc:'Digitaal tekenen (SketchUp / Floorplanner). Max 24m² is standaard.' },
        { title:'Materialen kiezen', desc:'Hout, isolatie, ramen, dak. Begin met 3 offertes per categorie.' },
        { title:'Budget concretiseren', desc:'Lijst compleet? Reken 15% buffer voor verrassingen.' },
        { title:'Vergunning-verkenning', desc:'Bel je gemeente. Vraag naar pilot-locaties of bijzonder gebruik.' },
        { title:'Beslismoment', desc:'Wel/niet door? Als ja: bouwdatum prikken en commitment maken.' },
      ],
      video:{ title:'Tinyhouse ontwerpen — van droom naar tekening', duration:'2u 35m', lessons:'11 lessen', thumb:IMG.cTinyhouse },
      challenges:[
        { level:'Beginner',   desc:'Maak 3 verschillende plattegronden in 1 week — dwing jezelf te variëren.' },
        { level:'Gevorderd',  desc:'Volledige materialenlijst met budget + vergunning-gesprek bij gemeente.' },
        { level:'Expert',     desc:'Ontwerp en bouw je eigen tinyhouse + deel draaiboek met community.' },
      ],
    },
  ];

  const filtered = typeF==='Alle' ? items : items.filter(i=>i.type===typeF);

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:20 }}>
      <div style={{ display:'flex', gap:8 }}>
        {['Alle','Knowledge','Building'].map(t=><Pill key={t} active={typeF===t} onClick={()=>setTypeF(t)}>{t}</Pill>)}
      </div>

      <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:22, rowGap:36 }}>
        {filtered.map(p => <PracticalFolder key={p.id} {...p} />)}
      </div>
    </div>
  );
};

// ─── Events — editorial date rail ─────────────────────────────────────────
// ─── Event detail overlay ─────────────────────────────────────────────────
const EventDetail = ({ event, isOpen, onClose }) => {
  const e = event || {};
  const isDigital = e.type === 'Digitaal';
  const typeCol   = e.typeColor || (isDigital ? '#007AFF' : '#020100');
  const description = e.description || '';
  const takeaways   = e.takeaways   || [];
  const host        = e.host;
  const meetLink    = e.meetLink;
  const meetPlatform= e.meetPlatform || 'Google Meet';
  const techCheck   = e.techCheck   || [];
  const address     = e.address;
  const transport   = e.transport;
  const bring       = e.bring       || [];
  const agenda      = e.agenda      || [];
  const prepare     = e.prepare     || [];
  const questions   = e.questions   || [];
  const cost        = e.cost;

  const [newQ,    setNewQ]    = React.useState('');
  const [localQs, setLocalQs] = React.useState([]);
  const [copied,  setCopied]  = React.useState(false);

  const submitQuestion = () => {
    if (!newQ.trim()) return;
    setLocalQs(qs => [...qs, { text:newQ.trim(), by:'Kevin (jij)' }]);
    setNewQ('');
  };
  const copyLink = async () => {
    try { await navigator.clipboard.writeText(meetLink); setCopied(true); setTimeout(()=>setCopied(false), 2000); } catch {}
  };
  const stop = (ev) => ev.stopPropagation();
  const allQs = [...questions, ...localQs];

  return (
    <>
      <div onClick={(ev)=>{ ev.stopPropagation(); onClose(ev); }} style={{
        position:'absolute', inset:0, zIndex:350,
        background:'rgba(20,18,16,0.55)',
        backdropFilter:'blur(4px)', WebkitBackdropFilter:'blur(4px)',
        opacity: isOpen?1:0, pointerEvents: isOpen?'auto':'none',
        transition:'opacity 0.25s',
      }} />
      <div onClick={stop} style={{
        position:'absolute', top:24, left:12, right:12, bottom:24,
        background:'#fff', borderRadius:26, zIndex:360, overflow:'hidden',
        transform: isOpen ? 'translateY(0) scale(1)' : 'translateY(20px) scale(0.96)',
        opacity: isOpen?1:0, pointerEvents: isOpen?'auto':'none',
        transition:'all 0.32s cubic-bezier(0.2,0.9,0.25,1)',
        boxShadow:'0 24px 60px rgba(0,0,0,0.28), 0 0 0 1px rgba(0,0,0,0.04)',
      }}>
        <button onClick={(ev)=>{ ev.stopPropagation(); onClose(ev); }} style={{
          position:'absolute', top:14, right:14, zIndex:10,
          width:32, height:32, borderRadius:'50%',
          background:'rgba(255,255,255,0.95)', border:'none',
          display:'flex', alignItems:'center', justifyContent:'center', cursor:'pointer',
          boxShadow:'0 2px 8px rgba(0,0,0,0.18)',
        }}>
          <Ico.X size={14} />
        </button>

        <div style={{ height:'100%', overflowY:'auto', scrollbarWidth:'none', WebkitOverflowScrolling:'touch' }}>
          {/* Hero image */}
          {e.img && (
            <div style={{ position:'relative', height:160, marginBottom:-40 }}>
              <img src={e.img} alt="" style={{ width:'100%', height:'100%', objectFit:'cover' }} />
              <div style={{ position:'absolute', inset:0, background:'linear-gradient(to bottom, rgba(0,0,0,0.15) 0%, rgba(0,0,0,0.05) 40%, #fff 100%)' }} />
            </div>
          )}

          {/* Header */}
          <div style={{ padding:'10px 22px 14px', position:'relative' }}>
            <span style={{
              ...PD_SANS, fontSize:10, fontWeight:700, color:typeCol,
              padding:'3px 10px', borderRadius:999, background:`${typeCol}18`,
              textTransform:'uppercase', letterSpacing:'0.08em',
              display:'inline-block', marginBottom:8,
            }}>{e.type}</span>
            <h1 style={{ ...PD_SERIF, fontSize:30, color:'#020100', margin:'0 0 10px', lineHeight:1.05 }}>{e.title}</h1>

            <div style={{ display:'flex', alignItems:'center', gap:12, marginBottom:12, flexWrap:'wrap' }}>
              <div style={{ display:'inline-flex', alignItems:'center', gap:6 }}>
                <Ico.Cal size={14} color="#8E8E93" />
                <span style={{ ...PD_SANS, fontSize:13, color:'rgba(2,1,0,0.78)', fontWeight:600 }}>{e.day} {e.date} {e.month}</span>
              </div>
              <div style={{ display:'inline-flex', alignItems:'center', gap:6 }}>
                <Ico.Clock size={14} color="#8E8E93" />
                <span style={{ ...PD_SANS, fontSize:13, color:'rgba(2,1,0,0.78)', fontWeight:600 }}>{e.time}</span>
              </div>
              {cost && <span style={{ ...PD_SANS, fontSize:12, color:'rgba(2,1,0,0.6)', fontWeight:500 }}>· {cost}</span>}
            </div>

            {e.attending && e.attending.length > 0 && (
              <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:14 }}>
                <div style={{ display:'flex' }}>
                  {e.attending.slice(0,5).map((src,i)=>(
                    <img key={i} src={src} alt="" style={{ width:24, height:24, borderRadius:'50%', objectFit:'cover', border:'2px solid #fff', marginLeft: i===0?0:-8 }} />
                  ))}
                </div>
                <span style={{ ...PD_SANS, fontSize:12, color:'rgba(2,1,0,0.65)' }}><b style={{ color:'#020100', fontWeight:700 }}>{e.count}</b> gaan erheen</span>
              </div>
            )}

            <button style={{
              width:'100%', padding:'12px 0', borderRadius:999,
              background:'#020100', color:'#fff', border:'none',
              ...PD_SANS, fontSize:13, fontWeight:700, cursor:'pointer', letterSpacing:'0.02em',
            }}>Aanmelden</button>
          </div>

          <div style={{ padding:'0 18px 36px', display:'flex', flexDirection:'column', gap:14 }}>
            {description && (
              <div style={{ background:'rgba(116,116,128,0.08)', borderRadius:18, padding:16 }}>
                <PDSectionTitle>Over dit event</PDSectionTitle>
                <p style={{ ...PD_SANS, fontSize:13.5, color:'rgba(2,1,0,0.75)', lineHeight:1.55, margin:0 }}>{description}</p>
              </div>
            )}

            {takeaways.length > 0 && (
              <div style={{ background:'rgba(116,116,128,0.08)', borderRadius:18, padding:16 }}>
                <PDSectionTitle>Wat je eruit haalt</PDSectionTitle>
                <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
                  {takeaways.map((t,i)=>(
                    <div key={i} style={{ display:'flex', gap:10, alignItems:'flex-start' }}>
                      <span style={{ width:20, height:20, flexShrink:0, marginTop:1, borderRadius:'50%', background:'rgba(52,199,89,0.15)', display:'flex', alignItems:'center', justifyContent:'center' }}>
                        <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="#34C759" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
                      </span>
                      <span style={{ ...PD_SANS, fontSize:13.5, color:'rgba(2,1,0,0.8)', lineHeight:1.45 }}>{t}</span>
                    </div>
                  ))}
                </div>
              </div>
            )}

            {isDigital && meetLink && (
              <div style={{ background:'rgba(116,116,128,0.08)', borderRadius:18, padding:16 }}>
                <PDSectionTitle>Online deelnemen</PDSectionTitle>
                <div style={{ background:'#020100', borderRadius:14, padding:'14px 16px', marginBottom: techCheck.length ? 14 : 0 }}>
                  <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:8 }}>
                    <div style={{ width:24, height:24, borderRadius:6, background:typeCol, display:'flex', alignItems:'center', justifyContent:'center' }}>
                      <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.3" strokeLinecap="round" strokeLinejoin="round"><polygon points="23 7 16 12 23 17 23 7"/><rect x="1" y="5" width="15" height="14" rx="2" ry="2"/></svg>
                    </div>
                    <span style={{ ...PD_SANS, fontSize:13, fontWeight:700, color:'#fff', letterSpacing:'-0.1px' }}>{meetPlatform}</span>
                  </div>
                  <div style={{ ...PD_SANS, fontSize:11.5, color:'rgba(255,255,255,0.65)', wordBreak:'break-all', marginBottom:10, fontFamily:'ui-monospace,monospace' }}>{meetLink}</div>
                  <div style={{ display:'flex', gap:8 }}>
                    <button onClick={copyLink} style={{
                      flex:1, padding:'9px 0', borderRadius:9,
                      background: copied ? '#34C759' : 'rgba(255,255,255,0.14)',
                      color:'#fff', border:'none', cursor:'pointer',
                      ...PD_SANS, fontSize:12, fontWeight:600, transition:'background 0.2s',
                    }}>{copied ? '✓ Gekopieerd' : 'Kopieer link'}</button>
                    <button style={{
                      flex:1, padding:'9px 0', borderRadius:9,
                      background:'#fff', color:'#020100', border:'none', cursor:'pointer',
                      ...PD_SANS, fontSize:12, fontWeight:700,
                    }}>Deelnemen →</button>
                  </div>
                </div>
                {techCheck.length > 0 && (
                  <div>
                    <span style={{ ...PD_SANS, fontSize:10.5, fontWeight:700, color:'rgba(2,1,0,0.5)', textTransform:'uppercase', letterSpacing:'0.08em', display:'block', marginBottom:8 }}>Tech check</span>
                    <div style={{ display:'flex', flexDirection:'column', gap:5 }}>
                      {techCheck.map((t,i)=>(
                        <div key={i} style={{ display:'flex', gap:8, alignItems:'center' }}>
                          <span style={{ width:4, height:4, borderRadius:'50%', background:'rgba(2,1,0,0.35)', flexShrink:0 }} />
                          <span style={{ ...PD_SANS, fontSize:12.5, color:'rgba(2,1,0,0.75)' }}>{t}</span>
                        </div>
                      ))}
                    </div>
                  </div>
                )}
              </div>
            )}

            {!isDigital && (address || e.loc) && (
              <div style={{ background:'rgba(116,116,128,0.08)', borderRadius:18, padding:16 }}>
                <PDSectionTitle>Locatie</PDSectionTitle>
                <div style={{
                  background:'linear-gradient(135deg,#E8EBF0,#D0D5E0)',
                  borderRadius:14, padding:'14px 16px', marginBottom:10,
                  position:'relative', overflow:'hidden',
                }}>
                  <div aria-hidden="true" style={{
                    position:'absolute', inset:0, opacity:0.18,
                    backgroundImage:'linear-gradient(0deg, transparent 24%, rgba(0,0,0,0.5) 25%, rgba(0,0,0,0.5) 26%, transparent 27%, transparent 74%, rgba(0,0,0,0.5) 75%, rgba(0,0,0,0.5) 76%, transparent 77%), linear-gradient(90deg, transparent 24%, rgba(0,0,0,0.5) 25%, rgba(0,0,0,0.5) 26%, transparent 27%, transparent 74%, rgba(0,0,0,0.5) 75%, rgba(0,0,0,0.5) 76%, transparent 77%)',
                    backgroundSize:'22px 22px',
                  }} />
                  <div style={{ position:'relative', display:'flex', alignItems:'flex-start', gap:12 }}>
                    <div style={{ width:34, height:34, borderRadius:'50%', background:'#FF3B30', display:'flex', alignItems:'center', justifyContent:'center', boxShadow:'0 2px 8px rgba(0,0,0,0.25)', flexShrink:0 }}>
                      <Ico.Pin size={16} color="#fff" />
                    </div>
                    <div style={{ flex:1, minWidth:0 }}>
                      <div style={{ ...PD_SANS, fontSize:13.5, fontWeight:700, color:'#020100', marginBottom:3, lineHeight:1.3 }}>{address || e.loc}</div>
                      {transport && <div style={{ ...PD_SANS, fontSize:11.5, color:'rgba(2,1,0,0.6)', lineHeight:1.4 }}>{transport}</div>}
                    </div>
                  </div>
                </div>
                <button style={{
                  width:'100%', padding:'10px 0', borderRadius:10,
                  background:'rgba(0,122,255,0.12)', color:'#007AFF',
                  border:'none', cursor:'pointer',
                  ...PD_SANS, fontSize:12.5, fontWeight:600,
                }}>Route plannen →</button>

                {bring.length > 0 && (
                  <div style={{ marginTop:14 }}>
                    <span style={{ ...PD_SANS, fontSize:10.5, fontWeight:700, color:'rgba(2,1,0,0.5)', textTransform:'uppercase', letterSpacing:'0.08em', display:'block', marginBottom:8 }}>Meenemen</span>
                    <div style={{ display:'flex', flexWrap:'wrap', gap:5 }}>
                      {bring.map((b,i)=>(
                        <span key={i} style={{
                          ...PD_SANS, fontSize:11.5, fontWeight:500,
                          padding:'4px 10px', borderRadius:999,
                          background:'#fff', color:'rgba(2,1,0,0.75)',
                          border:'1px solid rgba(2,1,0,0.06)',
                        }}>{b}</span>
                      ))}
                    </div>
                  </div>
                )}
              </div>
            )}

            {agenda.length > 0 && (
              <div style={{ background:'rgba(116,116,128,0.08)', borderRadius:18, padding:16 }}>
                <PDSectionTitle>Programma</PDSectionTitle>
                <div style={{ display:'flex', flexDirection:'column', gap:4 }}>
                  {agenda.map((a,i)=>(
                    <div key={i} style={{ display:'flex', gap:12, alignItems:'flex-start', padding:'10px 12px', background:'#fff', borderRadius:10 }}>
                      <span style={{ ...PD_SANS, fontSize:11.5, fontWeight:700, color:typeCol, width:48, flexShrink:0, fontVariantNumeric:'tabular-nums' }}>{a.time}</span>
                      <span style={{ ...PD_SANS, fontSize:12.5, color:'rgba(2,1,0,0.78)', lineHeight:1.4, flex:1 }}>{a.item}</span>
                    </div>
                  ))}
                </div>
              </div>
            )}

            {prepare.length > 0 && (
              <div style={{ background:'rgba(116,116,128,0.08)', borderRadius:18, padding:16 }}>
                <PDSectionTitle>Voorbereiding</PDSectionTitle>
                <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
                  {prepare.map((p,i)=>(
                    <div key={i} style={{ display:'flex', gap:10, alignItems:'flex-start' }}>
                      <span style={{ width:22, height:22, flexShrink:0, borderRadius:7, background:'rgba(255,149,0,0.14)', display:'flex', alignItems:'center', justifyContent:'center' }}>
                        <span style={{ ...PD_SANS, fontSize:11, fontWeight:700, color:'#FF9500' }}>{i+1}</span>
                      </span>
                      <span style={{ ...PD_SANS, fontSize:13, color:'rgba(2,1,0,0.78)', lineHeight:1.45, flex:1 }}>{p}</span>
                    </div>
                  ))}
                </div>
              </div>
            )}

            {/* Vragen insturen */}
            <div style={{ background:'rgba(116,116,128,0.08)', borderRadius:18, padding:16 }}>
              <PDSectionTitle>Vragen insturen</PDSectionTitle>
              <p style={{ ...PD_SANS, fontSize:12, color:'rgba(2,1,0,0.55)', margin:'-4px 0 12px', lineHeight:1.4 }}>Stuur je vraag vooraf — de host neemt hem mee.</p>
              <div style={{ display:'flex', gap:8, marginBottom: allQs.length ? 12 : 0 }}>
                <input
                  value={newQ}
                  onChange={ev=>setNewQ(ev.target.value)}
                  onKeyDown={ev=>{ if(ev.key==='Enter') submitQuestion(); }}
                  placeholder="Typ je vraag…"
                  style={{
                    flex:1, padding:'10px 12px', borderRadius:10,
                    border:'1px solid rgba(2,1,0,0.08)', background:'#fff',
                    ...PD_SANS, fontSize:13, color:'#020100', outline:'none',
                  }}
                />
                <button onClick={submitQuestion} style={{
                  padding:'0 16px', borderRadius:10,
                  background:'#020100', color:'#fff', border:'none', cursor:'pointer',
                  ...PD_SANS, fontSize:12, fontWeight:700,
                }}>Stuur</button>
              </div>
              {allQs.length > 0 && (
                <div>
                  <span style={{ ...PD_SANS, fontSize:10.5, fontWeight:700, color:'rgba(2,1,0,0.5)', textTransform:'uppercase', letterSpacing:'0.08em', display:'block', marginBottom:8 }}>{allQs.length} {allQs.length===1?'vraag':'vragen'} tot nu</span>
                  <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
                    {allQs.map((q,i)=>(
                      <div key={i} style={{ background:'#fff', borderRadius:10, padding:'10px 12px' }}>
                        <div style={{ ...PD_SANS, fontSize:12.5, color:'rgba(2,1,0,0.82)', lineHeight:1.4, marginBottom:3 }}>"{q.text}"</div>
                        <div style={{ ...PD_SANS, fontSize:10.5, color:'rgba(2,1,0,0.5)' }}>— {q.by}</div>
                      </div>
                    ))}
                  </div>
                </div>
              )}
            </div>

            {host && (
              <div style={{ background:'rgba(116,116,128,0.08)', borderRadius:18, padding:16 }}>
                <PDSectionTitle>Host</PDSectionTitle>
                <div style={{ display:'flex', alignItems:'center', gap:12 }}>
                  <img src={host.src} alt="" style={{ width:46, height:46, borderRadius:'50%', objectFit:'cover' }} />
                  <div style={{ flex:1, minWidth:0 }}>
                    <div style={{ ...PD_SANS, fontSize:14, fontWeight:700, color:'#020100', lineHeight:1.2 }}>{host.name}</div>
                    <div style={{ ...PD_SANS, fontSize:11.5, color:'rgba(2,1,0,0.55)' }}>{host.role}</div>
                  </div>
                  <button style={{
                    padding:'8px 14px', borderRadius:999,
                    background:'rgba(116,116,128,0.12)', color:'#020100',
                    border:'none', cursor:'pointer',
                    ...PD_SANS, fontSize:11.5, fontWeight:700,
                  }}>Bericht</button>
                </div>
              </div>
            )}
          </div>
        </div>
      </div>
    </>
  );
};

const EventsTab = () => {
  const [activeEvent, setActiveEvent] = React.useState(null);
  const events = PERSONAL_EVENTS.map(resolvePersonalEvent);

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
      {/* Hero: next event — tactile dark card */}
      <div onClick={()=>setActiveEvent(events[0])} style={{
        background:'linear-gradient(145deg, #1a1a1a 0%, #020100 100%)',
        borderRadius:22, overflow:'hidden', position:'relative', cursor:'pointer',
        boxShadow:'0 2px 4px rgba(0,0,0,0.12), 0 8px 16px rgba(0,0,0,0.18), 0 24px 48px rgba(0,0,0,0.24), inset 0 1px 0 rgba(255,255,255,0.12)',
        border:'1px solid rgba(255,255,255,0.06)',
      }}>
        <div style={{ position:'relative', height:120 }}>
          <img src={events[0].img} alt="" style={{ width:'100%', height:'100%', objectFit:'cover', opacity:0.55 }} />
          <div style={{ position:'absolute', inset:0, background:'linear-gradient(to bottom, transparent 0%, #020100 100%)' }} />
          <div style={{
            position:'absolute', top:14, left:14,
            display:'flex', alignItems:'center', gap:6,
            padding:'5px 11px', borderRadius:999,
            background:'rgba(255,255,255,0.15)',
            backdropFilter:'blur(20px)', WebkitBackdropFilter:'blur(20px)',
            border:'1px solid rgba(255,255,255,0.25)',
            boxShadow:'0 2px 8px rgba(0,0,0,0.15), inset 0 1px 0 rgba(255,255,255,0.3)',
          }}>
            <span style={{ width:6, height:6, borderRadius:'50%', background:'#34C759', boxShadow:'0 0 6px rgba(52,199,89,0.6)' }} />
            <span style={{ fontSize:11, fontWeight:600, color:'#fff', fontFamily:'Inter,system-ui,sans-serif' }}>Eerstvolgend</span>
          </div>
        </div>
        <div style={{ padding:'0 20px 20px', marginTop:-10, position:'relative' }}>
          <div style={{ fontSize:11, color:'rgba(255,255,255,0.5)', textTransform:'uppercase', letterSpacing:'0.08em', fontWeight:600, fontFamily:'Inter,system-ui,sans-serif', marginBottom:6 }}>
            {events[0].day} {events[0].date} {events[0].month} · {events[0].time}
          </div>
          <h3 style={{
            fontFamily:'"Instrument Serif",Georgia,serif', fontWeight:400,
            fontSize:26, color:'#fff', letterSpacing:'-0.4px',
            lineHeight:1.1, margin:'0 0 10px',
          }}>{events[0].title}</h3>
          <div style={{ display:'flex', alignItems:'center', gap:10 }}>
            <div style={{ display:'flex' }}>
              {events[0].attending.slice(0,4).map((src,i)=>(
                <img key={i} src={src} alt="" style={{
                  width:22, height:22, borderRadius:'50%', objectFit:'cover',
                  border:'2px solid #020100', marginLeft: i===0?0:-7,
                }} />
              ))}
            </div>
            <span style={{ fontSize:12, color:'rgba(255,255,255,0.6)', fontFamily:'Inter,system-ui,sans-serif' }}>
              <b style={{ color:'#fff', fontWeight:700 }}>{events[0].count}</b> gaan erheen
            </span>
            <button onClick={(e)=>{ e.stopPropagation(); setActiveEvent(events[0]); }} style={{
              marginLeft:'auto', padding:'9px 18px', borderRadius:999,
              border:'1px solid rgba(255,255,255,0.5)',
              background:'linear-gradient(145deg, #ffffff, #ececec)',
              color:'#020100',
              fontSize:12, fontWeight:700, cursor:'pointer',
              fontFamily:'Inter,system-ui,sans-serif',
              boxShadow:'0 2px 4px rgba(0,0,0,0.12), 0 6px 14px rgba(0,0,0,0.18), inset 0 1px 0 rgba(255,255,255,0.9)',
            }}>Aanmelden</button>
          </div>
        </div>
      </div>

      {/* Date rail list */}
      <div style={{
        fontSize:11, fontWeight:700, color:'#8E8E93',
        textTransform:'uppercase', letterSpacing:'0.08em',
        fontFamily:'Inter,system-ui,sans-serif', marginTop:6, paddingLeft:4,
      }}>Komende events · {events.length - 1}</div>

      <div style={{ display:'flex', flexDirection:'column', gap:20 }}>
        {events.slice(1).map((ev, idx) => {
          const tearX = 100;
          const notchR = 13;
          const stubWidth = 100;
          const ticketMaskImages = [
            `radial-gradient(circle ${notchR}px at ${tearX}px 0, transparent ${notchR - 0.5}px, #000 ${notchR + 0.5}px)`,
            `radial-gradient(circle ${notchR}px at ${tearX}px 100%, transparent ${notchR - 0.5}px, #000 ${notchR + 0.5}px)`,
          ].join(', ');
          const maskProps = {
            WebkitMaskImage: ticketMaskImages,
            maskImage: ticketMaskImages,
            WebkitMaskSize: '100% 50%, 100% 50%',
            maskSize: '100% 50%, 100% 50%',
            WebkitMaskPosition: 'top, bottom',
            maskPosition: 'top, bottom',
            WebkitMaskRepeat: 'no-repeat, no-repeat',
            maskRepeat: 'no-repeat, no-repeat',
          };
          const serial = String(1042 + idx*7).padStart(4, '0');
          const typeCode = ev.type.slice(0,3).toUpperCase();
          return (
          <div key={ev.title} onClick={()=>setActiveEvent(ev)} style={{
            filter:'drop-shadow(0 2px 3px rgba(0,0,0,0.05)) drop-shadow(0 10px 20px rgba(0,0,0,0.08)) drop-shadow(0 24px 44px rgba(0,0,0,0.1))',
            cursor:'pointer',
          }}>
          <div style={{
            display:'flex', alignItems:'stretch',
            background:'linear-gradient(145deg, #FEFEFB 0%, #F8F7F1 100%)',
            borderRadius:16,
            position:'relative',
            minHeight:108,
            ...maskProps,
          }}>
            {/* Inner frame — lighter outline following ticket body */}
            <div aria-hidden="true" style={{
              position:'absolute',
              top: 8, bottom: 8,
              left: 8, right: 8,
              border:'1px dashed rgba(0,0,0,0.18)',
              borderRadius:10,
              pointerEvents:'none',
            }} />

            {/* Dotted perforated tear line */}
            <div aria-hidden="true" style={{
              position:'absolute',
              left: tearX - 1.5,
              top: notchR + 8, bottom: notchR + 8,
              width: 3,
              backgroundImage: 'radial-gradient(circle, rgba(0,0,0,0.42) 1.1px, transparent 1.4px)',
              backgroundSize: '3px 6px',
              backgroundRepeat: 'repeat-y',
              pointerEvents:'none',
            }} />

            {/* Left stub — month / date / day only */}
            <div style={{
              width:stubWidth, flexShrink:0, display:'flex', flexDirection:'column',
              alignItems:'center', justifyContent:'center',
              padding:'14px 10px',
            }}>
              <div style={{
                fontSize:10, color:'#8E8E93', fontFamily:'Inter,system-ui,sans-serif',
                textTransform:'uppercase', fontWeight:700, letterSpacing:'0.1em',
              }}>{ev.month}</div>
              <div style={{
                fontFamily:'"Instrument Serif",Georgia,serif', fontWeight:400,
                fontSize:36, color:'#020100', letterSpacing:'-1.1px', lineHeight:1,
                textShadow:'0 1px 0 rgba(255,255,255,0.9)',
              }}>{ev.date}</div>
              <div style={{
                fontSize:10, color:'#8E8E93', fontFamily:'Inter,system-ui,sans-serif',
                fontWeight:500, marginTop:2,
              }}>{ev.day}</div>
            </div>

            {/* Body */}
            <div style={{
              flex:1, minWidth:0, display:'flex', gap:12, alignItems:'center',
              padding:'14px 18px 14px 24px',
            }}>
              <div style={{
                flex:1, minWidth:0, display:'flex', flexDirection:'column', justifyContent:'center', gap:4,
              }}>
                {/* Title */}
                <div style={{
                  fontFamily:'"Instrument Serif",Georgia,serif', fontWeight:400,
                  fontSize:19, color:'#020100', letterSpacing:'-0.3px',
                  lineHeight:1.1,
                  overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap',
                }}>{ev.title}</div>

                {/* Meta */}
                <div style={{
                  fontSize:11, color:'#6B6B70', fontFamily:'Inter,system-ui,sans-serif',
                  overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap',
                }}>{ev.time} · {ev.loc}</div>

                {/* Footer */}
                <div style={{
                  display:'flex', alignItems:'center', gap:8, marginTop:2,
                }}>
                  <span style={{
                    fontSize:9, padding:'3px 9px', borderRadius:999,
                    background:`linear-gradient(145deg, ${ev.typeColor}1f, ${ev.typeColor}10)`,
                    color:ev.typeColor, fontFamily:'Inter,system-ui,sans-serif', fontWeight:700,
                    border:`1px solid ${ev.typeColor}28`, letterSpacing:'0.06em',
                    textTransform:'uppercase',
                  }}>{ev.type}</span>
                  <div style={{ display:'flex' }}>
                    {ev.attending.slice(0,3).map((src,i)=>(
                      <img key={i} src={src} alt="" style={{
                        width:18, height:18, borderRadius:'50%', objectFit:'cover',
                        border:'2px solid #F7F6F0', marginLeft: i===0?0:-6,
                        boxShadow:'0 1px 2px rgba(0,0,0,0.14)',
                      }} />
                    ))}
                  </div>
                  <span style={{ fontSize:11, color:'#6B6B70', fontFamily:'Inter,system-ui,sans-serif', fontWeight:600 }}>{ev.count}</span>
                </div>
              </div>

              {/* Round emblem — event image as ticket seal */}
              <img src={ev.img} alt="" style={{
                width:44, height:44, borderRadius:'50%', objectFit:'cover',
                alignSelf:'center', flexShrink:0,
                border:'2px solid rgba(255,255,255,0.9)',
                boxShadow:'0 1px 2px rgba(0,0,0,0.12), 0 4px 10px rgba(0,0,0,0.1), inset 0 1px 0 rgba(255,255,255,0.4)',
              }} />
            </div>
          </div>
          </div>
          );
        })}
      </div>

      <button style={{
        width:'100%', padding:'16px 0', borderRadius:18,
        border:'1px solid rgba(255,255,255,0.8)',
        background:'linear-gradient(145deg, #F8F8F8 0%, #EFEFEF 100%)',
        color:'#8E8E93', fontSize:14, fontWeight:600, cursor:'pointer',
        fontFamily:'Inter,system-ui,sans-serif',
        display:'flex', alignItems:'center', justifyContent:'center', gap:6,
        boxShadow:'0 2px 4px rgba(0,0,0,0.04), 0 8px 16px rgba(0,0,0,0.06), inset 0 1px 0 rgba(255,255,255,0.9)',
      }}>
        <Ico.Plus size={16} /> Nieuw event
      </button>

      <EventDetail event={activeEvent} isOpen={!!activeEvent} onClose={()=>setActiveEvent(null)} />
    </div>
  );
};

// ─── Personal Page (header shell stays) ────────────────────────────────────
const PersonalPage = () => {
  const [tab, setTab] = React.useState('Taken');
  return (
    <div>
      <div style={{ padding:'0 16px 16px', background:'#F2F2F7' }}>
        <TabSlider tabs={[
          { id:'Taken',      label:'Taken',      Icon: Ico.CheckSq },
          { id:'Practicals', label:'Practicals', Icon: Ico.Bulb    },
          { id:'Events',     label:'Events',     Icon: Ico.Cal     },
        ]} active={tab} onChange={setTab} style={{ fontFamily:'Inter,system-ui,sans-serif' }} />
      </div>
      <div style={{ padding:'4px 16px 120px' }}>
        {tab==='Taken'      && <TakenTab />}
        {tab==='Practicals' && <PracticalsTab />}
        {tab==='Events'     && <EventsTab />}
      </div>
    </div>
  );
};

Object.assign(window, { PersonalPage, TakenTab, PracticalsTab, EventsTab, StatusFolderCard });
