// Kaart of abonnement kopen, en het scherm waar de koper na het betalen op terugkomt.
// Een bestand voor allebei, want het is een en dezelfde weg: kiezen, betalen, code krijgen.
// Welke helft je ziet hangt af van ?aankoop=<token> in het webadres.
//
// Wat hier NIET gebeurt: er wordt geen klant en geen kaart aangemaakt. Dat doet de database pas
// nadat de betaling bevestigd is. Zo kan niemand door het formulier af te breken rijen laten
// ontstaan, en houdt een half afgebroken poging niets bezet.

// De betaling loopt over dezelfde edge function als een reservering, met aankoop_token in plaats
// van boeking_id. Er is dus maar een betaalroute in het hele systeem.
async function startKaartBetaling(token){
  try{
    const r = await fetch(URL_+"/functions/v1/mollie-betaling",{method:"POST",
      headers:{"Content-Type":"application/json","Authorization":"Bearer "+KEY_},
      body:JSON.stringify({aankoop_token:token})});
    let d=null; try{ d=await r.json(); }catch(e){}
    if(!r.ok) return {status:"fout", reden:(d&&d.error)?String(d.error):("de betaaldienst gaf status "+r.status)};
    if(d && d.betaalUrl) return {status:"betalen", url:d.betaalUrl};
    return {status:"fout", reden:"onverwacht antwoord van de betaaldienst"};
  }catch(e){ return {status:"fout", reden:"de betaaldienst is niet bereikbaar"}; }
}

// ---- Ronde 18 (18 september 2026): de voorwaarden in een venster, ook op deze pagina ----
//
// Wat er misging op kaart.html: de link "algemene voorwaarden" opende voorwaarden.html in een
// nieuw tabblad. De keuze van de gast (strippenkaart of abonnement) en het akkoordvinkje staan
// alleen in het geheugen van deze pagina, dus wie terugkwam, begon opnieuw. Op het boekscherm
// (schermen.jsx) is dit dezelfde middag al opgelost; deze pagina bleef achter.
//
// De oplossing is EEN OP EEN dezelfde als in schermen.jsx: de tekst wordt uit voorwaarden.html
// zelf gehaald en in een venster over het scherm heen getoond. Daarmee staat de tekst nog steeds
// op precies EEN plek. preventDefault houdt de pagina staan, stopPropagation houdt het
// akkoordvinkje met rust (de link staat hier binnen het <label> van dat vinkje). De href blijft
// staan, zodat de gewone pagina blijft werken zonder javascript of als het ophalen mislukt.
//
// LET OP voor een volgende bouwronde: dit is bewust een KOPIE van VoorwaardenVenster en
// VoorwaardenLink uit schermen.jsx, geen gedeelde code. Reden: kaart.html laadt schermen.jsx
// bewust niet (zie de toelichting in kaart.html), en de twee bestanden samenvoegen of dit naar
// data.js verplaatsen raakt het boekscherm, dat vandaag werkt. Wie hier iets wijzigt, wijzigt
// hetzelfde in schermen.jsx, en andersom. Wil je van die kopie af, dan is de nette weg: allebei
// de definities naar data.js, dat door beide pagina's geladen wordt, en dan hier en in
// schermen.jsx weghalen. Dat is een aparte ronde met een eigen test.
function VoorwaardenVenster({ onSluit }){
  const [html,setHtml]=useState(null); const [fout,setFout]=useState(false);
  useEffect(()=>{
    let weg=false;
    fetch("voorwaarden.html")
      .then(r=>{ if(!r.ok) throw new Error("status "+r.status); return r.text(); })
      .then(t=>{
        if(weg) return;
        const d=new DOMParser().parseFromString(t,"text/html");
        // Weg met alles wat hier niet hoort: de terugkeerlink (die zou de pagina alsnog herladen),
        // scripts en de eigen stijlkoppelingen van die pagina.
        d.querySelectorAll('a[href="index.html"], script, link, style').forEach(e=>e.remove());
        const bron=d.querySelector("main")||d.body;
        setHtml(bron?bron.innerHTML:"");
      })
      .catch(e=>{ if(!weg){ console.warn("[upgolf] voorwaarden ophalen mislukt: "+(e&&e.message)); setFout(true); } });
    return ()=>{ weg=true; };
  },[]);
  return (
    <div className="scrim" onClick={e=>e.target===e.currentTarget&&onSluit()}>
      <div className="blad"><div className="greep"/>
        <h3>Algemene voorwaarden</h3>
        {!html && !fout && <div className="wl-tekst">Voorwaarden ophalen…</div>}
        {fout && <div className="let">De voorwaarden zijn nu niet op te halen. Ze staan ook op <a href="voorwaarden.html" target="_blank" rel="noopener">deze pagina</a>. Let op: die opent apart, je keuze blijft hier staan.</div>}
        {html && <div className="voorwaardentekst" dangerouslySetInnerHTML={{__html:html}}/>}
        <button className="knop vol stil" onClick={onSluit}>Terug naar mijn aankoop</button>
      </div>
    </div>
  );
}

