/* Helptyfy — marketing landing page (signed-out home).
   Composes DS primitives + shared widgets. window.Icons for iconography. */
const { useState, useEffect } = React;
const DS = window.HelptyDesignSystem_56c945;
const { Button, Logo, Card, Badge, GradientText, Tag, Input } = DS;
const { Icons, AIPanel, Customizer, LanguageMenu } = window;
const { useTweaks, TweaksPanel, TweakSection, TweakRadio, TweakColor, TweakSlider } = window;
const GO = { join: '/login', app: '/app' };
const go = (p) => { window.location.href = p; };

/* ---- Tweakable “feel” controls — each reshapes the whole page, not one pixel ---- */
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "atmosphere": "charged",
  "dotDensity": "balanced",
  "dotSize": 1.1,
  "mood": ["#8b5cf6", "#22d3ee", "#6d28d9"],
  "material": "glass"
}/*EDITMODE-END*/;
const MOOD_SWATCHES = [
  ["#8b5cf6", "#22d3ee", "#6d28d9"],  // Violet · the default electric dusk
  ["#06b6d4", "#818cf8", "#0e7490"],  // Cyan · cool & technical
  ["#f59e0b", "#fb7185", "#b45309"],  // Amber · warm & human
  ["#10b981", "#22d3ee", "#047857"],  // Emerald · fresh & calm
];
const MATERIAL_TOKENS = {
  glass:   null, // fall back to the design-system glass tokens
  solid:   { '--surface-glass': '#14141c', '--surface-glass-strong': '#1b1b27', '--surface-glass-hover': '#22222f', '--glass-blur': '0px', '--border-glass': 'rgba(255,255,255,0.08)' },
  outline: { '--surface-glass': 'transparent', '--surface-glass-strong': 'rgba(255,255,255,0.025)', '--surface-glass-hover': 'rgba(255,255,255,0.05)', '--glass-blur': '0px', '--border-glass': 'rgba(255,255,255,0.20)' },
};

/* ---- i18n: the strings that drive the page, in all 5 launch languages ---- */
const T = {
  EN: {
    how:'How it works', pricing:'Pricing', api:'API', business:'For business', signin:'Sign in', join:'Join free',
    badge:'AI-powered matching', h1a:'Find the person your', kw:'business', h1b:'is missing.',
    sub:'Tell us what you\u2019ve got and what you need. Our AI finds the people who complete the picture \u2014 and you only pay when it\u2019s mutual.',
    cta1:'Find your match', cta2:'See how it works', free:'Free to join \u00b7 free to browse \u00b7 pay only on a mutual yes',
    stepK:'How it works', stepT:'Match. Connect. Build together.',
    s1t:'Match', s1d:'AI reads both sides and surfaces complementary people, each with a one-line reason you fit.',
    s2t:'Connect', s2d:'Both say yes? A small connect fee unlocks chat. Nobody pays for a ghost.',
    s3t:'Work together', s3d:'Message and get it done \u2014 no commissions, no middlemen, no subscriptions.',
    s4t:'Team up', s4d:'Found people building something similar? Form a squad. Team Up turns matches into a group \u2014 several people, one shared project, moving as one.',
    priceK:'Honest pricing', priceT:'Free to join. You pay only on a mutual yes.',
    connectN:'Connect fee', connectD:'Charged once both sides agree, within 72 hours \u2014 otherwise auto-released.', perSide:'per side',
    ghostN:'The ghost guarantee', ghostD:'Your \u20ac9 is only held, never taken, until the other side pays too. If they don\u2019t within 72h, it\u2019s released \u2014 automatically.',
    apiK:'Build on Helptyfy', apiT:'An API for your AI agents.', apiSub:'Generate keys that let agents act on your account within scopes you choose. $20/mo per key, revocable anytime.',
    scopeView:'View', scopeEdit:'Edit', scopeEvery:'Everything', apiCta:'Read the docs',
    b2bK:'For business', b2bT:'Where businesses connect to work on projects.', b2bSub:'Helptyfy is built for businesses to find each other, close deals, and grow \u2014 directly, with no commissions and no middlemen.',
    b2b1t:'Do business, make money', b2b1d:'Find businesses ready to buy, sell, and refer. Offer your services or hire others \u2014 deals happen directly and you keep what you earn.',
    b2b2t:'Partner up, not pay up', b2b2d:'No budget? Trade value instead. Connect to build something together and share the upside \u2014 partnership over payment.',
    bizName:'DigitalRepeal', bizRole:'Automation, web & operations studio', bizPostTag:'Open for business', bizPostBody:'We\u2019re open to doing business \u2014 paid projects and partnership deals alike. Work with us on a brief, or pitch a partnership where we build together and share the upside instead of trading invoices.', bizOffer:'Offering', bizOpen:'Open to', bizDo:'Do business', bizPartner:'Partner up',
    ctaT:'Find the people your work is missing.', ctaSub:'Join the waitlist \u2014 free, in five languages, worldwide from day one.',
    ctaPh:'you@business.com', ctaBtn:'Join free', ctaNote:'Available in English, Български, Espa\u00f1ol, Deutsch & Fran\u00e7ais.',
    foot:'Find the person your business is missing.',
  },
  BG: {
    how:'Как работи', pricing:'Цени', api:'API', business:'За бизнеса', signin:'Вход', join:'Присъедини се',
    badge:'Свързване с изкуствен интелект', h1a:'Намерете човека, който', kw:'бизнесът', h1b:'ви липсва.',
    sub:'Кажете ни какво имате и какво търсите. Нашият ИИ намира хората, които допълват картината \u2014 и плащате само при взаимно съгласие.',
    cta1:'Намери своя мач', cta2:'Виж как работи', free:'Безплатно \u00b7 свободно разглеждане \u00b7 плащаш само при взаимно „да“',
    stepK:'Как работи', stepT:'Свържи. Договори. Работи заедно.',
    s1t:'Свързване', s1d:'ИИ чете и двете страни и показва допълващи се хора с по едно изречение защо си пасвате.',
    s2t:'Договаряне', s2d:'И двамата казват „да“? Малка такса отключва чата. Никой не плаща за призрак.',
    s3t:'Работа заедно', s3d:'Пишете и свършете работата \u2014 без комисиони и посредници.',
    priceK:'Честни цени', priceT:'Безплатно. Плащаш само при взаимно „да“.',
    connectN:'Такса за връзка', connectD:'Начислява се щом и двете страни се съгласят, до 72 часа \u2014 иначе се освобождава.', perSide:'на страна',
    ghostN:'Гаранция срещу призраци', ghostD:'Вашите \u20ac9 само се резервират, докато и другата страна плати. Ако не стане до 72ч \u2014 се освобождават автоматично.',
    apiK:'Изгради върху Helptyfy', apiT:'API за вашите ИИ агенти.', apiSub:'Генерирайте ключове, които позволяват на агенти да действат с избрани от вас права. $20/мес на ключ, отменим по всяко време.',
    scopeView:'Преглед', scopeEdit:'Редакция', scopeEvery:'Всичко', apiCta:'Документация',
    b2bK:'За бизнеса', b2bT:'Партньорства и интеграции.', b2bSub:'Вградете свързването на Helptyfy в продукта си или си партнирайте с нас за глобален обхват.',
    b2b1t:'Интегрирай API', b2b1d:'Добавете свързване в приложението си с няколко заявки.',
    b2b2t:'Стани партньор', b2b2d:'Съвместен маркетинг към растяща мрежа от малки бизнеси.',
    ctaT:'Намерете хората, които работата ви търси.', ctaSub:'Запишете се \u2014 безплатно, на пет езика, по целия свят.',
    ctaPh:'ti@biznes.com', ctaBtn:'Присъедини се', ctaNote:'Достъпно на English, Български, Espa\u00f1ol, Deutsch и Fran\u00e7ais.',
    foot:'Намерете човека, който бизнесът ви липсва.',
  },
  ES: {
    how:'Cómo funciona', pricing:'Precios', api:'API', business:'Para empresas', signin:'Entrar', join:'Únete gratis',
    badge:'Conexiones con IA', h1a:'Encuentra a la persona que', kw:'tu negocio', h1b:'necesita.',
    sub:'Cuéntanos qué tienes y qué necesitas. Nuestra IA encuentra a quienes completan el cuadro \u2014 y solo pagas cuando es mutuo.',
    cta1:'Encuentra tu match', cta2:'Ver cómo funciona', free:'Gratis \u00b7 explora gratis \u00b7 pagas solo con un sí mutuo',
    stepK:'Cómo funciona', stepT:'Conecta. Acuerda. Colabora.',
    s1t:'Conecta', s1d:'La IA lee ambos lados y muestra personas complementarias, con una razón de por qué encajáis.',
    s2t:'Acuerda', s2d:'¿Ambos decís que sí? Una pequeña tarifa abre el chat. Nadie paga por un fantasma.',
    s3t:'Colabora', s3d:'Escribe y hazlo \u2014 sin comisiones ni intermediarios.',
    priceK:'Precios honestos', priceT:'Únete gratis. Solo pagas con un sí mutuo.',
    connectN:'Tarifa de conexión', connectD:'Se cobra cuando ambos aceptan, en 72 horas \u2014 si no, se libera.', perSide:'por lado',
    ghostN:'La garantía anti-fantasma', ghostD:'Tus \u20ac9 solo se retienen hasta que el otro lado pague. Si no lo hace en 72h, se liberan \u2014 automáticamente.',
    apiK:'Construye sobre Helptyfy', apiT:'Una API para tus agentes de IA.', apiSub:'Genera claves que dejan a los agentes actuar con los permisos que elijas. $20/mes por clave, revocable cuando quieras.',
    scopeView:'Ver', scopeEdit:'Editar', scopeEvery:'Todo', apiCta:'Ver la documentación',
    b2bK:'Para empresas', b2bT:'Alianzas e integraciones.', b2bSub:'Integra el matching de Helptyfy en tu producto o asóciate con nosotros para llegar a todo el mundo.',
    b2b1t:'Integra la API', b2b1d:'Añade matching a tu app con unos pocos endpoints.',
    b2b2t:'Sé partner', b2b2d:'Comarketing hacia una red global de pequeñas empresas.',
    ctaT:'Encuentra a quienes le faltan a tu trabajo.', ctaSub:'Únete a la lista \u2014 gratis, en cinco idiomas, global desde el día uno.',
    ctaPh:'tu@empresa.com', ctaBtn:'Únete gratis', ctaNote:'Disponible en English, Български, Espa\u00f1ol, Deutsch y Fran\u00e7ais.',
    foot:'Encuentra a la persona que tu negocio necesita.',
  },
  DE: {
    how:'So funktioniert\u2019s', pricing:'Preise', api:'API', business:'Für Unternehmen', signin:'Anmelden', join:'Gratis beitreten',
    badge:'KI-gestütztes Matching', h1a:'Finde die Person, die deinem', kw:'Business', h1b:'fehlt.',
    sub:'Sag uns, was du hast und was du brauchst. Unsere KI findet die Menschen, die das Bild vervollständigen \u2014 und du zahlst nur, wenn es beidseitig passt.',
    cta1:'Finde dein Match', cta2:'So funktioniert\u2019s', free:'Gratis \u00b7 frei stöbern \u00b7 zahlen nur bei beidseitigem Ja',
    stepK:'So funktioniert\u2019s', stepT:'Matchen. Verbinden. Zusammenarbeiten.',
    s1t:'Matchen', s1d:'Die KI liest beide Seiten und zeigt passende Menschen \u2014 mit einer Zeile, warum ihr zueinander passt.',
    s2t:'Verbinden', s2d:'Beide sagen Ja? Eine kleine Gebühr öffnet den Chat. Niemand zahlt für einen Geist.',
    s3t:'Zusammenarbeiten', s3d:'Schreibt und erledigt es \u2014 ohne Provisionen, ohne Mittelsmänner.',
    priceK:'Ehrliche Preise', priceT:'Gratis beitreten. Zahlen nur bei beidseitigem Ja.',
    connectN:'Verbindungsgebühr', connectD:'Wird berechnet, sobald beide zustimmen, innerhalb von 72 Stunden \u2014 sonst freigegeben.', perSide:'pro Seite',
    ghostN:'Die Geist-Garantie', ghostD:'Deine \u20ac9 werden nur reserviert, bis die andere Seite ebenfalls zahlt. Passiert das nicht in 72h, wird der Betrag automatisch freigegeben.',
    apiK:'Auf Helptyfy bauen', apiT:'Eine API für deine KI-Agenten.', apiSub:'Erstelle Keys, mit denen Agenten in von dir gewählten Scopes handeln. $20/Monat pro Key, jederzeit widerrufbar.',
    scopeView:'Ansehen', scopeEdit:'Bearbeiten', scopeEvery:'Alles', apiCta:'Zur Doku',
    b2bK:'Für Unternehmen', b2bT:'Partnerschaften & Integrationen.', b2bSub:'Integriere Helptyfy-Matching in dein Produkt oder werde Partner für weltweite Reichweite.',
    b2b1t:'API integrieren', b2b1d:'Bring Matching mit wenigen Endpunkten in deine App.',
    b2b2t:'Partner werden', b2b2d:'Gemeinsames Marketing an ein globales Netzwerk kleiner Unternehmen.',
    ctaT:'Finde die Menschen, die deiner Arbeit fehlen.', ctaSub:'Tritt der Warteliste bei \u2014 gratis, in fünf Sprachen, weltweit ab Tag eins.',
    ctaPh:'du@firma.com', ctaBtn:'Gratis beitreten', ctaNote:'Verfügbar auf English, Български, Espa\u00f1ol, Deutsch & Fran\u00e7ais.',
    foot:'Finde die Person, die deinem Business fehlt.',
  },
  FR: {
    how:'Comment \u00e7a marche', pricing:'Tarifs', api:'API', business:'Entreprises', signin:'Connexion', join:'Rejoindre',
    badge:'Mise en relation par IA', h1a:'Trouvez la personne qui', kw:'manque', h1b:'\u00e0 votre activit\u00e9.',
    sub:'Dites-nous ce que vous avez et ce qu\u2019il vous faut. Notre IA trouve les personnes qui compl\u00e8tent le tableau \u2014 et vous ne payez que si c\u2019est mutuel.',
    cta1:'Trouver mon match', cta2:'Comment \u00e7a marche', free:'Gratuit \u00b7 navigation libre \u00b7 payez seulement sur un oui mutuel',
    stepK:'Comment \u00e7a marche', stepT:'Matcher. Connecter. Collaborer.',
    s1t:'Matcher', s1d:'L\u2019IA lit les deux c\u00f4t\u00e9s et propose des profils compl\u00e9mentaires, avec une ligne sur pourquoi vous collez.',
    s2t:'Connecter', s2d:'Les deux disent oui ? Un petit frais ouvre le chat. Personne ne paie pour un fant\u00f4me.',
    s3t:'Collaborer', s3d:'\u00c9crivez et faites-le \u2014 sans commissions ni interm\u00e9diaires.',
    priceK:'Tarifs honn\u00eates', priceT:'Gratuit \u00e0 l\u2019inscription. Vous payez seulement sur un oui mutuel.',
    connectN:'Frais de connexion', connectD:'Pr\u00e9lev\u00e9 quand les deux acceptent, sous 72 heures \u2014 sinon lib\u00e9r\u00e9.', perSide:'par c\u00f4t\u00e9',
    ghostN:'La garantie anti-fant\u00f4me', ghostD:'Vos \u20ac9 sont seulement retenus jusqu\u2019\u00e0 ce que l\u2019autre c\u00f4t\u00e9 paie. Sans paiement sous 72h, ils sont lib\u00e9r\u00e9s \u2014 automatiquement.',
    apiK:'Construire sur Helptyfy', apiT:'Une API pour vos agents IA.', apiSub:'G\u00e9n\u00e9rez des cl\u00e9s qui laissent les agents agir selon les scopes choisis. 20\u00a0$/mois par cl\u00e9, r\u00e9vocable \u00e0 tout moment.',
    scopeView:'Voir', scopeEdit:'Modifier', scopeEvery:'Tout', apiCta:'Lire la doc',
    b2bK:'Entreprises', b2bT:'Partenariats & int\u00e9grations.', b2bSub:'Int\u00e9grez le matching Helptyfy \u00e0 votre produit ou devenez partenaire pour une port\u00e9e mondiale.',
    b2b1t:'Int\u00e9grer l\u2019API', b2b1d:'Ajoutez le matching \u00e0 votre app en quelques endpoints.',
    b2b2t:'Devenir partenaire', b2b2d:'Co-marketing vers un r\u00e9seau mondial de petites entreprises.',
    ctaT:'Trouvez les personnes qui manquent \u00e0 votre travail.', ctaSub:'Rejoignez la liste \u2014 gratuit, en cinq langues, mondial d\u00e8s le premier jour.',
    ctaPh:'vous@entreprise.com', ctaBtn:'Rejoindre', ctaNote:'Disponible en English, Български, Espa\u00f1ol, Deutsch & Fran\u00e7ais.',
    foot:'Trouvez la personne qui manque \u00e0 votre activit\u00e9.',
  },
};

