// agYAP landing page — main app
const { useState, useEffect, useRef } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": ["#E8E5DD", "#0E0E0C", "#A78BFA", "#FF5436"],
  "dark": false,
  "heroVariant": "stamped",
  "showWaveformBg": true
}/*EDITMODE-END*/;

const PALETTES = [
  ["#F2EFE6", "#0E0E0C", "#D4FF3A", "#FF5436"], // cream / lime / coral
  ["#0E0E0C", "#F2EFE6", "#D4FF3A", "#FF5436"], // dark / lime
  ["#F2EFE6", "#0E0E0C", "#7CF5DD", "#FF5436"], // cream / cyan
  ["#FFE9D6", "#0E0E0C", "#FF5436", "#0E0E0C"], // peach / coral
  ["#E8E5DD", "#0E0E0C", "#A78BFA", "#FF5436"], // cream / lavender
];

function applyPalette(p) {
  const r = document.documentElement.style;
  r.setProperty('--bg', p[0]);
  r.setProperty('--ink', p[1]);
  r.setProperty('--accent', p[2]);
  r.setProperty('--warm', p[3]);
  // derived paper = a hair lighter than bg toward white, or hair lighter than ink for dark
  const isDark = p[0].toLowerCase() === '#0e0e0c';
  r.setProperty('--paper', isDark ? '#161613' : '#FBFAF4');
  r.setProperty('--muted', isDark ? '#a09e92' : '#6B6A5F');
  document.body.classList.toggle('theme-dark', isDark);
}

function Nav() {
  return (
    <nav className="top">
      <div className="wrap nav-row">
        <a className="brand" href="#">
          <span className="dot" />
          <span>agYAP</span>
        </a>
        <div className="nav-links">
          <a href="#how">How it works</a>
          <a href="#features">Features</a>
          <a href="#skills">Skills</a>
          <a href="#pricing">Pricing</a>
          <a href="#docs">Docs</a>
        </div>
        <div className="nav-cta">
          <a className="pill" href="#">Sign in</a>
          <a className="pill solid" href="#">Get the app →</a>
        </div>
      </div>
    </nav>
  );
}

function Hero() {
  return (
    <header className="hero" data-reveal>
      <HeroBlobs />
      <div className="wrap">
        <span className="hero-badge" data-reveal-child>
          <span className="live-dot" />
          <span className="hud-bullet" />
          v0.4 · openclaw-ready · <LatencyReadout base={142} jitter={12} prefix="latency" />
        </span>
        <h1 className="hero-title" data-reveal-child>
          Give your<br />
          agents a<br />
          <span className="accent-strike">voice</span>
        </h1>

        <div className="hero-grid">
          <div>
            <p className="hero-sub" data-reveal-child>
              <b>agYAP</b> is the mobile app that turns any openclaw-style agent into something you can <em className="serif">actually&nbsp;talk&nbsp;to</em>. Your agent can sit on your desk or be hosted in the cloud. No need to run and pay your own TTS, SST services. Auto-discover, pick a voice, hit a button, hold a real conversation. We bundle the messy cloud stack — STT, TTS, TURN, transport — into one tap.
            </p>
            <div className="hero-meta" data-reveal-child>
              <span className="meta-chip">⏱ &lt;180ms round trip</span>
              <span className="meta-chip">🔒 e2e · per-user isolation</span>
              <span className="meta-chip">⚡ auto-discovery</span>
              <span className="meta-chip">🎙 27 voices</span>
            </div>
            <div className="hero-cta-row" data-reveal-child>
              <a className="btn-primary" href="#pricing">
                Start yapping <span className="arrow">↗</span>
              </a>
              <a className="btn-ghost" href="#demo">
                ▶ Watch 90s demo
              </a>
            </div>
            <p className="tiny-note" data-reveal-child>// no card · no setup · pairs in 12 seconds</p>
          </div>
          <div>
            <VoiceCard />
          </div>
        </div>
      </div>
    </header>
  );
}

function Marquee() {
  const items = [
    'real-time voice', 'auto-discovery', 'private by default',
    '27 voices', 'push on completion', 'multi-agent',
    'local OR cloud', 'pipeline auto-setup', 'skill packs',
    'half-duplex', 'barge-in', 'smart routing',
  ];
  // duplicate for seamless loop
  const loop = [...items, ...items];
  return (
    <div className="marquee">
      <div className="marquee-track">
        {loop.map((t, i) => (
          <span key={i}>
            {t}
            <span className="dotmark" />
          </span>
        ))}
      </div>
    </div>
  );
}

