const { useState, useMemo, useEffect } = React;

/* Куда фронтенд шлёт заявку. Тот же origin, что и сайт (бэкенд раздаёт статику). */
const APPLY_ENDPOINT = "/api/apply";

/* =========================================================================
   PRICING MODEL
   ========================================================================= */
const FORMATS = {
  domofon: {
    id: "domofon",
    name: "Стенды в многоквартирных домах",
    short: "СТЕНДЫ",
    sub: "в многоквартирных домах",
    desc: "Носители А4 в подъездах жилых домов. Аудитория — жильцы каждый день, на пути из дома и обратно.",
    plans: {
      "15": { price: 225, perDay: 15, minQty: 80, label: "15 дней" },
      "30": { price: 270, perDay: 9,  minQty: 60, label: "1 месяц" },
    },
    unit: "стенд",
    unitPl: "стендов",
  },
  podgol: {
    id: "podgol",
    name: "Подголовники в автобусах",
    short: "ПОДГОЛОВНИКИ",
    sub: "в городских автобусах",
    desc: "Рекламные накидки на подголовники сидений. Пассажир видит рекламу всё время поездки.",
    plans: {
      "30": { price: 2990, perDay: 100, minQty: 5, label: "1 месяц" },
    },
    unit: "автобус",
    unitPl: "автобусов",
    note: "Размещение только от 1 месяца.",
  },
  aficha: {
    id: "aficha",
    name: "Афиши А3 в транспорте",
    short: "АФИШИ А3",
    sub: "в троллейбусах и автобусах",
    desc: "Афиши формата А3 над сидениями в автобусах и троллейбусах. Контакт — вся поездка.",
    plans: {
      "15": { price: 360, perDay: 24, minQty: 40, label: "15 дней" },
      "30": { price: 570, perDay: 19, minQty: 25, label: "1 месяц" },
    },
    unit: "ТС",
    unitPl: "ТС",
  },
};

/* Города размещения. Стенды и афиши — только Стерлитамак. Подголовники — мультивыбор. */
const PODGOL_CITIES = ["Стерлитамак", "Салават", "Ишимбай", "Нефтекамск", "Мелеуз", "Белебей"];
const FIXED_CITY = "Стерлитамак";

/* Формат стенда для стендов у домофонов. */
const STAND_SIZES = [
  { id: "A5", label: "А5 — над домофоном" },
  { id: "A4", label: "А4 — у подъезда" },
];
const citiesString = (formatId, cities) =>
  formatId === "podgol" ? (cities && cities.length ? cities.join(", ") : "") : FIXED_CITY;

const DURATION_OPTIONS = [
  { id: "15", label: "15 дней", baseDays: 15 },
  { id: "30", label: "1 месяц", baseDays: 30, multiplier: 1 },
  { id: "60", label: "2 месяца", baseDays: 60, multiplier: 2, basePlan: "30" },
  { id: "90", label: "3 месяца", baseDays: 90, multiplier: 3, basePlan: "30" },
  { id: "180", label: "6 месяцев", baseDays: 180, multiplier: 6, basePlan: "30" },
  { id: "365", label: "12 месяцев", baseDays: 365, multiplier: 12, basePlan: "30" },
];

function priceFor(formatId, durationId, qty) {
  const fmt = FORMATS[formatId];
  if (!fmt) return null;
  const dur = DURATION_OPTIONS.find(d => d.id === durationId);
  if (!dur) return null;
  // pick base plan
  let plan = fmt.plans[dur.id] || (dur.basePlan && fmt.plans[dur.basePlan]);
  if (!plan) return null;
  const mult = dur.multiplier ?? 1;
  const perUnit = plan.price * mult;
  const total = perUnit * qty;
  const minQty = plan.minQty;
  return { perUnit, total, minQty, plan, dur, fmt, multiplier: mult };
}

const fmtRub = (n) =>
  new Intl.NumberFormat("ru-RU", { maximumFractionDigits: 0 }).format(Math.round(n)) + " ₽";

/* =========================================================================
   SHARED CHROME
   ========================================================================= */
function Logo({ light }) {
  return (
    <div className="logo">
      <svg viewBox="0 0 40 40" width="32" height="32" aria-hidden="true">
        <path d="M6 30 L18 10 L24 20 L28 14 L34 30 Z" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinejoin="round" />
        <circle cx="20" cy="20" r="17" fill="none" stroke="currentColor" strokeWidth="1.2" opacity="0.35" />
      </svg>
      <div className="logo-text">
        <span className="logo-main">Рекламное решение</span>
        <span className="logo-sub">наружная реклама</span>
      </div>
    </div>
  );
}

function Header({ page, setPage }) {
  const [open, setOpen] = useState(false);
  const go = (p) => { setPage(p); setOpen(false); };

  return (
    <>
      <header className="site-header">
        <button className="header-slot left glass-pill" onClick={() => go("home")}>
          <Logo />
        </button>

        <nav className="header-slot center glass-pill nav-pill">
          <button className={page === "home"  ? "active" : ""} onClick={() => go("home")}>
            <span className="dot" /> Главная
          </button>
          <button className={page === "calc"  ? "active" : ""} onClick={() => go("calc")}>
            Калькулятор
          </button>
          <button className={page === "apply" ? "active" : ""} onClick={() => go("apply")}>
            Заявка
          </button>
        </nav>

        <button className="header-slot right glass-pill contact-pill" onClick={() => go("apply")}>
          <span className="contact-ico">
            <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2">
              <path d="M5 4h4l2 5-2.5 1.5a11 11 0 0 0 5 5L15 13l5 2v4a2 2 0 0 1-2 2A16 16 0 0 1 3 6a2 2 0 0 1 2-2z" />
            </svg>
          </span>
          +7 (906) 100-03-90
        </button>

        <button className={`mob-burger glass-pill ${open ? "open" : ""}`} onClick={() => setOpen(o => !o)} aria-label="Меню">
          <span /><span /><span />
        </button>
      </header>

      {open && (
        <div className="mob-menu glass-card">
          <button className={page === "home"  ? "active" : ""} onClick={() => go("home")}>Главная</button>
          <button className={page === "calc"  ? "active" : ""} onClick={() => go("calc")}>Калькулятор</button>
          <button className={page === "apply" ? "active" : ""} onClick={() => go("apply")}>Заявка</button>
          <a href="tel:+79061000390">
            <svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" strokeWidth="2">
              <path d="M5 4h4l2 5-2.5 1.5a11 11 0 0 0 5 5L15 13l5 2v4a2 2 0 0 1-2 2A16 16 0 0 1 3 6a2 2 0 0 1 2-2z" />
            </svg>
            +7 (906) 100-03-90
          </a>
        </div>
      )}
    </>
  );
}

