/* 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 (
Como funciona
Três fases. Zero fricção .
Não é um evento decorado. É um sistema operacional para encontros de alto valor — calibrado, medido e auditável.
{steps.map((s, i) => (
))}
);
};
// ===== 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 (
Stack Operacional
Hardware + Hexis AI . Sincronizados.
A camada física e o motor de inteligência operam como uma única plataforma. Sem zaps, sem CSVs.
{items.map((it, i) => (
{
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');
}
}}>
{it.tag}
{it.price}
))}
);
};
// ===== 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 (
Resultados auditáveis
Métrica é o decisor .
{cases.map((c, i) => (
{c.sector}
{c.client}
{c.delta}
))}
);
};
// ===== HOMEPAGE wrapper =====
const HomePage = ({ onNav }) => (
);
// ===== 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 (
e.target === e.currentTarget && onClose()}>
{step === 'success' ? (
🎟️
Bilhete Confirmado!
{qty}× {selected.tier} · {event.title}
€{total.toLocaleString('pt-PT')}
ID: MRC-{genUUID().substring(0, 8).toUpperCase()}
Fechar
{ onClose(); onNav('dashboard'); }}>Ver no Dashboard →
) : (
<>
Comprar Bilhete
{event.title}
{event.loc}
{event.tickets.map((t, i) => (
setSelected(t)}
>
{t.tier}
€{t.price}
{t.tier === 'VIP' ? 'Lounge + Hexis Priority' : t.tier === 'Executive' ? 'Executive Floor + Kit NFC' : 'Acesso geral + NFC Band'}
))}
Quantidade
setQty(q => Math.max(1, q - 1))}>
{qty}
setQty(q => Math.min(10, q + 1))}>
Total
€{total.toLocaleString('pt-PT')}
{step === 'confirm' ? 'A processar…' : user ? `Comprar · €${total.toLocaleString('pt-PT')}` : 'Entrar para comprar →'}
{!user && (
Precisas de conta · { onClose(); onNav('entrar'); }}>Criar grátis →
)}
>
)}
);
};
/* ── 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 (
e.target === e.currentTarget && onClose()}>
🔄
Bilhete em revenda!
O teu bilhete está listado no Marketplace Marcianus. Será reemitido com novo UUID quando vendido — o original é invalidado automaticamente.
Comissão Marcianus: 5% · Tu recebes: €{Math.round(price * 0.95).toLocaleString('pt-PT')}
Concluído
);
}
return (
e.target === e.currentTarget && onClose()}>
Revender Bilhete
O bilhete será listado no Marketplace P2P Marcianus . Quando vendido, o UUID é reemitido e o original invalidado (anti-fraude).
Preço de revenda (€)
setPrice(Math.max(1, +e.target.value))}
min={1}
max={event.tickets[event.tickets.length - 1].price * 2}
/>
Comissão plataforma: 5% · Recebes: €{Math.round(price * 0.95).toLocaleString('pt-PT')}
Listar para revenda →
);
};
/* ── 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 (
e.target === e.currentTarget && onClose()}>
Programa de Afiliados
Link de Afiliado
{!enrolled && !user ? (
🔒
Para aceder ao programa de afiliados, precisas de criar conta e ser aprovado pelo Hexis AI.
{ onClose(); onNav('entrar'); }}>Criar Conta →
) : !enrolled ? (
Como funciona
{['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) => (
✓ {s}
))}
{applying ? 'A processar pedido…' : 'Candidatar ao Programa →'}
) : (
Aprovado no Programa de Afiliados · Hexis AI
Teu link de afiliado (UUID criptografado incluído):
{copied ? <> Copiado> : <> Copiar>}
Comissão: 12% por venda · Pago na Wallet Marcianus · Rastreado via UUID
)}
);
};
/* ── 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 (
🚀
Proposta Enviada!
Patrocínio {PLANS.find(p => p.id === plan).name} · {event.title}
A equipa Marcianus entrará em contacto em 24 horas .
✓ Hexis AI notificado · Alerta gerado no teu dashboard
);
}
return (
e.target === e.currentTarget && onClose()}>
Patrocinar / Promover
{event.title}
{PLANS.map(p => (
{ SoundFX.tap(); setPlan(p.id); }}
>
{p.name}
{p.price}
{p.perks.map((k, i) =>
✓ {k}
)}
))}
Enviar Proposta de Patrocínio →
);
};
/* ── 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 && setShowTicket(false)} onNav={onNav} />}
{showResell && setShowResell(false)} />}
{showAffiliate && setShowAffiliate(false)} onNav={onNav} />}
{showSponsor && setShowSponsor(false)} />}
{ SoundFX.tap(); onToggle(e.id); }}
role="button"
tabIndex={0}
aria-expanded={expanded}
onKeyDown={(ev) => ev.key === 'Enter' && onToggle(e.id)}
>
{initials}
{e.title}
{e.loc}
{e.sector}
{statusLabel}
Pipeline est.
{e.pipeline}
{expanded && (
ev.stopPropagation()}>
Stack
Kiosk · NFC Wristband · Hexis Live · Smart Notes
Bilhetes
{e.tickets.map((t, i) => (
{t.tier}
€{t.price}
))}
{e.status !== 'past' && (
{ SoundFX.tap(); HexisBLS.track('cta_click', `buy_ticket_${e.id}`, 1); setShowTicket(true); }}>
Comprar
)}
{ SoundFX.tap(); HexisBLS.track('cta_click', `resell_open_${e.id}`, 1); setShowResell(true); }}>
Revender
{ SoundFX.tap(); HexisBLS.track('cta_click', `affiliate_open_${e.id}`, 1); setShowAffiliate(true); }}>
Link Afiliado
{ SoundFX.tap(); HexisBLS.track('cta_click', `sponsor_open_${e.id}`, 1); setShowSponsor(true); }}>
Patrocinar
{ SoundFX.tap(); HexisBLS.track('cta_click', `onepager_${e.id}`, 1); downloadOnepager(e); }}>
Onepager
)}
>
);
};
/* ═══════════════════════════════════════════════════════════
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 (
{title}
Quiz B2B infinito · {isAuth ? 'Ganhas XP real' : 'Ganhas XP · regista-te para guardar'} · 30s
{streak > 0 && 🔥 {streak} streak }
{ e.stopPropagation(); handleStart(); }}>
Jogar
);
}
if (step === 'quiz' && q) {
const col = window.InfiniteGameEngine ? InfiniteGameEngine.getCategoryColor(q.category) : accentColor;
const catLabel = window.InfiniteGameEngine ? InfiniteGameEngine.getCategoryLabel(q.category) : 'Quiz';
return (
{/* Header */}
{title}
{catLabel} · +{q.xp} XP
{streak > 0 &&
🔥 {streak} }
{combo >= 3 &&
⚡ COMBO ×{combo} }
{/* Question */}
{q.q}
{/* Options */}
{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 (
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}
);
})}
{/* Result + fact */}
{result && (
{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:'}
{result.fact}
{!isAuth && result.correct && (
Cria conta grátis para guardar XP permanentemente e desbloquear missões.
)}
{showNext && (
Próxima pergunta →
)}
{!isAuth && (
{ SoundFX.tap(); if (window.HexisStore) HexisStore.open(); }}>
Criar conta · guardar XP
)}
XP sessão: {totalXP + (result.correct ? result.xp : 0)}
)}
);
}
return null;
};
/* Backwards compat alias */
const QueueKillerWidget = () => ;
/* 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 (
Calendário Marcianus
Experiências orquestradas .
Cada evento é desenhado à medida do sector e do objetivo. Clica para abrir briefing, bilhetes e links de afiliado.
downloadCalendar(EVENTS)}>
Calendário
onNav('criar-experiencia')}>
Criar Experiência
{/* Stats row */}
{[
{ 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) => (
{s.label}
{s.v}
))}
{/* Search */}
{ setQ(e.target.value); setVisibleCount(EVENTS_PER_PAGE); }} placeholder="Procurar por nome ou local…" aria-label="Pesquisar eventos" />
{q && setQ('')}> }
{/* Time filter */}
Período
{timeFilters.map(f => (
{ SoundFX.tap(); setTimeFilt(f.id); setVisibleCount(EVENTS_PER_PAGE); }}
>
{f.label}
{f.id === 'live' && liveCount > 0 && }
))}
{/* Sector filter */}
Sector
{sectors.map(s => (
{ SoundFX.tap(); setSector(s); setVisibleCount(EVENTS_PER_PAGE); }}>{s}
))}
{/* Queue Killer™ — converts idle browsing time into engagement */}
{visible.length === 0 && (
🔍
Sem eventos para este filtro.
{ setSector('Todos'); setTimeFilt('Todos'); setQ(''); }}>Limpar filtros
)}
{visible.map(e => (
setExpanded(prev => prev === id ? null : id)}
onNav={onNav}
/>
))}
{/* Ver Mais — only shown when there are more than 50 events */}
{hasMore && (
{ SoundFX.tap(); setVisibleCount(c => c + EVENTS_PER_PAGE); }}
>
Ver Mais ({filtered.length - visibleCount} restantes)
)}
{/* Affiliate program CTA */}
Programa de Afiliados Marcianus
Ganha comissão em cada bilhete vendido.
Partilha links com UUID criptografado (AES-256). Cada venda é rastreada e a comissão (12%) é creditada automaticamente na tua Wallet.
12% comissão
Instant na Wallet
AES-256 UUID
{affiliateEnrolled ? (
Candidatura Enviada
Hexis AI avalia em 24h · Receberás email de confirmação
) : (
{
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 ? <> A processar…> : <> Candidatar ao Programa>}
)}
);
};
// ===== 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 (
{c.kind}
{c.price}
{c.title}
{c.summary}
{c.mins}
{c.dl}
{likes}
{ e.stopPropagation(); SoundFX.tap(); ToastBus.push({ icon: 'message', title: 'Comentários', desc: c.reactions.comments + ' comentários' }); }} title="Comentar">
{c.reactions.comments}
{ e.stopPropagation(); SoundFX.tap(); ToastBus.push({ icon: 'share', title: 'Partilhar', desc: 'Link copiado para a área de transferência' }); }} title="Partilhar">
{c.reactions.shares}
{ e.stopPropagation(); SoundFX.tap(); ToastBus.push({ icon: 'bookmark', title: 'Guardado', desc: c.title + ' guardado.' }); }} title="Guardar">
);
};
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 (
Conteúdos
Inteligência aplicada a eventos.
Frameworks, casos reais e dados do mercado. Cada peça é auditável e directa.
{/* Hero feature */}
Em destaque
State of B2B Events Portugal 2025
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.
24 págs
6.7K dl
Mar 2025
{ SoundFX.success(); fireConfetti({ x: window.innerWidth / 2, y: 320 }); ToastBus.push({ kind: 'gold', icon: 'download', title: 'Report a transferir', desc: 'PDF · 6.4MB' }); }}>
Descarregar PDF
showContentSummary(CONTENT[5])}>Ver sumário
(e.key === 'Enter' || e.key === ' ') && playFeaturedContent()}>
{/* Tabs + sort */}
{tabs.map(t => (
{ SoundFX.tap(); setTab(t.id); setShowAll(false); }}>
{t.l} {t.id === 'todos' ? CONTENT.length : CONTENT.filter(c => c.kind === t.id).length}
))}
{[{ id: 'recent', l: 'Recentes' }, { id: 'popular', l: 'Populares' }].map(s => (
{ SoundFX.tap(); setTimeSort(s.id); }}>
{s.l}
))}
{/* Infinite game between content tabs and grid */}
{/* Grid — max 7 cards, then Ver Mais */}
{visible.map(c => )}
{/* Ver Mais after 7 */}
{hasMore && (
{ SoundFX.tap(); setShowAll(true); }}>
Ver Mais ({list.length - CONTENT_PAGE_SIZE} conteúdos)
)}
{/* Carousel — most read */}
Mais lidos esta semana
scroll(-1)} aria-label="Anterior">
scroll(1)} aria-label="Próximo">
);
};
window.HomePage = HomePage;
window.EventsPage = EventsPage;
window.ContentPage = ContentPage;