/* global React */
const { useState, useEffect, useRef, useMemo } = React;

// ===== Logo (Wordmark) =====
function VeloMark({ variant = 'helvetica-grad' }) {
  // Wordmark only. Variants:
  //  'helvetica-grad' — Helvetica 700, blue gradient text (default, brand)
  //  'tight'      — Söhne-ish geometric, weight 600, very tight tracking, slight oblique
  //  'cursor'     — Inter Tight 500, accent dot at end (cursor / log entry feel)
  //  'slash'      — JetBrains Mono 500, trailing forward-slash in accent (path / route)
  //  'contrast'   — heavy 'v' + light 'elo' (acceleration via weight contrast)
  //  'underline'  — wordmark with a thin accent underline that sweeps on hover
  if (variant === 'helvetica-grad') {
    return <span className="wm wm-helvetica-grad">velo</span>;
  }
  if (variant === 'cursor') {
    return (
      <span className="wm wm-cursor">
        <span>velo</span>
        <span className="wm-dot" aria-hidden></span>
      </span>
    );
  }
  if (variant === 'slash') {
    return (
      <span className="wm wm-slash">
        <span>velo</span>
        <span className="wm-slash-mark">/</span>
      </span>
    );
  }
  if (variant === 'contrast') {
    return (
      <span className="wm wm-contrast">
        <span className="wm-heavy">v</span>
        <span className="wm-light">elo</span>
      </span>
    );
  }
  if (variant === 'underline') {
    return (
      <span className="wm wm-underline">
        <span className="wm-text">velo</span>
        <span className="wm-rule" aria-hidden></span>
      </span>
    );
  }
  // default: 'tight'
  return <span className="wm wm-tight">velo</span>;
}

// ===== Nav =====
function Nav({ logo = 'arrow' }) {
  return (
    <nav className="nav">
      <div className="container nav-inner">
        <a href="#" className="brand">
          <VeloMark variant={logo} />
        </a>
        <span className="nav-tagline mono" aria-label="Velo tagline">
          agentic creative ops for mobile
        </span>
        <div className="nav-cta">
          <span className="cta-tip">
            <a className="btn btn--primary" href="#signup">Request access <span className="arrow">→</span></a>
            <span className="cta-tip__label mono" role="tooltip">closed beta. few users. lots of care.</span>
          </span>
        </div>
      </div>
    </nav>
  );
}

// ===== Hero =====
function Hero({ headline, sub }) {
  return (
    <header className="hero" data-screen-label="Hero">
      <span className="hero-glow" aria-hidden></span>
      <div className="container">
        <h1 className="hero-title" data-comment-anchor="hero-headline">
          {headline}
        </h1>
        <p className="hero-sub">
          {sub}
        </p>
        <div className="hero-actions">
          <span className="cta-tip">
            <a className="btn btn--primary" href="#signup">Request access <span className="arrow">→</span></a>
            <span className="cta-tip__label mono" role="tooltip">closed beta. few users. lots of care.</span>
          </span>
          <a className="btn btn--ghost" href="#how">See the mechanism</a>
        </div>
      </div>
      <Conveyor />
    </header>
  );
}

// ===== Conveyor =====
// Real game-screenshot mockups. Names are educated guesses based on the
// visible game in each image; the meta string follows existing UA-team naming
// conventions (Game_Variant_Mechanic).
const IMG_BASE = '/images%20for%20creative%20mock-ups/';
const imgSrc = f => IMG_BASE + f.replace(/ /g, '%20');

