/* Homepage sections + Events + Conteúdos */
const { useState: useStateP, useEffect: useEffectP, useMemo: useMemoP, useRef: useRefP } = React;

/* ── UUID v4 (crypto-based for affiliate links) ───────────── */
const genUUID = () => {
  if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
    return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
      (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
    );
  }
  return Math.random().toString(36).substr(2, 9) + Date.now().toString(36);
};

/* ── AES-256 simulation (Base64 obfuscation for demo) ─────── */
const encodeAffiliateToken = (userId, eventId) => {
  const raw = `mrc_${userId}_${eventId}_${Date.now()}`;
  return btoa(raw).replace(/=/g, '').substring(0, 32);
};

const downloadFile = (filename, mime, body) => {
  const blob = new Blob([body], { type: mime });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  document.body.appendChild(a);
  a.click();
  a.remove();
  URL.revokeObjectURL(url);
};

const eventToIcs = (e) => {
  const start = `${e.date.replace(/-/g, '')}T090000`;
  const end = `${e.date.replace(/-/g, '')}T180000`;
  return [
    'BEGIN:VEVENT',
    `UID:${e.id}@marcianus.experience`,
    `DTSTAMP:${new Date().toISOString().replace(/[-:]/g, '').split('.')[0]}Z`,
    `DTSTART:${start}`,
    `DTEND:${end}`,
    `SUMMARY:${e.title}`,
    `LOCATION:${e.loc}`,
    `DESCRIPTION:${e.desc}`,
    'END:VEVENT',
  ].join('\r\n');
};

const downloadCalendar = (events, filename = 'marcianus-calendar.ics') => {
  const ics = ['BEGIN:VCALENDAR', 'VERSION:2.0', 'PRODID:-//Marcianus Experience//Web v3//PT', ...events.map(eventToIcs), 'END:VCALENDAR'].join('\r\n');
  downloadFile(filename, 'text/calendar;charset=utf-8', ics);
  SoundFX.success();
  ToastBus.push({ icon: 'calendar', title: 'Calendário gerado', desc: `${events.length} evento(s) exportado(s) em ICS.` });
};

const downloadOnepager = (e) => {
  const body = [
    `Marcianus Experience - ${e.title}`,
    '',
    `Data: ${e.date}`,
    `Local: ${e.loc}`,
    `Sector: ${e.sector}`,
    `Status: ${e.status}`,
    `Participantes: ${e.attendees}`,
    `Pipeline estimado: ${e.pipeline}`,
    `Match Score: ${e.match}%`,
    '',
    e.desc,
  ].join('\n');
  downloadFile(`${e.title.toLowerCase().replace(/[^a-z0-9]+/g, '-')}-onepager.txt`, 'text/plain;charset=utf-8', body);
  ToastBus.push({ icon: 'download', title: 'Onepager exportado', desc: `${e.title} pronto para consulta local.` });
};

// ===== HOW (3-step) =====
const HowItWorks = ({ onNav }) => {
  const steps = [
    { n: '01', t: 'Setup Operacional', d: 'Briefing, design, hardware (kioskes, NFC, wristbands) e integração com o teu CRM em 14 dias.', ic: 'package' },
    { n: '02', t: 'Evento Live', d: 'Hexis AI cruza interesses, pontua matches em tempo real e injeta a próxima conversa certa no momento certo.', ic: 'zap' },
    { n: '03', t: 'Pipeline Auditável', d: 'Cada handshake, score e follow-up sincronizado no teu CRM. Relatório executivo em 24h.', ic: 'chart-line' },
  ];
  return (
    <section className="page-section">
      <div className="container">
        <div className="section-head">
          <div className="left">
            <span className="eyebrow">Como funciona</span>
            <h2>Três fases. Zero <span className="hl">fricção</span>.</h2>
            <p className="section-lead">Não é um evento decorado. É um sistema operacional para encontros de alto valor — calibrado, medido e auditável.</p>
          </div>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 18 }}>
          {steps.map((s, i) => (
            <div key={i} className="card card-purple" style={{ position: 'relative' }}>
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }}>
                <span className="mono-eyebrow">Fase {s.n}</span>
                <div style={{ width: 36, height: 36, borderRadius: 9, background: 'rgba(123,97,255,0.14)', border: '1px solid var(--border-purple)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--purple-soft)' }}>
                  <Icon name={s.ic} size={18} />
                </div>
              </div>
              <h4 style={{ fontSize: 20, marginBottom: 8 }}>{s.t}</h4>
              <p style={{ fontSize: 14, color: 'var(--text-2)' }}>{s.d}</p>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
};

