// WebBrain — beta-test landing
// High-conversion single-page, beta signup focus.

const { useState, useEffect, useRef, useMemo, useCallback } = React;

// ─── Reveal-on-scroll hook ─────────────────────────────────────────────────
// Adds `.is-revealed` to elements with `.reveal` class once they enter viewport.
// Honours prefers-reduced-motion by revealing immediately.
function useScrollReveal() {
  useEffect(() => {
    if (!document.body) return;

    const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

    if (reduced || !("IntersectionObserver" in window)) {
      document.querySelectorAll(".reveal").forEach((el) => el.setAttribute("data-revealed", "true"));
      return;
    }

    const io = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            entry.target.setAttribute("data-revealed", "true");
            io.unobserve(entry.target);
          }
        });
      },
      { threshold: 0.12, rootMargin: "0px 0px -8% 0px" }
    );

    // Observe initially, and re-observe on DOM mutations (React re-renders
    // can replace elements; new .reveal nodes need to be picked up).
    const observed = new WeakSet();
    const scan = () => {
      document.querySelectorAll(".reveal:not([data-revealed])").forEach((el) => {
        if (observed.has(el)) return;
        observed.add(el);
        io.observe(el);
      });
    };
    scan();

    const mo = new MutationObserver(scan);
    mo.observe(document.body, { childList: true, subtree: true });

    return () => {
      io.disconnect();
      mo.disconnect();
    };
  }, []);
}

// ─── Design tokens ──────────────────────────────────────────────────────────
const ACCENTS = {
  lime: { hex: "#c8ff5e", rgb: "200,255,94", text: "#0a0c00", soft: "#1a2107", name: "Lime" },
  cyan: { hex: "#63e6ff", rgb: "99,230,255", text: "#001318", soft: "#062028", name: "Cyan" },
  violet: { hex: "#b794ff", rgb: "183,148,255", text: "#10001f", soft: "#180a2b", name: "Violet" }
};

// ─── Hero copy variants ─────────────────────────────────────────────────────
const HERO_VARIANTS = {
  outcome: {
    badge: "Закрытая бета",
    h1: ["Сайт, ", "который ", "приводит ", { accent: "заявки" }, ".", "  Не картинка."],
    sub: "Опишите бизнес в чате — WebBrain соберёт лендинг с формой, аналитикой и доменом. Первая заявка через 30 минут."
  },
  aggressive: {
    badge: "Закрытая бета",
    h1: ["Хватит платить ", "за ", { accent: "Tilda" }, ".", "  И не получать AI."],
    sub: "WebBrain — российский AI-конструктор сайтов. Дешевле Tilda, умнее Webflow. Подключение домена, формы и оплата из коробки."
  },
  speed: {
    badge: "Закрытая бета",
    h1: ["30 минут", "  от идеи ", "до ", { accent: "сайта в проде" }, "."],
    sub: "Опишите нишу в чате — получите готовый лендинг с формой, аналитикой и доменом. Без верстальщиков, без шаблонов с рыбой."
  }
};

const CTA_LABELS = {
  "early-access": "Получить ранний доступ",
  "enter-beta": "Войти в закрытую бету",
  "reserve": "Забронировать место"
};

// ─── Tiny icon set (SVG inline) ─────────────────────────────────────────────
const Ic = {
  arrow: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 12h14M13 5l7 7-7 7" /></svg>,
  spark: (p) => <svg viewBox="0 0 24 24" fill="currentColor" {...p}><path d="M12 2l1.7 5.3L19 9l-5.3 1.7L12 16l-1.7-5.3L5 9l5.3-1.7z" /></svg>,
  check: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 12l5 5L20 6" /></svg>,
  x: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M6 6l12 12M18 6L6 18" /></svg>,
  plus: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 5v14M5 12h14" /></svg>,
  tg: (p) => <svg viewBox="0 0 24 24" fill="currentColor" {...p}><path d="M9.78 18.65l.28-4.23 7.68-6.92c.34-.31-.07-.46-.52-.19L7.74 13.24 3.64 11.93c-.88-.28-.89-.88.2-1.31l16-6.17c.73-.33 1.43.18 1.15 1.31l-2.72 12.81c-.19.92-.74 1.14-1.5.71L13.6 16.4l-1.99 1.93c-.23.23-.42.42-.83.42z" /></svg>,
  send: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z" /></svg>,
  dot: (p) => <svg viewBox="0 0 8 8" {...p}><circle cx="4" cy="4" r="3" fill="currentColor" /></svg>,
  bolt: (p) => <svg viewBox="0 0 24 24" fill="currentColor" {...p}><path d="M13 2L4 14h7l-2 8 9-12h-7l2-8z" /></svg>,
  layers: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 2l9 5-9 5-9-5 9-5zM3 12l9 5 9-5M3 17l9 5 9-5" /></svg>,
  shield: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 3l8 3v6c0 5-3.5 8.5-8 9-4.5-.5-8-4-8-9V6l8-3z" /></svg>,
  chart: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 21h18M6 17V9M11 17V4M16 17v-6M21 17v-9" /></svg>,
  msg: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M21 11.5a8.5 8.5 0 01-12.5 7.5L3 21l2-5.5A8.5 8.5 0 1121 11.5z" /></svg>,
  vote: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M9 12l2 2 4-4M21 12c0 5-4 9-9 9s-9-4-9-9 4-9 9-9 9 4 9 9z" /></svg>,
  tag: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M20 12l-8 8-9-9V3h8l9 9z" /><circle cx="7.5" cy="7.5" r="1.5" fill="currentColor" /></svg>
};

// ─── Animated counter ───────────────────────────────────────────────────────
function useCountUp(target, duration = 1400) {
  const [v, setV] = useState(0);
  useEffect(() => {
    let raf, start;
    const step = (t) => {
      if (!start) start = t;
      const p = Math.min(1, (t - start) / duration);
      // easeOutCubic
      const eased = 1 - Math.pow(1 - p, 3);
      setV(Math.round(target * eased));
      if (p < 1) raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf);
  }, [target, duration]);
  return v;
}

