// Sections of the landing page const { useState, useEffect, useRef } = React; const M = window.Mockups; const I = window.Icons; // Reveal hook function useReveal() { const ref = useRef(null); useEffect(() => { const el = ref.current; if (!el) return; // Immediate check: if element is already in viewport, reveal now const rect = el.getBoundingClientRect(); if (rect.top < window.innerHeight && rect.bottom > 0) { el.classList.add('visible'); return; } const obs = new IntersectionObserver( (entries) => { entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add('visible'); obs.unobserve(e.target); } }); }, { threshold: 0.05, rootMargin: '0px 0px -10% 0px' } ); obs.observe(el); // Safety fallback: force visible after 1.5s no matter what const fallback = setTimeout(() => { el.classList.add('visible'); obs.disconnect(); }, 1500); return () => { obs.disconnect(); clearTimeout(fallback); }; }, []); return ref; } const Reveal = ({ children, delay = 0, className = "" }) => { const ref = useReveal(); return (
{children}
); }; // Logo const Logo = ({ light = false }) => (
Ecclesia Hub Ecclesia Hub
); // Header const Header = ({ lang, setLang, t }) => { const [scrolled, setScrolled] = useState(false); const [langOpen, setLangOpen] = useState(false); const [mobileOpen, setMobileOpen] = useState(false); useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 20); window.addEventListener('scroll', onScroll); return () => window.removeEventListener('scroll', onScroll); }, []); const current = window.LANGS.find(l => l.code === lang); return (
{/* Lang selector */}
{langOpen && (
{window.LANGS.map(l => ( ))}
)}
{mobileOpen && (
{[t.nav.features, t.nav.how, t.nav.pricing, t.nav.faq].map((l, i) => ( setMobileOpen(false)} className="block py-2.5 text-slate-700 font-medium">{l} ))}
)}
); }; // Hero const Hero = ({ t }) => (
{t.hero.eyebrow}

{t.hero.headline}

{t.hero.sub}

{t.hero.badges.map((b, i) => (
{[, , ][i]} {b}
))}
); // Trust Bar const TrustBar = ({ t }) => { const icons = [I.Building, I.Users, I.Shield, I.Cloud, I.Lock, I.RefreshCw]; return (
{t.trust.title}
{t.trust.items.map((item, i) => { const Ic = icons[i]; return (
{item} {i < t.trust.items.length - 1 && }
); })}
); }; // Features (3 pillars) const Features = ({ t }) => { const icons = [I.Globe, I.Users, I.LayoutDashboard]; const colors = ['blue', 'amber', 'emerald']; return (
3 Pilares

{t.features.title}

{t.features.sub}

{t.features.items.map((f, i) => { const Ic = icons[i]; const c = colors[i]; return (
0{i + 1}

{f.title}

{f.desc}

); })}
); }; // Benefits const Benefits = ({ t }) => { const icons = [I.Clock, I.DollarSign, I.BookOpen, I.BarChart, I.Palette, I.Cloud]; return (
Por que Ecclesia Hub

{t.benefits.title}

{t.benefits.sub}

{t.benefits.items.map((b, i) => { const Ic = icons[i]; return (

{b.title}

{b.desc}

); })}
); }; // How it works const HowItWorks = ({ t }) => (
Como Funciona

{t.how.title}

{t.how.sub}

{t.how.steps.map((s, i) => (
{i + 1}

{s.title}

{s.desc}

))}
); // Showcase (zigzag) const Showcase = ({ t }) => { const mockups = [M.FinancialMockup, M.CheckinMockup, M.EADMockup]; const icons = [I.DollarSign, I.QrCode, I.BookOpen]; const accents = ['blue', 'amber', 'emerald']; return (
Recursos

{t.showcase.title}

{t.showcase.sub}

{t.showcase.items.map((item, i) => { const Mock = mockups[i]; const Ic = icons[i]; const c = accents[i]; const reverse = i % 2 === 1; return (
Recurso {i + 1}

{item.title}

{item.desc}

); })}
); }; // Testimonials const Testimonials = ({ t }) => { const gradients = ['from-blue-500 to-indigo-600', 'from-amber-500 to-orange-600', 'from-emerald-500 to-teal-600']; return (
Prova Social

{t.testimonials.title}

{t.testimonials.sub}

{t.testimonials.items.map((tst, i) => { const initials = tst.name.split(' ').slice(-2).map(w => w[0]).join(''); return (
{[...Array(5)].map((_, j) => )}
"{tst.quote}"
{initials}
{tst.name}
{tst.role} · {tst.church}
{tst.size}
); })}
); }; // Pricing const Pricing = ({ t, currency }) => { const [yearly, setYearly] = useState(true); const p = window.PRICING[currency.code]; const fmt = (v) => { if (currency.code === 'BRL') return `${currency.symbol} ${v}`; if (currency.code === 'EUR') return `${currency.symbol} ${v}`; if (currency.code === 'GBP') return `${currency.symbol}${v}`; return `${currency.symbol}${v}`; }; return (
Preços

{t.pricing.title}

{t.pricing.sub}

{/* Monthly card */}
{t.pricing.monthlyPlan.label}

{t.pricing.monthlyPlan.name}

{fmt(p.monthly)} {t.pricing.monthlyPlan.period}
 
    {t.pricing.features.map((f, i) => (
  • {f}
  • ))}
{/* Yearly card */}
{t.pricing.bestValue}
{t.pricing.yearlyPlan.label}

{t.pricing.yearlyPlan.name}

{fmt(p.yearly)} {t.pricing.yearlyPlan.period}
≈ {fmt(p.perMonthYearly)}/mês · {t.pricing.yearlyPlan.save} {fmt(p.savings)}
    {t.pricing.yearlyExtras.map((f, i) => (
  • 0 ? 'font-semibold' : ''}>{f}
  • ))} {t.pricing.features.slice(0, -1).map((f, i) => (
  • {f}
  • ))}
{[I.Lock, I.RefreshCw, I.Check].map((Ic, i) => (
{t.pricing.seals[i]}
))}
); }; // FAQ const FAQ = ({ t }) => { const [open, setOpen] = useState(0); return (
FAQ

{t.faq.title}

{t.faq.sub}

{t.faq.items.map((item, i) => (
{item.a}
))}
); }; // Final CTA const FinalCTA = ({ t }) => (
Junte-se à comunidade

{t.finalCta.title}

{t.finalCta.sub}

{t.finalCta.support}

); // Footer const Footer = ({ t }) => { const socials = [I.Instagram, I.Youtube, I.Facebook]; return ( ); }; window.Sections = { Header, Hero, TrustBar, Features, Benefits, HowItWorks, Showcase, Testimonials, Pricing, FAQ, FinalCTA, Footer };