/*
 * Шрифты хостятся локально (public/fonts) — не через Google Fonts CDN,
 * см. docs/ru-legal-notes.md (запрет зарубежных CDN для шрифтов на проде).
 * Оба файла — вариативные (ось wght), поэтому один файл на скрипт (latin/cyrillic)
 * покрывает весь диапазон начертаний без дублирования байт.
 */
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 600 700;
  font-display: swap;
  src: url('/fonts/playfair-display-latin.woff2') format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2122, U+2212;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 600 700;
  font-display: swap;
  src: url('/fonts/playfair-display-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Golos Text';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/fonts/golos-text-latin.woff2') format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2122, U+2212;
}
@font-face {
  font-family: 'Golos Text';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/fonts/golos-text-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

/* Переменные темы — переопределяются при stamping под конкретного клиента */
:root {
  --color-primary: #1e4d3b;
  --color-primary-dark: #163a2c;
  --color-bg: #faf7f2;
  --color-bg-alt: #f1eae0;
  --color-text: #1a1a1a;
  --color-text-muted: #6b6558;
  --color-border: #e4dacb;
  --font-main: 'Playfair Display', Georgia, serif;
  --font-ui: 'Golos Text', system-ui, -apple-system, sans-serif;
  --max-width: 1100px;
  --radius: 14px;
  --radius-glass: 22px;
  /* Вертикальный ритм секций главной — единственный источник отступа.
     Прецедент: со снятием секции отзывов страница развалилась, потому
     что отступы были заданы поштучно у каждой секции и принадлежали
     промежутку между конкретной парой блоков, а не самой секции */
  --section-pad-y: 4.5rem;
  --section-pad-y-sm: 3rem;
  /* Safe-верхняя граница: на узких экранах (~360px и уже) шапка переносится
     на 2 строки (логотип + wrap-нав) и её реальная высота растёт до ~110px.
     Берём с запасом, чтобы hero+шапка гарантированно помещались в экран
     без скролла — иначе CTA уезжает за нижний край вьюпорта */
  --header-h: 112px;
  /* Стекло — только шапка и панель цены/CTA в hero, больше нигде */
  --glass-bg: rgba(250, 247, 242, 0.82);
  --glass-bg-strong: rgba(250, 247, 242, 0.96);
  --glass-border: rgba(255, 255, 255, 0.5);
  --glass-blur: blur(16px) saturate(150%);
}

/* Браузеры без backdrop-filter (см. definition-of-done: WebKit-специфика проверяется отдельно) —
   стекло превращается в непрозрачную панель, читаемость не зависит от фото под ней */
@supports not (
  (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))
) {
  :root {
    --glass-bg: var(--color-bg);
    --glass-bg-strong: var(--color-bg);
  }
}

/* Сброс */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: var(--font-ui);
  color: var(--color-text);
  background: var(--color-bg);
  line-height: 1.6;
}

img {
  max-width: 100%;
  display: block;
}

a {
  color: var(--color-primary-dark);
}

/* Утилиты */
.container {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 1.25rem;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  min-height: 44px;
  padding: 0.75rem 2rem;
  background: var(--color-primary);
  color: #fff;
  text-decoration: none;
  border-radius: 999px;
  font-family: var(--font-ui);
  font-size: 1rem;
  font-weight: 600;
  transition:
    background 0.2s,
    transform 0.15s;
  border: none;
  cursor: pointer;
}

.btn:hover {
  background: var(--color-primary-dark);
}

.btn:active {
  transform: scale(0.97);
}

/* ── Вертикальный ритм и разделение секций главной ──
   Отступ принадлежит секции, а не промежутку между конкретной парой
   блоков: включение или выключение любой секции не меняет пропорции
   остальных. Собственные padding/margin у секций — запрещены, см.
   docs/visual-system.md. Исключения ниже задокументированы поимённо
   (.hero, .trust-strip). */
main > section {
  padding: var(--section-pad-y-sm) 0;
}

@media (min-width: 768px) {
  main > section {
    padding: var(--section-pad-y) 0;
  }
}

/* Чередование фона — через nth-of-type, а НЕ через классы-модификаторы.
   Секции условны (рендерятся только при наличии данных владельца):
   при выключении любой из них последующие просто перечередуются, и
   ритм не может сломаться. Ручное назначение цвета классом оставляло
   бы после убранной секции двух одинаковых соседей подряд. */
main > section:nth-of-type(odd) {
  background: var(--color-bg);
}