const DEFAULT_BETA_STATS = {
  totalSpots: 100,
  seedCount: 23,
  submittedCount: 0,
  claimedCount: 23,
  spotsLeft: 77,
  nextPosition: 24,
  isFull: false
};

function useBetaStats() {
  const [stats, setStats] = useState(DEFAULT_BETA_STATS);

  const refresh = useCallback(async () => {
    try {
      const response = await fetch("/api/beta-stats", { cache: "no-store" });
      const result = await response.json();

      if (result && result.ok) {
        setStats({
          totalSpots: result.totalSpots ?? DEFAULT_BETA_STATS.totalSpots,
          seedCount: result.seedCount ?? DEFAULT_BETA_STATS.seedCount,
          submittedCount: result.submittedCount ?? DEFAULT_BETA_STATS.submittedCount,
          claimedCount: result.claimedCount ?? DEFAULT_BETA_STATS.claimedCount,
          spotsLeft: result.spotsLeft ?? DEFAULT_BETA_STATS.spotsLeft,
          nextPosition: result.nextPosition ?? DEFAULT_BETA_STATS.nextPosition,
          isFull: Boolean(result.isFull)
        });
      }
    } catch (error) {
      setStats(DEFAULT_BETA_STATS);
    }
  }, []);

  useEffect(() => {
    refresh();
  }, [refresh]);

  return { stats, refresh };
}

// ─── Mini editor mockup for the hero ────────────────────────────────────────
function HeroMockup({ accent }) {
  const [tick, setTick] = useState(0);
  useEffect(() => {
    const id = setInterval(() => setTick((t) => (t + 1) % 4), 1800);
    return () => clearInterval(id);
  }, []);

  return (
    <div className="hero-mockup">
      {/* Window chrome */}
      <div className="mock-chrome">
        <div className="mock-dots">
          <span /><span /><span />
        </div>
        <div className="mock-url">
          <span className="mock-dot-live" />
          biznes.webbrain.ru/cafe-bloom
        </div>
        <div className="mock-pub">
          <Ic.spark width="11" height="11" /> AI
        </div>
      </div>

      <div className="mock-body">
        {/* Chat panel */}
        <aside className="mock-chat">
          <div className="mock-chat-hd">
            <span className="mock-chat-dot" />
            <span>Чат · WebBrain</span>
          </div>

          <div className="mock-bubble mock-bubble-user">
            Сделай сайт для&nbsp;кофейни — атмосферный первый экран, меню и&nbsp;бронь столика.
          </div>
          <div className="mock-bubble mock-bubble-ai">
            <Ic.spark width="10" height="10" style={{ marginRight: 4, opacity: .9 }} />
            Готово. Лендинг для&nbsp;Cafe Bloom.
            <div className="mock-chips">
              <span>Меню</span>
              <span>Бронь</span>
              <span>Кнопка</span>
            </div>
          </div>

          <div className="mock-bubble mock-bubble-user mock-typing">
            <span /><span /><span />
          </div>

          <div className="mock-input">
            <Ic.spark width="11" height="11" style={{ opacity: .8 }} />
            <span>Замени фото на&nbsp;утренний свет…</span>
            <span className="mock-send"><Ic.send width="11" height="11" /></span>
          </div>
        </aside>

        {/* Site preview */}
        <div className="mock-site">
          <div className="mock-site-nav">
            <span className="mock-logo">Cafe Bloom</span>
            <div className="mock-site-nav-links">
              <span>Меню</span><span>О&nbsp;нас</span><span>Контакты</span>
              <span className="mock-site-cta">Забронировать</span>
            </div>
          </div>
          <div className="mock-site-hero">
            <div className="mock-site-hero-bg" />
            <div className="mock-site-hero-text">
              <div className="mock-site-eyebrow">Кофе и&nbsp;утро</div>
              <div className="mock-site-h1">
                Зерно сегодняшнего&nbsp;дня.
                <br />
                Завтрак до&nbsp;12:00.
              </div>
              <div className="mock-site-btns">
                <span className="mock-site-btn-primary">Забронировать</span>
                <span className="mock-site-btn-ghost">Меню →</span>
              </div>
            </div>
            <div className={`mock-cursor mock-cursor-${tick}`}>
              <svg viewBox="0 0 16 16" width="16" height="16">
                <path d="M2 2l5 12 2-5 5-2-12-5z" fill="white" stroke="black" strokeWidth=".7" />
              </svg>
              <span>Замена изображения…</span>
            </div>
            <div className="mock-site-section-stub mock-site-section-stub-1" />
            <div className="mock-site-section-stub mock-site-section-stub-2" />
          </div>
        </div>
      </div>

      {/* Live status footer */}
      <div className="mock-status">
        <span className="mock-status-pill">
          <Ic.bolt width="10" height="10" /> Опубликовано
        </span>
        <span className="mock-status-meta">сборка 0:24 · кэш свежий · CDN Москва</span>
        <span className="mock-status-leads">
          3 заявки сегодня
          <Ic.dot width="6" height="6" style={{ color: accent.hex }} />
        </span>
      </div>
    </div>);

}