/* =========================================================================
   HOME PAGE
   ========================================================================= */
function HomePage({ setPage, prefill }) {
  const [openProduct, setOpenProduct] = useState(null);

  const goToCalc = () => {
    if (openProduct) prefill(openProduct.id);
    setOpenProduct(null);
    setPage("calc");
  };

  return (
    <main className="page page-home" data-screen-label="01 Home">
      <div className="mountain-stage">
        <img src="assets/mountain.png" alt="" className="mountain-img" />
        <div className="mountain-fade" />
      </div>

      <section className="hero">
        <h1 className="hero-title">Рекламу&nbsp;надо?</h1>
        <p className="hero-sub">
          Помогаем увеличить продажи в&nbsp;вашем бизнесе, быстро и&nbsp;без больших вложений.
          <br />
          Разместим ваше предложение в&nbsp;транспорте и&nbsp;многоквартирных домах в&nbsp;Стерлитамаке и&nbsp;других городах Республики Башкортостан.
        </p>
      </section>

      {/* Товары — клик открывает модалку с фото и описанием */}
      <section className="format-row">
        {Object.values(FORMATS).map((fmt, i) => (
          <FormatCard key={fmt.id} fmt={fmt} idx={i} onClick={() => setOpenProduct(fmt)} />
        ))}
      </section>

      <section className="bottom-strip single">
        <div className="strip-mid glass-pill">
          <span>Готовы посчитать стоимость?</span>
          <button className="cta-mini" onClick={() => setPage("calc")}>
            Открыть калькулятор →
          </button>
        </div>
      </section>

      {/* Отдельный блок про компанию */}
      <section className="info-block">
        <div className="info-block-head">
          <span className="tag">О&nbsp;компании</span>
        </div>
        <div className="format-row">
          {INFO_CARDS.map((card, i) => (
            <InfoFlipCard key={card.id} card={card} idx={i} />
          ))}
        </div>
      </section>

      {openProduct && (
        <ProductModal
          product={openProduct}
          onClose={() => setOpenProduct(null)}
          onCalc={goToCalc}
        />
      )}
    </main>
  );
}

/* =========================================================================
   PRODUCT MODAL — открывается с главной по клику на карточку товара
   ========================================================================= */
/* Альбомы фото. У домофонных стендов их два (А5 и А4). У остальных — один. */
const PRODUCT_ALBUMS = {
  aficha: [
    { photos: ["assets/aficha-1.jpg", "assets/aficha-2.jpg"] },
  ],
  domofon: [
    {
      title: "стенд над домофоном",
      photos: ["assets/domofon-a5-1.jpg", "assets/domofon-a5-2.jpg", "assets/domofon-a5-3.jpg"],
    },
    {
      title: "стенд у подъезда",
      photos: ["assets/domofon-a4-1.jpg", "assets/domofon-a4-2.jpg", "assets/domofon-a4-3.jpg"],
    },
  ],
  podgol: [
    { photos: ["assets/podgol-1.jpg", "assets/podgol-2.jpg"] },
  ],
};

/* Развёрнутые описания для модалок товаров. Если для id нет ключа — модалка
   рендерит короткий fmt.desc как fallback. */