main > section:nth-of-type(even) {
  background: var(--color-bg-alt);
}

/* Контраст полос намеренно мал (250,247,242 против 241,234,224) — линия
   даёт чёткий край в том числе там, где после выключения секции две
   соседние оказались одного тона */
main > section + section {
  border-top: 1px solid var(--color-border);
}

/* ── Header: стекло (1 из 2 мест, где оно допустимо) ── */
.site-header {
  padding: 1.25rem 0;
  border-bottom: 1px solid var(--glass-border);
  /* glass-bg-strong, не glass-bg: при скролле контент проходит ПОД шапкой
     (не только под hero-фото), и на обычном фоне страницы более лёгкая
     версия недостаточно гасит текст под собой — получается нечитаемое
     наложение (see docs/visual-reports) */
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  position: sticky;
  top: 0;
  z-index: 20;
}

.site-header .container {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
}

.site-logo {
  text-decoration: none;
  max-width: 100%;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  /* min-width:0 нужен, иначе flex-элемент не сжимается меньше суммарной
     intrinsic-ширины детей (картинки + текста) */
  min-width: 0;
}

/* Логотип владельца (src/shop-logo.js) показывается рядом с текстовым
   названием, не вместо него (см. src/templates/site-chrome.js). Высота
   фиксирована, ширина свободная (object-fit: contain) — исходник уже
   вписан в габарит 480×160 без искажений на этапе обработки, здесь
   только масштабирование под шапку, одинаковое для квадратных и
   горизонтальных логотипов. flex-shrink:0 — картинка не должна сжиматься
   в пользу текста, обрезается многоточием только текст (см. ниже) */
.site-logo__img {
  display: block;
  height: 2.5rem;
  width: auto;
  max-width: 40%;
  object-fit: contain;
  flex-shrink: 0;
}

.site-logo__text {
  font-family: var(--font-main);
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--color-text);
  letter-spacing: 0.01em;
  white-space: nowrap;
  /* Название магазина редактируется владельцем через /admin/profile,
     без ограничения длины — на узких вьюпортах длинное название не
     должно расталкивать шапку в горизонтальный скролл, обрезаем
     многоточием. min-width:0 нужен, иначе flex-элемент с nowrap-текстом
     не сжимается меньше своей intrinsic-ширины */
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

/* Телефон/короткий адрес в шапке (src/header-contacts.js) — опциональный
   блок между логотипом и навигацией. min-width:0 + text-overflow —
   тот же приём страховки от длинного значения, что у .site-logo__text:
   поля не ограничены по длине в форме, "короткий адрес" — подсказка
   владельцу, не гарантия */
.site-header__contact {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--color-text-muted);
  font-size: 0.85rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.site-header__contact-phone {
  color: inherit;
  text-decoration: none;
}

.site-header__contact-phone:hover {
  color: var(--color-primary);
}

.site-header__contact-sep {
  opacity: 0.5;
}

/* margin-left:auto, а не только justify-content:space-between на
   .site-header .container — при переносе .site-nav на отдельную строку
   (короткая навигация/длинное название на узких экранах) единственный
   элемент строки с space-between прижимается к flex-start, а не к
   правому краю: cart-toggle повисал сразу после последней ссылки, не
   у края. auto-margin работает одинаково и в одну строку, и при переносе. */
.site-nav {
  margin-left: auto;
}

.site-nav a {
  color: var(--color-text-muted);
  text-decoration: none;
  margin-left: 1.5rem;
  font-size: 0.95rem;
  transition: color 0.15s;
}

.site-nav a:hover {
  color: var(--color-primary);
}

/* ── Корзина: кнопка-счётчик в шапке ── */
.cart-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  margin-left: 1.25rem;
  border: none;
  background: transparent;
  color: var(--color-text);
  cursor: pointer;
  padding: 0;
}

.cart-toggle__icon {
  width: 1.5rem;
  height: 1.5rem;
}

.cart-toggle__count {
  position: absolute;
  top: -0.2rem;
  right: -0.35rem;
  min-width: 1.2rem;
  height: 1.2rem;
  padding: 0 0.3rem;
  border-radius: 999px;
  background: var(--color-primary);
  color: #fff;
  font-family: var(--font-ui);
  font-size: 0.68rem;
  font-weight: 700;
  line-height: 1.2rem;
  text-align: center;
}