// ─── Beta signup form ───────────────────────────────────────────────────────
function BetaForm({ ctaLabel, accent, betaStats, onSubmit, compact = false }) {
  const [email, setEmail] = useState("");
  const [submitted, setSubmitted] = useState(false);
  const [pending, setPending] = useState(false);
  const [position, setPosition] = useState(null);

  const valid = email.includes("@") && email.includes(".");

  const submit = async (e) => {
    e.preventDefault();
    if (!valid || pending) return;

    const pos = betaStats?.nextPosition || 24;
    setPosition(pos);
    setPending(true);

    let redirectUrl = "/api/beta-request";

    try {
      const response = await fetch("/api/beta-request", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          email,
          source: window.location.href,
          page: "landing-beta"
        })
      });
      const result = await response.json().catch(() => ({}));
      redirectUrl = result.telegramBotUrl || result.telegramUrl || "https://t.me/aleksey_gredasov_ai";
      const confirmedPosition = result.position || pos;
      setPosition(confirmedPosition);
      onSubmit && onSubmit({ email, position: confirmedPosition, telegramSent: Boolean(result.telegramSent) });
    } catch (error) {
      redirectUrl = "https://t.me/aleksey_gredasov_ai";
    } finally {
      setSubmitted(true);
      window.setTimeout(() => {
        window.location.href = redirectUrl;
      }, 180);
    }
  };

  if (submitted) {
    return (
      <div className={`beta-form beta-form-success ${compact ? "is-compact" : ""}`}>
        <div className="success-icon">
          <Ic.check width="22" height="22" />
        </div>
        <div className="success-title">Вы в&nbsp;листе.</div>
        <div className="success-sub">
          Место&nbsp;
          <span className="success-num">№{String(position).padStart(2, "0")}</span>
          &nbsp;за&nbsp;вами. Заявка принята на&nbsp;<b>{email}</b>. Сейчас откроем Telegram, чтобы продолжить там.
        </div>
        <span className="success-tg">
          <Ic.tg width="14" height="14" /> Переходим в&nbsp;Telegram
        </span>
      </div>);

  }

  return (
    <form onSubmit={submit} className={`beta-form ${compact ? "is-compact" : ""}`}>
      <div className="beta-field-row">
        <label className="beta-field beta-field-email">
          <span className="beta-label">Почта</span>
          <input
            type="email"
            required
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            placeholder="you@company.ru"
            autoComplete="email" />
          
        </label>
      </div>

      <button
        type="submit"
        className="beta-submit"
        disabled={!valid || pending || betaStats?.isFull}
        style={{ "--cta-accent": accent.hex, "--cta-accent-rgb": accent.rgb }}>
        
        <span>{betaStats?.isFull ? "Места закончились" : pending ? "Отправляем заявку..." : ctaLabel}</span>
        <Ic.arrow width="16" height="16" />
      </button>

      <div className="beta-finerprint">
        <Ic.shield width="11" height="11" /> Без спама. Уведомим, когда место откроется.
      </div>
    </form>);

}

// ─── HERO ───────────────────────────────────────────────────────────────────
function Hero({ tweaks, accent, betaStats, onLeadSubmitted }) {
  const variant = HERO_VARIANTS[tweaks.heroVariant] || HERO_VARIANTS.outcome;
  const ctaLabel = CTA_LABELS[tweaks.ctaText] || CTA_LABELS["early-access"];
  const spotsLeft = betaStats.spotsLeft;
  const spotsTotal = betaStats.totalSpots;
  const claimedCount = betaStats.claimedCount;
  const inWaitlist = useCountUp(claimedCount, 1600);

  const renderH1 = () =>
  variant.h1.map((chunk, i) => {
    if (typeof chunk === "string") {
      // Force line break on double-space sentinel
      if (chunk.startsWith("  ")) {
        return <React.Fragment key={i}><br />{chunk.slice(2)}</React.Fragment>;
      }
      return <React.Fragment key={i}>{chunk}</React.Fragment>;
    }
    return <span key={i} className="hero-accent">{chunk.accent}</span>;
  });

  return (
    <section className="hero">
      <div className="hero-bg" aria-hidden="true">
        <div className="hero-bg-radial" />
        <div className="hero-bg-grid" />
        <div className="hero-bg-vignette" />
      </div>

      <div className="hero-grid">
        {/* LEFT */}
        <div className="hero-left">
          <div className="hero-badge hero-anim hero-anim-1">
            <span className="hero-badge-dot">
              <span className="hero-badge-dot-inner" />
            </span>
            {variant.badge}
            <span className="hero-badge-meta">{claimedCount} / {spotsTotal}</span>
          </div>

          <h1 className="hero-h1 hero-anim hero-anim-2">{renderH1()}</h1>

          <p className="hero-sub hero-anim hero-anim-3">{variant.sub}</p>

          <div className="hero-form-wrap hero-anim hero-anim-4">
            <BetaForm ctaLabel={ctaLabel} accent={accent} betaStats={betaStats} onSubmit={onLeadSubmitted} />
          </div>

          <div className="hero-trust hero-anim hero-anim-5">
            <span>
              <b>{inWaitlist}</b> уже в&nbsp;листе ожидания
            </span>
            <span className="hero-trust-sep" />
            <span>Цена основателя&nbsp;— навсегда</span>
            <span className="hero-trust-sep" />
            <span>ЮKassa</span>
          </div>
        </div>

        {/* RIGHT */}
        <div className="hero-right hero-anim hero-anim-mockup">
          <HeroMockup accent={accent} />
        </div>
      </div>
    </section>);

}

// ─── COUNTER STRIP ──────────────────────────────────────────────────────────
function CounterStrip({ tweaks, accent, betaStats }) {
  if (!tweaks.showCounter) return null;
  const total = betaStats.totalSpots;
  const left = betaStats.spotsLeft;
  const filled = betaStats.claimedCount;
  const filledAnim = useCountUp(filled, 1400);
  const pct = filled / total * 100;

  return (
    <section className="counter-strip">
      <div className="counter-grid reveal" style={{ "--final-pct": `${pct}%` }}>
        <div className="counter-lead">
          <div className="counter-eyebrow">
            <Ic.bolt width="11" height="11" /> Закрытая бета
          </div>
          <div className="counter-headline">
            Осталось&nbsp;
            <span className="counter-big" style={{ color: accent.hex }}>{left}</span>
            &nbsp;мест из&nbsp;{total}
          </div>
        </div>

        <div className="counter-bar-wrap">
          <div className="counter-bar">
            <div
              className="counter-bar-fill"
              style={{ width: `${pct}%`, background: accent.hex }} />
            
            <div className="counter-bar-ticks">
              {Array.from({ length: 20 }, (_, i) => <span key={i} />)}
            </div>
          </div>
          <div className="counter-bar-meta">
            <span><b style={{ color: accent.hex }}>{filledAnim}</b> заняли</span>
            <span>До&nbsp;15&nbsp;июля&nbsp;2026 или&nbsp;до&nbsp;100&nbsp;мест</span>
          </div>
        </div>

        <a href="#beta-form" className="counter-cta" style={{ "--cta-accent": accent.hex, "--cta-accent-rgb": accent.rgb }}>
          Занять место <Ic.arrow width="14" height="14" />
        </a>
      </div>
    </section>);

}

