// Reusable icons (lucide-style stroke icons)
const Icon = ({name, size=20, stroke=1.7, ...rest}) => {
  const s = size;
  const sw = stroke;
  const props = { width:s, height:s, viewBox:"0 0 24 24", fill:"none", stroke:"currentColor", strokeWidth:sw, strokeLinecap:"round", strokeLinejoin:"round", ...rest };
  switch(name){
    case "telegram": return <svg {...props}><path d="m22 2-7 20-4-9-9-4z"/><path d="M22 2 11 13"/></svg>;
    case "arrow-right": return <svg {...props}><path d="M5 12h14"/><path d="m13 5 7 7-7 7"/></svg>;
    case "arrow-down": return <svg {...props}><path d="M12 5v14"/><path d="m19 12-7 7-7-7"/></svg>;
    case "check": return <svg {...props}><path d="M20 6 9 17l-5-5"/></svg>;
    case "x": return <svg {...props}><path d="M18 6 6 18M6 6l12 12"/></svg>;
    case "zoom-in": return <svg {...props}><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/><path d="M11 8v6M8 11h6"/></svg>;
    case "plus": return <svg {...props}><path d="M5 12h14"/><path d="M12 5v14"/></svg>;
    case "play": return <svg {...props}><polygon points="6 3 20 12 6 21 6 3" fill="currentColor" stroke="none"/></svg>;
    case "shuffle": return <svg {...props}><path d="M2 18h2c1.3 0 2.5-.5 3.4-1.4l8.2-8.2c.9-.9 2.1-1.4 3.4-1.4H22"/><path d="M2 6h2c1.3 0 2.5.5 3.4 1.4l1.6 1.6"/><path d="m14 15 1.6 1.6c.9.9 2.1 1.4 3.4 1.4H22"/><path d="m18 2 4 4-4 4"/><path d="m18 14 4 4-4 4"/></svg>;
    case "sparkles": return <svg {...props}><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/></svg>;
    case "file-x": return <svg {...props}><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="m9.5 12.5 5 5"/><path d="m14.5 12.5-5 5"/></svg>;
    case "compass": return <svg {...props}><circle cx="12" cy="12" r="10"/><polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76"/></svg>;
    case "camera": return <svg {...props}><path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/><circle cx="12" cy="13" r="3"/></svg>;
    case "shapes": return <svg {...props}><path d="M8.3 10a.7.7 0 0 1-.626-1.079L11.4 3a.7.7 0 0 1 1.198-.043L16.3 8.9a.7.7 0 0 1-.572 1.1Z"/><rect x="3" y="14" width="7" height="7" rx="1"/><circle cx="17.5" cy="17.5" r="3.5"/></svg>;
    case "users": return <svg {...props}><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>;
    case "shopping-bag": return <svg {...props}><path d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"/><path d="M3 6h18"/><path d="M16 10a4 4 0 0 1-8 0"/></svg>;
    case "bag": return <svg {...props}><path d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"/><path d="M3 6h18"/><path d="M16 10a4 4 0 0 1-8 0"/></svg>;
    case "diamond": return <svg {...props}><path d="M12 2 2 9l10 13 10-13-10-7Z"/><path d="M2 9h20"/></svg>;
    case "book-open": return <svg {...props}><path d="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg>;
    case "book": return <svg {...props}><path d="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg>;
    case "palette": return <svg {...props}><circle cx="13.5" cy="6.5" r=".5" fill="currentColor"/><circle cx="17.5" cy="10.5" r=".5" fill="currentColor"/><circle cx="8.5" cy="7.5" r=".5" fill="currentColor"/><circle cx="6.5" cy="12.5" r=".5" fill="currentColor"/><path d="M12 2a10 10 0 1 0 0 20 1.5 1.5 0 0 0 1.06-2.56A1.5 1.5 0 0 1 14.12 17H16a6 6 0 0 0 6-6 10 10 0 0 0-10-9z"/></svg>;
    case "instagram": return (
      <svg {...props}>
        <rect width="20" height="20" x="2" y="2" rx="5" ry="5"/>
        <path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"/>
        <line x1="17.5" x2="17.51" y1="6.5" y2="6.5"/>
      </svg>
    );
    default: return null;
  }
};

// data.jsx кладёт данные на window; отдельный Babel-файл не видит const из data.jsx — читаем явно.
const {
  PERSONAS, PROBLEMS, USE_CASES, MODULES, STEPS, FOR_WHO, TESTIMONIALS, FAQ, TG_POSTS,
  FOUNDER_IMG, FOUNDER_HERO_IMG, FOUNDER_VIDEO_DESKTOP, FOUNDER_VIDEO_MOBILE, FOUNDER_VIDEO_POSTER, CONSISTENCY, LIVE_TG_START, LIVE_TG_STUDENTS, HERO_STATS,
  STATS_ENDPOINT,
} = window;

// Cross-browser matchMedia listener (Safari 13- doesn't have addEventListener)
const mqlSubscribe = (mql, handler) => {
  if (mql.addEventListener) {
    mql.addEventListener("change", handler);
    return () => mql.removeEventListener("change", handler);
  }
  mql.addListener(handler);
  return () => mql.removeListener(handler);
};

// Persona card (procedural visual)
const PersonaBg = ({hue, seed=0}) => {
  // Deterministic offsets from id/hue
  const a = (hue + seed*40) % 360;
  const b = (hue + 60 + seed*30) % 360;
  return (
    <div className="bg" style={{
      background:`
        radial-gradient(70% 50% at ${30+seed*10}% ${25+seed*8}%, hsl(${a} 70% 24% / 0.7) 0%, transparent 60%),
        radial-gradient(80% 60% at ${70-seed*6}% ${75-seed*4}%, hsl(${b} 60% 18% / 0.55) 0%, transparent 60%),
        linear-gradient(170deg, hsl(${a} 30% 9%) 0%, hsl(${b} 25% 6%) 100%)
      `
    }}/>
  );
};

/** Count-up on first viewport entry (GPU-friendly). */
const CountUp = ({ to, duration = 1400, decimals = 0, className = "", suffix = "" }) => {
  const ref = React.useRef(null);
  const [val, setVal] = React.useState(0);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    const run = () => {
      const start = performance.now();
      const from = 0;
      const tick = (t) => {
        const p = Math.min(1, (t - start) / duration);
        const eased = 1 - Math.pow(1 - p, 3);
        const cur = from + (to - from) * eased;
        setVal(decimals ? Number(cur.toFixed(decimals)) : Math.round(cur));
        if (p < 1) requestAnimationFrame(tick);
      };
      if (reduce) { setVal(to); return; }
      requestAnimationFrame(tick);
    };
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) { run(); io.disconnect(); }
      });
    }, { threshold: 0.2 });
    io.observe(el);
    return () => io.disconnect();
  }, [to, duration, decimals]);
  return (
    <span ref={ref} className={className} aria-live="off">
      {val}{suffix}
    </span>
  );
};

