
/* Сетка-"линейка" с теми же пропорциями колонок, что и .product-hero
   (19.07.2026: 1.4fr / 0.6fr, было 1.1fr / 0.9fr — см. коммент у .product-hero
   ниже, откуда взялось именно это число) — используется, чтобы жёстко
   привязать ширину/x-координату других блоков к границам колонок галереи и
   product-info, не гадая с px-значениями. Строка breadcrumbs + "Last updated"
   встаёт по этим же границам, а весь блок табов занимает ровно первую
   колонку (= ширина большого превью). */
.hero-align-row {
  display: grid;
  grid-template-columns: 1.4fr 0.6fr;
  gap: var(--space-6);
  align-items: baseline;
  margin-bottom: var(--space-5);
}
.hero-align-row .breadcrumbs { margin-bottom: 0; }

.last-updated-inline {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--fs-small);
  color: var(--color-text-secondary);
}
.last-updated-inline svg { color: var(--color-primary); flex-shrink: 0; }
.last-updated-inline strong { color: var(--color-text-primary); }

.tabs-col { grid-column: 1; }

/* ---------- Gallery + product info (top) ---------- */
/* Пропорция колонок 1.4fr/0.6fr (19.07.2026, эксперимент — было 1.1fr/0.9fr)
   — пересчитана так, чтобы после уменьшения миниатюр (180x120 -> 120x80,
   ÷1.5) главное превью выросло РОВНО в 1.5 раза, а не просто "стало чуть
   шире из-за освободившегося места от миниатюр". Расчёт при
   --container-max:1400px (.page padding var(--space-4) с обеих сторон,
   .page-body padding var(--space-7)): полезная ширина .hero-align-row/
   .product-hero = 1400 - 32*2 - 48*2 = 1240px. При старом 1.1fr/0.9fr левая
   колонка = 1240*1.1/2 = 682px, из них главное превью = 682 - 180(миниатюра)
   - 12(gap) = 490px. Цель: 490*1.5 = 735px. Новая левая колонка = 120(новая
   миниатюра) + 12(gap) + 735 = 867px -> в fr (сумма как и раньше = 2):
   867/1240*2 ≈ 1.4fr, остаток (1240-867)/1240*2 ≈ 0.6fr — правая колонка
   сузилась с 558px до ~373px соразмерно. */
.product-hero {
  display: grid;
  grid-template-columns: 1.4fr 0.6fr;
  gap: var(--space-6);
  margin-bottom: var(--space-6);
  /* align-items: start (17.07.2026, "поправить отступы на freebies продуктах") —
     на Freebie-страницах правая колонка (.email-gate: hero+форма+3 шага+
     trust-bar) почти всегда заметно выше .gallery слева. Дефолтный
     align-items:stretch растягивал .gallery на высоту правой колонки, а
     сама .gallery — просто блок фиксированной высоты (aspect-ratio превью +
     полоска миниатюр), поэтому стретч не добавлял ей контента — просто
     оставлял пустое место в НИЗУ её же бокса, перед табами. align-items:start
     убирает этот стретч: обе колонки занимают только свою естественную
     высоту, разница между ними — обычный визуальный перепад (как и на
     референсе), а не пустой отступ внутри .gallery. */
  align-items: start;
}

/* Freebie-страницы (17.07.2026, "табы поднять именно на страницах freebies"):
   первая попытка (margin-bottom на .product-hero) не сработала — с
   align-items:start высота ГРИД-РЯДА всё равно равна высоте более высокой
   колонки (.email-gate: форма+3 шага+trust-bar), а тонкая .tabs-col висела в
   отдельном .hero-align-row ПОСЛЕ этого ряда — то есть визуальный отступ
   определялся разницей высот колонок, а не margin. Реальный фикс — в
   single-freebie.php: .gallery и .tabs-col теперь вложены в общий
   .hero-col-left (обычный блочный поток), который не зависит от высоты
   .product-info/.email-gate справа — табы начинаются сразу под галереей.
   single-product.php НЕ трогаем — там своя структура (.hero-align-row). */
.hero-col-left { min-width: 0; }
.hero-col-left .tabs-col { margin-top: var(--space-4); }

/* Grid по умолчанию растягивает обе колонки на одинаковую высоту —
   .product-info делаем flex-колонкой, чтобы прижать "What's Included"
   к самому низу (margin-top:auto), ровно туда, где заканчиваются
   миниатюры галереи слева — а не оставлять там пустоту. */
.product-info { display: flex; flex-direction: column; }

/* 16.07.2026: у грид-элементов по умолчанию min-width:auto — это значит,
   что колонка не может стать УЖЕ, чем её самый широкий "неразрывный"
   контент (тогда это была горизонтальная полоска превью в один flex-ряд;
   с 19.07.2026 миниатюры — фиксированная вертикальная колонка 120px, но
   правило всё ещё нужно: .gallery-main внутри — тоже flex-элемент, и без
   min-width:0 не может ужаться меньше своего контента). Без этой строчки
   колонка .gallery раздувалась под реальную ширину контента вместо заданных
   fr-пропорций грида, а не обрезалась через overflow:hidden — проблема была
   именно в размере КОЛОНКИ, а не в клипинге. Из-за раздутой колонки съезжала
   и правая колонка .product-info. */