// ─── BENEFITS ───────────────────────────────────────────────────────────────
const BENEFITS = [
{
  Icon: Ic.msg,
  title: "Сайт начинается с диалога",
  body: "AI уточняет нишу, CTA, стиль, форму заявки и ограничения. На выходе не пустой шаблон, а структура под задачу бизнеса.",
  stat: "brief"
},
{
  Icon: Ic.chart,
  title: "Заявки видны сразу",
  body: "Форма, Telegram-уведомления и базовая аналитика готовятся вместе со страницей, чтобы сайт не был просто красивой картинкой.",
  stat: "leads"
},
{
  Icon: Ic.layers,
  title: "Редактор после генерации",
  body: "Первую версию можно править визуально: менять тексты, секции, блоки и акценты без ожидания верстальщика.",
  stat: "edit"
},
{
  Icon: Ic.shield,
  title: "Домен и инфраструктура",
  body: "Публикация, SSL и базовая защита форм продуманы заранее. В бете часть интеграций будет открываться поэтапно.",
  stat: "ssl"
}];


function BenefitsSection({ accent }) {
  return (
    <section className="benefits" id="benefits">
      <div className="section-head reveal">
        <div className="section-eyebrow" style={{ color: accent.hex, borderColor: `rgba(${accent.rgb}, .3)` }}>
          <Ic.spark width="11" height="11" /> Преимущества
        </div>
        <h2 className="section-h2">
          Не просто страница.
          <br />
          <span style={{ color: accent.hex }}>Рабочая система для заявок.</span>
        </h2>
        <p className="section-sub">
          WebBrain собирает первый лендинг вокруг действия пользователя: что нажать, куда оставить заявку и как не потерять контакт.
        </p>
      </div>

      <div className="benefits-grid">
        {BENEFITS.map((b, i) =>
        <article key={b.stat} className="benefit-card reveal" style={{ "--reveal-delay": `${i * 90}ms` }}>
            <div className="benefit-icon" style={{ color: accent.hex, borderColor: `rgba(${accent.rgb}, .34)` }}>
              <b.Icon width="19" height="19" />
            </div>
            <div className="benefit-kicker" style={{ color: accent.hex }}>{b.stat}</div>
            <h3 className="benefit-title">{b.title}</h3>
            <p className="benefit-body">{b.body}</p>
          </article>
        )}
      </div>
    </section>);

}

// ─── HOW IT WORKS ───────────────────────────────────────────────────────────
const STEPS = [
{
  n: "01",
  title: "Опишите бизнес в чате",
  body: "Ниша, услуги, кто клиент, что должен делать сайт. Никаких шаблонов с рыбой — AI спросит главное и соберёт структуру.",
  bullet: "5–7 вопросов · 3 минуты"
},
{
  n: "02",
  title: "AI собирает работающий лендинг",
  body: "Первый экран, преимущества, кейсы, форма, кнопка — с текстами под ваш бизнес. Не «рыба», а готовая копия с конверсионной логикой.",
  bullet: "30 секунд · реальная копия"
},
{
  n: "03",
  title: "Дорабатываете и публикуете",
  body: "Меняете тексты и блоки в визуальном редакторе. Подключаете свой домен. Заявки идут в Telegram и встроенную CRM.",
  bullet: "1 клик · biznes.webbrain.ru или свой домен"
}];


function StepMock({ n, accent }) {
  if (n === "01") {
    return (
      <div className="step-mock step-mock-1">
        <div className="step-mock-q">
          <div className="step-mock-label">Вопрос 3 из&nbsp;6</div>
          <div className="step-mock-text">Кто ваш клиент?</div>
          <div className="step-mock-pills">
            <span>Локальные жители</span>
            <span className="is-on" style={{ borderColor: accent.hex, color: accent.hex }}>Молодые семьи 25–40</span>
            <span>Туристы</span>
          </div>
        </div>
        <div className="step-mock-progress">
          <span style={{ width: "50%", background: accent.hex }} />
        </div>
      </div>);

  }
  if (n === "02") {
    return (
      <div className="step-mock step-mock-2">
        <div className="step-mock-line" style={{ width: "78%" }} />
        <div className="step-mock-line step-mock-line-h" />
        <div className="step-mock-cards">
          <div /><div /><div />
        </div>
        <div className="step-mock-form">
          <div className="step-mock-form-input" />
          <div className="step-mock-form-input" />
          <div className="step-mock-form-cta" style={{ background: accent.hex }} />
        </div>
        <div className="step-mock-spark" style={{ color: accent.hex }}>
          <Ic.spark width="11" height="11" /> Сгенерировано
        </div>
      </div>);

  }
  return (
    <div className="step-mock step-mock-3">
      <div className="step-mock-url">
        <span className="step-mock-url-dot" style={{ background: accent.hex }} />
        cafebloom.ru
      </div>
      <div className="step-mock-leads">
        <div className="step-mock-lead">
          <div className="step-mock-lead-avatar" />
          <div className="step-mock-lead-text">
            <div className="step-mock-lead-name">Анна К.</div>
            <div className="step-mock-lead-msg">Хочу столик на&nbsp;двоих, 19:00…</div>
          </div>
          <div className="step-mock-lead-time">2&nbsp;мин</div>
        </div>
        <div className="step-mock-lead">
          <div className="step-mock-lead-avatar" />
          <div className="step-mock-lead-text">
            <div className="step-mock-lead-name">Дмитрий</div>
            <div className="step-mock-lead-msg">Подскажите, есть&nbsp;ли веган-меню?</div>
          </div>
          <div className="step-mock-lead-time">17&nbsp;мин</div>
        </div>
      </div>
      <div className="step-mock-leads-meta" style={{ color: accent.hex }}>
        <Ic.bolt width="10" height="10" /> 3&nbsp;новые заявки сегодня
      </div>
    </div>);

}