const PRODUCT_DETAILS = {
  domofon: (
    <>
      <p><strong>Стенды в&nbsp;многоквартирных домах:</strong></p>
      <ul className="route-list">
        <li>над домофоном — формат <b>А5</b></li>
        <li>у&nbsp;подъезда — формат <b>А4</b></li>
      </ul>

      <p><strong>Стенд над домофоном</strong> — А5, горизонтальный.</p>
      <p><b>Преимущества:</b></p>
      <ul className="route-list">
        <li>1 рекламодатель;</li>
        <li>отсутствие конкуренции;</li>
        <li>вашу рекламу увидят неоднократно все жители дома.</li>
      </ul>

      <p><strong>Стенд у&nbsp;подъезда</strong> — А4, горизонтальный.</p>
      <p><b>Преимущества:</b></p>
      <ul className="route-list">
        <li>только 2 рекламодателя;</li>
        <li>отсутствие конкуренции;</li>
        <li>вашу рекламу увидят неоднократно все жители дома.</li>
      </ul>
    </>
  ),
  podgol: (
    <>
      <p>Подголовник на сиденье расположен на уровне глаз.</p>
      <p>15&nbsp;минут — среднее время поездки пассажира в&nbsp;автобусе. За&nbsp;это время ваше предложение 100% увидят.</p>
      <p><strong>21&nbsp;000 пассажиров</strong> перевозит один автобус в&nbsp;месяц.</p>
      <p><strong>Маршруты автобусов:</strong></p>
      <ul className="route-list">
        <li><b>Стерлитамак</b> — №№ 17, 31, 32, 33, 35, 36, 43с, 140, 141, 143 + межгородские</li>
        <li><b>Салават</b> — №№ 1, 3, 5, 10 + межгородские</li>
        <li><b>Ишимбай</b> — №№ 1, 2, 3, 8 + межгородские</li>
        <li><b>Мелеуз</b> — №№ 1, 2, 3, 8 + межгородские</li>
        <li><b>Нефтекамск</b> — №№ 1, 1а, 3, 5, 6, 7, 8, 10</li>
        <li><b>Белебей</b> — №№ 1, 5, 7, 101, 110</li>
      </ul>
      <p className="product-note">
        Поможем подобрать маршруты под ваш запрос — звоните{" "}
        <a href="tel:+79061000390">+7&nbsp;(906)&nbsp;100-03-90</a>.
      </p>
    </>
  ),
  aficha: (
    <>
      <p>Афиши размещены на&nbsp;видном месте в&nbsp;салоне троллейбусов и&nbsp;автобусов. Крепятся на&nbsp;стекло.</p>
      <p>Форматы афиш — <strong>А4 и&nbsp;А3</strong>.</p>
      <p>Ваше предложение видят пассажиры троллейбусов и&nbsp;автобусов:</p>
      <ul className="route-list">
        <li><b>15&nbsp;000 пассажиров</b> — один троллейбус в&nbsp;месяц</li>
        <li><b>180&nbsp;000 пассажиров</b> — один автобус в&nbsp;месяц</li>
      </ul>
      <p><strong>Маршруты размещения:</strong></p>
      <ul className="route-list">
        <li><b>Автобусы</b> — №№ 43с, 140, 141, 143</li>
        <li><b>Троллейбусы</b> — №№ 1, 2, 3, 6, 7, 8, 13, 14, 17</li>
      </ul>
      <p className="product-note">
        Поможем подобрать маршруты под ваш запрос — звоните{" "}
        <a href="tel:+79061000390">+7&nbsp;(906)&nbsp;100-03-90</a>.
      </p>
    </>
  ),
};

/* Обложки для показа в модалке.
   Если у товара несколько альбомов — берём первую фотку каждого и клик открывает
   свой альбом. Если один альбом — берём первые две фотки, обе ведут в этот
   альбом со стартом на своём индексе. */
function productCovers(albums) {
  if (!albums || !albums.length) return [];
  if (albums.length >= 2) {
    return albums.slice(0, 2).map((a, ai) => ({
      src: a.photos[0], album: ai, index: 0, title: a.title,
    }));
  }
  const a = albums[0];
  return [
    { src: a.photos[0], album: 0, index: 0 },
    { src: a.photos[1] || a.photos[0], album: 0, index: 1 },
  ];
}

function ProductModal({ product, onClose, onCalc }) {
  // zoom = { album: number, index: number } или null
  const [zoom, setZoom] = useState(null);
  const albums = PRODUCT_ALBUMS[product.id] || [];
  const isZoomed = zoom !== null;

  const zoomedPhotos = isZoomed ? albums[zoom.album].photos : [];
  const goPrev = () => setZoom(z => ({ ...z, index: (z.index - 1 + zoomedPhotos.length) % zoomedPhotos.length }));
  const goNext = () => setZoom(z => ({ ...z, index: (z.index + 1) % zoomedPhotos.length }));

  useEffect(() => {
    const onKey = (e) => {
      if (isZoomed) {
        if (e.key === "Escape") setZoom(null);
        else if (e.key === "ArrowLeft") goPrev();
        else if (e.key === "ArrowRight") goNext();
      } else if (e.key === "Escape") {
        onClose();
      }
    };
    document.addEventListener("keydown", onKey);
    const prevOverflow = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return () => {
      document.removeEventListener("keydown", onKey);
      document.body.style.overflow = prevOverflow;
    };
  }, [onClose, isZoomed, zoomedPhotos.length]);

  // Свайпы на телефоне для перелистывания в fullscreen
  const touchStart = React.useRef(null);
  const onTouchStart = (e) => { touchStart.current = e.touches[0].clientX; };
  const onTouchEnd = (e) => {
    if (touchStart.current === null) return;
    const dx = e.changedTouches[0].clientX - touchStart.current;
    touchStart.current = null;
    if (Math.abs(dx) < 40) return;
    if (dx < 0) goNext(); else goPrev();
  };

  // Рендерим прямо в document.body через Portal, чтобы не попадать в
  // stacking-context страницы — иначе шапка/бургер перекрывают крестик.
  return ReactDOM.createPortal(
    <>
      <div className="modal-overlay" onClick={onClose}>
        <div className="modal product-modal" onClick={(e) => e.stopPropagation()}>
          <button className="modal-close" onClick={onClose} aria-label="Закрыть">×</button>
          <div className="product-grid">
            <div className="product-photos">
              {productCovers(albums).map((cover, i) => (
                <button
                  key={i}
                  type="button"
                  className="product-photo-thumb"
                  onClick={() => setZoom({ album: cover.album, index: cover.index })}
                  aria-label={cover.title ? `Открыть альбом «${cover.title}»` : "Открыть фото"}
                >
                  <img src={cover.src} alt="" />
                  {cover.title && <span className="cover-label">{cover.title}</span>}
                  <span className="zoom-hint">⤢</span>
                </button>
              ))}
            </div>
            <div className="product-side">
              <div className="product-desc">
                <span className="fmt-pill">{product.short}</span>
                <h3>{product.name}</h3>
                {PRODUCT_DETAILS[product.id] || <p>{product.desc}</p>}
                {product.note && <p className="product-note">ⓘ {product.note}</p>}
              </div>
              <button className="cta-big" onClick={onCalc}>
                Рассчитать стоимость
                <span className="cta-arrow">→</span>
              </button>
            </div>
          </div>
        </div>
      </div>
      {isZoomed && (
        <div
          className="zoom-overlay"
          onClick={() => setZoom(null)}
          onTouchStart={onTouchStart}
          onTouchEnd={onTouchEnd}
        >
          <img src={zoomedPhotos[zoom.index]} alt={product.name} onClick={(e) => e.stopPropagation()} />
          {zoomedPhotos.length > 1 && (
            <>
              <button className="zoom-nav prev" onClick={(e) => { e.stopPropagation(); goPrev(); }} aria-label="Предыдущее фото">‹</button>
              <button className="zoom-nav next" onClick={(e) => { e.stopPropagation(); goNext(); }} aria-label="Следующее фото">›</button>
              <div className="zoom-counter">{zoom.index + 1} / {zoomedPhotos.length}</div>
            </>
          )}
          <button className="modal-close zoom-close" onClick={(e) => { e.stopPropagation(); setZoom(null); }} aria-label="Закрыть">×</button>
        </div>
      )}
    </>,
    document.body
  );
}