const LiveCounter = ({ start = 0 }) => {
  const STAGE_1_DELAY = 20000;
  const STAGE_2_DELAY = 30000;
  const TOAST_DURATION = 1800; /* было 1200 */

  const [display, setDisplay] = React.useState(start);
  const [showToast, setShowToast] = React.useState(false);

  const realRef = React.useRef(null);
  const counterRef = React.useRef(null);
  const isVisibleRef = React.useRef(false);
  const stageRef = React.useRef(0);
  const elapsedRef = React.useRef(0);
  const lastTickRef = React.useRef(null);
  const tickIntervalRef = React.useRef(null);
  const toastTimerRef = React.useRef(null);
  const animationPlayedForRef = React.useRef(null);

  const showToastAnimation = () => {
    if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
    setShowToast(false);
    requestAnimationFrame(() => {
      setShowToast(true);
      toastTimerRef.current = setTimeout(() => setShowToast(false), TOAST_DURATION);
    });
  };

  const tick = React.useCallback(() => {
    if (!isVisibleRef.current) {
      lastTickRef.current = null;
      return;
    }

    const now = Date.now();
    if (lastTickRef.current === null) {
      lastTickRef.current = now;
      return;
    }

    const delta = now - lastTickRef.current;
    lastTickRef.current = now;
    elapsedRef.current += delta;

    const real = realRef.current;
    if (!real) return;
    const stage = stageRef.current;

    if (stage === 0 && elapsedRef.current >= STAGE_1_DELAY) {
      stageRef.current = 1;
      elapsedRef.current = 0;
      setDisplay(real - 1);
      showToastAnimation();
    } else if (stage === 1 && elapsedRef.current >= STAGE_2_DELAY) {
      stageRef.current = 2;
      elapsedRef.current = 0;
      setDisplay(real);
      showToastAnimation();
      if (tickIntervalRef.current) {
        clearInterval(tickIntervalRef.current);
        tickIntervalRef.current = null;
      }
    }
  }, []);

  const startAnimation = React.useCallback(() => {
    const real = realRef.current;
    if (!real || real < 3) return;
    if (animationPlayedForRef.current === real) return;
    animationPlayedForRef.current = real;

    stageRef.current = 0;
    elapsedRef.current = 0;
    lastTickRef.current = isVisibleRef.current ? Date.now() : null;
    setDisplay(real - 2);

    if (tickIntervalRef.current) clearInterval(tickIntervalRef.current);
    tickIntervalRef.current = setInterval(tick, 1000);
  }, [tick]);

  const handleRealUpdate = React.useCallback((newReal) => {
    const oldReal = realRef.current;
    realRef.current = newReal;

    if (oldReal === null) {
      if (isVisibleRef.current) startAnimation();
      return;
    }

    if (newReal === oldReal) return;

    if (newReal < oldReal) {
      setDisplay(newReal);
      animationPlayedForRef.current = newReal;
      stageRef.current = 2;
      if (tickIntervalRef.current) {
        clearInterval(tickIntervalRef.current);
        tickIntervalRef.current = null;
      }
      return;
    }

    animationPlayedForRef.current = null;
    if (isVisibleRef.current) startAnimation();
  }, [startAnimation]);

  React.useEffect(() => {
    if (typeof STATS_ENDPOINT === "undefined" || !STATS_ENDPOINT) return;

    let cancelled = false;
    let pollTimer = null;

    const fetchStats = async () => {
      try {
        const resp = await fetch(STATS_ENDPOINT, { method: "GET" });
        if (!resp.ok) throw new Error(`Stats API ${resp.status}`);
        const data = await resp.json();
        if (cancelled) return;
        if (typeof data.subscribers === "number" && data.subscribers > 0) {
          handleRealUpdate(data.subscribers);
        }
      } catch (err) {
        console.warn("[LiveCounter] fetch failed:", err.message);
      }
    };

    fetchStats();
    pollTimer = setInterval(fetchStats, 120000);

    return () => {
      cancelled = true;
      if (pollTimer) clearInterval(pollTimer);
      if (tickIntervalRef.current) clearInterval(tickIntervalRef.current);
      if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
    };
  }, [handleRealUpdate]);

  React.useEffect(() => {
    const node = counterRef.current;
    if (!node) return;

    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            isVisibleRef.current = true;
            lastTickRef.current = null;
            if (realRef.current !== null && animationPlayedForRef.current !== realRef.current) {
              startAnimation();
            }
          } else {
            isVisibleRef.current = false;
            lastTickRef.current = null;
          }
        });
      },
      { threshold: 0.3 }
    );

    observer.observe(node);
    return () => observer.disconnect();
  }, [startAnimation]);

  return (
    <div className="live-counter" ref={counterRef}>
      <span className="live-dot" aria-hidden="true"></span>
      <span className="live-counter-num" aria-live="off">
        {display.toLocaleString("ru-RU")}
      </span>
      {showToast && (
        <span className="live-counter-toast" aria-hidden="true">+1</span>
      )}
    </div>
  );
};

const useTilt = () => {
  const ref = React.useRef(null);
  const onMove = React.useCallback((e) => {
    const el = ref.current;
    if (!el || (window.matchMedia && !window.matchMedia("(hover: hover)").matches)) return;
    const r = el.getBoundingClientRect();
    const px = (e.clientX - r.left) / r.width;
    const py = (e.clientY - r.top) / r.height;
    const rx = (py - 0.5) * -10;
    const ry = (px - 0.5) * 12;
    el.style.setProperty("--mx", `${px * 100}%`);
    el.style.setProperty("--my", `${py * 100}%`);
    const inner = el.querySelector(".persona-inner");
    if (inner) inner.style.transform = `perspective(820px) rotateX(${rx}deg) rotateY(${ry}deg) translateZ(0)`;
  }, []);
  const onLeave = React.useCallback(() => {
    const el = ref.current;
    if (!el) return;
    const inner = el.querySelector(".persona-inner");
    if (inner) inner.style.transform = "perspective(820px) rotateX(0deg) rotateY(0deg)";
  }, []);
  return { ref, onMove, onLeave };
};

/** Hero particle field — inspired by Linear-style ambient depth (CSS/canvas, not Three.js). */
const ParticlesCanvas = ({ enabled }) => {
  const canvasRef = React.useRef(null);
  React.useEffect(() => {
    if (!enabled) return;
    const canvas = canvasRef.current;
    if (!canvas) return;
    const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduce) return;
    const ctx = canvas.getContext("2d");
    let raf;
    let mx = 0, my = 0, tx = 0, ty = 0;
    const onMm = (e) => {
      const sec = canvas.closest(".hero-wrap");
      if (!sec) return;
      const b = sec.getBoundingClientRect();
      mx = (e.clientX - b.left) / b.width - 0.5;
      my = (e.clientY - b.top) / b.height - 0.5;
    };
    const pts = [];
    const resize = () => {
      const sec = canvas.closest(".hero-wrap");
      if (!sec) return;
      const dpr = Math.min(2, window.devicePixelRatio || 1);
      const w = sec.clientWidth, h = sec.clientHeight;
      canvas.width = w * dpr;
      canvas.height = h * dpr;
      canvas.style.width = w + "px";
      canvas.style.height = h + "px";
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      pts.length = 0;
      const n = Math.min(55, Math.floor((w * h) / 9000));
      for (let i = 0; i < n; i++) {
        pts.push({ x: Math.random() * w, y: Math.random() * h, vx: (Math.random() - 0.5) * 0.15, vy: (Math.random() - 0.5) * 0.15 });
      }
    };
    resize();
    window.addEventListener("resize", resize);
    window.addEventListener("mousemove", onMm, { passive: true });
    let t0 = performance.now();
    const loop = (t) => {
      const sec = canvas.closest(".hero-wrap");
      if (!sec) return;
      const w = sec.clientWidth, h = sec.clientHeight;
      tx += (mx - tx) * 0.06;
      ty += (my - ty) * 0.06;
      const driftX = tx * 40, driftY = ty * 36;
      ctx.clearRect(0, 0, w, h);
      pts.forEach((p) => {
        p.x += p.vx + driftX * 0.002;
        p.y += p.vy + driftY * 0.002;
        if (p.x < 0 || p.x > w) p.vx *= -1;
        if (p.y < 0 || p.y > h) p.vy *= -1;
      });
      const dt = Math.min(40, t - t0);
      t0 = t;
      ctx.strokeStyle = "rgba(167,139,250,0.12)";
      ctx.lineWidth = 1;
      for (let i = 0; i < pts.length; i++) {
        for (let j = i + 1; j < pts.length; j++) {
          const dx = pts[i].x - pts[j].x, dy = pts[i].y - pts[j].y;
          const d = Math.hypot(dx, dy);
          if (d < 72) {
            ctx.globalAlpha = (1 - d / 72) * 0.35;
            ctx.beginPath();
            ctx.moveTo(pts[i].x, pts[i].y);
            ctx.lineTo(pts[j].x, pts[j].y);
            ctx.stroke();
          }
        }
      }
      ctx.globalAlpha = 0.45;
      ctx.fillStyle = "rgba(196,181,253,0.35)";
      pts.forEach((p) => {
        ctx.beginPath();
        ctx.arc(p.x, p.y, 1.1, 0, Math.PI * 2);
        ctx.fill();
      });
      ctx.globalAlpha = 1;
      raf = requestAnimationFrame(loop);
    };
    raf = requestAnimationFrame(loop);
    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener("resize", resize);
      window.removeEventListener("mousemove", onMm);
    };
  }, [enabled]);
  if (!enabled) return null;
  return <canvas ref={canvasRef} className="hero-canvas" aria-hidden="true"/>;
};

const Persona = ({ p, ix, onOpen }) => {
  const { ref, onMove, onLeave } = useTilt();
  const src = p.img || "";
  return (
    <div
      className="persona"
      ref={ref}
      onMouseMove={onMove}
      onMouseLeave={onLeave}
      onClick={(e) => onOpen && onOpen(p, e.currentTarget)}
      role="button"
      tabIndex={0}
      onKeyDown={(e) => {
        if ((e.key === "Enter" || e.key === " ") && onOpen) {
          e.preventDefault();
          onOpen(p, e.currentTarget);
        }
      }}
    >
      <div className="persona-inner">
        {src ? (
          <img className="persona-img" src={src} alt={`ИИ-персонаж № ${String(p.id).padStart(2, "0")}, ${p.tag}`} loading="lazy" decoding="async"/>
        ) : (
          <PersonaBg hue={p.hue} seed={ix}/>
        )}
        <div className="persona-shine"/>
        <div className="persona-tap-hint" aria-hidden="true">
          <Icon name="arrow-right" size={12}/>
        </div>
        <div className="overlay">
          <div className="open">открыть →</div>
        </div>
        <div className="persona-detail">
          <div className="eyebrow" style={{ fontSize: 9, marginBottom: 4 }}>META</div>
          <div className="row"><b>Стиль</b> — {p.style}</div>
          <div className="row"><b>Среда</b> — {p.env}</div>
          <div className="row"><b>Эстетика</b> — {p.aesthetic}</div>
        </div>
      </div>
      <div className="ix">№ {String(p.id).padStart(2, "0")}</div>
      <div className="meta">
        <div className="tag">{p.tag.split(" / ")[0]}</div>
        <div className="nm">{p.subtitle}</div>
      </div>
    </div>
  );
};

