/* === из сниппета №127 «Краткое описание - параметры Страницы Продукта» === */
.exps-excerpt{ margin:0 0 18px; }
.exps-excerpt__p{ font-size:15px; line-height:1.6; color:#4a4a55; margin:0 0 12px; }
.exps-specs{ display:grid; grid-template-columns:1fr 1fr; gap:0 32px; margin:6px 0 4px; }
.exps-specs__row{ display:flex; align-items:baseline; justify-content:space-between; gap:12px; padding:10px 0; border-bottom:1px solid #efeff1; }
.exps-specs__label{ font-size:14px; color:#80808a; }
.exps-specs__value{ font-size:14px; font-weight:700; color:#1a2238; text-align:right; }
@media(max-width:600px){ .exps-specs{ grid-template-columns:1fr; } }



/* высота строки параметра (главное — расстояние между строками) */
.exps-specs__row{ padding:4px 0; }      /* было 10px→6px→4px, Волна 4 (25.07.2026): ещё плотнее по жалобе «рыхло» */

/* зазор между двумя колонками параметров */
.exps-specs{ gap:0 28px; }

/* текстовые абзацы описания (над и под параметрами) */
.exps-excerpt__p{ line-height:1.5; margin:0 0 10px; }

/* общий отступ блока описания */
.exps-excerpt{ margin:0 0 14px; }

/* === из сниппета №59 «Страница продукта» === */
/* =========================
   SINGLE PRODUCT — PRICE SPLIT + SPACING + QTY UNDER BUTTON
   Works for SIMPLE + VARIABLE
   ========================= */

/* --- PRICE SPLIT --- */

/* Старая цена — 25.07.2026, редизайн по макету (docs/product-page-
   spec.md): у макета нет прямого эталона для главной зачёркнутой цены
   (тестовый товар макета — без скидки), решение по этому месту
   отдельно не фиксировалось. Взят паттерн зачёркнутой цены из
   «Похожих моделей» того же макета (13px, приглушённый цвет) —
   визуальная согласованность с тем же макетом, а не собственная
   догадка с нуля; если Вакхтанг захочет другое значение — одна
   строка. */
.single-product div.product .summary .price del{
  font-size: 13px !important;
  font-weight: 400 !important;
  color: #97958f !important; /* ≈oklch(0.6 0.005 90), тот же тон, что у del в «Похожих моделях» макета */
  opacity: 1 !important;
  margin-right: 10px !important;
}

/* Новая цена (скидка) — размер/вес/цвет по макету («Цена», spec.md) */
.single-product div.product .summary .price ins{
  text-decoration: none !important;
}
.single-product div.product .summary .price ins .woocommerce-Price-amount,
.single-product div.product .summary .price ins .woocommerce-Price-amount bdi{
  font-size: 26px !important;
  font-weight: 800 !important;
  color: #0a0907 !important; /* ≈oklch(0.14 0.005 90) / --esc-text-1 — хардкод, эта страница не под body.exposhop-catalog, токен вне скоупа (тот же приём, что в video-badge.css) */
  text-decoration: none !important;
}

/* Обычная цена (без скидки) */
.single-product div.product .summary .price > .woocommerce-Price-amount,
.single-product div.product .summary .price > .woocommerce-Price-amount bdi{
  font-size: 26px !important;
  font-weight: 800 !important;
  color: #0a0907 !important;
}

/* --- SPACING --- */

/* Отступ между кратким описанием и ценой + типографика — по макету
   (Волна 4, 25.07.2026): было font-size 17px/line-height 1.8/
   color #3a3a3a/margin-bottom 28px (Astra WC-compat дефолт, этот блок
   раньше не стилизовался вообще) — макет: 15px/1.7/oklch(0.42
   0.005 90)/24px. */
.single-product div.product .summary .woocommerce-product-details__short-description{
  font-size: 15px !important;
  line-height: 1.7 !important;
  color: #6b6a67 !important; /* ≈oklch(0.42 0.005 90) */
  margin-bottom: 24px !important;
}

/* Отступ под ценой */
.single-product div.product .summary p.price,
.single-product div.product .summary .price{
  margin-bottom: 14px !important;
}

/* --- QTY РЯДОМ С КНОПКОЙ --- */
/* 25.07.2026, Волна 3 (product-page-redesign-task-v3.md, п. Количество):
   было — колонка, qty ПОД кнопкой на всю ширину. В самом макете поля
   количества нет вообще (проверено построчным grep по .dc.html — ни
   "quantity", ни "qty", ни аналогов) — не «спрятать» (это реальная,
   нужная функциональность выбора количества, терять её — не задача
   стиля), а расположить компактно в одну строку с кнопкой, как
   принято в большинстве вариантов такого лейаута без явного qty-блока
   в макете. flex-direction:row вместо column; qty — фиксированная
   компактная ширина, кнопка занимает остальное (flex:1 вместо 100%). */

/* SIMPLE */
/* Волна 17 (25.07.2026) — найден реальный источник «кнопка В корзину
   обрезана на вариативных товарах»: у WooCommerce <form> на вариативном
   товаре ДВА класса разом — `class="variations_form cart"` (не только
   `variations_form`!). Селектор `form.cart` ниже (написан для SIMPLE)
   поэтому срабатывал ТАКЖЕ и на вариативных формах, силой делая ВНЕШНИЙ
   <form> flex-row — а прямые дети внешней формы на вариативном товаре
   это НЕ .quantity/.single_add_to_cart_button (как на simple), а
   table.variations + .single_variation_wrap + .woocommerce-variation-
   add-to-cart — все трое утискивались в одну строку, отжимая кнопку до
   ~64px на мобильном (текст «შეკვეთა» визуально обрублен) и до ~88px на
   десктопе (подтверждено живым замером обоих). Правило для .woocommerce-
   variation-add-to-cart (см. блок VARIABLE ниже) уже было правильным —
   проблема была только в том, что внешняя форма его перекрывала лишним
   flex-row уровнем. Фикс — `:not(.variations_form)`, чтобы это
   SIMPLE-правило не задевало форму вариативного товара вообще; она
   остаётся обычным block-элементом, все секции стекаются вертикально
   каждая на 100% ширины — без единой дополнительной строчки CSS сверх
   уже существующего блока VARIABLE. Баг был не мобильно-специфичным
   (десктоп тоже страдал, просто менее заметно) — фикс без media-запроса. */
.single-product div.product .summary form.cart:not(.variations_form){
  display:flex !important;
  flex-direction:row !important;
  flex-wrap:wrap !important; /* блок услуг (.exo-svc, assembly.css) — своей строкой над кнопкой */
  align-items:stretch;
  gap:12px !important;
}

.single-product div.product .summary form.cart:not(.variations_form) .single_add_to_cart_button{
  order:2 !important;
  margin:0 !important;
  /* Цвет/фон НЕ трогать — уже совпадают с макетом (#d00072/white),
     решение задания п.34 (Волна 2). */
  flex: 1 1 auto !important;
  width: auto !important;
  box-sizing: border-box !important;
  padding: 17px 0 !important;
  border-radius: 8px !important;
  font-weight: 700 !important;
  font-size: 15px !important;
}

/* Степпер (−/1/+) — Волна 4 (25.07.2026), точные размеры из макета:
   единая рамка НА КОНТЕЙНЕРЕ (было — рамка только на .qty input,
   −/+ без рамки вообще, ширины 38/58/38px вразнобой), три сегмента
   по 44px (было 38/58/38). border-radius на контейнере + overflow:
   hidden, чтобы внутренние сегменты не вылезали за скруглённый угол. */
.single-product div.product .summary form.cart:not(.variations_form) .quantity{
  order:1 !important;
  margin:0 !important;
  flex: 0 0 auto !important;
  display: flex !important;
  align-items: stretch !important;
  border: 1px solid #cfcecb !important; /* ≈--esc-border-strong, хардкод — вне скоупа body.exposhop-catalog */
  border-radius: 8px !important;
  overflow: hidden;
}
.single-product div.product .summary form.cart:not(.variations_form) .quantity .qty,
.single-product div.product .summary form.cart:not(.variations_form) .quantity .minus,
.single-product div.product .summary form.cart:not(.variations_form) .quantity .plus{
  height: auto !important;
  width: 44px !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-sizing: border-box !important;
}
.single-product div.product .summary form.cart:not(.variations_form) .quantity .minus,
.single-product div.product .summary form.cart:not(.variations_form) .quantity .plus{
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  font-size: 18px !important;
  color: #615f5a !important; /* ≈oklch(0.4 0.005 90) */
  text-decoration: none !important;
}
.single-product div.product .summary form.cart:not(.variations_form) .quantity .qty{
  text-align: center !important;
  font-weight: 700 !important;
  font-size: 15px !important;
  color: #0a0907 !important; /* ≈--esc-text-1 */
}

/* VARIABLE (обычно qty+button внутри .woocommerce-variation-add-to-cart) */
/* Волна 17 — таблица атрибутов (свотчи размера/направления открывания,
   плагин Smart Swatches, реальные классы .sp-smart-swatches-* — не
   .swatch/.variable-item, как в черновике задания, сверено живым DOM)
   по умолчанию shrink-to-fit (~125px на мобильном, ~240px на десктопе)
   — теперь, когда внешняя форма больше не сжимает её в общую строку
   (см. фикс выше), единственное недостающее — явная width:100%, чтобы
   она занимала всю доступную ширину колонки, а не только свой
   контент. flex-wrap на .sp-smart-swatches-container уже есть
   (свойство самого плагина) — переопределять не нужно. */
.single-product div.product .summary form.variations_form table.variations{
  width: 100% !important;
}
.single-product div.product .summary form.variations_form .woocommerce-variation-add-to-cart{
  display:flex !important;
  flex-direction:row !important;
  flex-wrap:wrap !important; /* блок услуг (.exo-svc, assembly.css) — своей строкой над кнопкой */
  align-items:stretch;
  gap:12px !important;
}

.single-product div.product .summary form.variations_form .woocommerce-variation-add-to-cart .single_add_to_cart_button{
  order:2 !important;
  margin:0 !important;
  flex: 1 1 auto !important;
}

.single-product div.product .summary form.variations_form .woocommerce-variation-add-to-cart .quantity{
  order:1 !important;
  margin:0 !important;
  flex: 0 0 auto !important;
  display: flex !important;
  align-items: stretch !important;
  border: 1px solid #cfcecb !important;
  border-radius: 8px !important;
  overflow: hidden;
}
.single-product div.product .summary form.variations_form .woocommerce-variation-add-to-cart .quantity .qty,
.single-product div.product .summary form.variations_form .woocommerce-variation-add-to-cart .quantity .minus,
.single-product div.product .summary form.variations_form .woocommerce-variation-add-to-cart .quantity .plus{
  height: auto !important;
  width: 44px !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-sizing: border-box !important;
}
.single-product div.product .summary form.variations_form .woocommerce-variation-add-to-cart .quantity .minus,
.single-product div.product .summary form.variations_form .woocommerce-variation-add-to-cart .quantity .plus{
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  font-size: 18px !important;
  color: #615f5a !important;
  text-decoration: none !important;
}
.single-product div.product .summary form.variations_form .woocommerce-variation-add-to-cart .quantity .qty{
  text-align: center !important;
  font-weight: 700 !important;
  font-size: 15px !important;
  color: #0a0907 !important;
}


/* === из сниппета №61 «Блок Доверия на странице продукта» === */
/* Волна 4 (25.07.2026): margin-top:0 — отступ СВЕРХУ уже даёт margin-
   bottom:24px короткого описания выше по флоу (flex+order, Волна 2),
   задавать его ещё раз здесь означало бы задвоить зазор. */
.exps-under-btn{ margin-top:0; }

/* строка доставки */
.exps-delivery{
  margin:0 0 16px;
  text-align:left;
  font-size:14px;
  color:#80808a;
}

/* чек-лист доверия: в ряд, галочки — Волна 4 (25.07.2026), значения
   из макета: контейнер gap:20px (было 14px 24px — двузначный,
   вразнобой), пункт — gap 8px между галочкой и текстом (было через
   padding-left:30px на всём li), font-size 13px (было 14), цвет
   текста oklch(0.35 0.005 90)≈#59564f (было #4a4a55). Галочка в
   макете — простой символ цветом #2a8a4a, БЕЗ кружка-фона (было
   circle badge #eaf3d8/#5f8a13, наш собственный, более «плашечный»
   вид) — упрощено до макета. */
.exps-checklist{
  list-style:none;
  margin:0 0 28px; /* было 18px — по макету (margin-bottom трастовой строки перед кнопкой) */
  padding:0;
  border:0;                 /* убираем большую рамку-коробку */
  display:flex;
  flex-wrap:wrap;
  gap:20px;
}
.exps-checklist li{
  position:relative;
  margin:0;
  padding-left:22px;
  font-size:13px;
  line-height:20px;
  color:#59564f;
}
.exps-checklist li:before{
  content:"✓";
  position:absolute; left:0; top:0;
  width:20px; height:20px;
  display:flex; align-items:center; justify-content:center;
  color:#2a8a4a;            /* цвет галочки по макету (НЕ фирменный малиновый — он только для CTA) */
  font-size:12px; font-weight:700;
}

.exps-installment-btn{ display:none !important; }

/* === из сниппета №63 «Кредиты» === */
/* ========== EXPS INSTALLMENTS — UI под макет (JS не меняется) ========== */
.exps-inst{
  margin-top:22px;
  padding:18px 18px 12px;
  border:1px solid #ececef;
  border-radius:14px;
  background:#fff;
  font-family:inherit;
}
.exps-inst__head{ margin-bottom:12px; }
.exps-inst__head-text{
  font-size:14px; font-weight:700; letter-spacing:0; color:#1a2238;
}

/* строки банков */
.exps-inst__bank{ margin-bottom:8px; }
.exps-inst__row{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:13px 15px;
  border:1px solid #efeff1; border-radius:10px; background:#fff;
  cursor:pointer;
  transition:background .15s ease, border-color .15s ease;
}
.exps-inst__row:hover{ background:#fafafb; border-color:#e2e2e6; }
.exps-inst__label{ font-size:14px; font-weight:400; color:#4a4a55; }
.exps-inst__label b{ font-weight:600; color:#1a2238; }
.exps-inst__amount{ font-size:15px; font-weight:700; color:#1a2238; white-space:nowrap; }
.exps-inst__chev{ color:#cfcfd6; }
.exps-inst__chev:after{ content:"›"; font-size:20px; line-height:1; }

/* условия скрыты на странице (нужны только модалке) — НЕ удалять */
.exps-inst__terms{ display:none !important; }

/* ---- Волна 4 (25.07.2026), п.10 — блок кредитов свёрнут в макете:
   было 2 отдельные строки (TBC/Credo) с шевронами, стало — ОДНА
   строка «Рассрочка от {мин. платёж} — TBC, Credo» + «Подробнее ›».
   Суммы TBC/Credo считает JS сниппета №64 (аннуитет 18%/24 мес и
   price/3 соответственно) — трогать сниппет не стали (вне
   git-репозитория плагина, тот же принцип, что и везде в этом
   проекте), вместо этого спрятали исходные 2 строки CSS-ом и
   добавили СВОЙ маленький скрипт (class-exposhop-product-page.php,
   render_installment_summary_script(), хук wp_footer), который
   считает те же 2 суммы САМ (те же формулы) и печатает готовую
   строку — клик по «Подробнее» триггерит клик по строке банка с
   меньшим платежом, чтобы переиспользовать готовую модалку №64 как
   есть. Риск: если формулы в №64 когда-нибудь изменят (ставка/срок/
   делитель Credo) — эта копия не узнает сама, разъедет с реальным
   расчётом; отмечено в докладе сессии. ---- */
.single-product .exps-inst {
  padding: 14px 20px !important;
  border: 1px solid #dfdedb !important; /* ≈--esc-border */
  border-radius: 8px !important;
}
.single-product .exps-inst__head,
.single-product .exps-inst__bank {
  display: none !important;
}
.exps-inst-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-size: 14px;
  color: #59564f; /* ≈oklch(0.35 0.005 90) */
}
.exps-inst-summary strong {
  color: #0a0907; /* ≈--esc-text-1 */
}
.exps-inst-summary__more {
  color: #d00072; /* ≈--esc-accent */
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
}

/* ========== МОДАЛКА ========== */
.exps-modal-overlay{
  position:fixed; inset:0; z-index:999999;
  display:flex; align-items:center; justify-content:center;
  background:rgba(26,34,56,.55); backdrop-filter:blur(3px);
}
.exps-modal{
  position:relative; width:92%; max-width:520px;
  background:#fff; border-radius:18px; padding:30px 28px 26px;
  box-shadow:0 30px 80px rgba(20,20,45,.30);
  font-family:inherit;
}
.exps-modal-title{ font-size:20px; font-weight:800; color:#1a2238; margin-bottom:16px; padding-right:40px; }
.exps-modal-body{ font-size:15px; line-height:1.6; color:#4a4a55; }

.exps-inst__title{ font-size:16px; font-weight:700; color:#1a2238; margin:0 0 12px; }
.exps-inst__content{ margin:0 0 16px; }
.exps-inst__content ul{ margin:8px 0 0; padding-left:18px; }
.exps-inst__content li{ margin:6px 0; }
.exps-inst__content strong{ color:#1a2238; }

/* чипы сроков (TBC) */
.exps-inst__options{ display:flex; flex-wrap:wrap; gap:8px; margin:6px 0 4px; }
.exps-inst__opt{
  display:inline-flex; align-items:center; justify-content:center;
  padding:7px 14px; border-radius:999px;
  border:1.5px solid #e0e0e6; background:#fff; color:#4a4a55;
  font-size:13px; font-weight:600; cursor:pointer; user-select:none;
  transition:all .15s ease;
}
.exps-inst__opt:hover{ border-color:#1a2238; color:#1a2238; }
.exps-inst__opt.is-on{ background:#1a2238; border-color:#1a2238; color:#fff; }

/* строка платежа */
[data-role="tbc-payment"], [data-role="credo-payment"]{
  display:inline-block; margin-top:14px;
  font-size:16px; font-weight:800; color:#1a2238;
}

/* крестик */
.exps-modal-close{
  position:absolute !important; top:14px !important; right:14px !important;
  width:34px !important; height:34px !important; padding:0 !important;
  display:flex !important; align-items:center !important; justify-content:center !important;
  border:0 !important; border-radius:999px !important;
  background:#f0f0f2 !important; color:#1a2238 !important;
  font-size:20px !important; line-height:1 !important; font-weight:700 !important;
  cursor:pointer !important; box-shadow:none !important;
}
.exps-modal-close:hover{ background:#e4e4e8 !important; }

/* === из сниппета №91 «Стабилизация видео в описании продукта» — только .product-video-wrapper часть; голое video{} НЕ перенесено (см. docs/video-stack-map.md, Пакет A/B решения) === */
/* Стабильный контейнер под видео */
.product-video-wrapper .video-desktop,
.product-video-wrapper .video-mobile{
  max-width: 100%;
}

/* 16:9 для desktop */
.product-video-wrapper .video-desktop{
  aspect-ratio: 16 / 9;
}

/* 9:16 для mobile */
.product-video-wrapper .video-mobile{
  aspect-ratio: 9 / 16;
}

/* Видео всегда растягиваем по контейнеру */
.product-video-wrapper video,
.product-video-wrapper .wp-video,
.product-video-wrapper .wp-video video{
  width: 100% !important;
  height: 100% !important;
  display: block;
  object-fit: cover; /* можно заменить на contain если хочешь без обрезки */
}

/* (желательно) убрать лишние отступы вокруг wp-video */
.product-video-wrapper .wp-video{
  margin: 0 !important;
}

/* === из сниппета №71 «Video layout – YouTube + Self-host» — generic .video-desktop/.video-mobile + .product-video-wrapper margin ===
   ВНИМАНИЕ: этот же блок продублирован в assets/css/video-landing.css (enqueue-контекст page/post).
   Обслуживает 191 товар здесь + 7 страниц там — два разных enqueue-контекста без пересечения, не нарушение «одного источника». === */
/* По умолчанию: desktop */
.video-mobile {
  display: none !important;
}

.video-desktop,
.video-mobile {
  width: 100%;
  max-width: 720px;
  margin: 0 auto 14px;
}

/* Desktop 16:9 */
.video-desktop {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
}

.video-desktop iframe {
  position: absolute;
  inset: 0;
  width: 100% !important;
  height: 100% !important;
  border: 0;
}

/* Mobile: vertical 9:16 */
@media (max-width: 768px) {
  .video-desktop {
    display: none !important;
  }

  .video-mobile {
    display: block !important;
    max-width: 420px;
  }

  .video-mobile {
    position: relative;
    aspect-ratio: 9 / 16;
    overflow: hidden;
  }

  .video-mobile iframe {
    position: absolute;
    inset: 0;
    width: 100% !important;
    height: 100% !important;
    border: 0;
  }
}

.product-video-wrapper {
  margin: 18px 0 24px;
}

/* ================================================================
   Из «Разбора солянки №131/№132» (docs/tasks/task-soljanka-131-132.md,
   docs/soljanka-render-baseline.md) — правила, матчащиеся только на
   товарной странице. Значения — эталон, снятый реальными
   computed-значениями с прода, не текст сниппета.
   ================================================================ */

/* ---- Кнопка «Показать описание» (toggle-desc) — источник №131,
   общий базовый стиль с .geo-btn (About/GEO-модуль) продублирован
   здесь по прецеденту .video-desktop/.video-mobile (Волна 2-В-2,
   Пакет C) — контексты не пересекаются, объединяющего адресата нет.
   ЗАВИСИМОСТЬ ОТ №130: --exo-green/-green-dark/-radius — №130
   остаётся активным. При унификации --exo-*→--esc-* в Волне 6
   обновить и это правило (чек-лист в css-migration-plan-v2.md). ---- */
.toggle-desc {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--exo-radius);
  background: var(--exo-green);
  color: #fff;
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: background .25s ease, transform .15s ease;
  padding: 10px 15px;
  font-size: 14px;
}
.toggle-desc:hover {
  background: var(--exo-green-dark);
  transform: translateY(-1px);
}

/* ---- Сетка related products — РЕШЕНИЕ 25.07.2026 (редизайн по
   макету, п.4): 4 колонки, как в макете. Прежнее «3, отличается от
   GEO-модуля» на практике и не работало — grid-template-columns здесь
   не имел !important, а у Astra уже есть своё правило для
   `.products.columns-4` (реальный класс, который WooCommerce и
   печатает по умолчанию), которое и побеждало молча — фактическая
   сетка уже была 4-колоночной до этой правки, теперь это явное,
   осознанное значение, а не случайный проигрыш каскада.
   1.8.80 (docs/tasks/task-bundles-admin.md, Задача 1): базовое правило
   было безусловным 4-колоночным !important независимо от того, какой
   `columns-N` класс реально напечатан на `<ul>` — движок бандлов
   (Exposhop_Bundles_Engine::render()) печатает `columns-{3,4,5}` по
   настройке конкретного бандла, это правило её молча отменяло бы.
   Оставлено единственным владельцем `.exps-bundle-related`/`.related.
   products` (см. остальной файл) — не дублируется в отдельный файл,
   только расширено: базовое значение (без класса columns-N — на
   случай, если он не напечатан) остаётся 4, columns-3/columns-5
   переопределяют по специфичности (2 класса вместо 1 — не гонка
   !important, обе стороны уже !important, побеждает более специфичный
   селектор). Мобильный брейкпоинт ниже — уже общий для всех
   вариантов, дополнительно трогать не нужно. */
.woocommerce ul.products,
.woocommerce-page ul.products {
  clear: both !important;
  width: 100% !important;
  display: grid !important;
  grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
  gap: var(--exo-gap); /* зависимость от №130 — уже совпадает с 24px из макета */
}
.woocommerce ul.products.columns-3,
.woocommerce-page ul.products.columns-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
}
.woocommerce ul.products.columns-5,
.woocommerce-page ul.products.columns-5 {
  grid-template-columns: repeat(5, minmax(0, 1fr)) !important;
}
/* Волна 6 (25.07.2026): 4 колонки были ЖЁСТКО заданы без единого
   media-запроса — на 390px это давало ~66px на карточку (337px
   контента / 4), не буквальный горизонтальный overflow
   (bodyScrollWidth===viewportWidth, проверено живьём на 4 товарах),
   но фактически нечитаемые, разваливающиеся карточки — то, что
   выглядело как «страница плавает». Этот же файл (product-page.css)
   грузится ТОЛЬКО на is_product() (Exposhop_Product_Page::enqueue_
   assets()) — здесь безопасно давать медиа-запросы на общий
   `.woocommerce ul.products`, каталог эти правила не увидит вообще
   (свой брейкпоинт уже есть в catalog.css, не пересекается).
   Волна 7 (25.07.2026), решение Вакхтанга: было 921px→2 колонки,
   544px→1 колонка — на практике 2 разных мобильных устройства
   (iPhone/Android с разными реальными шириной вьюпорта) попадали по
   разные стороны от 544px и получали РАЗНОЕ число колонок, отсюда
   ощущение «то 1 колонка с длинным скроллом, то сплюснутая строка».
   Убран брейкпоинт 544px — теперь ровно 2 состояния: >921px = 4
   колонки, ≤921px = 2 колонки ВСЕГДА, независимо от конкретной
   ширины телефона. */
@media (max-width: 921px) {
  .woocommerce ul.products,
  .woocommerce-page ul.products {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }
}
.woocommerce ul.products li.product,
.woocommerce-page ul.products li.product {
  width: auto !important;
  max-width: 100%;
  min-width: 0;
}

/* ================================================================
   Единая система бейджей на товарной странице — РЕШЕНИЕ 25.07.2026
   (редизайн по макету, пп.2-3): убрать зелёный (--exo-green, №131),
   применить ту же геометрию/цвета, что в каталоге (1.8.58,
   catalog.css). Токены --esc-* там объявлены внутри
   body.exposhop-catalog{} — на этой странице того body-класса нет
   (Exposhop_Catalog::add_body_class() сознательно не покрывает
   is_product()), поэтому значения здесь хардкод, тот же приём и то же
   обоснование, что уже применено в video-badge.css.

   Два независимых места: (1) бейдж самого товара — WooCommerce core
   печатает .onsale на woocommerce_before_single_product_summary@10,
   якорь позиционирования — div.product (position:relative, живой
   замер подтвердил, что div.product и галерея делят один и тот же
   верхний левый угол); .out-of-stock-badge/.esc-badge-preorder —
   новый рендерер Exposhop_Badges::render_single_status_badge() (см.
   class-exposhop-badges.php), тот же приоритет ровно один бейдж уже
   гарантирован там (sale подавляется в sale_flash() независимо от
   цикла). (2) бейджи внутри .related.products — та же разметка, что
   в каталоге (.astra-shop-thumbnail-wrap, подтверждено живым DOM),
   просто без body.exposhop-catalog в селекторе. ---- */
.single-product div.product .onsale,
.single-product div.product .out-of-stock-badge,
.single-product div.product .esc-badge-preorder,
.related.products .onsale,
.related.products .out-of-stock-badge,
.related.products .esc-badge-preorder {
  position: absolute !important;
  top: 8px !important;
  left: 8px !important;
  right: auto !important;
  bottom: auto !important;
  z-index: 3 !important;
  width: auto !important;
  min-height: 0 !important;
  min-width: 0 !important;
  max-width: max-content !important;
  font-size: 11px !important;
  font-weight: 700 !important;
  letter-spacing: .04em !important;
  text-transform: uppercase !important;
  line-height: 1.2 !important;
  padding: 4px 8px !important;
  margin: 0 !important;
  white-space: nowrap !important;
  border-radius: 3px !important;
}
.single-product div.product .onsale,
.related.products .onsale {
  background: #d00072 !important; /* --esc-accent */
  color: #fff !important;
}
.single-product div.product .out-of-stock-badge,
.related.products .out-of-stock-badge {
  background: #fff !important;
  color: #0a0907 !important; /* --esc-text-1 */
}
.single-product div.product .esc-badge-preorder,
.related.products .esc-badge-preorder {
  background: #3A6EA5 !important; /* --esc-preorder */
  color: #fff !important;
}

/* ---- Отступы вкладок и блока рассрочки — источник №131.
   #tbc-credit-block/#credo-credit-block из исходного правила НЕ
   перенесены — проверено на ~50 живых товарах, 0 совпадений везде,
   мёртвая разметка (заменена на data-role="tbc-payment"/"credo-payment",
   уже стилизовано в этом файле отдельно). .exps-inst — живой класс
   (подтверждён на живом товаре), перенесён.
   ЗАВИСИМОСТЬ ОТ №130: --exo-space/--exo-space-sm. ---- */
/* Волна 6 (25.07.2026): margin-top:18px было мало для реального
   визуального разрыва, а margin-bottom Astra давала ~68px (свой
   дефолт, не наш) — обе цифры перебиты ниже, в едином блоке
   ритма секций (см. .exps-bundle-related/.related.products/
   .woocommerce-tabs дальше в файле) — это правило больше не
   единственный источник отступа, оставлено 0, чтобы не спорить. */
.single-product .woocommerce-tabs {
  margin-top: 0 !important;
  margin-bottom: 0 !important;
}
.single-product .summary .exps-inst {
  margin-top: var(--exo-space-sm) !important;
}

/* ---- НАЙДЕНО В РЕГРЕССИИ ЭТАПА 3, не было в исходной таблице
   адресатов Этапа 1: №131's мобильный блок «сайдбар — убрать на
   планшете/мобайле» селектором `body.woocommerce #primary,
   body.woocommerce-page #primary{width/max-width/flex:100%!important}`
   (@media ≤921px) матчится не только на checkout/account/cart
   (единственные зоны, отмеченные в аудите) — is_product() тоже даёт
   тело body.woocommerce, поэтому товарная страница ТОЖЕ теряла эту
   защиту при деактивации №131. checkout/cart/account уже безопасны —
   их собственный #primary там переопределён в service-pages.css с
   max-width:100%!important независимо. Товар — нет, закрыто здесь,
   дословно из источника. ---- */
@media (max-width: 921px) {
  body.woocommerce #primary,
  body.woocommerce-page #primary {
    width: 100% !important;
    max-width: 100% !important;
    flex: 0 0 100% !important;
  }
}

/* ================================================================
   Редизайн страницы товара по макету (Product Page.dc.html) —
   25.07.2026, docs/tasks/product-page-redesign-task.md. Всё ниже —
   НОВЫЕ правила (элементы, которых раньше не касался ни один снипет
   в этом файле) — сверено с реальным DOM отдельным прогоном
   (docs/product-page-diff.md), а не угадано. Токены — хардкод-хекс
   там, где селектор не под body.exposhop-catalog (тот же приём, что
   в video-badge.css и в блоке бейджей выше).
   ================================================================ */

/* ---- Общий layout: галерея/инфо — сейчас float-раскладка Astra
   (div.product{display:inline-block}, .summary{float:right}), в
   макете — CSS grid 1fr/1fr, gap 56px. Оба прямых ребёнка div.product
   подтверждены живым DOM (.woocommerce-product-gallery и .summary —
   родитель у обоих буквально div.product, не промежуточная обёртка). */
.single-product div.product {
  display: grid !important;
  grid-template-columns: 1fr 1fr;
  gap: 56px;
  /* align-items:start — иначе grid по умолчанию (stretch) растягивает
     галерею на всю высоту строки (= высота колонки .summary, обычно
     заметно выше самого фото за счёт таб/рассрочки под колонкой) —
     живой баг найден при проверке видео-капсулы --single: bottom:12px
     считался от невидимого низа растянутого контейнера, а не от
     фото, капсула улетала на ~1000px вниз. */
  align-items: start;
}
.single-product div.product > .woocommerce-product-gallery,
.single-product div.product > .summary.entry-summary {
  float: none !important;
  width: 100% !important;
}
@media (max-width: 921px) {
  .single-product div.product {
    grid-template-columns: 1fr;
    gap: 24px;
  }
}
/* Волна 10 (25.07.2026) — ИСПРАВЛЕНА ОШИБКА АТРИБУЦИИ из Волны 9:
   источник margin-bottom:2em (=34px) — НЕ Astra, а WooCommerce CORE,
   подтверждено через CDP CSS.getMatchedStylesForNode (задание явно
   потребовало этот метод, не угадывание): побеждающее правило —
   `.woocommerce-js div.product div.summary{margin-bottom:2em}`,
   specificity (0,3,3). Волна 9 обнулила этот margin ТОЛЬКО на
   мобильном (@media max-width:921px) — решив мобильный симптом
   (гигантский нижний padding), но правило WC core применяется на
   ЛЮБОЙ ширине, включая десктоп, где его никто не трогал — отсюда
   раздутый зазор Summary→Cross-sells на 1440px (90px вместо ожидаемых
   ~56, разница — ровно эти же 34px). Убрано отсюда, перенесено ниже
   БЕЗ media-запроса (действует везде) — тот же селектор из Волны 9
   (.single-product div.product > .woocommerce-product-gallery/
   .summary.entry-summary, specificity 0,4,1 — четыре класса против
   трёх у WC core, побеждает без !important, но он уже был у
   исходного правила — оставлен для гарантии, WC core тоже не
   использует !important, но лучше не полагаться на голую
   специфичность при следующей правке рядом). */
.single-product div.product > .woocommerce-product-gallery,
.single-product div.product > .summary.entry-summary {
  margin-bottom: 0 !important;
}

/* ---- H1 — размер/вес по макету, шрифт Manrope (НЕ serif — решение
   от 24.07.2026, см. корневой CLAUDE.md). Грузинский — системный
   фолбэк, как везде на сайте (тот же стек, что --esc-sans в
   catalog.css, хардкод — токен вне скоупа этой страницы). ---- */
.single-product div.product .summary .product_title {
  font-family: 'Manrope', 'Noto Sans Georgian', -apple-system, BlinkMacSystemFont, system-ui, sans-serif !important;
  font-size: 30px !important;
  font-weight: 600 !important;
  line-height: 1.25 !important;
  color: #0a0907 !important;
  margin-bottom: 16px !important;
  /* 25.07.2026, Волна 2 (product-page-redesign-task.md v2): было
     по центру (Astra WC-compat даёт text-align:center на H1 по
     умолчанию) — макет требует левый край. */
  text-align: left !important;
}

/* ---- Порядок блоков в правой колонке — РЕШЕНИЕ 25.07.2026 (Волна 2):
   макет — title→price→short_desc→trust→add_cart→consult→credit.
   Реально было — Astra's Customizer-опция single-product-structure
   даёт title→short_desc→price→add_cart (проверено `wp eval astra_get_
   option()`), а trust/credit/consult довешены отдельными add_action
   на woocommerce_single_product_summary — совсем другой уровень
   контроля. Переставлять через remove_action/приоритеты НЕВОЗМОЖНО
   безопасно для trust-бейджей: сниппет №60 регистрирует свой вывод
   анонимной замыкающей функцией (`add_action('woocommerce_single_
   product_summary', function(){...}, 35)`) — у анонимных замыканий
   нет объекта-адреса, которым можно было бы адресовать remove_action
   снаружи файла, где они объявлены (штатное ограничение WP hooks
   API, не наша недоработка). Пере ставить их можно только правкой
   самого сниппета — вне периметра git-репозитория плагина.
   Решение — визуальный порядок чисто через flex+order на .summary,
   не трогая ни один хук/сниппет: все 7 блоков — реально прямые дети
   .summary.entry-summary (подтверждено живым DOM), безопасно и
   обратимо одним файлом. */
.single-product div.product .summary.entry-summary {
  display: flex;
  flex-direction: column;
}
.single-product div.product .summary.entry-summary > .product_title { order: 1; }
.single-product div.product .summary.entry-summary > .price { order: 2; }
.single-product div.product .summary.entry-summary > .woocommerce-product-details__short-description { order: 3; }
.single-product div.product .summary.entry-summary > .exps-under-btn { order: 4; }
.single-product div.product .summary.entry-summary > form.cart { order: 5; }
.single-product div.product .summary.entry-summary > .exps-consult-btn { order: 6; }
.single-product div.product .summary.entry-summary > .exps-inst { order: 7; }

/* ================================================================
   КРИТИЧЕСКИЙ БАГ, найден в Волне 3 (25.07.2026, product-page-
   redesign-task-v3.md): табы/cross-sells (№78)/related — НЕ
   siblings div.product, как предполагалось в задании («секции после
   div.product»), а РЕАЛЬНЫЕ прямые дети div.product (подтверждено
   живым DOM: div.product children = .onsale, .woocommerce-product-
   gallery, .summary.entry-summary, .woocommerce-tabs, .exps-bundle-
   related, .related.products — ровно 6, макет WooCommerce, где
   woocommerce_after_single_product_summary стреляет ДО закрытия
   </div> самого div.product, не после). Волна 1 включила на
   div.product `display:grid;grid-template-columns:1fr 1fr` для
   галереи/summary — но не ограничила остальных детей, поэтому таб/
   cross-sell/related тоже стали grid-item'ами по 1 колонке и
   автоматически расползлись по строкам сетки ПО ДВА В РЯД (ровно
   баг из доклада — табы и cross-sells бок о бок). grid-column:1/-1
   растягивает каждую секцию на всю ширину (обе колонки), order —
   тот же приём, что на .summary выше, задаёт порядок по макету
   (cross-sells → табы → related) НЕ трогая ни один хук/сниппет —
   те же причины, что и в Волне 2 (№78/anonymous-closure-подобные
   ограничения снипетов вне репозитория). ================================================================ */
.single-product div.product > .woocommerce-tabs,
.single-product div.product > .exps-bundle-related,
.single-product div.product > .related.products {
  grid-column: 1 / -1;
  width: 100%;
}
.single-product div.product > .exps-bundle-related { order: 1; }
.single-product div.product > .woocommerce-tabs { order: 2; }
.single-product div.product > .related.products { order: 3; }

/* ---- Галерея — фикс искажения (найдено попутно, не в самом
   макете): было object-fit:fill на главном фото И на thumbnails —
   реальное растяжение/сжатие пропорций, хуже запрещённого правилом
   1.2 обрезания. object-fit:contain + однотонный фон под letterbox
   (тот же принцип, что у карточек каталога — правило 1.3 корневого
   CLAUDE.md). Соотношение — по пропорции макета (636×480 ≈ 4:3),
   через aspect-ratio, а не фиксированный px — колонка на сайте не
   зафиксирована в 1440px, как в самом .dc.html. ---- */
.single-product .woocommerce-product-gallery__wrapper {
  border-radius: 16px;
  overflow: hidden;
  background: #cfcecb; /* ≈--esc-card-bg */
}
.single-product .woocommerce-product-gallery__image.flex-active-slide {
  aspect-ratio: 4 / 3;
}
.single-product .woocommerce-product-gallery__image img {
  width: 100% !important;
  height: 100% !important;
  object-fit: contain !important;
}
.single-product .flex-control-thumbs {
  display: grid !important;
  grid-template-columns: repeat(4, 1fr) !important;
  gap: 12px !important;
  margin-top: 16px !important;
}
.single-product .flex-control-thumbs li {
  width: auto !important;
  height: auto !important;
  /* 25.07.2026, Волна 4 (10 точечных правок): было 1/1 (квадрат) —
     ошибочно перенесено по аналогии с каталогом («квадрат обязателен»
     — то решение про карточки каталога, НЕ про thumbnails товара).
     В макете thumbnails прямоугольные: height:90px фикс., width не
     задан явно — вычисляется из грида (4 колонки, gap 12px, контейнер
     636px = ширина главного фото при 1440px макета) → (636-3×12)/4 =
     150px. 150/90 = 5/3 — используем ratio, не px, страница не
     зафиксирована в 1440px. */
  aspect-ratio: 5 / 3;
  border-radius: 10px;
  border: 1px solid #dfdedb; /* ≈--esc-border */
  overflow: hidden;
  background: #cfcecb;
}
.single-product .flex-control-thumbs li img {
  width: 100% !important;
  height: 100% !important;
  object-fit: contain !important;
}

/* ---- Хлебные крошки — разделитель »→› чинится у источника (Yoast
   SEO фильтр, см. class-exposhop-product-page.php::breadcrumb_
   separator() — тут только типографика). ---- */
.single-product .breadcrumb-trail,
.single-product .breadcrumb-trail a {
  font-size: 13px;
  color: #646360; /* ≈--esc-text-3 */
}
.single-product .breadcrumb-trail a {
  text-decoration: none;
}
.single-product .breadcrumb-trail a:hover {
  text-decoration: underline;
}
.single-product .breadcrumb-trail .breadcrumb_last {
  color: #0a0907; /* ≈--esc-text-1 */
  font-weight: 600;
}

/* ---- Волна 4 (25.07.2026), пп.1-2:
   1) Разделитель под шапкой — в макете border-bottom:1px solid
      oklch(0.9 0.004 90) на второй строке хедера (лого+меню), у
      реального .site-header сейчас 0 (проверено computed — Astra
      далее ничего не рисует по низу хедера на этом сайте).
   2) Отступ шапка→крошки — реальный источник НЕ сами крошки (у них
      padding-top:0, проверено), а `.ast-woocommerce-container{padding-
      top:90.78px}` — штатный отступ Astra для страниц WooCommerce
      (Customizer), задуман под контент без собственных верхних
      отступов. Уменьшен до 20px по макету (padding крошек в самом
      .dc.html: `padding:20px 56px 0`). ---- */
.single-product .site-header {
  border-bottom: 1px solid #dfdedb; /* ≈--esc-border */
}
.single-product .ast-woocommerce-container {
  /* Не 20px буквально: у Astra есть ЕЩЁ одно правило выше по дереву —
     `.content-area.primary{margin-top:-30px}` (найдено живым замером,
     не в этом файле — тянет весь контент-блок вверх на 30px,
     компенсируя его же padding-top:90.78px чуть меньше, чем полностью,
     что и давало исходные ~60px зазора). 20px (padding) − 30px
     (внешний margin) дал бы -10px — заголовок и крошки перекрылись
     бы. 50px компенсирует margin и оставляет ровно 20px по макету. */
  padding-top: 50px !important;
  /* Волна 5 (25.07.2026), п.1 — источник «маленького фото»: Astra
     даёт этому контейнеру padding-left/right:113.39px (живой замер,
     Customizer-настройка WooCommerce-контейнера, не наша) поверх и
     без того урезанного общего #primary (у темы max-width:1240px на
     .ast-container, сайт-wide — НЕ трогаем, затронуло бы все
     страницы). Итог — контент товара был всего 973px при вьюпорте
     1440px, вдвое ýже, чем подразумевает макет (1440-112=1328px при
     56px паддингах с обеих сторон). Уменьшено до тех же 56px, что и в
     .dc.html — при 1240-колонке даёт 1128px контента (меньше 1328
     макета, но это уже данность сайт-wide ширины темы, не трогаем
     отдельно ради этой страницы), фото за счёт этого заметно крупнее.
     Только ДЕСКТОП (min-width:922px, брейкпоинт проекта — корневой
     CLAUDE.md): без медиа-запроса 56px×2 на вьюпорте 390px съедали
     29% ширины экрана — живая регрессия, найдена и исправлена в этой
     же волне при обязательной мобильной проверке (Astra's
     113.39px — тоже, скорее всего, не применяется буквально на
     мобильном, у темы обычно свой respons-путь; наш !important без
     медиа-запроса перебивал бы его на всех ширинах без разбора). */
}
@media (min-width: 922px) {
  .single-product .ast-woocommerce-container {
    padding-left: 56px !important;
    padding-right: 56px !important;
    /* Волна 10 (25.07.2026) — найдено через CDP CSS.getMatchedStylesForNode
       (задание явно потребовало этот метод): `.ast-separate-container
       .ast-woocommerce-container{padding:5.34em 6.67em}` — тема задаёт
       ОДНИМ shorthand все 4 стороны сразу; Волны 5/8 переопределили
       top/left/right по отдельности, но НИКОГДА не трогали bottom —
       он молча оставался на театральном 90.78px (5.34em), раздувая
       зазор Related→Footer на десктопе. Обнулено здесь же, тем же
       приёмом. */
    padding-bottom: 0 !important;
  }
  /* Второе, отдельное от .ast-woocommerce-container: сам #primary тоже
     нёс margin-bottom:68px (=4em). Найдено через тот же CDP-запрос —
     три конкурирующих правила на #primary, побеждает `.ast-separate-
     container #primary, .ast-separate-container.ast-left-sidebar
     #primary, .ast-separate-container.ast-right-sidebar #primary{
     margin:4em 0;padding:0}` (Astra) — margin-top у него же перебит
     ДРУГИМ, более специфичным правилом (`.site .site-content #primary
     {margin-top:-30px}`, уже учтено в Волне 4 через компенсацию
     padding-top на woocommerce-container), а margin-BOTTOM никем не
     тронут — молча оставался 68px, это и есть вторая половина
     раздутого зазора Related→Footer (90.78+68=158.78 ≈ измеренные
     158.8px до этой волны). */
  .single-product #primary {
    margin-bottom: 0 !important;
  }
}

/* ---- Табы — сейчас 0 правил вообще (проверено — Astra отдаёт их
   без единого стиля активного/неактивного состояния), полная
   стилизация по макету. Реальные классы — description_tab/
   additional_information_tab/reviews_tab на <li>, не угадано. ---- */
.single-product .woocommerce-tabs ul.tabs {
  display: flex;
  gap: 32px;
  margin: 0 0 28px;
  padding: 0 0 16px;
  border-bottom: 1px solid #dfdedb; /* ≈--esc-border */
  list-style: none;
}
.single-product .woocommerce-tabs ul.tabs li {
  margin: 0 !important;
  padding: 0 !important;
  background: none !important;
  border: 0 !important;
}
.single-product .woocommerce-tabs ul.tabs li a {
  font-size: 14px !important;
  font-weight: 700 !important;
  color: #646360 !important; /* ≈--esc-text-3, неактивный */
  text-decoration: none;
  display: inline-block;
  padding-bottom: 16px;
  margin-bottom: -17px;
  border-bottom: 2px solid transparent;
}
/* Волна 11 (25.07.2026) — найдено через CDP-аудит по всем элементам
   макета (product-page-redesign-task-v11.md): единственное реальное
   расхождение из ~20 проверенных — цвет табов проигрывал WooCommerce
   core (`.woocommerce-js div.product .woocommerce-tabs ul.tabs li a
   {color:#515151}`, specificity 0,3,4 — на один тип-селектор длиннее
   нашего 0,3,3 при равном числе классов, тай-брейк по типам).
   !important — тот же приём, что и везде в этом файле против той же
   природы конфликта. Остальные ~19 проверенных категорий (H1, цена,
   кнопки, галерея, крошки, карточки, бейдж и т.д.) уже совпадали с
   макетом точно — сплошной !important-reset всего файла не
   потребовался. */
.single-product .woocommerce-tabs ul.tabs li.active a {
  color: #d00072 !important; /* ≈--esc-accent, активный */
  border-bottom-color: #d00072 !important;
}
.single-product .woocommerce-tabs .woocommerce-Tabs-panel {
  font-size: 15px;
  line-height: 1.8;
  color: #2f2e2b; /* ≈--esc-text-2 */
}

/* ---- Кнопка «Консультация по этой модели» — новый элемент,
   PHP-рендер class-exposhop-product-page.php::render_consult_button(),
   выведена после кнопки «В корзину» на woocommerce_single_product_
   summary@35. Outline-стиль по макету, отличается от .toggle-desc
   (тот же visual language, что и «Читать полностью» в описании —
   тоже outline/text-1, случайное совпадение с макетом, не копия
   правила). ---- */
.exps-consult-btn {
  display: block;
  width: 100%;
  box-sizing: border-box;
  margin: 14px 0 0;
  border: 1px solid #0a0907; /* ≈--esc-text-1 */
  background: #fff;
  color: #0a0907;
  font-weight: 700;
  font-size: 14px;
  font-family: inherit;
  padding: 15px 0;
  border-radius: 8px;
  text-align: center;
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.exps-consult-btn:hover {
  background: #0a0907;
  color: #fff;
}

/* ================================================================
   Волна 2 (25.07.2026) — доработка по расхождениям со скриншотов,
   docs/tasks/product-page-redesign-task-v2.md. Инвентаризация
   сниппетов ПЕРЕД правками (обязательный первый шаг задания):
   - №60 «Блок Доверия на странице продукта» — trust-бейджи
     (.exps-under-btn/.exps-delivery/.exps-checklist), УЖЕ хукнут и
     УЖЕ рендерится на странице товара (не «отсутствует», как
     предполагало задание) — anonymous closure на woocommerce_single_
     product_summary@35, поэтому не трогаем хук (см. блок order выше),
     только типографика ниже.
   - №78 «Сопутствующие товары» — cross-sell «бандлы» (.exps-bundle-
     related/.exps-bundle-title), woocommerce_after_single_product_
     summary@15, показывается ТОЛЬКО для 3 триггер-категорий (кровати/
     основания/межкомнатные двери) — не универсальный cross-sell для
     любого товара, это осознанная особенность сниппета, не баг.
   - №50 «Сокращение описания товара» — .toggle-desc/«Read More»,
     the_content@99, текст кнопки хардкод БЕЗ переводов вообще.
   - №128 «Краткое описание» — .exps-specs (буллет-параметры) —
     формат зависит от того, есть ли `/.../ ` разделитель в реальном
     тексте short_description конкретного товара — контентный вопрос,
     не CSS/PHP, по заданию не трогаем.
   ================================================================ */

/* ---- Trust-бейджи (№60) — РЕШЕНИЕ ВАКХТАНГА 25.07.2026 (Волна 3):
   привести под макет — 3 пункта в одну строку, без отдельной строки
   доставки. Правка контента через CSS-скрытие (безопаснее правки
   сниппета №60 вне репозитория плагина, по явному указанию задания):
   .exps-delivery целиком, четвёртый <li> в .exps-checklist
   («Доставка по всей Грузии» — идёт последним в массиве $bullets
   сниппета, порядок в DOM фиксирован, :last-child адресует его
   надёжно независимо от языка). ---- */
.single-product .exps-delivery {
  display: none;
}
.single-product .exps-checklist li:last-child {
  display: none;
}
.single-product .exps-checklist li {
  /* цвет — НЕ здесь: перебивал бы более специфичным селектором цвет
     из макета, заданный в базовом .exps-checklist li выше (Волна 4) —
     оставлен только шрифт, единственное, что этому правилу нужно. */
  font-family: 'Manrope', 'Noto Sans Georgian', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
}

/* ---- Toggle-desc / «Читать полностью» (№50) — было сплошная
   заливка --exo-green (тот же .toggle-desc, что и About/GEO-модуль,
   поэтому скоуп .single-product обязателен — не трогать общий
   класс). Outline по макету. Текст «Read More» — хардкод в PHP
   сниппета БЕЗ переводов (проверено чтением кода №50) — правится тем
   же приёмом, что переводы в checkout.css: font-size:0 скрывает
   родной текстовый узел, ::after показывает переведённый по :lang(). ---- */
.single-product .toggle-desc {
  background: #fff !important;
  color: #0a0907 !important; /* ≈--esc-text-1 */
  border: 1px solid #0a0907 !important;
  border-radius: 8px !important;
  padding: 12px 24px !important;
  font-size: 0 !important; /* скрывает родной текстовый узел "Read More" */
}
.single-product .toggle-desc:hover {
  background: #0a0907 !important;
  color: #fff !important;
  transform: none !important;
}
.single-product .toggle-desc::after {
  font-size: 13px;
  font-weight: 700;
  content: "Read more";
}
:lang(ka) .single-product .toggle-desc::after {
  content: "სრულად ნახვა";
}
:lang(ru) .single-product .toggle-desc::after {
  content: "Читать полностью";
}

/* ---- Заголовки секций related/cross-sell — эйброу+хедлайн по
   макету. Разметка обеих секций даёт только ОДИН <h2> с готовым
   текстом (Reсomended-заголовок №78 через PHP-конфиг бандла;
   стандартный WooCommerce related-заголовок — через фильтр
   woocommerce_product_related_products_heading, см. class-exposhop-
   product-page.php) — эйброу-строка над ним физически не может быть
   частью того же текстового узла, добавлена как ::before (тот же
   приём, что перевод toggle-desc выше и заголовки в checkout.css). ---- */
/* Ритм между тремя секциями (cross-sell/табы/related) — Волна 6
   (25.07.2026): было margin-top:48px ДОПОЛНИТЕЛЬНО к padding-top:48px
   на каждой секции (96px), а div.product и без того grid с
   gap:56px — секции получали 56+96=152px разрыва, вдвое больше
   макета (там ритм — padding-bottom предыдущего блока 48 + border 1
   + padding-top следующего 48 = 97px). Табы теперь тоже участвуют в
   этом едином ритме (были отдельным легаси-правилом margin-top:18px,
   см. выше) — все три секции получают одинаковую border-top +
   padding-top, БЕЗ отдельного margin-top (56px даёт сама сетка). */
.single-product .exps-bundle-related,
.single-product .related.products,
.single-product .woocommerce-tabs {
  margin-top: 0 !important;
  /* !important обязателен на padding-top: у Astra есть собственное
     .woocommerce-tabs{padding-top:34px} той же/выше специфичности —
     без него побеждало оно (найдено живым замером — border-top
     применялся, а padding-top молча оставался 34px). */
  padding-top: 40px !important;
  border-top: 1px solid #dfdedb; /* ≈--esc-border */
}
.single-product .exps-bundle-title,
.single-product .related.products > h2 {
  font-family: 'Manrope', 'Noto Sans Georgian', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  font-size: 24px;
  font-weight: 800;
  color: #0a0907;
  margin: 0 0 28px;
}
/* Волна 7: .exps-bundle-title (не .related h2 — там после заголовка
   сразу сетка, 28px уже верно совпадает с макетом) идёт перед строкой
   .exps-bundle-links, которой нет в макете — уменьшено здесь же. */
.single-product .exps-bundle-title {
  margin-bottom: 12px;
}
.single-product .exps-bundle-title::before,
.single-product .related.products > h2::before {
  display: block;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #d00072; /* ≈--esc-accent */
  margin-bottom: 10px;
}
.single-product .exps-bundle-title::before {
  content: "Дополните покупку";
}
:lang(ka) .single-product .exps-bundle-title::before { content: "შეავსეთ შენაძენი"; }
:lang(en) .single-product .exps-bundle-title::before { content: "Complete the purchase"; }
.single-product .related.products > h2::before {
  content: "Похожие модели";
}
:lang(ka) .single-product .related.products > h2::before { content: "მსგავსი მოდელები"; }
:lang(en) .single-product .related.products > h2::before { content: "Similar models"; }

/* Ссылки-категории бандла (.exps-bundle-links, №78) — были без
   стиля вообще (наследуют дефолт браузера/темы). Этого ряда нет в
   макете вообще (там сразу эйброу→хедлайн→сетка) — это дополнительный
   контент самого сниппета №78, контент не убираем, но его margin-
   bottom (Волна 7, 25.07.2026) уменьшен: было 20px, вместе с
   margin-bottom заголовка (28px) и высотой самой строки давало
   ~78.6px между заголовком и первой карточкой вместо ~28px в
   макете — теперь ~44px, ближе к макету при сохранении ряда ссылок. */
.single-product .exps-bundle-links {
  margin-bottom: 12px;
  font-size: 13px;
  color: #646360; /* ≈--esc-text-3 */
}
.single-product .exps-bundle-link {
  color: #646360;
  text-decoration: underline;
}
.single-product .exps-bundle-sep {
  margin: 0 8px;
}
.single-product .exps-bundle-sep:last-child {
  display: none;
}

/* ---- Карточки related/bundle — рамка по макету (было — без рамки,
   разметка идентична каталожной, .astra-shop-thumbnail-wrap
   подтверждено живым DOM в Волне 1). Колонки/gap уже 4/24px из
   существующего правила `.woocommerce ul.products{grid-template-
   columns:repeat(4,...)!important}` — оно уже покрывает оба грида
   (общий body-класс woocommerce), здесь только рамка + кнопка. ---- */
.single-product .related.products li.product,
.single-product .exps-bundle-related li.product {
  border: 1px solid #dfdedb; /* ≈--esc-border */
  border-radius: 8px;
  overflow: hidden;
}
.single-product .related.products .add_to_cart_button,
.single-product .exps-bundle-related .add_to_cart_button {
  background: #fff !important;
  color: #0a0907 !important; /* ≈--esc-text-1 */
  border: 1px solid #0a0907 !important;
}
.single-product .related.products .add_to_cart_button:hover,
.single-product .exps-bundle-related .add_to_cart_button:hover {
  background: #fdf0f6 !important; /* лёгкий розовый тинт, как hover мини-кнопок макета */
  color: #d00072 !important;
  border-color: #d00072 !important;
}

/* Волна 7 (25.07.2026), видео-кнопка на карточках cross-sell/related —
   скрыть ТОЛЬКО на мобильном (≤921px, брейкпоинт проекта), не на
   главном товаре: на 2-колоночной карточке ~170px шириной капсула
   (88×34px, см. video-badge.css) — треть ширины фото, ломает
   восприятие карточки. На главном фото товара капсула НЕ трогается
   ни на каком размере экрана (задание явно: остаётся и на десктопе,
   и на мобильном) — селектор ниже спефичично адресует только карточки
   ВНУТРИ этих двух секций (.exps-video-badge без --single), сама
   капсула --single синтаксически другой класс и этим правилом не
   заденется даже без явного исключения. */
@media (max-width: 921px) {
  .single-product .related.products .exps-video-badge,
  .single-product .exps-bundle-related .exps-video-badge {
    display: none !important;
  }
}

/* ---- Волна 8 (25.07.2026) — «шапка и тело разной ширины», причина
   найдена, временный overflow-x:hidden из Волны 7 убран (по прямому
   указанию задания).
   На странице ДВА разных DOM-узла с классом .ast-container — один
   оборачивает шапку, другой оборачивает контент (прямой предок
   #primary). На ДЕСКТОПЕ (1440px) у обоих padding:0 20px, max-width:
   1240px — идентичны. На МОБИЛЬНОМ (390px) у шапки — по-прежнему
   0 20px (контент шапки начинается на x:20). У контентного —
   padding-left:9.18px (не круглое число, адаптивный расчёт Astra,
   отличный от шапки), а ВНУТРИ него ещё один слой —
   .ast-woocommerce-container — добавляет СВОИ +17px. Итог: контент
   начинался на x:26.2 (9.18+17) вместо x:20 у шапки — ~6px
   рассогласования на каждый край, ровно то, что выглядело как
   «шапка и тело разной ширины».
   ПЕРВАЯ ПОПЫТКА фикса (приравнять внешний .ast-container к 20px)
   была ошибочной — не учла второй вложенный слой: 20+17=37px, УВЕЛИЧИЛ
   расхождение с шапкой (было 6.2px, стало 17px) вместо того, чтобы
   его убрать. Правильный фикс — обнулить паддинг ВНЕШНЕГО контейнера
   на мобильном, оставив ровно один слой отступа (внутренний, уже
   близкий к 20px: 17px, разница всего 3px — на порядок меньше
   исходных 6.2/17px). Ни одно правило в этом файле раньше не
   трогало ни один из этих контейнеров — не наш код, только фикс. */
@media (max-width: 921px) {
  .single-product #content > .ast-container {
    padding-left: 0 !important;
    padding-right: 0 !important;
  }
}

/* ---- Волна 14 (25.07.2026) — добивает остаточные 3px из Волны 8:
   шапка (`.ast-primary-header-bar{padding:20px}`, подтверждено живьём
   и на логотипе слева, и на гамбургере справа — оба ровно 20px от
   края) vs тело (`.ast-woocommerce-container` — свой, ДРУГОЙ,
   некруглый дефолт Astra, 17px, никогда не трогался на мобильном).
   Всё вложенное (div.product/галерея/крошки/summary/H1) само по себе
   НЕ добавляет своего отступа — все они замерены с ТЕМИ ЖЕ 17px, что
   и сам .ast-woocommerce-container (подтверждено живьём: одинаковые
   left/right у всех пятерых) — контейнера с исходным 17px было
   достаточно, отдельного «фото без падинга» не было. Приравнено к
   шапке — 20px на оба края. */
@media (max-width: 921px) {
  .single-product .ast-woocommerce-container {
    padding-left: 20px !important;
    padding-right: 20px !important;
    /* box-sizing/width добавлены Волной 16 — контейнер сам задаёт
       границы контента (width:100% его собственного родителя +
       паддинг внутрь через border-box, не поверх). */
    box-sizing: border-box !important;
    width: 100% !important;
  }
}

/* ================================================================
   Волна 8, п.3 — карточки cross-sell/related ДОЛЖНЫ выглядеть как в
   каталоге. Правило проекта: не переписывать заново, использовать те
   же значения, что уже работают в catalog.css (не изобретать заново).
   Все catalog.css-правила для карточек скопом висят на
   `body.exposhop-catalog` (Exposhop_Catalog::add_body_class() — этот
   класс сознательно НЕ ставится на is_product(), см. class-exposhop-
   catalog.php) — файл catalog.css вдобавок физически не грузится на
   товарной странице (enqueue условие — своё, отдельное для каждого
   модуля), так что даже сними я тело-класс, сами правила были бы
   недоступны. Плюс структурная разница: карточки каталога используют
   СОБСТВЕННУЮ разметку модуля (.esc-card__image, рендерит
   Exposhop_Catalog::render_card_image()) — related/cross-sell здесь
   используют ЧИСТУЮ разметку WooCommerce/Astra по умолчанию
   (.astra-shop-thumbnail-wrap оборачивает <img> напрямую, БЕЗ
   промежуточного .esc-card__image) — те же ЗНАЧЕНИЯ (aspect-ratio,
   object-fit, шрифты, цвета — буквально те же числа/токены-константы,
   что в catalog.css) переносятся на реальный здесь селектор, не
   изобретаются заново. Найдена и попутно исправлена реальная порча
   фото: .astra-shop-thumbnail-wrap img здесь был object-fit:fill —
   ТА ЖЕ РАСТЯЖКА, что чинилась для главного фото в Волне 1, просто
   не была перенесена на карточки related/cross-sell тогда. ================================================================ */
.single-product .related.products .astra-shop-thumbnail-wrap,
.single-product .exps-bundle-related .astra-shop-thumbnail-wrap {
  position: relative;
  aspect-ratio: 1 / 1;
  background: #cfcecb; /* ≈--esc-card-bg, тот же токен, что и главное фото/каталог */
  overflow: hidden;
  margin: 0 0 12px;
}
.single-product .related.products .astra-shop-thumbnail-wrap img,
.single-product .exps-bundle-related .astra-shop-thumbnail-wrap img {
  width: 100% !important;
  height: 100% !important;
  object-fit: contain !important; /* было fill — искажало фото, как когда-то главное фото до Волны 1 */
  object-position: center !important;
}
.single-product .related.products .woocommerce-loop-product__title,
.single-product .exps-bundle-related .woocommerce-loop-product__title {
  font-family: 'Manrope', 'Noto Sans Georgian', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  font-size: 14px !important; /* было 17px — как в catalog.css до правки специфичности там же */
  font-weight: 600;
  line-height: 1.24 !important;
  color: #2f2e2b; /* ≈--esc-text-2 */
  margin: 0 0 8px !important;
}
.single-product .related.products .price,
.single-product .exps-bundle-related .price {
  font-family: 'Manrope', 'Noto Sans Georgian', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  font-size: 17px !important;
  font-weight: 800 !important;
  color: #0a0907 !important; /* ≈--esc-text-1, было Astra-дефолтный #3a3a3a */
  margin: 0 0 12px !important;
}
.single-product .related.products .price del,
.single-product .exps-bundle-related .price del {
  color: #646360; /* ≈--esc-text-3 */
  font-weight: 400;
  opacity: .8;
}
.single-product .related.products li.product,
.single-product .exps-bundle-related li.product {
  padding: 12px;
  box-sizing: border-box;
}

/* ================================================================
   Волна 9 (25.07.2026) — «гигантский нижний padding» на мобильном.
   Метод — визуальный (задание): full-page скриншот на 390px (webkit),
   найдена одна явная зона — пустое пространство МЕЖДУ последним рядом
   related-карточек и футером (Copyright…). Числами (getBoundingClientRect):
   90.65px — заметно больше остальных межсекционных зазоров на этой же
   странице (24-58px). Источник — НЕ related.products (её собственные
   padding-bottom/margin-bottom — оба 0, проверено), а ДВА разных
   Astra-контейнера ВЫШЕ по дереву, суммарно:
   `.ast-woocommerce-container{padding-bottom:22.67px}` (не круглое
   число, тот же адаптивный расчёт Astra, что уже чинился для padding-
   top в Волне 5/8) + `#primary{padding-bottom:68px}` — ЭТОГО второго
   на ДЕСКТОПЕ у #primary вообще нет (0px, проверено живьём на 1440px,
   задание подтверждает «десктоп — ОК») — мобильно-специфичное
   Astra-правило, вероятно рассчитанное на блог/архивные шаблоны, не
   на карточку товара. 22.67+68=90.67 ≈ ровно измеренный зазор. Не наш
   код — обнулено только на мобильном, десктоп не тронут. ================================================================ */
@media (max-width: 921px) {
  .single-product .ast-woocommerce-container {
    padding-bottom: 0 !important;
  }
  .single-product #primary {
    padding-bottom: 0 !important;
  }
}

/* ================================================================
   Волна 12 (25.07.2026) — RESET-эксперимент по прямому запросу:
   отступы между блоками на десктопе продолжают репортиться как
   проблема через несколько задач подряд, несмотря на то, что CDP
   (Волны 10-11) находил и точечно чинил каждый конкретный источник
   (WooCommerce core margin-bottom:2em на .summary, Astra padding/
   margin-shorthand на .ast-woocommerce-container/#primary), и живой
   computed после каждой правки подтверждал целевые числа. Раз
   проблема продолжает воспроизводиться на стороне Вакхтанга — здесь
   не «ещё один источник», а МАКСИМАЛЬНО ГРУБЫЙ, безусловный оверрайд
   поверх всего предыдущего: полная цепочка предков в селекторе (body
   class → #primary → .ast-woocommerce-container → div.product → сам
   элемент), !important на ВСЕХ box-model свойствах разом (margin,
   padding — все 4 стороны explicit, не shorthand, чтобы ни одна
   сторона не могла унаследовать чужое значение через shorthand-partial
   override). Если после этого блока проблема останется —
   правки в этом файле точно ни при чём (доказательство методом
   исключения, не итерация вслепую), и картина, которую видит
   Вакхтанг, идёт из другого источника (браузерный кэш конкретного
   устройства, другой домен/среда, JS после этого CSS). ================================================================ */
body.single-product #primary .ast-woocommerce-container div.product {
  margin-top: 0 !important;
  margin-bottom: 0 !important;
  margin-left: 0 !important;
  margin-right: 0 !important;
}
body.single-product #primary .ast-woocommerce-container div.product > .woocommerce-product-gallery,
body.single-product #primary .ast-woocommerce-container div.product > .summary.entry-summary {
  margin-top: 0 !important;
  margin-bottom: 0 !important;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}
/* Волна 13 (25.07.2026): padding-top уменьшен 40px→24px по прямому
   решению (значение теперь ЗДЕСЬ, не в отдельном блоке Волны 13 ниже
   по файлу — то правило проигрывало этому же самому правилу Волны 12,
   у которого выше специфичность за счёт #primary в цепочке селектора;
   правка value на месте, а не второй конкурирующий слой, чтобы
   больше не создавать самому себе таких войн специфичности). */
body.single-product #primary .ast-woocommerce-container div.product > .exps-bundle-related,
body.single-product #primary .ast-woocommerce-container div.product > .woocommerce-tabs,
body.single-product #primary .ast-woocommerce-container div.product > .related.products {
  margin-top: 0 !important;
  margin-bottom: 0 !important;
  padding-top: 24px !important;
  border-top: 1px solid #dfdedb !important;
}
/* padding-bottom различается: табы — 0 (последнее — не последнее,
   но контент таба сам даёт свой отступ), cross-sell/related — 12px
   (решение Волны 13). */
body.single-product #primary .ast-woocommerce-container div.product > .woocommerce-tabs {
  padding-bottom: 0 !important;
}
body.single-product #primary .ast-woocommerce-container div.product > .exps-bundle-related,
body.single-product #primary .ast-woocommerce-container div.product > .related.products {
  padding-bottom: 12px !important;
}
@media (min-width: 922px) {
  body.single-product #primary .ast-woocommerce-container div.product {
    gap: 56px !important;
  }
}

/* ================================================================
   Волна 13 (25.07.2026) — три слоя пустоты под секциями на десктопе,
   найдены Вакхтангом через DevTools (не CDP-поиском этой сессии —
   ни один из трёх раньше не проверялся отдельно, каждый — реальная,
   независимая находка, проверено живым computed перед правкой):
   1) `li.ast-article-single` (карточки товаров — Astra-класс, стоит
      на КАЖДОЙ карточке в cross-sell И related одинаково) —
      margin-bottom:42.5px, наш Волна 8 `li.product{padding:12px}`
      этого свойства не касался вообще.
   2) padding-top:40px на секциях (.exps-bundle-related/.woocommerce-
      tabs/.related.products) — НАШ собственный (Волна 6), уменьшен
      здесь по прямому решению, не был «лишним» источником, а
      кандидатом на уменьшение.
   3) `ul.products.columns-3`/`.columns-4` (WooCommerce core class,
      реальный — оба варианта живьём подтверждены: cross-sell/№78
      выводит columns-3, related — columns-4) — margin-bottom:17px.
   Плюс подстраховка на .ast-woocommerce-container/#primary — оба уже
   0 с Волны 10, продублировано здесь же для целостности одного
   решения одним блоком.

   Пункт 2 (padding-top/bottom секций) НЕ здесь: писал его сюда
   изначально с селектором `body.single-product section.exps-bundle-
   related` и т.п. — оказалось, ПРОИГРЫВАЕТ собственному правилу
   Волны 12 (`body.single-product #primary .ast-woocommerce-container
   div.product > .exps-bundle-related`, есть #primary в цепочке — ID
   бьёт любое число классов независимо от !important на обеих
   сторонах). Не стал держать два конкурирующих блока с разными
   значениями — актуальные 24px/12px правятся прямо в блоке Волны 12
   выше по файлу, здесь эта правка была бы мёртвым кодом. ================================================================ */
body.single-product li.ast-article-single {
  margin-bottom: 0 !important;
}
body.single-product ul.products.columns-3,
body.single-product ul.products.columns-4 {
  margin-bottom: 0 !important;
}
body.single-product .ast-woocommerce-container {
  padding-bottom: 0 !important;
}
body.single-product #primary {
  margin-bottom: 0 !important;
}

/* ================================================================
   Волна 16 (25.07.2026) — замена костылей Волны 15 (overflow-x:hidden/
   max-width:100% россыпью по предкам) на решение у источника.

   Корень (реальный, не гипотетический): на мобильном div.product —
   `grid-template-columns:1fr` (Волна 1). В CSS Grid ширина трека 1fr
   всё равно не может стать МЕНЬШЕ автоматического минимума grid-item'а
   (по умолчанию — max-content его содержимого), если явно не обнулить
   min-width. Из-за этого достаточно широкого по intrinsic-контенту
   ребёнка (широкое фото товара до применения object-fit-бокса, длинная
   строка без переноса и т.п.), чтобы раздуть весь трек — отсюда и
   зависимость «одни фото ок, другие нет» из жалобы.

   Решение — на мобильном div.product не grid, а flex-column, НЕ
   display:block: в задании предлагался block, но в этом файле order
   на прямых детях div.product (Волна 3: bundle-related=1, tabs=2,
   related=3 — визуально переставляет местами исходный DOM-порядок,
   где tabs идёт ПЕРЕД bundle-related) — order работает только в
   flex/grid-контейнере, в block игнорируется молча. display:block
   откатил бы порядок секций к исходному DOM (tabs→bundle-related)
   — реальная регрессия проверенного поведения, не просто гипотетическая:
   проверено ниже воспроизведением текущего мобильного скриншота.
   flex-column даёt то же самое главное свойство, что и block (ширина
   ребёнка = 100% контейнера по умолчанию, без per-item costylей) —
   для column-direction flex ширина это cross-axis, который не подвержен
   min-width:auto/max-content квирку (тот квирк — про main-axis), — и
   при этом сохраняет order. */
@media (max-width: 921px) {
  body.single-product div.product {
    display: flex !important;
    flex-direction: column !important;
    width: 100% !important;
    box-sizing: border-box !important;
  }
  body.single-product div.product > * {
    box-sizing: border-box !important;
    width: 100% !important;
  }
}

/* Легитимный overflow:hidden оставлен только на .flex-viewport — это
   вьюпорт карусели FlexSlider, её .wrapper ВСЕГДА шире контейнера по
   механике (все слайды в ряд), обрезка снаружи это штатный паттерн, не
   костыль. Max-width на нём убран — с исправленным div.product он
   получает 100% ширины по умолчанию (block-level ребёнок), явно
   задавать нечего. */
body.single-product .woocommerce-product-gallery .flex-viewport {
  overflow: hidden !important;
}
/* img{max-width:100%} — стандартная практика, оставлено (задание
   явно требует не убирать). Остальные костыли Волны 15
   (overflow:hidden/max-width на .woocommerce-product-gallery и
   .flex-control-thumbs, overflow-x:hidden на цепочке предков) —
   удалены: с фиксом у источника (div.product) они ничего больше не
   сдерживали, единственный источник правды на контейнмент теперь один. */
body.single-product .woocommerce-product-gallery__image img {
  max-width: 100% !important;
}

/* ================================================================
   Волна 18 (25.07.2026) — кнопка «შეკვეთა» на карточках «нет в
   наличии» в cross-sell/related. Живой DOM (карточка outofstock,
   проверено на реальном товаре post-39723): WooCommerce для outofstock
   САМ подменяет обычную add-to-cart ссылку (класс `add_to_cart_button
   ajax_add_to_cart`, aria-label «Add to cart») на простую ссылку на
   страницу товара (класс — просто `button product_type_simple`, БЕЗ
   add_to_cart_button/ajax_add_to_cart, aria-label «Узнать больше»)
   — то есть кликом в корзину она и так ничего не добавляет уже
   сейчас. Проблема оказалась не в функции, а в подписи: грузинский
   перевод строк WooCommerce «Add to cart» и «Read more» — ОБА
   «შეკვეთა», визуально неотличимы, отсюда ощущение «активная кнопка
   заказа на недоступном товаре». Скрываю (не делаю серой — серая
   «შეკვეთა» только усилила бы путаницу формулировки; переход на
   страницу товара остаётся через фото/заголовок карточки, этот
   дубль-линк не нужен). `.add_to_cart_button` в реальном DOM на
   outofstock не встречается (WooCommerce не ставит этот класс для
   этого состояния) — оставлен селектором про запас, без вреда. */
body.single-product li.outofstock .button,
body.single-product li.outofstock .add_to_cart_button {
  display: none !important;
}
