// Kelappa Landing — main page composition const { useState: useStateL } = React; // ── Counter (abacus.jasoncameron.dev — no-auth pageview counter) ─ const COUNTER_NS = 'kelappa-2026'; const counterHit = (key) => { const url = `https://abacus.jasoncameron.dev/hit/${COUNTER_NS}/${key}`; if (typeof navigator !== 'undefined' && navigator.sendBeacon) { navigator.sendBeacon(url); } else { fetch(url, { method: 'POST', keepalive: true }).catch(() => {}); } }; // ── Responsive: <768px counts as mobile ───────────────────── function useIsMobile(bp = 768) { const [m, setM] = React.useState( typeof window !== 'undefined' ? window.innerWidth < bp : false ); React.useEffect(() => { const onR = () => setM(window.innerWidth < bp); window.addEventListener('resize', onR); return () => window.removeEventListener('resize', onR); }, [bp]); return m; } // ── Reusable: smile underline under any inline span ──────── function SmileSpan({ children, color, height = 18 }) { return ( {children} ); } // ── Section shell ───────────────────────────────────────── function Sec({ bg, color, children, pad = '120px 40px', padMobile = '72px 20px', id }) { const isMobile = useIsMobile(); return (
{children}
); } function Eyebrow({ children, color }) { return (
{children}
); } function H({ children, size = 72, color, weight = 700, ls = '-0.035em', lh = 1.02, style = {} }) { const minSize = Math.max(28, Math.round(size * 0.5)); const responsiveSize = `clamp(${minSize}px, 6.5vw, ${size}px)`; return (

{children}

); } // ── NAV ──────────────────────────────────────────────────── function Nav({ t, copy, lang, setLang }) { const [scrolled, setScrolled] = React.useState(false); const isMobile = useIsMobile(); React.useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 24); window.addEventListener('scroll', onScroll); return () => window.removeEventListener('scroll', onScroll); }, []); return ( ); } // ── HERO ─────────────────────────────────────────────────── function Hero({ t, copy }) { const isMobile = useIsMobile(); const apps = [ { bg: KELAPPA_BROWN, mark: t.cream, dots: KELAPPA_BROWN, name: 'CCV', sub: 'macOS · DMG', href: 'https://kelappa.com/ccv/', track: 'dl-ccv' }, { bg: t.coral, mark: t.cream, dots: t.coral, name: 'VText', sub: 'macOS · DMG' }, { bg: t.lagoon, mark: KELAPPA_BROWN, dots: t.cream, name: 'FloFi', sub: 'iOS · web', href: 'https://flofi.online', track: 'dl-flofi' }, { bg: t.saffron, mark: KELAPPA_BROWN, dots: t.cream, name: 'En-Ru Switcher', sub: 'macOS · DMG', href: '/switcher/EN-RU-Switcher.dmg', track: 'dl-switcher' }, { bg: t.palm, mark: t.cream, dots: KELAPPA_BROWN, name: 'Teleprompter', sub: 'web', href: 'https://www.free-teleprompter.online', track: 'dl-teleprompter' }, { bg: t.ink, mark: t.coral, dots: t.cream, name: 'Telesufler', sub: 'macOS · DMG', href: '/teleprompter/Telesufler.dmg', track: 'dl-telesufler' }, ]; return ( {/* gradient blobs */}

{copy.hero.h_pre}{' '} {copy.hero.h_hl}{copy.hero.h_post}

{copy.hero.sub}

{copy.hero.cta_primary} → {copy.hero.cta_secondary}
{/* app strip */}
{copy.hero.strip_label}
{apps.map((a) => { const Tag = a.href ? 'a' : 'div'; const linkProps = a.href ? { href: a.href, target: '_blank', rel: 'noopener noreferrer', onClick: () => a.track && counterHit(a.track) } : {}; return (
{a.name}
{a.sub}
); })}
); } // ── MANIFESTO ───────────────────────────────────────────── function Manifesto({ t, copy }) { const isMobile = useIsMobile(); return (
{copy.manifesto.eyebrow} {copy.manifesto.h}

{copy.manifesto.p1}

{copy.manifesto.p2}

); } // ── PRINCIPLES ──────────────────────────────────────────── function Principles({ t, copy }) { const isMobile = useIsMobile(); return (
{copy.principles.eyebrow} {copy.principles.h}
{copy.principles.items.map((p, i) => (
{p.n}
{p.title}
{p.body}
))}
); } // ── APPS ────────────────────────────────────────────────── function AppsSection({ t, copy }) { const isMobile = useIsMobile(); const mocks = [CCVMock, VTextMock, FloFiMock, SwitcherMock, TeleprompterMock, TelesuflerMock]; const bgs = ['husk', 'coral', 'lagoon', 'saffron', 'palm', 'ink']; const marks = ['cream', 'cream', 'brown', 'brown', 'cream', 'coral']; const dots = ['husk', 'coral', 'cream', 'cream', 'brown', 'cream']; const resolve = (key) => key === 'brown' ? KELAPPA_BROWN : t[key]; return (
{copy.apps.eyebrow} {copy.apps.h}

{copy.apps.sub}

{copy.apps.items.map((a, i) => { const Mock = mocks[i]; const reverse = !isMobile && i % 2 === 1; return (
{a.name}
{a.sub}
{a.tagline}

{a.desc}

{a.platforms.map((p) => ( {p} ))}
{a.status}
{copy.apps.cta} →
); })}
); } // ── STUDIO ──────────────────────────────────────────────── function Studio({ t, copy }) { const isMobile = useIsMobile(); return (
{/* photo placeholder */}
Studio photo · placeholder
{copy.studio.eyebrow} {copy.studio.h}

{copy.studio.p}

{copy.studio.p2}

); } // ── CTA ─────────────────────────────────────────────────── function CtaSection({ t, copy }) { return (
{copy.cta.eyebrow}

{copy.cta.h_pre}{' '} {copy.cta.h_hl}{copy.cta.h_post}

{copy.cta.sub}

{copy.cta.btn} →
); } // ── FOOTER ──────────────────────────────────────────────── function Footer({ t, copy }) { const isMobile = useIsMobile(); return (

{copy.footer.tag}

{copy.footer.cols.map((col) => (
{col.h}
    {col.l.map((item) => (
  • {item}
  • ))}
))}
{copy.footer.legal} v1.0
); } // ── PAGE ROOT ───────────────────────────────────────────── function Landing({ t }) { const [lang, setLang] = React.useState('en'); const copy = COPY[lang]; React.useEffect(() => { counterHit('visits'); }, []); return (
); } Object.assign(window, { Landing, SmileSpan });