/* Checkout - full pushed page, mirrors web checkout.html (mobile): order card → attendee details (if any) → seats (if seated) → where we send → payment → terms → agree + Pay */
const Card = ({ children, style }) => <div className="dcard" style={style}>{children}</div>;
const CL = ({ children }) => <div style={{ fontFamily: 'var(--dp-font-mono)', fontSize: 10, letterSpacing: '.14em', textTransform: 'uppercase', color: 'var(--mut2)', fontWeight: 600, marginBottom: 12 }}>{children}</div>;
const Inp = (p) => <input {...p} style={{ width: '100%', height: 46, padding: '0 14px', borderRadius: 10, border: '1px solid var(--line)', background: 'var(--sur)', fontSize: 14.5, color: 'var(--ink)', outline: 0, ...p.style }} />;

function SectionPicker({ ev, tier, qty, value, set }) {
  const base = tier.p || 0; const S = DP.SECTIONS;
  const blocks = { gold: { x: 20, y: 36, w: 60, h: 14 }, floor: { x: 10, y: 52, w: 80, h: 22 }, l1: { x: 4, y: 20, w: 92, h: 14 }, l2: { x: 0, y: 4, w: 100, h: 14 }, box: { x: 0, y: 36, w: 14, h: 38 } };
  return <div>
    <div style={{ position: 'relative', aspectRatio: '10/8', borderRadius: 12, border: '1px solid var(--line)', overflow: 'hidden' }}>
      <div style={{ position: 'absolute', left: '25%', right: '25%', bottom: 6, height: 18, borderRadius: '6px 6px 0 0', background: 'var(--fill)', color: '#fff', fontSize: 9, letterSpacing: '.2em', display: 'grid', placeItems: 'center', fontFamily: 'var(--dp-font-mono)' }}>STAGE</div>
      {S.map(s => { const b = blocks[s.k], on = value === s.k, out = false; return <button key={s.k} onClick={() => !out && set(s.k)} style={{ position: 'absolute', left: b.x + '%', top: b.y + '%', width: b.w + '%', height: b.h + '%', borderRadius: 6, border: on ? '2px solid var(--red)' : '1px solid var(--line)', background: on ? 'var(--red-soft)' : 'var(--sur)', color: out ? 'var(--mut2)' : on ? 'var(--red)' : 'var(--ink)', fontSize: 10, fontWeight: 700, display: 'grid', placeItems: 'center', transition: 'all .2s', padding: 2, textAlign: 'center', lineHeight: 1.15 }}>{s.nm.replace('Section ', '')}</button>; })}
    </div>
    <div style={{ display: 'grid', gap: 6, marginTop: 10 }}>{S.map(s => { const on = value === s.k, out = false, p = base; return <button key={s.k} className="press" onClick={() => !out && set(s.k)} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 12px', borderRadius: 10, textAlign: 'left', border: `1px solid ${on ? 'var(--red)' : 'var(--line)'}`, background: on ? 'var(--red-soft)' : 'transparent', opacity: out ? .45 : 1 }}><span style={{ flex: 1 }}><span style={{ display: 'block', fontWeight: 700, fontSize: 13.5 }}>{s.nm}</span></span><span style={{ fontWeight: 700, color: 'var(--price)', fontSize: 14 }}>{DP.money(p, ev.cc)}</span></button>; })}</div>
    <div style={{ fontSize: 11.5, color: 'var(--mut2)', marginTop: 8 }}>Best available seats in the section are assigned at payment.</div>
  </div>;
}

function RowPicker({ qty, value, set }) {
  const rows = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']; const N = 12;
  const taken = useMemo(() => { const r = rnd(42), t = new Set(); rows.forEach(R => { for (let i = 1; i <= N; i++) if (false && r() < .4) t.add(R + i); }); return t; }, []);
  const toggle = (id) => { if (taken.has(id)) return; const s = new Set(value); if (s.has(id)) s.delete(id); else { if (s.size >= qty) s.delete([...s][0]); s.add(id); } set(s); };
  return <div>
    <div style={{ display: 'flex', justifyContent: 'center', marginBottom: 10 }}><span style={{ padding: '4px 36px', borderRadius: '0 0 10px 10px', background: 'var(--fill)', color: '#fff', fontSize: 9, letterSpacing: '.2em', fontFamily: 'var(--dp-font-mono)' }}>STAGE</span></div>
    <div style={{ display: 'grid', gap: 5 }}>{rows.map((R, ri) => <div key={R} style={{ display: 'grid', gridTemplateColumns: `14px repeat(${N},1fr) 14px`, gap: 4, alignItems: 'center' }}><span style={{ fontSize: 10, color: 'var(--mut2)', fontWeight: 700 }}>{R}</span>{[...Array(N)].map((_, i) => { const id = R + (i + 1), t = taken.has(id), on = value.has(id); return <button key={id} onClick={() => toggle(id)} style={{ aspectRatio: '1', borderRadius: '5px 5px 3px 3px', border: 0, marginLeft: i === 3 || i === 7 ? 4 : 0, background: t ? 'var(--line)' : on ? 'var(--red)' : ri < 3 ? 'var(--purple-soft)' : 'var(--chip)', transform: on ? 'scale(1.15)' : 'none', transition: 'all .15s', cursor: t ? 'default' : 'pointer' }}></button>; })}<span style={{ fontSize: 10, color: 'var(--mut2)', fontWeight: 700 }}>{R}</span></div>)}</div>
    <div style={{ display: 'flex', gap: 14, justifyContent: 'center', marginTop: 12, fontSize: 11, color: 'var(--mut)' }}>{[['var(--purple-soft)', 'Premium rows'], ['var(--chip)', 'Standard'], ['var(--red)', 'Yours'], ['var(--line)', 'Taken']].map(([c, l]) => <span key={l} style={{ display: 'inline-flex', alignItems: 'center', gap: 5 }}><span style={{ width: 10, height: 10, borderRadius: 3, background: c }}></span>{l}</span>)}</div>
    <div style={{ marginTop: 10, fontSize: 13, fontWeight: 600, display: 'flex', justifyContent: 'space-between' }}><span>{value.size} of {qty} seats picked</span><span style={{ color: 'var(--mut)' }}>{[...value].join(', ') || '-'}</span></div>
  </div>;
}

const boxStyle = (on, bad) => ({ position: 'relative', height: 52, borderRadius: 14, border: `1.5px solid ${bad ? 'var(--red)' : on ? 'var(--ink)' : 'var(--line)'}`, background: 'var(--sur)', transition: 'border-color .2s, box-shadow .2s', boxShadow: on ? '0 0 0 4px rgba(29,13,49,.06)' : 'none', display: 'flex', alignItems: 'center', padding: '0 14px', gap: 10 });
const QLabel = ({ children, opt, bad }) => <div style={{ fontSize: 12.5, fontWeight: 600, color: bad ? 'var(--red)' : 'var(--mut)', margin: '0 2px 8px', display: 'flex', gap: 6, alignItems: 'center' }}>{children}{opt && <span style={{ fontSize: 10, fontWeight: 600, padding: '1px 6px', borderRadius: 4, background: 'var(--chip)', color: 'var(--mut2)' }}>Optional</span>}</div>;

function FloatField({ label, value, onChange, bad, opt, type = 'text', placeholder }) {
  const [f, setF] = useState(false);
  return <div><QLabel opt={opt} bad={bad}>{label}</QLabel><div className={bad ? 'shake' : ''} style={boxStyle(f, bad)}><input type={type} value={value} onChange={e => onChange(e.target.value)} onFocus={() => setF(true)} onBlur={() => setF(false)} placeholder={placeholder || ''} style={{ flex: 1, minWidth: 0, border: 0, outline: 0, background: 'transparent', fontSize: 15.5, fontWeight: 500, color: 'var(--ink)' }} /></div></div>;
}

function DateField({ label, value, onChange, bad, opt }) {
  const [f, setF] = useState(false); const ref = useRef();
  const open = () => { const el = ref.current; if (!el) return; el.focus(); try { el.showPicker && el.showPicker(); } catch (x) {} };
  return <div><QLabel opt={opt} bad={bad}>{label}</QLabel><div className={bad ? 'shake' : ''} onClick={open} style={{ ...boxStyle(f, bad), cursor: 'pointer' }}>
    <input ref={ref} className="dp-date" type="date" value={value || ''} onChange={e => onChange(e.target.value)} onFocus={() => setF(true)} onBlur={() => setF(false)} style={{ flex: 1, minWidth: 0, border: 0, outline: 0, background: 'transparent', fontSize: 15.5, fontWeight: 500, color: value ? 'var(--ink)' : 'var(--mut2)', fontFamily: 'inherit' }} />
    <Ico.cal size={18} style={{ color: 'var(--mut2)', flex: 'none', pointerEvents: 'none' }} /></div></div>;
}

function MultiSelect({ q, v, set, bad }) {
  const [open, setOpen] = useState(false); const arr = v || [];
  return <div><QLabel opt={!q.required} bad={bad}>{q.label}</QLabel>
    <button onClick={() => setOpen(true)} className={bad ? 'shake' : ''} style={{ ...boxStyle(open, bad), width: '100%', height: 'auto', minHeight: 52, padding: arr.length ? '8px 14px' : '0 14px', textAlign: 'left' }}>
      <span style={{ flex: 1, minWidth: 0, display: 'flex', flexWrap: 'wrap', gap: 6 }}>{arr.length ? arr.map(o => <span key={o} style={{ display: 'inline-flex', alignItems: 'center', gap: 4, height: 28, padding: '0 6px 0 10px', borderRadius: 9999, background: 'var(--red-soft)', color: 'var(--red)', fontSize: 13, fontWeight: 600 }}>{o}<span role="button" onClick={(e) => { e.stopPropagation(); set(arr.filter(x => x !== o)); }} style={{ display: 'inline-grid', placeItems: 'center', width: 18, height: 18 }}><Ico.x size={11} stroke={2.4} /></span></span>) : <span style={{ fontSize: 15.5, color: 'var(--mut2)', fontWeight: 500 }}>Select all that apply</span>}</span>
      <Ico.down size={18} style={{ color: 'var(--mut2)', flex: 'none' }} />
    </button>
    <Sheet open={open} onClose={() => setOpen(false)} title={q.label}>
      {q.options.map((o, i) => { const on = arr.includes(o); return <button key={o} className="press" onClick={() => set(on ? arr.filter(x => x !== o) : [...arr, o])} style={{ display: 'flex', alignItems: 'center', gap: 12, width: '100%', minHeight: 52, textAlign: 'left', borderBottom: i < q.options.length - 1 ? '1px solid var(--line)' : 0 }}><span style={{ width: 22, height: 22, flex: 'none', borderRadius: 6, border: on ? '1.5px solid var(--red)' : '1.5px solid #C4BDCC', background: on ? 'var(--red)' : 'transparent', display: 'grid', placeItems: 'center', color: '#fff', transition: 'all .15s' }}>{on && <Ico.check size={14} stroke={2.6} />}</span><span style={{ flex: 1, fontSize: 15, fontWeight: 500 }}>{o}</span></button>; })}
      <Btn onClick={() => setOpen(false)} style={{ marginTop: 14 }}>{arr.length ? `Done · ${arr.length} selected` : 'Done'}</Btn>
    </Sheet>
  </div>;
}

function Question({ q, v, set, bad }) {
  if (q.type === 'multi') return <div data-q={q.id}><MultiSelect q={q} v={v} set={set} bad={bad} /></div>;
  if (q.type === 'date') return <div data-q={q.id}><DateField label={q.label} value={v} onChange={set} bad={bad} opt={!q.required} /></div>;
  if (q.type === 'single') return <div data-q={q.id} className={bad ? 'shake' : ''}><QLabel opt={!q.required} bad={bad}>{q.label}</QLabel>
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>{q.options.map(o => { const on = v === o; return <button key={o} className="press" onClick={() => set(on ? '' : o)} style={{ height: 48, padding: '0 12px', borderRadius: 14, display: 'flex', alignItems: 'center', gap: 10, textAlign: 'left', fontSize: 14, fontWeight: 600, border: `1.5px solid ${on ? 'var(--red)' : 'var(--line)'}`, background: on ? 'var(--red-soft)' : 'var(--sur)', color: on ? 'var(--red)' : 'var(--ink)', transition: 'all .18s' }}><span style={{ width: 18, height: 18, flex: 'none', borderRadius: '50%', border: `1.5px solid ${on ? 'var(--red)' : '#C4BDCC'}`, display: 'grid', placeItems: 'center', transition: 'all .18s' }}>{on && <span className="pop" style={{ width: 9, height: 9, borderRadius: '50%', background: 'var(--red)' }}></span>}</span><span style={{ minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{o}</span></button>; })}</div>
  </div>;
  return <div data-q={q.id}><FloatField label={q.label} value={v || ''} onChange={set} bad={bad} opt={!q.required} /></div>;
}

function Checkout({ z, ev, initialQty, onBack, onPaid, closing }) {
  const { device, bottomInset, toast, sim, setStage } = useApp();
  const [fail, setFail] = useState(''); const [tds, setTds] = useState(false);
  const tiers = tiersFor(ev);
  const [qty] = useState(initialQty || { [tiers[0].k]: 1 });
  const [pm, setPm] = useState(''); const [optin, setOptin] = useState(false); const [agree, setAgree] = useState(false); const [busy, setBusy] = useState(false); const [brk, setBrk] = useState(false); const [promo, setPromo] = useState(false); const [code, setCode] = useState(''); const [coupon, setCoupon] = useState(null); const [err, setErr] = useState('');
  const [section, setSection] = useState(''); const [seats, setSeats] = useState(new Set());
  const [terms, setTerms] = useState(''); const [copied, setCopied] = useState(false);
  const [who, setWho] = useState({ name: DP.USER.name, email: DP.USER.email }); const [editing, setEditing] = useState(false);
  const n = Object.values(qty).reduce((a, b) => a + b, 0);
  const needsAppr = tiers.some(t => qty[t.k] && t.appr);
  const list = useMemo(() => tiers.flatMap(t => Array.from({ length: qty[t.k] || 0 }, () => t.nm)), []);
  const [guests, setGuests] = useState(() => list.map((tier, i) => ({ name: i === 0 ? DP.USER.name : '', tier, a: {} })));
  const [gi, setGi] = useState(0);
  const secMult = 1;
  const sub = tiers.reduce((s, t) => s + (qty[t.k] || 0) * Math.round(t.p * secMult), 0);
  const fee = Math.round(sub * feeFor(ev) * 100) / 100; const disc = coupon ? Math.min(sub, coupon.v) : 0;
  const pmFee = pm === 'PayPal' || pm === 'Klarna' ? Math.round(((sub - disc + fee) * .005 + .2) * 100) / 100 : 0;
  const total = Math.max(0, sub + fee - disc + pmFee); const vat = total - total / 1.19;
  const cur = (v) => DP.money(Math.round(v * 100) / 100, ev.cc);
  const done = (g) => g.name.trim() && DP.QUESTIONS.every(q => !q.required || (q.type === 'multi' ? (g.a[q.id] || []).length : g.a[q.id]));
  const allDone = !ev.questions || guests.every(done);
  const seatsOk = !ev.seated || (ev.seated === 'sections' ? !!section : seats.size === n);
  const wallet = device === 'android' ? 'Google Pay' : 'Apple Pay';
  const PM = [[wallet, 'wallet', ''], ['Credit or debit card', 'card', ''], ['Klarna', 'klarna', '+ ' + cur((sub - disc + fee) * .005 + .2) + ' transaction fee'], ['PayPal', 'paypal', '+ ' + cur((sub - disc + fee) * .005 + .2) + ' transaction fee'], ['iDEAL | Wero', 'ideal', ''], ['Bancontact', 'bancontact', '']];
  const Logo = ({ k }) => k === 'wallet' ? <svg width="44" height="24" viewBox="0 0 44 24" fill="none" stroke="var(--purple)" strokeWidth="2.2"><rect x="2" y="3" width="40" height="18" rx="7" /><rect x="29" y="10" width="8" height="4" rx="2" fill="var(--purple)" stroke="none" /></svg> : k === 'card' ? <svg width="40" height="26" viewBox="0 0 40 26" fill="none" stroke="var(--purple)" strokeWidth="2.2"><rect x="2" y="3" width="36" height="20" rx="3" /><path d="M2 9h36M7 17h8" /></svg> : k === 'klarna' ? <span style={{ padding: '3px 8px', borderRadius: 6, background: '#FFB3C7', color: '#17120F', fontWeight: 700, fontSize: 12 }}>Klarna</span> : k === 'paypal' ? <img src={DP.A + 'payments/paypal.png'} alt="PayPal" style={{ height: 18 }} /> : k === 'ideal' ? <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, padding: '3px 7px', borderRadius: 6, background: '#FFF27A', fontWeight: 800, fontSize: 11, color: '#111' }}><img src={DP.A + 'payments/ideal.svg'} alt="iDEAL" style={{ height: 16 }} /><span style={{ width: 1, height: 14, background: 'rgba(0,0,0,.3)' }}></span>wero</span> : <span style={{ fontWeight: 800, fontSize: 13, color: '#1E4B9C' }}>Bancontact</span>;
  const ready = agree && allDone && seatsOk && (pm || !total);
  const blocker = !seatsOk ? (ev.seated === 'sections' ? 'Choose a section' : `Pick ${n - seats.size} more seat${n - seats.size > 1 ? 's' : ''}`) : !allDone ? 'Complete attendee details' : (!pm && total) ? 'Choose a payment method' : !agree ? 'Agree to the terms' : '';
  const scrRef = useRef(); const [flag, setFlag] = useState(''); const refs = { seats: useRef(), details: useRef(), pay: useRef(), agree: useRef() };
  const nudge = () => {
    const k = !seatsOk ? 'seats' : !allDone ? 'details' : (!pm && total) ? 'pay' : 'agree';
    if (k === 'details') { const i = guests.findIndex(g => !done(g)); if (i >= 0) setGi(i); }
    setFlag(k); setTimeout(() => setFlag(''), 2400);
    setTimeout(() => { const el = refs[k].current, s = scrRef.current; if (el && s && k !== 'agree') s.scrollTo({ top: el.offsetTop - 80, behavior: 'smooth' }); if (el) { const f = el.querySelector('input:not([type=checkbox]):placeholder-shown, input[value=""]'); if (f && k === 'details') setTimeout(() => f.focus({ preventScroll: true }), 350); } }, 60);
  };
  const finish = () => onPaid({ ev, qty, tiers, total, pm: pm || 'Free', n, section, seats: [...seats], guests: ev.questions ? guests : null, status: needsAppr ? 'pending' : 'confirmed' });
  const pay = () => { if (!ready) return nudge(); setBusy(true); setTimeout(() => { if (sim === 'declined') { setBusy(false); return setFail('declined'); } if (sim === 'soldout') { setBusy(false); return setFail('soldout'); } if (sim === 'session') { setBusy(false); return setFail('session'); } if (sim === '3ds' && total > 0) { setTds(true); setTimeout(() => { setTds(false); finish(); }, 2600); return; } finish(); }, 1100); };
  const apply = () => { const c = code.trim().toUpperCase(); if (!c) return setErr('Enter a code first.'); if (c === 'DESI2') { setCoupon({ k: c, v: 2 }); setErr(''); setPromo(false); } else setErr(`“${c}” is not a valid code.`); };
  const setG = (patch) => { if (gi === 0 && patch.a) setCopied(false); setGuests(gs => gs.map((g, i) => i === gi ? { ...g, ...patch } : g)); };
  const Line = ({ l, v, sub, bold }) => <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 12, fontSize: sub ? 12.5 : 13.5, color: sub ? 'var(--mut)' : 'var(--ink)', fontWeight: bold ? 700 : 500, padding: '3px 0' }}><span style={{ flex: 1, minWidth: 0, lineHeight: 1.4, overflowWrap: 'anywhere' }}>{l}</span><span style={{ flex: 'none' }}>{v}</span></div>;
  return <div className={'push' + (closing ? ' out' : '')} style={{ position: 'absolute', inset: 0, zIndex: z || 31, background: 'var(--paper)' }}>
    <div ref={scrRef} className="scr" style={{ background: 'var(--paper)' }}>
      <TopBar onBack={onBack} title={needsAppr ? 'Request a spot' : 'Checkout'} />
      <div style={{ padding: `4px 16px ${bottomInset + 150}px`, display: 'grid', gap: 12 }}>
        <Card>
          <div style={{ display: 'flex', gap: 12, alignItems: 'center' }}><img src={ev.img} alt="" style={{ width: 52, height: 52, borderRadius: 10, objectFit: 'cover' }} /><div style={{ minWidth: 0 }}><div style={{ fontWeight: 700, fontSize: 14.5, lineHeight: 1.25, display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden' }}>{ev.nm}</div><div style={{ fontSize: 12.5, color: 'var(--mut)', marginTop: 3 }}>{fmtDate(ev.date)} · {ev.time}</div></div></div>
          <button onClick={() => setBrk(!brk)} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%', marginTop: 14, padding: '14px 0 12px', borderTop: '1px solid var(--line)', borderBottom: '1px solid var(--line)' }}><span style={{ fontFamily: 'var(--dp-font-display)', fontWeight: 600, fontSize: 16 }}>Summary</span><span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 13, color: 'var(--mut)' }}>{`${n} ${tiers.some(t => t.appr !== undefined) && ev.approval ? 'pass' + (n > 1 ? 'es' : '') : 'ticket' + (n > 1 ? 's' : '')}`}<Ico.down size={14} style={{ transform: brk ? 'rotate(180deg)' : 'none', transition: 'transform .25s' }} /></span></button>
          <div style={{ display: 'grid', gridTemplateRows: brk ? '1fr' : '0fr', transition: 'grid-template-rows .3s cubic-bezier(.2,.8,.2,1)' }}><div style={{ overflow: 'hidden' }}><div style={{ paddingTop: 10 }}>{tiers.filter(t => qty[t.k]).map(t => <Line key={t.k} l={`${t.group ? qty[t.k] + ' × ' + t.nm + ' (' + qty[t.k] * t.group + ' pax)' : t.k === 'grpx' ? qty[t.k] + ' × extra seat' + (qty[t.k] > 1 ? 's' : '') : qty[t.k] + ' × ' + t.nm}${section ? ' · ' + DP.SECTIONS.find(s => s.k === section).nm : ''}${seats.size ? ' · ' + [...seats].join(', ') : ''}`} v={t.p ? cur(qty[t.k] * Math.round(t.p * secMult)) : 'Free'} />)}</div></div></div>
          <div style={{ padding: '10px 0 12px', borderBottom: '1px solid var(--line)' }}><Line sub l="Sub-Total" v={cur(sub)} />{fee > 0 && <Line sub l={`Booking fee`} v={cur(fee)} />}{ev.feeInc && sub > 0 && <Line sub l="Booking fee" v="Included" />}{pmFee > 0 && <Line sub l={pm + ' fee'} v={cur(pmFee)} />}{disc > 0 && <Line sub l={'Coupon ' + coupon.k} v={'−' + cur(disc)} />}<div style={{ display: 'flex', justifyContent: 'space-between', fontWeight: 700, fontSize: 15.5, paddingTop: 8 }}><span>Total amount</span><span>{cur(total)}</span></div>{needsAppr && total > 0 && <div style={{ fontSize: 12, color: 'var(--mut)', paddingTop: 4 }}>Charged only once the organiser approves.</div>}</div>
          {sub > 0 && <div style={{ paddingTop: 12 }}>{coupon ? <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13.5, color: 'var(--green)', fontWeight: 600 }}><Ico.check size={16} />{coupon.k} applied, {cur(coupon.v)} off<button onClick={() => setCoupon(null)} style={{ marginLeft: 'auto', color: 'var(--mut)', fontSize: 12.5 }}>Remove</button></div> : !promo ? <button onClick={() => setPromo(true)} style={{ display: 'inline-flex', alignItems: 'center', gap: 8, fontSize: 14.5, fontWeight: 600, color: 'var(--red)' }}><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M20.6 13.4 13.4 20.6a2 2 0 0 1-2.8 0L3 13V3h10l7.6 7.6a2 2 0 0 1 0 2.8Z"/><circle cx="7.5" cy="7.5" r="1.5"/></svg>Add coupon</button> : <div className="fade-in"><div style={{ display: 'flex', gap: 8 }}><Inp value={code} onChange={e => setCode(e.target.value)} placeholder="Enter code" style={{ flex: 1 }} /><Btn small kind="dark" onClick={apply} style={{ height: 46 }}>Apply</Btn></div>{err && <div style={{ fontSize: 12, color: 'var(--red)', marginTop: 6 }}>{err}</div>}</div>}</div>}
        </Card>
        {ev.seated && <div ref={refs.seats}><Card style={flag === 'seats' ? { boxShadow: '0 0 0 2px var(--red)', animation: 'dpShake .4s' } : undefined}><CL>{ev.seated === 'sections' ? 'Choose a section' : `Pick ${n} seat${n > 1 ? 's' : ''}`}</CL>{ev.seated === 'sections' ? <SectionPicker ev={ev} tier={tiers.find(t => qty[t.k]) || tiers[0]} qty={n} value={section} set={setSection} /> : <RowPicker qty={n} value={seats} set={setSeats} />}</Card></div>}
        {ev.questions && <div ref={refs.details}><Card style={flag === 'details' ? { boxShadow: '0 0 0 2px var(--red)', animation: 'dpShake .4s' } : undefined}><CL>Attendee details</CL>
          {guests.length > 1 && <div className="hs" style={{ gap: 6, margin: '0 -4px 4px', padding: '0 4px', scrollSnapType: 'none' }}>{guests.map((g, i) => <button key={i} onClick={() => setGi(i)} style={{ flex: 'none', display: 'inline-flex', alignItems: 'center', gap: 6, height: 32, padding: '0 12px', borderRadius: 9999, fontSize: 12.5, fontWeight: 700, border: `1px solid ${gi === i ? 'var(--red)' : 'var(--line)'}`, background: gi === i ? 'var(--red-soft)' : 'transparent', color: gi === i ? 'var(--red)' : 'var(--ink)' }}><span style={{ width: 7, height: 7, borderRadius: '50%', background: done(g) ? 'var(--green)' : 'var(--line)' }}></span>{g.name.trim() ? g.name.trim().split(' ')[0] : 'Guest ' + (i + 1)}</button>)}</div>}
          <div key={gi} className="fade-in"><div style={{ fontSize: 11.5, color: 'var(--mut2)', marginTop: 8 }}>{guests[gi].tier}</div><div style={{ display: 'grid', gap: 18, marginTop: 12 }}><FloatField label="Full name" placeholder="Guest's full name" value={guests[gi].name} onChange={v => setG({ name: v })} bad={flag === 'details' && !guests[gi].name.trim()} />{DP.QUESTIONS.map(q => <Question key={q.id} bad={flag === 'details' && q.required && !(q.type === 'multi' ? (guests[gi].a[q.id] || []).length : guests[gi].a[q.id])} q={q} v={guests[gi].a[q.id]} set={v => setG({ a: { ...guests[gi].a, [q.id]: v } })} />)}</div>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 16 }}>{gi === 0 && guests.length > 1 ? (copied ? <span className="fade-in" style={{ fontSize: 13, fontWeight: 600, color: 'var(--green)', display: 'inline-flex', gap: 6, alignItems: 'center' }}><Ico.check size={15} stroke={2.4} />Answers copied to {guests.length - 1} guest{guests.length > 2 ? 's' : ''}</span> : <button onClick={() => { const src = guests[0].a; if (!Object.keys(src).length) { setFlag('details'); setTimeout(() => setFlag(''), 2000); return; } setGuests(gs => gs.map((g, i) => i === 0 ? g : { ...g, a: JSON.parse(JSON.stringify(src)) })); setCopied(true); }} style={{ fontSize: 13, fontWeight: 700, color: 'var(--red)', display: 'inline-flex', gap: 6, alignItems: 'center' }}><Ico.copy size={15} />Use these answers for all guests</button>) : <span />}{gi < guests.length - 1 && <Btn small kind="ghost" onClick={() => setGi(gi + 1)} style={{ height: 36, fontSize: 13 }}>Next guest<Ico.chev size={14} /></Btn>}</div></div>
        </Card></div>}
        <Card><CL>Where we send your tickets</CL>{editing ? <div className="fade-in" style={{ display: 'grid', gap: 10 }}><Inp value={who.name} onChange={e => setWho({ ...who, name: e.target.value })} placeholder="Full name" /><Inp value={who.email} onChange={e => setWho({ ...who, email: e.target.value })} type="email" placeholder="Email address" /><Btn small kind="dark" onClick={() => setEditing(false)} style={{ height: 42, justifySelf: 'start' }}>Done</Btn></div> : <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 14px', borderRadius: 12, border: '1px solid var(--line)' }}><img src={DP.USER.avatar} alt="" style={{ width: 38, height: 38, borderRadius: '50%', objectFit: 'cover' }} /><div style={{ flex: 1, minWidth: 0 }}><div style={{ fontWeight: 700, fontSize: 14 }}>{who.name}</div><div style={{ fontSize: 12.5, color: 'var(--mut)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{who.email}</div></div><button onClick={() => setEditing(true)} style={{ fontSize: 13, fontWeight: 700, color: 'var(--red)' }}>Edit</button></div>}<div style={{ marginTop: 12 }}><OptIn on={optin} set={setOptin} /></div></Card>
        {total > 0 && <div ref={refs.pay}><Card style={flag === 'pay' ? { boxShadow: '0 0 0 2px var(--red)', animation: 'dpShake .4s' } : undefined}><CL>Payment method</CL>
          <div>{PM.map(([k, logo, sub]) => <React.Fragment key={k}><button className="press" onClick={() => setPm(k)} style={{ display: 'flex', alignItems: 'center', gap: 12, width: '100%', minHeight: 50, textAlign: 'left', borderBottom: '1px solid var(--line)' }}><span style={{ width: 20, height: 20, borderRadius: '50%', border: `2px solid ${pm === k ? 'var(--red)' : '#C4BDCC'}`, display: 'grid', placeItems: 'center', transition: 'all .15s', flex: 'none' }}>{pm === k && <span className="pop" style={{ width: 10, height: 10, borderRadius: '50%', background: 'var(--red)' }}></span>}</span><span style={{ flex: 1 }}><span style={{ display: 'block', fontSize: 15, fontWeight: 500 }}>{k}</span>{sub && pm === k && <span className="fade-in" style={{ display: 'flex', alignItems: 'center', gap: 4, fontSize: 11.5, color: 'var(--mut2)', marginTop: 2 }}>{sub}<span role="button" tabIndex={0} aria-label="About this fee" onClick={(e) => { e.stopPropagation(); toast('PayPal and Klarna charge a higher transaction fee, which we pass on at cost.'); }} style={{ width: 16, height: 16, borderRadius: '50%', border: '1.3px solid currentColor', display: 'inline-grid', placeItems: 'center', fontSize: 10, fontWeight: 700, fontStyle: 'italic', fontFamily: 'Georgia, serif', lineHeight: 1, cursor: 'pointer' }}>i</span></span>}</span><Logo k={logo} /></button>{k === 'Credit or debit card' && pm === k && <div className="fade-in" style={{ display: 'grid', gap: 8, padding: '4px 0 14px', borderBottom: '1px solid var(--line)' }}><Inp placeholder="Card number" inputMode="numeric" /><div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}><Inp placeholder="MM / YY" inputMode="numeric" /><Inp placeholder="CVC" inputMode="numeric" /></div><Inp placeholder="Name on card" defaultValue={DP.USER.name} /></div>}</React.Fragment>)}</div>
        </Card></div>}
        <div style={{ height: 4 }}></div>
      </div>
    </div>
    <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, zIndex: 9, padding: `12px 16px ${bottomInset + 10}px`, background: 'var(--tabbg)', backdropFilter: 'blur(18px)', borderTop: '1px solid var(--line)', boxShadow: '0 -8px 24px -12px rgba(29,13,49,.18)' }}>
          <button ref={refs.agree} onClick={() => setAgree(!agree)} style={{ display: 'flex', gap: 12, alignItems: 'flex-start', textAlign: 'left', width: '100%', borderRadius: 10, padding: flag === 'agree' ? 6 : 0, margin: flag === 'agree' ? -6 : 0, boxShadow: flag === 'agree' ? '0 0 0 2px var(--red)' : 'none', animation: flag === 'agree' ? 'dpShake .4s' : 'none', transition: 'box-shadow .2s' }}><span style={{ width: 22, height: 22, flex: 'none', borderRadius: 6, border: agree ? '1.5px solid var(--red)' : '1.5px solid #C4BDCC', background: agree ? 'var(--red)' : 'transparent', display: 'grid', placeItems: 'center', color: '#fff', transition: 'all .15s' }}>{agree && <Ico.check size={14} stroke={2.6} />}</span><span style={{ fontSize: 13, color: 'var(--mut)', lineHeight: 1.5 }}>I agree to the <a onClick={(e) => { e.stopPropagation(); setTerms('event'); }} style={{ color: 'var(--ink)', textDecoration: 'underline', textUnderlineOffset: 2 }}>Event Terms</a>, DesiPass <a onClick={(e) => { e.stopPropagation(); setTerms('terms'); }} style={{ color: 'var(--ink)', textDecoration: 'underline', textUnderlineOffset: 2 }}>Terms</a> &amp; <a onClick={(e) => { e.stopPropagation(); setTerms('privacy'); }} style={{ color: 'var(--ink)', textDecoration: 'underline', textUnderlineOffset: 2 }}>Privacy</a>.</span></button>
          <Btn onClick={pay} style={{ height: 50, marginTop: 10, opacity: ready || busy ? 1 : .55 }} icon={!busy && <Ico.lock size={17} />}>{busy ? <span style={{ width: 18, height: 18, borderRadius: '50%', border: '2.5px solid rgba(255,255,255,.35)', borderTopColor: '#fff', animation: 'dpSpin .7s linear infinite' }}></span> : needsAppr ? 'Request a spot' : total ? `Pay now · ${cur(total)}` : 'Confirm RSVP'}</Btn>
    </div>
    <StateSheet open={fail === 'declined'} onClose={() => setFail('')} icon="card" title="Payment didn't go through" body="Your bank declined the payment. You haven't been charged. Try again or choose another payment method." primary="Try again" onPrimary={() => setFail('')} secondary="Use another method" onSecondary={() => { setFail(''); setPm(''); }} />
    <StateSheet open={tds} onClose={() => {}} icon="bank" tone="purple" spin title="Confirm with your bank" body="Approve this payment in your banking app. We'll continue automatically." />
    <StateSheet open={fail === 'soldout'} onClose={onBack} icon="sold" tone="amber" title="Tickets just sold out" body="Someone else got the last tickets while you were checking out. You haven't been charged." primary="Back to event" onPrimary={onBack} />
    <StateSheet open={fail === 'session'} onClose={() => setFail('')} icon="user" tone="purple" title="Please sign in again" body="For your security your session ended. Your selection is saved." primary="Sign in" onPrimary={() => setStage('signin')} />
    <TermsSheet open={!!terms} tab={terms} setTab={setTerms} onClose={() => setTerms('')} />
  </div>;
}

Object.assign(window, { Checkout });