/* ── Панель корзины: оверлей + выезжающий drawer справа. Без стекла —
   glass зарезервирован под шапку и hero__panel (см. переменные темы выше),
   у drawer сплошной фон, чтобы список позиций читался поверх любого фото. ── */
.cart-panel[hidden] {
  display: none;
}

.cart-panel {
  position: fixed;
  inset: 0;
  z-index: 40;
}

.cart-panel__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(26, 26, 26, 0.45);
}

.cart-panel__drawer {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  max-width: 420px;
  background: var(--color-bg);
  box-shadow: -8px 0 32px rgba(0, 0, 0, 0.18);
  display: flex;
  flex-direction: column;
  padding: 1.5rem;
  padding-top: calc(1.5rem + env(safe-area-inset-top));
  padding-bottom: calc(1.5rem + env(safe-area-inset-bottom));
  overflow-y: auto;
}

.cart-panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.25rem;
}

.cart-panel__title {
  font-family: var(--font-main);
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--color-text);
}

.cart-panel__close {
  border: none;
  background: transparent;
  font-size: 1.7rem;
  line-height: 1;
  color: var(--color-text-muted);
  cursor: pointer;
  padding: 0.25rem;
}

.cart-panel__close:hover {
  color: var(--color-text);
}

.cart-panel__items {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  flex: 1;
}

.cart-panel__empty {
  color: var(--color-text-muted);
  text-align: center;
  padding: 2rem 0;
}

.cart-panel__foot {
  border-top: 1px solid var(--color-border);
  margin-top: 1rem;
  padding-top: 1rem;
}

.cart-panel__total {
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--color-text);
  margin-bottom: 0.75rem;
}

.cart-panel__checkout {
  width: 100%;
}

.cart-panel__checkout:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ── Позиция в корзине. Две строки: фото+название/цена+удаление сверху,
   qty-степпер отдельной строкой на всю ширину снизу — так крупное фото
   (это цветочный магазин, фото букета и есть товар) не отжимает qty
   в узкую колонку и кнопки +/- остаются некликабельно-мелкими. ── */
.cart-item {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.cart-item--unavailable {
  border: 1.5px solid #c0392b;
  border-radius: var(--radius);
  padding: 0.75rem;
  margin: -0.75rem;
}

.cart-item__top {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
}

.cart-item__media {
  flex: 0 0 144px;
}

.cart-item__img,
.cart-item__img-placeholder {
  display: block;
  width: 144px;
  /* Тот же аспект-рейшо, что у .product-card__media в каталоге —
     вертикальный 3:4. Раньше здесь оставался устаревший 6:5 от более
     старого формата карточки (см. коммит 21eef11), который так и не
     обновили вместе с ней */
  aspect-ratio: 3 / 4;
  border-radius: var(--radius);
  object-fit: cover;
  background: var(--color-bg-alt);
}

.cart-item__info {
  flex: 1;
  min-width: 0;
}

.cart-item__name {
  font-family: var(--font-main);
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--color-text);
  line-height: 1.3;
}

.cart-item__price {
  font-size: 0.9rem;
  color: var(--color-text-muted);
  margin-top: 0.3rem;
}

.cart-item__error {
  color: #c0392b;
  font-size: 0.82rem;
  margin-top: 0.5rem;
}

.cart-item__remove {
  flex: 0 0 auto;
  border: none;
  background: transparent;
  color: var(--color-text-muted);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.25rem;
}

.cart-item__remove:hover {
  color: #c0392b;
}

