<!doctype html>
<html lang="nl">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover" />
<title>PadelLeraar · KNLTB Reminder</title>
<style>
:root{--bg:#f5f7fb;--card:#fff;--ink:#14213d;--muted:#667085;--line:#dfe5ee;--blue:#0b6cff;--cyan:#00bcd4;--green:#0c9b68;--orange:#f59e0b;--red:#d92d20;--shadow:0 8px 24px rgba(16,24,40,.08)}
*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;font-family:Inter,system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;background:var(--bg);color:var(--ink)}
button,input,textarea,select{font:inherit}.app{max-width:1180px;margin:auto;min-height:100vh}.top{position:sticky;top:0;z-index:20;background:rgba(255,255,255,.96);backdrop-filter:blur(10px);border-bottom:1px solid var(--line);padding:12px 16px}.brand{display:flex;align-items:center;gap:12px}.logo{width:42px;height:42px;border-radius:14px;background:linear-gradient(135deg,var(--cyan),var(--blue));display:grid;place-items:center;color:white;font-size:22px;box-shadow:var(--shadow)}h1{font-size:19px;margin:0}.sub{font-size:12px;color:var(--muted)}
.search{display:flex;gap:8px;margin-top:10px}.search input{width:100%;padding:11px 13px;border:1px solid var(--line);border-radius:12px;background:#fff}.pill{border:1px solid var(--line);background:#fff;border-radius:999px;padding:9px 12px;cursor:pointer}.pill.active{background:var(--ink);color:#fff;border-color:var(--ink)}
.nav{display:flex;gap:7px;overflow:auto;padding:10px 16px 0}.nav button{white-space:nowrap;border:0;background:#e9eef6;border-radius:999px;padding:9px 12px;color:#344054;cursor:pointer}.nav button.active{background:var(--blue);color:#fff}.main{padding:16px}.view{display:none}.view.active{display:block}.grid{display:grid;grid-template-columns:repeat(12,1fr);gap:14px}.card{background:var(--card);border:1px solid var(--line);border-radius:18px;padding:16px;box-shadow:var(--shadow)}.span12{grid-column:span 12}.span8{grid-column:span 8}.span6{grid-column:span 6}.span4{grid-column:span 4}.span3{grid-column:span 3}
.kpi{font-size:28px;font-weight:800}.muted{color:var(--muted)}.small{font-size:13px}.title{font-size:16px;font-weight:800;margin:0 0 8px}.flow{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.step{padding:9px 11px;background:#eef4ff;border:1px solid #cfe0ff;border-radius:12px;font-weight:700}.arrow{color:var(--muted)}
ul{padding-left:20px;margin:8px 0}.two{columns:2;column-gap:28px}.badge{display:inline-block;padding:4px 8px;border-radius:999px;font-size:12px;font-weight:700;background:#eef4ff;color:#175cd3}.ok{background:#ecfdf3;color:#067647}.warn{background:#fffaeb;color:#b54708}.danger{background:#fef3f2;color:#b42318}
.assignment{margin-bottom:12px}.assignment summary{cursor:pointer;list-style:none;font-weight:800;padding:12px 0;display:flex;justify-content:space-between;gap:10px}.assignment summary::-webkit-details-marker{display:none}.assignment[open] summary{border-bottom:1px solid var(--line);margin-bottom:12px}.checkrow{display:flex;gap:10px;align-items:flex-start;padding:7px 0}.checkrow input{margin-top:4px}.note{width:100%;min-height:88px;border:1px solid var(--line);border-radius:12px;padding:10px;resize:vertical;background:#fbfcfe}.btn{border:0;background:var(--blue);color:white;border-radius:12px;padding:10px 13px;font-weight:700;cursor:pointer}.btn.secondary{background:#eef4ff;color:#175cd3}.btn.green{background:var(--green)}.btn.ghost{background:#fff;color:var(--ink);border:1px solid var(--line)}
.flash{min-height:190px;display:flex;flex-direction:column;justify-content:space-between}.flashq{font-size:22px;font-weight:800}.answer{display:none;padding:12px;background:#f8fafc;border-radius:12px;border:1px solid var(--line);margin-top:12px}.answer.show{display:block}.examline{display:grid;grid-template-columns:1.3fr 1fr 1fr;gap:8px;align-items:center;padding:8px 0;border-bottom:1px solid #eef2f6}.traffic button{width:32px;height:32px;border-radius:50%;border:2px solid #fff;box-shadow:0 0 0 1px var(--line);cursor:pointer;margin-right:5px}.t-red{background:#f97066}.t-orange{background:#fdb022}.t-green{background:#32d583}.traffic button.selected{outline:3px solid #344054}.lesson-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}.field label{display:block;font-size:12px;font-weight:700;color:#475467;margin-bottom:5px}.field input,.field select,.field textarea{width:100%;border:1px solid var(--line);border-radius:10px;padding:10px;background:#fff}.lesson-output{white-space:pre-wrap;background:#101828;color:#f2f4f7;padding:14px;border-radius:14px;min-height:200px}.footer{padding:24px 16px 40px;text-align:center;color:var(--muted);font-size:12px}
@media(max-width:800px){.span8,.span6,.span4,.span3{grid-column:span 12}.two{columns:1}.examline{grid-template-columns:1fr}.lesson-grid{grid-template-columns:1fr}.top{padding-top:max(12px,env(safe-area-inset-top))}}
@media print{.top,.nav,.no-print{display:none!important}.view{display:block!important}.card{box-shadow:none;break-inside:avoid}.main{padding:0}}
/* MES v2 additions */
.statusbar{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}.statusdot{padding:6px 9px;border-radius:999px;background:#f2f4f7;font-size:12px}.toolbar{display:flex;gap:8px;flex-wrap:wrap;margin:10px 0}.modal{position:fixed;inset:0;background:rgba(16,24,40,.55);display:none;place-items:center;z-index:100;padding:18px}.modal.show{display:grid}.modalbox{background:#fff;width:min(620px,100%);max-height:90vh;overflow:auto;border-radius:20px;padding:18px;box-shadow:var(--shadow)}.modalhead{display:flex;justify-content:space-between;gap:12px;align-items:center}.tabs2{display:flex;gap:7px;flex-wrap:wrap;margin:12px 0}.tabs2 button{border:1px solid var(--line);background:#fff;border-radius:999px;padding:8px 11px}.tabs2 button.active{background:var(--ink);color:#fff}.loginpane{display:none}.loginpane.active{display:block}.linkbtn{color:var(--blue);text-decoration:none;font-weight:700}.syncok{background:#ecfdf3;color:#067647}.syncoff{background:#f2f4f7;color:#475467}.syncerr{background:#fef3f2;color:#b42318}.exportgrid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}@media(max-width:700px){.exportgrid{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="app">
<header class="top">
<div class="brand"><div class="logo">🎾</div><div><h1>PadelLeraar · KNLTB Reminder</h1><div class="sub">van waarnemen naar lesgeven · mobiel, snel, praktisch</div></div></div>
<div class="search"><input id="search" placeholder="Zoek: GRAS, achterspel, lob, SMART, differentiatie…"><button class="pill" id="clearSearch">Wis</button></div>
<div class="statusbar no-print"><a class="linkbtn" href="https://sites.google.com/view/padelstudie/reminder" target="_blank">PadelStudie · Reminder ↗</a><span class="statusdot syncoff" id="syncStatus">Lokaal</span><span class="statusdot" id="userStatus">Gast</span><button class="pill" id="loginOpen">Login</button><button class="pill" id="settingsOpen">Settings</button><button class="pill" id="exportOpen">Import / Export</button></div>
</header>
<nav class="nav" id="nav"></nav>
<main class="main">
<section class="view active" data-view="home">
<div class="grid">
<div class="card span8"><div class="title">De rode draad van de opleiding</div><div class="flow"><span class="step">Waarnemen</span><span class="arrow">→</span><span class="step">Beslissen</span><span class="arrow">→</span><span class="step">Uitvoeren</span><span class="arrow">→</span><span class="step">Terugkoppelen</span></div><p class="small muted">Kijk breed: spelsituatie, aankomende bal, positie, bedoeling, technische mogelijkheid, timing/balans/bladcontrole, resultaat en volgende keuze.</p></div>
<div class="card span4"><div class="title">Vandaag onthouden</div><div class="kpi" id="todayFocus">1 aanwijzing</div><div class="small muted">Kort en bondig. Praatje → plaatje → daadje. Observeer daarna opnieuw.</div></div>
<div class="card span4"><div class="title">5 hoofdspelsituaties</div><ol><li>Service</li><li>Return</li><li>Achterspel</li><li>Transitie</li><li>Netspel</li></ol></div>
<div class="card span4"><div class="title">5 bedoelingen</div><ol><li>Scoren</li><li>Uitlokken</li><li>Opbouwen</li><li>Neutraliseren</li><li>Voorkomen</li></ol></div>
<div class="card span4"><div class="title">GRAS</div><ul><li><b>G</b>rip</li><li><b>R</b>aakpunt</li><li><b>A</b>rmactie</li><li><b>S</b>tand / lichaam</li></ul></div>
<div class="card span12"><div class="title">Les-check vóór de eerste bal</div><div class="two"><div>☐ Veiligheid en ruimte klopt</div><div>☐ Doel is concreet en passend</div><div>☐ Spelers begrijpen bedoeling</div><div>☐ Organisatie houdt iedereen actief</div><div>☐ Aanspelen is dienstbaar aan doel</div><div>☐ Eén primaire coachingaanwijzing</div><div>☐ Stap terug / stap verder voorbereid</div><div>☐ Transfer naar spelrealistische B-vorm</div><div>☐ Evaluatievraag voorbereid</div><div>☐ Positie leraar geeft overzicht</div></div></div>
</div>
</section>
<section class="view" data-view="model">
<div class="grid">
<div class="card span12"><div class="title">Padelhandeling</div><div class="flow"><span class="step">👀 Waarnemen</span><span class="arrow">→</span><span class="step">🧠 Beslissen</span><span class="arrow">→</span><span class="step">🎾 Uitvoeren</span><span class="arrow">→</span><span class="step">🔁 Terugkoppelen</span></div></div>
<div class="card span3"><div class="title">Waarnemen</div><ul><li>tegenstander</li><li>AKB</li><li>eigen positie</li><li>partner</li><li>ruimte/omstandigheden</li></ul></div>
<div class="card span3"><div class="title">Beslissen</div><ul><li>bedoeling</li><li>tactische kennis</li><li>technische mogelijkheden</li><li>score</li><li>emotie / druk</li></ul></div>
<div class="card span3"><div class="title">Uitvoeren</div><ul><li>beweging</li><li>timing</li><li>balans</li><li>bladcontrole</li><li>GRAS</li></ul></div>
<div class="card span3"><div class="title">Terugkoppelen</div><ul><li>resultaat</li><li>rendement</li><li>gevoel</li><li>analyse</li><li>volgende keuze</li></ul></div>
<div class="card span6"><div class="title">Timingfactoren · reminder</div><ul><li>oog-hand / oog-voet coördinatie</li><li>snelheid AKB</li><li>richting AKB</li><li>snelheid lichaam</li><li>plaats balbehandeling VTB</li><li>zwaaisnelheid racket</li><li>speelrichting VTB</li><li>rotatie AKB / VTB</li></ul></div>
<div class="card span6"><div class="title">Differentiëren</div><p>Maak makkelijker/moeilijker met:</p><div class="flow"><span class="badge">Tempo</span><span class="badge">Tijd</span><span class="badge">Ruimte</span><span class="badge">Voorspelbaarheid</span><span class="badge">Druk</span></div><p class="small muted">Richtwaarde uit de opleiding: rond 70% succes geeft leren én uitdaging. Onder ±40%: stap terug. Boven ±80%: stap verder.</p></div>
</div>
</section>
<section class="view" data-view="situations"><div class="grid" id="situationsGrid"></div></section>
<section class="view" data-view="assignments"><div class="grid"><div class="card span12"><div class="title">Opleidingsopdrachten · checklist + eigen notities</div><div id="assignmentsList"></div></div></div></section>
<section class="view" data-view="lesson">
<div class="grid"><div class="card span12"><div class="title">Snelle lesbouwer · reminder</div><div class="lesson-grid">
<div class="field"><label>Spelsituatie</label><select id="lsSituation"><option>Service</option><option>Return</option><option>Achterspel</option><option>Transitie</option><option>Netspel</option></select></div>
<div class="field"><label>Bedoeling</label><select id="lsIntent"><option>Scoren</option><option>Uitlokken</option><option selected>Opbouwen</option><option>Neutraliseren</option><option>Voorkomen</option></select></div>
<div class="field"><label>Slag / thema</label><input id="lsStroke" value="Forehand lob"></div>
<div class="field"><label>Niveau</label><input id="lsLevel" value="9–6"></div>
<div class="field"><label>SMART leerdoel</label><input id="lsGoal" value="7 van 10 ballen functioneel uitvoeren"></div>
<div class="field"><label>Primaire aanwijzing</label><input id="lsCue" value="Raakpunt vóór en ruimte maken"></div>
<div class="field"><label>Stap terug</label><input id="lsEasy" value="langzamere voorspelbare AKB, groter doelvak"></div>
<div class="field"><label>Stap verder</label><input id="lsHard" value="meer variatie in AKB, kleiner doelvak, tijdsdruk"></div>
</div><div style="display:flex;gap:8px;margin-top:12px"><button class="btn" id="buildLesson">Bouw reminder</button><button class="btn ghost" onclick="window.print()">Print</button></div></div>
<div class="card span12"><div class="lesson-output" id="lessonOutput">Kies je thema en klik op “Bouw reminder”.</div></div></div>
</section>
<section class="view" data-view="exam"><div class="grid">
<div class="card span8"><div class="title">Proefexamen / examenfocus</div><p class="small muted">Gebruik verkeerslichten voor je eigen voorbereiding. Data wordt lokaal op dit apparaat opgeslagen.</p><div id="examList"></div></div>
<div class="card span4"><div class="title">Lesindeling 40 min</div><ul><li>5 min warming-up</li><li>15 min Kern A</li><li>15 min Kern B incl. evaluatie</li><li>5 min afronding / wissel</li></ul><hr style="border:0;border-top:1px solid var(--line)"><div class="title">Examinator kijkt o.a. naar</div><ul><li>veiligheid</li><li>kort & bondig instrueren</li><li>aanspelen in dienst van doel</li><li>optimale leraarpositie</li><li>analyse & feedback</li><li>techniek ↔ tactiek</li><li>positionering</li><li>AKB / VTB</li></ul></div>
</div></section>
<section class="view" data-view="quiz"><div class="grid"><div class="card span8"><div class="flash"><div><span class="badge">Flashcard</span><div class="flashq" id="flashQ"></div><div class="answer" id="flashA"></div></div><div class="no-print" style="display:flex;gap:8px"><button class="btn secondary" id="showAnswer">Toon antwoord</button><button class="btn" id="nextFlash">Volgende</button></div></div></div><div class="card span4"><div class="title">Toetsstatus</div><p>Toets 1 <span class="badge ok">7,40</span></p><p>Toets 2 <span class="badge ok">7,0</span></p><p class="small muted">Gebruik de flashcards als herhaling van begrippen en leskeuzes, niet als vervanging van het officiële cursusmateriaal.</p></div></div></section>
<section class="view" data-view="profile"><div class="grid">
<div class="card span6"><div class="title">Praktijk & ontwikkeling</div><ul><li>Stage: groepslessen, privélessen, clinics</li><li>Focus: structureren, differentiëren, observeren, coachen</li><li>Reminder: rust en eenvoud zijn vaak effectiever dan veel informatie tegelijk</li></ul></div>
<div class="card span6"><div class="title">EH / veiligheid</div><p><span class="badge ok">Certificaat aanwezig</span></p><ul><li>reanimatie</li><li>verstikking</li><li>bloeding stoppen</li><li>niet-spoedeisende eerste hulp</li></ul><p class="small muted">Afgifte 11-04-2026; in het aangeleverde certificaat staat geldig tot 1 jaar na afgifte.</p></div>
<div class="card span12"><div class="title">Persoonlijke notitie</div><textarea class="note" id="profileNote" placeholder="Wat wil ik bij mijn volgende les bewust beter doen?"></textarea></div>
</div></section>
</main>
<div class="footer">PadelLeraar Reminder v2 · Site + Sheet + Script · <a href="https://sites.google.com/view/padelstudie" target="_blank">PadelStudie</a> · persoonlijke data blijft lokaal beschikbaar en kan na login met de Sheet synchroniseren.</div>
<div class="modal" id="loginModal"><div class="modalbox"><div class="modalhead"><div><div class="title">Login & account</div><div class="small muted">E-mailcode → wachtwoord instellen → sessie</div></div><button class="pill" data-close="loginModal">Sluit</button></div><div class="tabs2"><button class="active" data-login-tab="code">Code via mail</button><button data-login-tab="password">Wachtwoord</button><button data-login-tab="account">Account maken</button></div><div class="loginpane active" data-login-pane="code"><div class="field"><label>E-mail</label><input id="authEmail" type="email" placeholder="naam@example.nl"></div><div class="toolbar"><button class="btn" id="requestCode">Stuur code</button></div><div class="field"><label>6-cijferige code</label><input id="authCode" inputmode="numeric" maxlength="6" placeholder="123456"></div><div class="toolbar"><button class="btn green" id="verifyCode">Controleer & login</button></div></div><div class="loginpane" data-login-pane="password"><div class="field"><label>E-mail</label><input id="pwEmail" type="email"></div><div class="field"><label>Wachtwoord</label><input id="pwPassword" type="password"></div><div class="toolbar"><button class="btn" id="passwordLogin">Login</button></div></div><div class="loginpane" data-login-pane="account"><div class="field"><label>Naam</label><input id="newName"></div><div class="field"><label>E-mail</label><input id="newEmail" type="email"></div><div class="field"><label>Nieuw wachtwoord (min. 10 tekens)</label><input id="newPassword" type="password"></div><div class="toolbar"><button class="btn" id="createAccount">Wachtwoord instellen</button></div><p class="small muted">Log eerst één keer in met de e-mailcode. Daarna kun je hier zonder hergebruik van die code een wachtwoord instellen.</p></div><div id="authMessage" class="small muted"></div><div class="toolbar"><button class="btn ghost" id="logoutBtn">Uitloggen</button></div></div></div>
<div class="modal" id="settingsModal"><div class="modalbox"><div class="modalhead"><div class="title">Persoonlijke settings</div><button class="pill" data-close="settingsModal">Sluit</button></div><div class="lesson-grid"><div class="field"><label>Naam</label><input id="setName"></div><div class="field"><label>Telefoon</label><input id="setPhone"></div><div class="field"><label>Eigen site/link</label><input id="setSite"></div><div class="field"><label>Eigen quote</label><input id="setQuote"></div><div class="field"><label>Lettergrootte</label><input id="setFont" type="number" min="14" max="28" value="18"></div><div class="field"><label>Accent</label><select id="setAccent"><option value="#0b6cff">Blauw</option><option value="#0c9b68">Groen</option><option value="#7f56d9">Paars</option><option value="#f79009">Oranje</option></select></div></div><div class="toolbar"><button class="btn" id="saveSettings">Opslaan</button></div></div></div>
<div class="modal" id="exportModal"><div class="modalbox"><div class="modalhead"><div><div class="title">Import · Export · Backup</div><div class="small muted">Checklist, notities, lessen, examenstatus, profiel en settings.</div></div><button class="pill" data-close="exportModal">Sluit</button></div><div class="exportgrid"><button class="btn" id="exportJson">Backup JSON</button><button class="btn secondary" id="exportTxt">Export TXT</button><button class="btn secondary" id="exportCsv">Export CSV</button><button class="btn green" id="exportWhatsapp">WhatsApp</button></div><hr style="border:0;border-top:1px solid var(--line);margin:16px 0"><div class="field"><label>Import backup JSON</label><input id="importFile" type="file" accept="application/json,.json"></div><div class="toolbar"><button class="btn" id="importJson">Importeer JSON</button><button class="btn ghost" id="syncNow">Sync met Sheet</button></div><div id="ioMessage" class="small muted"></div></div></div>
</div>
<script>
const tabs=[['home','Start'],['model','Kernmodel'],['situations','5 situaties'],['assignments','Opdrachten'],['lesson','Lesbouwer'],['exam','Examen'],['quiz','Quiz'],['profile','Profiel']];
const nav=document.getElementById('nav');tabs.forEach(([id,label],i)=>{const b=document.createElement('button');b.textContent=label;b.dataset.target=id;if(!i)b.classList.add('active');b.onclick=()=>show(id);nav.appendChild(b)});
function show(id){document.querySelectorAll('.view').forEach(v=>v.classList.toggle('active',v.dataset.view===id));document.querySelectorAll('.nav button').forEach(b=>b.classList.toggle('active',b.dataset.target===id));window.scrollTo({top:0,behavior:'smooth'})}
const situations=[
['Service','Punt starten en na service door naar een goede netpositie.','Voorbereiden → gecontroleerd serveren → samen naar voren.','Let op: tijd nemen, raakpunt, richting, eerste volley.'],
['Return','Service neutraliseren en ruimte creëren voor de volgende actie.','Lees service → stabiele return → positie herstellen / transitie kiezen.','Vaak eerst controle boven risico.'],
['Achterspel','Comfortabel blijven in rally en mogelijkheden creëren om initiatief te nemen.','Uitgangspositie bij glasnaden, open houding, herstel vóór raakpunt tegenstander.','Keuzes: zacht/dalend, lob, hoog BH, body.'],
['Transitie','Netpositie verkrijgen of behouden op het juiste moment.','Goede lob/chiquita herkennen → samen bewegen → geen niemandsland.','Timing en communicatie bepalen succes.'],
['Netspel','Tegenstander bewegen en kansen creëren.','Positie rond tweede paal, compact volleren/overhead, herstellen.','Variëren in kort/lang, links/rechts, laag raakpunt, vaart.']];
const sg=document.getElementById('situationsGrid');situations.forEach(s=>{sg.insertAdjacentHTML('beforeend',`<div class="card span6 searchable"><div class="title">${s[0]}</div><p><b>Doel:</b> ${s[1]}</p><p><b>Proces:</b> ${s[2]}</p><p class="small muted">${s[3]}</p></div>`)});
const assignments=[
['01 Achterspel',['Padelhandeling beschrijven','Uitgangspositie en herstel observeren','Tactische keuzes koppelen aan AKB','Verslag: spelconcept + afsluiting']],
['02 Netspel',['Positionering rond tweede paal','Reiken/blokken en foutloos blijven','Plaatsing kort/lang en links/rechts','Overzicht, controle en herstel observeren']],
['03 Transities',['Service → netpositie','Netpositie behouden bij lob','Na goede lob naar voren','Na goede chiquita naar voren','2 tegen 2 teamposities']],
['04 Voorbeeldvaardigheid',['Slagen demonstreren','GRAS per slag benoemen','Eigen uitvoering reflecteren','Praatje → plaatje → daadje']],
['05 SMART-doelen',['2 tactische + 2 technische doelen','Specifiek / Meetbaar / Acceptabel / Realistisch / Tijdgebonden','Passend bij niveau en spelsituatie','Oefening makkelijker/moeilijker maken']],
['06 Motieven & beginsituatie',['Gesprek met speler','Techniek / tactiek / fysiek / mentaal observeren','Slagen/situaties testen','Beginsituatie vastleggen']],
['07 Methodegroepen',['Methodisch van eenvoudig naar complex','Methodegroep kiezen per slag','A1/A2 naar B verbinden','Differentiëren']],
['08 Biomechanica',['Keten benen → romp → arm → racket','Richting / spin / vaart analyseren','Video achter- en zijaanzicht','Schakels accentueren / afremmen']],
['09 Timing & methodische opbouw',['8 timingsfactoren herkennen','Breekpunt zoeken','Vastheid / precisie / variatie / vaart','Hulpmiddel doelgericht inzetten']],
['10 Methodische hulpmiddelen',['Pionnen / doelen / zones','Touw / bankje / dwingende situatie','GRAS + output analyseren','Veilig én doelgericht organiseren']],
['11 Analyseren & corrigeren',['Observeren in spelrealistische vorm','Eén hoofdprobleem kiezen','Korte concrete aanwijzing','Oefenvorm aanpassen als correctie niet landt']],
['12 Differentiëren',['Tempo / tijd / ruimte / voorspelbaarheid / druk','<40% stap terug','40–80% door-oefenen','>80% stap verder']],
['13 Meerwekenplan & LVF',['16 weken groep','8 weken privé','SMART & motieven koppelen','Materiaal / organisatie / lesmanagement']],
['14 Aangeefvaardigheid',['Minimaal 70% passend aanspelen','Vaart / rotatie doseren','Richting / frequentie aanpassen','Wanden en tweede balstuit beheersen']],
['15 TOF Padel',['Matrix + level kiezen','Praatje / plaatje / daadje','1 oefening + 1 variatie','Uitleg → uitvoeren → evalueren → opruimen']],
['16 Beroepshouding',['Reëel zelfbeeld en professionele uitstraling','Bemoedigend, luisteren, waarderen','Proactief, op tijd, huiswerk','Fair Play / gedragscode']],
['Materiaal',['Rackets vergelijken: gewicht/balans/hardheid/grip','Advies beginner / gevorderd / wedstrijdspeler','Verschillende ballen ervaren','Relatie met niveau, blessures en speltype']],
['Fysiek',['Kracht','Snelheid','Uithoudingsvermogen','Lenigheid','Coördinatie']],
['Proefexamen',['5 min warming-up','15 min Kern A','15 min Kern B + evaluatie','5 min afronding / voorbereiding volgende kandidaat']]
];
const al=document.getElementById('assignmentsList');assignments.forEach((a,idx)=>{const key='ass_'+idx;const saved=JSON.parse(localStorage.getItem(key)||'{}');const checks=a[1].map((x,i)=>`<label class="checkrow"><input type="checkbox" data-k="${key}" data-i="${i}" ${saved[i]?'checked':''}><span>${x}</span></label>`).join('');al.insertAdjacentHTML('beforeend',`<details class="assignment searchable"><summary><span>${a[0]}</span><span class="badge">${a[1].length} reminders</span></summary>${checks}<textarea class="note" data-note="note_${idx}" placeholder="Eigen notities bij ${a[0]}…">${localStorage.getItem('note_'+idx)||''}</textarea></details>`)});
al.addEventListener('change',e=>{if(e.target.matches('input[type=checkbox]')){const k=e.target.dataset.k,i=e.target.dataset.i;const o=JSON.parse(localStorage.getItem(k)||'{}');o[i]=e.target.checked;localStorage.setItem(k,JSON.stringify(o))}});al.addEventListener('input',e=>{if(e.target.dataset.note)localStorage.setItem(e.target.dataset.note,e.target.value)});
const examItems=['Veiligheid fysiek & sociaal','Vier lesonderdelen logisch op elkaar afstemmen','Instructies kort en bondig','Aanspelen in dienst van lesdoel','Optimale leraarpositie','Slagen analyseren (bio)mechanisch','Tactische waarde gespeelde bal beoordelen','Feedback vanuit analyse geven','Positionering beoordelen','AKB en VTB tactisch beoordelen','Technische mogelijkheid ↔ tactische keuze','Spelers actief en betrokken houden'];
const ex=document.getElementById('examList');examItems.forEach((x,i)=>{const val=localStorage.getItem('exam_'+i)||'';ex.insertAdjacentHTML('beforeend',`<div class="examline searchable"><div>${x}</div><div class="traffic" data-exam="${i}"><button class="t-red ${val==='r'?'selected':''}" data-v="r" title="Nog oefenen"></button><button class="t-orange ${val==='o'?'selected':''}" data-v="o" title="Bijna"></button><button class="t-green ${val==='g'?'selected':''}" data-v="g" title="Goed"></button></div><div><input style="width:100%;border:1px solid var(--line);border-radius:9px;padding:8px" data-exnote="${i}" value="${localStorage.getItem('exnote_'+i)||''}" placeholder="notitie"></div></div>`)});
ex.addEventListener('click',e=>{if(e.target.matches('.traffic button')){const p=e.target.parentElement;p.querySelectorAll('button').forEach(b=>b.classList.remove('selected'));e.target.classList.add('selected');localStorage.setItem('exam_'+p.dataset.exam,e.target.dataset.v)}});ex.addEventListener('input',e=>{if(e.target.dataset.exnote!==undefined)localStorage.setItem('exnote_'+e.target.dataset.exnote,e.target.value)});
const flashes=[
['Wat zijn de 4 stappen van de padelhandeling?','Waarnemen → beslissen → uitvoeren → terugkoppelen.'],
['Wat zijn de 5 hoofdspelsituaties?','Service, return, achterspel, transitie en netspel.'],
['Wat zijn de 5 bedoelingen?','Scoren, uitlokken, opbouwen, neutraliseren en voorkomen.'],
['Waar staat GRAS voor?','Grip, raakpunt, armactie en stand van het lichaam.'],
['Welke 5 knoppen kun je gebruiken om te differentiëren?','Tempo, tijd, ruimte, voorspelbaarheid en druk.'],
['Wat is de kern van spelrealistisch opleiden?','Techniek en tactiek koppelen aan echte keuzes, posities, balbanen en vervolgacties in het spel.'],
['Wat doe je als een oefening minder dan ongeveer 40% lukt?','Maak de opdracht makkelijker: een stap terug.'],
['Wat doe je als een oefening meer dan ongeveer 80% lukt?','Maak de opdracht moeilijker: een stap verder.'],
['Wat is het doel van aangeefvaardigheid?','De bal zó aanspelen dat de leerling het lesdoel optimaal kan oefenen.'],
['Wat is een sterke coachregel tijdens correctie?','Kies één primair verbeterpunt en geef een korte, concrete aanwijzing.']
];let fi=0;function renderFlash(){flashQ.textContent=flashes[fi][0];flashA.textContent=flashes[fi][1];flashA.classList.remove('show')}renderFlash();showAnswer.onclick=()=>flashA.classList.toggle('show');nextFlash.onclick=()=>{fi=(fi+1)%flashes.length;renderFlash()};
buildLesson.onclick=()=>{lessonOutput.textContent=`LESREMINDER\n\nSpelsituatie: ${lsSituation.value}\nBedoeling: ${lsIntent.value}\nSlag/thema: ${lsStroke.value}\nNiveau: ${lsLevel.value}\nSMART: ${lsGoal.value}\n\nA1 · techniek\nPraatje → plaatje → daadje. Leg maximaal 1 primaire aanwijzing uit: ${lsCue.value}. Gebruik GRAS en laat veel herhalen.\n\nA2 · waarnemen + kiezen\nVoeg een herkenbare AKB / keuze toe. Vraag: “Wat zag je vóórdat je koos?” Laat speler positie herstellen.\n\nB · spelrealistische transfer\n2 tegen 2 of rallyvorm. Laat ${lsIntent.value.toLowerCase()} functioneel terugkomen in de spelsituatie ${lsSituation.value.toLowerCase()}.\n\nDIFFERENTIATIE\nStap terug: ${lsEasy.value}.\nStap verder: ${lsHard.value}.\n\nCOACHCYCLUS\nObserveer → diagnose → 1 aanwijzing → opnieuw uitvoeren → resultaat terugkoppelen.\n\nEVALUATIE\n1. Wat zag je?\n2. Welke keuze maakte je?\n3. Wat deed de bal?\n4. Wat doe je de volgende keer?`};
const search=document.getElementById('search');search.addEventListener('input',()=>{const q=search.value.toLowerCase().trim();document.querySelectorAll('.searchable').forEach(el=>el.style.display=!q||el.innerText.toLowerCase().includes(q)?'':'none')});clearSearch.onclick=()=>{search.value='';search.dispatchEvent(new Event('input'))};
const pn=document.getElementById('profileNote');pn.value=localStorage.getItem('profileNote')||'';pn.oninput=()=>localStorage.setItem('profileNote',pn.value);
// ===== MES v2: auth, settings, import/export, optional Apps Script sync =====
const MES_KEY='padelleraar_mes_v2';
const mesDefault={profile:{name:'',email:'',phone:'',site:'https://sites.google.com/view/padelstudie',quote:''},settings:{fontSize:18,accent:'#0b6cff'},session:null,lastSync:null};
function mesLoad(){try{return Object.assign({},mesDefault,JSON.parse(localStorage.getItem(MES_KEY)||'{}'))}catch(e){return structuredClone(mesDefault)}}
let MES=mesLoad();
function mesSave(){localStorage.setItem(MES_KEY,JSON.stringify(MES));applySettings();updateUserUI()}
function hasGas(){return typeof google!=='undefined'&&google.script&&google.script.run}
function gas(fn,args){return new Promise((resolve,reject)=>{if(!hasGas())return reject(new Error('Apps Script backend niet actief'));let r=google.script.run.withSuccessHandler(resolve).withFailureHandler(e=>reject(new Error(e&&e.message?e.message:String(e))));r[fn](args)})}
function setSync(t,cls='syncoff'){const e=document.getElementById('syncStatus');e.textContent=t;e.className='statusdot '+cls}
function updateUserUI(){const u=document.getElementById('userStatus');u.textContent=MES.session?.email||MES.profile?.name||'Gast';setSync(hasGas()?(MES.lastSync?'Gesynchroniseerd':'Backend actief'):'Lokaal',hasGas()?'syncok':'syncoff')}
function applySettings(){document.documentElement.style.fontSize=(MES.settings?.fontSize||18)+'px';document.documentElement.style.setProperty('--blue',MES.settings?.accent||'#0b6cff')}
function openModal(id){document.getElementById(id).classList.add('show')}
document.querySelectorAll('[data-close]').forEach(b=>b.onclick=()=>document.getElementById(b.dataset.close).classList.remove('show'));
document.getElementById('loginOpen').onclick=()=>openModal('loginModal');document.getElementById('settingsOpen').onclick=()=>{fillSettings();openModal('settingsModal')};document.getElementById('exportOpen').onclick=()=>openModal('exportModal');
document.querySelectorAll('[data-login-tab]').forEach(b=>b.onclick=()=>{document.querySelectorAll('[data-login-tab]').forEach(x=>x.classList.toggle('active',x===b));document.querySelectorAll('[data-login-pane]').forEach(x=>x.classList.toggle('active',x.dataset.loginPane===b.dataset.loginTab))});
function authMsg(t){document.getElementById('authMessage').textContent=t}
document.getElementById('requestCode').onclick=async()=>{const email=document.getElementById('authEmail').value.trim();if(!email)return authMsg('Vul je e-mail in.');try{const r=await gas('plRequestLoginCode',{email});authMsg(r.message||'Code verzonden.')}catch(e){authMsg('Backend niet actief. Open de gedeployde Apps Script webapp om mailcodes te gebruiken.')}};
document.getElementById('verifyCode').onclick=async()=>{const btn=document.getElementById('verifyCode');btn.disabled=true;try{const email=document.getElementById('authEmail').value.trim();const code=document.getElementById('authCode').value.trim();if(!email||!code)return authMsg('Vul e-mail en 6-cijferige code in.');const r=await gas('plVerifyLoginCode',{email,code});MES.session=r.session;MES.profile=Object.assign(MES.profile,r.profile||{});MES.profile.email=email;mesSave();document.getElementById('authCode').value='';document.getElementById('newEmail').value=email;authMsg('Ingelogd. Je sessie is actief. Je kunt nu eventueel een wachtwoord instellen.');setTimeout(()=>{document.querySelector('[data-login-tab="account"]').click()},350)}catch(e){authMsg(e.message)}finally{btn.disabled=false}};
document.getElementById('passwordLogin').onclick=async()=>{try{const r=await gas('plPasswordLogin',{email:document.getElementById('pwEmail').value.trim(),password:document.getElementById('pwPassword').value});MES.session=r.session;MES.profile=Object.assign(MES.profile,r.profile||{});mesSave();authMsg('Ingelogd.')}catch(e){authMsg(e.message)}};
document.getElementById('createAccount').onclick=async()=>{try{if(!MES.session?.token)throw new Error('Log eerst in met de e-mailcode.');const password=document.getElementById('newPassword').value;const name=document.getElementById('newName').value.trim();const r=await gas('plSetPassword',{token:MES.session.token,password});if(name){MES.profile.name=name;mesSave();try{await gas('plSaveSettings',{token:MES.session.token,profile:MES.profile,settings:MES.settings})}catch(_){}}document.getElementById('newPassword').value='';authMsg(r.message||'Wachtwoord ingesteld.')}catch(e){authMsg(e.message)}};
document.getElementById('logoutBtn').onclick=async()=>{try{if(MES.session)await gas('plLogout',{token:MES.session.token})}catch(e){}MES.session=null;mesSave();authMsg('Uitgelogd.')};
function fillSettings(){document.getElementById('setName').value=MES.profile?.name||'';document.getElementById('setPhone').value=MES.profile?.phone||'';document.getElementById('setSite').value=MES.profile?.site||'';document.getElementById('setQuote').value=MES.profile?.quote||'';document.getElementById('setFont').value=MES.settings?.fontSize||18;document.getElementById('setAccent').value=MES.settings?.accent||'#0b6cff'}
document.getElementById('saveSettings').onclick=async()=>{MES.profile=Object.assign(MES.profile,{name:setName.value.trim(),phone:setPhone.value.trim(),site:setSite.value.trim(),quote:setQuote.value.trim()});MES.settings=Object.assign(MES.settings,{fontSize:Number(setFont.value)||18,accent:setAccent.value});mesSave();try{if(MES.session)await gas('plSaveSettings',{token:MES.session.token,profile:MES.profile,settings:MES.settings})}catch(e){}document.getElementById('settingsModal').classList.remove('show')};
function collectBackup(){const all={version:'2.0.0',exportedAt:new Date().toISOString(),site:'https://sites.google.com/view/padelstudie/reminder',mes:MES,local:{}};for(let i=0;i<localStorage.length;i++){const k=localStorage.key(i);if(k&&k.startsWith('padel'))all.local[k]=localStorage.getItem(k)}return all}
function dl(name,text,type){const a=document.createElement('a');a.href=URL.createObjectURL(new Blob([text],{type}));a.download=name;a.click();setTimeout(()=>URL.revokeObjectURL(a.href),1000)}
function stamp(ext){return 'PadelLeraar_Reminder_'+new Date().toISOString().slice(0,10)+'.'+ext}
document.getElementById('exportJson').onclick=()=>dl(stamp('json'),JSON.stringify(collectBackup(),null,2),'application/json');
document.getElementById('exportTxt').onclick=()=>{const b=collectBackup();let t='PadelLeraar · KNLTB Reminder\n'+b.exportedAt+'\n\nProfiel\n'+JSON.stringify(MES.profile,null,2)+'\n\nLesreminder\n'+(document.getElementById('lessonOutput')?.innerText||'')+'\n\nNotitie\n'+(document.getElementById('profileNote')?.value||'');dl(stamp('txt'),t,'text/plain')};
document.getElementById('exportCsv').onclick=()=>{const rows=[['type','key','value'],['profile','name',MES.profile?.name||''],['profile','email',MES.session?.email||MES.profile?.email||''],['profile','phone',MES.profile?.phone||''],['profile','site',MES.profile?.site||''],['profile','quote',MES.profile?.quote||''],['settings','fontSize',MES.settings?.fontSize||18],['settings','accent',MES.settings?.accent||'']];const csv=rows.map(r=>r.map(v=>'"'+String(v).replaceAll('"','""')+'"').join(',')).join('\n');dl(stamp('csv'),csv,'text/csv')};
document.getElementById('exportWhatsapp').onclick=()=>{const txt=['🎾 PadelLeraar · KNLTB Reminder',MES.profile?.name||'',MES.profile?.quote||'',document.getElementById('lessonOutput')?.innerText||'',MES.profile?.site||'https://sites.google.com/view/padelstudie/reminder'].filter(Boolean).join('\n\n');window.open('https://wa.me/?text='+encodeURIComponent(txt),'_blank')};
document.getElementById('importJson').onclick=()=>{const f=document.getElementById('importFile').files[0];if(!f)return ioMessage.textContent='Kies eerst een JSON-backup.';const r=new FileReader();r.onload=()=>{try{const b=JSON.parse(r.result);if(b.local)Object.entries(b.local).forEach(([k,v])=>localStorage.setItem(k,v));if(b.mes){MES=b.mes;mesSave()}ioMessage.textContent='Backup geïmporteerd. Herlaad de pagina indien nodig.'}catch(e){ioMessage.textContent='Ongeldige JSON-backup.'}};r.readAsText(f)};
async function syncAll(){if(!MES.session)throw new Error('Log eerst in.');const payload=collectBackup();const r=await gas('plSyncBackup',{token:MES.session.token,payload});MES.lastSync=new Date().toISOString();mesSave();return r}
document.getElementById('syncNow').onclick=async()=>{ioMessage.textContent='Synchroniseren…';try{const r=await syncAll();ioMessage.textContent=r.message||'Gesynchroniseerd.'}catch(e){ioMessage.textContent=e.message}};
applySettings();updateUserUI();
</script>
</body></html>