/* =========================================================================
   INFO FLIP CARDS (на главной): О нас, Почему мы, Контакты
   ========================================================================= */
const INFO_CARDS = [
  {
    id: "about",
    pill: "Кто мы",
    title: "О нас",
    sub: "коротко о компании",
    icon: (
      <svg viewBox="0 0 48 48" width="40" height="40" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinejoin="round" strokeLinecap="round">
        <circle cx="24" cy="18" r="7" />
        <path d="M10 40c2-7 8-11 14-11s12 4 14 11" />
      </svg>
    ),
    back: (
      <>
        <p><strong>«Рекламное решение»</strong> — компания, главная задача которой помогать бизнесам увеличивать продажи за счёт размещения рекламы в&nbsp;транспорте и&nbsp;в&nbsp;многоквартирных домах.</p>
        <p>За&nbsp;7&nbsp;лет помогли более <strong>230&nbsp;организациям</strong> в&nbsp;Республике Башкортостан увеличить продажи.</p>
        <p><strong>Работаем в&nbsp;городах:</strong><br />Стерлитамак, Салават, Ишимбай, Мелеуз, Нефтекамск, Белебей.</p>
      </>
    ),
  },
  {
    id: "why",
    pill: "Преимущества",
    title: "Почему именно мы?",
    sub: "что мы делаем лучше",
    icon: (
      <svg viewBox="0 0 48 48" width="40" height="40" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinejoin="round" strokeLinecap="round">
        <path d="M24 6l4.6 9.4 10.4 1.5-7.5 7.3 1.8 10.3L24 29.7l-9.3 4.8 1.8-10.3L9 16.9l10.4-1.5z" />
      </svg>
    ),
    back: (
      <>
        <p>Нам доверяют и&nbsp;с&nbsp;нами выгодно работать по&nbsp;следующим причинам:</p>
        <ol className="info-list numbered">
          <li>
            <b>Экономим ваше время — всё в&nbsp;одном месте.</b><br />
            Команда специалистов с&nbsp;7-летним опытом из&nbsp;разных рекламных направлений: подберём наилучшие варианты размещения и&nbsp;дадим рабочие инструменты без потери времени и&nbsp;средств.
          </li>
          <li>
            <b>Экономим ваш бюджет.</b><br />
            Работаем напрямую с&nbsp;перевозчиками и&nbsp;управляющими компаниями — за&nbsp;счёт этого даём лучшую цену.
          </li>
          <li>
            <b>Небольшой порог входа.</b><br />
            Подберём лучшие рекламные инструменты под ваш запрос и&nbsp;бюджет.
          </li>
          <li>
            <b>Семь рекламных направлений в&nbsp;Стерлитамаке.</b><br />
            Подберём площадки, где есть ваша аудитория. Покажем вашу рекламу клиентам точечно, в&nbsp;нужном районе.
          </li>
        </ol>
      </>
    ),
  },
  {
    id: "contact",
    pill: "Связаться",
    title: "Контактная информация",
    sub: "как с нами связаться",
    icon: (
      <svg viewBox="0 0 48 48" width="40" height="40" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinejoin="round" strokeLinecap="round">
        <path d="M14 8h8l3 8-4 3a18 18 0 0 0 8 8l3-4 8 3v8a4 4 0 0 1-4 4C20.3 38 10 27.7 10 12a4 4 0 0 1 4-4z" />
      </svg>
    ),
    back: (
      <ul className="info-list contact-list">
        <li>
          <span className="info-key">Телефон</span>
          <a className="info-val" href="tel:+79061000390">+7 (906) 100-03-90</a>
        </li>
        <li>
          <span className="info-key">Телефон</span>
          <a className="info-val" href="tel:+79061000240">+7 (906) 100-02-40</a>
        </li>
        <li>
          <span className="info-key">ВКонтакте</span>
          <a className="info-val" href="https://vk.ru/reklamynado" target="_blank" rel="noopener noreferrer">vk.ru/reklamynado</a>
        </li>
        <li>
          <span className="info-key">E-mail</span>
          <a className="info-val" href="mailto:reklama@stutr.ru">reklama@stutr.ru</a>
        </li>
      </ul>
    ),
  },
];

function InfoFlipCard({ card, idx }) {
  const [flipped, setFlipped] = useState(false);
  return (
    <div
      className={`flip-card delay-${idx} ${flipped ? "is-flipped" : ""}`}
      onClick={() => setFlipped(f => !f)}
      role="button"
      tabIndex={0}
      onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); setFlipped(f => !f); } }}
    >
      <div className="flip-inner">
        <div className="flip-face flip-front glass-card">
          <div className="fmt-top">
            <span className="fmt-pill">{card.pill}</span>
          </div>
          <div className="fmt-icon">{card.icon}</div>
          <div className="fmt-body">
            <div className="fmt-name">{card.title}</div>
            <div className="fmt-sub">{card.sub}</div>
          </div>
          <div className="flip-hint">нажмите, чтобы перевернуть →</div>
        </div>
        <div className="flip-face flip-back glass-card dark">
          <div className="flip-back-title">{card.title}</div>
          <div className="flip-back-body">{card.back}</div>
          <div className="flip-hint back">← назад</div>
        </div>
      </div>
    </div>
  );
}