function HowItWorks({ accent }) {
  return (
    <section className="how" id="how">
      <div className="section-head reveal">
        <div className="section-eyebrow">Как это работает</div>
        <h2 className="section-h2">
          От описания в&nbsp;чате до&nbsp;первой заявки —&nbsp;
          <span style={{ color: accent.hex }}>один вечер</span>.
        </h2>
      </div>

      <div className="steps-grid">
        {STEPS.map((s, i) =>
        <article key={s.n} className="step-card reveal" style={{ "--reveal-delay": `${i * 110}ms` }}>
            <div className="step-mock-wrap">
              <StepMock n={s.n} accent={accent} />
            </div>
            <div className="step-text">
              <div className="step-num" style={{ color: accent.hex }}>{s.n}</div>
              <h3 className="step-title">{s.title}</h3>
              <p className="step-body">{s.body}</p>
              <div className="step-bullet">{s.bullet}</div>
            </div>
          </article>
        )}
      </div>
    </section>);

}

// ─── FOUNDING MEMBERS ───────────────────────────────────────────────────────
const FOUNDING_BENEFITS = [
{
  Icon: Ic.tag,
  title: "Цена ×½ навсегда",
  body: "Тариф «Бизнес» — 1490 ₽/мес вместо 2990 ₽. Зафиксирован на весь период подписки, без пересмотра.",
  tag: "value"
},
{
  Icon: Ic.msg,
  title: "Прямой канал с командой",
  body: "Закрытый чат с основателями и инженерами. Баги чиним за день, фичи — приоритет в очереди.",
  tag: "access"
},
{
  Icon: Ic.vote,
  title: "Голос в плане развития",
  body: "Голосуете за фичи на ближайший квартал. AmoCRM, Битрикс24, квизы — что важнее лично вам.",
  tag: "control"
},
{
  Icon: Ic.layers,
  title: "Свой бренд на 90 дней раньше",
  body: "Для агентств: размещение под собственным брендом, командная работа и API открываются за 3 месяца до публичного релиза.",
  tag: "agency"
}];


function FoundingSection({ accent }) {
  return (
    <section className="founding" id="founding">
      <div className="section-head reveal">
        <div className="section-eyebrow" style={{ color: accent.hex }}>
          <Ic.spark width="11" height="11" /> Ранние участники
        </div>
        <h2 className="section-h2">
          Спокойные условия
          <br />
          <span style={{ color: accent.hex }}>для первых команд.</span>
        </h2>
        <p className="section-sub">
          Мы фиксируем понятные ранние условия и внимательно собираем обратную связь, чтобы развивать WebBrain вместе с реальными проектами.
        </p>
      </div>

      <div className="founding-grid">
        {FOUNDING_BENEFITS.map((b, i) =>
        <article key={i} className="founding-card reveal" data-tag={b.tag} style={{ "--reveal-delay": `${i * 90}ms` }}>
            <div className="founding-icon" style={{ color: accent.hex, borderColor: `rgba(${accent.rgb}, .35)` }}>
              <b.Icon width="18" height="18" />
            </div>
            <h3 className="founding-title">{b.title}</h3>
            <p className="founding-body">{b.body}</p>
            <div className="founding-stamp" style={{ color: accent.hex }}>РАННИЕ</div>
          </article>
        )}
      </div>
    </section>);

}

// ─── COMPARISON ─────────────────────────────────────────────────────────────
const COMP_ROWS = [
{ label: "AI-генерация лендинга из промпта", wb: true, ti: false },
{ label: "Цена за 1 сайт", wb: "990 ₽/мес*", ti: "1 250 ₽/мес" },
{ label: "Время от старта до публикации", wb: "~30 мин", ti: "часы / дни" },
{ label: "Конструктор форм + защита от спама", wb: true, ti: true },
{ label: "Уведомления в Telegram из коробки", wb: true, ti: false },
{ label: "Свой домен с авто-SSL", wb: true, ti: true },
{ label: "Встроенная CRM заявок", wb: true, ti: false },
{ label: "Тепловые карты кликов", wb: true, ti: false },
{ label: "AmoCRM / Битрикс24", wb: "Q3 2026", ti: true },
{ label: "ЮKassa", wb: true, ti: true }];


function ComparisonSection({ tweaks, accent }) {
  if (!tweaks.showComparison) return null;
  return (
    <section className="comp" id="vs">
      <div className="section-head reveal">
        <div className="section-eyebrow">Сравнение</div>
        <h2 className="section-h2">
          WebBrain vs конструкторы,
          <br />
          которые
          <br />
          <span style={{ color: accent.hex }}>застряли в&nbsp;2018&nbsp;году</span>.
        </h2>
      </div>

      <div className="comp-table reveal">
        <div className="comp-row comp-row-head">
          <div className="comp-cell-label" />
          <div className="comp-cell comp-cell-wb" style={{ color: accent.hex }}>
            WebBrain
            <span className="comp-cell-sub" style={{ color: `rgba(${accent.rgb}, .55)` }}>
              <Ic.spark width="9" height="9" /> AI в основе
            </span>
          </div>
          <div className="comp-cell comp-cell-ti">
            Tilda
            <span className="comp-cell-sub">конструктор</span>
          </div>
        </div>

        {COMP_ROWS.map((r, i) =>
        <div className="comp-row" key={i}>
            <div className="comp-cell-label">{r.label}</div>
            <div className="comp-cell comp-cell-wb">
              {r.wb === true ?
            <span className="comp-y" style={{ color: accent.hex }}><Ic.check width="16" height="16" /></span> :
            r.wb === false ?
            <span className="comp-n"><Ic.x width="16" height="16" /></span> :
            <span className="comp-val" style={{ color: accent.hex }}>{r.wb}</span>}
            </div>
            <div className="comp-cell comp-cell-ti">
              {r.ti === true ?
            <span className="comp-y"><Ic.check width="16" height="16" /></span> :
            r.ti === false ?
            <span className="comp-n"><Ic.x width="16" height="16" /></span> :
            <span className="comp-val">{r.ti}</span>}
            </div>
          </div>
        )}
      </div>

      <div className="comp-foot">
        <span>* цена для участников ранней беты. Публичный тариф «Старт» — 990 ₽/мес после релиза.</span>
        <span>В бете часть функций и интеграций может открываться поэтапно — актуальный доступ покажем перед подключением.</span>
      </div>
    </section>);

}