const CREATIVE_ROW = [
  { id: 'C01', img: '1e.png',         tag: 'BUILD', name: 'Township_DRAG_TUT',     kind: 'win',  metric: 'IPM', value: '+38%' },
  { id: 'C02', img: '1r.png',         tag: 'PVP',   name: 'BrawlStars_GOAL_15s',   kind: 'win',  metric: 'IPM', value: '+47%' },
  { id: 'C03', img: '1w.png',         tag: 'PUZ',   name: 'BlockBlast_CLR_PUZ',    kind: 'test', metric: 'CTR', value: 'rendering' },
  { id: 'C04', img: '2q.png',         tag: 'M3',    name: 'CandyCrush_SAGA_M3',    kind: 'win',  metric: 'D1',  value: '+44%' },
  { id: 'C05', img: 'f1.png',         tag: 'SORT',  name: 'WaterSort_BTL_4x',      kind: 'win',  metric: 'IPM', value: '+29%' },
  { id: 'C06', img: 'f2.png',         tag: 'RUN',   name: 'GoingBalls_LAVA_LV2',   kind: 'lose', metric: 'CPI', value: '+18%' },
  { id: 'C07', img: 'g3.png',         tag: 'POP',   name: 'PopIt_PIPE_99',         kind: 'win',  metric: 'ROI', value: '+180%' },
  { id: 'C08', img: 'image (39).png', tag: 'TILE',  name: 'TileMatch_BEACH_MTC',   kind: 'test', metric: 'IPM', value: 'rendering' },
  { id: 'C09', img: 'image (40).png', tag: 'M3',    name: 'RoyalMatch_BLDG_M3',    kind: 'win',  metric: 'IPM', value: '+47%' },
  { id: 'C10', img: 'image (41).png', tag: 'AR',    name: 'PokemonGO_CHR_AR',      kind: 'win',  metric: 'D1',  value: '+36%' },
  { id: 'C11', img: 'image (42).png', tag: 'GACHA', name: 'BrawlStars_BOX_RAR',    kind: 'lose', metric: 'CTR', value: '-19%' },
  { id: 'C12', img: 'image (43).png', tag: 'MAZE',  name: 'MazeEscape_PATH_LV1',   kind: 'lose', metric: 'IPM', value: '-12%' },
  { id: 'C13', img: 'image (44).png', tag: 'BRAND', name: 'Revolut_INTER_FB',      kind: 'win',  metric: 'CPM', value: '$3.40' },
  { id: 'C14', img: 'image (45).png', tag: 'SIM',   name: 'TheSims_BABY_LIFE',     kind: 'test', metric: 'CPI', value: 'rendering' },
  { id: 'C15', img: 'image (46).png', tag: 'JAM',   name: 'ParkingJam_LOT4_PRK',   kind: 'win',  metric: 'IPM', value: '+18%' },
  { id: 'C16', img: 'image (47).png', tag: 'SORT',  name: 'WaterSort_8x_BTL',      kind: 'lose', metric: 'IPM', value: '-21%' },
  { id: 'C17', img: 'image (48).png', tag: 'RPG',   name: 'VikingRise_777_RPG',    kind: 'win',  metric: 'ROI', value: '+144%' },
  { id: 'C18', img: 'image (49).png', tag: 'IO',    name: 'StumbleGuys_15_RUN',    kind: 'win',  metric: 'D1',  value: '+44%' },
  { id: 'C19', img: 'image1.png',     tag: 'M3',    name: 'RoyalMatch_HRT_M3',     kind: 'test', metric: 'CPM', value: 'rendering' },
];

function CreativeCard({ c, eager }) {
  const valClass = c.kind === 'win' ? 'win' : c.kind === 'lose' ? 'lose' : 'test';
  return (
    <div className={`creative ${c.kind === 'win' ? 'win' : ''}`}>
      <img
        className="creative-img"
        src={imgSrc(c.img)}
        alt=""
        width="156"
        height="277"
        // Eager load on the first pass so all 19 unique images are decoded
        // before the marquee starts. The second pass is the same URLs from
        // browser cache — instant.
        loading={eager ? 'eager' : 'lazy'}
        decoding="async"
        fetchpriority={eager ? 'high' : 'low'}
        draggable="false"
      />
      <span className="tag mono">{c.tag}</span>
      <div className="creative-art">
        <span className="creative-art-pill">{c.name}</span>
      </div>
      <div className="perf">
        <span className="metric-label">{c.metric}</span>
        <span className={`ipm ${valClass}`}>{c.value}</span>
      </div>
    </div>
  );
}

function Conveyor() {
  // Doubled exactly so translateX(-50%) lands on the seamless repeat.
  // First copy is eager-loaded; second copy points to the same cached URLs.
  const N = CREATIVE_ROW.length;
  const row = [...CREATIVE_ROW, ...CREATIVE_ROW];
  return (
    <div className="conveyor-wrap" aria-label="Creatives moving through the pipeline">
      <div className="conveyor-status container">
        <span className="conv-status-left mono">
          <span className="live-dot" aria-hidden></span>
          PIPELINE
        </span>
        <span className="conv-status-right mono"><span className="conv-locked">5 WINNERS LOCKED</span></span>
      </div>
      <div className="conveyor-rails">
        <div className="conveyor-track" aria-hidden="true">
          {row.map((c, i) => <CreativeCard key={`c-${i}`} c={c} eager={i < N} />)}
        </div>
      </div>
      <div className="conveyor-legend container mono">
        <span className="legend-state">
          <span className="legend-dot legend-dot--win" aria-hidden></span> WIN
          <span className="legend-dot legend-dot--lose" aria-hidden></span> LOSE
          <span className="legend-dot legend-dot--test" aria-hidden></span> TEST
        </span>
      </div>
    </div>
  );
}