/* Сетка галереи (19.07.2026, эксперимент — стандартизация под Creative
   Market, затем скорректирована по прямому запросу: главное превью
   увеличено в 1.5 раза, миниатюры уменьшены в 1.5 раза, обе пропорции 3:2
   сохранены — см. расчёт у .product-hero выше). Колонка миниатюр СЛЕВА от
   главного превью, а не полоской под ним — раньше было flex-column (главное
   превью сверху, полоска миниатюр под ним, горизонтальный скролл при >5
   штук), теперь flex-row, полоска миниатюр стала вертикальной колонкой
   слева (см. .gallery-thumbs-viewport/.gallery-thumb ниже и
   product-gallery.js — логика скролла при наведении на крайнюю миниатюру
   осталась той же, просто ось X -> Y). */
.gallery { min-width: 0; display: flex; gap: var(--space-3); align-items: flex-start; }

/* Точки-индикаторы под большой картинкой (03.08.2026). Разметку собирает
   product-gallery.js — см. подробный комментарий там. На десктопе не нужны:
   там есть и колонка миниатюр, и стрелки по наведению. */
.gallery-dots { display: none; }

.gallery-main {
  position: relative;
  aspect-ratio: 3 / 2;
  flex: 1 1 auto;
  min-width: 0;
  background: #DADCE0;
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #B3B6BB;
  overflow: hidden;
}
/* Кросс-фейд между кадрами (16.07.2026): вместо мгновенной замены src —
   два слоя друг над другом, у уходящего кадра opacity плавно падает,
   у входящего — плавно растёт, одновременно (не "погасло-зажглось",
   а настоящее перекрёстное растворение). Слои создаёт/удаляет JS
   (product-gallery.js), тут только сама механика прозрачности. */
.gallery-main-stage { position: absolute; inset: 0; }
.gallery-main-img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity .35s ease;
}
.gallery-main-img.is-active { opacity: 1; }
.gallery-zoom {
  position: absolute;
  top: var(--space-3);
  left: var(--space-3);
  width: 36px; height: 36px;
  border-radius: 50%;
  background: #fff;
  box-shadow: var(--shadow-2);
  display: flex; align-items: center; justify-content: center;
  color: var(--color-text-primary);
}
/* Стрелки листания большой картинки (16.07.2026) — видны только при
   наведении на .gallery-main, как просил Alex. Логика листания в
   assets/js/product-gallery.js. */
.gallery-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 36px; height: 36px;
  border-radius: 50%;
  background: #fff;
  box-shadow: var(--shadow-2);
  border: none;
  display: flex; align-items: center; justify-content: center;
  font-size: 20px;
  line-height: 1;
  color: var(--color-text-primary);
  cursor: pointer;
  opacity: 0;
  transition: opacity .15s ease, background-color .15s ease, color .15s ease;
  z-index: 2;
}
.gallery-arrow--prev { left: var(--space-3); }
.gallery-arrow--next { right: var(--space-3); }
.gallery-main:hover .gallery-arrow { opacity: 1; }
.gallery-arrow:hover { background: var(--color-tint-peach); color: var(--color-accent-amber); }

/* Колонка миниатюр (19.07.2026, эксперимент — см. коммент у .gallery выше) —
   viewport обрезает лишнее по ВЫСОТЕ (max-height ровно на 5 миниатюр + 4
   зазора), track держит ВСЕ миниатюры друг под другом (выше viewport, если
   их больше 5), сдвиг track по вертикали считает product-gallery.js (тот же
   приём, что и раньше для горизонтальной полоски, просто translateY вместо
   translateX).
   Размер миниатюры (19.07.2026, эксперимент №2, по прямому запросу): было
   180×120 (стандарт Creative Market из первого ТЗ), теперь ÷1.5 = 120×80 —
   см. расчёт у .product-hero выше (это уменьшение и освободило место для
   увеличения главного превью в те же 1.5 раза). Пропорция 3:2 сохранена.
   Размер по-прежнему ФИКСИРОВАН, JS не подгоняет его под контейнер. */