// De link zelf, met zijn eigen venster. preventDefault houdt de pagina staan, stopPropagation
// houdt het akkoordvinkje met rust.
function VoorwaardenLink({ tekst }){
  const [open,setOpen]=useState(false);
  return (
    <>
      <a href="voorwaarden.html" onClick={e=>{ e.preventDefault(); e.stopPropagation(); setOpen(true); }}>{tekst||"algemene voorwaarden"}</a>
      {open && <VoorwaardenVenster onSluit={()=>setOpen(false)}/>}
    </>
  );
}

function looptijdTekst(t){
  if(t.looptijd_dagen && t.uiterlijk_tot) return t.looptijd_dagen + " dagen, uiterlijk tot " + kort(t.uiterlijk_tot);
  if(t.looptijd_dagen) return t.looptijd_dagen + " dagen vanaf je aankoop";
  if(t.uiterlijk_tot) return "geldig tot en met " + kort(t.uiterlijk_tot);
  return "";
}

// ----------------------------------------------------------------------------------------------
// Ronde 7, 14 september 2026: kaart kopen via het Recras-boekproces.
// Afspraak met Rene (Roy, letterlijk): "de kaarten en strippenkaarten via Recras op de website",
// "zodat dat ook direct in Recras komt". Standaard toont deze pagina daarom het boekproces van
// Recras (strippenkaart of abonnement) in plaats van ons eigen aankooppad. Klant, boeking,
// factuur en code landen dan in Recras zelf (gemeten in RECRAS-KENNIS sectie 9 en 12).
//
// Alles staat in tabel instellingen, zodat omschakelen naar de echte Recras alleen een instelling is:
//   recras_boekproces_url_strippenkaart  adres van het boekproces voor de strippenkaart
//   recras_boekproces_url_abonnement     adres van het boekproces voor het abonnement
//   recras_boekproces_weergave           "embed" (in een iframe op deze pagina) of "link"
//   kaartaankoop_eigen_pad_actief        "true" zet ons eigen aankooppad terug (standaard uit)
//
// Waarom embed mag: gemeten op 14 september (BOUWLOGBOEK ronde 7). Recras stuurt op
// /bookprocess/ geen X-Frame-Options en geen Content-Security-Policy, stap 1 en 2 werken in een
// iframe vanaf de lokale testserver, het script meldt zijn hoogte met postMessage ({iframeHeight}), en bij
// een betaallink zet het window.top.location, dus Mollie opent in het HELE venster, niet in het iframe.
// GEEN sandbox-attribuut op het iframe: dat zou die doorsturing blokkeren.
//
// Een beheerder kan de adressen wijzigen en anon mag ze lezen. Daarom opent deze pagina alleen een
// adres dat https is, zonder gebruikersnaam, wachtwoord, poort of anker, met een host op .recras.nl
// of .recras.com (dezelfde hostregel als veiligRecrasAdres in de edge functions), en met precies
// het pad /bookprocess/ en ?id=<cijfers>. Anders valt die kaartsoort weg.
function veiligBoekprocesAdres(ruw){
  let u; try{ u = new URL(String(ruw||"").trim()); }catch(e){ return null; }
  if(u.protocol!=="https:") return null;
  if(u.username || u.password || u.port || u.hash) return null;
  const host = u.hostname.toLowerCase();
  if(!(host.endsWith(".recras.nl") || host.endsWith(".recras.com"))) return null;
  if(u.pathname!=="/bookprocess/") return null;
  if(!/^\?id=[0-9]{1,9}$/.test(u.search)) return null;
  return u.toString();
}

const BOEKPROCES_SLEUTELS = ["kaartaankoop_eigen_pad_actief","recras_boekproces_url_strippenkaart",
  "recras_boekproces_url_abonnement","recras_boekproces_weergave"];