// ===== BrandIcon =====
// Minimal recognizable glyph per brand. currentColor stroke/fill so the icon
// inherits text color — keeps the strip monochrome by default and lifts on hover.
function BrandIcon({ name }) {
  const p = { width: 22, height: 22, viewBox: '0 0 24 24', fill: 'currentColor', 'aria-hidden': true };
  switch (name) {
    case 'Claude':
      // Stylized monogram — minimal "C" arc with center dot (generic, abstract)
      return (
        <svg {...p} fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round">
          <path d="M19 7a8 8 0 1 0 0 10"/>
          <circle cx="12" cy="12" r="1.6" fill="currentColor"/>
        </svg>
      );
    case 'Gemini':
      return (
        <svg {...p}><path d="M12 2L13.5 9 21 12L13.5 14.5L12 22L10.5 14.5L3 12L10.5 9L12 2Z"/></svg>
      );
    case 'ElevenLabs':
      return (
        <svg {...p}><rect x="7" y="5" width="3" height="14" rx="1"/><rect x="14" y="5" width="3" height="14" rx="1"/></svg>
      );
    case 'HeyGen':
      return (
        <svg {...p} fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"><circle cx="12" cy="9" r="3.5"/><path d="M5 21c0-3.5 3-6 7-6s7 2.5 7 6"/></svg>
      );
    case 'SensorTower':
      return (
        <svg {...p}><rect x="6" y="18" width="12" height="2" rx="0.5"/><rect x="7" y="14" width="10" height="2" rx="0.5"/><rect x="9" y="10" width="6" height="2" rx="0.5"/><rect x="10.5" y="6" width="3" height="2" rx="0.5"/></svg>
      );
    case 'Remotion':
      return (
        <svg {...p}><path d="M6 4l14 8-14 8V4z"/></svg>
      );
    case 'Playwright':
      return (
        <svg {...p} fill="none" stroke="currentColor" strokeWidth="1.5"><ellipse cx="9" cy="11" rx="5" ry="6"/><ellipse cx="16.5" cy="13" rx="3.5" ry="4.5" opacity="0.55"/></svg>
      );
    case 'CCapture.js':
      return (
        <svg {...p} fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"><path d="M9 6H6v3M15 6h3v3M9 18H6v-3M15 18h3v-3"/></svg>
      );
    case 'AppLovin':
      // Stylized peak/upward triangle — generic geometric mark
      return (
        <svg {...p} fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinejoin="round"><path d="M12 4L3 20h18L12 4z"/></svg>
      );
    case 'Unity Ads':
      return (
        <svg {...p} fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M12 2.5L21 7.5v9L12 21.5L3 16.5v-9L12 2.5z"/><path d="M12 2.5v19M3 7.5l18 9M21 7.5l-18 9" opacity="0.4"/></svg>
      );
    case 'Liftoff':
      return (
        <svg {...p} fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M12 2c2.5 2 4 5 4 9v7l-4-2-4 2v-7c0-4 1.5-7 4-9z"/><circle cx="12" cy="10" r="1.5" fill="currentColor"/></svg>
      );
    case 'Mintegral':
      return (
        <svg {...p}><path d="M3 5h3l4 7 4-7h3v14h-3v-8l-3 5h-2l-3-5v8H3V5z"/></svg>
      );
    case 'ironSource':
      return (
        <svg {...p} fill="none" stroke="currentColor" strokeWidth="1.5"><rect x="4" y="4" width="16" height="16" rx="2"/><path d="M9 9h6v6H9z" fill="currentColor"/></svg>
      );
    case 'Meta':
      return (
        <svg {...p} fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"><path d="M2 12c0-3 2-5 4.5-5 2 0 3.4 1.4 4.6 3.5 1.2 2 2.6 3.5 4.6 3.5 2.5 0 4.3-2 4.3-5"/><path d="M2 12c0 3 2 5 4.5 5 2 0 3.4-1.4 4.6-3.5 1.2-2 2.6-3.5 4.6-3.5 2.5 0 4.3 2 4.3 5" opacity="0.55"/></svg>
      );
    case 'TikTok':
      return (
        <svg {...p}><path d="M16 4v3a4.2 4.2 0 0 0 4 4v3a7 7 0 0 1-4-1.3V16a5 5 0 1 1-5-5h1v3h-1a2 2 0 1 0 2 2V4h3z"/></svg>
      );
    case 'Google Ads':
      // Generic megaphone / broadcast glyph — abstract ad symbol
      return (
        <svg {...p} fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M4 10v4l13 5V5L4 10z"/><path d="M9 14v3a2 2 0 0 0 4 0v-1.5"/></svg>
      );
    case 'Moloco':
      return (
        <svg {...p} fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round"><path d="M3 17c0-5 2.5-9 5-9s2.5 4 2.5 4 0-4 2.5-4 5 4 5 9"/><circle cx="20" cy="9" r="1.5" fill="currentColor" stroke="none"/></svg>
      );
    default:
      return (
        <svg {...p} fill="none" stroke="currentColor" strokeWidth="1.5"><circle cx="12" cy="12" r="6"/></svg>
      );
  }
}