.cart-item__qty {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.cart-item__qty-btn {
  width: 1.75rem;
  height: 1.75rem;
  border: 1px solid var(--color-border);
  border-radius: 50%;
  background: var(--color-bg);
  color: var(--color-text);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}

.cart-item__qty-btn:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.cart-item__qty-value {
  min-width: 1.4rem;
  text-align: center;
  font-weight: 600;
  font-size: 0.9rem;
}

.no-scroll {
  overflow: hidden;
}

@media (min-width: 640px) {
  .cart-panel__drawer {
    width: 380px;
  }

  .cart-item__media,
  .cart-item__img,
  .cart-item__img-placeholder {
    flex-basis: 168px;
    width: 168px;
  }
}

/* ── Hero: фото букета на весь экран, дизайн — только обрамление ── */
.hero {
  /* Контейнер позиционирования для .hero__panel (сиблинга .hero__media, не потомка) —
     без этого panel «отвязана» от фото: абсолютное позиционирование падает на initial
     containing block, а не на секцию, и совпадает с нужным местом только случайно,
     когда scrollY=0 и высота вьюпорта совпадает с высотой фото */
  position: relative;
  /* Исключение из ритма секций: hero занимает вьюпорт целиком, фото —
     полноэкранное, вертикальный паддинг секции ему противопоказан */
  padding: 0;
}

.hero__media {
  position: relative;
  width: 100%;
  /* svh (гарантированно видимая часть, панель инструментов Safari развёрнута) —
     не dvh: хук/цена/CTA обязаны быть видны без скролла и без ожидания схлопывания chrome.
     Минус высота шапки — сама шапка в потоке документа перед hero, а не поверх него */
  height: calc(100vh - var(--header-h));
  height: calc(100svh - var(--header-h));
  min-height: 420px;
  overflow: hidden;
}

.hero__img,
.hero__img-placeholder {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hero__img-placeholder {
  background: var(--color-border);
}

/* Панель хука/цены/CTA — стекло (2 из 2 мест, где оно допустимо) */
.hero__panel {
  position: absolute;
  left: 1rem;
  right: 1rem;
  bottom: calc(1.25rem + env(safe-area-inset-bottom));
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-glass);
  padding: 1.5rem;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
  text-align: center;
}

.hero__hook {
  font-family: var(--font-main);
  font-size: clamp(2.5rem, 9vw, 3rem);
  font-weight: 700;
  line-height: 1.1;
  margin-bottom: 0.6rem;
  color: var(--color-text);
}

.hero__price {
  font-family: var(--font-ui);
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--color-primary);
  margin-bottom: 1.1rem;
}

.hero__subtitle {
  font-size: 1.15rem;
  color: var(--color-text-muted);
  max-width: 520px;
  margin: 0 auto 2.5rem;
}

.hero__cta {
  display: flex;
  width: 100%;
  font-size: 1.05rem;
  padding: 0.9rem 2rem;
}

/* ── Полоса доверия ── */
/* Исключение из ритма секций: не самостоятельная секция, а тонкая лента,
   визуально приклеенная к hero. Линию на границе рисует общее правило
   main > section + section, своя border-bottom дала бы двойную */
.trust-strip {
  padding: 1.1rem 0;
}

.trust-strip__list {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem 1.75rem;
}

.trust-strip__item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--color-text);
  text-align: left;
}

.trust-strip__item::before {
  content: '✓';
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 1.3rem;
  height: 1.3rem;
  border-radius: 50%;
  background: var(--color-primary);
  color: #fff;
  font-size: 0.7rem;
}

/* ── Микродвижение при скролле (IntersectionObserver, public/js/reveal.js) ── */
/* Только opacity, без translateY: transform на элементе (даже в обычном block-flow,
   не только в grid) расширяет scrollable-область родителя в WebKit на величину
   сдвига — второй раз ловим этот же ложный overflow (сначала на .product-card
   в гриде, теперь на секциях внутри main), поэтому убираем transform из reveal
   насовсем, а не точечно на очередном элементе */
.reveal {
  opacity: 0;
  transition: opacity 0.3s ease;
}

.reveal--visible {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transition: none;
  }
}

.section-title {
  font-family: var(--font-main);
  font-size: clamp(1.5rem, 3vw, 2.2rem);
  font-weight: 600;
  margin-bottom: 1.25rem;
  color: var(--color-text);
}

/* ── Как это работает ── */
.how-it-works__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  margin-top: 2rem;
  text-align: center;
}

.how-it-works__icon {
  position: relative;
  width: 3.5rem;
  height: 3.5rem;
  margin: 0 auto 1rem;
  border-radius: 50%;
  background: rgba(30, 77, 59, 0.12);
  color: var(--color-primary);
  display: flex;
  align-items: center;
  justify-content: center;
}

.how-it-works__icon > svg {
  width: 1.9rem;
  height: 1.9rem;
}

.how-it-works__badge {
  /* right/bottom:0, без выступа за край кружка — отрицательный offset
     или transform засчитываются WebKit как переполнение контейнера
     (check-visual.js), даже когда это декоративный бейдж, а не баг */
  position: absolute;
  right: 0.1rem;
  bottom: 0.1rem;
  width: 1.3rem;
  height: 1.3rem;
  border-radius: 50%;
  background: var(--color-primary);
  border: 2.5px solid var(--color-bg);
  display: flex;
  align-items: center;
  justify-content: center;
}

