/* What-is, Positioning slab, Why cards, Customization, Process steps, Scenarios */

const WhatIs = ({ disc = {} }) => {
  const stageRef = React.useRef(null);
  const flipRef = React.useRef(null);
  const cfg = React.useRef({});
  cfg.current = {
    tilt: disc.tilt != null ? disc.tilt : 22,
    idle: disc.idle !== false,
    idleAmp: disc.idleAmp != null ? disc.idleAmp : 1
  };
  React.useEffect(() => {
    /* наклон как в старом hero: слушаем весь экран, нормировка по секции */
    const stage = stageRef.current, flip = flipRef.current;
    if (!stage || !flip) return;
    const sec = stage.closest("section") || stage;
    let reduce = false;
    try { reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches; } catch (e) {}
    if (reduce) return;
    let tx = 0, ty = 0, cx = 0, cy = 0, vx = 0, vy = 0, raf = 0, lastMove = -9999;
    let mx = -1, my = -1, lx = 0, ly = 0, prox = 0;
    let spin = 0, spinV = 0, vUp = 0, outAbove = false;
    let sY = window.scrollY, sT = performance.now(), lastT = performance.now();
    /* без клампа, как в старом hero: далеко от секции ty большой, диск лежит
       перевёрнутым — и при подъёме со дна лендинга красиво прокручивается на место */
    const calc = () => {
      const r = sec.getBoundingClientRect();
      tx = (mx - r.left) / r.width - 0.5;
      ty = (my - r.top) / r.height - 0.5;
      /* локальный отклик: рядом с диском курсор «продавливает» ближний край.
         Центр меряем по нетрансформированному родителю (.sc-left) — rect самого
         stage дышит вместе с поворотом и дал бы обратную связь */
      const pr = stage.parentElement.getBoundingClientRect();
      const w = stage.offsetWidth || 1;
      const dx = mx - (pr.left + pr.width / 2), dy = my - (pr.top + pr.height / 2);
      const p = Math.max(0, Math.min(1, 1 - (Math.hypot(dx, dy) - w * 0.55) / (w * 0.85)));
      prox = p * p * (3 - 2 * p);
      lx = Math.max(-0.75, Math.min(0.75, dx / w));
      ly = Math.max(-0.75, Math.min(0.75, dy / w));
    };
    const onMove = (e) => {
      mx = e.clientX; my = e.clientY;
      calc();
      lastMove = performance.now();
    };
    const onScroll = () => {
      if (mx >= 0) calc();
      /* сглаженная скорость подъёма (px/s) — топливо инерционного прокрута */
      const y = window.scrollY, t = performance.now();
      const dt = Math.min(400, Math.max(4, t - sT));
      vUp += ((sY - y) / dt * 1000 - vUp) * Math.min(1, dt / 120);
      sY = y; sT = t;
      if (sec.getBoundingClientRect().bottom <= 0) outAbove = true;
      else if (outAbove) {
        /* секция вернулась в кадр; один запуск на заход */
        outAbove = false;
        if (vUp > 2000) spinV = Math.min(1400, Math.max(900, vUp * 0.35));
      }
    };
    const reset = () => { tx = 0; ty = 0; };
    const loop = () => {
      raf = requestAnimationFrame(loop);
      const now = performance.now();
      const dt = Math.min(0.05, Math.max(0.004, (now - lastT) / 1000));
      lastT = now;
      const c = cfg.current;
      const idleWeight = c.idle ? Math.min(1, Math.max(0, (now - lastMove - 700) / 900)) : 0;
      const a = 0.16 * c.idleAmp * idleWeight;
      const gx = tx + lx * 0.95 * prox + Math.sin(now / 1700) * a;
      const gy = ty + ly * 0.95 * prox + Math.cos(now / 2300) * a * 0.8;
      /* недодемпфированная пружина вместо lerp: диск чуть перелетает цель и
         докачивается. Кламп скорости — чтобы телепорт скролла не хлестал сцену */
      vx = Math.max(-14, Math.min(14, vx + (gx - cx) * 90 * dt)) * Math.exp(-7 * dt);
      vy = Math.max(-14, Math.min(14, vy + (gy - cy) * 90 * dt)) * Math.exp(-7 * dt);
      cx += vx * dt; cy += vy * dt;
      stage.style.transform = `rotateY(${cx * c.tilt}deg) rotateX(${-cy * c.tilt}deg)`;
      /* инерционный прокрут «подброшенной монеты»: экспоненциальное затухание,
         ниже 30°/с — доводка до ближайшего полного оборота, диск ложится ровно */
      if (spinV > 0) {
        spin += spinV * dt;
        spinV *= Math.pow(0.08, dt);
        if (spinV < 30) spinV = 0;
      } else if (spin !== 0) {
        const t360 = Math.round(spin / 360) * 360;
        spin += (t360 - spin) * (1 - Math.pow(0.88, dt * 60));
        if (Math.abs(t360 - spin) < 0.05) spin = 0;
      }
      flip.style.transform = `rotateX(${spin}deg)`;
    };
    raf = requestAnimationFrame(loop);
    window.addEventListener("mousemove", onMove, { passive: true });
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("blur", reset);
    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("blur", reset);
    };
  }, []);

  return (
    <section className="section-pad" id="product">
      <div className="wrap">
        <div className="showcase">
          <div className="sc-left">
            <div className="hero-disc-stage sc-stage" ref={stageRef}>
              {/* обёртка под инерционный прокрут: спин не трогает hd-tag,
                  иначе бейджи зеркалились бы при перевороте */}
              <div className="edible-flip" ref={flipRef} style={{ transformStyle: "preserve-3d", willChange: "transform" }}>
              <div className="edible-disc">
                <div className="edible-rot">
                  <img className="edible-img" src="exports/edible-record-v3.webp" alt="Съедобная карамельная музыкальная пластинка Вкусноты — кастомный вкус и цвет под релиз" />
                  <svg className="edible-label" viewBox="0 0 400 400" aria-hidden="true">
                    <defs>
                      <path id="vk-arc-top" d="M 156 200 A 44 44 0 0 1 244 200" />
                      <path id="vk-arc-bot" d="M 145 200 A 55 55 0 0 0 255 200" />
                    </defs>
                    {/* печатный лейбл — текст по дуге вокруг дырки, как на настоящем прессе */}
                    <text className="vk-arc-top">
                      <textPath href="#vk-arc-top" startOffset="50%" textAnchor="middle">ВКУСНОТЫ</textPath>
                    </text>
                    <text className="vk-arc-bot">
                      <textPath href="#vk-arc-bot" startOffset="50%" textAnchor="middle">СЪЕДОБНАЯ ПЛАСТИНКА</textPath>
                    </text>
                    <text className="vk-star" x="150" y="203.5" textAnchor="middle">✶</text>
                    <text className="vk-star" x="250" y="203.5" textAnchor="middle">✶</text>
                  </svg>
                </div>
              </div>
              </div>
              <span className="hd-tag tl">12″ пластинка</span>
              <span className="hd-tag br">Съедобно</span>
            </div>
          </div>
          <div className="sc-right">
            <div className="eyebrow">[ 01 ] Что это</div>
            <h2>Усиление промо-кампании вашего релиза.</h2>
            <p className="lede muted">
              Каждую пластинку собираем под конкретный запуск&nbsp;— от&nbsp;вкуса и&nbsp;упаковки до&nbsp;тиража и&nbsp;сроков.
            </p>
            <ul className="args">
              <li><b>Физический инфоповод.</b><span> Предмет, который снимают, пересылают и&nbsp;обсуждают&nbsp;— вместо ещё одного поста в&nbsp;ленте.</span></li>
              <li><b>Кастом под релиз.</b><span> Вкус, цвет и&nbsp;упаковка собираются под визуальный мир трека. <a className="syn-inline" href={SYN_URL("args")} target="_blank" rel="noopener noreferrer">Примерить вкус на&nbsp;свой трек&nbsp;→</a></span></li>
              <li><b>Лимит под дату.</b><span> Небольшой тираж к&nbsp;релизу&nbsp;— дефицит, который работает на&nbsp;охваты.</span></li>
              <li><b>Контент-машина.</b><span> Распаковка, реакция, дегустация&nbsp;— несколько роликов с&nbsp;одной пластинки.</span></li>
            </ul>
            <div className="note">Проигрывание&nbsp;— спецформат: зависит от&nbsp;партии, обсуждаем на&nbsp;брифе.</div>
          </div>
        </div>
      </div>
    </section>
  );
};