function KaartKopen(){
  const [stand,setStand]=useState(null);   // null = laden
  useEffect(()=>{ (async()=>{
    const r = await db.from("instellingen").select("sleutel,waarde").in("sleutel",BOEKPROCES_SLEUTELS);
    if(r.error){ console.warn("[upgolf] instellingen kaartkoop niet gelezen: " + r.error.message); setStand({fout:true}); return; }
    const w = {}; (r.data||[]).forEach(x=>{ w[x.sleutel]=String(x.waarde); });
    setStand({
      eigen: w.kaartaankoop_eigen_pad_actief==="true",
      weergave: w.recras_boekproces_weergave==="link" ? "link" : "embed",
      strippenkaart: veiligBoekprocesAdres(w.recras_boekproces_url_strippenkaart),
      abonnement: veiligBoekprocesAdres(w.recras_boekproces_url_abonnement)
    });
  })(); },[]);
  if(!stand) return <div className="laden">Laden…</div>;
  if(stand.eigen) return <EigenKaartKopen/>;
  return <RecrasKaartKopen stand={stand}/>;
}

function RecrasKaartKopen({ stand }){
  const soorten = [
    {sleutel:"strippenkaart", naam:"Strippenkaart", bij:"Een kaart met een vast aantal keer spelen", url:stand.strippenkaart},
    {sleutel:"abonnement", naam:"Abonnement", bij:"Onbeperkt golfen tot de vervaldatum", url:stand.abonnement}
  ].filter(s=>s.url);
  const gevraagd = new URLSearchParams(window.location.search).get("soort");
  const [keuze,setKeuze]=useState(soorten.find(s=>s.sleutel===gevraagd) ? gevraagd : (soorten.length===1 ? soorten[0].sleutel : null));
  const [hoogte,setHoogte]=useState(520);
  // Punt 6 (17 september 2026): akkoord met de voorwaarden is verplicht voordat het
  // boekproces in beeld komt. Zonder vinkje geen formulier en geen afrekenlink.
  const [akkoord,setAkkoord]=useState(false);
  const gekozen = soorten.find(s=>s.sleutel===keuze) || null;

  useEffect(()=>{
    if(!gekozen || stand.weergave!=="embed") return;
    const herkomst = new URL(gekozen.url).origin;
    function bericht(e){
      if(e.origin!==herkomst) return;
      const h = e.data && Number(e.data.iframeHeight);
      if(Number.isFinite(h)) setHoogte(Math.min(4000, Math.max(320, Math.round(h)+24)));
    }
    window.addEventListener("message", bericht);
    return ()=>window.removeEventListener("message", bericht);
  },[keuze, stand.weergave]);

  if(stand.fout || soorten.length===0){
    if(!stand.fout) console.warn("[upgolf] geen geldig Recras-boekprocesadres in de instellingen");
    return (
      <div className="kaartkoop">
        <h2><Kop tekst="Een kaart of abonnement kopen"/></h2>
        <div className="let">Online een kaart kopen kan op dit moment niet. Een kaart kopen kan aan de balie.</div>
        <a className="terug" href="index.html">Terug naar reserveren</a>
      </div>);
  }

  return (
    <div className="kaartkoop">
      <h2><Kop tekst="Een kaart of abonnement kopen"/></h2>
      <p className="bij">Kies wat je wilt en reken online af. Je code komt per mail.
        Liever aan de balie? Dat kan ook gewoon.</p>
      {soorten.length>1 && <div className="kaartlijst">
        {soorten.map(s=>(
          <button key={s.sleutel} className={"kaartkeuze"+(keuze===s.sleutel?" aan":"")} onClick={()=>{ setHoogte(520); setKeuze(s.sleutel); }}>
            <span className="kk-naam">{s.naam}</span>
            <span className="kk-bij">{s.bij}</span>
          </button>))}
      </div>}
      {gekozen && <label className="akkoordregel">
        <input type="checkbox" checked={akkoord} onChange={e=>setAkkoord(e.target.checked)}/>
        <span>Ik ga akkoord met de <VoorwaardenLink/>.</span>
      </label>}
      {gekozen && akkoord && stand.weergave==="embed" && <>
        <iframe key={gekozen.sleutel} className="recras-venster" src={gekozen.url} title={gekozen.naam+" kopen"}
          style={{height:hoogte+"px"}}/>
        <a className="terug" href={gekozen.url}>Laadt het formulier niet? Open het op een eigen pagina</a>
      </>}
      {gekozen && akkoord && stand.weergave==="link" &&
        <a className="knop vol recras-link" href={gekozen.url}>Verder naar afrekenen</a>}
      <a className="terug" href="index.html">Terug naar reserveren</a>
    </div>);
}