// ─── Sections ───────────────────────────────────────────────────────────────

const SectionHead = ({tag, title, subtitle, align="left", children}) => (
  <div className="section-head reveal" style={align==="center"?{marginLeft:"auto",marginRight:"auto",textAlign:"center",alignItems:"center"}:{}}>
    <span className="eyebrow">{tag}</span>
    <h2 className="display-2 text-balance">{title}</h2>
    {subtitle && <p className="text-pretty" style={{color:"var(--muted)",fontSize:"clamp(15px,1.3vw,17px)",maxWidth:560}}>{subtitle}</p>}
    {children}
  </div>
);

const ConsistencyCompare = () => {
  const L = CONSISTENCY.left;
  const R = CONSISTENCY.right;
  return (
    <section id="consistency" style={{ position: "relative", overflow: "hidden" }}>
      <div className="section-decorative-orb section-decorative-orb-violet" style={{ width: 480, height: 480, top: "-200px", left: "-100px" }}/>
      <div className="section-decorative-orb section-decorative-orb-pink" style={{ width: 360, height: 360, bottom: "-150px", right: "-80px" }}/>
      <div className="container">
        <SectionHead
          tag="Без системы / С системой"
          title="Одна и та же задача, разный результат"
          subtitle="Слева то, что получает большинство: каждая генерация выдаёт некачественное лицо, интересного персонажа нет. Справа то, что выходит по программе: один и тот же персонаж в любых сценах."
        />
        <div className="consistency-wrap reveal">
          <div className="consistency-headers">
            <div className="consistency-header consistency-header-bad">
              <div className="ch-meta">01 · Хаос</div>
              <div className="ch-label">Без системы</div>
              <div className="ch-sub">Каждая генерация: некачественное лицо</div>
            </div>

            <div className="consistency-divider-wrap" aria-hidden="true">
              <div className="consistency-divider-line"/>
              <div className="consistency-divider-icon">
                <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M5 12h14"/>
                  <path d="M13 6l6 6-6 6"/>
                </svg>
              </div>
            </div>

            <div className="consistency-header consistency-header-good">
              <div className="ch-meta">02 · Контроль</div>
              <div className="ch-label">С системой</div>
              <div className="ch-sub">Один персонаж в любых сценах</div>
            </div>
          </div>
          <div className="consistency-grid">
            <div className="consistency-side">
              <div className="consistency-photos">
                {L.map((c, i) => (
                  <div key={i} className="consistency-photo">
                    <img src={c.src} alt={`Вариант ${i + 1}, без системы контроля лица`} loading="lazy"/>
                  </div>
                ))}
              </div>
            </div>
            <div className="consistency-side">
              <div className="consistency-photos">
                {R.map((c, i) => (
                  <div key={i} className="consistency-photo">
                    <img src={c.src} alt={`Сцена ${i + 1}, согласованный персонаж`} loading="lazy"/>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
};

const AnimatedProcess = () => {
  const [isMobileProcess, setIsMobileProcess] = React.useState(() =>
    typeof window !== "undefined" ? window.innerWidth <= 720 : false
  );
  React.useEffect(() => {
    const check = () => setIsMobileProcess(window.innerWidth <= 720);
    check();
    window.addEventListener("resize", check);
    return () => window.removeEventListener("resize", check);
  }, []);

  if (isMobileProcess) {
    return (
      <div className="process-mobile">
        <div className="process-step">
          <div className="process-step-num">01</div>
          <div className="process-step-body">
            <div className="process-step-title">Идея</div>
            <div className="process-step-desc">Внешность, характер, история персонажа</div>
          </div>
        </div>
        <div className="process-step">
          <div className="process-step-num">02</div>
          <div className="process-step-body">
            <div className="process-step-title">Генерация</div>
            <div className="process-step-desc">Подготовка контента по проверенной стратегии</div>
          </div>
        </div>
        <div className="process-step">
          <div className="process-step-num">03</div>
          <div className="process-step-body">
            <div className="process-step-title">Продвижение</div>
            <div className="process-step-desc">Набор аудитории для ИИ-персонажа</div>
          </div>
        </div>
        <div className="process-step">
          <div className="process-step-num">04</div>
          <div className="process-step-body">
            <div className="process-step-title">Результат</div>
            <div className="process-step-desc">Раскрытие потенциала и масштабирование проекта</div>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="process-svg-wrap">
      <svg className="process-svg" viewBox="0 0 720 200" fill="none" xmlns="http://www.w3.org/2000/svg" aria-label="Схема: четыре шага создания ИИ-персонажа">
        <defs>
          <linearGradient id="flowGrad" x1="0" y1="0" x2="720" y2="0" gradientUnits="userSpaceOnUse">
            <stop stopColor="#7C3AED"/><stop offset="0.5" stopColor="#3B82F6"/><stop offset="1" stopColor="#E879F9"/>
          </linearGradient>
          <filter id="glowN" x="-50%" y="-50%" width="200%" height="200%">
            <feGaussianBlur stdDeviation="6" result="b"/>
            <feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
          </filter>
        </defs>
        <path d="M60 100 H180 M260 100 H340 M420 100 H500 M580 100 H660" stroke="url(#flowGrad)" strokeWidth="2" strokeLinecap="round" opacity="0.35"/>
        <path d="M60 100 H660" stroke="url(#flowGrad)" strokeWidth="2" strokeDasharray="12 10" opacity="0.9">
          <animate attributeName="stroke-dashoffset" from="0" to="-220" dur="3.5s" repeatCount="indefinite"/>
        </path>
        {[
          { cx: 120, label: "Идея", sub: ["Внешность, характер,", "история персонажа"] },
          { cx: 300, label: "Генерация", sub: ["Подготовка контента", "по проверенной стратегии"], core: true },
          { cx: 460, label: "Продвижение", sub: ["Набор аудитории", "для ИИ-персонажа"] },
          { cx: 620, label: "Результат", sub: ["Раскрытие потенциала", "и масштабирование"] },
        ].map((n, i) => (
          <g key={i} transform={`translate(${n.cx},100)`}>
            {!n.core && <circle r="22" fill="rgba(124,58,237,0.15)" stroke="rgba(255,255,255,0.12)"/>}
            {n.core && (
              <>
                <circle r="36" fill="rgba(232,121,249,0.12)" filter="url(#glowN)">
                  <animate attributeName="r" values="34;40;34" dur="2.4s" repeatCount="indefinite"/>
                </circle>
                <circle r="28" fill="rgba(17,17,26,0.9)" stroke="rgba(232,121,249,0.45)" strokeWidth="1.5"/>
              </>
            )}
            {!n.core && <circle r="18" fill="rgba(17,17,26,0.95)" stroke="rgba(124,58,237,0.35)" strokeWidth="1.2"/>}
            <text y="4" textAnchor="middle" fill="#F5F5F7" fontFamily="Space Grotesk, sans-serif" fontSize="13" fontWeight="600">{n.label}</text>
            <text x="0" y="22" textAnchor="middle" fill="#A0A0AB" fontFamily="JetBrains Mono, monospace" fontSize="8">
              <tspan x="0" dy="0">{n.sub[0]}</tspan>
              <tspan x="0" dy="11">{n.sub[1]}</tspan>
            </text>
          </g>
        ))}
      </svg>
    </div>
  );
};

// ScrollVideoHero — Apple-style scroll-driven canvas player.
// Pre-loads frame sequence, redraws canvas based on scroll progress.
// Mobile (pointer:coarse) falls back to autoplay-loop mp4.

const FRAME_COUNT = 120;
const FRAME_PATH = (i) => `frames/frame_${String(i).padStart(4, "0")}.webp`;
const MOBILE_FALLBACK_VIDEO = "mobile_loop.mp4";
const POSTER_IMG = "poster.jpg";
const INITIAL_PRELOAD = 30;

const ScrollVideoHero = ({ onCTA }) => {
  const containerRef = React.useRef(null);
  const canvasRef = React.useRef(null);
  const imagesRef = React.useRef([]);
  const currentFrameRef = React.useRef(0);
  const rafRef = React.useRef(null);
  const [loadProgress, setLoadProgress] = React.useState(0);
  const [ready, setReady] = React.useState(false);
  const [isMobile, setIsMobile] = React.useState(() =>
    typeof window !== "undefined"
    && (window.matchMedia("(pointer: coarse)").matches
      || window.matchMedia("(max-width: 720px)").matches)
  );

  React.useEffect(() => {
    const mqCoarse = window.matchMedia("(pointer: coarse)");
    const mqNarrow = window.matchMedia("(max-width: 720px)");
    const update = () => setIsMobile(mqCoarse.matches || mqNarrow.matches);
    update();
    const unsubCoarse = mqlSubscribe(mqCoarse, update);
    const unsubNarrow = mqlSubscribe(mqNarrow, update);
    window.addEventListener("resize", update);
    return () => {
      unsubCoarse();
      unsubNarrow();
      window.removeEventListener("resize", update);
    };
  }, []);

  React.useEffect(() => {
    if (isMobile) return;
    let cancelled = false;
    const imgs = new Array(FRAME_COUNT);
    let loadedCount = 0;
    let initialLoadedCount = 0;

    const loadOne = (i) => new Promise((resolve) => {
      const img = new Image();
      img.onload = () => {
        if (cancelled) return resolve();
        imgs[i] = img;
        loadedCount++;
        if (i < INITIAL_PRELOAD) initialLoadedCount++;
        setLoadProgress(Math.round((loadedCount / FRAME_COUNT) * 100));
        if (initialLoadedCount >= Math.min(INITIAL_PRELOAD, FRAME_COUNT)) setReady(true);
        resolve();
      };
      img.onerror = () => {
        console.warn(`Frame ${i + 1} failed`);
        loadedCount++;
        if (i < INITIAL_PRELOAD) initialLoadedCount++;
        setLoadProgress(Math.round((loadedCount / FRAME_COUNT) * 100));
        if (initialLoadedCount >= Math.min(INITIAL_PRELOAD, FRAME_COUNT)) setReady(true);
        resolve();
      };
      img.src = FRAME_PATH(i + 1);
    });

    const initial = [];
    for (let i = 0; i < Math.min(INITIAL_PRELOAD, FRAME_COUNT); i++) {
      initial.push(loadOne(i));
    }
    Promise.all(initial).then(() => {
      if (cancelled) return;
      const loadBatch = async () => {
        for (let i = INITIAL_PRELOAD; i < FRAME_COUNT; i += 10) {
          if (cancelled) return;
          const batch = [];
          for (let j = i; j < Math.min(i + 10, FRAME_COUNT); j++) {
            batch.push(loadOne(j));
          }
          await Promise.all(batch);
        }
      };
      loadBatch();
    });

    imagesRef.current = imgs;
    return () => { cancelled = true; };
  }, [isMobile]);

  const drawFrame = React.useCallback((idx) => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const img = imagesRef.current[idx];
    if (!img) return;
    const ctx = canvas.getContext("2d");
    const dpr = Math.min(window.devicePixelRatio || 1, 2);
    const cw = canvas.width / dpr;
    const ch = canvas.height / dpr;
    const iw = img.naturalWidth;
    const ih = img.naturalHeight;
    const scale = Math.max(cw / iw, ch / ih);
    const w = iw * scale;
    const h = ih * scale;
    const x = (cw - w) / 2;
    const y = (ch - h) / 2;
    ctx.clearRect(0, 0, cw, ch);
    ctx.drawImage(img, x, y, w, h);
  }, []);

  React.useEffect(() => {
    if (!ready || isMobile) return;
    drawFrame(0);
  }, [ready, isMobile, drawFrame]);

  React.useEffect(() => {
    if (isMobile) return;
    const canvas = canvasRef.current;
    if (!canvas) return;
    const resize = () => {
      const dpr = Math.min(window.devicePixelRatio || 1, 2);
      canvas.width = window.innerWidth * dpr;
      canvas.height = window.innerHeight * dpr;
      canvas.style.width = window.innerWidth + "px";
      canvas.style.height = window.innerHeight + "px";
      const ctx = canvas.getContext("2d");
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      drawFrame(currentFrameRef.current);
    };
    resize();
    window.addEventListener("resize", resize);
    return () => window.removeEventListener("resize", resize);
  }, [isMobile, ready, drawFrame]);

  React.useEffect(() => {
    if (isMobile || !ready) return;
    const container = containerRef.current;
    if (!container) return;
    const onScroll = () => {
      if (rafRef.current) return;
      rafRef.current = requestAnimationFrame(() => {
        rafRef.current = null;
        const rect = container.getBoundingClientRect();
        const total = container.offsetHeight - window.innerHeight;
        const scrolled = Math.max(0, Math.min(1, -rect.top / Math.max(1, total)));
        const targetFrame = Math.min(FRAME_COUNT - 1, Math.floor(scrolled * FRAME_COUNT));
        if (targetFrame !== currentFrameRef.current) {
          currentFrameRef.current = targetFrame;
          drawFrame(targetFrame);
        }
      });
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => {
      window.removeEventListener("scroll", onScroll);
      if (rafRef.current) cancelAnimationFrame(rafRef.current);
    };
  }, [ready, isMobile, drawFrame]);

  if (isMobile) {
    return (
      <section className="hero hero-video-scroll hero-mobile" id="hero">
        <video autoPlay muted loop playsInline poster={POSTER_IMG} className="hero-mobile-video">
          <source src={MOBILE_FALLBACK_VIDEO} type="video/mp4"/>
        </video>
        <div className="hero-mobile-overlay"/>
        <div className="hero-mobile-content">
          <div className="eyebrow">Обучение · Создание ИИ-персонажей</div>
          <h1 className="display-1 hero-h1">
            <span className="hero-h1-main">Один ИИ-персонаж.</span>
            <span className="hero-h1-main">Одно лицо.</span>
            <span className="hero-h1-accent">Десятки способов применить навык.</span>
          </h1>
          <p style={{color:"var(--muted)",fontSize:16,lineHeight:1.5,marginBottom:24,maxWidth:520}}>
            Системная программа по созданию ИИ-персонажей с нуля. Подходит и новичкам, и тем, кто уже пробовал создавать ИИ-блогера, но не получил стабильного результата.
          </p>
          <div className="hero-cta-row">
          <button type="button" onClick={onCTA} className="btn btn-primary" style={{width:"100%"}}>
            <Icon name="telegram" size={16}/><span>Получить бесплатный урок</span>
          </button>
          </div>
          <div className="hero-trust-line">
            Бесплатные материалы → попробуй → решай сам
          </div>
        </div>
      </section>
    );
  }

  return (
    <section ref={containerRef} className="hero hero-video-scroll hero-desktop" id="hero">
      {!ready && (
        <div className="hero-scroll-loading">
          <img src={POSTER_IMG} alt="" className="hero-scroll-poster"/>
          <div className="hero-scroll-loader">
            <div className="loader-bar"><div style={{width:`${loadProgress}%`}}/></div>
            <div className="mono" style={{fontSize:12,color:"var(--muted)",marginTop:8}}>
              Загрузка кадров… {loadProgress}%
            </div>
          </div>
        </div>
      )}
      <div className="hero-scroll-sticky">
        <canvas ref={canvasRef} className="hero-scroll-canvas"/>
        <div className="hero-scroll-overlay" aria-hidden="true"/>
        <div className="hero-scroll-content container">
          <div className="eyebrow">Обучение · Создание ИИ-персонажей</div>
          <h1 className="display-1 hero-h1">
            <span className="hero-h1-main">Один ИИ-персонаж.</span>
            <span className="hero-h1-main">Одно лицо.</span>
            <span className="hero-h1-accent">Десятки способов применить навык.</span>
          </h1>
          <p style={{color:"var(--muted)",fontSize:18,lineHeight:1.5,marginBottom:28,maxWidth:560}}>
            Системная программа по созданию ИИ-персонажей с нуля. Подходит и новичкам, и тем, кто уже пробовал создавать ИИ-блогера, но не получил стабильного результата.
          </p>
          <div className="hero-cta-row">
            <button type="button" onClick={onCTA} className="btn btn-primary">
              <Icon name="telegram" size={16}/><span>Получить бесплатный урок</span>
            </button>
            <a href="#modules" className="btn btn-ghost">
              <span>Посмотреть программу</span><Icon name="arrow-down" size={14}/>
            </a>
          </div>
          <div className="hero-trust-line">
            Бесплатные материалы → попробуй → решай сам
          </div>
        </div>
      </div>
    </section>
  );
};

const Hero = ({ variant, onCTA, particlesOn }) => {
  const wrapRef = React.useRef(null);
  const glowRef = React.useRef(null);

  React.useEffect(() => {
    const el = wrapRef.current;
    const glow = glowRef.current;
    if (!el || !glow) return;
    const fine = window.matchMedia("(pointer: fine)").matches;
    if (!fine) return;
    let lx = 50, ly = 40, tx = 50, ty = 40;
    const onMove = (e) => {
      const r = el.getBoundingClientRect();
      tx = ((e.clientX - r.left) / r.width) * 100;
      ty = ((e.clientY - r.top) / r.height) * 100;
    };
    let raf;
    const smooth = () => {
      lx += (tx - lx) * 0.08;
      ly += (ty - ly) * 0.08;
      glow.style.setProperty("--hx", `${lx}%`);
      glow.style.setProperty("--hy", `${ly}%`);
      raf = requestAnimationFrame(smooth);
    };
    raf = requestAnimationFrame(smooth);
    el.addEventListener("mousemove", onMove, { passive: true });
    return () => { cancelAnimationFrame(raf); el.removeEventListener("mousemove", onMove); };
  }, []);

  if (variant === "video-scroll") {
    return <ScrollVideoHero onCTA={onCTA}/>;
  }

  return (
    <section className="hero hero-wrap" id="hero" ref={wrapRef}>
      <ParticlesCanvas enabled={particlesOn}/>
      <div ref={glowRef} className="hero-cursor-glow"/>
      <div className="container hero-inner">
        <div className="hero-grid">
          <div>
            <span className="eyebrow reveal">Обучение · Создание ИИ-персонажей</span>
            <h1 className="hero-h1 display-1 text-balance" style={{ marginTop: 18 }}>
              <span className="text-reveal-line"><span>Создавай реалистичных</span></span>
              <span className="text-reveal-line"><span>ИИ-персонажей с нуля.</span></span>
              <span className="text-reveal-line line2" style={{ color: "var(--muted)", fontSize: "clamp(28px,4.2vw,52px)", letterSpacing: "-0.03em", marginTop: 8 }}><span>Без опыта и сложного ПО.</span></span>
            </h1>
            <p className="hero-sub text-pretty reveal" style={{ transitionDelay: ".15s" }}>
              Системная программа: от первого промпта до управляемого персонажа, который сохраняет лицо в десятках сцен. Доступно из любой точки мира — нужен только ноутбук и интернет.
            </p>
            <div className="hero-ctas reveal" style={{ transitionDelay: ".22s" }}>
              <MagneticBtn className="btn btn-primary btn-lg" onClick={onCTA}>
                <Icon name="telegram" size={18}/>
                <span>Получить бесплатный урок</span>
              </MagneticBtn>
              <a href="#modules" className="btn btn-ghost btn-lg">
                <span>Посмотреть программу</span>
                <span className="arrow"><Icon name="arrow-right" size={16}/></span>
              </a>
            </div>
            <div className="hero-trust reveal" style={{ transitionDelay: ".30s" }}>
              <Icon name="check" size={16}/>
              <span>Бесплатные материалы → попробуй → решай сам</span>
            </div>
          </div>

          <div className="reveal" style={{ transitionDelay: ".15s", position: "relative" }}>
            <HeroVisual variant={variant}/>
            {HERO_STATS.students != null && (
              <div className="floater f1"><span className="dot"/><span><CountUp to={HERO_STATS.students} className="floater-num"/>+ учеников</span></div>
            )}
            {HERO_STATS.personas != null && (
              <div className="floater f2"><span className="dot"/><span><CountUp to={HERO_STATS.personas} className="floater-num"/>+ персонажей</span></div>
            )}
            {HERO_STATS.rating != null && (
              <div className="floater f3"><span className="dot"/><span><CountUp to={HERO_STATS.rating} decimals={1} className="floater-num"/> ★ рейтинг материалов</span></div>
            )}
          </div>
        </div>
      </div>
    </section>
  );
};

const HeroVisual = ({variant}) => {
  if (variant === "mesh") return (
    <div className="hero-visual hv-mesh">
      <div className="b1"/><div className="b2"/><div className="b3"/>
      <div className="grid"/>
      <div className="skyline"/>
      <div className="horizon"/>
      <div className="core"/>
      <div className="label">CONSISTENCY ENGINE / v1.0</div>
      <div className="label-br"><span style={{width:6,height:6,borderRadius:999,background:"var(--accent)",boxShadow:"0 0 10px var(--accent), 0 0 20px var(--accent-glow)",display:"inline-block"}}/> live preview</div>
    </div>
  );
  if (variant === "collage") return (
    <div className="hero-visual hv-collage">
      <div className="grid">
        {[
          { n: "01", nm: "Editorial", img: PERSONAS[0]?.img },
          { n: "02", nm: "Urban", img: PERSONAS[1]?.img },
          { n: "03", nm: "Studio", img: PERSONAS[2]?.img },
          { n: "04", nm: "Outdoor", img: PERSONAS[8]?.img },
        ].map((t, i) => (
          <div key={i} className={`tile t${i + 1}`}>
            {t.img ? (
              <img src={t.img} alt="" style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" }}/>
            ) : (
              <PersonaBg hue={PERSONAS[i].hue} seed={i + 2}/>
            )}
            <div className="num">№ {t.n}</div>
            <div className="nm">{t.nm}</div>
          </div>
        ))}
      </div>
    </div>
  );
  // default: video
  return (
    <div className="hero-visual hv-video">
      <div className="frame"/>
      <div className="portrait">
        <img className="portrait-img" src={FOUNDER_HERO_IMG || FOUNDER_IMG} alt="Юлия — основатель программы MODELCORE" loading="eager" decoding="async"/>
        <div className="scan"/>
      </div>
      <button type="button" className="play" aria-label="Воспроизвести приветственное видео (скоро)"><Icon name="play" size={22}/></button>
      <div className="meta">
        <b>Юлия</b>
        <span>основатель программы · приветствие</span>
      </div>
    </div>
  );
};

// Magnetic CTA — pulls toward cursor on desktop
const MagneticBtn = ({className="", onClick, children, ...rest}) => {
  const ref = React.useRef();
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    if (window.matchMedia && window.matchMedia("(pointer: coarse)").matches) return;
    const r = 120;
    const handle = (e) => {
      const rect = el.getBoundingClientRect();
      const cx = rect.left + rect.width/2, cy = rect.top + rect.height/2;
      const dx = e.clientX - cx, dy = e.clientY - cy;
      const dist = Math.hypot(dx, dy);
      if (dist < r + Math.max(rect.width, rect.height)/2) {
        const f = Math.max(0, 1 - dist/(r*2));
        el.style.transform = `translate(${dx*0.18*f}px, ${dy*0.18*f}px)`;
      } else {
        el.style.transform = "";
      }
    };
    const reset = () => { el.style.transform = ""; };
    window.addEventListener("mousemove", handle);
    window.addEventListener("mouseleave", reset);
    return () => { window.removeEventListener("mousemove", handle); window.removeEventListener("mouseleave", reset); };
  }, []);
  return (
    <button ref={ref} className={className} onClick={onClick} {...rest}>{children}</button>
  );
};

const Problems = () => (
  <section id="problems">
    <div className="container">
      <SectionHead tag="В чём загвоздка" title="Пробовал, но результат не радует?" subtitle="Скорее всего, ты упирался в один из четырёх типичных тупиков. Дело не в тебе, а в подходе."/>
      <div className="reveal-stagger reveal" style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(240px,1fr))",gap:14}}>
        {PROBLEMS.map((p,i) => (
          <div key={i} className="card">
            <div className="card-icon"><Icon name={p.icon}/></div>
            <h3 style={{fontFamily:"var(--font-display)",fontSize:18,fontWeight:600,marginBottom:8,letterSpacing:"-0.01em"}}>{p.title}</h3>
            <p style={{color:"var(--muted)",fontSize:14,lineHeight:1.6}}>{p.desc}</p>
          </div>
        ))}
      </div>
      <p className="reveal" style={{marginTop:32,color:"var(--muted)",fontSize:16,maxWidth:600}}>
        Знакомо? <span style={{color:"var(--text)"}}>Это нормально.</span> Большинство застревает именно здесь — пока не выстроится система.
      </p>
    </div>
  </section>
);

const Showcase = ({galleryStyle, onOpen}) => {
  const [active, setActive] = React.useState(0);
  return (
    <section id="showcase">
      <div className="container">
        <SectionHead tag="Работы учеников" title="Вот что создают наши ученики" subtitle="Один персонаж, одна история, одно узнаваемое лицо и лояльная аудитория. Реализм в премиальной эстетике, подходит как для соцсетей, так и для всевозможных бренд-проектов."/>
        {galleryStyle === "marquee" ? (
          <div className="marquee reveal">
            <div className="marquee-track">
              {[...PERSONAS, ...PERSONAS].map((p,i) => <Persona key={i} p={p} ix={i} onOpen={onOpen}/>)}
            </div>
          </div>
        ) : galleryStyle === "spotlight" ? (
          <div className="spotlight reveal">
            <div className="spotlight-main">
              {PERSONAS[active].img ? (
                <img src={PERSONAS[active].img} alt={`ИИ-персонаж № ${String(PERSONAS[active].id).padStart(2, "0")}, ${PERSONAS[active].tag}`} style={{ position:"absolute", inset:0, width:"100%", height:"100%", objectFit:"cover" }}/>
              ) : (
                <>
                  <PersonaBg hue={PERSONAS[active].hue} seed={active}/>
                  <div style={{position:"absolute",left:"50%",bottom:0,transform:"translateX(-50%)",width:"55%",height:"82%",background:"radial-gradient(50% 35% at 50% 28%, rgba(255,255,255,0.6), transparent 65%)",borderRadius:"200px 200px 30px 30px / 240px 240px 30px 30px",filter:"blur(1.5px)",opacity:.7}}/>
                </>
              )}
              <div style={{position:"absolute",left:24,bottom:22,display:"flex",flexDirection:"column",gap:6}}>
                <span className="eyebrow">{PERSONAS[active].tag}</span>
                <div style={{fontFamily:"var(--font-display)",fontWeight:600,fontSize:28,letterSpacing:"-0.02em"}}>{PERSONAS[active].subtitle}</div>
                <div style={{color:"var(--muted)",fontSize:13.5,maxWidth:360}}>{PERSONAS[active].aesthetic}</div>
              </div>
              <button type="button" className="btn btn-mono" onClick={(e) => onOpen(PERSONAS[active], e.currentTarget)} style={{position:"absolute",right:18,bottom:18}}>Открыть</button>
            </div>
            <div className="spotlight-list">
              {PERSONAS.slice(0,8).map((p,i) => (
                <div
                  key={p.id}
                  className={`persona ${i===active?"active":""}`}
                  onClick={() => setActive(i)}
                  onKeyDown={(e) => {
                    if (e.key === "Enter" || e.key === " ") {
                      e.preventDefault();
                      setActive(i);
                    }
                  }}
                  role="button"
                  tabIndex={0}
                  aria-label={`Выбрать персонажа № ${String(p.id).padStart(2, "0")}, ${p.subtitle}`}
                >
                  <div className="thumb">
                    {p.img ? <img src={p.img} alt="" style={{ width:"100%", height:"100%", objectFit:"cover" }}/> : <PersonaBg hue={p.hue} seed={i}/>}
                  </div>
                  <div className="info">
                    <div className="tag">{p.tag.split(" / ")[0]}</div>
                    <div className="nm">{p.subtitle}</div>
                  </div>
                </div>
              ))}
            </div>
          </div>
        ) : (
          <div className="gallery-grid reveal-stagger reveal">
            {PERSONAS.map((p,i) => <Persona key={p.id} p={p} ix={i} onOpen={onOpen}/>)}
          </div>
        )}
      </div>
    </section>
  );
};

const UseCases = () => (
  <section id="usecases">
    <div className="container">
      <SectionHead tag="Применение" title="Где пригодится навык" subtitle="Одно обучение, десятки направлений. Без обещаний, просто реальные сферы, где такой навык сейчас востребован."/>
      <div className="reveal-stagger reveal" style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(280px,1fr))",gap:14}}>
        {USE_CASES.map((u,i) => (
          <div key={i} className="card">
            <div className="card-icon"><Icon name={u.icon}/></div>
            <h3 style={{fontFamily:"var(--font-display)",fontSize:19,fontWeight:600,marginBottom:8,letterSpacing:"-0.01em"}}>{u.title}</h3>
            <p style={{color:"var(--muted)",fontSize:14,lineHeight:1.6}}>{u.desc}</p>
          </div>
        ))}
      </div>
    </div>
  </section>
);

const Modules = () => (
  <section id="modules">
    <div className="container">
      <SectionHead tag="Программа" title="Что ты получишь" subtitle="4 модуля, выстроенных в систему. От идеи и первого запуска нейросети до управления визуальным образом персонажа и масштабирования."/>
      <div className="modules-list reveal">
        {MODULES.map((m,i) => (
          <div key={i} className="module-row">
            <div className="ix">{m.ix}</div>
            <div>
              <div className="name">{m.name}</div>
              <div className="desc">{m.desc}</div>
            </div>
            <div className="meta duration"><b>{m.duration}</b></div>
            <div className="meta">{m.format}</div>
          </div>
        ))}
      </div>

      <div className="process reveal" style={{marginTop:48}}>
        <span className="eyebrow">Как это устроено</span>
        <h3 className="display-3" style={{marginTop:14,marginBottom:12,maxWidth:720}}>Как создаётся ИИ-персонаж за 4 шага</h3>
        <p style={{color:"var(--muted)",fontSize:"clamp(15px,1.3vw,17px)",lineHeight:1.6,maxWidth:640,marginBottom:24}}>Каждый этап решает свою задачу. Пропустишь, результат сломается.</p>
        <AnimatedProcess/>
      </div>
    </div>
  </section>
);

const FounderVideo = () => {
  const videoRef = React.useRef(null);
  const [paused, setPaused] = React.useState(true);
  const [started, setStarted] = React.useState(false);

  const [videoSrc] = React.useState(() => {
    if (typeof window === "undefined") return FOUNDER_VIDEO_DESKTOP;
    return window.innerWidth <= 720 ? FOUNDER_VIDEO_MOBILE : FOUNDER_VIDEO_DESKTOP;
  });

  const startPlay = () => {
    const v = videoRef.current;
    if (!v) return;
    v.play().catch(() => {/* autoplay restrictions — ignore */});
    setStarted(true);
  };

  return (
    <div className="founder-media">
      <video
        ref={videoRef}
        src={videoSrc}
        poster={FOUNDER_VIDEO_POSTER}
        controls={started}
        preload="metadata"
        playsInline
        className="founder-video"
        onPlay={() => setPaused(false)}
        onPause={() => setPaused(true)}
        onEnded={() => setPaused(true)}
      />
      {paused && !started && (
        <button
          type="button"
          className="founder-play-btn"
          onClick={startPlay}
          aria-label="Запустить приветственное видео"
        >
          <svg width="28" height="28" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d="M7 5v14l12-7L7 5z" fill="currentColor"/>
          </svg>
        </button>
      )}
      <div className="founder-media-glow"/>
    </div>
  );
};

const Founder = () => (
  <section id="founder" className="section section-pad" style={{ position: "relative", overflow: "hidden" }}>
    <div className="section-decorative-orb section-decorative-orb-violet" style={{ width: 420, height: 420, top: "-160px", right: "-120px" }}/>
    <div className="section-decorative-orb section-decorative-orb-pink" style={{ width: 320, height: 320, bottom: "-120px", left: "-60px" }}/>
    <div className="container">
      <div className="founder-grid">
        <div className="founder-photo reveal">
          <FounderVideo/>
          <div className="rim"/>
          <div className="founder-chip"><Icon name="check" size={12}/> практик · эксперт</div>
          <div className="tag">
            <span>Автор · MODELCORE</span>
            <b>Юлия</b>
          </div>
        </div>
        <div className="reveal" style={{transitionDelay:".1s"}}>
          <span className="eyebrow">Автор</span>
          <h2 className="display-2" style={{marginTop:14}}>Кто ведёт обучение</h2>
          <div className="founder-quote text-balance">
            <p>«Реалистичный ИИ-блогер — это уже не будущее, а настоящее. Я учу тому, что реально даёт результаты.»</p>
          </div>
          <div className="founder-bio">
            <p>Юлия. Работаю с генеративными нейросетями и созданием цифровых персонажей <strong>с мая 2025 года</strong>. Сейчас веду <strong>6 ИИ-персонажей</strong> для контент-проектов под разные задачи.</p>
            <p>Большинство в этой нише работает анонимно. Я веду обучение под своим именем, потому что отвечаю за качество методики. Результат каждого ученика складывается из работы по рекомендациям и собственных усилий.</p>
            <p>Программа собрана из того, что работает на практике у меня и учеников. Без воды, без копипасты гайдов из интернета, с фокусом на результат.</p>
          </div>
          <div className="founder-cta-row">
            <a className="btn btn-ghost" href="#tg-channel"><Icon name="telegram" size={16}/><span>Телеграм-канал</span></a>
            <a
              href="https://www.instagram.com/julietta.jpeg/"
              target="_blank"
              rel="noopener noreferrer"
              className="btn btn-ghost founder-ig-btn"
              aria-label="Instagram Юлии"
            >
              <Icon name="instagram" size={16}/><span>Instagram</span>
            </a>
          </div>
        </div>
      </div>
    </div>
  </section>
);

const Testimonials = () => {
  const [openIdx, setOpenIdx] = React.useState(null);
  const [showAll, setShowAll] = React.useState(false);
  const [isNarrowT, setIsNarrowT] = React.useState(() =>
    typeof window !== "undefined" && window.innerWidth <= 720
  );
  const VISIBLE_COUNT = 6;
  const visibleTestimonials = (showAll || isNarrowT) ? TESTIMONIALS : TESTIMONIALS.slice(0, VISIBLE_COUNT);
  const triggerRef = React.useRef(null);
  const closeRef = React.useRef(null);

  const openLightbox = (idx, btn) => {
    triggerRef.current = btn;
    setOpenIdx(idx);
  };

  React.useEffect(() => {
    const check = () => setIsNarrowT(window.innerWidth <= 720);
    check();
    window.addEventListener("resize", check);
    return () => window.removeEventListener("resize", check);
  }, []);

  React.useEffect(() => {
    if (openIdx === null) {
      triggerRef.current?.focus();
      return;
    }
    const t = setTimeout(() => closeRef.current?.focus(), 50);
    const onKey = (e) => { if (e.key === "Escape") setOpenIdx(null); };
    document.body.style.overflow = "hidden";
    window.addEventListener("keydown", onKey);
    return () => {
      clearTimeout(t);
      document.body.style.overflow = "";
      window.removeEventListener("keydown", onKey);
    };
  }, [openIdx]);

  const avatarGradient = (name) => {
    let h = 0;
    for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) >>> 0;
    const hue1 = h % 360;
    const hue2 = (hue1 + 60) % 360;
    return `linear-gradient(135deg, hsl(${hue1} 70% 55%) 0%, hsl(${hue2} 65% 45%) 100%)`;
  };

  return (
    <section className="section section-pad" id="testimonials">
      <div className="container">
        <div className="eyebrow reveal">Отзывы</div>
        <h2 className="display-2 reveal" style={{margin:"12px 0 16px"}}>Что говорят ученики</h2>
        <p className="reveal" style={{color:"var(--muted)",fontSize:17,lineHeight:1.6,maxWidth:640,marginBottom:48}}>
          Реальные отзывы из закрытого чата учеников про систему и поддержку.
        </p>

        <div className="testimonials-grid-v2">
          {visibleTestimonials.map((t) => (
            <article key={t.id} className="t-card reveal">
              <div className="t-card-head">
                <div className="t-avatar" style={{background: avatarGradient(t.name)}}>
                  {t.name.charAt(0).toUpperCase()}
                </div>
                <div className="t-meta">
                  <div className="t-name">{t.name}</div>
                  <div className="t-role">{t.role}</div>
                </div>
              </div>
              <p className="t-quote">«{t.quote}»</p>
              <button
                type="button"
                className="t-screen-btn"
                onClick={(e) => {
                  const i = TESTIMONIALS.findIndex((x) => x.id === t.id);
                  if (i >= 0) openLightbox(i, e.currentTarget);
                }}
                aria-label={`Открыть скриншот отзыва от ${t.name}`}
              >
                <Icon name="zoom-in" size={14}/>
                <span>Открыть скрин</span>
              </button>
            </article>
          ))}
        </div>

        <div className="testimonials-scroll-hint" aria-hidden="true">
          ← листай →
        </div>

        {TESTIMONIALS.length > VISIBLE_COUNT && (
          <div className="testimonials-show-more-wrap">
            <button
              type="button"
              className="testimonials-show-more"
              onClick={() => setShowAll((s) => !s)}
              aria-expanded={showAll}
            >
              {showAll
                ? `Свернуть до ${VISIBLE_COUNT}`
                : `Показать ещё ${TESTIMONIALS.length - VISIBLE_COUNT} отзыва`}
            </button>
          </div>
        )}
      </div>

      {openIdx !== null && (
        <div
          className="testimonial-lightbox"
          onClick={() => setOpenIdx(null)}
          role="dialog"
          aria-modal="true"
          aria-label="Скриншот отзыва"
        >
          <button
            ref={closeRef}
            type="button"
            className="testimonial-lightbox-close"
            onClick={() => setOpenIdx(null)}
            aria-label="Закрыть скриншот"
          >
            <Icon name="x" size={20}/>
          </button>
          <img
            src={TESTIMONIALS[openIdx].img}
            alt={`Отзыв от ${TESTIMONIALS[openIdx].name}`}
            className="testimonial-lightbox-img"
            onClick={(e) => e.stopPropagation()}
          />
          <div className="testimonial-lightbox-meta" onClick={(e) => e.stopPropagation()}>
            <div className="testimonial-lightbox-name">{TESTIMONIALS[openIdx].name}</div>
            <div className="testimonial-lightbox-role">{TESTIMONIALS[openIdx].role}</div>
          </div>
        </div>
      )}
    </section>
  );
};