// ===== Brand cell — shared layout for Networks + Stack =====
function BrandCell({ name, sub }) {
  return (
    <div className="brand-cell" role="listitem">
      <span className="brand-icon" aria-hidden><BrandIcon name={name} /></span>
      <span className="brand-name">{name}</span>
      {sub && <span className="brand-sub mono">{sub}</span>}
    </div>
  );
}

function PlaceholderCell({ label, sub }) {
  return (
    <div className="brand-cell brand-cell--text" role="listitem">
      <span className="brand-name brand-name--muted">{label}</span>
      {sub && <span className="brand-sub mono">{sub}</span>}
    </div>
  );
}

// ===== Networks =====
function Networks() {
  const primary = ['AppLovin', 'Unity Ads', 'Liftoff', 'Mintegral', 'ironSource'];
  const secondary = ['Meta', 'TikTok', 'Google Ads', 'Moloco'];
  return (
    <section id="networks" data-screen-label="Networks">
      <div className="container">
        <div className="section-head">
          <div className="section-marker">
            <span className="section-marker__tag">Networks</span>
          </div>
          <div>
            <h2>Plugs into the networks <em>you already buy on.</em></h2>
            <p className="lede">Velo reads spend, IPM, ROAS and retention from your MMP and ad-network APIs, labels every winning ad by axis, and feeds the bias straight back into the next run's matrix.</p>
          </div>
        </div>
        <div className="brand-strip" role="list">
          {primary.map(n => <BrandCell key={n} name={n} />)}
        </div>
        <div className="brand-strip brand-strip--secondary" role="list">
          {secondary.map(n => <BrandCell key={n} name={n} />)}
          <PlaceholderCell label="+ AppsFlyer · Adjust · Singular" />
        </div>
      </div>
    </section>
  );
}

// ===== Tech Stack =====
function TechStack() {
  const primary = [
    { name: 'Claude',      sub: 'orchestration' },
    { name: 'Gemini',      sub: 'video understanding' },
    { name: 'ElevenLabs',  sub: 'voice synthesis' },
    { name: 'HeyGen',      sub: 'AI personas' },
    { name: 'SensorTower', sub: 'competitor intel' },
  ];
  const secondary = [
    { name: 'Remotion',    sub: 'render engine' },
    { name: 'Playwright',  sub: 'gameplay capture' },
    { name: 'CCapture.js', sub: 'frame capture' },
  ];
  return (
    <section id="stack" data-screen-label="Stack">
      <div className="container">
        <div className="section-head">
          <div className="section-marker">
            <span className="section-marker__tag">Stack</span>
          </div>
          <div>
            <h2>Built on the AI stack <em>you'd ship if you had the time.</em></h2>
            <p className="lede">Best of breed, one orchestration. Every stage uses the right model for the shape of the input. Gemini for video, Claude for synthesis, ElevenLabs for voice, HeyGen for personas, Remotion for render.</p>
          </div>
        </div>
        <div className="brand-strip" role="list">
          {primary.map(t => <BrandCell key={t.name} name={t.name} sub={t.sub} />)}
        </div>
        <div className="brand-strip brand-strip--secondary" role="list">
          {secondary.map(t => <BrandCell key={t.name} name={t.name} sub={t.sub} />)}
          <PlaceholderCell label="+ your MMP" sub="AppsFlyer · Adjust · Singular" />
          <PlaceholderCell label="+ your network" sub="ad-network APIs" />
        </div>
      </div>
    </section>
  );
}