// ===== STACK / TECH =====
const StackSection = ({ onNav }) => {
  const items = [
    {
      t: 'Kiosk Inteligente', d: 'Check-in NFC com touchscreen, impressão de wristband e Hexis AI Live integrado. Setup em 48h.', img: 'assets/samsung-kiosk.png', tag: 'Hardware', price: 'Kz 1.400.000', cta: 'Ver especificações',
      specs: 'Kiosk NFC Marcianus: Touchscreen 21" · Leitura NFC + QR · Impressão wristband on-site · Hexis AI overlay · Bateria 8h · Setup 48h · Suporte técnico incluído.',
      action: 'specs',
    },
    {
      t: 'NFC Card / Wristband', d: 'Identidade física que regista cada conexão, sessão e interação em tempo real via pgvector.', img: 'assets/nfc-card.png', tag: 'Identity', price: 'Kz 7.000/un.', cta: 'Pedir orçamento',
      action: 'quote',
    },
    {
      t: 'Hexis AI Live', d: 'Overlay de matching em tempo real: cosine similarity em pgvector, <50ms, determinístico e auditável.', img: 'assets/wristband.png', tag: 'Intelligence', price: 'Kz 700.000/evento', cta: 'Saber mais',
      specs: 'Hexis AI Live: Motor cosine similarity em pgvector · Latência <50ms · Match Score em tempo real · CRM injection automática · Logs imutáveis · XAI auditável · Zero LLM no matching.',
      action: 'detail',
    },
  ];
  return (
    <section className="page-section" style={{ background: 'var(--surface-1)' }}>
      <div className="container">
        <div className="section-head">
          <div className="left">
            <span className="eyebrow">Stack Operacional</span>
            <h2>Hardware <span className="hl-grad">+ Hexis AI</span>. Sincronizados.</h2>
            <p className="section-lead">A camada física e o motor de inteligência operam como uma única plataforma. Sem zaps, sem CSVs.</p>
          </div>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 18 }}>
          {items.map((it, i) => (
            <div key={i} className="stack-card" style={{ cursor: 'pointer' }} onClick={() => {
              SoundFX.tap();
              if (it.action === 'specs' || it.action === 'detail') {
                ToastBus.push({ kind: 'gold', icon: 'package', title: it.t, desc: it.specs, duration: 8000 });
                if (onNav) onNav('marketplace');
              } else if (it.action === 'quote') {
                SoundFX.success();
                window.open('https://wa.me/244930179037?text=Olá%2C%20gostaria%20de%20pedir%20orçamento%20para%20NFC%20Wristbands.', '_blank');
              }
            }}>
              <div className="stack-card-img">
                <img src={it.img} alt={it.t} loading="lazy" />
                <span className="chip chip-purple stack-tag">{it.tag}</span>
                <span className="stack-price">{it.price}</span>
              </div>
              <div className="stack-card-body">
                <h4>{it.t}</h4>
                <p>{it.d}</p>
                <div className="stack-card-cta">
                  <span>{it.cta}</span>
                  <span className="arrow"><Icon name="arrow-up-right" size={14} /></span>
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
};

// ===== CASES / RESULTS =====
const CasesSection = ({ onNav }) => {
  const cases = [
    { sector: 'Banca', client: 'Banco Invicta', metric: '€4.2M', label: 'Pipeline pós-evento', delta: '+38% vs. 2024' },
    { sector: 'Tech', client: 'Veridian VC', metric: '17', label: 'Term sheets em 5 dias', delta: '3.4× histórico' },
    { sector: 'Saúde', client: 'Helix Bio', metric: '92%', label: 'Match Score médio', delta: 'Top quartile' },
  ];
  return (
    <section className="page-section">
      <div className="container">
        <div className="section-head">
          <div className="left">
            <span className="eyebrow">Resultados auditáveis</span>
            <h2>Métrica é o <span className="hl">decisor</span>.</h2>
          </div>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 18 }}>
          {cases.map((c, i) => (
            <div key={i} className="card">
              <span className="chip chip-purple">{c.sector}</span>
              <div style={{ marginTop: 18 }}>
                <div className="metric-xl" style={{ fontFamily: 'var(--font-mono)' }}>{c.metric}</div>
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--text-3)', marginTop: 8, fontWeight: 700 }}>{c.label}</div>
              </div>
              <div style={{ marginTop: 18, paddingTop: 18, borderTop: '1px solid var(--border-1)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                <span style={{ fontWeight: 700, fontSize: 14 }}>{c.client}</span>
                <span className="chip chip-success">{c.delta}</span>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
};

// ===== HOMEPAGE wrapper =====
const HomePage = ({ onNav }) => (
  <div className="page active">
    <Hero onNav={onNav} />
    <HowItWorks onNav={onNav} />
    <section className="page-section" style={{ paddingTop: 0, paddingBottom: 0 }}>
      <div className="container">
        <InfiniteGameWidget title="B2B Intelligence Arena™" accentColor="#7B61FF" compact />
      </div>
    </section>
    <StackSection onNav={onNav} />
    <CasesSection onNav={onNav} />
  </div>
);

// ===== EVENTS DATA =====
const TODAY = new Date('2026-04-28');
const EVENTS = [
  { id: 'e1', d: 12, m: 'Mar', date: '2025-03-12', title: 'Invicta Capital Forum', loc: 'Alfândega · Porto', sector: 'Banca', status: 'past', attendees: 240, pipeline: '€4.2M', match: 94, price: 480, desc: 'Encontro fechado entre top 50 CFOs nacionais e gestoras de capital alternativo. Foco em ESG-linked debt e venture debt.', tickets: [{ tier: 'General', price: 480 }, { tier: 'Executive', price: 980 }, { tier: 'VIP', price: 1800 }] },
  { id: 'e2', d: 26, m: 'Mar', date: '2025-03-26', title: 'Veridian Tech Summit', loc: 'LX Factory · Lisboa', sector: 'Tech', status: 'past', attendees: 180, pipeline: '€2.8M', match: 91, price: 380, desc: 'Curated investor day — Series A/B founders & 22 LPs europeus. 1:1 matchmaking via Hexis.', tickets: [{ tier: 'General', price: 380 }, { tier: 'Executive', price: 780 }, { tier: 'VIP', price: 1500 }] },
  { id: 'e3', d: 9, m: 'Abr', date: '2025-04-09', title: 'Helix Bio Roundtable', loc: 'Pavilhão do Conhecimento · Lisboa', sector: 'Saúde', status: 'past', attendees: 92, pipeline: '€1.9M', match: 88, price: 320, desc: 'Roundtable executivo entre HPGM, fundos europeus de health-tech e clusters de I&D nacionais.', tickets: [{ tier: 'General', price: 320 }, { tier: 'Executive', price: 680 }] },
  { id: 'e4', d: 22, m: 'Abr', date: '2025-04-22', title: 'Solaris Energy Briefing', loc: 'Casa da Música · Porto', sector: 'Energia', status: 'past', attendees: 130, pipeline: '€3.6M', match: 86, price: 420, desc: 'Briefing executivo sobre transição energética e pipeline regulatório PT/EU.', tickets: [{ tier: 'General', price: 420 }, { tier: 'Executive', price: 880 }] },
  { id: 'e5', d: 20, m: 'Mai', date: '2026-05-20', title: 'Aether Real Estate Summit', loc: 'Convento do Beato · Lisboa', sector: 'Real Estate', status: 'upcoming', attendees: 210, pipeline: '€5.4M', match: 90, price: 560, desc: 'Encontro entre developers, family offices e operadores institucionais. Foco em logistics + BTR.', tickets: [{ tier: 'General', price: 560 }, { tier: 'Executive', price: 1200 }, { tier: 'VIP', price: 2400 }] },
  { id: 'e6', d: 18, m: 'Jun', date: '2026-06-18', title: 'Cygnus AI Forum', loc: 'NOS Alive Hub · Algés', sector: 'Tech', status: 'upcoming', attendees: 320, pipeline: '€6.1M', match: 95, price: 680, desc: 'Reunião privada entre 30 founders de IA aplicada e 14 CDOs/CIOs do PSI-20.', tickets: [{ tier: 'General', price: 680 }, { tier: 'Executive', price: 1480 }, { tier: 'VIP', price: 2800 }] },
  { id: 'e7', d: 28, m: 'Abr', date: '2026-04-28', title: 'FinTech Lisboa 2026 · Live Now', loc: 'MAAT · Lisboa', sector: 'FinTech', status: 'live', attendees: 260, pipeline: '€4.8M', match: 93, price: 520, desc: 'Summit de inovação financeira com CEOs de bancos, fintechs e reguladores europeus. Hexis Live ativo.', tickets: [{ tier: 'General', price: 520 }, { tier: 'Executive', price: 1100 }, { tier: 'VIP', price: 2200 }] },
  { id: 'e8', d: 15, m: 'Jul', date: '2026-07-15', title: 'HealthTech Investors Day', loc: 'Hospital da Luz · Lisboa', sector: 'Saúde', status: 'upcoming', attendees: 140, pipeline: '€3.2M', match: 87, price: 440, desc: 'Dia de investidores dedicado a scale-ups de HealthTech em expansão europeia.', tickets: [{ tier: 'General', price: 440 }, { tier: 'Executive', price: 940 }] },
  { id: 'e9', d: 10, m: 'Set', date: '2026-09-10', title: 'GreenEnergy Impact Forum', loc: 'Parque das Nações · Lisboa', sector: 'Energia', status: 'upcoming', attendees: 300, pipeline: '€7.2M', match: 89, price: 580, desc: 'Encontro estratégico entre fundos de infraestrutura verde, reguladores e startups cleantech.', tickets: [{ tier: 'General', price: 580 }, { tier: 'Executive', price: 1240 }, { tier: 'VIP', price: 2600 }] },
  { id: 'e10', d: 25, m: 'Out', date: '2026-10-25', title: 'Marcianus Summit 2026', loc: 'Centro de Congressos · Lisboa', sector: 'Multi-sector', status: 'upcoming', attendees: 600, pipeline: '€12M', match: 96, price: 780, desc: 'O maior evento anual do ecossistema Marcianus. Todos os sectores, todos os kernels, ao vivo.', tickets: [{ tier: 'General', price: 780 }, { tier: 'Executive', price: 1680 }, { tier: 'VIP', price: 3200 }] },
];
const EVENTS_PER_PAGE = 50;

/* ── AFFILIATE PROGRAM (simulated state) ───────────────── */
const AFFILIATE_PROGRAM = {
  enrolled: false,
  commissionRate: 0.12,
  pendingApproval: false,
};

/* ── TICKET PURCHASE MODAL ──────────────────────────────── */
const TicketModal = ({ event, onClose, onNav }) => {
  const auth = window.useAuth ? window.useAuth() : { user: null };
  const { user } = auth;
  const [selected, setSelected] = useStateP(event.tickets[0]);
  const [qty, setQty] = useStateP(1);
  const [step, setStep] = useStateP('select');

  const total = selected.price * qty;

  const handleBuy = () => {
    if (!user) { onClose(); onNav('entrar'); return; }
    setStep('confirm');
    setTimeout(() => {
      setStep('success');
      SoundFX.success();
      fireConfetti({ x: window.innerWidth / 2, y: window.innerHeight / 2 }, ['#FFD700', '#7B61FF', '#00C48C']);
      if (window.HexisEngine) HexisEngine.handleAction('ticket_buy', { event: event.title });
      if (window.HexisBLS) HexisBLS.track('cta_click', `ticket_buy_${event.id}`, total);
      ToastBus.push({ kind: 'gold', icon: 'check-circle', title: 'Bilhete confirmado!', desc: `${qty}× ${selected.tier} · ${event.title}`, duration: 5000 });
    }, 1200);
  };

  return (
    <div className="ticket-modal-overlay" onClick={e => e.target === e.currentTarget && onClose()}>
      <div className="ticket-modal">
        {step === 'success' ? (
          <div style={{ textAlign: 'center', padding: '20px 0' }}>
            <div style={{ fontSize: 52, marginBottom: 16 }}>🎟️</div>
            <h3 style={{ marginBottom: 8 }}>Bilhete Confirmado!</h3>
            <p style={{ color: 'var(--text-2)', marginBottom: 8 }}>
              {qty}× {selected.tier} · {event.title}
            </p>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 20, color: 'var(--gold)', fontWeight: 900, marginBottom: 24 }}>
              €{total.toLocaleString('pt-PT')}
            </div>
            <div style={{ background: 'var(--surface-3)', borderRadius: 12, padding: '12px 16px', marginBottom: 20, fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-3)', letterSpacing: '0.12em' }}>
              ID: MRC-{genUUID().substring(0, 8).toUpperCase()}
            </div>
            <div style={{ display: 'flex', gap: 8 }}>
              <button className="btn btn-ghost btn-sm" style={{ flex: 1 }} onClick={onClose}>Fechar</button>
              <button className="btn btn-primary btn-sm" style={{ flex: 2 }} onClick={() => { onClose(); onNav('dashboard'); }}>Ver no Dashboard →</button>
            </div>
          </div>
        ) : (
          <>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 20 }}>
              <div>
                <div className="eyebrow" style={{ marginBottom: 6 }}>Comprar Bilhete</div>
                <h3 style={{ fontSize: 18, fontWeight: 800 }}>{event.title}</h3>
                <div style={{ fontSize: 12, color: 'var(--text-3)', marginTop: 4, display: 'flex', alignItems: 'center', gap: 4 }}>
                  <Icon name="map-pin" size={11} />{event.loc}
                </div>
              </div>
              <button className="icon-btn" onClick={onClose}><Icon name="x" size={16} /></button>
            </div>

            <div className="ticket-tiers">
              {event.tickets.map((t, i) => (
                <div
                  key={i}
                  className={`ticket-tier ${selected.tier === t.tier ? 'selected' : ''}`}
                  onClick={() => setSelected(t)}
                >
                  <div className="tier-name">{t.tier}</div>
                  <div className="tier-price">€{t.price}</div>
                  <div className="tier-desc">{t.tier === 'VIP' ? 'Lounge + Hexis Priority' : t.tier === 'Executive' ? 'Executive Floor + Kit NFC' : 'Acesso geral + NFC Band'}</div>
                </div>
              ))}
            </div>

            <div style={{ display: 'flex', alignItems: 'center', gap: 12, margin: '16px 0', background: 'var(--surface-3)', borderRadius: 10, padding: '10px 14px' }}>
              <span style={{ fontSize: 13, color: 'var(--text-2)', flex: 1 }}>Quantidade</span>
              <button className="icon-btn" style={{ width: 32, height: 32 }} onClick={() => setQty(q => Math.max(1, q - 1))}><Icon name="minus" size={14} /></button>
              <span style={{ fontFamily: 'var(--font-mono)', fontWeight: 900, fontSize: 18, minWidth: 24, textAlign: 'center' }}>{qty}</span>
              <button className="icon-btn" style={{ width: 32, height: 32 }} onClick={() => setQty(q => Math.min(10, q + 1))}><Icon name="plus" size={14} /></button>
            </div>

            <div style={{ borderTop: '1px solid var(--border-1)', paddingTop: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 }}>
              <span style={{ color: 'var(--text-2)', fontSize: 14 }}>Total</span>
              <span style={{ fontFamily: 'var(--font-mono)', fontWeight: 900, fontSize: 22, color: 'var(--gold)' }}>€{total.toLocaleString('pt-PT')}</span>
            </div>

            <button
              className="btn btn-gold"
              style={{ width: '100%', height: 48 }}
              onClick={handleBuy}
              disabled={step === 'confirm'}
            >
              {step === 'confirm' ? 'A processar…' : user ? `Comprar · €${total.toLocaleString('pt-PT')}` : 'Entrar para comprar →'}
            </button>
            {!user && (
              <p style={{ textAlign: 'center', marginTop: 8, fontSize: 11, color: 'var(--text-3)' }}>
                Precisas de conta · <span style={{ color: 'var(--purple-soft)', cursor: 'pointer' }} onClick={() => { onClose(); onNav('entrar'); }}>Criar grátis →</span>
              </p>
            )}
          </>
        )}
      </div>
    </div>
  );
};

/* ── RESELL MODAL ─────────────────────────────────────────── */
const ResellModal = ({ event, onClose }) => {
  const [price, setPrice] = useStateP(event.tickets[0].price);
  const [submitted, setSubmitted] = useStateP(false);

  const handleResell = () => {
    SoundFX.success();
    if (window.HexisBLS) HexisBLS.track('cta_click', `resell_${event.id}`, price);
    if (window.HexisEngine) HexisEngine.handleAction('resell_submit', { event: event.title, price });
    ToastBus.push({ kind: 'gold', icon: 'refresh', title: 'Bilhete listado!', desc: `${event.title} · €${Math.round(price * 0.95).toLocaleString('pt-PT')} após comissão.`, duration: 5000 });
    setSubmitted(true);
  };

  if (submitted) {
    return (
      <div className="ticket-modal-overlay" onClick={e => e.target === e.currentTarget && onClose()}>
        <div className="ticket-modal" style={{ textAlign: 'center' }}>
          <div style={{ fontSize: 48, marginBottom: 16 }}>🔄</div>
          <h3 style={{ marginBottom: 8 }}>Bilhete em revenda!</h3>
          <p style={{ color: 'var(--text-2)', marginBottom: 20 }}>O teu bilhete está listado no Marketplace Marcianus. Será reemitido com novo UUID quando vendido — o original é invalidado automaticamente.</p>
          <div style={{ background: 'var(--surface-3)', borderRadius: 10, padding: 12, fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--success)', marginBottom: 20 }}>
            Comissão Marcianus: 5% · Tu recebes: €{Math.round(price * 0.95).toLocaleString('pt-PT')}
          </div>
          <button className="btn btn-gold" style={{ width: '100%' }} onClick={onClose}>Concluído</button>
        </div>
      </div>
    );
  }

  return (
    <div className="ticket-modal-overlay" onClick={e => e.target === e.currentTarget && onClose()}>
      <div className="ticket-modal">
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}>
          <h3 style={{ fontSize: 18, fontWeight: 800 }}>Revender Bilhete</h3>
          <button className="icon-btn" onClick={onClose}><Icon name="x" size={16} /></button>
        </div>
        <p style={{ color: 'var(--text-2)', fontSize: 14, marginBottom: 20, lineHeight: 1.6 }}>
          O bilhete será listado no <strong style={{ color: '#fff' }}>Marketplace P2P Marcianus</strong>. Quando vendido, o UUID é reemitido e o original invalidado (anti-fraude).
        </p>
        <div className="form-group" style={{ marginBottom: 16 }}>
          <label>Preço de revenda (€)</label>
          <input
            className="form-input"
            type="number"
            value={price}
            onChange={e => setPrice(Math.max(1, +e.target.value))}
            min={1}
            max={event.tickets[event.tickets.length - 1].price * 2}
          />
        </div>
        <div style={{ fontSize: 12, color: 'var(--text-3)', marginBottom: 20, fontFamily: 'var(--font-mono)' }}>
          Comissão plataforma: 5% · Recebes: €{Math.round(price * 0.95).toLocaleString('pt-PT')}
        </div>
        <button className="btn btn-gold" style={{ width: '100%' }} onClick={handleResell}>
          Listar para revenda →
        </button>
      </div>
    </div>
  );
};

/* ── AFFILIATE MODAL ─────────────────────────────────────── */
const AffiliateModal = ({ event, user, onClose, onNav }) => {
  const [enrolled, setEnrolled] = useStateP(false);
  const [applying, setApplying] = useStateP(false);
  const [copied, setCopied] = useStateP(false);

  const token = user ? encodeAffiliateToken(user.id || 'u1', event.id) : null;
  const affiliateLink = token ? `https://marcianus.io/e/${event.id}?ref=${token}` : null;

  const handleCopy = () => {
    if (!affiliateLink) return;
    navigator.clipboard.writeText(affiliateLink).then(() => {
      setCopied(true);
      SoundFX.success();
      ToastBus.push({ kind: 'gold', icon: 'check-circle', title: 'Link copiado!', desc: 'UUID criptografado incluído para rastreabilidade.' });
      setTimeout(() => setCopied(false), 3000);
    });
  };

  const handleApply = () => {
    if (!user) { onClose(); onNav('entrar'); return; }
    setApplying(true);
    setTimeout(() => {
      setApplying(false);
      setEnrolled(true);
      SoundFX.success();
      if (window.HexisBLS) HexisBLS.track('cta_click', `affiliate_enroll_${event.id}`, 1);
      if (window.HexisEngine) HexisEngine.handleAction('affiliate_enroll', { event: event.title });
      ToastBus.push({ kind: 'gold', icon: 'gift', title: 'Afiliado aprovado!', desc: `12% por cada bilhete de ${event.title} vendido. Começa a partilhar!`, duration: 5000 });
    }, 1200);
  };

  return (
    <div className="ticket-modal-overlay" onClick={e => e.target === e.currentTarget && onClose()}>
      <div className="ticket-modal">
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}>
          <div>
            <div className="eyebrow" style={{ marginBottom: 4 }}>Programa de Afiliados</div>
            <h3 style={{ fontSize: 18, fontWeight: 800 }}>Link de Afiliado</h3>
          </div>
          <button className="icon-btn" onClick={onClose}><Icon name="x" size={16} /></button>
        </div>

        {!enrolled && !user ? (
          <div style={{ textAlign: 'center', padding: '20px 0' }}>
            <div style={{ fontSize: 40, marginBottom: 12 }}>🔒</div>
            <p style={{ color: 'var(--text-2)', marginBottom: 20 }}>Para aceder ao programa de afiliados, precisas de criar conta e ser aprovado pelo Hexis AI.</p>
            <button className="btn btn-gold" style={{ width: '100%' }} onClick={() => { onClose(); onNav('entrar'); }}>Criar Conta →</button>
          </div>
        ) : !enrolled ? (
          <div>
            <div style={{ background: 'rgba(123,97,255,0.06)', border: '1px solid var(--border-purple)', borderRadius: 12, padding: 16, marginBottom: 20 }}>
              <div style={{ fontWeight: 800, fontSize: 15, marginBottom: 8 }}>Como funciona</div>
              <ul style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                {['Inscreve-te no programa e aguarda aprovação Hexis AI', 'Recebe link com UUID AES-256 criptografado', 'Cada venda via link gera comissão automática na Wallet', 'Comissão padrão: 12% por bilhete vendido'].map((s, i) => (
                  <li key={i} style={{ display: 'flex', gap: 8, fontSize: 13, color: 'var(--text-2)', alignItems: 'flex-start' }}>
                    <span style={{ color: 'var(--success)', fontWeight: 900, flexShrink: 0, fontSize: 11, marginTop: 2 }}>✓</span>{s}
                  </li>
                ))}
              </ul>
            </div>
            <button className="btn btn-gold" style={{ width: '100%' }} onClick={handleApply} disabled={applying}>
              {applying ? 'A processar pedido…' : 'Candidatar ao Programa →'}
            </button>
          </div>
        ) : (
          <div>
            <div style={{ background: 'rgba(0,196,140,0.06)', border: '1px solid rgba(0,196,140,0.30)', borderRadius: 10, padding: '10px 14px', marginBottom: 16, display: 'flex', alignItems: 'center', gap: 8 }}>
              <Icon name="check-circle" size={14} color="var(--success)" />
              <span style={{ fontSize: 13, color: 'var(--success)', fontWeight: 700 }}>Aprovado no Programa de Afiliados · Hexis AI</span>
            </div>
            <div style={{ marginBottom: 8, fontSize: 13, color: 'var(--text-2)' }}>Teu link de afiliado (UUID criptografado incluído):</div>
            <div className="affiliate-link-row">
              <input
                className="affiliate-link-input"
                value={affiliateLink || 'Faz login para ver o teu link'}
                readOnly
              />
              <button className="btn btn-primary btn-sm" onClick={handleCopy}>
                {copied ? <><Icon name="check" size={13} /> Copiado</> : <><Icon name="share" size={13} /> Copiar</>}
              </button>
            </div>
            <div style={{ marginTop: 12, fontSize: 11, color: 'var(--text-3)', fontFamily: 'var(--font-mono)', letterSpacing: '0.08em' }}>
              Comissão: 12% por venda · Pago na Wallet Marcianus · Rastreado via UUID
            </div>
          </div>
        )}
      </div>
    </div>
  );
};

/* ── SPONSOR / PROMOTE MODAL ─────────────────────────────── */
const SponsorModal = ({ event, onClose }) => {
  const [plan, setPlan] = useStateP('silver');
  const [submitted, setSubmitted] = useStateP(false);
  const PLANS = [
    { id: 'bronze', name: 'Bronze', price: '€1.500', perks: ['Logo no check-in screen', 'Menção no email de boas-vindas', 'Leads: 20 qualificados'] },
    { id: 'silver', name: 'Silver', price: '€4.500', perks: ['Stand digital premium', 'Overlay Hexis prioritário', 'Leads: 60 qualificados', 'Relatório pós-evento'] },
    { id: 'gold', name: 'Gold', price: '€9.000', perks: ['Keynote slot 15 min', 'Acesso a todos os dados', 'Leads: 150 qualificados', 'Hexis Live branding', 'Reuniões garantidas: 10'] },
  ];

  const handleSubmit = () => {
    const selectedPlan = PLANS.find(p => p.id === plan);
    SoundFX.success();
    if (window.HexisBLS) HexisBLS.track('cta_click', `sponsor_${plan}_${event.id}`, selectedPlan.price);
    if (window.HexisEngine) HexisEngine.handleAction('sponsor_submit', { plan: `${selectedPlan.name} ${selectedPlan.price}`, event: event.title });
    ToastBus.push({ kind: 'gold', icon: 'rocket', title: 'Proposta enviada!', desc: `Patrocínio ${selectedPlan.name} · ${event.title} · Respondemos em 24h.`, duration: 5500 });
    setSubmitted(true);
    setTimeout(onClose, 2200);
  };

  if (submitted) {
    return (
      <div className="ticket-modal-overlay">
        <div className="ticket-modal" style={{ maxWidth: 480, textAlign: 'center', padding: '44px 28px' }}>
          <div style={{ width: 72, height: 72, borderRadius: '50%', background: 'rgba(255,215,0,0.12)', border: '2px solid var(--gold)', display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 20px', fontSize: 32 }}>🚀</div>
          <h3 style={{ fontSize: 22, fontWeight: 900, color: 'var(--gold)', marginBottom: 10 }}>Proposta Enviada!</h3>
          <p style={{ color: 'var(--text-2)', fontSize: 14, lineHeight: 1.6 }}>
            Patrocínio <strong style={{ color: '#fff' }}>{PLANS.find(p => p.id === plan).name}</strong> · {event.title}<br />
            A equipa Marcianus entrará em contacto em <strong style={{ color: 'var(--gold)' }}>24 horas</strong>.
          </p>
          <div style={{ marginTop: 16, padding: '8px 16px', background: 'rgba(0,196,140,0.08)', border: '1px solid rgba(0,196,140,0.25)', borderRadius: 8, fontSize: 12, color: 'var(--success)', fontFamily: 'var(--font-mono)' }}>
            ✓ Hexis AI notificado · Alerta gerado no teu dashboard
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="ticket-modal-overlay" onClick={e => e.target === e.currentTarget && onClose()}>
      <div className="ticket-modal" style={{ maxWidth: 560 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 20 }}>
          <div>
            <div className="eyebrow" style={{ marginBottom: 4 }}>Patrocinar / Promover</div>
            <h3 style={{ fontSize: 18, fontWeight: 800 }}>{event.title}</h3>
          </div>
          <button className="icon-btn" onClick={onClose}><Icon name="x" size={16} /></button>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 10, marginBottom: 20 }}>
          {PLANS.map(p => (
            <div
              key={p.id}
              style={{
                border: `1px solid ${plan === p.id ? (p.id === 'gold' ? 'rgba(255,215,0,0.5)' : 'var(--border-purple)') : 'var(--border-1)'}`,
                borderRadius: 12, padding: 14, cursor: 'pointer', transition: '150ms',
                background: plan === p.id ? (p.id === 'gold' ? 'rgba(255,215,0,0.04)' : 'rgba(123,97,255,0.06)') : 'transparent',
              }}
              onClick={() => { SoundFX.tap(); setPlan(p.id); }}
            >
              <div style={{ fontWeight: 900, fontSize: 14, marginBottom: 4, color: p.id === 'gold' ? 'var(--gold)' : '#fff' }}>{p.name}</div>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: 16, fontWeight: 900, marginBottom: 8, color: p.id === 'gold' ? 'var(--gold)' : 'var(--purple-soft)' }}>{p.price}</div>
              {p.perks.map((k, i) => <div key={i} style={{ fontSize: 11, color: 'var(--text-3)', marginBottom: 3, display: 'flex', gap: 4 }}><span style={{ color: 'var(--success)' }}>✓</span>{k}</div>)}
            </div>
          ))}
        </div>
        <button className="btn btn-gold" style={{ width: '100%' }} onClick={handleSubmit}>
          Enviar Proposta de Patrocínio →
        </button>
      </div>
    </div>
  );
};