.gallery-thumbs-viewport {
  flex: 0 0 120px;
  width: 120px;
  max-height: calc( 80px * 5 + var(--space-2) * 4 );
  overflow: hidden;
}
.gallery-thumbs-track { display: flex; flex-direction: column; gap: var(--space-2); }
.gallery-thumb {
  all: unset;
  box-sizing: border-box;
  flex: 0 0 auto;
  width: 120px;
  height: 80px;
  aspect-ratio: 3 / 2;
  border-radius: var(--radius-sm);
  background: #DADCE0;
  display: flex; align-items: center; justify-content: center;
  color: #B3B6BB;
  border: 2px solid transparent;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.gallery-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gallery-thumb.is-active { border-color: var(--color-primary); }
/* Hover — фирменный оранжевый (19.07.2026, по прямому запросу), 2px рамка
   (border уже 2px по умолчанию, просто был прозрачным). :not(.is-active),
   чтобы наведение на УЖЕ активную миниатюру не перебивало её зелёный
   индикатор оранжевым — это два разных состояния (выбрано / под курсором),
   не должны визуально путаться. */
.gallery-thumb:not(.is-active):hover { border-color: var(--color-accent-amber); }
/* Тот же белёсый hover (5% непрозрачности белого), что и на .card__image
   (02-cards.css) и превью статей (04-home.css) — консистентно по сайту. */
.gallery-thumb::after {
  content: '';
  position: absolute;
  inset: 0;
  background: #fff;
  opacity: 0;
  transition: opacity .15s ease;
  pointer-events: none;
}
.gallery-thumb:hover::after { opacity: .05; }

.product-title {
  font-family: var(--font-heading);
  font-size: 30px;
  line-height: 1.25;
  font-weight: 700;
  margin: 0 0 var(--space-4);
}
.product-meta-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
  font-size: var(--fs-small);
  color: var(--color-text-secondary);
}
.product-meta-row .rating__stars { color: var(--color-gold); font-size: 16px; }
.meta-sep { color: var(--color-border); }
/* Ссылка "(N reviews)" рядом со звёздами (18.07.2026) — серая с подчёркиванием
   в покое (выглядит как обычный текст, но кликабельна), фирменный оранжевый
   hover, как у остальных ссылок сайта. Клик — переключает таб Reviews и
   скроллит к нему (site.js, модуль 3 "Tabs"). */
.reviews-count-link { color: var(--color-text-secondary); text-decoration: underline; cursor: pointer; }
.reviews-count-link:hover { color: var(--color-accent-amber); }
.sales-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--color-tint-peach);
  color: #B36B00;
  padding: 5px 12px;
  border-radius: var(--radius-sm);
  font-weight: 700;
  font-size: var(--fs-caption);
}
.sales-badge svg { flex-shrink: 0; }

.price-block { margin: 0 0 var(--space-5); }
.price-block .price { font-family: var(--font-heading); font-size: 36px; font-weight: 700; }

.price-cta-row { display: flex; flex-direction: column; gap: var(--space-3); margin-bottom: var(--space-6); }
.price-cta-row .btn-primary { width: 100%; justify-content: center; }
.price-cta-row .cta-secondary-row { display: flex; gap: var(--space-3); align-items: flex-start; }
.price-cta-row .cta-secondary-row .btn-secondary { flex: 1; justify-content: center; }

/* Wishlist-кнопка на Product Detail — активное состояние (товар уже в
   списке): та же логика/цвет, что и звёздочка на карточке (.card__wishlist-btn.is-active). 16.07.2026. */
.price-cta-row .cta-secondary-row .btn-secondary[data-wishlist-toggle].is-active {
  border-color: var(--color-gold);
  color: var(--color-gold);
}

/* ---------- Notify signup ("Discount Notified" — 16.07.2026, уведомление о скидке) ----------
   Кнопка-триггер [data-notify-trigger] живёт в .cta-secondary-row (ряд с
   Wishlist, обычная .btn-secondary flex:1 — правило выше уже её покрывает).
   Сама форма (.notify-cta) — ОТДЕЛЬНЫЙ блок на всю ширину .price-cta-row,
   разворачивается ПОД рядом кнопок, а не зажата в половину колонки (16.07.2026,
   правка по скрину — раньше форма была там же, в половине ширины, и выглядела
   сломанной). Поле + квадратная кнопка со стрелкой — единый "pill" через
   общую рамку на .notify-cta__field, не на инпуте отдельно. */
/* [hidden] + display:flex/inline-flex авторским правилом (19.07.2026, найдено
   при проверке нового .email-gate__cta — тот же баг молча жил ещё в 3
   местах): .btn задаёт display:inline-flex, .email-gate__form/.review-form/
   .email-gate__subscribed-hint — display:flex, обычное авторское правило
   побеждает UA-правило [hidden]{display:none} при равной специфичности
   (0,1,0) — элемент оставался виден, даже когда JS уже проставил ему
   hidden (кнопка поверх выехавшей формы, форма отзыва видна до подписки и
   т.п.). Явный override с более высокой специфичностью (0,2,0) чинит все
   места разом. */