function FormatCard({ fmt, idx, onClick }) {
  const icons = {
    domofon: (
      <svg viewBox="0 0 48 48" width="40" height="40" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinejoin="round">
        <rect x="10" y="6" width="28" height="36" rx="2" />
        <rect x="16" y="12" width="16" height="14" />
        <circle cx="20" cy="33" r="1.6" fill="currentColor" />
        <circle cx="28" cy="33" r="1.6" fill="currentColor" />
        <line x1="20" y1="38" x2="28" y2="38" />
      </svg>
    ),
    podgol: (
      <svg viewBox="0 0 48 48" width="40" height="40" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinejoin="round">
        <path d="M8 38h32" />
        <rect x="14" y="10" width="20" height="22" rx="3" />
        <rect x="18" y="14" width="12" height="10" />
        <path d="M14 32v6M34 32v6" />
      </svg>
    ),
    aficha: (
      <svg viewBox="0 0 48 48" width="40" height="40" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinejoin="round">
        <rect x="6" y="14" width="36" height="22" rx="2" />
        <circle cx="14" cy="38" r="3" />
        <circle cx="34" cy="38" r="3" />
        <line x1="12" y1="20" x2="36" y2="20" />
        <line x1="12" y1="26" x2="28" y2="26" />
      </svg>
    ),
  };

  return (
    <button className={`fmt-card glass-card delay-${idx}`} onClick={onClick}>
      <div className="fmt-top">
        <span className="fmt-pill">{["Реклама в многоквартирных домах", "Реклама в общественном транспорте", "Реклама в общественном транспорте"][idx]}</span>
      </div>
      <div className="fmt-icon">{icons[fmt.id]}</div>
      <div className="fmt-body">
        <div className="fmt-name">{fmt.short}</div>
        <div className="fmt-sub">{fmt.sub}</div>
      </div>
      <div className="fmt-foot">
        <span className="fmt-cta">Подробнее</span>
        <span className="fmt-arrow">→</span>
      </div>
    </button>
  );
}

/* =========================================================================
   CALCULATOR
   ========================================================================= */