.how-it-works__badge svg {
  width: 0.7rem;
  height: 0.7rem;
}

.how-it-works__num {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--color-text-muted);
  margin-bottom: 0.35rem;
}

.how-it-works__title {
  font-family: var(--font-main);
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--color-text);
}

/* Гарантии магазина — второй смысловой блок той же секции. Список, а не
   сетка карточек: пунктов может быть сколько угодно и они разной длины,
   сетка на длинных формулировках («Заменим букет, если получателю не
   понравился») давала бы рваные по высоте ячейки */
.how-it-works__guarantees {
  list-style: none;
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.85rem 2rem;
  margin-top: 2rem;
  padding-top: 2rem;
  border-top: 1px solid var(--color-border);
}

.how-it-works__guarantee {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  font-size: 0.95rem;
  color: var(--color-text);
  /* min-width:0 — иначе длинный пункт без пробелов распирает колонку
     грида шире контейнера (тот же класс бага, что ловили на .site-logo) */
  min-width: 0;
}

.how-it-works__guarantee-icon {
  flex-shrink: 0;
  width: 1.35rem;
  height: 1.35rem;
  color: var(--color-primary);
  /* Оптическое выравнивание с первой строкой текста (line-height 1.6) */
  margin-top: 0.15rem;
}

/* display:block обязателен: svg по умолчанию inline-level, встаёт на
   базовую линию текста и добавляет под собой место под нижние выносные —
   контейнер иконки становится выше своей заданной высоты, и check-visual
   справедливо считает это переполнением */
.how-it-works__guarantee-icon svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* ── Отзывы: виджет Яндекса ──
   Размер задаёт обёртка, а не атрибуты width/height у iframe: жёсткая
   ширина в атрибуте распирает страницу на мобильном горизонтальным
   скроллом.

   Габариты — из документации виджета (сверено 2026-08-01): рабочая
   ширина 300–760px, высота от 500px. Поэтому max-width, а не вся ширина
   контейнера (1100px) — за 760px виджет добавляет серые поля по бокам, —
   и фиксированная высота, а не aspect-ratio: на широком экране пропорция
   дала бы низкий виджет, в котором не помещается ни одного отзыва. */
.reviews__widget {
  margin: 2rem auto 0;
  width: 100%;
  max-width: 560px;
  height: 560px;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--color-border);
}

.reviews__widget iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

@media (min-width: 768px) {
  .reviews__widget {
    height: 640px;
  }
}

/* ── Контакты: единая система pill-кнопок, важность — только filled/outline ── */
/* Grid вместо flex-wrap: ширина кнопки в ряду определяется колонкой
   сетки, а не длиной текста внутри неё — иначе короткие кнопки («VK»)
   вставали по две в ряд, а длинные (телефон) — всегда на всю ширину,
   и ряды выглядели по-разному на одной и той же ширине экрана.
   340px — фактическая ширина самой длинной кнопки (телефон с полным
   номером), измерено на реальной странице: колонка не может стать уже
   и обрезать её при обычных обстоятельствах; на случай нетипично
   длинного номера/email при stamping — text-overflow ниже как страховка. */
.contacts__hub {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 0.75rem;
  margin-top: 2rem;
}

.contacts__hub .btn span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.btn--outline {
  background: transparent;
  color: var(--color-primary);
  border: 1.5px solid var(--color-primary);
}

.btn--outline:hover {
  background: var(--color-bg-alt);
}

.contacts__icon {
  width: 1.15rem;
  height: 1.15rem;
  flex-shrink: 0;
}

.contacts__meta {
  margin-top: 2rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--color-border);
  color: var(--color-text-muted);
  font-size: 0.9rem;
}

/* ── Успеть сегодня ── */
.urgent__subtitle {
  color: var(--color-text-muted);
  margin-top: -0.75rem;
  margin-bottom: 0;
}

.urgent .catalog__grid {
  margin-top: 1.5rem;
}

/* ── Каталог товаров ── */
.catalog-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1.5rem;
}

.catalog-tabs__tab {
  font-family: var(--font-ui);
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--color-text-muted);
  background: var(--color-bg-alt);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 0.45rem 1rem;
  cursor: pointer;
  transition:
    background 0.2s,
    color 0.2s,
    border-color 0.2s;
}

.catalog-tabs__tab:hover {
  border-color: var(--color-primary);
  color: var(--color-primary-dark);
}

.catalog-tabs__tab.is-active {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: #fff;
}