// Het eigen aankooppad van voor ronde 7, ongewijzigd. Alleen zichtbaar als de instelling
// kaartaankoop_eigen_pad_actief op "true" staat. Niet verwijderen: dit is de terugdraaiweg.
function EigenKaartKopen(){
  const [rittenkaarten,setRitten]=useState([]);
  const [abonnementen,setAbos]=useState([]);
  const [keuze,setKeuze]=useState(null);       // {soort, id, naam, prijs, bij}
  const [naam,setNaam]=useState(""); const [email,setEmail]=useState(""); const [tel,setTel]=useState("");
  const [laden,setLaden]=useState(true); const [f,setF]=useState(null); const [bezig,setBezig]=useState(false);
  const [mollie,setMollie]=useState(false);

  useEffect(()=>{ (async()=>{
    const [a,b,c] = await Promise.all([
      db.from("kaarttypes").select("*").eq("actief",true).order("beurten"),
      db.from("periodekaarttypes").select("*").eq("actief",true).order("sortering"),
      db.from("instellingen").select("waarde").eq("sleutel","mollie_actief").maybeSingle()
    ]);
    setRitten((a.data||[]).filter(t=>t.sport==="golf"||t.sport==="beide"));
    setAbos((b.data||[]).filter(t=>t.sport==="golf"||t.sport==="beide"));
    setMollie(!!(c.data && String(c.data.waarde)==="true"));
    setLaden(false);
  })(); },[]);

  async function koop(){
    if(!keuze) return;
    setBezig(true); setF(null);
    const r = await db.rpc("start_kaartaankoop",{
      p_soort: keuze.soort, p_type_id: keuze.id, p_naam: naam.trim(),
      p_email: email.trim(), p_kanaal: "online", p_telefoon: tel.trim()||null });
    if(r.error){ setF(foutTekst(r.error)); setBezig(false); return; }
    const token = r.data && r.data.token;
    if(!token){ setF("Er ging iets mis bij het klaarzetten van je aankoop. Probeer het zo nog eens."); setBezig(false); return; }
    // Het token gaat MEE in het webadres voordat we naar de betaaldienst vertrekken. Komt de koper
    // terug met de terugknop, dan is dat het enige spoor dat er al een aankoop klaarstaat.
    const u = await startKaartBetaling(token);
    if(u.status==="betalen"){ window.location.href = u.url; return; }
    console.warn("[upgolf] betaling niet gestart voor aankoop " + token + ": " + u.reden);
    setF("Je aankoop staat klaar, maar het afrekenen lukte niet. Probeer het zo nog eens, of bel ons op "+TELEFOON+".");
    setBezig(false);
  }

  if(laden) return <div className="laden">Laden…</div>;

  const kanKopen = !!keuze && naam.trim() && geldigEmail(email);

  return (
    <div className="kaartkoop">
      <h2><Kop tekst="Een kaart of abonnement kopen"/></h2>
      <p className="bij">Kies wat je wilt, reken online af, en je krijgt je code meteen op het scherm en per mail.
        Liever aan de balie? Dat kan ook gewoon.</p>

      {!mollie && <div className="let">Online afrekenen staat op dit moment uit. Een kaart kopen kan aan de balie.</div>}

      <h3>Rittenkaarten</h3>
      <p className="bij">Je speelt zoveel keer als er ritten op staan. De kaart verloopt niet.</p>
      <div className="kaartlijst">
        {rittenkaarten.map(t=>(
          <button key={t.id} className={"kaartkeuze"+(keuze&&keuze.soort==="strippenkaart"&&keuze.id===t.id?" aan":"")}
            onClick={()=>setKeuze({soort:"strippenkaart", id:t.id, naam:t.naam, prijs:t.prijs_cent, bij:t.beurten+" ritten"})}>
            <span className="kk-naam">{t.naam}</span>
            <span className="kk-bij">{t.beurten} keer spelen</span>
            <span className="kk-prijs">{euro(t.prijs_cent)}</span>
          </button>))}
      </div>

      <h3>Onbeperkt golfen</h3>
      <p className="bij">Zo vaak spelen als je wilt, binnen de periode die erbij staat.</p>
      <div className="kaartlijst">
        {abonnementen.map(t=>(
          <button key={t.id} className={"kaartkeuze"+(keuze&&keuze.soort==="periodekaart"&&keuze.id===t.id?" aan":"")}
            onClick={()=>setKeuze({soort:"periodekaart", id:t.id, naam:t.naam, prijs:t.prijs_cent, bij:looptijdTekst(t)})}>
            <span className="kk-naam">{t.naam}</span>
            <span className="kk-bij">{looptijdTekst(t)}</span>
            <span className="kk-prijs">{euro(t.prijs_cent)}</span>
          </button>))}
      </div>

      <h3>Je gegevens</h3>
      <label htmlFor="kk-naam">Naam</label>
      <input id="kk-naam" value={naam} onChange={e=>setNaam(e.target.value)} placeholder="Voor- en achternaam"/>
      <label htmlFor="kk-mail">E-mail</label>
      <input id="kk-mail" type="email" value={email} onChange={e=>setEmail(e.target.value)}/>
      <label htmlFor="kk-tel">Telefoon (optioneel)</label>
      <input id="kk-tel" type="tel" value={tel} onChange={e=>setTel(e.target.value)}/>
      {email.trim() && !geldigEmail(email) && <div className="fout">Dit lijkt geen e-mailadres. Controleer of er een apenstaartje in staat en een punt erachter.</div>}
      <div className="let">Op dit adres sturen we je code. Bewaar die mail, of schrijf de code over.</div>

      {keuze && <div className="som"><div className="lb">{keuze.naam}<div className="bij" style={{margin:0}}>{keuze.bij}</div></div><div className="bd">{euro(keuze.prijs)}</div></div>}
      {f && <div className="fout">{f}</div>}
      <button className="knop vol" onClick={koop} disabled={!kanKopen||bezig||!mollie}>
        {bezig?"Bezig…":(keuze?("Afrekenen, "+euro(keuze.prijs)):"Kies eerst een kaart")}</button>
      <a className="terug" href="index.html">Terug naar reserveren</a>
    </div>
  );
}