function CalcPage({ setPage, calcState, setCalcState }) {
  const { formatId, durationId, qty, cities } = calcState;
  const fmt = FORMATS[formatId];
  const availableDurations = DURATION_OPTIONS.filter(d =>
    fmt.plans[d.id] || (d.basePlan && fmt.plans[d.basePlan])
  );

  const result = useMemo(() => priceFor(formatId, durationId, qty), [formatId, durationId, qty]);
  const belowMin = result && qty < result.minQty;

  // ensure duration is valid for selected format
  useEffect(() => {
    if (!availableDurations.find(d => d.id === durationId)) {
      setCalcState(s => ({ ...s, durationId: availableDurations[0].id }));
    }
  }, [formatId]);

  const setF = (id) => setCalcState(s => ({ ...s, formatId: id }));
  const setD = (id) => setCalcState(s => ({ ...s, durationId: id }));
  const setQ = (n) => setCalcState(s => ({ ...s, qty: Math.max(1, Math.min(9999, n || 1)) }));
  const toggleCity = (c) => setCalcState(s => {
    const has = s.cities.includes(c);
    // нельзя оставить пустым — последний город нельзя снять
    if (has && s.cities.length === 1) return s;
    return { ...s, cities: has ? s.cities.filter(x => x !== c) : [...s.cities, c] };
  });

  return (
    <main className="page page-calc" data-screen-label="02 Calculator">
      <div className="mountain-stage subtle">
        <img src="assets/mountain.png" alt="" className="mountain-img" />
        <div className="mountain-fade" />
      </div>

      <section className="calc-head">
        <span className="crumbs">
          <button onClick={() => setPage("home")} className="crumb">Главная</button>
          <span className="crumb-sep">/</span>
          <span className="crumb-here">Калькулятор</span>
        </span>
        <h1 className="calc-title">Сколько будет стоить?</h1>
        <p className="calc-sub">Выберите формат, срок и количество — увидите цену в реальном времени.</p>
      </section>

      <div className="calc-grid">
        {/* LEFT — controls */}
        <div className="calc-form glass-card">
          <Step n="01" title="Тип рекламы">
            <div className="fmt-pick">
              {Object.values(FORMATS).map(f => (
                <button
                  key={f.id}
                  className={`fmt-pick-card ${formatId === f.id ? "on" : ""}`}
                  onClick={() => setF(f.id)}
                >
                  <span className="fmt-pick-short">{f.short}</span>
                  <span className="fmt-pick-sub">{f.sub}</span>
                  <span className="fmt-pick-from">от {fmtRub(Math.min(...Object.values(f.plans).map(p => p.price)))} / {f.unit}</span>
                </button>
              ))}
            </div>

            {formatId === "domofon" && (
              <div className="sub-choice">
                <span className="sub-choice-label">Формат размещения:</span>
                <div className="duration-row">
                  {STAND_SIZES.map(s => (
                    <button
                      key={s.id}
                      type="button"
                      className={`dur-pill ${calcState.standSize === s.id ? "on" : ""}`}
                      onClick={() => setCalcState(st => ({ ...st, standSize: s.id }))}
                    >
                      {s.label}
                    </button>
                  ))}
                </div>
              </div>
            )}
          </Step>

          <Step n="02" title="Срок размещения">
            <div className="duration-row">
              {DURATION_OPTIONS.map(d => {
                const ok = !!availableDurations.find(a => a.id === d.id);
                return (
                  <button
                    key={d.id}
                    className={`dur-pill ${durationId === d.id ? "on" : ""} ${!ok ? "off" : ""}`}
                    disabled={!ok}
                    onClick={() => setD(d.id)}
                    title={!ok ? "Недоступно для этого формата" : ""}
                  >
                    {d.label}
                  </button>
                );
              })}
            </div>
            {fmt.note && <p className="note">ⓘ {fmt.note}</p>}
          </Step>

          <Step n="03" title={`Количество (${fmt.unitPl})`}>
            <div className="qty-row">
              <button className="qty-btn" onClick={() => setQ(qty - 1)}>−</button>
              <input
                className="qty-input"
                type="number"
                value={qty}
                onChange={e => setQ(parseInt(e.target.value, 10))}
              />
              <button className="qty-btn" onClick={() => setQ(qty + 1)}>+</button>
              <div className="qty-quick">
                {[result?.minQty, (result?.minQty || 1) * 2, (result?.minQty || 1) * 4].filter(Boolean).map(v => (
                  <button key={v} className="quick-pill" onClick={() => setQ(v)}>{v}</button>
                ))}
              </div>
            </div>
            <div className={`min-line ${belowMin ? "warn" : "ok"}`}>
              {belowMin
                ? `Минимальный заказ для этого тарифа — ${result.minQty} ${fmt.unitPl}. Стоимость считаем как ориентир.`
                : `Минимальный заказ — ${result?.minQty} ${fmt.unitPl}. ✓`}
            </div>
          </Step>

          <Step n="04" title="Город размещения">
            {formatId === "podgol" ? (
              <>
                <div className="duration-row">
                  {PODGOL_CITIES.map(c => (
                    <button
                      key={c}
                      type="button"
                      className={`dur-pill ${cities.includes(c) ? "on" : ""}`}
                      onClick={() => toggleCity(c)}
                    >
                      {c}
                    </button>
                  ))}
                </div>
                <p className="note">ⓘ Можно выбрать несколько городов — у каждого свой пул автобусов. Минимум один город обязателен.</p>
              </>
            ) : (
              <>
                <div className="duration-row">
                  <span className="dur-pill on" style={{ cursor: "default" }}>{FIXED_CITY}</span>
                </div>
                <p className="note">ⓘ Этот формат рекламы размещается только в&nbsp;Стерлитамаке.</p>
              </>
            )}
          </Step>
        </div>

        {/* RIGHT — result */}
        <aside className="calc-result glass-card dark">
          <div className="res-eyebrow">Предварительная стоимость</div>
          <div className="res-total">{result ? fmtRub(result.total) : "—"}</div>
          <div className="res-meta">
            {result && (
              <>
                <span>{fmtRub(result.perUnit)} × {qty} {fmt.unitPl}</span>
                <span className="dotsep">•</span>
                <span>{result.dur.label}</span>
              </>
            )}
          </div>

          <div className="res-divider" />

          <ul className="res-breakdown">
            <li><span>Формат</span><strong>{fmt.short}</strong></li>
            {formatId === "domofon" && (
              <li>
                <span>Размещение</span>
                <strong>{STAND_SIZES.find(s => s.id === calcState.standSize)?.label}</strong>
              </li>
            )}
            <li>
              <span>{formatId === "podgol" && cities.length > 1 ? "Города" : "Город"}</span>
              <strong>{citiesString(formatId, cities)}</strong>
            </li>
            <li><span>Срок</span><strong>{result?.dur.label}</strong></li>
            <li>
              <span>Цена за {fmt.unit}</span>
              <strong>{result ? fmtRub(result.perUnit) : "—"}</strong>
            </li>
            <li><span>Количество</span><strong>{qty} {fmt.unitPl}</strong></li>
            <li><span>Минимум</span><strong>{result?.minQty} {fmt.unitPl}</strong></li>
          </ul>

          <div className="res-divider" />

          <p className="res-fineprint">
            Поможем разработать рекламный макет.<br />
            Монтаж и&nbsp;фотоотчёт входят в&nbsp;стоимость размещения.
          </p>

          <button className="cta-big" onClick={() => setPage("apply")}>
            Оформить заявку
            <span className="cta-arrow">→</span>
          </button>
        </aside>
      </div>
    </main>
  );
}

function Step({ n, title, children }) {
  return (
    <div className="step">
      <div className="step-head">
        <span className="step-n">{n}</span>
        <span className="step-title">{title}</span>
      </div>
      <div className="step-body">{children}</div>
    </div>
  );
}

/* =========================================================================
   APPLY (REQUEST) FORM
   ========================================================================= */