[data-notify-trigger][hidden],
[data-email-gate-trigger][hidden],
[data-email-gate-hint][hidden],
[data-email-gate-form][hidden],
[data-review-form][hidden] { display: none; }
.notify-cta { margin-top: var(--space-3); }
.notify-cta__field {
  display: flex;
  align-items: stretch;
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: #fff;
  transition: border-color .15s ease;
}
.notify-cta__field:focus-within { border-color: var(--color-primary); }
.notify-cta__input {
  flex: 1;
  min-width: 0;
  border: none;
  background: transparent;
  padding: 12px var(--space-3);
  font-family: var(--font-body);
  font-size: var(--fs-small);
  color: var(--color-text-primary);
}
.notify-cta__input:focus { outline: none; }
.notify-cta__input.is-error { background: var(--color-tint-peach); }
.notify-cta__submit {
  flex-shrink: 0;
  width: 46px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-primary);
  border: none;
  cursor: pointer;
  transition: background-color .15s ease;
}
.notify-cta__submit:hover { background: var(--color-accent-amber); }
.notify-cta__form .error-text { margin: var(--space-2) 0 0; }
.notify-cta__msg { font-size: var(--fs-small); color: var(--color-primary); margin: var(--space-2) 0 0; }

/* ---------- Trust icons: 6 в ряд, иконка сверху + подпись снизу ---------- */
.trust-icon-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--space-3);
  margin-bottom: var(--space-6);
}
.trust-icon-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 6px;
}
.trust-icon-item svg { color: var(--color-primary); flex-shrink: 0; }
.trust-icon-item span { font-size: 11px; line-height: 1.3; color: var(--color-text-secondary); }

/* ---------- What's Included, перенесённый в правую колонку (15.07.2026) ----------
   Прижат к низу .product-info (margin-top:auto), поэтому его нижний край
   всегда совпадает с нижним краем миниатюр галереи слева. Уже колонки —
   2 в ряд вместо 3, компактный паддинг под узкую ширину. */
.included-mini { margin-top: auto; }
.included-grid--compact {
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-2);
}
.included-grid--compact .included-item {
  padding: var(--space-3);
  gap: var(--space-2);
}
.included-grid--compact .included-item strong { font-size: var(--fs-body); }
.included-grid--compact .included-item span { font-size: 11px; }

/* "Last updated" теперь .last-updated-inline (см. верх файла) — без рамки,
   в одном ряду с breadcrumbs. Старый .changelog-box (карточка с рамкой) убран. */

/* ---------- Complete the Series: мини-карточки без рейтинга/описания/CTA ----------
   Свой, не растянутый на 2 строки заголовок (эти названия всегда короткие,
   в 2-строчный резерв .product-card__title из 02-cards.css не нуждаются —
   отсюда пустой разрыв перед ценой на скриншоте). Цена + стрелка вместо
   кнопки — компактный явно кликабельный "футер" карточки. */
.mini-cross-card .card__body { padding: var(--space-3) var(--space-4); }
.mini-cross-card__title {
  font-family: var(--font-heading);
  font-size: var(--fs-body);
  font-weight: 700;
  margin: 0 0 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mini-cross-card__desc {
  font-size: var(--fs-caption);
  color: var(--color-text-secondary);
  line-height: 1.4;
  margin: 0 0 var(--space-2);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  min-height: calc(1.4em * 2);
}
.mini-cross-card__price {
  font-family: var(--font-heading);
  font-size: var(--fs-body-lg);
  font-weight: 700;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.mini-cross-card__price .arrow { color: var(--color-primary); font-family: var(--font-body); }
/* Тот же общий hover, что и .card:hover .product-card__title/.article-card__title
   в 02-cards.css — здесь отдельно, т.к. .mini-cross-card__title не подпадает
   под те селекторы (свой класс, не product-card__title/article-card__title). */
.card.mini-cross-card:hover .mini-cross-card__title {
  color: var(--color-accent-amber);
  text-decoration: underline;
}

/* ---------- Tabs content ----------
   18.07.2026: убраны .tab-panel + .tab-panel (лишний бордер/паддинг между
   вкладками) и .tab-panel-label (дублировал название таба, которое уже
   написано на самой кнопке .tab). Обе правки были уместны в статичном
   референсе БЕЗ JS, где все панели показывались сразу друг под другом —
   с 16.07.2026 переключение реальное (display:none / .is-active), видна
   только ОДНА панель за раз, и .tab-panel + .tab-panel (сосед по DOM,
   не по видимости) добавлял бордер/отступ почти всем табам, кроме первого
   (Overview), даже когда они показывались в одиночку — выглядело как
   лишняя двойная линия под рядом табов. */

.overview-list { padding-left: 20px; margin: var(--space-4) 0; color: var(--color-text-secondary); font-size: var(--fs-body); line-height: 1.7; }

.included-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
}
.included-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}
.included-item svg { color: var(--color-primary); flex-shrink: 0; }
.included-item strong { display: block; font-size: var(--fs-body); }
.included-item span { font-size: var(--fs-caption); color: var(--color-text-secondary); }