const Positioning = () => (
  <section className="slab">
    <div className="wrap">
      <div className="slab-head">
        <div className="eyebrow">[ 02 ] Позиционирование</div>
        <h2>Не&nbsp;просто сладость. Не&nbsp;только сувенир. <span className="hl">Инфоповод.</span></h2>
      </div>

      <div className="triplet">
        <div className="tile">
          <span className="strike f-mono">НЕ ПРОСТО СЛАДОСТЬ</span>
          <h3>Релизный артефакт</h3>
          <p className="dim">Связан с&nbsp;датой, треком и&nbsp;легендой запуска.</p>
        </div>
        <div className="tile">
          <span className="strike f-mono">НЕ ВСЕГДА СУВЕНИР</span>
          <h3>Объект для посева</h3>
          <p className="dim">Уезжает медиа, блогерам, кураторам и&nbsp;близкому кругу.</p>
        </div>
        <div className="tile">
          <span className="strike f-mono">СОВСЕМ НЕ ПРИКОЛ</span>
          <h3>Способ выделить запуск</h3>
          <p className="dim">Физический, уникальный, ошарашивающий предмет там, где у&nbsp;всех — только пост.</p>
        </div>
      </div>

      <p className="slab-line">
        Когда лента перегрета, выигрывает не&nbsp;тот, кто громче, а&nbsp;тот, у&nbsp;кого есть предмет, который хочется снять и&nbsp;переслать.
      </p>
    </div>
  </section>
);