const GetStarted = ({onCTA}) => (
  <section id="getstarted">
    <div className="container">
      <SectionHead tag="С чего начать" title="Путь к первому персонажу" subtitle="Три шага, чтобы понять, твоё это или нет."/>
      <div className="steps reveal-stagger reveal">
        {STEPS.map((s,i) => (
          <div key={i} className="step">
            <div className="ix">{s.ix}</div>
            <div className="name">{s.name}</div>
            <div className="desc">{s.desc}</div>
          </div>
        ))}
      </div>
      <div className="reveal" style={{marginTop:32,display:"flex",justifyContent:"center"}}>
        <MagneticBtn className="btn btn-primary btn-lg" onClick={onCTA}>
          <Icon name="telegram" size={18}/>
          <span>Шаг 01 — открыть Телеграм</span>
          <span className="arrow"><Icon name="arrow-right" size={16}/></span>
        </MagneticBtn>
      </div>
    </div>
  </section>
);

const ForWho = () => (
  <section id="forwho">
    <div className="container">
      <SectionHead tag="Кому подойдёт" title="Для кого программа" subtitle="Честно: кому подойдёт, а кому нет. Лучше понять сейчас, чем разочароваться потом."/>
      <div className="twocol reveal-stagger reveal">
        <div className="listcard yes">
          <span className="chip chip-accent"><Icon name="check" size={14}/> Подходит</span>
          <ul>{FOR_WHO.yes.map((t,i) => <li key={i}><Icon name="check" size={18}/>{t}</li>)}</ul>
        </div>
        <div className="listcard no">
          <span className="chip"><Icon name="x" size={14}/> Не подходит</span>
          <ul>{FOR_WHO.no.map((t,i) => <li key={i}><Icon name="x" size={18}/>{t}</li>)}</ul>
        </div>
      </div>
    </div>
  </section>
);