function ApplyPage({ setPage, calcState, setCalcState }) {
  const [form, setForm] = useState({
    name: "",
    phone: "",
    email: "",
    formatId: calcState.formatId,
    durationId: calcState.durationId,
    qty: calcState.qty,
    cities: calcState.cities || [PODGOL_CITIES[0]],
    standSize: calcState.standSize || "A5",
    comment: "",
  });
  const [submitted, setSubmitted] = useState(false);
  const [touched, setTouched] = useState({});
  const [sending, setSending] = useState(false);
  const [sendError, setSendError] = useState("");

  const fmt = FORMATS[form.formatId];
  const result = useMemo(() => priceFor(form.formatId, form.durationId, form.qty), [form]);

  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const touch = (k) => setTouched(t => ({ ...t, [k]: true }));

  const phoneOk = /^[+\d\s()-]{7,}$/.test(form.phone);
  const emailOk = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.email);
  const nameOk  = form.name.trim().length >= 2;
  const formOk = phoneOk && emailOk && nameOk;

  const submit = async (e) => {
    e.preventDefault();
    setTouched({ name: true, phone: true, email: true });
    if (!formOk || sending) return;
    setSendError("");
    setSending(true);
    try {
      const res = await fetch(APPLY_ENDPOINT, {
        method: "POST",
        headers: { "Content-Type": "application/json", Accept: "application/json" },
        body: JSON.stringify({
          name: form.name,
          phone: form.phone,
          email: form.email,
          format: form.formatId === "domofon"
            ? `${fmt.name} (${STAND_SIZES.find(s => s.id === form.standSize)?.label || form.standSize})`
            : fmt.name,
          city: citiesString(form.formatId, form.cities),
          duration: result ? result.dur.label : form.durationId,
          qty: `${form.qty} ${fmt.unitPl}`,
          price: result ? fmtRub(result.total) : "—",
          comment: form.comment.trim(),
        }),
      });
      const data = await res.json().catch(() => ({}));
      if (res.ok && data.success) {
        setSubmitted(true);
      } else {
        setSendError(data.message || "Не удалось отправить заявку. Попробуйте ещё раз или позвоните нам.");
      }
    } catch (err) {
      setSendError("Нет связи с сервером. Проверьте интернет и попробуйте ещё раз.");
    } finally {
      setSending(false);
    }
  };

  if (submitted) {
    return (
      <main className="page page-apply" data-screen-label="03 Apply Success">
        <div className="mountain-stage subtle">
          <img src="assets/mountain.png" alt="" className="mountain-img" />
          <div className="mountain-fade" />
        </div>
        <section className="success glass-card">
          <div className="success-tick">
            <svg viewBox="0 0 48 48" width="48" height="48" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round">
              <circle cx="24" cy="24" r="20" />
              <path d="M14 25 l7 7 l13 -15" />
            </svg>
          </div>
          <h2>Заявка отправлена</h2>
          <p>Здравствуйте, {form.name}! Менеджер свяжется с&nbsp;вами по&nbsp;номеру <strong>{form.phone}</strong> в&nbsp;течение рабочего дня.</p>
          <div className="success-summary">
            <div><span>Формат</span><strong>{fmt.short}</strong></div>
            <div><span>Срок</span><strong>{result?.dur.label}</strong></div>
            <div><span>Количество</span><strong>{form.qty} {fmt.unitPl}</strong></div>
            <div><span>Ориентир по&nbsp;цене</span><strong>{result && fmtRub(result.total)}</strong></div>
          </div>
          <div className="success-actions">
            <button className="cta-big ghost" onClick={() => { setSubmitted(false); setPage("home"); }}>← На главную</button>
            <button className="cta-big" onClick={() => { setSubmitted(false); setPage("calc"); }}>Посчитать ещё формат</button>
          </div>
        </section>
      </main>
    );
  }

  return (
    <main className="page page-apply" data-screen-label="03 Apply">
      <div className="mountain-stage subtle">
        <img src="assets/mountain.png" alt="" className="mountain-img" />
        <div className="mountain-fade" />
      </div>

      <section className="calc-head">
        <span className="crumbs">
          <button onClick={() => setPage("home")} className="crumb">Главная</button>
          <span className="crumb-sep">/</span>
          <button onClick={() => setPage("calc")} className="crumb">Калькулятор</button>
          <span className="crumb-sep">/</span>
          <span className="crumb-here">Заявка</span>
        </span>
        <h1 className="calc-title">Оставьте заявку</h1>
        <p className="calc-sub">Менеджер вернётся с&nbsp;адресным списком, графиком монтажа и&nbsp;финальной сметой.</p>
      </section>

      <form className="apply-grid" onSubmit={submit} noValidate>
        <div className="apply-form glass-card">
          <Step n="01" title="Контактные данные">
            <div className="field-row single">
              <Field
                label="Имя"
                placeholder="Как к вам обращаться"
                value={form.name}
                onChange={v => set("name", v)}
                onBlur={() => touch("name")}
                error={touched.name && !nameOk && "Минимум 2 символа"}
              />
            </div>
            <div className="field-row">
              <Field
                label="Телефон"
                placeholder="+7 (___) ___-__-__"
                value={form.phone}
                onChange={v => set("phone", v)}
                onBlur={() => touch("phone")}
                error={touched.phone && !phoneOk && "Введите номер телефона"}
              />
              <Field
                label="E-mail"
                placeholder="hello@company.ru"
                value={form.email}
                onChange={v => set("email", v)}
                onBlur={() => touch("email")}
                error={touched.email && !emailOk && "Введите корректный e-mail"}
              />
            </div>
          </Step>

          <Step n="02" title="Тип рекламы">
            <div className="fmt-pick small">
              {Object.values(FORMATS).map(f => (
                <button
                  type="button"
                  key={f.id}
                  className={`fmt-pick-card ${form.formatId === f.id ? "on" : ""}`}
                  onClick={() => set("formatId", f.id)}
                >
                  <span className="fmt-pick-short">{f.short}</span>
                  <span className="fmt-pick-sub">{f.sub}</span>
                  <span className="fmt-pick-from">от {fmtRub(Math.min(...Object.values(f.plans).map(p => p.price)))} / {f.unit}</span>
                </button>
              ))}
            </div>

            {form.formatId === "domofon" && (
              <div className="sub-choice">
                <span className="sub-choice-label">Формат размещения:</span>
                <div className="duration-row">
                  {STAND_SIZES.map(s => (
                    <button
                      key={s.id}
                      type="button"
                      className={`dur-pill ${form.standSize === s.id ? "on" : ""}`}
                      onClick={() => set("standSize", s.id)}
                    >
                      {s.label}
                    </button>
                  ))}
                </div>
              </div>
            )}
          </Step>

          <Step n="03" title="Срок и объём">
            <div className="duration-row">
              {DURATION_OPTIONS.map(d => {
                const ok = !!(fmt.plans[d.id] || (d.basePlan && fmt.plans[d.basePlan]));
                return (
                  <button
                    type="button"
                    key={d.id}
                    className={`dur-pill ${form.durationId === d.id ? "on" : ""} ${!ok ? "off" : ""}`}
                    disabled={!ok}
                    onClick={() => set("durationId", d.id)}
                  >
                    {d.label}
                  </button>
                );
              })}
            </div>
            <div className="qty-row tight">
              <button type="button" className="qty-btn" onClick={() => set("qty", Math.max(1, form.qty - 1))}>−</button>
              <input
                className="qty-input"
                type="number"
                value={form.qty}
                onChange={e => set("qty", Math.max(1, parseInt(e.target.value, 10) || 1))}
              />
              <button type="button" className="qty-btn" onClick={() => set("qty", form.qty + 1)}>+</button>
              <span className="qty-suffix">{fmt.unitPl}</span>
            </div>

            <div className="field-label" style={{ marginTop: 18 }}>Город размещения</div>
            <div className="duration-row" style={{ marginTop: 8 }}>
              {form.formatId === "podgol" ? (
                PODGOL_CITIES.map(c => (
                  <button
                    type="button"
                    key={c}
                    className={`dur-pill ${form.cities.includes(c) ? "on" : ""}`}
                    onClick={() => set("cities",
                      form.cities.includes(c)
                        ? (form.cities.length > 1 ? form.cities.filter(x => x !== c) : form.cities)
                        : [...form.cities, c]
                    )}
                  >
                    {c}
                  </button>
                ))
              ) : (
                <span className="dur-pill on" style={{ cursor: "default" }}>{FIXED_CITY}</span>
              )}
            </div>
            {form.formatId !== "podgol" && (
              <p className="note" style={{ marginTop: 8 }}>ⓘ Этот формат рекламы размещается только в&nbsp;Стерлитамаке.</p>
            )}
          </Step>

          <Step n="04" title="Комментарий (необязательно)">
            <textarea
              className="textarea"
              rows={3}
              placeholder="Адреса, пожелания, сроки старта, ссылки на макеты…"
              value={form.comment}
              onChange={e => set("comment", e.target.value)}
            />
          </Step>

          <div className="apply-foot">
            <p className="consent">
              Нажимая «Отправить», вы соглашаетесь с&nbsp;обработкой персональных данных.
            </p>
            {sendError && <p className="field-error" style={{ marginBottom: 10 }}>{sendError}</p>}
            <button className={`cta-big ${(!formOk || sending) ? "disabled" : ""}`} type="submit" disabled={sending}>
              {sending ? "Отправка…" : "Отправить заявку"}
              {!sending && <span className="cta-arrow">→</span>}
            </button>
          </div>
        </div>

        <aside className="apply-summary glass-card dark">
          <div className="res-eyebrow">В заявке</div>
          <div className="sum-block">
            <span>Формат</span>
            <strong>{fmt.short}</strong>
          </div>
          {form.formatId === "domofon" && (
            <div className="sum-block">
              <span>Размещение</span>
              <strong>{STAND_SIZES.find(s => s.id === form.standSize)?.label}</strong>
            </div>
          )}
          <div className="sum-block">
            <span>{form.formatId === "podgol" && form.cities.length > 1 ? "Города" : "Город"}</span>
            <strong>{citiesString(form.formatId, form.cities)}</strong>
          </div>
          <div className="sum-block">
            <span>Срок</span>
            <strong>{result?.dur.label}</strong>
          </div>
          <div className="sum-block">
            <span>Количество</span>
            <strong>{form.qty} {fmt.unitPl}</strong>
          </div>
          <div className="res-divider" />
          <div className="sum-total">
            <span>Ориентир</span>
            <strong>{result && fmtRub(result.total)}</strong>
          </div>
          <p className="res-fineprint">
            Финальную смету согласуем с&nbsp;менеджером после подтверждения адресов и&nbsp;графика.
          </p>
        </aside>
      </form>
    </main>
  );
}