function VideoSection() {
  const chapters = [
    { t: '00:00', l: 'open the app · agents auto-discovered' },
    { t: '00:14', l: 'pick a voice for "Nova"' },
    { t: '00:31', l: 'first conversation, end-to-end encrypted' },
    { t: '00:58', l: 'switch agents mid-thread' },
    { t: '01:18', l: 'push notification on task done' },
  ];
  return (
    <section id="demo">
      <div className="wrap">
        <span className="eyebrow"><span className="num">01</span> see it move</span>
        <h2 className="section-title">A button. A&nbsp;voice. <em>The&nbsp;skills.</em></h2>
        <p className="section-lead">
          Watch agYAP discover three local agents, pair a voice in a tap, and hand off mid-sentence. Shot vertical. Captured on a phone, like you'll use it.
        </p>

        <div className="brut-box">
          <div className="brut-hud">
            <div className="hud-l">
              <span className="hud-bullet" />
              <span>FEED_001 · 9:16</span>
              <span className="hud-sep">/</span>
              <span><LatencyReadout base={142} jitter={11} prefix="RTT" /></span>
              <span className="hud-sep">/</span>
              <span>AUTO_PIPE</span>
            </div>
            <div className="hud-r">
              <span>REC</span>
              <span className="hud-sep">·</span>
              <span>NO_CUTS</span>
              <span className="hud-sep">·</span>
              <span>01:32</span>
            </div>
          </div>

          <div className="brut-grid-bg" />

          <div className="brut-inner">
            <div className="brut-stage">
              <div className="brut-axis brut-axis-y">
                <span>00:00</span>
                <span>00:30</span>
                <span>01:00</span>
                <span>01:32</span>
              </div>
              <div className="phone-shell">
                <div className="phone-bezel">
                  <div className="phone-notch" />
                  <div className="phone-canvas">
                    <div className="stripes" />
                    <PhoneRipples />
                    <ScanlinesCanvas />
                    <div className="phone-status">
                      <span>9:41</span>
                      <span style={{display:'flex',gap:6,alignItems:'center'}}>
                        <span style={{fontFamily:'JetBrains Mono,monospace',fontSize:9,letterSpacing:'.05em'}}>5G</span>
                        <span style={{width:18,height:9,border:'1px solid currentColor',borderRadius:2,position:'relative',display:'inline-block'}}>
                          <span style={{position:'absolute',inset:1,right:6,background:'currentColor',borderRadius:1}} />
                        </span>
                      </span>
                    </div>
                    <div className="phone-label">demo · 01:32 · 9:16</div>
                    <button className="play" aria-label="Play demo">
                      <svg viewBox="0 0 24 24"><path d="M6 4l14 8-14 8V4z" fill="#0E0E0C" /></svg>
                    </button>
                    <div className="phone-caption">
                      <div className="cap-tag">live</div>
                      <div className="cap-line">"hey Nova — kick off the migration when you're ready."</div>
                    </div>
                    <div className="phone-bar"><i style={{width:'42%'}}/></div>
                  </div>
                  <div className="phone-home" />
                </div>
              </div>
              <div className="brut-tag tag-tl">[ DEVICE_01 ]</div>
              <div className="brut-tag tag-br">↳ TAP TO PLAY</div>
            </div>

            <div className="brut-chapters">
              <div className="bch-head">
                <span>CHAPTERS</span>
                <span className="bch-count">{String(chapters.length).padStart(2,'0')}</span>
              </div>
              <ol className="chapter-list">
                {chapters.map((c, i) => (
                  <li key={i}>
                    <span className="ch-idx">{String(i+1).padStart(2,'0')}</span>
                    <span className="ch-time">{c.t}</span>
                    <span className="ch-label">{c.l}</span>
                    <span className="ch-arrow">→</span>
                  </li>
                ))}
              </ol>
            </div>
          </div>

          <div className="brut-footer">
            <span>◢ FEED_001.MOV</span>
            <span>SHOT_ON_DEVICE · NO_RETAKES</span>
            <span>CC · EN/CZ/DE</span>
          </div>
        </div>
      </div>
    </section>
  );
}