const TgChannel = ({onCTA}) => (
  <section id="tg-channel">
    <div className="container">
      <SectionHead tag="Активный канал" title="Что в Телеграм-канале прямо сейчас" subtitle="Бесплатные уроки, разборы и статьи. Заходи без обязательств, посмотри, как мы работаем, и решай сам."/>
      <div className="tg-preview reveal">
        <div className="tg-channel">
          <div className="tg-head">
            <div className="tg-avatar"><span>M</span></div>
            <div>
              <div style={{fontFamily:"var(--font-display)",fontWeight:600,fontSize:18}}>MODELCORE</div>
              <div style={{color:"var(--muted)",fontSize:13}}>Закрытый Телеграм-канал · по приглашению</div>
            </div>
          </div>
          {LIVE_TG_START != null && (
          <div className="tg-live"><span className="dot" style={{width:6,height:6,borderRadius:999,background:"var(--accent)",boxShadow:"0 0 8px var(--accent-glow)",display:"inline-block"}}/> В канале сейчас</div>
          )}
          {LIVE_TG_START != null ? (
          <div className="tg-counter-block">
            <div className="tg-counter-main">
              <LiveCounter start={LIVE_TG_START}/>
              <div className="tg-counter-label">человек уже в канале</div>
            </div>
            <div className="tg-counter-students">
              {LIVE_TG_STUDENTS} учеников в закрытом чате
            </div>
          </div>
          ) : (
          <div style={{margin:"18px 0 8px"}}>
            <div style={{fontFamily:"var(--font-display)",fontSize:"clamp(28px,3.6vw,42px)",fontWeight:600,letterSpacing:"-0.02em",lineHeight:1.1}}>Растущее сообщество</div>
            <p style={{color:"var(--muted)",fontSize:13,marginTop:8}}>Бесплатные уроки, разборы и анонсы открытия программы</p>
          </div>
          )}
          <p style={{color:"var(--muted)",fontSize:14.5,lineHeight:1.6,margin:"12px 0 24px"}}>Бесплатные уроки, разборы домашних, анонсы открытия программы. Без спама — только польза и практика.</p>
          <MagneticBtn className="btn btn-primary" onClick={onCTA}>
            <Icon name="telegram" size={16}/><span>Присоединиться к каналу</span>
          </MagneticBtn>
        </div>
        <div className="tg-posts">
          {TG_POSTS.map((p,i) => (
            <div key={i} className="tg-post">
              <div className="date">{p.when}</div>
              <h4>{p.title}</h4>
              <p className="preview">{p.excerpt}</p>
            </div>
          ))}
        </div>
      </div>
    </div>
  </section>
);