/* ---------- Email-gate (Freebie Detail — редизайн 19.07.2026 по A/B-мокапу
   от ChatGPT, по прямому запросу) ----------
   Заменяет .price-block + .price-cta-row из Product Detail на странице
   Freebie (single-freebie.php) — тот же слот в правой колонке .product-info.
   Было (16-17.07.2026): мятная карточка (--color-tint-green-soft) с большим
   маскотом-хиро, иконкой-конвертом, заголовком/подзаголовком, ВСЕГДА видимой
   формой, блоком "Here's what happens next" (3 шага) и нижней trust-bar —
   длинная, во многом дублировала название/рейтинг, которые и так уже стоят
   выше в .product-title/.product-meta-row.
   Стало: без цветной подложки, одна кнопка "Get Free Download" (форма
   выезжает под ней по клику — см. site.js, модуль "Email gate"), чек-лист
   преимуществ, компактная плашка "Already subscribed?" с маленьким
   маскотом. 3 состояния (data-email-gate-default/success/recognized)
   переключает тот же JS, что и раньше — только разметка внутри каждой
   панели упрощена. */
.email-gate-eyebrow {
  display: block;
  font-size: var(--fs-caption);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--color-primary);
  margin-bottom: var(--space-2);
}
.email-gate-divider {
  border: none;
  border-top: 1px solid var(--color-border);
  margin: var(--space-5) 0;
}
/* Кнопка "Get Free Download" больше не идёт следом за серой hr-полоской
   (19.07.2026, по скрину) — только небольшой отступ от рейтинга/eyebrow. */
.email-gate {
  margin-top: var(--space-3);
}
/* ВАЖНО: селектор специально :not([hidden]), а не просто .email-gate__panel —
   иначе display:flex здесь перебивает по специфичности UA-правило
   [hidden]{display:none} и скрытая JS-ом (data-email-gate-success, атрибут
   hidden) панель "Check your inbox" начинает рендериться ОДНОВРЕМЕННО с
   формой, наложением поверх (16.07.2026, поймано по скрину — обе панели
   были видны сразу друг на друге). */
.email-gate__panel:not([hidden]) {
  display: flex;
  flex-direction: column;
}
.email-gate__cta { width: 100%; justify-content: center; }
.email-gate__form {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-3);
}
.email-gate__form .error-text { margin: -6px 0 0; }
.email-gate__submit { width: 100%; justify-content: center; }

/* ---------- "Письмо отправлено" ----------
   Переделано 2026-07-31: светло-зелёная карточка (.email-gate__success-card)
   со своей иконкой, заголовком, подзаголовком, разделителем и подсказкой
   удалена целиком — остались две строки текста, маскот и кнопки. Правила
   удалённых элементов убраны отсюда же, чтобы не копить мёртвый CSS.
   .email-gate__panel уже даёт display:flex;flex-direction:column через
   :not([hidden]) выше — здесь только выравнивание/отступы, без display,
   чтобы не наступить на тот же [hidden]-баг. ---------- */
.email-gate__success {
  align-items: center;
  gap: var(--space-4);
  text-align: center;
  /* Высота плашки с адресом. Изначально (2026-07-31) бралась от кнопки,
     чтобы совпадать с ней, но кнопки от этого вытягивались на широкой
     колонке — теперь это просто зафиксированный размер самой плашки,
     кнопки живут своей высотой. */
  --email-gate-info-h: 68px;
}
/* Маскот 206px (было 242px) — минус 15%, 2026-07-31. Отрицательный
   margin-top подтягивает его чуть выше: после переноса строк с адресом
   вниз он стал первым элементом панели, и сверху осталось лишнего воздуха. */
.email-gate__success-mascot {
  width: 206px;
  height: auto;
  margin-top: calc(var(--space-3) * -1);
}
/* Плашка с адресом: та же геометрия, что у кнопки (padding/радиус/толщина
   рамки), но рамка нейтрально-серая (--color-border, #E5E7EA) — чтобы
   читалась как информационное поле, а не как ещё одна кнопка. Ширина —
   вся колонка, т.е. ровно как две кнопки вместе. */
.email-gate__success-email {
  box-sizing: border-box;
  width: 100%;
  min-height: var(--email-gate-info-h);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 12px var(--space-5);
  border: 2px solid var(--color-border);
  border-radius: var(--radius-sm);
  margin: 0;
  font-size: var(--fs-small);
  line-height: 1.4;
  color: var(--color-text-secondary);
}
.email-gate__success-email strong { display: block; color: var(--color-primary); }
.email-gate__success-actions { display: flex; gap: var(--space-3); width: 100%; }
/* Высота кнопок — своя, естественная (от паддингов .btn), min-height здесь
   сознательно нет. Была попытка (2026-07-31) привязать её к высоте плашки
   с адресом, но на широкой колонке подписи в одну строку и кнопки от этого
   неоправданно вытягивались — откатано по прямому запросу: кнопки ниже
   плашки, и это нормально. */
.email-gate__success-actions .btn {
  flex: 1;
  justify-content: center;
  padding-left: var(--space-3);
  padding-right: var(--space-3);
}
.email-gate__success-privacy {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-caption);
  color: var(--color-text-secondary);
  margin: 0;
}