function HowItWorks() {
  const steps = [
    { n: '01', t: 'Open agYAP', d: 'Install on iOS or Android. The app sniffs your network for openclaw, claude-desktop, ollama and friends.' },
    { n: '02', t: 'Agents auto-appear', d: 'Local discovery via mDNS, remote via QR or paste-a-token. No port-forwarding, no docker yoga.' },
    { n: '03', t: 'Pick a voice', d: 'Match each agent to a TTS voice — calm female, dry baritone, synthetic, your own clone. Persists per agent.' },
    { n: '04', t: 'Just talk', d: 'Push-to-talk or hands-free. Switch agents mid-thread. Get a buzz when long tasks finish in the background.' },
  ];
  return (
    <section id="how">
      <div className="wrap">
        <span className="eyebrow"><span className="num">02</span> how it works</span>
        <h2 className="section-title">Four taps from <em>nothing</em> to&nbsp;a&nbsp;conversation.</h2>
        <p className="section-lead">
          You don't write a config. You don't pick endpoints. agYAP negotiates the pipeline — STT, TTS, transport, fallbacks — and gets out of the way.
        </p>
        <div className="steps">
          {steps.map((s) => (
            <div className="step" key={s.n}>
              <div className="step-num">step / {s.n}</div>
              <div className="step-icon">{s.n}</div>
              <h3>{s.t}</h3>
              <p>{s.d}</p>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

function MiniRadar() {
  return (
    <div className="vis-radar">
      <div className="ring" />
      <div className="ring r2" />
      <div className="ring r3" />
      <div className="blip" style={{ left: '32%', top: '38%' }} />
      <div className="blip" style={{ left: '58%', top: '60%', background: 'var(--warm)' }} />
      <div className="blip" style={{ left: '74%', top: '32%', background: '#9DC8FF' }} />
    </div>
  );
}

function Features() {
  const feats = [
    {
      tone: 'lime', tag: 'realtime',
      h: 'Sub-200ms voice loop',
      p: "Streaming STT into streaming inference into streaming TTS — no wait-and-see. agYAP picks the fastest path your agent supports.",
      gloss: 'p50: 142ms · p95: 188ms',
      vis: <VoiceLoopVis />
    },
    {
      tone: '', tag: 'discovery',
      h: 'Agents that find themselves',
      p: 'mDNS for local. Token + QR for remote. agYAP stitches them together so you don\'t open a single config file.',
      gloss: '// no docker · no ports · no yaml',
      vis: <DiscoveryRadar />
    },
    {
      tone: 'invert', tag: 'privacy',
      h: 'Private by design',
      p: "End-to-end encrypted between your phone and the agent. Per-user isolation, zero shared context. Sessions auto-purge — nothing logged, nothing trained on.",
      gloss: 'no recordings stored · no training',
      vis: (
        <div className="vis-shield">
          <svg viewBox="0 0 80 80" fill="none">
            <path d="M40 6 L70 20 V44 C70 60 56 72 40 76 C24 72 10 60 10 44 V20 Z" stroke="#D4FF3A" strokeWidth="2" fill="rgba(212,255,58,0.06)"/>
            <path d="M28 42 L37 51 L54 32" stroke="#D4FF3A" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"/>
          </svg>
        </div>
      )
    },
    {
      tone: '', tag: 'multi-agent',
      h: 'Switch agents mid-sentence',
      p: 'Hand a thought from your code agent to your calendar agent without losing thread. agYAP keeps shared context where it makes sense — and isolates it where it matters.',
      gloss: '4 agents max on Casual · ∞ on Pro',
      vis: <AvatarCycle />
    },
    {
      tone: 'warm', tag: 'pipelines',
      h: 'Pipelines, auto-tuned',
      p: "Whisper, Deepgram, Eleven, Cartesia, Coqui, Apple Speech — agYAP benchmarks what works on your hardware and route, then locks it in.",
      gloss: 'works offline. no, really.',
      vis: <PipelineVis />
    },
    {
      tone: '', tag: 'background',
      h: 'Push when it\'s done',
      p: "Long-running task? Lock the phone. agYAP pings you the moment the agent finishes — and lets you pick up where you left off, in voice.",
      gloss: 'apns + fcm · respects DND',
      vis: <PushVis />
    },
  ];
  return (
    <section id="features" style={{paddingTop:60}}>
      <div className="wrap">
        <span className="eyebrow"><span className="num">03</span> what's in the box</span>
        <h2 className="section-title">Built for <em>real</em> conversations.</h2>
        <p className="section-lead">Six things that turn a chatbox into a&nbsp;voice. None of them are toggles you have to find.</p>
        <div className="features">
          {feats.map((f, i) => (
            <div className={`feat ${f.tone}`} key={i}>
              <div className="feat-tag">{f.tag}</div>
              <h3>{f.h}</h3>
              <p>{f.p}</p>
              {f.vis}
              <div className="gloss">{f.gloss}</div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

function Skills() {
  const items = [
    { name: 'turn-taking', desc: 'Teach agents to wait their turn — silence detection, barge-in, half- and full-duplex modes.', tag: 'voice/core' },
    { name: 'prosody-aware', desc: 'Output that sounds spoken, not read. SSML, breath marks, pace controls, emphasis.', tag: 'voice/output' },
    { name: 'noisy-room', desc: 'VAD calibration, noise gating, and de-essing baked in. Works in cafes, cars, kitchens.', tag: 'voice/input' },
    { name: 'voice-tools', desc: 'Tool calls that announce themselves: "I\'m about to send the email — confirm?" Always.', tag: 'voice/safety' },
    { name: 'fast-fallback', desc: 'Cloud TTS down? Drop to on-device. Latency spike? Compress. Never goes silent on the user.', tag: 'voice/transport' },
  ];
  return (
    <section id="skills">
      <div className="wrap">
        <span className="eyebrow"><span className="num">04</span> skills</span>
        <h2 className="section-title">Not just a&nbsp;voice. A <em>way</em> of speaking.</h2>
        <p className="section-lead">agYAP ships with a Skills SDK — a tight set of behaviours that turn any agent into a polite, fluid, voice-native conversationalist. Drop into your prompt, your tool layer, or your runtime.</p>

        <div className="skills-band">
          <div className="glyph" />
          <div className="skills-grid">
            <div>
              <span className="eyebrow" style={{color:'color-mix(in srgb,var(--paper) 50%,transparent)'}}>
                <span className="num" style={{background:'var(--accent)',color:'#0E0E0C'}}>SDK</span> agYAP-skills
              </span>
              <h2 className="section-title" style={{fontSize:'clamp(34px,4.6vw,58px)'}}>Five primitives. One <em>much&nbsp;better</em> agent.</h2>
              <div className="skill-list" style={{marginTop:32}}>
                {items.map((s, i) => (
                  <div className="skill-item" key={s.name}>
                    <div className="si-num">/{String(i+1).padStart(2,'0')}</div>
                    <div>
                      <div className="si-name">{s.name}</div>
                      <div className="si-desc">{s.desc}</div>
                    </div>
                    <div className="si-tag">{s.tag}</div>
                  </div>
                ))}
              </div>
            </div>
            <div>
              <div className="codeblock">
                <div className="cb-bar"><i/><i/><i/></div>
                <div><span className="cb-cm"># wire any openclaw agent</span></div>
                <div><span className="cb-key">from</span> agYAP <span className="cb-key">import</span> Voice, Skills</div>
                <div>&nbsp;</div>
                <div>agent = Voice(<span className="cb-str">"openclaw://nova"</span>)</div>
                <div>agent.use(Skills.<span className="cb-fn">turn_taking</span>)</div>
                <div>agent.use(Skills.<span className="cb-fn">noisy_room</span>)</div>
                <div>agent.use(Skills.<span className="cb-fn">voice_tools</span>(confirm=<span className="cb-key">True</span>))</div>
                <div>&nbsp;</div>
                <div>agent.<span className="cb-fn">listen</span>()  <span className="cb-cm"># done.</span></div>
                <div>&nbsp;</div>
                <div><span className="cb-cm">› paired with iPhone (Klara) in 11s</span></div>
                <div><span className="cb-cm">› running pipeline: whisper.cpp → llm → kokoro</span></div>
                <div><span className="cb-cm">› p95 latency: 174ms · auto-routed</span></div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

function Pricing() {
  return (
    <section id="pricing">
      <div className="wrap">
        <span className="eyebrow"><span className="num">05</span> pricing</span>
        <h2 className="section-title">Nine bucks to&nbsp;start. <em>Worth it</em> if you stay.</h2>
        <p className="section-lead">No seat math. No per-minute pricing. Talk as much as you want.</p>

        <div className="price-grid">
          <div className="tier" data-reveal>
            <div className="top-row">
              <div className="tier-name">Casual Yap</div>
              <div className="tier-tag stamp">Starter</div>
            </div>
            <div className="tier-price">$9<span className="per">/ month</span></div>
            <p className="tier-desc">Everything you need to talk to your own agents on your own device.</p>
            <ul>
              <li>Up to 4 connected agents</li>
              <li>Bundled cloud pipeline · one-click setup</li>
              <li>27 voices · 8 languages</li>
              <li>Auto-discovery on local network</li>
              <li>Push notifications · 1 device</li>
              <li>Community Skills pack</li>
            </ul>
            <a className="btn-tier" href="#">Get Casual Yap <span>↗</span></a>
          </div>

          <div className="tier pro" data-reveal>
            <AuroraPlate />
            <div className="top-row">
              <div className="tier-name">Yap Pro</div>
              <div className="tier-tag">PRO · $19/mo</div>
            </div>
            <div className="tier-price">$19<span className="per">/ month</span></div>
            <p className="tier-desc">For people who run agents like a stable. Cloud routes, voice clones, and the works.</p>
            <ul>
              <li>Unlimited agents · multi-thread</li>
              <li>Cloud pipeline w/ auto-fallback (Eleven, Deepgram, Cartesia)</li>
              <li>Custom voice clone · 30 sec to train</li>
              <li>Cross-device sync (phone, watch, mac)</li>
              <li>Pro Skills pack + early access</li>
              <li>Encrypted shared sessions (teams later)</li>
              <li>Priority push · DND-aware</li>
            </ul>
            <a className="btn-tier" href="#">Try Yap Pro · 14 days <span>↗</span></a>
          </div>
        </div>
      </div>
    </section>
  );
}

function CTA() {
  return (
    <section className="cta-band" style={{padding:'120px 0',marginTop:0}}>
      <AuroraPlate slow />
      <RibbonWave />
      <div className="wrap">
        <span className="eyebrow"><span className="num">06</span> ready</span>
        <h2>
          <LetterReveal text="Stop typing. Start " />
          <ParticleWords words={["talking","yapping","speaking","vibing","agYAP"]} cycleMs={2800} />
        </h2>
        <div className="cta-row">
          <p className="desc">Pair your first agent in under a minute. Nine bucks a month, flat. Never throttled, never resold, never silent.</p>
          <div className="actions">
            <a className="btn-primary" href="#">Get agYAP <span className="arrow">↗</span></a>
            <a className="btn-ghost" href="#">Read the docs</a>
          </div>
        </div>
      </div>
    </section>
  );
}

function Foot() {
  return (
    <footer>
      <div className="wrap">
        <div className="foot-grid">
          <div>
            <div className="foot-brand">agYAP</div>
            <p className="foot-blurb">Voice for agents. Mobile first. Privacy default. Built for people who run their own openclaw, ollama or self-hosted stack.</p>
          </div>
          <div>
            <h4>Product</h4>
            <ul>
              <li><a href="#">Download iOS</a></li>
              <li><a href="#">Download Android</a></li>
              <li><a href="#">Skills SDK</a></li>
              <li><a href="#">Changelog</a></li>
              <li><a href="#">Status</a></li>
            </ul>
          </div>
          <div>
            <h4>Resources</h4>
            <ul>
              <li><a href="#">Docs</a></li>
              <li><a href="#">Pipeline guide</a></li>
              <li><a href="#">Voice catalogue</a></li>
              <li><a href="#">Community</a></li>
              <li><a href="#">Discord</a></li>
            </ul>
          </div>
          <div>
            <h4>Company</h4>
            <ul>
              <li><a href="#">About</a></li>
              <li><a href="#">Privacy</a></li>
              <li><a href="#">Security</a></li>
              <li><a href="#">Press</a></li>
              <li><a href="#">hello@agYAP.com</a></li>
            </ul>
          </div>
        </div>
        <div className="foot-bottom">
          <span>© 2026 agYAP labs · made loud, kept quiet</span>
          <span className="foot-rtt"><FooterRTT /></span>
          <span>v0.4.2 · build 1714</span>
        </div>
      </div>
    </footer>
  );
}

function FooterRTT() {
  const [v, setV] = React.useState(58);
  React.useEffect(() => {
    const id = setInterval(() => setV(Math.round(58 + (Math.random() - 0.5) * 16)), 2000);
    return () => clearInterval(id);
  }, []);
  return <span>rtt: {v}ms · alive · build 1714</span>;
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  React.useEffect(() => {
    applyPalette(t.palette);
  }, [t.palette]);
  useRevealOnScroll();
  useSpotlight('.voice-card');

  return (
    <>
      <ScrollProgress />
      <GrainOverlay />
      <NoYapModal />
      <Nav />
      <Hero />
      <Marquee />
      <VideoSection />
      <HowItWorks />
      <Features />
      <Skills />
      <Pricing />
      <CTA />
      <Foot />

      <TweaksPanel title="Tweaks">
        <TweakSection label="Palette">
          <TweakColor label="Theme" value={t.palette} options={PALETTES}
                      onChange={(v) => setTweak('palette', v)} />
        </TweakSection>
      </TweaksPanel>
    </>
  );
}

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