function Section({ id, children, style }) {
  return <section id={id} style={{ position: 'relative', maxWidth: 1180, margin: '0 auto', padding: '0 24px', ...style }}>{children}</section>;
}
function Kicker({ children }) {
  return <div className="hl-eyebrow" style={{ marginBottom: 14 }}>{children}</div>;
}

function Nav({ t, lang, setLang }) {
  const scroll = (id) => {
    const el = document.getElementById(id);
    if (el) window.scrollTo({ top: window.scrollY + el.getBoundingClientRect().top - 90, behavior: 'smooth' });
  };
  return (
    <div style={{ position: 'sticky', top: 0, zIndex: 100, padding: '14px 0' }}>
      <Section style={{ padding: '0 24px' }}>
        <div className="hl-glass-strong" style={{ display: 'flex', alignItems: 'center', gap: 18, padding: '10px 12px 10px 20px', borderRadius: 999 }}>
          <Logo />
          <nav style={{ display: 'flex', gap: 4, marginLeft: 8 }} className="nav-links">
            {[['how', 'how'], ['api', 'api'], ['business', 'business']].map(([k, id]) => (
              <button key={k} onClick={() => scroll(id)} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-secondary)', fontFamily: 'var(--font-sans)', fontSize: 14.5, fontWeight: 600, padding: '8px 12px', borderRadius: 10 }}>{t[k]}</button>
            ))}
          </nav>
          <div style={{ flex: 1 }} />
          <LanguageMenu value={lang} onChange={setLang} />
          <Button variant="ghost" size="sm" onClick={() => go(GO.join)}>{t.signin}</Button>
          <Button variant="primary" size="sm" onClick={() => go(GO.join)}>{t.join}</Button>
        </div>
      </Section>
    </div>
  );
}

function Hero({ t }) {
  return (
    <Section style={{ paddingTop: 70, paddingBottom: 70 }}>
      <div className="hero-grid" style={{ display: 'grid', gridTemplateColumns: '1.05fr 0.95fr', gap: 56, alignItems: 'center' }}>
        <div>
          <h1 style={{ fontSize: 'var(--display-md)', fontWeight: 800, letterSpacing: '-0.035em', lineHeight: 1.04, margin: '0' }}>
            {t.h1a} <GradientText>{t.kw}</GradientText> {t.h1b}
          </h1>
          <p style={{ fontSize: 19, lineHeight: 1.6, color: 'var(--text-secondary)', maxWidth: 520, margin: '22px 0 0' }}>{t.sub}</p>
          <div style={{ display: 'flex', gap: 12, marginTop: 30, flexWrap: 'wrap' }}>
            <Button variant="primary" size="lg" onClick={() => go(GO.join)} iconRight={<Icons.ArrowRight size={19} />}>{t.cta1}</Button>
            <Button variant="secondary" size="lg">{t.cta2}</Button>
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 24, color: 'var(--text-muted)', fontSize: 14 }}>
            <Icons.ShieldCheck size={16} style={{ color: 'var(--success)' }} />{t.free}
          </div>
        </div>
        <div aria-hidden="true">
          <Partnership compact />
        </div>
      </div>
    </Section>
  );
}

function HeroPreview({ t }) {
  return (
    <div style={{ position: 'relative' }}>
      <Card padding="sm">
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 14 }}>
          <span style={{ fontWeight: 800, fontSize: 15 }}>Matches</span>
          <Badge tone="boost">Boosted</Badge>
        </div>
        {[
          { n: 'DigitalRepeal', sub: 'Automation & web studio', cat: 'Engineering', p: 92, has: ['Automation', 'Design', 'Websites'], need: 'New clients', boost: true, stance: 'offering', logo: (window.__resources && window.__resources.logoDR) || '../../assets/logo-digitalrepeal.png' },
          { n: 'YS1Pro', sub: 'Accounting & operations', cat: 'Finance', p: 86, has: ['Accounting', 'Save time'], need: 'Automation', stance: 'offering', logo: (window.__resources && window.__resources.logoYS) || '../../assets/logo-ys1.png' },
        ].map((m, i) => (
          <div key={i} className="hl-glass" style={{ padding: 14, borderRadius: 16, marginBottom: 10, display: 'flex', gap: 13, alignItems: 'flex-start' }}>
            {m.logo
              ? <span style={{ width: 40, height: 40, borderRadius: '50%', flex: 'none', backgroundImage: `url(${m.logo})`, backgroundSize: 'cover', backgroundPosition: 'center', boxShadow: i === 0 ? '0 0 0 2px var(--accent)' : 'none', border: '1px solid var(--border-glass)' }} />
              : <DS.Avatar name={m.n} ring={i === 0} />}
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
                <strong style={{ fontSize: 14.5, letterSpacing: '-0.01em' }}>{m.n}</strong>
                {m.boost && <Badge tone="boost">Boosted</Badge>}
                <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, height: 22, padding: '0 9px', borderRadius: 999, background: 'var(--surface-glass-strong)', border: '1px solid var(--border-glass)', color: 'var(--text-secondary)', fontSize: 11.5, fontWeight: 700 }}>
                  <Icons.Code size={12} />Digital
                </span>
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 4, flexWrap: 'wrap' }}>
                <span style={{ fontSize: 12, color: 'var(--text-secondary)' }}>{m.sub}</span>
                <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, height: 21, padding: '0 9px', borderRadius: 999, fontSize: 11, fontWeight: 700, background: m.stance === 'offering' ? 'color-mix(in oklab, var(--success) 16%, transparent)' : 'var(--info-soft)', border: '1px solid', borderColor: m.stance === 'offering' ? 'color-mix(in oklab, var(--success) 38%, transparent)' : 'color-mix(in oklab, var(--info) 38%, transparent)', color: m.stance === 'offering' ? 'var(--success)' : 'var(--info)' }}>
                  {m.stance === 'offering' ? <Icons.Handshake size={12} /> : <Icons.Search size={12} />}
                  {m.stance === 'offering' ? 'Offering help/ Need' : 'Looking for help'}
                </span>
              </div>
              <div style={{ display: 'flex', gap: 6, marginTop: 9, flexWrap: 'wrap' }}>
                {m.has.map(h => <Tag key={h} kind="has" style={{ height: 24, fontSize: 11 }}>{h}</Tag>)}
                <Tag kind="need" style={{ height: 24, fontSize: 11 }}>{m.need}</Tag>
              </div>
            </div>
            <Badge tone="match" size="lg" style={{ flex: 'none', alignSelf: 'flex-start' }}>{m.p}%</Badge>
          </div>
        ))}
      </Card>
    </div>
  );
}