/* ---------- Чек-лист преимуществ (19.07.2026) ---------- */
.email-gate__checklist {
  list-style: none;
  margin: var(--space-4) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  font-size: var(--fs-small);
  color: var(--color-text-primary);
}
.email-gate__checklist li { display: flex; align-items: center; gap: var(--space-2); }
.email-gate__checklist svg { color: var(--color-primary); flex-shrink: 0; }

/* ---------- "Already subscribed?" — компактная плашка вместо большой
   recognized-панели-хиро (19.07.2026) ---------- */
.email-gate__subscribed-hint {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
/* Новый маскот (19.07.2026) — уже кадрированный PNG с прозрачным фоном
   (грудь + флакон), не бейдж-иконка, поэтому без circle-обрезки, как было
   раньше у mascot-hero.png. */
.email-gate__subscribed-hint img { flex-shrink: 0; width: 120px; height: auto; }
.email-gate__subscribed-hint p { margin: 0; margin-left: 20px; font-size: var(--fs-small); color: var(--color-text-secondary); }
.email-gate__subscribed-hint strong { display: block; margin-bottom: -11px; font-size: var(--fs-body); color: var(--color-text-primary); }

/* Чекбокс согласия — первый в теме настоящий (не декоративный) чекбокс в
   реальной форме, поэтому стилизуем нативный <input type="checkbox">
   через appearance:none вместо JS-переключения класса — доступнее
   (клавиатура/скринридер/required из коробки), но выглядит как атом
   .checkbox из 01-atoms.css. */
.email-gate__consent {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  font-size: var(--fs-caption);
  color: var(--color-text-secondary);
  line-height: 1.4;
  cursor: pointer;
}
.email-gate__consent input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  margin-top: 1px;
  border: 1.5px solid var(--color-border);
  border-radius: 5px;
  background: #fff;
  cursor: pointer;
  position: relative;
  transition: background-color .15s ease, border-color .15s ease;
}
.email-gate__consent input[type="checkbox"]:checked {
  background: var(--color-primary);
  border-color: var(--color-primary);
}
.email-gate__consent input[type="checkbox"]:checked::after {
  content: '';
  position: absolute;
  left: 5px;
  top: 1px;
  width: 4px;
  height: 9px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.email-gate__consent input[type="checkbox"].is-error { border-color: var(--color-red); }
.email-gate__consent a { color: var(--color-text-secondary); text-decoration: underline; }
.email-gate__consent a:hover { color: var(--color-accent-amber); }

.review-card { padding: var(--space-5) 0; border-bottom: 1px solid var(--color-border); }
.review-card:first-child { padding-top: 0; }
.review-card__head { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-2); }
.review-card__avatar {
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--color-tint-green); color: var(--color-primary-active);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; flex-shrink: 0;
}
.review-card__name { font-weight: 700; font-size: var(--fs-body); }
.review-card__verified { font-size: var(--fs-caption); color: var(--color-primary); font-weight: 600; }
.review-card__stars { color: var(--color-gold); font-size: 13px; margin-bottom: var(--space-2); }

/* ---------- Reviews: gate + submit form (17.07.2026, "архитектор") ----------
   Переиспользует существующие атомы — .input (textarea), .btn/.btn-primary
   (кнопка), .error-text (01-atoms.css), .page-intro (текст плашки) —
   ничего с нуля, только новая обёртка/звёзды. */
.review-gate { margin-top: var(--space-5); }

.review-form { display: flex; flex-direction: column; gap: var(--space-3); max-width: 520px; }

.star-rating { display: flex; gap: 4px; }
.star-input {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font-size: 28px;
  line-height: 1;
  color: var(--color-border);
  cursor: pointer;
  transition: color .1s ease;
}
.star-input.is-active { color: var(--color-gold); }

.review-form textarea.input { min-height: 96px; resize: vertical; font-family: var(--font-body); }

.review-form__success {
  color: var(--color-primary);
  font-weight: 600;
  font-size: var(--fs-body);
}
.review-card__text { font-size: var(--fs-small); color: var(--color-text-secondary); line-height: 1.5; margin: 0; }

/* ---------- Product CTA banner (23.07.2026, по прямому запросу) ----------
   Часть типового шаблона Product Detail — авто-выводится после блока
   Overview на каждой странице товара (single-product.php), между описанием
   и "Complete the Series"/"You May Also Like". margin — обычный section
   (var(--space-8) 0, см. 05-page-shell.css), отдельно не задаём.
   aspect-ratio 905:108 — та же пропорция, что и у banner_product_back.svg
   (viewBox), так что фон растягивается по всей высоте без искажений при
   любой ширине контейнера — размер banner ровно совпадает с образцом
   (референс-скриншот пользователя). */