// ===== Studios → Production (numbers + anonim tier grid) =====
function Studios() {
  // Anonim tier etiketleri — gerçek studio isimleri yerine.
  // Otorite kaybını üstteki Big Numbers strip telafi ediyor.
  const tiers = [
    { name: 'Top-50 Publisher',     meta: 'Match-3 · iOS+Android' },
    { name: 'Tier-1 Hyper-Casual',  meta: 'Runner · Global' },
    { name: 'Match-3 Mid-Core',     meta: 'Live-ops · iOS+Android' },
    { name: 'AAA Mobile RPG',       meta: 'Gacha · Tier-1 markets' },
    { name: 'Hybrid-Casual',        meta: 'Merge · Global' },
    { name: 'Idle/Sim Tier-1',      meta: 'Idle tycoon · iOS+Android' },
    { name: 'Casino Studio',        meta: 'Slots · regulated markets' },
    { name: 'Word Game Studio',     meta: 'Casual · iOS+Android' },
    { name: 'Sports Tier-2',        meta: 'Arcade sports · Global' },
    { name: 'Puzzle Tier-1',        meta: 'Block puzzle · iOS+Android' },
    { name: 'Hyper-Casual #2',      meta: '.io · Global' },
    { name: 'Tier-2 Hybrid',        meta: 'Casual sim · iOS+Android' },
  ];
  return (
    <section id="studios" data-screen-label="Production">
      <div className="container">
        <div className="section-head">
          <div className="section-marker">
            <span className="section-marker__tag">Production</span>
          </div>
          <div>
            <h2>Built for studios that ship <em>creatives across genres.</em></h2>
            <p className="lede">From hyper-casual to mid-core RPG, Velo adapts to the studio's style guide rather than the other way around. The numbers below are from pilot runs; the tiers below are the studio shapes Velo is currently sized for.</p>
          </div>
        </div>
        <div className="production-numbers" aria-label="Velo by the numbers">
          <CountUpCell
            valueDisplay="$420k+"
            valueEnd={420}
            unit="/mo"
            accent
            label="Spend optimized"
            desc="Across pilot runs · blended Q1 2026"
          />
          <CountUpCell
            valueDisplay="1,284"
            valueEnd={1284}
            label="In flight"
            desc="Variations rendering across pilots this week"
          />
          <CountUpCell
            valueDisplay="47"
            valueEnd={47}
            label="Winners shipped"
            desc="Top-quartile creatives, weighted by spend"
          />
          <CountUpCell
            valueDisplay="3wk → 4h"
            label="Cycle compressed"
            desc="Brief to delivered MP4s, gates included"
          />
        </div>
        <div className="studios">
          {tiers.map(s => (
            <div className="cell" key={s.name}>
              <span className="name">{s.name}</span>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

// ===== CountUpCell — number that animates from 0 when it scrolls into view =====
function CountUpCell({ valueDisplay, valueEnd, unit, label, desc, accent }) {
  const ref = useRef(null);
  const [revealed, setRevealed] = useState(false);
  const [shown, setShown] = useState(valueEnd ? '0' : valueDisplay);

  useEffect(() => {
    if (!ref.current) return;
    if (typeof IntersectionObserver === 'undefined') {
      setRevealed(true); setShown(valueDisplay); return;
    }
    const reduced = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    const io = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) { setRevealed(true); io.disconnect(); }
    }, { threshold: 0.5 });
    io.observe(ref.current);
    return () => io.disconnect();
  }, [valueDisplay]);

  useEffect(() => {
    if (!revealed) return;
    if (!valueEnd) { setShown(valueDisplay); return; }
    const reduced = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    if (reduced) { setShown(valueDisplay); return; }
    const start = performance.now();
    const dur = 900;
    let raf;
    const tick = (t) => {
      const p = Math.min(1, (t - start) / dur);
      const eased = 1 - Math.pow(1 - p, 3);
      const v = Math.round(eased * valueEnd);
      // Re-format to preserve commas & prefix from the display string
      const formatted = valueDisplay.replace(/[\d,]+/, v.toLocaleString('en-US'));
      setShown(formatted);
      if (p < 1) raf = requestAnimationFrame(tick);
      else setShown(valueDisplay);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [revealed, valueDisplay, valueEnd]);

  return (
    <div ref={ref} className={`pn-cell ${accent ? 'pn-cell--accent' : ''}`}>
      <div className="pn-l mono">{label}</div>
      <div className="pn-v">
        {shown}
        {unit && <span className="pn-unit">{unit}</span>}
      </div>
      <div className="pn-d">{desc}</div>
    </div>
  );
}

window.VeloMark = VeloMark;
window.Nav = Nav;
window.Hero = Hero;
window.Networks = Networks;
window.TechStack = TechStack;
window.Studios = Studios;