// ─── FAQ ────────────────────────────────────────────────────────────────────
const FAQ = [
{
  q: "Когда я смогу зайти в продукт?",
  a: "Доступ открываем волнами по 20–25 человек в неделю. Если место зарезервировано — приглашение придёт на email и в Telegram в течение 5–7 дней. Первые волны — фрилансеры и микро-бизнес, агентства — со 2-й по 4-ю."
},
{
  q: "Сколько это будет стоить после беты?",
  a: "Публичный прайс: 990 / 2990 / 7990 ₽ за «Старт» / «Бизнес» / «Агентство». Если вы вошли в бету — за вами навсегда зафиксирован тариф «Бизнес» за 1 490 ₽/мес, пока подписка активна."
},
{
  q: "Можно ли использовать сайт коммерчески уже сейчас?",
  a: "Да. Все сайты, опубликованные во время беты, остаются вашими и продолжают работать после релиза. Заявки идут на ваш email и в Telegram, домен ваш — вы ничего не теряете при переходе на публичный план."
},
{
  q: "Я агентство. Что мне даёт бета?",
  a: "Размещение под своим брендом, командный доступ и API открываются для ранних агентств за 90 дней до публичного релиза. Плюс 30% регулярная комиссия за каждого приведённого клиента в первые 6 месяцев."
},
{
  q: "Что если AI соберёт сайт, который мне не нравится?",
  a: "Дорабатываете в визуальном редакторе — двигаете блоки, меняете тексты и изображения, как в Tilda. AI — это старт, не клетка. На пилоте средний пользователь редактирует ~40% от первой версии."
},
{
  q: "Какие данные вы собираете на этапе заявки?",
  a: "Email — обязательно (для приглашения), Telegram — для канала с командой, ниша — чтобы понять приоритет очереди. Данные не передаются третьим лицам, используются только для приглашения в бету."
}];


function FaqSection({ accent }) {
  const [open, setOpen] = useState(0);
  return (
    <section className="faq" id="faq">
      <div className="section-head reveal">
        <div className="section-eyebrow">Частые вопросы</div>
        <h2 className="section-h2">
          Что важно знать
          <br />
          <span style={{ color: accent.hex }}>до того, как занять место</span>.
        </h2>
      </div>

      <div className="faq-list">
        {FAQ.map((item, i) => {
          const isOpen = open === i;
          return (
            <div key={i} className={`faq-item reveal ${isOpen ? "is-open" : ""}`} style={{ "--reveal-delay": `${i * 60}ms` }}>
              <button
                className="faq-q"
                onClick={() => setOpen(isOpen ? -1 : i)}
                aria-expanded={isOpen}>
                
                <span className="faq-q-num" style={{ color: isOpen ? accent.hex : undefined }}>
                  {String(i + 1).padStart(2, "0")}
                </span>
                <span className="faq-q-text">{item.q}</span>
                <Ic.plus
                  width="18"
                  height="18"
                  className="faq-q-icon"
                  style={{ transform: isOpen ? "rotate(45deg)" : "none" }} />
                
              </button>
              <div className={`faq-a ${isOpen ? "is-open" : ""}`}>
                <div className="faq-a-inner">{item.a}</div>
              </div>
            </div>);

        })}
      </div>
    </section>);

}

// ─── FINAL CTA ──────────────────────────────────────────────────────────────
function FinalCTA({ tweaks, accent, betaStats, onLeadSubmitted }) {
  const ctaLabel = CTA_LABELS[tweaks.ctaText] || CTA_LABELS["early-access"];
  const spotsLeft = betaStats.spotsLeft;
  return (
    <section className="final" id="beta-form">
      <div className="final-bg" aria-hidden="true">
        <div className="final-bg-radial" style={{ background: `radial-gradient(ellipse at 30% 40%, rgba(${accent.rgb}, .14), transparent 55%)` }} />
        <div className="final-bg-grid" />
      </div>

      <div className="final-grid">
        <div className="final-left reveal">
          <div className="final-eyebrow">
            <span className="final-eyebrow-dot" style={{ background: accent.hex }} />
            Закрытая бета · {spotsLeft} мест осталось
          </div>
          <h2 className="final-h2">
            Первая заявка с&nbsp;сайта —&nbsp;
            <span style={{ color: accent.hex }}>сегодня&nbsp;вечером</span>.
          </h2>
          <p className="final-sub">
            Опишите бизнес в&nbsp;чате после того, как мы&nbsp;пришлём вам ссылку. Получите рабочий сайт с&nbsp;формой и&nbsp;аналитикой за&nbsp;один вечер. Не&nbsp;шаблон — лендинг под&nbsp;вашу нишу.
          </p>

          <div className="final-stats">
            <div className="final-stat">
              <div className="final-stat-num" style={{ color: accent.hex }}>30<span>мин</span></div>
              <div className="final-stat-label">до&nbsp;первой публикации</div>
            </div>
            <div className="final-stat">
              <div className="final-stat-num" style={{ color: accent.hex }}>−50<span>%</span></div>
              <div className="final-stat-label">от&nbsp;цены навсегда</div>
            </div>
            <div className="final-stat">
              <div className="final-stat-num" style={{ color: accent.hex }}>1<span>чат</span></div>
              <div className="final-stat-label">вместо&nbsp;3&nbsp;подрядчиков</div>
            </div>
          </div>
        </div>

        <div className="final-right reveal" style={{ "--reveal-delay": "120ms" }}>
          <div className="final-form-card">
            <div className="final-form-head">
              <span className="final-form-pill" style={{ background: `rgba(${accent.rgb}, .14)`, color: accent.hex }}>
                <Ic.bolt width="11" height="11" /> Закрытая бета
              </span>
              <span className="final-form-meta">Заявка занимает 30&nbsp;секунд</span>
            </div>
            <BetaForm ctaLabel={ctaLabel} accent={accent} betaStats={betaStats} onSubmit={onLeadSubmitted} compact />
          </div>

          <a href="#telegram" className="final-tg" id="telegram">
            <Ic.tg width="16" height="16" />
            <span>
              <b>Дневник запуска в&nbsp;Telegram</b>
              <span className="final-tg-sub">— строим российский AI-конструктор публично</span>
            </span>
            <Ic.arrow width="14" height="14" />
          </a>
        </div>
      </div>
    </section>);

}