function Field({ label, value, onChange, onBlur, placeholder, error }) {
  return (
    <label className={`field ${error ? "err" : ""}`}>
      <span className="field-label">{label}</span>
      <input
        className="field-input"
        value={value}
        onChange={e => onChange(e.target.value)}
        onBlur={onBlur}
        placeholder={placeholder}
      />
      {error && <span className="field-error">{error}</span>}
    </label>
  );
}

/* =========================================================================
   APP
   ========================================================================= */
function App() {
  const [page, setPage] = useState("home");
  const [calcState, setCalcState] = useState({
    formatId: "domofon",
    durationId: "30",
    qty: 60,
    cities: [PODGOL_CITIES[0]], // выбор только для подголовников; стенды/афиши — Стерлитамак фиксированно
    standSize: "A5", // формат стенда, показывается только для formatId === "domofon"
  });

  // jump to top on page change
  useEffect(() => {
    window.scrollTo({ top: 0, behavior: "instant" });
  }, [page]);

  const prefillFormat = (id) => {
    const fmt = FORMATS[id];
    const firstDur = Object.keys(fmt.plans)[0];
    const minQty = fmt.plans[firstDur].minQty;
    setCalcState(s => ({
      ...s,
      formatId: id,
      durationId: firstDur,
      qty: minQty,
      cities: s.cities && s.cities.length ? s.cities : [PODGOL_CITIES[0]],
      standSize: s.standSize || "A5",
    }));
  };

  return (
    <div className="app">
      <Header page={page} setPage={setPage} />
      {page === "home"  && <HomePage setPage={setPage} prefill={prefillFormat} />}
      {page === "calc"  && <CalcPage setPage={setPage} calcState={calcState} setCalcState={setCalcState} />}
      {page === "apply" && <ApplyPage setPage={setPage} calcState={calcState} setCalcState={setCalcState} />}
      <footer className="site-foot">
        <span>© 2026 Рекламное решение</span>
        <span className="dotsep">•</span>
        <span>reklama@stutr.ru</span>
      </footer>
    </div>
  );
}

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