/* ── EVENT ROW ───────────────────────────────────────────── */
const EventRow = ({ e, expanded, onToggle, onNav }) => {
  const auth = window.useAuth ? window.useAuth() : { user: null };
  const { user } = auth;
  const [showTicket, setShowTicket] = useStateP(false);
  const [showResell, setShowResell] = useStateP(false);
  const [showAffiliate, setShowAffiliate] = useStateP(false);
  const [showSponsor, setShowSponsor] = useStateP(false);

  const logoMap = { 'Banca': 'banca', 'Tech': 'tech', 'Saúde': 'saude', 'Energia': 'energia', 'Real Estate': 'real' };
  const initials = e.title.split(' ').slice(0, 2).map(w => w[0]).join('');

  const statusLabel = e.status === 'live' ? 'Live' : e.status === 'upcoming' ? 'Confirmado' : 'Passado';
  const chipClass = e.status === 'live' ? 'chip-success chip-live' : e.status === 'upcoming' ? 'chip-blue' : 'chip-warning';

  return (
    <>
      {showTicket && <TicketModal event={e} onClose={() => setShowTicket(false)} onNav={onNav} />}
      {showResell && <ResellModal event={e} onClose={() => setShowResell(false)} />}
      {showAffiliate && <AffiliateModal event={e} user={user} onClose={() => setShowAffiliate(false)} onNav={onNav} />}
      {showSponsor && <SponsorModal event={e} onClose={() => setShowSponsor(false)} />}

      <div
        className={`event-row ${expanded ? 'expanded' : ''}`}
        onClick={() => { SoundFX.tap(); onToggle(e.id); }}
        role="button"
        tabIndex={0}
        aria-expanded={expanded}
        onKeyDown={(ev) => ev.key === 'Enter' && onToggle(e.id)}
      >
        <div className={`event-logo ${logoMap[e.sector] || ''}`}>{initials}</div>
        <div className="event-date"><div className="d">{e.d}</div><div className="m">{e.m}</div></div>
        <div className="event-info">
          <h4>{e.title}</h4>
          <div className="loc"><Icon name="map-pin" size={12} />{e.loc}</div>
          <div style={{ marginTop: 8, display: 'flex', gap: 6, flexWrap: 'wrap' }}>
            <span className="chip chip-purple">{e.sector}</span>
            <span className={`chip ${chipClass}`}>{statusLabel}</span>
          </div>
        </div>
        <div className="event-cell"><div className="k">Convidados</div><div className="v">{e.attendees}</div></div>
        <div className="event-cell"><div className="k">Pipeline est.</div><div className="v gold">{e.pipeline}</div></div>
        <div className="event-cell"><div className="k">Match</div><div className="v">{e.match}%</div></div>
        <button className="icon-btn" aria-label={expanded ? 'Colapsar' : 'Expandir'}>
          <Icon name={expanded ? 'chevron-down' : 'chevron-right'} size={16} />
        </button>

        {expanded && (
          <div className="event-detail" onClick={(ev) => ev.stopPropagation()}>
            <div className="blk">
              <h6>Briefing</h6>
              <p>{e.desc}</p>
            </div>
            <div className="blk">
              <h6>Stack</h6>
              <p>Kiosk · NFC Wristband · Hexis Live · Smart Notes</p>
            </div>
            <div className="blk">
              <h6>Bilhetes</h6>
              {e.tickets.map((t, i) => (
                <div key={i} style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, color: 'var(--text-2)', marginBottom: 4 }}>
                  <span>{t.tier}</span>
                  <span style={{ fontFamily: 'var(--font-mono)', fontWeight: 700, color: '#fff' }}>€{t.price}</span>
                </div>
              ))}
            </div>
            <div className="actions" style={{ display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center', justifyContent: 'center' }}>
              {e.status !== 'past' && (
                <button className="btn btn-gold btn-sm" onClick={() => { SoundFX.tap(); HexisBLS.track('cta_click', `buy_ticket_${e.id}`, 1); setShowTicket(true); }}>
                  <Icon name="qr-code" size={13} /> Comprar
                </button>
              )}
              <button className="btn btn-ghost btn-sm" onClick={() => { SoundFX.tap(); HexisBLS.track('cta_click', `resell_open_${e.id}`, 1); setShowResell(true); }}>
                <Icon name="refresh" size={13} /> Revender
              </button>
              <button className="btn btn-ghost btn-sm" onClick={() => { SoundFX.tap(); HexisBLS.track('cta_click', `affiliate_open_${e.id}`, 1); setShowAffiliate(true); }}>
                <Icon name="share" size={13} /> Link Afiliado
              </button>
              <button className="btn btn-ghost btn-sm" onClick={() => { SoundFX.tap(); HexisBLS.track('cta_click', `sponsor_open_${e.id}`, 1); setShowSponsor(true); }}>
                <Icon name="star" size={13} /> Patrocinar
              </button>
              <button className="btn btn-ghost btn-sm" onClick={() => { SoundFX.tap(); HexisBLS.track('cta_click', `onepager_${e.id}`, 1); downloadOnepager(e); }}>
                <Icon name="download" size={13} /> Onepager
              </button>
            </div>
          </div>
        )}
      </div>
    </>
  );
};