function KaartKlaar({ token }){
  const [stand,setStand]=useState(null); const [f,setF]=useState(null);
  const [pogingen,setPogingen]=useState(0);

  // De betaalbevestiging komt van de betaaldienst naar de database, niet via dit scherm. Op het
  // moment dat de koper terugkomt kan die melding er net nog niet zijn. Daarom kijken we een paar
  // keer opnieuw in plaats van meteen te zeggen dat er niets is.
  useEffect(()=>{ let weg=false;
    (async()=>{
      const r = await db.rpc("zoek_aankoop",{p_token:token});
      if(weg) return;
      if(r.error){ setF("We konden je aankoop even niet ophalen. Ververs deze pagina."); return; }
      setStand(r.data);
      if(r.data && r.data.gevonden && r.data.status!=="afgerond" && pogingen<6){
        setTimeout(()=>{ if(!weg) setPogingen(p=>p+1); }, 2000);
      }
    })();
    return ()=>{ weg=true; };
  },[token,pogingen]);

  if(f) return <div className="kaartkoop"><div className="fout">{f}</div></div>;
  if(!stand) return <div className="laden">Even kijken…</div>;

  if(!stand.gevonden) return (
    <div className="kaartkoop">
      <h2><Kop tekst="Deze aankoop kennen we niet"/></h2>
      <p className="bij">Het adres klopt misschien niet meer. Heb je betaald, dan staat je code in de mail.
        Kom je er niet uit, meld je dan bij de balie.</p>
      <a className="terug" href="index.html">Terug naar reserveren</a>
    </div>);

  const klaar = stand.status==="afgerond" && stand.code;
  const soortWoord = stand.soort==="strippenkaart" ? "rittenkaart" : "abonnement";

  return (
    <div className="kaartkoop">
      <div className={"vink"+(klaar?"":" letop")}>{klaar?"✓":"…"}</div>
      <h2><Kop tekst={klaar ? "Je "+soortWoord+" staat klaar" : "We wachten op de betaling"}/></h2>
      {klaar ? <>
        <p className="bij">Schrijf deze code over of bewaar de mail. Je vult hem in als je een starttijd reserveert.</p>
        <div className="codelb">Jouw code</div>
        <div className="code">{stand.code}</div>
        <div className="let">Bewaar deze code. Ben je hem kwijt, bel ons dan op {TELEFOON}.</div>
      </> : <>
        <p className="bij">De betaling is nog niet bij ons binnen. Dat kan een moment duren.
          Deze pagina kijkt vanzelf opnieuw. Blijft dit staan, meld je dan bij de balie met je naam.</p>
        <div className="let">Status: {stand.betaalstatus==="betaald" ? "betaald, we maken je kaart klaar" : "nog niet betaald"}.</div>
      </>}
      <div className="details">
        <div><span>Soort</span><span>{soortWoord}</span></div>
        <div><span>Bedrag</span><span>{euro(stand.bedrag_cent||0)}</span></div>
      </div>
      <a className="terug" href="index.html">Naar reserveren</a>
    </div>
  );
}