function HowItWorks({ t }) {
  const steps = [
    { t: t.s1t, d: t.s1d, icon: <Icons.Sparkles size={24} /> },
    { t: t.s2t, d: t.s2d, icon: <Icons.Handshake size={24} /> },
    { t: t.s3t, d: t.s3d, icon: <Icons.Message size={24} /> },
    { t: t.s4t || 'Team up', d: t.s4d || 'Found people building something similar? Form a squad. Team Up turns matches into a group — several people, one shared project, moving as one.', icon: <Icons.Users size={24} />, featured: true, tag: 'Multiplayer' },
  ];
  return (
    <Section id="how" style={{ padding: '72px 24px' }}>
      <div style={{ textAlign: 'center', marginBottom: 48 }}>
        <Kicker>{t.stepK}</Kicker>
        <h2 style={{ fontSize: 'var(--text-4xl)', fontWeight: 800, letterSpacing: '-0.03em' }}>{t.stepT}</h2>
      </div>
      <div className="flow-4">
        {steps.map((s, i) => (
          <div key={i} className="flow-step">
            <Card glow={s.featured} style={{ height: '100%', display: 'flex', flexDirection: 'column', gap: 16, position: 'relative', overflow: 'hidden', background: s.featured ? 'linear-gradient(160deg, color-mix(in oklab, var(--accent) 16%, var(--surface-card)), var(--surface-card) 60%)' : undefined, border: s.featured ? '1px solid var(--accent-border)' : undefined }}>
              {s.featured && <span style={{ position: 'absolute', top: 0, right: 0, width: 130, height: 130, background: 'radial-gradient(circle at top right, color-mix(in oklab, var(--accent) 42%, transparent), transparent 70%)', pointerEvents: 'none' }} />}
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', position: 'relative', zIndex: 1 }}>
                <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', width: 56, height: 56, borderRadius: 18, background: s.featured ? 'var(--accent-gradient)' : 'var(--accent-soft)', color: s.featured ? '#fff' : 'var(--text-accent)', border: s.featured ? 'none' : '1px solid var(--accent-border)', boxShadow: s.featured ? 'var(--glow-accent)' : 'none' }}>{s.icon}</div>
                {s.tag
                  ? <Badge tone="boost" icon={<Icons.Sparkles size={11} />}>{s.tag}</Badge>
                  : <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text-faint)' }}>0{i + 1}</span>}
              </div>
              <div style={{ position: 'relative', zIndex: 1 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8 }}>
                  {s.tag && <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text-accent)' }}>0{i + 1}</span>}
                  <h3 style={{ fontSize: 21, fontWeight: 700, letterSpacing: '-0.01em' }}>{s.t}</h3>
                </div>
                <p style={{ color: 'var(--text-secondary)', fontSize: 14.5, lineHeight: 1.62 }}>{s.d}</p>
              </div>
            </Card>
          </div>
        ))}
      </div>
    </Section>
  );
}

function Pricing({ t }) {
  return (
    <Section id="pricing" style={{ padding: '64px 24px' }}>
      <div style={{ textAlign: 'center', marginBottom: 44 }}>
        <Kicker>{t.priceK}</Kicker>
        <h2 style={{ fontSize: 'var(--text-4xl)', fontWeight: 800, letterSpacing: '-0.03em', maxWidth: 680, margin: '0 auto' }}>{t.priceT}</h2>
      </div>
      <div className="pricing-grid" style={{ display: 'grid', gridTemplateColumns: '0.9fr 1.1fr', gap: 20, alignItems: 'stretch' }}>
        <Card accent glow style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', textAlign: 'center', gap: 6 }}>
          <div style={{ fontSize: 13, fontWeight: 700, color: 'var(--text-secondary)' }}>{t.connectN}</div>
          <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'center', gap: 8 }}>
            <span style={{ fontSize: 64, fontWeight: 800, letterSpacing: '-0.04em' }}><GradientText>\u20ac9</GradientText></span>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 14, color: 'var(--text-muted)' }}>{t.perSide}</span>
          </div>
          <p style={{ fontSize: 14, color: 'var(--text-secondary)', lineHeight: 1.55, maxWidth: 300, margin: '8px auto 0' }}>{t.connectD}</p>
        </Card>
        <Card style={{ display: 'flex', gap: 18, alignItems: 'flex-start' }}>
          <div style={{ flex: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center', width: 56, height: 56, borderRadius: 18, background: 'var(--success-soft)', color: 'var(--success)' }}><Icons.ShieldCheck size={26} /></div>
          <div>
            <h3 style={{ fontSize: 22, fontWeight: 700, marginBottom: 8 }}>{t.ghostN}</h3>
            <p style={{ color: 'var(--text-secondary)', fontSize: 15.5, lineHeight: 1.65 }}>{t.ghostD}</p>
            <div style={{ display: 'flex', gap: 16, marginTop: 16, flexWrap: 'wrap' }}>
              {[['Hold', 'on agreement'], ['Capture', 'when both pay'], ['Release', 'after 72h']].map(([a, b]) => (
                <div key={a} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13 }}>
                  <Icons.Check size={15} style={{ color: 'var(--success)' }} />
                  <span><strong>{a}</strong> <span style={{ color: 'var(--text-muted)' }}>{b}</span></span>
                </div>
              ))}
            </div>
          </div>
        </Card>
      </div>
    </Section>
  );
}

function ApiSection({ t }) {
  const scopes = [
    { n: t.scopeView, c: 'var(--info)', d: 'Read-only' },
    { n: t.scopeEdit, c: 'var(--accent)', d: 'Read + write' },
    { n: t.scopeEvery, c: 'var(--boost)', d: 'Full access' },
  ];
  return (
    <Section id="api" style={{ padding: '64px 24px' }}>
      <Card padding="lg" style={{ overflow: 'hidden' }}>
        <div className="api-grid" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 40, alignItems: 'center' }}>
          <div>
            <Kicker>{t.apiK}</Kicker>
            <h2 style={{ fontSize: 'var(--text-3xl)', fontWeight: 800, letterSpacing: '-0.03em', marginBottom: 14 }}>{t.apiT}</h2>
            <p style={{ color: 'var(--text-secondary)', fontSize: 16, lineHeight: 1.6, marginBottom: 22 }}>{t.apiSub}</p>
            <div style={{ display: 'flex', gap: 10, marginBottom: 24, flexWrap: 'wrap' }}>
              {scopes.map(s => (
                <div key={s.n} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 14px', borderRadius: 999, background: 'var(--surface-glass)', border: '1px solid var(--border-glass)' }}>
                  <span style={{ width: 8, height: 8, borderRadius: 99, background: s.c }} />
                  <strong style={{ fontSize: 14 }}>{s.n}</strong>
                  <span style={{ fontSize: 12, color: 'var(--text-muted)' }}>{s.d}</span>
                </div>
              ))}
            </div>
            <Button variant="secondary" iconRight={<Icons.ArrowUpRight size={17} />}>{t.apiCta}</Button>
          </div>
          <div className="hl-glass" style={{ padding: 20, borderRadius: 18, fontFamily: 'var(--font-mono)', fontSize: 13, lineHeight: 1.8, color: 'var(--text-secondary)' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 14, color: 'var(--text-muted)' }}><Icons.Key size={15} /> helpty_sk_live_4f9c\u2026a92f</div>
            <div><span style={{ color: 'var(--text-accent)' }}>POST</span> /v1/matches</div>
            <div style={{ paddingLeft: 14 }}>{'{'} need: <span style={{ color: 'var(--success)' }}>"growth engineer"</span>, scope: <span style={{ color: 'var(--success)' }}>"edit"</span> {'}'}</div>
            <div style={{ marginTop: 10, color: 'var(--text-muted)' }}>// 200 \u2014 3 matches, each with a why_fit line</div>
            <div style={{ marginTop: 14, paddingTop: 14, borderTop: '1px solid var(--border-glass)', display: 'flex', justifyContent: 'space-between' }}>
              <span>$20<span style={{ color: 'var(--text-muted)' }}>/mo \u00b7 per key</span></span>
              <span style={{ color: 'var(--text-accent)' }}>revocable anytime</span>
            </div>
          </div>
        </div>
      </Card>
    </Section>
  );
}