.product-cta-banner {
  position: relative;
  background: #ecf4e1;
  border-radius: var(--radius-lg);
  aspect-ratio: 905 / 108;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
/* Фон — на всю плашку (inset:0), не в углу: сам SVG уже скомпонован так,
   что декоративные элементы кучкуются у левого/правого края и у верха/низа
   собственного холста, оставляя центр пустым под кнопки. */
.product-cta-banner__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.product-cta-banner__bg svg { width: 100%; height: 100%; display: block; }
.product-cta-banner__buttons {
  position: relative;
  z-index: 1;
  display: flex;
  gap: var(--space-4);
}
/* Одинаковая ширина кнопок (23.07.2026, по прямому запросу) — измерено
   вживую: "Buy on Creative Market" ~228px, "View free Demo" ~171px без
   этого правила. 230px берёт более длинный текст с небольшим запасом.
   Скоуп только на эту плашку — общий .btn в 01-atoms.css не трогаем. */
.product-cta-banner__buttons .btn { width: 230px; justify-content: center; }
/* .grid-4 (Complete the Series) теперь в 05-page-shell.css — общий для всех страниц */
/* ==========================================================================
   Карточка товара и фрибi на телефоне (02.08.2026).
   ========================================================================== */
@media (max-width: 900px) {

  /* Две колонки (1.4fr / 0.6fr) складываются в одну: галерея сверху, правая
     колонка — цена и кнопки на товаре, форма email-gate на фрибi — под ней.
     Порядок в разметке уже правильный, поэтому достаточно убрать вторую
     колонку, ничего переставлять не нужно. */
  /* minmax(0, …), а не 1fr — см. пояснение в 05-page-shell.css: голый 1fr
     раздувается до min-content содержимого, и вся карточка вылезала за
     белое поле на 94px. */
  .product-hero { grid-template-columns: minmax(0, 1fr); }

  /* Хлебные крошки: последняя ссылка повторяет заголовок товара, а он тут
     длинный («Cupcake Branding Kit – Cute Vector Cupcakes, Patterns &
     Branding Pack») и растягивал строку. На телефоне она не нужна — этот же
     текст стоит заголовком H1 прямо под ней. Путь до раздела остаётся. */
  .breadcrumbs { flex-wrap: wrap; row-gap: var(--space-1); }
  .breadcrumbs .crumb-current { display: none; }
  /* Разделитель перед скрытой крошкой, иначе строка кончается висящим «/».
     Через :has(), потому что «предыдущий соседний элемент» иначе в CSS не
     выбрать: .crumb-sep и .crumb-current — оба <span>, и :last-of-type
     попадает в саму крошку, а не в отделитель перед ней. */
  .breadcrumbs .crumb-sep:has(+ .crumb-current) { display: none; }

  /* «Last updated: …» убрано по прямому решению. */
  .last-updated-inline { display: none; }

  /* Шесть иконок-преимуществ в один ряд не помещаются никак: это и была
     та «нерушимая» ширина, из-за которой раздувался трек сетки.
     margin-bottom снят: до вкладок оставалось 64px — 32 от самой сетки плюс
     32 от .product-hero. На широком экране это два разных блока в разных
     колонках, и отступы не складывались; после сборки в одну колонку они
     встали друг под другом и сложились. Остаётся 32 — ровно половина. */
  .trust-icon-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin-bottom: 0;
  }

  /* Строка, в которой лежат вкладки (и отдельно — крошки с «Last updated»),
     оставалась двухколоночной 1.4fr/0.6fr: вкладки занимали ~70% ширины, а
     справа висела пустая колонка. */
  .hero-align-row {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-3);
  }

  /* Кнопки покупки и «Get Notified» — во всю ширину колонки, в столбик.
     Рядом они не помещаются, а ужатые до многоточия выглядят сломанными. */
  .price-cta-row,
  .cta-secondary-row { flex-direction: column; align-items: stretch; }
  .price-cta-row .btn,
  .cta-secondary-row .btn { width: 100%; }

  /* Зелёная плашка с пробирками под описанием.
     На десктопе её высоту задаёт жёсткая пропорция 905/108 — она там
     широкая и низкая. При ширине колонки 319px та же пропорция даёт высоту
     38px, то есть ниже самой кнопки, а overflow:hidden всё лишнее обрезает.
     Плашка декоративная, её высоту должно задавать содержимое плюс поля. */
  .product-cta-banner {
    aspect-ratio: auto;
    padding: var(--space-6) var(--space-5);
    min-height: 130px;   /* +20% к высоте, которую давало одно содержимое (108px) */
  }
  /* Кнопки по 230px рядом в 319px не помещаются — ставим в столбик во всю
     ширину, как и остальные кнопки на странице. */
  .product-cta-banner__buttons {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    gap: var(--space-3);
  }
  .product-cta-banner__buttons .btn { width: 100%; }

  /* Фон. Замерено по самому файлу: холст 905x108, декор двумя группами по
     краям — левая занимает 0–31% ширины, правая 68–100%, центр пустой под
     кнопки. Из этого следует, что «увеличить колбы, оставив обе группы»
     невозможно: они разнесены на всю ширину холста, и любое увеличение
     выталкивает их за края, оставляя в кадре ровно пустую середину.

     Поэтому рисунок увеличивается до полной высоты плашки с сохранением
     пропорций и прижимается влево: левая группа колб становится крупной и
     попадает в кадр целиком, правая уходит в обрез. Растягивать по обеим
     осям нельзя — колбы вытянулись бы втрое по вертикали.

     Правильное решение на будущее — отдельный вертикальный вариант фона под
     мобильную плашку, здесь это компромисс на имеющемся файле. */
  .product-cta-banner__bg svg {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: auto;        /* пропорция 8.4:1 сохраняется, ширина уходит за край */
    max-width: none;    /* иначе глобальное img/svg-правило ужмёт обратно в 100% */
  }

  /* Миниатюры убраны совсем, а не перенесены под большую картинку.
     Причина техническая: лента вертикальная и прокручивается по наведению
     курсора на крайнюю миниатюру (product-gallery.js пишет треку
     translateY инлайном). На сенсорном экране наведения нет — дальше пятой
     картинки было бы не добраться, а инлайновый transform всё равно
     перебил бы любую раскладку из таблицы стилей.
     Ничего не теряется: стрелки на большой картинке остаются и листают всю
     галерею. Если миниатюры на телефоне понадобятся, это отдельная работа —
     горизонтальная лента со свайпом вместо hover-логики. */
  .gallery-thumbs-viewport { display: none; }

  /* Точки под большой картинкой. .gallery — flex-строка (миниатюры слева,
     картинка справа), поэтому просто так точки встали бы СБОКУ от картинки.
     Разрешаем перенос и отдаём им целую строку: миниатюры выше уже скрыты,
     так что в первой строке остаётся одна картинка, точки уезжают под неё. */
  .gallery { flex-wrap: wrap; }
  .gallery-dots {
    display: flex;
    flex: 0 0 100%;
    justify-content: center;
    margin-top: var(--space-3);
  }
  /* Сама точка — 8px, но кнопка вокруг неё 24×24: восьмипиксельная цель для
     пальца слишком мелкая (рекомендуемый минимум — 24px). Точка рисуется
     псевдоэлементом внутри прозрачной кнопки, поэтому увеличение области
     нажатия ничего не меняет на вид. Своё поле у кнопок заодно расставляет
     точки друг от друга — отдельный gap не нужен. */
  .gallery-dot {
    position: relative;
    width: 24px;
    height: 24px;
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
  }
  .gallery-dot::after {
    content: '';
    position: absolute;
    inset: 8px;
    border-radius: 50%;
    background: var(--color-text-secondary);
    transition: background .15s ease;
  }
  .gallery-dot.is-active::after { background: var(--color-accent-amber); }
}