const WhyIcon = ({ kind }) => {
  const common = { viewBox: "0 0 32 32", width: 30, height: 30, fill: "none", stroke: "currentColor", strokeWidth: 1.8, strokeLinecap: "square", strokeLinejoin: "miter" };
  if (kind === "disc") return (
    <svg {...common} aria-hidden="true"><circle cx="16" cy="16" r="13"/><circle cx="16" cy="16" r="7"/><circle cx="16" cy="16" r="1.6" fill="currentColor" stroke="none"/></svg>
  );
  if (kind === "seed") return (
    <svg {...common} aria-hidden="true"><circle cx="16" cy="16" r="3.4"/><path d="M16 12.6 V5"/><path d="M16 19.4 V27"/><path d="M12.6 16 H5"/><path d="M19.4 16 H27"/><circle cx="16" cy="4" r="1.5" fill="currentColor" stroke="none"/><circle cx="16" cy="28" r="1.5" fill="currentColor" stroke="none"/><circle cx="4" cy="16" r="1.5" fill="currentColor" stroke="none"/><circle cx="28" cy="16" r="1.5" fill="currentColor" stroke="none"/></svg>
  );
  if (kind === "play") return (
    <svg {...common} aria-hidden="true"><rect x="4" y="4" width="24" height="24"/><path d="M13 11 L21 16 L13 21 Z" fill="currentColor" stroke="none"/></svg>
  );
  return (
    <svg {...common} aria-hidden="true"><path d="M16 3 L29 16 L16 29 L3 16 Z"/><path d="M16 11 L21 16 L16 21 L11 16 Z" fill="currentColor" stroke="none"/></svg>
  );
};