.catalog__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.75rem;
  margin-top: 2rem;
}

.category-page__empty {
  margin-top: 2rem;
  color: var(--color-text-muted);
}

.product-card.is-hidden {
  display: none;
}

.product-card {
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  overflow: hidden;
  transition:
    box-shadow 0.2s,
    transform 0.15s;
}

.product-card:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}

.product-card:active {
  transform: scale(0.98);
}

.product-card__media {
  position: relative;
  /* Вертикальный формат 3:4 — отраслевой стандарт для карточек товара,
     букеты преимущественно вертикальные */
  aspect-ratio: 3 / 4;
  overflow: hidden;
}

.product-card__media-link {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: block;
}

.product-card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  background: var(--color-bg-alt);
}

.product-card__img-placeholder {
  width: 100%;
  height: 100%;
  background: var(--color-bg-alt);
}

.product-card__badge {
  position: absolute;
  top: 0.5rem;
  left: 0.5rem;
  background: var(--color-primary);
  color: #fff;
  font-family: var(--font-ui);
  font-size: 0.68rem;
  font-weight: 600;
  padding: 0.3rem 0.6rem;
  border-radius: 999px;
  line-height: 1;
}

.product-card__body {
  padding: 0.5rem 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.product-card__name {
  font-family: var(--font-main);
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--color-text);
  line-height: 1.25;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.product-card__name a {
  color: inherit;
  text-decoration: none;
}

.product-card__price {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--color-primary-dark);
  line-height: 1.2;
}

.product-card__price--old {
  text-decoration: line-through;
  color: var(--color-text-muted);
  font-weight: 400;
  font-size: 0.85em;
}

.product-card__price--discount {
  color: var(--color-primary);
}

.product-card__cta {
  position: absolute;
  right: 0.5rem;
  bottom: 0.5rem;
  width: 2.75rem;
  height: 2.75rem;
  border: none;
  border-radius: 50%;
  background: var(--color-primary);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
  transition: background 0.2s;
}

.product-card__cta:hover {
  background: var(--color-primary-dark);
}

.product-card__cta:active {
  transform: scale(0.92);
}

/* ── Форма заявки ── */
.order__selected {
  font-weight: 600;
  color: var(--color-primary-dark);
  min-height: 1.4em;
}

.order-form {
  max-width: 520px;
  margin-top: 1rem;
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.order-form__hint {
  font-size: 0.85rem;
  color: var(--color-text-muted);
  margin-top: -0.75rem;
}

.order-form__checkbox {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  font-size: 0.9rem;
  color: var(--color-text);
  cursor: pointer;
}

.order-form__checkbox input {
  margin-top: 0.2rem;
  accent-color: var(--color-primary);
  width: 1.05rem;
  height: 1.05rem;
}

.order-form__policy-link {
  font-size: 0.85rem;
}

/* Способ оплаты — fieldset внутри формы заказа. Селекторы с двумя
   классами: правило .order-form__field label (font-weight 600) иначе
   перебивает по специфичности — подписи радиокнопок стали бы жирными */
.order-form__payment {
  border: 1px solid var(--color-border);
  border-radius: 8px;
  padding: 0.9rem 1rem;
  gap: 0.55rem;
}

.order-form__payment legend {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-text);
  padding: 0 0.35rem;
}

.order-form__payment .order-form__radio {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.9rem;
  font-weight: 400;
  cursor: pointer;
}

.order-form__payment .order-form__radio input {
  accent-color: var(--color-primary);
  width: 1.05rem;
  height: 1.05rem;
  flex-shrink: 0;
}

.order-form__payment .order-form__hint,
.order-form__payment .order-form__policy-link {
  margin: 0.15rem 0 0;
}

/* Подсказка внутри поля (например, «на этот адрес придёт чек») стоит
   сразу под input и не должна тянуться отрицательным margin вверх —
   он задан у .order-form__hint для подсказок МЕЖДУ полями */
.order-form__field .order-form__hint {
  margin-top: 0;
}

/* Сумма к списанию — крупнее подсказок рядом: это то, ради чего
   покупатель читает этот блок */
.order-form__total:empty {
  display: none;
}

.order-form__total {
  margin: 0.35rem 0 0;
  font-size: 1rem;
  font-weight: 600;
  color: var(--color-text);
}

.order-form__field {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.order-form__field label {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-text);
}