const FaqList = () => {
  const [open, setOpen] = React.useState(0);
  return (
    <section id="faq">
      <div className="container">
        <SectionHead tag="Вопросы" title="Частые вопросы" subtitle="Если не нашёл ответ, напиши в Телеграм, разберёмся."/>
        <div className="faq reveal">
          {FAQ.map((f,i) => (
            <div key={i} className={`faq-item ${open===i?"open":""}`}>
              <div
                className="faq-q"
                role="button"
                tabIndex={0}
                aria-expanded={open === i}
                onClick={() => setOpen(open === i ? -1 : i)}
                onKeyDown={(e) => {
                  if (e.key === "Enter" || e.key === " ") {
                    e.preventDefault();
                    setOpen(open === i ? -1 : i);
                  }
                }}
              >
                <span>{f.q}</span>
                <span className="faq-toggle"><Icon name="plus" size={16}/></span>
              </div>
              <div className="faq-a" style={{maxHeight: open===i ? 800 : 0}}>
                <div className="inner">{f.a}</div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
};

const FinalCTA = ({onCTA, tgUrl, formEndpoint}) => {
  const [name, setName] = React.useState("");
  const [tg, setTg] = React.useState("");
  const [status, setStatus] = React.useState(null);
  const [errs, setErrs] = React.useState({});
  const [submitting, setSubmitting] = React.useState(false);
  const submitInFlightRef = React.useRef(false);
  const submit = async (e) => {
    e.preventDefault();
    const newErrs = {};
    if (!name.trim() || name.trim().length < 2) newErrs.name = true;
    const tgClean = tg.trim().replace(/^https?:\/\/(t\.me\/|telegram\.me\/)/i, "").replace(/^@/, "");
    if (!tgClean || !/^[a-z][a-z0-9_]{3,30}[a-z0-9]$/i.test(tgClean)) newErrs.tg = true;
    setErrs(newErrs);
    if (Object.keys(newErrs).length) {
      setStatus({ok:false, text:"Проверь поля — нужно имя (от 2 символов) и ник в Телеграме (от 5 символов, латиница, цифры, _)."});
      return;
    }
    if (submitInFlightRef.current) return;
    submitInFlightRef.current = true;
    setSubmitting(true);
    setStatus({ok:null, text:"Отправляем…"});
    try {
      const r = await fetch(formEndpoint, {
        method: "POST",
        headers: {"Content-Type": "application/json", "Accept": "application/json"},
        body: JSON.stringify({
          name: name.trim(),
          telegram: `@${tgClean}`,
          source: "modelcoreai-landing",
          page: window.location.href,
          ts: new Date().toISOString(),
        }),
      });
      if (!r.ok) throw new Error(`HTTP ${r.status}`);
      setStatus({ok:true, text:`Заявка принята. Юлия свяжется в Телеграме (@${tgClean}) в ближайшее время.`});
      setName("");
      setTg("");
    } catch (err) {
      setStatus({ok:false, text:"Не удалось отправить — попробуй ещё раз или напиши в Телеграм-канал напрямую."});
      console.error("Form submit failed:", err);
    } finally {
      submitInFlightRef.current = false;
      setSubmitting(false);
    }
  };
  const msgClass =
    status == null
      ? ""
      : status.ok === true
        ? "ok form-success"
        : status.ok === false
          ? status.text && status.text.includes("Проверь поля")
            ? "err"
            : "err form-error"
          : "pending";
  return (
    <section id="final">
      <div className="container">
        <div className="final reveal">
          <span className="eyebrow" style={{justifyContent:"center"}}>Поехали?</span>
          <h2 className="display-1 text-balance" style={{marginTop:18,fontSize:"clamp(42px,7vw,96px)"}}>Готов создать своего ИИ-персонажа?</h2>
          <p className="text-pretty" style={{color:"var(--muted)",fontSize:"clamp(15px,1.4vw,18px)",marginTop:18,maxWidth:560,marginLeft:"auto",marginRight:"auto"}}>
            Начни с бесплатных материалов в Телеграме. Решение остаётся за тобой, после того как попробуешь.
          </p>
          <div style={{marginTop:32,display:"flex",justifyContent:"center"}}>
            <MagneticBtn className="btn btn-primary btn-lg" onClick={onCTA}>
              <Icon name="telegram" size={18}/>
              <span>Открыть Телеграм-канал</span>
              <span className="arrow"><Icon name="arrow-right" size={16}/></span>
            </MagneticBtn>
          </div>
          <div style={{marginTop:48,paddingTop:32,borderTop:"1px solid var(--line)",maxWidth:560,marginLeft:"auto",marginRight:"auto"}}>
            <div style={{color:"var(--muted)",fontSize:14}}>Или сразу оставь заявку на полную программу</div>
            <form className="final-form" onSubmit={submit}>
              <input type="text" name="name" placeholder="Твоё имя" value={name} onChange={e=>setName(e.target.value)} className={errs.name?"err":""} aria-label="Имя"/>
              <input type="text" name="telegram" placeholder="@username в Телеграм" value={tg} onChange={e=>setTg(e.target.value)} className={errs.tg?"err":""} aria-label="Ник в Телеграме"/>
              <button
                type="submit"
                className="btn btn-ghost btn-lg form-submit-btn"
                style={{flex:"0 0 auto"}}
                disabled={submitting}
                aria-busy={submitting}
              >
                {submitting ? "Отправка..." : "Оставить заявку"}
              </button>
            </form>
            {status && (
              <div
                className={`form-msg ${msgClass}`}
                role={
                  status.ok === true
                    ? "status"
                    : status.ok === false && msgClass.includes("form-error")
                      ? "alert"
                      : "status"
                }
              >
                {status.text}
              </div>
            )}
            <div style={{marginTop:24,color:"var(--muted-2)",fontSize:12,lineHeight:1.5}}>
              Образовательная программа. Результат зависит от усилий и практики ученика.
            </div>
          </div>
        </div>
      </div>
    </section>
  );
};

const Footer = ({tgUrl, supportUrl, email}) => (
  <footer>
    <div className="container footer-grid">
      <div className="footer-col">
        <a href="#hero" className="logo"><span className="logo-mark"/><span>MODELCORE</span></a>
        <p className="footer-text" style={{color:"var(--muted)",fontSize:13.5,marginTop:14,maxWidth:340,lineHeight:1.6}}>
          Обучение созданию реалистичных ИИ-персонажей с нуля. Без опыта и сложного ПО.
        </p>
      </div>
      <div className="footer-col" style={{display:"flex",flexDirection:"column",gap:10}}>
        <div className="eyebrow">NAV</div>
        <a href="#modules">Программа</a>
        <a href="#testimonials">Отзывы</a>
        <a href="#faq">Вопросы</a>
        <a href="#tg-channel">Телеграм</a>
      </div>
      <div className="footer-col" style={{display:"flex",flexDirection:"column",gap:10}}>
        <div className="eyebrow">CONTACT</div>
        <a href={tgUrl} target="_blank" rel="noopener">Телеграм-канал</a>
        {supportUrl && <a href={supportUrl} target="_blank" rel="noopener">Поддержка</a>}
        {email && <a className="footer-email" href={`mailto:${email}`}>{email}</a>}
        <a href="privacy.html">Политика конфиденциальности</a>
        <a href="offer.html">Публичная оферта</a>
      </div>
    </div>
    <div className="container footer-bottom">
      <div className="footer-bottom-row">
        <div className="footer-copyright">© {new Date().getFullYear()} MODELCORE · Все права защищены</div>
        <div className="footer-credits">
          Разработка сайта: <a href="https://tenetlab.agency/" target="_blank" rel="noopener noreferrer">TenetLab</a>
        </div>
      </div>
      <div className="footer-disclaimer">Обучение творческому и техническому навыку. Применение полученных знаний — на ответственности ученика.</div>
    </div>
  </footer>
);

// Lightbox
const Lightbox = ({ persona, onClose, openTriggerRef }) => {
  const closeRef = React.useRef(null);
  React.useEffect(() => {
    if (!persona) {
      openTriggerRef?.current?.focus();
      return;
    }
    const t = setTimeout(() => closeRef.current?.focus(), 50);
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    document.body.style.overflow = "hidden";
    window.addEventListener("keydown", onKey);
    return () => {
      clearTimeout(t);
      document.body.style.overflow = "";
      window.removeEventListener("keydown", onKey);
    };
  }, [persona, onClose, openTriggerRef]);
  return (
    <div className={`lightbox ${persona?"open":""}`} onClick={onClose} role="dialog" aria-modal="true" aria-label="Детали персонажа">
      {persona && (
        <div className="lightbox-card" onClick={e=>e.stopPropagation()}>
          <button ref={closeRef} type="button" className="lightbox-close" onClick={onClose} aria-label="Закрыть"><Icon name="x" size={18}/></button>
          <div className="lbimg">
            {persona.img ? (
              <img src={persona.img} alt={`ИИ-персонаж № ${String(persona.id).padStart(2, "0")}, ${persona.tag}`} style={{ position:"absolute", inset:0, width:"100%", height:"100%", objectFit:"cover" }}/>
            ) : (
              <>
                <PersonaBg hue={persona.hue} seed={persona.id}/>
                <div style={{position:"absolute",left:"50%",bottom:0,transform:"translateX(-50%)",width:"65%",height:"82%",background:"radial-gradient(50% 35% at 50% 28%, rgba(255,255,255,0.6), transparent 65%)",borderRadius:"200px 200px 30px 30px / 240px 240px 30px 30px",filter:"blur(1.5px)",opacity:.7}}/>
              </>
            )}
            <div style={{position:"absolute",left:20,top:18}} className="eyebrow">{persona.tag} · № {String(persona.id).padStart(2,"0")}</div>
          </div>
          <div className="lbinfo">
            <span className="eyebrow">{persona.tag} · № {String(persona.id).padStart(2,"0")}</span>
            <h3 className="display-3" style={{marginTop:6}}>{persona.subtitle}</h3>
            <div>
              <div className="eyebrow" style={{marginBottom:6}}>STYLE</div>
              <div style={{fontSize:15,color:"var(--text)"}}>{persona.style}</div>
            </div>
            <div>
              <div className="eyebrow" style={{marginBottom:6}}>ENVIRONMENT</div>
              <div style={{fontSize:15,color:"var(--text)"}}>{persona.env}</div>
            </div>
            <div>
              <div className="eyebrow" style={{marginBottom:6}}>AESTHETIC</div>
              <div style={{fontSize:15,color:"var(--text)"}}>{persona.aesthetic}</div>
            </div>
            <div style={{marginTop:"auto",paddingTop:16,fontSize:12.5,color:"var(--muted)",lineHeight:1.6,borderTop:"1px solid var(--line)"}}>
              Все визуалы — SFW, реалистичные портреты, lifestyle, fashion в нейтральной эстетике.
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

Object.assign(window, { Icon, Persona, PersonaBg, SectionHead, ConsistencyCompare, AnimatedProcess, CountUp, LiveCounter, ParticlesCanvas, ScrollVideoHero, Hero, HeroVisual, MagneticBtn, Problems, Showcase, UseCases, Modules, Founder, Testimonials, GetStarted, ForWho, TgChannel, FaqList, FinalCTA, Footer, Lightbox });