function B2B({ t }) {
  const F = (k, fb) => t[k] || fb;
  const values = [
    { t: F('b2b1t', 'Do business, make money'), d: F('b2b1d', 'Find businesses ready to buy, sell, and refer. Offer your services or hire others — deals happen directly and you keep what you earn.'), icon: <Icons.Handshake size={22} /> },
    { t: F('b2b2t', 'Partner up, not pay up'), d: F('b2b2d', 'No budget? Trade value instead. Connect to build something together and share the upside — partnership over payment.'), icon: <Icons.Users size={22} /> },
  ];
  const offers = ['Automation', 'Websites', 'Operations', 'AI agents', 'Anything your business needs'];
  const openTo = ['Paid projects', 'Partnerships', 'Equity deals', 'Referrals', 'and More'];
  return (
    <Section id="business" style={{ padding: '72px 24px' }}>
      <div style={{ textAlign: 'center', marginBottom: 44 }}>
        <Kicker>{F('b2bK', 'For business')}</Kicker>
        <h2 style={{ fontSize: 'var(--text-4xl)', fontWeight: 800, letterSpacing: '-0.03em', marginBottom: 10 }}>{F('b2bT', 'Where businesses connect to work on projects.')}</h2>
        <p style={{ color: 'var(--text-secondary)', fontSize: 17, maxWidth: 620, margin: '0 auto', lineHeight: 1.6 }}>{F('b2bSub', '')}</p>
      </div>
      <div className="biz-grid" style={{ display: 'grid', gridTemplateColumns: '1.08fr 0.92fr', gap: 20, alignItems: 'stretch' }}>
        {/* The "open for business" post */}
        <Card glow style={{ position: 'relative', overflow: 'hidden', display: 'flex', flexDirection: 'column', gap: 16, border: '1px solid var(--accent-border)', background: 'linear-gradient(160deg, color-mix(in oklab, var(--accent) 14%, var(--surface-card)), var(--surface-card) 62%)' }}>
          <span style={{ position: 'absolute', top: -40, right: -40, width: 200, height: 200, background: 'radial-gradient(circle, color-mix(in oklab, var(--accent) 36%, transparent), transparent 70%)', pointerEvents: 'none' }} />
          <div style={{ position: 'relative', zIndex: 1, display: 'flex', alignItems: 'center', gap: 14 }}>
            <DS.Avatar name={F('bizName', 'DigitalRepeal')} size="lg" ring />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
                <strong style={{ fontSize: 17, letterSpacing: '-0.01em' }}>{F('bizName', 'DigitalRepeal × YS1')}</strong>
                <Icons.ShieldCheck size={15} style={{ color: 'var(--text-accent)' }} />
              </div>
              <div style={{ fontSize: 13, color: 'var(--text-secondary)', marginTop: 2 }}>{F('bizRole', 'Automation, web & operations studio')}</div>
            </div>
            <Badge tone="boost" icon={<Icons.Sparkles size={11} />}>{F('bizPostTag', 'Open for business')}</Badge>
          </div>
          <p style={{ position: 'relative', zIndex: 1, fontSize: 15, lineHeight: 1.65, color: 'var(--text-primary)', textWrap: 'pretty' }}>{F('bizPostBody', '')}</p>
          <div style={{ position: 'relative', zIndex: 1, display: 'flex', flexDirection: 'column', gap: 12 }}>
            <div>
              <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: '.08em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: 8 }}>{F('bizOffer', 'Offering')}</div>
              <div style={{ display: 'flex', gap: 7, flexWrap: 'wrap' }}>{offers.map(x => <Tag key={x} kind="has" style={{ height: 26 }}>{x}</Tag>)}</div>
            </div>
            <div>
              <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: '.08em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: 8 }}>{F('bizOpen', 'Open to')}</div>
              <div style={{ display: 'flex', gap: 7, flexWrap: 'wrap' }}>{openTo.map(x => <Tag key={x} kind="need" style={{ height: 26 }}>{x}</Tag>)}</div>
            </div>
          </div>
          <div style={{ position: 'relative', zIndex: 1, display: 'flex', gap: 10, marginTop: 'auto', paddingTop: 4, flexWrap: 'wrap' }}>
            <Button variant="primary" onClick={() => go(GO.join)} iconLeft={<Icons.Handshake size={16} />} style={{ flex: 1, minWidth: 150 }}>{F('bizDo', 'Do business')}</Button>
            <Button variant="secondary" onClick={() => go(GO.join)} iconLeft={<Icons.Users size={16} />} style={{ flex: 1, minWidth: 150 }}>{F('bizPartner', 'Partner up')}</Button>
          </div>
        </Card>

        {/* Two value points */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
          {values.map((it, i) => (
            <Card key={i} interactive style={{ flex: 1, display: 'flex', gap: 16, alignItems: 'flex-start' }}>
              <div style={{ flex: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center', width: 52, height: 52, borderRadius: 16, background: 'var(--accent-soft)', color: 'var(--text-accent)', border: '1px solid var(--accent-border)' }}>{it.icon}</div>
              <div>
                <h3 style={{ fontSize: 19, fontWeight: 700, marginBottom: 6 }}>{it.t}</h3>
                <p style={{ color: 'var(--text-secondary)', fontSize: 15, lineHeight: 1.58 }}>{it.d}</p>
              </div>
            </Card>
          ))}
        </div>
      </div>
    </Section>
  );
}

const BOOST_PEOPLE = [
  { id: 'p1', name: 'DigitalRepeal', role: 'Automation & web studio', stance: 'offering', has: ['Automation', 'Design', 'Websites', 'Systems', 'AI agents'], need: ['New clients'], pct: 92, boostLevel: 'ultimate', verified: true, email: 'Digitalrepeal08@gmail.com', tagline: '120+ launches · replies within a day', logo: 'assets/logo-digitalrepeal.png' },
  { id: 'p2', name: 'YS1Pro', role: 'Accounting & operations', stance: 'offering', has: ['Accounting', 'Save time'], need: ['Automation'], pct: 86, boostLevel: 'ultimate', verified: true, email: 'ilia@ys1inc.com', tagline: 'Trusted by 40 small businesses', logo: 'assets/logo-ys1.png' },
];
/* Other boosted accounts (pro tier) shown in the grid below the featured handshake */
const BOOST_MORE = [];
const BOOST_COLORS = { purple: '#8b5cf6', red: '#ef4444' };

function ColorGroup({ label, color, items }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
      <span style={{ display: 'inline-flex', alignItems: 'center', height: 24, padding: '0 9px', borderRadius: 999, fontSize: 11, fontWeight: 800, letterSpacing: '.04em', textTransform: 'uppercase', color: color, background: `color-mix(in srgb, ${color} 15%, transparent)`, border: `1px solid color-mix(in srgb, ${color} 40%, transparent)` }}>{label}</span>
      {items.map(h => (
        <span key={h} style={{ display: 'inline-flex', alignItems: 'center', whiteSpace: 'nowrap', height: 26, padding: '0 11px', borderRadius: 999, fontSize: 12, fontWeight: 600, color: 'var(--text-primary)', background: `color-mix(in srgb, ${color} 12%, var(--surface-glass))`, border: `1px solid color-mix(in srgb, ${color} 30%, var(--border-glass))` }}>{h}</span>
      ))}
    </div>
  );
}

function ShakeEmblem() {
  return (
    <div className="shake-emblem">
      <span className="shake-halo2" />
      <span className="shake-ring" />
      <span className="shake-ring b" />
      <span className="shake-spark l" />
      <span className="shake-spark r" />
      <div className="shake-mark" role="img" aria-label="DigitalRepeal and YS1Pro shaking hands" />
    </div>
  );
}

function BoostedCard({ p, onConnect, className, compact = false }) {
  return (
    <div className={"boost-card" + (className ? " " + className : "")} style={{ display: 'flex', flexDirection: 'column', gap: compact ? 7 : 10, height: '100%' }}>
      {!compact && p.boostLevel === 'ultimate' && <div className="ult-banner"><Icons.Sparkles size={13} /> Ultimate · Exclusive <Icons.Sparkles size={13} /></div>}
      <div className="boost-card__top" style={{ display: 'flex', alignItems: 'flex-start', gap: compact ? 8 : 12 }}>
        {p.logo
          ? <span style={{ display: 'block', width: compact ? 32 : 44, height: compact ? 32 : 44, borderRadius: '50%', backgroundImage: `url(${p.logo})`, backgroundSize: 'cover', backgroundPosition: 'center', boxShadow: '0 0 0 2px var(--accent)', border: '1px solid var(--border-glass)', flex: 'none' }} />
          : <DS.Avatar name={p.name} ring />}
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
            <strong style={{ fontSize: compact ? 13 : 15.5, letterSpacing: '-0.01em', minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{p.name}</strong>
            {p.verified && <Icons.ShieldCheck size={14} style={{ color: 'var(--text-accent)', flex: 'none' }} />}
          </div>
          <div style={{ fontSize: 12.5, color: 'var(--text-secondary)', marginTop: 1, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{p.role}</div>
        </div>
        <Badge tone="match">{p.pct}%</Badge>
      </div>
      <div className="boost-tags" style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
        <Badge tone="boost" icon={<Icons.Sparkles size={11} />}>{p.boostLevel === 'ultimate' ? 'Ultimate' : 'Boosted'}</Badge>
        {p.stance === 'offering' && <Badge tone="success" icon={<Icons.Handshake size={11} />}>Offering help</Badge>}
      </div>
      {p.tagline && !compact && <div style={{ fontSize: 12, color: 'var(--text-accent)', fontWeight: 600 }}>{p.tagline}</div>}
      <div className="boost-tags" style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
        {p.has.length > 0 && <ColorGroup label="Expert" color={BOOST_COLORS.purple} items={compact ? p.has.slice(0, 3) : p.has} />}
        {p.need.length > 0 && !compact && <ColorGroup label="Needs" color={BOOST_COLORS.red} items={p.need} />}
      </div>
      <div style={{ marginTop: 'auto', paddingTop: 4, display: 'flex', flexDirection: 'column', gap: 7 }}>
        <Button size="sm" variant="primary" fullWidth onClick={onConnect} iconLeft={<Icons.Handshake size={15} />}>Connect</Button>
        {!compact && <Button size="sm" variant="secondary" fullWidth onClick={onConnect} iconLeft={<Icons.Users size={15} />}>Work together</Button>}
        {p.email && !compact && <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11.5, color: 'var(--text-muted)', display: 'inline-flex', alignItems: 'center', gap: 5, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}><Icons.Mail size={12} style={{ flex: 'none' }} />{p.email}</span>}
      </div>
    </div>
  );
}

function Partnership({ compact = false }) {
  const [dr, ys] = BOOST_PEOPLE;
  const sparks = [{ left: '12%', top: '20%', d: '0s' }, { left: '88%', top: '14%', d: '1.2s' }, { left: '58%', top: '6%', d: '2.1s' }, { left: '30%', top: '82%', d: '.6s' }, { left: '80%', top: '76%', d: '1.7s' }];
  const onConnect = () => go(GO.join);
  const showcase = (
    <div className={"boost-showcase" + (compact ? " boost-showcase--compact" : "")}>
      <div className="boost-showcase__inner">
        <span className="boost-shimmer" />
        {sparks.map((s, i) => <span key={i} className="boost-spark" style={{ left: s.left, top: s.top, animationDelay: s.d }} />)}
        <div style={{ position: 'relative', zIndex: 3, display: compact ? 'none' : 'flex', alignItems: 'flex-start', gap: compact ? 9 : 12, marginBottom: compact ? 10 : 16 }}>
          <span style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: compact ? 32 : 42, height: compact ? 32 : 42, borderRadius: compact ? 10 : 13, flex: 'none', background: 'var(--accent-gradient)', color: '#fff', boxShadow: 'var(--glow-accent)' }} className="boost-crown"><Icons.Zap size={compact ? 17 : 22} /></span>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
              <h3 style={{ fontSize: compact ? 14 : 17, fontWeight: 800, letterSpacing: '-0.02em', margin: 0, lineHeight: 1.15 }}>Boosted accounts</h3>
              {!compact && <Badge tone="boost">⚡ Exclusive</Badge>}
            </div>
            {!compact && <div style={{ fontSize: 13, color: 'var(--text-secondary)', marginTop: 6 }}>Top-of-feed, verified, and ready to connect.</div>}
          </div>
        </div>
        <div className="shake-row">
          <BoostedCard p={dr} onConnect={onConnect} compact={compact} />
          <ShakeEmblem />
          <BoostedCard p={ys} onConnect={onConnect} className="shake-card-r" compact={compact} />
        </div>
        {!compact && BOOST_MORE.length > 0 && (
          <div style={{ position: 'relative', zIndex: 3, display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(240px, 1fr))', gap: 14, marginTop: 16 }}>
            {BOOST_MORE.map(p => <BoostedCard key={p.id} p={p} onConnect={onConnect} />)}
          </div>
        )}
      </div>
    </div>
  );
  if (compact) return <div style={{ position: 'relative' }}>{showcase}</div>;
  return <Section style={{ marginTop: 56, marginBottom: 56 }}>{showcase}</Section>;
}

function CTA({ t }) {
  const [email, setEmail] = useState('');
  const [done, setDone] = useState(false);
  return (
    <Section style={{ padding: '40px 24px 90px' }}>
      <div style={{ position: 'relative', overflow: 'hidden', borderRadius: 'var(--radius-2xl)' }}>
        <div className="hl-glass-strong" style={{ position: 'relative', padding: '56px 32px', textAlign: 'center', borderRadius: 'var(--radius-2xl)' }}>
          <div className="hl-orb-bg" style={{ width: 320, height: 320, background: 'var(--violet-600)', top: -160, left: '20%' }} />
          <div className="hl-orb-bg" style={{ width: 280, height: 280, background: 'var(--cyan-500)', bottom: -160, right: '15%' }} />
          <div style={{ position: 'relative' }}>
            <h2 style={{ fontSize: 'var(--display-sm)', fontWeight: 800, letterSpacing: '-0.035em', lineHeight: 1.1, maxWidth: 720, margin: '0 auto' }}>{t.ctaT}</h2>
            <p style={{ color: 'var(--text-secondary)', fontSize: 17, margin: '16px auto 28px', maxWidth: 520 }}>{t.ctaSub}</p>
            <div style={{ display: 'flex', gap: 10, maxWidth: 460, margin: '0 auto', flexWrap: 'wrap', justifyContent: 'center' }}>
              <div style={{ flex: '1 1 240px', minWidth: 220 }}>
                <Input placeholder={t.ctaPh} value={email} onChange={e => setEmail(e.target.value)} iconLeft={<Icons.Globe size={16} />} />
              </div>
              <Button variant="primary" size="lg" onClick={() => { setDone(true); setTimeout(() => go(GO.join), 450); }} iconRight={done ? <Icons.Check size={18} /> : <Icons.ArrowRight size={18} />}>
                {done ? 'You\u2019re in' : t.ctaBtn}
              </Button>
            </div>
            <div style={{ marginTop: 18, color: 'var(--text-muted)', fontSize: 13.5 }}>{t.ctaNote}</div>
          </div>
        </div>
      </div>
    </Section>
  );
}

function Footer({ t, lang, setLang }) {
  return (
    <footer style={{ borderTop: '1px solid var(--border-subtle)', padding: '36px 0' }}>
      <Section style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 20, flexWrap: 'wrap' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
          <Logo size="sm" />
          <span style={{ color: 'var(--text-muted)', fontSize: 14 }}>{t.foot}</span>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
          <a href="../../DigitalRepeal x YS1 Handshake.html" style={{ color: 'var(--text-secondary)', fontSize: 13, fontWeight: 700, textDecoration: 'none' }}>DigitalRepeal × YS1</a>
          <span style={{ color: 'var(--text-faint)', fontSize: 13 }}>© 2026 Helptyfy</span>
          <LanguageMenu value={lang} onChange={setLang} />
        </div>
      </Section>
    </footer>
  );
}

function EyesBg() {
  const ref = React.useRef(null);
  useEffect(() => {
    const canvas = ref.current;
    const ctx = canvas.getContext('2d');
    let w, h, dpr, eyes = [], raf, last = performance.now();
    const mouse = { x: window.innerWidth / 2, y: window.innerHeight * 0.4 };
    const reduced = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    const build = () => {
      dpr = Math.min(window.devicePixelRatio || 1, 2);
      w = window.innerWidth; h = window.innerHeight;
      canvas.width = w * dpr; canvas.height = h * dpr;
      canvas.style.width = w + 'px'; canvas.style.height = h + 'px';
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      eyes = [];
      const gap = Math.max(104, Math.min(168, w / 8));
      for (let y = gap * 0.55; y < h + gap * 0.3; y += gap) {
        for (let x = gap * 0.55; x < w + gap * 0.3; x += gap) {
          const r = gap * 0.17 * (0.72 + Math.random() * 0.75);
          eyes.push({ x: x + (Math.random() - 0.5) * gap * 0.42, y: y + (Math.random() - 0.5) * gap * 0.42, r, phase: 0, blinking: false, tmr: Math.random() * 4200 });
        }
      }
    };
    build();
    const onMove = (e) => { mouse.x = e.clientX; mouse.y = e.clientY; };
    window.addEventListener('resize', build);
    window.addEventListener('mousemove', onMove);
    const draw = (now) => {
      const dt = Math.min(48, now - last); last = now;
      ctx.clearRect(0, 0, w, h);
      for (const e of eyes) {
        if (!reduced) {
          e.tmr -= dt;
          if (e.blinking) { e.phase += dt / 165; if (e.phase >= 1) { e.blinking = false; e.phase = 0; e.tmr = 1900 + Math.random() * 5200; } }
          else if (e.tmr <= 0) { e.blinking = true; e.phase = 0.0001; }
        }
        const open = e.blinking ? Math.abs(Math.cos(e.phase * Math.PI)) : 1;
        ctx.save();
        ctx.translate(e.x, e.y);
        ctx.scale(1, Math.max(0.05, open));
        ctx.beginPath(); ctx.arc(0, 0, e.r, 0, 7);
        ctx.fillStyle = 'rgba(247,248,255,0.95)'; ctx.fill();
        ctx.lineWidth = Math.max(1, e.r * 0.07); ctx.strokeStyle = 'rgba(18,16,28,0.45)'; ctx.stroke();
        ctx.restore();
        if (open > 0.22) {
          const dx = mouse.x - e.x, dy = mouse.y - e.y, d = Math.hypot(dx, dy) || 1;
          const pr = e.r * 0.44, maxOff = e.r - pr - e.r * 0.07;
          const off = Math.min(maxOff, d);
          const px = e.x + dx / d * off, py = e.y + dy / d * off;
          ctx.beginPath(); ctx.arc(px, py, pr, 0, 7); ctx.fillStyle = 'rgba(14,12,22,0.96)'; ctx.fill();
          ctx.beginPath(); ctx.arc(px - pr * 0.32, py - pr * 0.36, pr * 0.3, 0, 7); ctx.fillStyle = 'rgba(255,255,255,0.85)'; ctx.fill();
        }
      }
      raf = requestAnimationFrame(draw);
    };
    raf = requestAnimationFrame(draw);
    return () => { cancelAnimationFrame(raf); window.removeEventListener('resize', build); window.removeEventListener('mousemove', onMove); };
  }, []);
  return <canvas ref={ref} style={{ position: 'fixed', inset: 0, width: '100%', height: '100%', zIndex: 0, pointerEvents: 'none' }} />;
}

function DotsBomb({ density = 'balanced', size = 1.1 }) {
  const ref = React.useRef(null);
  const sizeRef = React.useRef(size);
  sizeRef.current = size;
  useEffect(() => {
    const canvas = ref.current;
    const ctx = canvas.getContext('2d');
    const css = getComputedStyle(document.documentElement);
    const hexToRgb = (hex) => { hex = (hex || '').trim().replace('#', ''); if (hex.length === 3) hex = hex.split('').map(c => c + c).join(''); const n = parseInt(hex, 16); return [(n >> 16) & 255, (n >> 8) & 255, n & 255]; };
    const cy = hexToRgb(css.getPropertyValue('--accent-2') || '#22d3ee');
    const vi = hexToRgb(css.getPropertyValue('--accent') || '#8b5cf6');
    const reduced = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    let w, h, dpr, N, px, py, vx, vy, col, raf, last = performance.now(), t = 0;
    const FUSE = 1.8;
    const mouse = { x: -9999, y: -9999, present: false };
    let prevX = -9999, prevY = -9999, charge = 0, armed = true, flash = 0, shockX = 0, shockY = 0;
    const build = () => {
      dpr = Math.min(window.devicePixelRatio || 1, 1.5);
      w = window.innerWidth; h = window.innerHeight;
      canvas.width = w * dpr; canvas.height = h * dpr; canvas.style.width = w + 'px'; canvas.style.height = h + 'px';
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      const divisor = density === 'sparse' ? 96 : density === 'dense' ? 22 : 42;
      const floor = density === 'sparse' ? 4000 : density === 'dense' ? 14000 : 8000;
      const ceil = density === 'sparse' ? 14000 : density === 'dense' ? 48000 : 28000;
      N = Math.min(reduced ? floor : ceil, Math.max(floor, Math.round(w * h / divisor)));
      px = new Float32Array(N); py = new Float32Array(N); vx = new Float32Array(N); vy = new Float32Array(N); col = new Uint8Array(N);
      for (let i = 0; i < N; i++) { px[i] = Math.random() * w; py[i] = Math.random() * h; vx[i] = (Math.random() - 0.5) * 0.2; vy[i] = (Math.random() - 0.5) * 0.2; col[i] = Math.random() < 0.5 ? 0 : 1; }
    };
    build();
    let down = false;
    const onMove = (e) => { mouse.x = e.clientX; mouse.y = e.clientY; mouse.present = true; };
    const onDown = (e) => { mouse.x = e.clientX; mouse.y = e.clientY; mouse.present = true; down = true; };
    const onUp = () => { down = false; charge = 0; armed = true; };
    const onLeave = () => { mouse.present = false; charge = 0; };
    window.addEventListener('resize', build);
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mousedown', onDown);
    window.addEventListener('mouseup', onUp);
    window.addEventListener('mouseout', onLeave);
    const explode = () => {
      shockX = mouse.x; shockY = mouse.y; flash = 1; armed = false; charge = 0;
      for (let i = 0; i < N; i++) {
        px[i] = Math.random() * w; py[i] = Math.random() * h;
        const dir = Math.random() < 0.5 ? -1 : 1;
        vx[i] = dir * (16 + Math.random() * 18);
        vy[i] = (Math.random() - 0.5) * 1.4;
      }
    };
    const draw = (now) => {
      const dt = Math.min(0.05, (now - last) / 1000); last = now; t += dt;
      ctx.clearRect(0, 0, w, h);
      // cursor speed (per frame)
      const charging = mouse.present && down && armed;
      if (charging) { charge += dt; if (charge >= FUSE) explode(); } else if (!down) charge = 0;
      const factor = charge / FUSE;
      const fric = charging ? 0.9 : 0.985;
      for (let i = 0; i < N; i++) {
        if (charging) {
          const dx = mouse.x - px[i], dy = mouse.y - py[i], d = Math.sqrt(dx * dx + dy * dy) + 0.01;
          if (d < 13) { const e = Math.random() * 4 | 0; if (e === 0) { px[i] = Math.random() * w; py[i] = -2; } else if (e === 1) { px[i] = Math.random() * w; py[i] = h + 2; } else if (e === 2) { px[i] = -2; py[i] = Math.random() * h; } else { px[i] = w + 2; py[i] = Math.random() * h; } vx[i] = 0; vy[i] = 0; continue; }
          const pull = 0.07 + 0.95 * factor;
          vx[i] += dx / d * pull - dy / d * 0.3 * factor;
          vy[i] += dy / d * pull + dx / d * 0.3 * factor;
        } else if (!reduced) { vx[i] += (Math.random() - 0.5) * 0.06; vy[i] += (Math.random() - 0.5) * 0.06; }
        vx[i] *= fric; vy[i] *= fric;
        let sp = vx[i] * vx[i] + vy[i] * vy[i];
        if (sp > 1156) { sp = 34 / Math.sqrt(sp); vx[i] *= sp; vy[i] *= sp; }
        px[i] += vx[i]; py[i] += vy[i];
        if (px[i] < 0) px[i] += w; else if (px[i] > w) px[i] -= w;
        if (py[i] < 0) py[i] += h; else if (py[i] > h) py[i] -= h;
      }
      // draw — two color passes
      const sz = sizeRef.current;
      ctx.globalAlpha = 0.85;
      ctx.fillStyle = `rgb(${cy[0]},${cy[1]},${cy[2]})`;
      for (let i = 0; i < N; i++) if (col[i] === 0) ctx.fillRect(px[i], py[i], sz, sz);
      ctx.fillStyle = `rgb(${vi[0]},${vi[1]},${vi[2]})`;
      for (let i = 0; i < N; i++) if (col[i] === 1) ctx.fillRect(px[i], py[i], sz, sz);
      ctx.globalAlpha = 1;
      // fuse ring on cursor
      if (charging && charge > 0.04) {
        const cr = Math.round(34 + (255 - 34) * factor), cg = Math.round(211 + (70 - 211) * factor), cb = Math.round(238 + (60 - 238) * factor);
        const pulse = 1 + Math.sin(t * (6 + 20 * factor)) * (0.12 + 0.18 * factor);
        const rad = (15 + 30 * factor) * pulse;
        ctx.strokeStyle = `rgba(${cr},${cg},${cb},0.85)`; ctx.lineWidth = 1.5 + 2 * factor;
        ctx.beginPath(); ctx.arc(mouse.x, mouse.y, rad, 0, Math.PI * 2); ctx.stroke();
        ctx.strokeStyle = `rgba(${cr},${cg},${cb},0.95)`; ctx.lineWidth = 3;
        ctx.beginPath(); ctx.arc(mouse.x, mouse.y, rad + 6, -Math.PI / 2, -Math.PI / 2 + factor * Math.PI * 2); ctx.stroke();
        ctx.fillStyle = `rgba(${cr},${cg},${cb},${0.12 + 0.25 * factor})`;
        ctx.beginPath(); ctx.arc(mouse.x, mouse.y, rad, 0, Math.PI * 2); ctx.fill();
      }
      // explosion flash
      if (flash > 0) {
        const rr = (1 - flash) * Math.max(w, h) * 0.7;
        ctx.strokeStyle = `rgba(255,255,255,${flash * 0.6})`; ctx.lineWidth = 2 + flash * 8;
        ctx.beginPath(); ctx.arc(shockX, shockY, rr, 0, Math.PI * 2); ctx.stroke();
        const g = ctx.createRadialGradient(shockX, shockY, 0, shockX, shockY, 120 + 200 * (1 - flash));
        g.addColorStop(0, `rgba(255,255,255,${flash * 0.5})`); g.addColorStop(1, 'rgba(255,255,255,0)');
        ctx.fillStyle = g; ctx.fillRect(0, 0, w, h);
        flash -= dt / 0.6; if (flash < 0) flash = 0;
      }
      raf = requestAnimationFrame(draw);
    };
    raf = requestAnimationFrame(draw);
    return () => { cancelAnimationFrame(raf); window.removeEventListener('resize', build); window.removeEventListener('mousemove', onMove); window.removeEventListener('mousedown', onDown); window.removeEventListener('mouseup', onUp); window.removeEventListener('mouseout', onLeave); };
  }, [density]);
  return <canvas ref={ref} style={{ position: 'fixed', inset: 0, width: '100%', height: '100%', zIndex: 0, pointerEvents: 'none' }} />;
}

function NetworkBg() {
  const ref = React.useRef(null);
  useEffect(() => {
    const canvas = ref.current;
    const ctx = canvas.getContext('2d');
    let w, h, dpr, nodes = [], raf, t = 0;
    const mouse = { x: -9999, y: -9999, active: false };
    const css = getComputedStyle(document.documentElement);
    const hexToRgb = (hex) => { hex = (hex || '').trim().replace('#', ''); if (hex.length === 3) hex = hex.split('').map(c => c + c).join(''); const n = parseInt(hex, 16); return [(n >> 16) & 255, (n >> 8) & 255, n & 255]; };
    const c1 = hexToRgb(css.getPropertyValue('--accent') || '#8b5cf6');
    const c2 = hexToRgb(css.getPropertyValue('--accent-2') || '#22d3ee');
    const reduced = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    const resize = () => {
      dpr = Math.min(window.devicePixelRatio || 1, 2);
      w = window.innerWidth; h = window.innerHeight;
      canvas.width = w * dpr; canvas.height = h * dpr;
      canvas.style.width = w + 'px'; canvas.style.height = h + 'px';
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      const target = Math.round(Math.min(120, Math.max(40, (w * h) / 17000)));
      nodes = [];
      for (let i = 0; i < target; i++) { const dig = Math.random() < 0.5; nodes.push({ x: Math.random() * w, y: Math.random() * h, vx: (Math.random() - 0.5) * 0.26, vy: (Math.random() - 0.5) * 0.26, r: Math.random() * 1.7 + 1.3, dig, c: dig ? c2 : c1 }); }
    };
    resize();
    const onMove = (e) => { mouse.x = e.clientX; mouse.y = e.clientY; mouse.active = true; };
    const onLeave = () => { mouse.active = false; mouse.x = mouse.y = -9999; };
    window.addEventListener('resize', resize);
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseout', onLeave);
    const LINK = 134, MR = 215;
    const draw = () => {
      ctx.clearRect(0, 0, w, h); t += 16;
      for (const n of nodes) {
        if (!reduced) { n.x += n.vx; n.y += n.vy; }
        if (n.x < -20) n.x = w + 20; if (n.x > w + 20) n.x = -20;
        if (n.y < -20) n.y = h + 20; if (n.y > h + 20) n.y = -20;
        if (mouse.active) { const dx = mouse.x - n.x, dy = mouse.y - n.y, d = Math.hypot(dx, dy); if (d < MR && d > 0.01) { const f = (1 - d / MR) * 0.05; n.vx += dx / d * f; n.vy += dy / d * f; } }
        n.vx *= 0.984; n.vy *= 0.984;
      }
      for (let i = 0; i < nodes.length; i++) {
        for (let j = i + 1; j < nodes.length; j++) {
          const a = nodes[i], b = nodes[j], dx = a.x - b.x, dy = a.y - b.y, d = Math.hypot(dx, dy);
          if (d < LINK) {
            const cross = a.dig !== b.dig;
            const o = (1 - d / LINK) * (cross ? 0.72 : 0.24);
            ctx.strokeStyle = cross ? `rgba(202,209,255,${o})` : `rgba(${a.c[0]},${a.c[1]},${a.c[2]},${o})`;
            ctx.lineWidth = cross ? 1.3 : 0.9;
            ctx.beginPath(); ctx.moveTo(a.x, a.y); ctx.lineTo(b.x, b.y); ctx.stroke();
            if (cross && d < LINK * 0.5) { const mx = (a.x + b.x) / 2, my = (a.y + b.y) / 2, pulse = 1.5 + Math.sin(t * 0.005 + a.x * 0.05) * 0.7; ctx.fillStyle = `rgba(255,255,255,${o})`; ctx.beginPath(); ctx.arc(mx, my, pulse, 0, 7); ctx.fill(); }
          }
        }
      }
      if (mouse.active) {
        for (const n of nodes) { const dx = mouse.x - n.x, dy = mouse.y - n.y, d = Math.hypot(dx, dy); if (d < MR) { const o = (1 - d / MR) * 0.8; ctx.strokeStyle = `rgba(${c2[0]},${c2[1]},${c2[2]},${o})`; ctx.lineWidth = 1.1; ctx.beginPath(); ctx.moveTo(mouse.x, mouse.y); ctx.lineTo(n.x, n.y); ctx.stroke(); } }
        ctx.fillStyle = `rgba(${c2[0]},${c2[1]},${c2[2]},0.95)`; ctx.beginPath(); ctx.arc(mouse.x, mouse.y, 3.4, 0, 7); ctx.fill();
      }
      for (const n of nodes) {
        ctx.fillStyle = `rgba(${n.c[0]},${n.c[1]},${n.c[2]},0.95)`;
        if (n.dig) { const s = n.r * 1.7; ctx.fillRect(n.x - s / 2, n.y - s / 2, s, s); }
        else { ctx.beginPath(); ctx.arc(n.x, n.y, n.r, 0, 7); ctx.fill(); }
      }
      raf = requestAnimationFrame(draw);
    };
    draw();
    return () => { cancelAnimationFrame(raf); window.removeEventListener('resize', resize); window.removeEventListener('mousemove', onMove); window.removeEventListener('mouseout', onLeave); };
  }, []);
  return <canvas ref={ref} style={{ position: 'fixed', inset: 0, width: '100%', height: '100%', zIndex: 0, pointerEvents: 'none' }} />;
}

// Vectorized "businessman holding a glowing brain" — reconstructed entirely from glowing
// dots that trace the silhouette (a reference image is used only as a luminance mask; the
// photo is never drawn). The figure is a crisp static dot-field; the brain is a live particle
// system you can click to zoom into and detonate. Golden dust on black.
function BrainScene() {
  const ref = React.useRef(null);
  useEffect(() => {
    const canvas = ref.current;
    const ctx = canvas.getContext('2d');
    const reduced = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

    let w, h, dpr, raf, last = performance.now(), t = 0;
    let buffer = null, dots = [], sparks = [];
    let N = 0, hx, hy, px, py, vx, vy, pal;
    let BX = 0, BY = 0, BRAD = 120;
    let phase = 'idle', phaseT = 0, cam = 1, flash = 0, core = 0.2;
    const ZOOM_DUR = 2.0, ZMAX = 2.7, BURST_DUR = 1.0, HOLD_DUR = 1.8, SETTLE_DUR = 2.4;

    const img = new Image();
    let imgReady = false;
    img.onload = () => { imgReady = true; build(); };
    img.src = 'assets/brainman-ref.png';

    const COL = [[150, 92, 34], [205, 132, 52], [240, 176, 92], [255, 214, 150], [255, 244, 222]];
    const bucket = (L, g) => (g > 42 || L > 232) ? 4 : L > 188 ? 3 : L > 140 ? 2 : L > 92 ? 1 : 0;
    const BR = { x0: 0.03, x1: 0.42, y0: 0.45, y1: 0.72 };

    const buildScene = () => {
      dots = [];
      if (!imgReady || !img.naturalWidth) { buffer = null; N = 0; return; }
      const OW = 420, OH = Math.round(OW * img.naturalHeight / img.naturalWidth);
      const oc = document.createElement('canvas'); oc.width = OW; oc.height = OH;
      const o = oc.getContext('2d'); o.drawImage(img, 0, 0, OW, OH);
      let d; try { d = o.getImageData(0, 0, OW, OH).data; } catch (e) { return; }
      const lum = new Float32Array(OW * OH);
      for (let i = 0; i < OW * OH; i++) { const k = i * 4; lum[i] = 0.299 * d[k] + 0.587 * d[k + 1] + 0.114 * d[k + 2]; }

      const SH = Math.min(h * 0.98, 1240), SW = SH * (OW / OH);
      const sx0 = w - SW - w * 0.10, sy0 = (h - SH) * 0.5 + 16;
      const mapX = (ox) => sx0 + (ox / OW) * SW, mapY = (oy) => sy0 + (oy / OH) * SH;

      const buf = document.createElement('canvas'); buf.width = w; buf.height = h;
      const bc = buf.getContext('2d'); bc.globalCompositeOperation = 'lighter';

      const BH = [];
      let bx = 0, by = 0, bn = 0;
      const bx0 = OW * BR.x0, bx1 = OW * BR.x1, by0 = OH * BR.y0, by1 = OH * BR.y1;

      for (let oy = 0; oy < OH; oy++) {
        for (let ox = 0; ox < OW; ox++) {
          const i = oy * OW + ox, L = lum[i];
          if (L < 14) continue;
          const lx = ox < OW - 1 ? lum[i + 1] : L, ly = oy < OH - 1 ? lum[i + OW] : L;
          const g = Math.abs(L - lx) + Math.abs(L - ly);
          const inBrain = ox >= bx0 && ox <= bx1 && oy >= by0 && oy <= by1;
          const pe = Math.min(1, (L / 255) * 0.55 + g / 80);
          if (Math.random() > pe * (reduced ? 0.6 : (inBrain ? 1.0 : 0.98))) continue;
          const c = bucket(L, g);
          const x = mapX(ox + Math.random()), y = mapY(oy + Math.random());
          if (inBrain && L > 40) {
            BH.push(x, y, c); bx += x; by += y; bn++;
          } else {
            const sz = c === 4 ? 1.9 : c >= 2 ? 1.5 : 1.2;
            const cc = COL[c];
            bc.fillStyle = 'rgba(' + cc[0] + ',' + cc[1] + ',' + cc[2] + ',' + (0.5 + 0.45 * (c / 4)) + ')';
            bc.fillRect(x, y, sz, sz);
            if (c >= 3 && dots.length < 2200 && Math.random() < 0.22) dots.push([x, y]);
          }
        }
      }
      buffer = buf;
      if (bn > 0) { BX = bx / bn; BY = by / bn; BRAD = SW * 0.22; }
      N = BH.length / 3;
      hx = new Float32Array(N); hy = new Float32Array(N); px = new Float32Array(N); py = new Float32Array(N);
      vx = new Float32Array(N); vy = new Float32Array(N); pal = new Uint8Array(N);
      for (let i = 0; i < N; i++) { hx[i] = BH[i * 3]; hy[i] = BH[i * 3 + 1]; px[i] = hx[i]; py[i] = hy[i]; pal[i] = BH[i * 3 + 2]; }
    };

    const buildSparks = () => {
      sparks = [];
      const n = reduced ? 380 : 900;
      for (let i = 0; i < n; i++) {
        sparks.push({
          x: Math.random() * w, y: Math.random() * h,
          ph: Math.random() * 6.283, sp: 0.4 + Math.random() * 1.1,
          r: 0.6 + Math.random() * 1.4, dx: (Math.random() - 0.5) * 0.12, dy: -0.05 - Math.random() * 0.12,
          c: COL[2 + (Math.random() * 3 | 0)],
        });
      }
    };

    const build = () => {
      dpr = Math.min(window.devicePixelRatio || 1, 2);
      w = window.innerWidth; h = window.innerHeight;
      canvas.width = w * dpr; canvas.height = h * dpr; canvas.style.width = w + 'px'; canvas.style.height = h + 'px';
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      buildScene(); buildSparks();
    };
    build();

    const onResize = () => build();
    const onDown = (e) => {
      if (phase !== 'idle' || reduced || !N) return;
      if (e.target && e.target.closest && e.target.closest('button,a,input,textarea,select,label,[role="button"]')) return;
      phase = 'zoom'; phaseT = 0;
    };
    window.addEventListener('resize', onResize);
    window.addEventListener('mousedown', onDown);

    const easeIn = (x) => x * x * x;
    const burst = () => {
      phase = 'burst'; phaseT = 0; flash = 1; cam = 1;
      const big = Math.max(w, h) * 0.05;
      for (let i = 0; i < N; i++) {
        const ang = Math.atan2(hy[i] - BY, hx[i] - BX) + (Math.random() - 0.5) * 1.1, sp = 5 + Math.random() * big;
        vx[i] = Math.cos(ang) * sp; vy[i] = Math.sin(ang) * sp;
      }
    };

    const draw = (now) => {
      const dt = Math.min(0.05, (now - last) / 1000); last = now; t += dt;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0); ctx.clearRect(0, 0, w, h);
      ctx.globalCompositeOperation = 'lighter';

      if (phase === 'zoom') { phaseT += dt; const p = Math.min(1, phaseT / ZOOM_DUR); cam = 1 + (ZMAX - 1) * easeIn(p); core = 0.2 + 0.8 * p; if (p >= 1) burst(); }
      else if (phase === 'burst') { phaseT += dt; if (phaseT >= BURST_DUR) { phase = 'hold'; phaseT = 0; try { window.dispatchEvent(new CustomEvent('brain-burst')); } catch (e) {} } }
      else if (phase === 'hold') { phaseT += dt; core = 0; if (phaseT >= HOLD_DUR) { phase = 'settle'; phaseT = 0; } }
      else if (phase === 'settle') { phaseT += dt; const p = Math.min(1, phaseT / SETTLE_DUR); cam = 1; core = 0.2 + 0.8 * (1 - p); if (p >= 1) { phase = 'idle'; phaseT = 0; core = 0.2; } }
      else { core = 0.2 + 0.12 * Math.sin(t * 1.4); }
      if (flash > 0) { flash -= dt / 0.5; if (flash < 0) flash = 0; }

      const pulse = 0.5 + 0.5 * Math.sin(t * 1.3);
      const halo = ctx.createRadialGradient(BX, BY, 0, BX, BY, BRAD * 1.9);
      halo.addColorStop(0, 'rgba(255,206,130,' + (0.15 + 0.10 * pulse + 0.25 * core) + ')');
      halo.addColorStop(0.5, 'rgba(190,120,50,0.06)'); halo.addColorStop(1, 'rgba(0,0,0,0)');
      ctx.fillStyle = halo; ctx.fillRect(0, 0, w, h);

      if (buffer) { const figA = (phase === 'zoom' || phase === 'burst' || phase === 'hold') ? 0.5 : 1; ctx.globalAlpha = figA * (0.84 + 0.16 * (0.5 + 0.5 * Math.sin(t * 0.8))); ctx.drawImage(buffer, 0, 0, w, h); ctx.globalAlpha = 1; }

      const drifting = phase === 'burst' || phase === 'hold';
      const fric = phase === 'burst' ? 0.95 : phase === 'hold' ? 0.97 : 0.7;
      const k = phase === 'settle' ? 0.06 : phase === 'zoom' ? 0.2 : 0.14;
      const jit = phase === 'idle' ? 0.35 : phase === 'zoom' ? 0.7 : phase === 'hold' ? 0.2 : 0;
      for (let i = 0; i < N; i++) {
        if (drifting) { vx[i] += (Math.random() - 0.5) * jit; vy[i] += (Math.random() - 0.5) * jit; vx[i] *= fric; vy[i] *= fric; px[i] += vx[i]; py[i] += vy[i]; continue; }
        vx[i] += (hx[i] - px[i]) * k; vy[i] += (hy[i] - py[i]) * k;
        if (jit) { vx[i] += (Math.random() - 0.5) * jit; vy[i] += (Math.random() - 0.5) * jit; }
        vx[i] *= fric; vy[i] *= fric; px[i] += vx[i]; py[i] += vy[i];
      }

      const sz = cam > 1.8 ? 2.1 : 1.5;
      for (let p = 0; p < COL.length; p++) {
        const cc = COL[p]; ctx.fillStyle = 'rgb(' + cc[0] + ',' + cc[1] + ',' + cc[2] + ')';
        const ss = p === 4 ? sz + 0.5 : sz;
        for (let i = 0; i < N; i++) { if (pal[i] !== p) continue; const x = BX + (px[i] - BX) * cam, y = BY + (py[i] - BY) * cam; if (x < -4 || x > w + 4 || y < -4 || y > h + 4) continue; ctx.fillRect(x, y, ss, ss); }
      }

      const glowR = BRAD * 0.45 * (0.5 + 0.9 * core) * (phase === 'zoom' ? cam : 1);
      const gi = ctx.createRadialGradient(BX, BY, 0, BX, BY, glowR);
      gi.addColorStop(0, 'rgba(255,242,214,' + (0.1 + 0.4 * core) + ')'); gi.addColorStop(0.4, 'rgba(245,176,82,' + (0.08 + 0.24 * core) + ')'); gi.addColorStop(1, 'rgba(20,12,4,0)');
      ctx.fillStyle = gi; ctx.beginPath(); ctx.arc(BX, BY, glowR, 0, 7); ctx.fill();

      if (!reduced && dots.length) { for (let i = 0; i < 70; i++) { const pp = dots[(Math.random() * dots.length) | 0]; ctx.fillStyle = 'rgba(255,246,224,' + (0.3 + 0.7 * Math.random()) + ')'; const s = 1 + Math.random() * 1.6; ctx.fillRect(pp[0], pp[1], s, s); } }

      for (let i = 0; i < sparks.length; i++) {
        const s = sparks[i]; s.x += s.dx; s.y += s.dy;
        if (s.y < -4) { s.y = h + 4; s.x = Math.random() * w; }
        if (s.x < -4) s.x = w + 4; else if (s.x > w + 4) s.x = -4;
        const a = 0.12 + 0.5 * (0.5 + 0.5 * Math.sin(t * s.sp + s.ph));
        ctx.fillStyle = 'rgba(' + s.c[0] + ',' + s.c[1] + ',' + s.c[2] + ',' + a + ')';
        ctx.fillRect(s.x, s.y, s.r, s.r);
      }

      if (flash > 0) {
        const gg = ctx.createRadialGradient(BX, BY, 0, BX, BY, 140 + 520 * (1 - flash));
        gg.addColorStop(0, 'rgba(255,244,222,' + (flash * 0.6) + ')'); gg.addColorStop(1, 'rgba(255,255,255,0)');
        ctx.fillStyle = gg; ctx.fillRect(0, 0, w, h);
        ctx.strokeStyle = 'rgba(255,224,168,' + (flash * 0.45) + ')'; ctx.lineWidth = 2 + flash * 8;
        ctx.beginPath(); ctx.arc(BX, BY, (1 - flash) * Math.max(w, h) * 0.5, 0, 7); ctx.stroke();
      }

      ctx.globalCompositeOperation = 'source-over';
      raf = requestAnimationFrame(draw);
    };
    raf = requestAnimationFrame(draw);
    return () => { cancelAnimationFrame(raf); window.removeEventListener('resize', onResize); window.removeEventListener('mousedown', onDown); };
  }, []);
  return <canvas ref={ref} style={{ position: 'fixed', inset: 0, width: '100%', height: '100%', zIndex: 0, pointerEvents: 'none' }} />;
}

// Reactive brain hero — photoreal render + gold-dust particle canvas (cursor light-web,
// parallax, brain flare on hover). Scoped behind the hero content, first viewport only.
function ReactiveHero() {
  const imgRef = React.useRef(null);
  const cvRef = React.useRef(null);
  useEffect(() => {
    const cv = cvRef.current, ctx = cv.getContext('2d'), imgEl = imgRef.current;
    const reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    const CONFIG = {
      brain: { x: 0.275, y: 0.58 }, imgNatural: { w: 1024, h: 1535 },
      particles: 95,
      gold: ['#ffe6ad', '#ffcf7a', '#f5b942', '#d4862a'],
      driftSpeed: 0.20, parallaxImg: 14, parallaxDust: 34, cursorRadius: 140, brainPulse: 0.55, brainGlow: 200,
    };
    const isMobile = window.matchMedia('(max-width:760px)').matches;
    let W = 0, H = 0, DPR = 1, P = [], raf = 0, running = true, t = 0;
    const sparks = [];
    const mouse = { x: -9999, y: -9999, tx: -9999, ty: -9999, active: false };
    const par = { x: 0, y: 0, tx: 0, ty: 0 };
    let _seed = 1234.5678;
    const fr = () => { _seed = (_seed * 9301 + 49297) % 233280; return _seed / 233280; };
    const rand = (a, b) => a + (b - a) * fr();
    const hexA = (hex, a) => { const n = parseInt(hex.slice(1), 16); return 'rgba(' + ((n >> 16) & 255) + ',' + ((n >> 8) & 255) + ',' + (n & 255) + ',' + a + ')'; };
    function brainScreen() {
      const r = imgEl.getBoundingClientRect();
      const nw = CONFIG.imgNatural.w, nh = CONFIG.imgNatural.h;
      const scale = isMobile ? Math.min(r.width / nw, r.height / nh) : Math.max(r.width / nw, r.height / nh);
      const dispW = nw * scale, dispH = nh * scale;
      const offX = r.left + (r.width - dispW) / 2, offY = r.top + (r.height - dispH) / 2;
      return { x: offX + CONFIG.brain.x * dispW, y: offY + CONFIG.brain.y * dispH };
    }
    function buildParticles() {
      const n = isMobile ? Math.round(CONFIG.particles * 0.45) : CONFIG.particles; P = [];
      const b = brainScreen();
      for (let i = 0; i < n; i++) {
        const core = i < n * 0.45;
        const x = core ? b.x + rand(-W * 0.18, W * 0.30) : rand(0, W);
        const y = core ? b.y + rand(-H * 0.32, H * 0.30) : rand(0, H);
        P.push({ x, y, r: rand(0.5, core ? 2.4 : 1.8), a: rand(0.15, core ? 0.9 : 0.55), tw: rand(0, 6.28), tws: rand(0.6, 1.8), vx: rand(-0.4, 0.4), vy: rand(-0.45, 0.2), c: CONFIG.gold[(i * 7) % CONFIG.gold.length] });
      }
    }
    function resize() {
      DPR = Math.min(2, window.devicePixelRatio || 1); W = window.innerWidth; H = window.innerHeight;
      cv.width = W * DPR; cv.height = H * DPR; cv.style.width = W + 'px'; cv.style.height = H + 'px';
      ctx.setTransform(DPR, 0, 0, DPR, 0, 0); buildParticles();
    }
    function frame() {
      if (!running) return; t += 0.016;
      par.x += (par.tx - par.x) * 0.06; par.y += (par.ty - par.y) * 0.06;
      mouse.x += (mouse.tx - mouse.x) * 0.18; mouse.y += (mouse.ty - mouse.y) * 0.18;
      if (imgEl) imgEl.style.transform = 'translate(' + par.x + 'px,' + par.y + 'px)';
      ctx.clearRect(0, 0, W, H); ctx.globalCompositeOperation = 'lighter';
      const b = brainScreen();
      const dB = Math.hypot(mouse.x - b.x, mouse.y - b.y);
      const near = mouse.active ? Math.max(0, 1 - dB / 280) : 0;
      const pulse = 0.5 + 0.5 * Math.sin(t * 1.4);
      const intensity = (0.45 + CONFIG.brainPulse * pulse * 0.55) + near * 0.9;
      const R = CONFIG.brainGlow * (0.85 + 0.15 * pulse + near * 0.5);
      const g = ctx.createRadialGradient(b.x, b.y, 0, b.x, b.y, R);
      g.addColorStop(0, hexA('#ffe6ad', Math.min(0.6, 0.22 * intensity)));
      g.addColorStop(0.4, hexA('#f5b942', Math.min(0.4, 0.14 * intensity)));
      g.addColorStop(1, 'rgba(0,0,0,0)');
      ctx.fillStyle = g; ctx.beginPath(); ctx.arc(b.x, b.y, R, 0, 6.2832); ctx.fill();
      if (near > 0.55 && (t % 0.12) < 0.016) { for (let k = 0; k < 2; k++) sparks.push({ x: b.x + rand(-40, 40), y: b.y + rand(-30, 30), vx: rand(-0.4, 0.4), vy: rand(-1.4, -0.5), life: 1, c: CONFIG.gold[k % CONFIG.gold.length] }); }
      const dustOffX = (mouse.active ? (mouse.x / W - 0.5) : 0) * -CONFIG.parallaxDust;
      const dustOffY = (mouse.active ? (mouse.y / H - 0.5) : 0) * -CONFIG.parallaxDust;
      for (const p of P) {
        p.x += p.vx * CONFIG.driftSpeed; p.y += p.vy * CONFIG.driftSpeed;
        if (p.x < -20) p.x = W + 20; if (p.x > W + 20) p.x = -20; if (p.y < -20) p.y = H + 20; if (p.y > H + 20) p.y = -20;
        const sx = p.x + dustOffX, sy = p.y + dustOffY;
        let a = p.a * (0.6 + 0.4 * Math.sin(t * p.tws + p.tw));
        if (mouse.active) {
          const d = Math.hypot(sx - mouse.x, sy - mouse.y);
          if (d < CONFIG.cursorRadius) {
            const f = 1 - d / CONFIG.cursorRadius; a = Math.min(1, a + f * 0.7);
            p.x += (mouse.x - sx) * 0.012 * f; p.y += (mouse.y - sy) * 0.012 * f;
            ctx.strokeStyle = hexA('#ffcf7a', f * 0.16); ctx.lineWidth = 0.6;
            ctx.beginPath(); ctx.moveTo(sx, sy); ctx.lineTo(mouse.x, mouse.y); ctx.stroke();
          }
        }
        ctx.fillStyle = hexA(p.c, a); ctx.beginPath(); ctx.arc(sx, sy, p.r, 0, 6.2832); ctx.fill();
      }
      for (let i = sparks.length - 1; i >= 0; i--) {
        const s = sparks[i]; s.x += s.vx; s.y += s.vy; s.vy += 0.01; s.life -= 0.02;
        if (s.life <= 0) { sparks.splice(i, 1); continue; }
        ctx.fillStyle = hexA(s.c, s.life * 0.9); ctx.beginPath(); ctx.arc(s.x, s.y, 1.6 * s.life + 0.4, 0, 6.2832); ctx.fill();
      }
      ctx.globalCompositeOperation = 'source-over'; raf = requestAnimationFrame(frame);
    }
    function staticFrame() {
      ctx.clearRect(0, 0, W, H); ctx.globalCompositeOperation = 'lighter';
      const b = brainScreen();
      const g = ctx.createRadialGradient(b.x, b.y, 0, b.x, b.y, CONFIG.brainGlow);
      g.addColorStop(0, hexA('#ffe6ad', 0.18)); g.addColorStop(0.4, hexA('#f5b942', 0.1)); g.addColorStop(1, 'rgba(0,0,0,0)');
      ctx.fillStyle = g; ctx.beginPath(); ctx.arc(b.x, b.y, CONFIG.brainGlow, 0, 6.2832); ctx.fill();
      for (const p of P) { ctx.fillStyle = hexA(p.c, p.a * 0.7); ctx.beginPath(); ctx.arc(p.x, p.y, p.r, 0, 6.2832); ctx.fill(); }
      ctx.globalCompositeOperation = 'source-over';
    }
    function setMouse(x, y) { mouse.tx = x; mouse.ty = y; mouse.active = true; par.tx = (x / W - 0.5) * -CONFIG.parallaxImg; par.ty = (y / H - 0.5) * -CONFIG.parallaxImg; }
    const onMove = (e) => setMouse(e.clientX, e.clientY);
    const onTouch = (e) => { const t0 = e.touches[0]; if (t0) setMouse(t0.clientX, t0.clientY); };
    const onLeave = () => { mouse.active = false; par.tx = 0; par.ty = 0; };
    const onVis = () => { if (reduce) return; if (document.hidden) { running = false; cancelAnimationFrame(raf); } else if (!running) { running = true; raf = requestAnimationFrame(frame); } };
    window.addEventListener('mousemove', onMove); window.addEventListener('touchmove', onTouch, { passive: true });
    window.addEventListener('mouseleave', onLeave); window.addEventListener('resize', resize); document.addEventListener('visibilitychange', onVis);
    resize(); if (reduce) { staticFrame(); } else { raf = requestAnimationFrame(frame); }
    return () => { cancelAnimationFrame(raf); running = false; window.removeEventListener('mousemove', onMove); window.removeEventListener('touchmove', onTouch); window.removeEventListener('mouseleave', onLeave); window.removeEventListener('resize', resize); document.removeEventListener('visibilitychange', onVis); };
  }, []);
  return (
    <div style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100vh', zIndex: 0, overflow: 'hidden', pointerEvents: 'none' }}>
      <div ref={imgRef} className="rh-img" />
      <canvas ref={cvRef} style={{ position: 'absolute', inset: 0, zIndex: 2, pointerEvents: 'none' }} />
      <div style={{ position: 'absolute', inset: 0, zIndex: 3, pointerEvents: 'none', background: "radial-gradient(58% 78% at 80% 54%, rgba(255,180,90,.05), transparent 60%), linear-gradient(0deg, rgba(5,5,5,.55) 0%, rgba(5,5,5,0) 26%)" }} />
    </div>
  );
}

function Page() {
  const [lang, setLang] = useState(() => localStorage.getItem('helpty-lang') || 'EN');
  useEffect(() => { localStorage.setItem('helpty-lang', lang); }, [lang]);
  const [tw, setTweak] = useTweaks(TWEAK_DEFAULTS);
  // Mood — recolor the entire site by driving the accent token trio
  useEffect(() => {
    const s = document.documentElement.style, m = tw.mood || MOOD_SWATCHES[0];
    s.setProperty('--accent', m[0]); s.setProperty('--accent-2', m[1]); s.setProperty('--accent-strong', m[2]);
  }, [tw.mood]);
  // Material — reshape every surface (glass / solid / outline) site-wide
  useEffect(() => {
    const s = document.documentElement.style, keys = ['--surface-glass', '--surface-glass-strong', '--surface-glass-hover', '--glass-blur', '--border-glass'];
    const set = MATERIAL_TOKENS[tw.material];
    keys.forEach((k) => set && set[k] != null ? s.setProperty(k, set[k]) : s.removeProperty(k));
  }, [tw.material]);
  const [showMatches, setShowMatches] = useState(false);
  useEffect(() => {
    let tmr;
    const onBurst = () => { setShowMatches(true); clearTimeout(tmr); tmr = setTimeout(() => setShowMatches(false), 2000); };
    window.addEventListener('brain-burst', onBurst);
    return () => { window.removeEventListener('brain-burst', onBurst); clearTimeout(tmr); };
  }, []);
  const t = T[lang] || T.EN;
  return (
    <div style={{ minHeight: '100vh', position: 'relative', overflow: 'hidden' }}>
      {tw.atmosphere === 'charged' && <DotsBomb density={tw.dotDensity} size={tw.dotSize} />}
      {tw.atmosphere === 'network' && <NetworkBg />}
      <div style={{ position: 'relative', zIndex: 3 }}>
        <Nav t={t} lang={lang} setLang={setLang} />
        <Hero t={t} />
        <HowItWorks t={t} />
        <B2B t={t} />
        <ApiSection t={t} />
        <CTA t={t} />
        <Footer t={t} lang={lang} setLang={setLang} />
      </div>
      <Customizer />
      <AIPanel />
      <TweaksPanel title="Tweaks">
        <TweakSection label="Atmosphere" hint="The living background behind the page" />
        <TweakRadio label="Backdrop" value={tw.atmosphere}
          options={[{ value: 'charged', label: 'Charged' }, { value: 'network', label: 'Network' }, { value: 'calm', label: 'Calm' }]}
          onChange={(v) => setTweak('atmosphere', v)} />
        {tw.atmosphere === 'charged' && (
          <>
            <TweakRadio label="Dot density" value={tw.dotDensity}
              options={[{ value: 'sparse', label: 'Sparse' }, { value: 'balanced', label: 'Balanced' }, { value: 'dense', label: 'Dense' }]}
              onChange={(v) => setTweak('dotDensity', v)} />
            <TweakSlider label="Dot size" value={tw.dotSize} min={0.6} max={2.6} step={0.1} unit="px"
              onChange={(v) => setTweak('dotSize', v)} />
          </>
        )}
        <TweakSection label="Mood" hint="Recolors the whole site" />
        <TweakColor label="Accent" value={tw.mood} options={MOOD_SWATCHES}
          onChange={(v) => setTweak('mood', v)} />
        <TweakSection label="Material" hint="How every surface is rendered" />
        <TweakRadio label="Surfaces" value={tw.material}
          options={[{ value: 'glass', label: 'Glass' }, { value: 'solid', label: 'Solid' }, { value: 'outline', label: 'Outline' }]}
          onChange={(v) => setTweak('material', v)} />
      </TweaksPanel>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<Page />);