function KaartPagina(){
  const token = new URLSearchParams(window.location.search).get("aankoop");
  // Bevestigingsblok na een geslaagde Recras-kaartaankoop, ronde 20, 19 september 2026.
  // De Recras-boekprocessen krijgen vandaag success_url = kaart.html?gekocht=1 (besluit van Roy,
  // 17 september 2026: de gast doet alles op upgolf.nl en ziet nooit een sprong naar een ander
  // systeem). Zonder dit landde de gast na het betalen op een kale Recras-pagina.
  // Geen bedrag en geen kaartsoort in de tekst: die weet deze pagina niet, Recras zelf regelt de
  // betaling en de code komt via de bevestigingsmail van Recras, niet via onze eigen database.
  // Dezelfde opmaak (.banner.ok, met .ic/.tt/.sl) als de betaalbanner op schermen.jsx, zodat een
  // gast die eerst gereserveerd heeft dezelfde soort melding terugziet. haalUitAdres komt uit
  // data.js en is hier al beschikbaar omdat kaart.html data.js voor deze pagina laadt.
  const [gekocht, setGekocht] = useState(()=> new URLSearchParams(window.location.search).get("gekocht")==="1");
  useEffect(()=>{ if(gekocht) haalUitAdres("gekocht"); },[]);
  return (<div className="wrap smal">
    {/* Nav toegevoegd, ronde 3, 24 augustus 2026, zelfde nabouwopdracht als schermen.jsx (zie de
        toelichting daar). Deze pagina laadt schermen.jsx niet (BOUWLOGBOEK, ronde 22 augustus:
        "kaart.html laadt schermen.jsx niet"), dus de nav staat hier los, met dezelfde drie items
        en dezelfde klassen (.hoofdnav / .aan), zodat hij er identiek uitziet. Kaart kopen is hier
        de actieve pagina, dus dat item krijgt het kader. */}
    <div className="balk"><div className="balk-in">
      {/* Lockup herbouwd, ronde 4, 24 augustus 2026, zelfde nabouw als schermen.jsx (zie de
          toelichting bij .merk-up in stijl.css). .merk is hier een <a>, geen <div>, met dezelfde
          klassen zodat hij er identiek uitziet. */}
      <a className="merk" href="index.html">
        <span className="merk-up">UP</span>
        <span className="merk-scheiding"></span>
        <span className="merk-tekst">
          <span className="merk-naam">Golf Weesp</span>
          <span className="merk-sub">Premium booking</span>
        </span>
      </a>
      <nav className="hoofdnav">
        <a href="index.html">Golf</a>
        <a href="footgolf.html">Footgolf</a>
        <a className="aan" href="kaart.html">Kaart kopen</a>
      </nav>
      {/* MIJN UP toegevoegd, ronde 4, 24 augustus 2026, op melding van hoofd-activiteiten: stond bij
          Daniel op alle drie zijn schermen, ontbrak hier. MIJN UP opent bij ons een verzamelscherm
          dat in schermen.jsx woont (de MijnUp-component), en deze pagina laadt schermen.jsx bewust
          niet (kaart.html is een apart, klein bestand, geen risico op een demo-dag). Dus GEEN knop
          die hier een scherm opent: een gewone link naar index.html, waar MIJN UP wel echt werkt.
          Zelfde klasse (.mijnup-knop) zodat hij er identiek uitziet als op de andere twee pagina's. */}
      <a className="mijnup-knop" href="index.html">MIJN UP</a>
    </div></div>
    <div className="kaart">
      {gekocht &&
        <div className="banner ok">
          <div className="ic">✓</div>
          <div><div className="tt">Je aankoop is gelukt</div>
            <div>Je code komt per mail, met daarin je strippenkaart of je abonnement. Zie je die
              mail niet snel, kijk dan ook in je map met ongewenste mail of spam. Met de code uit
              die mail kun je meteen een <a href="index.html">starttijd reserveren</a>.</div></div>
          <button className="sl" onClick={()=>setGekocht(false)}>×</button>
        </div>}
      {token ? <KaartKlaar token={token}/> : <KaartKopen/>}
    </div>
  </div>);
}

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