// ─── FOOTER ─────────────────────────────────────────────────────────────────
function Footer() {
  return (
    <footer className="foot">
      <div className="foot-grid">
        <div className="foot-brand">
          <div className="foot-logo">
            Web<span className="foot-logo-accent">Brain</span>
          </div>
          <div className="foot-tag">AI-конструктор сайтов · Россия · {new Date().getFullYear()}</div>
        </div>
        <div className="foot-links">
          <a href="#how">Как работает</a>
          <a href="#benefits">Преимущества</a>
          <a href="#vs">Сравнение</a>
          <a href="#faq">Вопросы</a>
          <a href="#telegram">Telegram</a>
        </div>
        <div className="foot-legal">
          Договор оферты · Политика конфиденциальности
        </div>
      </div>
    </footer>);

}

// ─── TWEAKS PANEL ───────────────────────────────────────────────────────────
function Tweaks({ tweaks, setTweak }) {
  return (
    <TweaksPanel>
      <TweakSection label="Hero" />
      <TweakRadio
        label="Сценарий копи"
        value={tweaks.heroVariant}
        options={[
        { label: "Outcome", value: "outcome" },
        { label: "Aggressive", value: "aggressive" },
        { label: "Speed", value: "speed" }]
        }
        onChange={(v) => setTweak("heroVariant", v)} />
      
      <TweakRadio
        label="Текст CTA"
        value={tweaks.ctaText}
        options={[
        { label: "Ранний доступ", value: "early-access" },
        { label: "В бету", value: "enter-beta" },
        { label: "Бронь места", value: "reserve" }]
        }
        onChange={(v) => setTweak("ctaText", v)} />
      

      <TweakSection label="Brand" />
      <TweakColor
        label="Акцент"
        value={tweaks.accent}
        options={[ACCENTS.lime.hex, ACCENTS.cyan.hex, ACCENTS.violet.hex]}
        onChange={(v) => {
          const key = Object.keys(ACCENTS).find((k) => ACCENTS[k].hex === v);
          setTweak("accent", key || "lime");
        }} />
      

      <TweakSection label="Конверсия" />
      <TweakToggle
        label="Счётчик мест"
        value={tweaks.showCounter}
        onChange={(v) => setTweak("showCounter", v)} />
      
      <TweakToggle
        label="Сравнение с Tilda"
        value={tweaks.showComparison}
        onChange={(v) => setTweak("showComparison", v)} />
      
      <TweakSlider
        label="Свободно мест"
        value={tweaks.spotsLeft}
        min={5}
        max={100}
        unit=" / 100"
        onChange={(v) => setTweak("spotsLeft", v)} />
      
    </TweaksPanel>);

}

// ─── APP ────────────────────────────────────────────────────────────────────
function App() {
  const [tweaks, setTweak] = useTweaks(window.TWEAK_DEFAULTS);
  // Tweaks color picker stores a hex string; map back to ACCENTS key
  const accentKey = typeof tweaks.accent === "string" && ACCENTS[tweaks.accent] ?
  tweaks.accent :
  Object.keys(ACCENTS).find((k) => ACCENTS[k].hex === tweaks.accent) || "lime";
  const accent = ACCENTS[accentKey];
  const { stats: betaStats, refresh: refreshBetaStats } = useBetaStats();

  useScrollReveal();

  useEffect(() => {
    if (!window.location.hash) return;
    const target = document.querySelector(window.location.hash);
    if (!target) return;
    requestAnimationFrame(() => {
      target.scrollIntoView({ block: "start", behavior: "smooth" });
    });
  }, []);

  // Update CSS vars for accent
  useEffect(() => {
    const r = document.documentElement;
    r.style.setProperty("--accent", accent.hex);
    r.style.setProperty("--accent-rgb", accent.rgb);
    r.style.setProperty("--accent-text", accent.text);
    r.style.setProperty("--accent-soft", accent.soft);
  }, [accent]);

  return (
    <div className="page">
      <SiteHeader accent={accent} />
      <Hero tweaks={tweaks} accent={accent} betaStats={betaStats} onLeadSubmitted={refreshBetaStats} />
      <BenefitsSection accent={accent} />
      <CounterStrip tweaks={tweaks} accent={accent} betaStats={betaStats} />
      <HowItWorks accent={accent} />
      <ComparisonSection tweaks={tweaks} accent={accent} />
      <FoundingSection accent={accent} />
      <FaqSection accent={accent} />
      <FinalCTA tweaks={tweaks} accent={accent} betaStats={betaStats} onLeadSubmitted={refreshBetaStats} />
      <Footer />
      <Tweaks tweaks={tweaks} setTweak={setTweak} />
    </div>);

}