const Why = () => {
  const items = [
    { num: "01", title: "Выделить релиз", body: "Пластинка превращает запуск в физический опыт. Вместо ещё одной новости — предмет, о котором говорят.", ico: "disc" },
    { num: "02", title: "Запустить посев", body: "Объект удобно при желании отправить блогерам, редакциям, партнёрам и кураторам плейлистов.", ico: "seed" },
    { num: "03", title: "Наполнить контент-план", body: "Распаковка, проигрывание, реакция, вкус. Один предмет — множество роликов и поводов для сторис.", ico: "play" },
    { num: "04", title: "Сделать дроп", body: "Небольшой тираж как лимитированный мерч, конкурсный приз или подарок первым слушателям.", ico: "diamond" },
  ];
  return (
    <section className="section-pad">
      <div className="wrap">
        <div className="title-block">
          <div className="left">
            <div className="eyebrow">[ 03 ] Почему артисту и&nbsp;лейблу</div>
            <h2>Обычный мерч не&nbsp;создаёт событие.</h2>
          </div>
          <div className="right">
            <p className="lede muted">
              Футболка лежит в&nbsp;шкафу. Пост скроллится. Пластинка из&nbsp;пищевого материала под конкретный релиз — это объект, который снимают, передают и&nbsp;запоминают.
            </p>
          </div>
        </div>

        <div className="why-grid">
          {items.map(it => (
            <div className="why-card" key={it.num}>
              <div className="ico" aria-hidden="true"><WhyIcon kind={it.ico} /></div>
              <span className="num">[{it.num}]</span>
              <h3>{it.title}</h3>
              <p>{it.body}</p>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
};

const Customization = () => {
  const dims = [
    { n: "01", t: "Вкус", d: "под настроение релиза" },
    { n: "02", t: "Цвет", d: "drop-палитра артиста" },
    { n: "03", t: "Тираж", d: "от камерного до партии" },
    { n: "04", t: "Упаковка", d: "sleeve под арт релиза" },
    { n: "05", t: "Релизная легенда", d: "история запуска" },
    { n: "06", t: "Сценарий посева", d: "кому и как уедет" },
  ];
  return (
    <section className="section-tight" style={{ borderTop: "1px solid var(--line)" }}>
      <div className="wrap">
        <div className="custom">
          <div className="custom-intro">
            <div className="eyebrow" style={{ marginBottom: 18 }}>[ 04 ] Кастомизация</div>
            <h2>Всё работает на&nbsp;одну легенду.</h2>
            <p className="lede muted" style={{ marginTop: 20, maxWidth: "42ch" }}>
              Вкус, цвет и&nbsp;упаковка собираются вокруг визуального мира артиста — пластинка читается как часть релиза, а&nbsp;не&nbsp;случайная сладость.
            </p>
          </div>
          <div className="custom-list">
            {dims.map(d => (
              <div className="cd-row" key={d.n}>
                <span className="cd-n">{d.n}</span>
                <span className="cd-t">{d.t}</span>
                <span className="cd-d">{d.d}</span>
              </div>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
};

const Process = () => {
  const steps = [
    { n: "01", k: "Разбираем запуск", b: "Кто артист, что выходит, когда дедлайн, кому отправляем, какой эффект нужен.", t: "Бриф, 1–2 дня" },
    { n: "02", k: "Собираем концепцию", b: "Определяем вкус, цвет, подачу, упаковку, тираж и сценарий контента.", t: "Концепт, подача" },
    { n: "03", k: "Бронируем слот", b: "Фиксируем очередь, дату готовности и реалистичный объём кастомизации.", t: "Запуск работ" },
    { n: "04", k: "Готовим партию", b: "Производим, упаковываем и передаём под релиз, розыгрыш, посев или спецподарок.", t: "Передача партии артисту" },
  ];
  return (
    <section className="section-tight">
      <div className="wrap">
        <div className="title-block process-head">
          <div className="left">
            <div className="eyebrow">[ 05 ] Как это работает</div>
            <h2>От&nbsp;даты релиза к&nbsp;готовому объекту.</h2>
          </div>
          <div className="right">
            <p className="lede muted">
              Чем раньше понятны дата, тираж и&nbsp;посыл, тем чище формат и&nbsp;спокойнее производство.
            </p>
          </div>
        </div>

        <div className="steps steps-row">
          {steps.map(s => (
            <div className="step" key={s.n}>
              <span className="stepnum">{s.n}<span className="lil">/04</span></span>
              <div className="step-body">
                <h3>{s.k}</h3>
                <p>{s.b}</p>
                <span className="tag">→ {s.t}</span>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
};

const Scenarios = () => {
  const sc = [
    { tag: "A", title: "Релизный запуск", body: "Пластинки для команды, фанатов, победителей конкурса или первых слушателей.", ph: "Cover · drop" },
    { tag: "B", title: "PR-посев", body: "Подарок медиа, блогерам, партнёрам и тем, кто покажет объект своей аудитории.", ph: "Sleeve · mailer" },
    { tag: "C", title: "Лимитированный мерч", body: "Небольшая партия для drop-механики, закрытого клуба или спецпродажи.", ph: "Box · drop kit" },
    { tag: "D", title: "Контентная активация", body: "Объект для backstage, распаковки, тизера, live-реакции и коротких видео.", ph: "On hand · 9:16" },
    { tag: "E", title: "Подарок партнёрам", body: "Запоминающийся физический объект вместо стандартного брендированного набора.", ph: "Gift · close-up" },
  ];
  return (
    <section className="section-pad" id="scenarios" style={{ borderTop: "1px solid var(--line)" }}>
      <div className="wrap">
        <div className="title-block">
          <div className="left">
            <div className="eyebrow">[ 06 ] Сценарии</div>
            <h2>Лучше всего работает там,<br/>где есть дата и&nbsp;шум.</h2>
          </div>
          <div className="right">
            <p className="lede muted">
              Вкусноты нужны не&nbsp;«когда-нибудь». Они нужны к&nbsp;моменту: релизу, клипу, концерту, PR-рассылке, розыгрышу или при остром желании взаимодействия со своей аудиторией.
            </p>
          </div>
        </div>

        <div className="scenarios">
          {sc.map(s => (
            <div className="scn" key={s.tag}>
              <div className="tagrow">
                <span>Use · {s.tag}</span>
                <span style={{ color: "var(--acid)" }}>●</span>
              </div>
              <h3>{s.title}</h3>
              <p>{s.body}</p>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
};

Object.assign(window, { WhatIs, Positioning, Why, Customization, Process, Scenarios });