.order-form__field input,
.order-form__field textarea,
.order-form__field select {
  padding: 0.8rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  font-size: 1rem;
  font-family: inherit;
  background: var(--color-bg);
  color: var(--color-text);
  transition:
    border-color 0.15s,
    box-shadow 0.15s;
  width: 100%;
}

.order-form__field input:focus,
.order-form__field textarea:focus,
.order-form__field select:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(30, 77, 59, 0.15);
}

.order-form__input--error {
  border-color: #c0392b !important;
}

.order-form__error {
  font-size: 0.82rem;
  color: #c0392b;
  min-height: 1em;
}

/* Напоминание про гарантию перед кнопкой отправки (та же иконка, что
   у .how-it-works__guarantee-icon — визуальная связка с полной секцией
   гарантий) */
.order-form__guarantee {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  font-size: 0.85rem;
  color: var(--color-text);
  margin: 0;
}

.order-form__guarantee-icon {
  flex-shrink: 0;
  width: 1.1rem;
  height: 1.1rem;
  color: var(--color-primary);
  margin-top: 0.1rem;
}

.order-form__guarantee-icon svg {
  display: block;
  width: 100%;
  height: 100%;
}

.order-form__submit {
  align-self: flex-start;
}

.order-form__status {
  font-size: 0.95rem;
  min-height: 1.4em;
}

.order-form__status--ok {
  color: #27ae60;
}
.order-form__status--err {
  color: #c0392b;
}

/* ── Юридические страницы (политика, оферта) ── */
.legal {
  padding: 3rem 0 4rem;
}

.legal__content {
  max-width: 720px;
}

.legal__content h1 {
  font-family: var(--font-main);
  font-size: clamp(1.6rem, 3.5vw, 2.2rem);
  font-weight: 600;
  margin-bottom: 1.5rem;
  color: var(--color-text);
}

.legal__content h2 {
  font-size: 1.15rem;
  margin: 1.75rem 0 0.75rem;
  color: var(--color-text);
}

.legal__content p {
  color: var(--color-text-muted);
  line-height: 1.75;
  margin-bottom: 0.5rem;
}

/* ── Footer ── */
.site-footer {
  padding: 2rem 0;
  border-top: 1px solid var(--color-border);
  text-align: center;
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

/* Строка авторства (src/footer-credit-config.js) — заметно мельче и
   тише остального подвала: не должна спорить вниманием с контактами
   магазина и ссылками на политику/оферту над ней */
.footer-credit {
  margin-top: 0.5rem;
  font-size: 0.75rem;
  opacity: 0.7;
}

.footer-credit a {
  color: inherit;
}

/* ── Адаптив: tablet+ ── */
@media (min-width: 640px) {
  .how-it-works__grid {
    grid-template-columns: repeat(3, 1fr);
  }

  .how-it-works__guarantees {
    grid-template-columns: repeat(2, 1fr);
  }

  .catalog__grid {
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 1.5rem;
  }

  .product-card__body {
    padding: 0.75rem 1rem;
  }

  .product-card__name {
    font-size: 1.1rem;
  }

  .product-card__price {
    font-size: 1.1rem;
  }
}

@media (min-width: 900px) {
  /* Фото остаётся героем на весь экран и на десктопе — панель прижата слева, не растягивается на всю ширину */
  .hero__panel {
    left: 3rem;
    right: auto;
    bottom: 3rem;
    max-width: 420px;
    text-align: left;
    padding: 2rem;
  }

  .hero__cta {
    width: auto;
    padding: 0.9rem 2.75rem;
  }

  .hero__subtitle {
    margin: 0 0 2.5rem;
  }
}

.not-found {
  padding: 4rem 0;
  text-align: center;
}

.not-found__text {
  color: var(--color-text-muted);
  margin: 1rem 0 2rem;
}

/* ── Страница возврата с платёжной формы ── */
.payment-result {
  padding: 4rem 0;
  text-align: center;
}

.payment-result__text {
  color: var(--color-text-muted);
  margin: 1rem auto 2rem;
  max-width: 32rem;
}

/* ── Хлебные крошки ── */
.breadcrumbs {
  margin: 1.5rem 0 1rem;
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

.breadcrumbs__list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  list-style: none;
}

.breadcrumbs__item:not(:last-child)::after {
  content: '/';
  margin-left: 0.35rem;
  color: var(--color-border);
}

.breadcrumbs__item a {
  color: var(--color-text-muted);
  text-decoration: none;
}

.breadcrumbs__item a:hover {
  text-decoration: underline;
}

.breadcrumbs__item[aria-current='page'] {
  color: var(--color-text);
  font-weight: 500;
}

/* ── Страница товара ── */
.product-page__layout {
  display: grid;
  gap: 2rem;
  margin: 1.5rem 0 3rem;
}

@media (min-width: 768px) {
  .product-page__layout {
    grid-template-columns: minmax(280px, 420px) 1fr;
    align-items: start;
  }
}

.product-page__media {
  position: relative;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  border: none;
  border-radius: var(--radius);
  padding: 0;
  width: 100%;
  display: block;
  cursor: zoom-in;
  background: var(--color-bg-alt);
}

.product-page__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.product-page__img-placeholder {
  width: 100%;
  height: 100%;
  background: var(--color-bg-alt);
}

.product-page__badge {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  background: var(--color-primary);
  color: #fff;
  font-family: var(--font-ui);
  font-size: 0.75rem;
  font-weight: 600;
  padding: 0.35rem 0.75rem;
  border-radius: 999px;
  line-height: 1;
}

.product-page__name {
  font-family: var(--font-main);
  font-size: 1.8rem;
  margin: 0 0 0.5rem;
}

.product-page__price {
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--color-primary-dark);
  margin-bottom: 0.5rem;
}