/* ═══════════════════════════════════════════════════════════
   INFINITE GAME WIDGET — works for ALL users (guest + auth)
   Non-deterministic questions from InfiniteGameEngine.
   Dopamine loop: streak counter, combo, fact reveal, next Q.
═══════════════════════════════════════════════════════════ */
const InfiniteGameWidget = ({ compact = false, title = 'Queue Killer™', accentColor = '#00D1FF', showNext = true }) => {
  const [step, setStep]       = useStateP('idle');
  const [q, setQ]             = useStateP(null);
  const [picked, setPicked]   = useStateP(null);
  const [result, setResult]   = useStateP(null);
  const [streak, setStreak]   = useStateP(0);
  const [combo, setCombo]     = useStateP(0);
  const [totalXP, setTotalXP] = useStateP(0);
  const [qIdx, setQIdx]       = useStateP(0);
  const isAuth = window.getAuthUser ? !!getAuthUser() : false;

  const loadQuestion = (idx) => {
    if (!window.InfiniteGameEngine) return;
    setQ(InfiniteGameEngine.getQuestion(idx));
    setPicked(null);
    setResult(null);
    setStep('quiz');
  };

  const handleStart = () => { SoundFX.tap(); if (window.HexisBLS) HexisBLS.track('cta_click', 'game_start', 1); loadQuestion(qIdx); };

  const handleAnswer = (i) => {
    if (picked !== null || !q) return;
    setPicked(i);
    const res = InfiniteGameEngine.scoreAnswer(q, i);
    setResult(res);
    if (res.correct) {
      SoundFX.success();
      const newStreak = streak + 1;
      const newCombo  = combo + 1;
      const bonus     = newCombo >= 3 ? Math.floor(res.xp * 0.5) : 0;
      const earned    = res.xp + bonus;
      setStreak(newStreak);
      setCombo(newCombo);
      setTotalXP(t => t + earned);
      if (!isAuth) {
        ToastBus.push({ kind: 'gold', icon: 'zap', title: `+${earned} XP${bonus > 0 ? ` (combo ×${newCombo}!)` : ''}`, desc: 'Cria conta para guardar os teus XP permanentemente.', duration: 4000 });
      }
      if (newStreak % 3 === 0 && window.HexisStore) {
        HexisStore.addAlert({ kind: 'success', title: `Streak de ${newStreak}!`, body: `${newStreak} respostas certas consecutivas. ${isAuth ? '' : 'Cria conta para desbloquear badges.'}` });
      }
    } else {
      SoundFX.tap();
      setCombo(0);
      if (window.HexisEngine && !HexisEngine.getProfile().isGuest) {
        HexisEngine.penalizeXP(5, `Quiz errado · ${q.category?.replace(/_/g, ' ') || 'B2B'}`);
      }
    }
  };

  const handleNext = () => {
    const nextIdx = qIdx + 1;
    setQIdx(nextIdx);
    loadQuestion(nextIdx);
  };

  const handleReset = () => { setStep('idle'); setQ(null); setPicked(null); setResult(null); };

  if (step === 'idle') {
    const col = accentColor;
    return (
      <div style={{ display: 'flex', alignItems: 'center', gap: 14, padding: compact ? '10px 14px' : '12px 16px', borderRadius: 12, background: col + '07', border: `1px solid ${col}25`, marginBottom: 20, cursor: 'pointer' }}
        onClick={handleStart}>
        <div style={{ width: 32, height: 32, borderRadius: 8, background: col + '20', display: 'flex', alignItems: 'center', justifyContent: 'center', color: col, flexShrink: 0 }}>
          <Icon name="zap" size={15} />
        </div>
        <div style={{ flex: 1 }}>
          <span style={{ fontWeight: 700, fontSize: 13, color: col }}>{title}</span>
          <span style={{ fontSize: 12, color: 'var(--text-3)', marginLeft: 10 }}>
            Quiz B2B infinito · {isAuth ? 'Ganhas XP real' : 'Ganhas XP · regista-te para guardar'} · 30s
            {streak > 0 && <span style={{ marginLeft: 8, color: '#FFD700', fontWeight: 700 }}>🔥 {streak} streak</span>}
          </span>
        </div>
        <button className="btn btn-sm" style={{ background: col + '18', border: `1px solid ${col}40`, color: col, flexShrink: 0 }}
          onClick={(e) => { e.stopPropagation(); handleStart(); }}>
          Jogar
        </button>
      </div>
    );
  }

  if (step === 'quiz' && q) {
    const col = window.InfiniteGameEngine ? InfiniteGameEngine.getCategoryColor(q.category) : accentColor;
    const catLabel = window.InfiniteGameEngine ? InfiniteGameEngine.getCategoryLabel(q.category) : 'Quiz';
    return (
      <div style={{ padding: '18px 20px', borderRadius: 14, background: col + '09', border: `1px solid ${col}30`, marginBottom: 20 }}>
        {/* Header */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 14 }}>
          <div style={{ width: 28, height: 28, borderRadius: 8, background: col + '25', display: 'flex', alignItems: 'center', justifyContent: 'center', color: col, flexShrink: 0 }}><Icon name="zap" size={14} /></div>
          <div style={{ flex: 1 }}>
            <span style={{ fontWeight: 700, fontSize: 12, color: col }}>{title}</span>
            <span style={{ fontSize: 11, color: 'var(--text-3)', marginLeft: 8 }}>{catLabel} · +{q.xp} XP</span>
          </div>
          {streak > 0 && <span style={{ fontSize: 11, fontWeight: 700, color: '#FFD700', background: 'rgba(255,215,0,0.1)', border: '1px solid rgba(255,215,0,0.3)', borderRadius: 6, padding: '2px 8px' }}>🔥 {streak}</span>}
          {combo >= 3 && <span style={{ fontSize: 11, fontWeight: 700, color: '#FF7849', background: 'rgba(255,120,73,0.1)', border: '1px solid rgba(255,120,73,0.3)', borderRadius: 6, padding: '2px 8px' }}>⚡ COMBO ×{combo}</span>}
          <button style={{ marginLeft: 4, background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-3)', padding: 4 }} onClick={handleReset}><Icon name="x" size={13} /></button>
        </div>

        {/* Question */}
        <div style={{ fontSize: 14, color: '#fff', fontWeight: 600, lineHeight: 1.6, marginBottom: 14 }}>{q.q}</div>

        {/* Options */}
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: result ? 14 : 0 }}>
          {q.opts.map((o, i) => {
            let bg = 'rgba(255,255,255,0.04)', border = 'var(--border-1)', col2 = 'var(--text-2)';
            if (picked !== null) {
              if (i === q.correct) { bg = 'rgba(0,196,140,0.16)'; border = '#00C48C90'; col2 = '#00C48C'; }
              else if (i === picked && i !== q.correct) { bg = 'rgba(255,59,92,0.12)'; border = '#FF3B5C70'; col2 = '#FF3B5C'; }
            }
            return (
              <button key={i} onClick={() => handleAnswer(i)}
                style={{ padding: '8px 14px', borderRadius: 8, background: bg, border: `1px solid ${border}`, color: col2, fontSize: 13, cursor: picked !== null ? 'default' : 'pointer', fontFamily: 'var(--font-body)', transition: 'all 0.25s' }}>
                {String.fromCharCode(65 + i)}. {o}
              </button>
            );
          })}
        </div>

        {/* Result + fact */}
        {result && (
          <div style={{ marginTop: 10, padding: '10px 14px', borderRadius: 10, background: result.correct ? 'rgba(0,196,140,0.08)' : 'rgba(255,59,92,0.06)', border: `1px solid ${result.correct ? 'rgba(0,196,140,0.3)' : 'rgba(255,59,92,0.25)'}` }}>
            <div style={{ fontSize: 13, fontWeight: 700, color: result.correct ? '#00C48C' : '#FF3B5C', marginBottom: 4 }}>
              {result.correct ? `✓ Correto! +${result.xp + (combo >= 3 ? Math.floor(result.xp * 0.5) : 0)} XP${combo >= 3 ? ' (combo bónus!)' : ''}` : '✗ Errado. Fica com o facto:'}
            </div>
            <div style={{ fontSize: 12, color: 'var(--text-2)', lineHeight: 1.5 }}>{result.fact}</div>
            {!isAuth && result.correct && (
              <div style={{ marginTop: 8, fontSize: 11, color: 'var(--purple-soft)', fontStyle: 'italic' }}>
                Cria conta grátis para guardar XP permanentemente e desbloquear missões.
              </div>
            )}
            <div style={{ marginTop: 10, display: 'flex', gap: 8, flexWrap: 'wrap' }}>
              {showNext && (
                <button className="btn btn-sm" style={{ background: col + '18', border: `1px solid ${col}40`, color: col }}
                  onClick={handleNext}>
                  Próxima pergunta →
                </button>
              )}
              {!isAuth && (
                <button className="btn btn-sm" style={{ background: 'rgba(123,97,255,0.15)', border: '1px solid rgba(123,97,255,0.4)', color: 'var(--purple-soft)' }}
                  onClick={() => { SoundFX.tap(); if (window.HexisStore) HexisStore.open(); }}>
                  Criar conta · guardar XP
                </button>
              )}
              <div style={{ marginLeft: 'auto', fontSize: 11, color: 'var(--text-3)', display: 'flex', alignItems: 'center', gap: 6 }}>
                XP sessão: <strong style={{ color: '#FFD700' }}>{totalXP + (result.correct ? result.xp : 0)}</strong>
              </div>
            </div>
          </div>
        )}
      </div>
    );
  }

  return null;
};