// ─── SITE HEADER ────────────────────────────────────────────────────────────
function HeaderLiquidGlassStatic() {
  const width = 800;
  const height = 200;
  const noiseStrength = 142;

  return (
    <span
      className="site-header-liquid-glass"
      style={{
        "--webbrain-glass-width": `${width}px`,
        "--webbrain-glass-height": `${height}px`,
        "--webbrain-glass-radius": "var(--webbrain-header-radius, 28px)",
        "--webbrain-glass-inner-shadow-color": "#000000",
        "--webbrain-glass-inner-shadow-blur": "21px",
        "--webbrain-glass-inner-shadow-spread": "-2px",
        "--webbrain-glass-tint-color": "rgba(255, 255, 255, 0)",
        "--webbrain-glass-tint-opacity": 0,
        "--webbrain-glass-frost-blur": "3px"
      }}
      aria-hidden="true">
      
      <svg
        className="site-header-liquid-glass__filters"
        viewBox={`0 0 ${width} ${height}`}
        preserveAspectRatio="none"
        role="presentation"
        focusable="false">
        
        <defs>
          <filter
            id="site-header-glass-distortion"
            x={-noiseStrength}
            y={-noiseStrength}
            width={width + noiseStrength * 2}
            height={height + noiseStrength * 2}
            filterUnits="userSpaceOnUse"
            colorInterpolationFilters="sRGB">
            
            <feTurbulence
              type="fractalNoise"
              baseFrequency="0.008"
              numOctaves="4"
              seed="11"
              stitchTiles="stitch"
              result="noise" />
            
            <feColorMatrix in="noise" type="saturate" values="0" result="monoNoise" />
            <feDisplacementMap
              in="SourceGraphic"
              in2="monoNoise"
              scale={noiseStrength}
              xChannelSelector="R"
              yChannelSelector="G"
              result="displaced" />
            
            <feGaussianBlur in="displaced" stdDeviation="3" result="frosted" />
            <feComposite in="frosted" in2="SourceGraphic" operator="over" />
          </filter>
        </defs>
      </svg>
      <span className="site-header-liquid-glass__frost" />
      <span className="site-header-liquid-glass__refraction" />
      <span className="site-header-liquid-glass__inner-shadow" />
    </span>);

}

function SiteHeader({ accent }) {
  const headerRef = useRef(null);

  useEffect(() => {
    const header = headerRef.current;
    if (!header) return;

    let frame = 0;
    let currentMetrics = null;
    let targetMetrics = null;

    const getTargetMetrics = () => {
      const viewportWidth = window.innerWidth;
      const scrollStart = 24;
      const scrollDistance = viewportWidth >= 1024 ? 1180 : 820;
      const progress = Math.min(1, Math.max(0, (window.scrollY - scrollStart) / scrollDistance));
      const easedProgress = progress * progress * progress * (progress * (progress * 6 - 15) + 10);
      const topGap = viewportWidth >= 768 ? 20 : 12;
      const startSideGap = viewportWidth >= 1024 ? 48 : 12;
      const endWidth = Math.min(viewportWidth - 24, viewportWidth >= 1024 ? 980 : viewportWidth - 24);
      const startWidth = viewportWidth - startSideGap * 2;
      const baseHeight = viewportWidth >= 768 ? 86 : viewportWidth >= 420 ? 70 : 64;
      const heightDelta = viewportWidth >= 768 ? 8 : 5;

      return {
        width: Math.max(0, startWidth + (endWidth - startWidth) * easedProgress),
        height: baseHeight - heightDelta * easedProgress,
        radius: (viewportWidth >= 540 ? 28 : 24) + 18 * easedProgress,
        top: topGap,
        y: -2 * easedProgress
      };
    };

    const applyMetrics = (metrics) => {
      header.style.setProperty("--webbrain-header-width", `${metrics.width}px`);
      header.style.setProperty("--webbrain-header-height", `${metrics.height}px`);
      header.style.setProperty("--webbrain-header-radius", `${metrics.radius}px`);
      header.style.setProperty("--webbrain-header-top", `${metrics.top}px`);
      header.style.setProperty("--webbrain-header-y", `${metrics.y}px`);
    };

    const animateHeader = () => {
      frame = 0;
      if (!targetMetrics) return;

      if (!currentMetrics) {
        currentMetrics = targetMetrics;
        applyMetrics(currentMetrics);
        return;
      }

      const smoothing = 0.075;
      currentMetrics = {
        width: currentMetrics.width + (targetMetrics.width - currentMetrics.width) * smoothing,
        height: currentMetrics.height + (targetMetrics.height - currentMetrics.height) * smoothing,
        radius: currentMetrics.radius + (targetMetrics.radius - currentMetrics.radius) * smoothing,
        top: currentMetrics.top + (targetMetrics.top - currentMetrics.top) * smoothing,
        y: currentMetrics.y + (targetMetrics.y - currentMetrics.y) * smoothing
      };

      const isSettled =
        Math.abs(currentMetrics.width - targetMetrics.width) < 0.25 &&
        Math.abs(currentMetrics.height - targetMetrics.height) < 0.05 &&
        Math.abs(currentMetrics.radius - targetMetrics.radius) < 0.05;

      if (isSettled) currentMetrics = targetMetrics;

      applyMetrics(currentMetrics);

      if (!isSettled) {
        frame = window.requestAnimationFrame(animateHeader);
      }
    };

    const requestUpdate = () => {
      targetMetrics = getTargetMetrics();
      if (frame) return;
      frame = window.requestAnimationFrame(animateHeader);
    };

    targetMetrics = getTargetMetrics();
    currentMetrics = targetMetrics;
    applyMetrics(currentMetrics);

    window.addEventListener("scroll", requestUpdate, { passive: true });
    window.addEventListener("resize", requestUpdate);

    return () => {
      if (frame) window.cancelAnimationFrame(frame);
      window.removeEventListener("scroll", requestUpdate);
      window.removeEventListener("resize", requestUpdate);
    };
  }, []);

  return (
    <header ref={headerRef} className="site-header">
      <div className="site-header-inner">
        <HeaderLiquidGlassStatic />
        <a href="#top" className="site-logo">
          Web<span style={{ color: accent.hex }}>Brain</span>
        </a>
        <nav className="site-nav">
          <a href="#how">Как работает</a>
          <a href="#benefits">Преимущества</a>
          <a href="#vs">Сравнение</a>
          <a href="#faq">Вопросы</a>
        </nav>
        <a
          href="#beta-form"
          className="site-cta"
          style={{ "--cta-accent": accent.hex, "--cta-accent-rgb": accent.rgb }}>
          
          В бету <Ic.arrow width="14" height="14" />
        </a>
      </div>
    </header>);

}

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