.product-page__price--old {
  text-decoration: line-through;
  color: var(--color-text-muted);
  font-weight: 400;
  font-size: 0.85em;
}

.product-page__price--discount {
  color: var(--color-primary);
}

.product-page__category {
  color: var(--color-text-muted);
  font-size: 0.9rem;
  margin-bottom: 1rem;
}

.product-page__unavailable {
  color: #b3261e;
  font-weight: 600;
  margin-bottom: 1rem;
}

.product-page__description {
  white-space: pre-line;
  line-height: 1.7;
  margin-bottom: 1.5rem;
}

.product-page__cta {
  width: 100%;
  max-width: 320px;
}

.product-page__cta:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ── Галерея из нескольких фото товара (public/js/product-gallery.js) ──
   Рендерится только когда фото больше одного (src/templates/product.js) */
.product-gallery {
  position: relative;
}

.product-gallery .product-page__media {
  padding: 0;
  cursor: zoom-in;
}

.product-gallery__track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  width: 100%;
  height: 100%;
}

.product-gallery__track::-webkit-scrollbar {
  display: none;
}

.product-gallery__slide {
  flex: 0 0 100%;
  scroll-snap-align: start;
  width: 100%;
  height: 100%;
}

.product-gallery__slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}

.product-gallery__counter {
  position: absolute;
  bottom: 0.75rem;
  right: 0.75rem;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  font-family: var(--font-ui);
  font-size: 0.75rem;
  font-weight: 600;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  pointer-events: none;
}

.product-gallery__thumbs {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.75rem;
  overflow-x: auto;
}

.product-gallery__thumb {
  flex: 0 0 3.5rem;
  width: 3.5rem;
  height: 3.5rem;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 6px;
  overflow: hidden;
  cursor: pointer;
  background: none;
}

.product-gallery__thumb[aria-current='true'] {
  border-color: var(--color-primary);
}

.product-gallery__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ── Лайтбокс фото товара ── */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
}

.lightbox[hidden] {
  display: none;
}

.lightbox__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.85);
}

.lightbox__figure {
  position: relative;
  z-index: 1;
  max-width: min(92vw, 900px);
  max-height: 92vh;
}

.lightbox__img {
  display: block;
  max-width: 100%;
  max-height: 92vh;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: var(--radius);
}

.lightbox__close {
  position: absolute;
  top: -2.5rem;
  right: 0;
  width: 2.5rem;
  height: 2.5rem;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.9);
  color: #1a1a1a;
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
}

/* Cookie-баннер — простое одноразовое уведомление, не блокирует
   использование сайта (не модальный оверлей) */
.cookie-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1000;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 1.5rem;
  background: var(--color-text);
  color: #fff;
  box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.2);
}

.cookie-banner__text {
  margin: 0;
  font-size: 0.9rem;
  flex: 1 1 260px;
}

.cookie-banner__text a {
  color: #fff;
  text-decoration: underline;
}

.cookie-banner__btn {
  flex: 0 0 auto;
  white-space: nowrap;
}

@media (max-width: 480px) {
  .cookie-banner {
    flex-direction: column;
    align-items: stretch;
    text-align: center;
  }
}