/* Backwards compat alias */
const QueueKillerWidget = () => <InfiniteGameWidget title="Queue Killer™" accentColor="#00D1FF" />;

/* Export so other scripts (about.jsx, pricing.jsx) can use it */
window.InfiniteGameWidget = InfiniteGameWidget;

/* ── EVENTS PAGE ─────────────────────────────────────────── */
const EventsPage = ({ onNav }) => {
  const [q, setQ] = useStateP('');
  const [sector, setSector] = useStateP('Todos');
  const [timeFilt, setTimeFilt] = useStateP('Todos');
  const [expanded, setExpanded] = useStateP(null);
  const [visibleCount, setVisibleCount] = useStateP(EVENTS_PER_PAGE);
  const [affiliateEnrolled, setAffiliateEnrolled] = useStateP(false);
  const [affiliateApplying, setAffiliateApplying] = useStateP(false);

  const sectors = ['Todos', 'Banca', 'Tech', 'Saúde', 'Energia', 'Real Estate', 'FinTech', 'Multi-sector'];
  const timeFilters = [
    { id: 'Todos',    label: 'Todos' },
    { id: 'live',     label: 'Live',    class: 'live-chip' },
    { id: 'upcoming', label: 'Futuros' },
    { id: 'past',     label: 'Passados' },
  ];

  const filtered = useMemoP(() => EVENTS.filter(e =>
    (sector === 'Todos' || e.sector === sector) &&
    (timeFilt === 'Todos' || e.status === timeFilt) &&
    (!q || e.title.toLowerCase().includes(q.toLowerCase()) || e.loc.toLowerCase().includes(q.toLowerCase()))
  ), [sector, timeFilt, q]);

  const visible = filtered.slice(0, visibleCount);
  const hasMore = filtered.length > visibleCount;

  const liveCount = EVENTS.filter(e => e.status === 'live').length;
  const upcomingCount = EVENTS.filter(e => e.status === 'upcoming').length;
  const pastCount = EVENTS.filter(e => e.status === 'past').length;

  return (
    <div className="page active">
      <section className="page-section" style={{ paddingTop: 56 }}>
        <div className="container">
          <div className="section-head">
            <div className="left">
              <span className="eyebrow">Calendário Marcianus</span>
              <h2>Experiências <span className="hl-grad">orquestradas</span>.</h2>
              <p className="section-lead">Cada evento é desenhado à medida do sector e do objetivo. Clica para abrir briefing, bilhetes e links de afiliado.</p>
            </div>
            <div className="right">
              <button className="btn btn-ghost btn-sm" onClick={() => downloadCalendar(EVENTS)}>
                <Icon name="calendar" size={14} /> Calendário
              </button>
              <button className="btn btn-gold btn-sm" onClick={() => onNav('criar-experiencia')}>
                <Icon name="plus" size={14} /> Criar Experiência
              </button>
            </div>
          </div>

          {/* Stats row */}
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12, marginBottom: 24 }}>
            {[
              { label: 'Live Agora', v: liveCount, color: 'var(--success)', chip: 'chip-success' },
              { label: 'Eventos Futuros', v: upcomingCount, color: 'var(--blue)', chip: 'chip-blue' },
              { label: 'Eventos Passados', v: pastCount, color: 'var(--text-3)', chip: '' },
            ].map((s, i) => (
              <div key={i} style={{ background: 'var(--surface-2)', border: '1px solid var(--border-1)', borderRadius: 12, padding: '14px 18px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                <span style={{ fontSize: 13, color: 'var(--text-2)' }}>{s.label}</span>
                <span style={{ fontFamily: 'var(--font-mono)', fontWeight: 900, fontSize: 20, color: s.color }}>{s.v}</span>
              </div>
            ))}
          </div>

          <div className="events-toolbar">
            {/* Search */}
            <div className="events-search">
              <Icon name="search" size={16} color="var(--text-3)" />
              <input value={q} onChange={e => { setQ(e.target.value); setVisibleCount(EVENTS_PER_PAGE); }} placeholder="Procurar por nome ou local…" aria-label="Pesquisar eventos" />
              {q && <button style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-3)', padding: 0 }} onClick={() => setQ('')}><Icon name="x" size={14} /></button>}
            </div>

            {/* Time filter */}
            <div className="filter-bar">
              <span className="lab">Período</span>
              {timeFilters.map(f => (
                <span
                  key={f.id}
                  className={`filter-chip ${f.class || ''} ${timeFilt === f.id ? 'on' : ''}`}
                  onClick={() => { SoundFX.tap(); setTimeFilt(f.id); setVisibleCount(EVENTS_PER_PAGE); }}
                >
                  {f.label}
                  {f.id === 'live' && liveCount > 0 && <span style={{ marginLeft: 4, background: 'var(--success)', borderRadius: '50%', width: 6, height: 6, display: 'inline-block', verticalAlign: 'middle', boxShadow: '0 0 6px var(--success)', animation: 'pulse 2s infinite' }} />}
                </span>
              ))}
            </div>

            {/* Sector filter */}
            <div className="filter-bar">
              <span className="lab">Sector</span>
              {sectors.map(s => (
                <span key={s} className={`filter-chip ${sector === s ? 'on' : ''}`} onClick={() => { SoundFX.tap(); setSector(s); setVisibleCount(EVENTS_PER_PAGE); }}>{s}</span>
              ))}
            </div>
          </div>

          {/* Queue Killer™ — converts idle browsing time into engagement */}
          <QueueKillerWidget />

          <div className="events-list-wrap">
            {visible.length === 0 && (
              <div className="card" style={{ textAlign: 'center', color: 'var(--text-2)', padding: '48px 24px' }}>
                <div style={{ fontSize: 36, marginBottom: 12 }}>🔍</div>
                <div style={{ fontWeight: 700, marginBottom: 8 }}>Sem eventos para este filtro.</div>
                <button className="btn btn-ghost btn-sm" style={{ marginTop: 4 }} onClick={() => { setSector('Todos'); setTimeFilt('Todos'); setQ(''); }}>Limpar filtros</button>
              </div>
            )}
            {visible.map(e => (
              <EventRow
                key={e.id}
                e={e}
                expanded={expanded === e.id}
                onToggle={(id) => setExpanded(prev => prev === id ? null : id)}
                onNav={onNav}
              />
            ))}
          </div>

          {/* Ver Mais — only shown when there are more than 50 events */}
          {hasMore && (
            <div style={{ textAlign: 'center', marginTop: 32 }}>
              <button
                className="btn btn-ghost"
                onClick={() => { SoundFX.tap(); setVisibleCount(c => c + EVENTS_PER_PAGE); }}
              >
                Ver Mais <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-3)' }}>({filtered.length - visibleCount} restantes)</span>
                <Icon name="chevron-down" size={14} />
              </button>
            </div>
          )}

          {/* Affiliate program CTA */}
          <div style={{ marginTop: 56, background: 'linear-gradient(135deg, rgba(123,97,255,0.08), rgba(0,209,255,0.04))', border: '1px solid var(--border-purple)', borderRadius: 20, padding: '32px 40px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 24, flexWrap: 'wrap' }}>
            <div>
              <div className="eyebrow" style={{ marginBottom: 8 }}>Programa de Afiliados Marcianus</div>
              <h3 style={{ fontSize: 22, fontWeight: 900, marginBottom: 8 }}>Ganha comissão em cada bilhete vendido.</h3>
              <p style={{ fontSize: 14, color: 'var(--text-2)', maxWidth: 480 }}>
                Partilha links com UUID criptografado (AES-256). Cada venda é rastreada e a comissão (12%) é creditada automaticamente na tua Wallet.
              </p>
              <div style={{ display: 'flex', gap: 16, marginTop: 14, fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-3)' }}>
                <span><span style={{ color: 'var(--gold)', fontWeight: 900 }}>12%</span> comissão</span>
                <span><span style={{ color: 'var(--success)', fontWeight: 900 }}>Instant</span> na Wallet</span>
                <span><span style={{ color: 'var(--purple-soft)', fontWeight: 900 }}>AES-256</span> UUID</span>
              </div>
            </div>
            {affiliateEnrolled ? (
              <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>
                <div style={{ background: 'rgba(0,255,136,0.12)', border: '1px solid var(--success)', borderRadius: 12, padding: '10px 20px', display: 'flex', alignItems: 'center', gap: 8 }}>
                  <Icon name="check-circle" size={16} style={{ color: 'var(--success)' }} />
                  <span style={{ color: 'var(--success)', fontWeight: 700, fontSize: 14 }}>Candidatura Enviada</span>
                </div>
                <span style={{ fontSize: 11, color: 'var(--text-3)', fontFamily: 'var(--font-mono)' }}>Hexis AI avalia em 24h · Receberás email de confirmação</span>
              </div>
            ) : (
              <button className="btn btn-gold" disabled={affiliateApplying} onClick={async () => {
                setAffiliateApplying(true);
                SoundFX.tap();
                await new Promise(r => setTimeout(r, 900));
                SoundFX.success();
                setAffiliateEnrolled(true);
                setAffiliateApplying(false);
                if (window.HexisEngine) HexisEngine.handleAction('affiliate_enroll', { source: 'events_page_cta' });
                if (window.HexisBLS) HexisBLS.track('cta_click', 'affiliate_program', 1);
                ToastBus.push({ kind: 'gold', icon: 'gift', title: 'Candidatura Recebida!', desc: 'Hexis AI vai avaliar o teu perfil nas próximas 24h. Comissão: 12% por bilhete.', duration: 6000 });
              }}>
                {affiliateApplying ? <><Icon name="loader" size={16} /> A processar…</> : <><Icon name="gift" size={16} /> Candidatar ao Programa</>}
              </button>
            )}
          </div>
        </div>
      </section>
    </div>
  );
};

// ===== CONTEÚDOS PAGE =====
const CONTENT_PAGE_SIZE = 7;
const CONTENT = [
  { id: 'c1', kind: 'Playbook', title: 'Como medir ROI de eventos B2B sem fé', tag: 'gold', mins: '12 min', dl: '2.4K downloads', img: 'assets/symbol-mark.png', summary: 'Framework de 7 passos para imputar pipeline real a cada conexão registada.', price: 'Gratuito', free: true, reactions: { likes: 412, comments: 38, shares: 124 } },
  { id: 'c2', kind: 'Case Study', title: 'Banco Invicta: €4.2M em 90 dias', tag: 'purple', mins: '8 min', dl: '1.8K leituras', img: 'assets/logo-lockup.png', summary: 'Como 240 conversas viraram 17 reuniões executivas e 4 mandates assinados.', price: 'Premium', reactions: { likes: 286, comments: 24, shares: 88 } },
  { id: 'c3', kind: 'Insight', title: 'A morte do networking espontâneo', tag: 'blue', mins: '6 min', dl: '4.1K leituras', img: 'assets/symbol-tight.png', summary: 'Por que a aleatoriedade é o pior algoritmo para um evento de alto valor.', price: 'Gratuito', free: true, reactions: { likes: 638, comments: 92, shares: 214 } },
  { id: 'c4', kind: 'Podcast', title: 'Hexis Sessions #04 · Veridian VC', tag: 'success', mins: '42 min', dl: '12K plays', img: 'assets/nfc-card.png', summary: 'Conversa com Miguel Tavares sobre matchmaking institucional em tese ESG.', price: 'Gratuito', free: true, reactions: { likes: 1240, comments: 184, shares: 412 } },
  { id: 'c5', kind: 'Webinar', title: 'CRM-first event design', tag: 'purple', mins: '38 min', dl: '900 inscritos', img: 'assets/samsung-kiosk.png', summary: 'Sessão técnica para CMOs e Heads of Growth: integração com Salesforce / HubSpot.', price: '€49', reactions: { likes: 184, comments: 12, shares: 38 } },
  { id: 'c6', kind: 'Report', title: 'State of B2B Events Portugal 2025', tag: 'gold', mins: '24 págs', dl: '6.7K downloads', img: 'assets/wristband.png', summary: 'Diagnóstico do mercado: 318 entrevistas, 12 sectores, 3 verdades inconvenientes.', price: '€129', reactions: { likes: 892, comments: 64, shares: 312 } },
  { id: 'c7', kind: 'Playbook', title: 'Hexis AI: Como configurar Matching de Precisão', tag: 'purple', mins: '15 min', dl: '1.1K downloads', img: 'assets/symbol-mark.png', summary: 'Guia técnico para configurar o algoritmo de matching vectorial no teu evento.', price: 'Premium', reactions: { likes: 344, comments: 28, shares: 98 } },
  { id: 'c8', kind: 'Insight', title: 'O ROI real de Hardware em Eventos', tag: 'gold', mins: '9 min', dl: '2.9K leituras', img: 'assets/nfc-card.png', summary: 'Dados de 46 eventos com e sem kiosk NFC. A diferença é 3.1× em pipeline qualificado.', price: 'Gratuito', free: true, reactions: { likes: 521, comments: 44, shares: 172 } },
  { id: 'c9', kind: 'Case Study', title: 'Cygnus AI Forum: 95% Match Score', tag: 'blue', mins: '10 min', dl: '1.4K leituras', img: 'assets/samsung-kiosk.png', summary: 'Como 14 CDOs e 30 founders geraram €6.1M de pipeline em 8 horas de evento.', price: 'Premium', reactions: { likes: 418, comments: 36, shares: 128 } },
  { id: 'c10', kind: 'Podcast', title: 'Hexis Sessions #08 · FinTech Founders', tag: 'success', mins: '55 min', dl: '8.4K plays', img: 'assets/wristband.png', summary: 'Painel com 4 fundadores de fintechs sobre como usar dados de evento para fundraise.', price: 'Gratuito', free: true, reactions: { likes: 956, comments: 104, shares: 328 } },
];

const showContentSummary = (content) => {
  SoundFX.tap();
  ToastBus.push({
    icon: 'newspaper',
    title: content.title,
    desc: content.summary,
  });
};

const playFeaturedContent = () => {
  SoundFX.success();
  HexisStore.open();
  ToastBus.push({ icon: 'play', title: 'Conteúdo iniciado', desc: 'Hexis AI abriu o contexto para explorar o report.' });
};

const ContentCard = ({ c }) => {
  const [liked, setLiked] = useStateP(false);
  const [likes, setLikes] = useStateP(c.reactions.likes);
  const onLike = (ev) => {
    ev.stopPropagation();
    SoundFX.tap();
    setLiked(!liked);
    setLikes(liked ? likes - 1 : likes + 1);
  };
  const handleOpen = () => {
    SoundFX.tap();
    if (window.HexisEngine) HexisEngine.handleAction('content_open', { id: c.id, kind: c.kind, free: c.free });
    if (window.HexisBLS) HexisBLS.track('content_view', c.id, c.free ? 0 : parseFloat(c.price?.replace('€','')) || 0);
    if (c.free) {
      ToastBus.push({ icon: 'newspaper', title: c.title, desc: 'A abrir conteúdo… ' + c.mins });
    } else {
      ToastBus.push({ kind: 'gold', icon: 'lock', title: 'Conteúdo Premium', desc: c.title + ' · ' + c.price + ' · Acede via Wallet ou subscrição.' });
    }
  };
  return (
    <div className="content-card" onClick={handleOpen}>
      <div className="content-card-img">
        <img src={c.img} alt={c.title} loading="lazy" />
        <span className={`chip chip-${c.tag} badge`} style={{ position: 'absolute', top: 12, left: 12 }}>{c.kind}</span>
        <span className={`content-price ${c.free ? 'free' : 'paid'}`}>{c.price}</span>
      </div>
      <div className="content-card-body">
        <h4>{c.title}</h4>
        <p>{c.summary}</p>
        <div className="content-meta-row">
          <span><Icon name="clock" size={12} /> {c.mins}</span>
          <span><Icon name="download" size={12} /> {c.dl}</span>
        </div>
        <div className="content-reactions">
          <button className={`reaction ${liked ? 'on' : ''}`} onClick={onLike} title="Gostar" aria-label={`${likes} gostos`}>
            <Icon name="heart" size={14} /> <span>{likes}</span>
          </button>
          <button className="reaction" onClick={(e) => { e.stopPropagation(); SoundFX.tap(); ToastBus.push({ icon: 'message', title: 'Comentários', desc: c.reactions.comments + ' comentários' }); }} title="Comentar">
            <Icon name="message" size={14} /> <span>{c.reactions.comments}</span>
          </button>
          <button className="reaction" onClick={(e) => { e.stopPropagation(); SoundFX.tap(); ToastBus.push({ icon: 'share', title: 'Partilhar', desc: 'Link copiado para a área de transferência' }); }} title="Partilhar">
            <Icon name="share" size={14} /> <span>{c.reactions.shares}</span>
          </button>
          <button className="reaction reaction-save" onClick={(e) => { e.stopPropagation(); SoundFX.tap(); ToastBus.push({ icon: 'bookmark', title: 'Guardado', desc: c.title + ' guardado.' }); }} title="Guardar">
            <Icon name="bookmark" size={14} />
          </button>
        </div>
      </div>
    </div>
  );
};

const ContentPage = ({ onNav }) => {
  const tabs = [
    { id: 'todos', l: 'Todos', n: CONTENT.length },
    { id: 'Playbook', l: 'Playbooks' },
    { id: 'Case Study', l: 'Cases' },
    { id: 'Insight', l: 'Insights' },
    { id: 'Podcast', l: 'Podcasts' },
    { id: 'Webinar', l: 'Webinars' },
    { id: 'Report', l: 'Reports' },
  ];
  const [tab, setTab] = useStateP('todos');
  const [timeSort, setTimeSort] = useStateP('recent');
  const [showAll, setShowAll] = useStateP(false);

  const list = useMemoP(() => {
    let items = tab === 'todos' ? CONTENT : CONTENT.filter(c => c.kind === tab);
    if (timeSort === 'popular') items = [...items].sort((a, b) => b.reactions.likes - a.reactions.likes);
    return items;
  }, [tab, timeSort]);

  const visible = showAll ? list : list.slice(0, CONTENT_PAGE_SIZE);
  const hasMore = list.length > CONTENT_PAGE_SIZE && !showAll;

  const carouselRef = useRefP(null);
  const scroll = (dir) => { if (carouselRef.current) carouselRef.current.scrollBy({ left: dir * 300, behavior: 'smooth' }); };

  return (
    <div className="page active">
      <section className="page-section" style={{ paddingTop: 56 }}>
        <div className="container">
          <div className="section-head">
            <div className="left">
              <span className="eyebrow">Conteúdos</span>
              <h2>Inteligência <span className="hl">aplicada</span> a eventos.</h2>
              <p className="section-lead">Frameworks, casos reais e dados do mercado. Cada peça é auditável e directa.</p>
            </div>
          </div>

          {/* Hero feature */}
          <div className="content-hero">
            <div>
              <span className="hl-tag"><Icon name="star" size={12} /> Em destaque</span>
              <h3>State of B2B Events Portugal 2025</h3>
              <p>Diagnóstico definitivo do mercado: 318 entrevistas com C-levels, análise de 142 eventos privados e 12 sectores cruzados. O relatório que vai mudar a forma como o teu CFO olha para a tua linha de eventos.</p>
              <div className="meta">
                <span><Icon name="newspaper" size={11} /> 24 págs</span>
                <span><Icon name="download" size={11} /> 6.7K dl</span>
                <span><Icon name="calendar" size={11} /> Mar 2025</span>
              </div>
              <div style={{ display: 'flex', gap: 10, marginTop: 18, flexWrap: 'wrap' }}>
                <button className="btn btn-gold btn-sm" onClick={() => { SoundFX.success(); fireConfetti({ x: window.innerWidth / 2, y: 320 }); ToastBus.push({ kind: 'gold', icon: 'download', title: 'Report a transferir', desc: 'PDF · 6.4MB' }); }}>
                  <Icon name="download" size={14} /> Descarregar PDF
                </button>
                <button className="btn btn-ghost btn-sm" onClick={() => showContentSummary(CONTENT[5])}>Ver sumário</button>
              </div>
            </div>
            <div className="content-hero-img">
              <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(135deg, #5D3FD3, #7B61FF)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <img src="assets/symbol-mark.png" alt="" style={{ width: '50%', opacity: 0.7 }} loading="lazy" />
              </div>
              <div className="play-btn" role="button" tabIndex={0}
                onClick={playFeaturedContent}
                onKeyDown={(e) => (e.key === 'Enter' || e.key === ' ') && playFeaturedContent()}>
                <Icon name="play" size={22} />
              </div>
            </div>
          </div>

          {/* Tabs + sort */}
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', flexWrap: 'wrap', gap: 12 }}>
            <div className="content-tabs">
              {tabs.map(t => (
                <div key={t.id} className={`content-tab ${tab === t.id ? 'active' : ''}`} onClick={() => { SoundFX.tap(); setTab(t.id); setShowAll(false); }}>
                  {t.l} <span className="num">{t.id === 'todos' ? CONTENT.length : CONTENT.filter(c => c.kind === t.id).length}</span>
                </div>
              ))}
            </div>
            <div style={{ display: 'flex', gap: 6 }}>
              {[{ id: 'recent', l: 'Recentes' }, { id: 'popular', l: 'Populares' }].map(s => (
                <span key={s.id} className={`filter-chip ${timeSort === s.id ? 'on' : ''}`} onClick={() => { SoundFX.tap(); setTimeSort(s.id); }}>
                  {s.l}
                </span>
              ))}
            </div>
          </div>

          {/* Infinite game between content tabs and grid */}
          <InfiniteGameWidget title="Knowledge Arena™" accentColor="#FFD700" compact />

          {/* Grid — max 7 cards, then Ver Mais */}
          <div className="content-grid" style={{ marginTop: 24 }}>
            {visible.map(c => <ContentCard key={c.id} c={c} />)}
          </div>

          {/* Ver Mais after 7 */}
          {hasMore && (
            <div style={{ textAlign: 'center', marginTop: 24, marginBottom: 8 }}>
              <button className="btn btn-ghost" onClick={() => { SoundFX.tap(); setShowAll(true); }}>
                Ver Mais <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-3)' }}>({list.length - CONTENT_PAGE_SIZE} conteúdos)</span>
                <Icon name="chevron-down" size={14} />
              </button>
            </div>
          )}

          {/* Carousel — most read */}
          <h3 style={{ marginTop: 56, marginBottom: 18, fontSize: 20 }}>Mais lidos esta semana</h3>
          <div className="carousel-wrap">
            <button className="carousel-arrow l" onClick={() => scroll(-1)} aria-label="Anterior"><Icon name="chevron-left" size={16} /></button>
            <div className="carousel-track" ref={carouselRef}>
              {CONTENT.map(c => (
                <div key={'cr-' + c.id} className="carousel-card"><ContentCard c={c} /></div>
              ))}
            </div>
            <button className="carousel-arrow r" onClick={() => scroll(1)} aria-label="Próximo"><Icon name="chevron-right" size={16} /></button>
          </div>
        </div>
      </section>
    </div>
  );
};

window.HomePage = HomePage;
window.EventsPage = EventsPage;
window.ContentPage = ContentPage;