/* Фрибi: форма подписки поднимается сразу под галерею (02.08.2026).

   На товаре в правой колонке лежит только цена с кнопками, и после
   складывания в одну колонку она встаёт сразу под галереей — всё логично.
   На фрибi иначе: там .hero-col-left оборачивает И галерею, И вкладки
   (так чинили высоту колонок 17.07.2026), поэтому email-gate оказывался
   ниже всего содержимого страницы — на живой странице форма уезжала на
   1657px от верха. За фрибi приходят именно ради неё, пролистывать до неё
   весь Overview с лицензией и FAQ бессмысленно.

   display:contents снимает саму обёртку с раскладки, не трогая разметку:
   галерея и вкладки становятся прямыми элементами той же сетки, и порядок
   уже можно задать. Сетка одноколоночная, поэтому order просто выстраивает
   их сверху вниз: галерея -> форма -> вкладки. */
@media (max-width: 900px) {
  .hero-col-left { display: contents; }
  .product-hero .gallery    { order: 1; }
  .product-hero .product-info { order: 2; }
  .product-hero .tabs-col   { order: 3; }
}

/* ==========================================================================
   Фрибi: обвязка вокруг кнопки убрана (03.08.2026, по прямому решению).

   На телефоне между кнопкой «Get Free Download» и вкладками стояло ещё три
   блока: чек-лист из трёх пунктов, серая линейка и плашка «Already
   subscribed?» с маскотом. На десктопе они заполняют правую колонку,
   которая иначе была бы наполовину пустой. В одну колонку заполнять нечего:
   те же блоки становятся тремя экранами прокрутки между кнопкой, за
   которой пришли, и содержимым товара.

   Скрывается обёртка [data-email-gate-checklist] целиком — линейка лежит
   внутри неё, отдельного правила не нужно.

   JS (site.js, модуль «Email gate») прячет и показывает эти же блоки через
   атрибут hidden при переходе в состояние «письмо отправлено». Атрибут и
   display:none друг с другом не спорят: оба ведут в одну сторону, а на
   десктопе правило не действует вовсе — сценарий остаётся прежним.
   ========================================================================== */
@media (max-width: 900px) {
  [data-email-gate-checklist],
  .email-gate__subscribed-hint { display: none; }
}
