/* ================================================================
   Exposhop Catalog — WooCommerce archive pages (shop / product
   category / product taxonomy). Restyles these to match the
   homepage's visual language; scoped to body.exposhop-catalog (set
   by Exposhop_Catalog::add_body_class(), only on the archive types
   this module targets) rather than :root, so these tokens can't
   leak into or collide with Astra's or another plugin's globals.

   Source: design/Catalog Page.dc.html — its H1 typeface (Noto Serif
   Georgian) is NOT followed: serif was deliberately removed from the
   whole site in an earlier round and stays removed here. The H1 uses
   --esc-sans instead, matching the homepage's section headings.
   ================================================================ */

body.exposhop-catalog {
  /* ---- Text grays — 3 tiers, converted from the mockup's oklch
     values (OKLab reference matrices; low chroma ~0.005 so these
     read as near-neutral warm grays, not tinted). Cross-checked
     against the mockup live in task 2 — see the border/gray note
     below if any of these get corrected. */
  --esc-text-1: #0a0907; /* oklch(0.14 0.005 90) — headings, prices */
  --esc-text-2: #2f2e2b; /* oklch(0.30 0.005 90) — body text, product names, nav labels */
  --esc-text-3: #646360; /* oklch(0.50 0.005 90) — breadcrumbs, counts, muted labels */

  /* ---- Borders — the mockup actually uses three weights, not two;
     task 4's follow-up caught that only two had been captured here,
     which is why price-field/checkbox borders read too pale on
     staging — they'd been pointed at --esc-border (the lightest tier,
     meant for dividers) instead of the darker tier the mockup
     actually uses for those controls. */
  --esc-border:         #dfdedb; /* oklch(0.90 0.004 90) — section/sidebar dividers */
  --esc-border-strong:  #cfcecb; /* oklch(0.85 0.004 90) — price/text-input fields */
  --esc-border-control: #afaeab; /* oklch(0.75 0.004 90) — checkbox/swatch borders (mockup's darkest, most visible tier) */

  /* ---- Accent — same value as the homepage's --accent. Kept as its
     own token so this module has no hard dependency on .exo (the
     homepage shortcode's scope) being present on the page. */
  --esc-accent: #d00072;

  /* ---- Preorder badge — новый токен 24.07.2026 (docs/tasks/task-
     badges-video-button.md, Этап 1/2). Голубой, вариант 2 из трёх
     предложенных (docs/badges-video-etap1-report.md) — приглушённый
     стальной синий, не спорит с --esc-accent, контраст с белым
     текстом ≈5.6:1 (проходит WCAG AA). */
  --esc-preorder: #3A6EA5;

  /* ---- Font — same stack as the homepage's --sans, declared fresh
     here for the same self-containment reason as --esc-accent above.
     Manrope/Noto Sans Georgian aren't enqueued anywhere in this
     plugin (not even for the homepage) — they're assumed to already
     load site-wide at the theme level; verify on a live archive page
     that the H1 actually renders in Manrope, not a system-font
     fallback. */
  --esc-sans: 'Manrope', 'Noto Sans Georgian', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;

  /* ---- Product card background ----
     Полосатый плейсхолдер макета (--esc-stripe-1/2, ниже — оставлены
     только как исторический архив значений, больше нигде не
     используются) ОТМЕНЁН решением Вакхтанга (правило 1.3, CLAUDE.md):
     фон карточки — только однотонный, белый или светло-серый, не
     полосатый/пёстрый. Возвращать стрипы больше не планируется — этот
     блок раньше советовал обратное, исправлено 24.07.2026.

     Правка дизайна 24.07.2026 (docs/card-image-background-plan.md):
     --esc-card-bg переведён с плоского белого (совпадал с фоном
     страницы — зона изображения читалась как отсутствие фона, а не
     как белый фон) на #cfcecb — тот же тон, что уже существующий
     --esc-border-strong (рамка полей ввода в сайдбаре), вариант 2 из
     трёх предложенных, выбран Вакхтангом по итогам сравнения. */
  --esc-stripe-1: #ebe7de; /* архив, не используется */
  --esc-stripe-2: #f7f5f0; /* архив, не используется */
  --esc-card-bg: #cfcecb;

  /* ---- Radii ---- */
  --esc-radius-card:        14px; /* desktop product card */
  --esc-radius-card-mobile: 12px; /* mobile product card */
  --esc-radius-control:     6px;  /* buttons, inputs, pagination */
  --esc-radius-control-lg:  8px;  /* mobile filter-trigger button, filter-drawer CTA */
}

/* ================================================================
   Task 2 — category header + breadcrumbs. CSS only: no HTML/markup
   changes anywhere below (H1, description, breadcrumb structure,
   URLs, pagination all stay exactly as WooCommerce/Astra render
   them) — this file only ever restyles what's already there.
   ================================================================ */

/* ---- Breadcrumbs (Astra's existing .breadcrumb-trail markup) ---- */
body.exposhop-catalog .breadcrumb-trail,
body.exposhop-catalog .breadcrumb-trail a {
  font-family: var(--esc-sans);
  font-size: 13px;
  color: var(--esc-text-3);
}
body.exposhop-catalog .breadcrumb-trail a {
  text-decoration: none;
}
body.exposhop-catalog .breadcrumb-trail a:hover {
  text-decoration: underline;
}
/* Last crumb (current page) — dark + bold. .trail-end is confirmed
   correct: Astra's actual source (checked directly, v4.13.6 —
   Astra_Breadcrumb_Trail::trail() in
   inc/addons/breadcrumbs/class-astra-breadcrumb-trail.php) marks the
   final <li> with exactly this class. */
body.exposhop-catalog .breadcrumb-trail .trail-end {
  color: var(--esc-text-1);
  font-weight: 700;
}
/* Separator — two earlier attempts at this (a CSS ::before guess, then
   two different PHP filter guesses) turned out to be based on
   incomplete information. Astra's actual source confirms the
   separator is generated as plain CSS from a dynamically-built
   stylesheet: .trail-items li::after { content: "<separator>"; }
   (see dynamic-css/dynamic.css.php, "Breadcrumb Separator" section) —
   driven by a Customizer option (default \00bb, literally "»",
   matching the reported bug exactly), not a filter or a template arg.
   Overriding it here, in a rule that's guaranteed to load as part of
   this plugin's own stylesheet (not dependent on Astra's dynamic CSS
   possibly being file-cached), is the reliable fix; !important is
   necessary since Astra's own rule targets this exact same selector.
   li:last-of-type already gets its own separator hidden by Astra
   (display:none on its ::after) — untouched, still hidden. */
body.exposhop-catalog .trail-items li::after {
  content: '›' !important;
}

/* ---- H1 — WooCommerce core's own class from archive-product.php;
   text/markup untouched, presentation only. Character matched to the
   homepage's section headings (.exo h1/h2/.../h5: 800 weight, sans),
   not to the mockup's serif treatment (see the file header note). ---- */
body.exposhop-catalog .woocommerce-products-header__title.page-title {
  font-family: var(--esc-sans);
  font-size: 38px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--esc-text-1);
  margin: 14px 0 14px;
}
@media (max-width: 640px) {
  body.exposhop-catalog .woocommerce-products-header__title.page-title {
    font-size: 26px;
  }
}

/* ---- Category/shop description — .term-description (category/tag
   archives) and .page-description (shop root), both from WooCommerce
   core's woocommerce_archive_description() output. HTML untouched. ---- */
body.exposhop-catalog .term-description,
body.exposhop-catalog .page-description {
  font-family: var(--esc-sans);
  font-size: 15px;
  line-height: 1.7;
  color: var(--esc-text-2);
  max-width: 760px;
}
body.exposhop-catalog .term-description strong,
body.exposhop-catalog .page-description strong {
  color: var(--esc-text-1);
}
@media (max-width: 640px) {
  body.exposhop-catalog .term-description,
  body.exposhop-catalog .page-description {
    font-size: 13px;
  }
}

/* ---- Header block bottom border — full content width, no extra
   markup needed since .woocommerce-products-header is already a
   block-level element spanning the content column. ---- */
body.exposhop-catalog .woocommerce-products-header {
  border-bottom: 1px solid var(--esc-border);
  padding-bottom: 32px;
}

/* ================================================================
   Task 3 — product card in the archive loop.

   Card markup changes go through WooCommerce's own hooks (see
   Exposhop_Catalog::maybe_override_loop_hooks()/render_product_image())
   — only the image thumbnail is rewrapped, because WC's default
   output there is a bare <img> with no container to hang a
   fixed-height striped background on. .onsale, the <h2> title, .price,
   and the add-to-cart button/link all stay WooCommerce's own markup
   and hooks — restyled here, not replaced.
   ================================================================ */

/* ---- Grid ----
   было в catalog.css: grid-template-columns: repeat(3, 1fr); gap: 28px 24px —
   заменено фактическим из №110 при реконсиляции (minmax(270px,1fr) не
   растягивается на всю ширину #primary на реальном рендере — grid
   оставляет свободное место справа, это факт текущего вида, не баг
   этой правки). */
/* РЕКОНСИЛЯЦИЯ №110, второй проход: у №110 (секция «5. Сетка товаров»)
   ВСЕ свойства этого правила были с !important, включая align-items —
   реальное значение на проде start, не stretch (проверено computed +
   замером высоты карточек в ряду: все карточки в ряду сегодня одной
   высоты несмотря на align-items:start — это li.product's собственный
   height:100% сам подгоняет карточку под высоту ряда, align-items тут
   визуально ничего не меняет, но для точного computed-паритета
   значение всё равно заменено на факт). */
body.exposhop-catalog ul.products {
  clear: both !important;
  display: grid !important;
  grid-template-columns: repeat(3, minmax(270px, 1fr)) !important;
  /* Правка дизайна 24.07.2026 (docs/catalog-fixes-plan.md, п.7): было
     24px (временное значение №110, деактивирован) — макет задаёт
     row/column раздельно, 28px 24px. Мобильный ≤921px гап (16px) не
     трогается этой правкой — там сетка уже 1-2 колонки, не 2, как в
     макете (структурное расхождение шире, чем "gap", вне объёма этой
     точечной правки — см. отчёт). */
  gap: 28px 24px !important;
  /* было в catalog.css: stretch — заменено фактическим из №110 (start);
     визуально идентично благодаря height:100% на li.product ниже. */
  align-items: start !important;
  list-style: none;
  margin: 0 !important;
  padding: 0 !important;
}
/* Neutralize WC core's own float/percentage-width column system
   (.columns-3 li.product { width:...; float:left; ... }) so it can't
   fight the grid track sizing above. display:flex + column here gives
   this element its row height (height:100%, matching the grid row's
   tallest sibling on mixed-height photo rows).
   ИСПРАВЛЕНО 24.07.2026: предыдущая версия этого комментария
   утверждала, что это позволяет кнопке "прижаться" к низу карточки
   через margin-top:auto — неверно, проверено живьём. .button лежит не
   прямо в li.product, а в .astra-shop-summary-wrap (обычный
   display:block, не flex) — margin-top:auto там резолвится в 0px,
   эффекта нет. Лишнее место от разницы высот в ряду оседает целиком
   ПОСЛЕ .astra-shop-summary-wrap, внизу карточки (см. .button ниже).
   РЕКОНСИЛЯЦИЯ №110, второй проход: width/max-width/min-width/
   justify-content/box-sizing были у №110 тоже (секция «6. Карточка
   товара»), пропущены в первом проходе — !important добавлен везде,
   где был у №110. */
body.exposhop-catalog ul.products li.product {
  width: 100% !important;
  max-width: 100% !important;
  min-width: 0 !important;
  float: none;
  margin: 0 !important;
  height: 100%;
  display: flex !important;
  flex-direction: column !important;
  justify-content: flex-start !important;
  position: relative; /* anchors .onsale */
  padding: 12px !important;
  background: #fff;
  box-sizing: border-box !important;
}
/* Планшет (922–1100px) — было пусто в catalog.css (сетка не имела
   отдельного правила на этом диапазоне, базовое 3-колоночное правило
   применялось бы без изменений); значение колонок из №110 при
   реконсиляции. gap на этом диапазоне не отличается от базового. */
@media (min-width: 922px) and (max-width: 1100px) {
  /* !important обязателен — база выше теперь тоже !important, иначе
     это переопределение проиграет. */
  body.exposhop-catalog ul.products {
    grid-template-columns: repeat(3, minmax(220px, 1fr)) !important;
  }
}
/* Мобильный (≤921px) — было пусто в catalog.css на этом диапазоне
   (только ≤640px ниже имел отдельное правило); значения из №110 при
   реконсиляции. */
@media (max-width: 921px) {
  /* !important обязателен на всех трёх свойствах — базовые правила
     выше теперь тоже !important. */
  body.exposhop-catalog ul.products {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: 16px !important;
  }
  body.exposhop-catalog ul.products li.product {
    padding: 10px !important;
  }
}
/* Малый мобильный (≤640px) — было в catalog.css: repeat(2, 1fr), gap
   20px 14px; заменено фактическим из №110 при реконсиляции — на этом
   диапазоне №110 схлопывает сетку в одну колонку (секция 15, отдельная
   от секции 14 выше). gap/padding не переопределяются здесь — остаются
   16px/10px, унаследованные из блока ≤921px. */
@media (max-width: 640px) {
  body.exposhop-catalog ul.products {
    grid-template-columns: 1fr !important;
  }
}

/* ---- Image container ----
   New wrapper div (render_product_image()) around WooCommerce's own
   <img> (untouched — same wc_get_product_thumbnail() output used for
   simple/variable products and the no-photo placeholder alike, so
   products without a photo fall back automatically, no extra code
   needed for that case).

   РЕКОНСИЛЯЦИЯ №110: было в catalog.css — сознательно НИКАКИХ width/
   height/object-fit на img (расчёт был на то, что размер миниатюры —
   забота WooCommerce/Astra, не этого файла). По факту №110 всё это
   время форсил width:100%/height:auto/object-fit:initial с
   !important, то есть замысел ниже никогда не был реализован на живом
   сайте — заменено фактическим значением при реконсиляции 2026-07,
   см. docs/catalog-render-baseline.md. Оригинальный абзац оставлен
   ниже для истории намерения (актуален для будущего редизайна, если
   решим вернуться к нерегулируемому размеру).

   Because nothing here constrains the img's width, a configured
   thumbnail size wider than the grid column it lands in (most likely
   on the 2-col mobile layout) will overflow and get clipped by this
   container's overflow:hidden — if that happens, it's the Astra/
   WooCommerce thumbnail-size setting to adjust, not a size rule to
   add back here.

   img gets display:block — an <img> is inline by default, which
   reserves a few pixels below it for the line box's descender; that
   phantom gap showed the container's striped background as a strip
   between the photo and the title. display:flex on the container
   alone doesn't prevent this on every browser/scenario, so it's set
   directly on the img too, still with no size properties. */
/* .astra-shop-thumbnail-wrap: Astra's own wrapper around the whole
   image area (confirmed via its actual source while researching task
   5 — astra_woo_shop_thumbnail_wrap_start/_end() — it opens before
   .onsale/the out-of-stock span and closes after them, so both
   render inside it, not inside .esc-card__image, which is a separate,
   inner element). position:relative here is what those two badges
   actually anchor to; .esc-card__image gets the same treatment as its
   own anchor for whatever renders inside IT specifically (e.g. the
   video badge, if that's where it turns out to land — its real
   markup/position is still unconfirmed, so both candidate ancestors
   are covered rather than guessing which one is right). */
/* РЕКОНСИЛЯЦИЯ №110, второй проход: margin/aspect-ratio/overflow/
   min-height/height были у №110 тоже (секция «7. Фото товара»), все с
   !important — пропущены целиком в первом проходе. */
/* Правка дизайна 24.07.2026 (зона изображения — собственная высота,
   docs/card-image-background-plan.md + решение Вакхтанга по итогам
   сравнения трёх вариантов): margin-bottom 12px → 16px по макету
   (десктоп; мобильный 12px уже совпадал, не трогается). */
body.exposhop-catalog .astra-shop-thumbnail-wrap {
  position: relative !important;
  margin: 0 0 16px !important;
  aspect-ratio: auto !important;
  overflow: visible !important;
  min-height: 0 !important;
  height: auto !important;
}
@media (max-width: 640px) {
  body.exposhop-catalog .astra-shop-thumbnail-wrap {
    margin: 0 0 12px !important;
  }
}
/* Правка дизайна 24.07.2026: зона изображения получает собственную
   форму (aspect-ratio, не px-высоту — масштабируется пропорционально
   на любой ширине колонки, включая мобильный, без отдельного значения
   на брейкпоинт). Выбран квадрат 1:1 — см. docs/card-image-background-
   plan.md, сравнение трёх вариантов (210 / квадрат / 250 на реальной
   ширине колонки 246px, не 270 — 270 was an eyeballed assumption,
   270px is the grid track, 246px is what's left after li.product's
   12px padding on each side). Обрезки нет — object-fit:contain на img
   ниже, вписывание целиком с центрированием (правило 1.2, CLAUDE.md). */
body.exposhop-catalog .esc-card__image {
  position: relative; /* anchors whatever renders inside this element specifically — see .astra-shop-thumbnail-wrap above for the more common case */
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1 / 1;
  border-radius: var(--esc-radius-card);
  background: var(--esc-card-bg);
  padding: 0;
  margin-bottom: 0;
  overflow: hidden;
}
body.exposhop-catalog .esc-card__image img {
  display: block !important;
  width: 100% !important;
  height: 100% !important;
  max-height: none !important;
  /* было object-fit:initial (эквивалент fill — растяжение без
     сохранения пропорций; на практике не искажало, т.к. контейнер
     раньше был auto-высоты, точно под фото). Теперь контейнер имеет
     фиксированную форму (aspect-ratio выше) — object-fit:contain
     обязателен, чтобы вписать фото целиком без искажения/обрезки. */
  object-fit: contain !important;
  object-position: center !important;
  aspect-ratio: auto !important;
}
@media (max-width: 640px) {
  body.exposhop-catalog .esc-card__image {
    border-radius: var(--esc-radius-card-mobile);
    padding: 0;
  }
}

/* ---- Card links — RETROACTIVE FIX (found while researching task 5):
   Astra doesn't use one link around the whole card, contrary to what
   earlier tasks assumed. Its actual source (checked directly, v4.13.6
   — woocommerce-common-functions.php) shows two separate wrappers:
   .woocommerce-loop-product__link (WooCommerce core's own, unmodified
   — wraps only the thumbnail area, opened/closed by
   woocommerce_template_loop_product_link_open/_close) and
   .ast-loop-product__link (Astra's own addition, wraps only the
   title — astra_woo_woocommerce_template_loop_product_title()). They
   are siblings, not nested, each inside its own wrapper
   (.astra-shop-thumbnail-wrap / .astra-shop-summary-wrap). The title
   hover-color rule below was targeting the image's link, which never
   contains the title, so it never fired — fixed to target the title's
   own link instead. Both links get the same cursor/color/underline
   reset. ---- */
body.exposhop-catalog ul.products a.woocommerce-loop-product__link,
body.exposhop-catalog ul.products a.ast-loop-product__link {
  display: block;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}

/* ---- Title — WooCommerce's own <h2>, text/markup untouched. Long
   Georgian names need to wrap rather than overflow (same pattern
   used for product names on the homepage). ---- */
/* РЕКОНСИЛЯЦИЯ №110, второй проход: у №110 (секция «9. Название») ВСЕ
   пять свойств группы были с !important — первый проход перенёс
   только word-break и без !important. min-height/margin/overflow-wrap
   значениями совпадали и так, но без !important рисковали проиграть
   что-то ещё после ухода №110 (тот же класс проблемы, что нашёлся у
   .price — см. ниже); line-height отличался (1.25 вместо факта 1.24). */
body.exposhop-catalog .woocommerce-loop-product__title {
  font-family: var(--esc-sans);
  /* Правка дизайна 24.07.2026 (docs/catalog-fixes-plan.md, п.2): !important
     добавлен — без него проигрывал по специфичности теме Astra
     (.woocommerce-js ul.products li.product .woocommerce-loop-product__title,
     .woocommerce-page ul.products li.product .woocommerce-loop-product__title
     {font-size:1em}, специфичность 0,4,2 против наших 0,2,1 — подтверждено
     живой проверкой через CSS.getMatchedStylesForNode, тот же класс
     проблемы, что и у .price ниже). Раньше рендерился 17px вместо
     заданных здесь 14px. */
  font-size: 14px !important;
  font-weight: 600;
  /* было в catalog.css: 1.25 без !important — заменено фактическим из
     №110 (1.24, !important) */
  line-height: 1.24 !important;
  min-height: 2.9em !important; /* reserves 2 lines, so a 1-line title doesn't pull the price/button above it up */
  color: var(--esc-text-2);
  margin: 0 0 8px !important;
  text-wrap: balance;
  overflow-wrap: anywhere !important;
  word-break: break-word !important;
  transition: color .15s ease;
}
body.exposhop-catalog ul.products a.ast-loop-product__link:hover .woocommerce-loop-product__title {
  color: var(--esc-accent);
}

/* ---- Price — WooCommerce's own .price markup untouched; the
   variable-product range ("59 ₾ – 93 ₾") already renders as one
   inline string via WC's own min–max markup, nothing extra needed to
   keep it on one line. display:block is needed here for min-height
   to take effect at all — .price is a <span> (inline) by default,
   and min-height on an inline element is a no-op. ---- */
/* РЕКОНСИЛЯЦИЯ №110, второй проход: первая попытка сменила только
   значения, не добавив !important. Пиксельная сверка стейджинг↔прод
   показала реальный сбой — Astra's own `.woocommerce-js ul.products
   li.product .price{font-size:.9em}` (тема, относительный em) имеет ТУ
   ЖЕ специфичность, что и селектор №110, и без №110 побеждает наш
   плоский `body.exposhop-catalog .price` по специфичности (у Astra
   больше элементов в цепочке селектора). №110 сам держался только за
   счёт !important на display/min-height/line-height/margin — font-size/
   font-weight у него были БЕЗ !important, а побеждал он там за счёт
   специфичности/порядка, что нельзя надёжно воспроизвести здесь без
   более сложного селектора — поэтому здесь !important добавлен и на
   font-size/font-weight тоже, для гарантированного результата
   независимо от темы. */
body.exposhop-catalog .price {
  display: block !important;
  font-family: var(--esc-sans);
  /* Правка дизайна 24.07.2026 (docs/catalog-fixes-plan.md, п.3): было
     22px/700 — временное значение реконсиляции №110 (см. историю выше),
     №110 деактивирован (подтверждено `wp snippet list 110` — inactive
     на проде, отсутствует на стейджинге), блокировка снята. Возврат к
     макетным 17px/800 (`docs/catalog-mockup-spec.md`). */
  font-size: 17px !important;
  font-weight: 800 !important;
  min-height: 2.2em !important; /* a del+ins sale-price row and a plain price row take the same space */
  color: var(--esc-text-1);
  margin: 0 0 12px !important;
  line-height: 1.28 !important;
}
@media (max-width: 921px) {
  /* Правка дизайна 24.07.2026: было 18px (временное значение №110),
     макет задаёт 15px на мобильном. */
  body.exposhop-catalog .price {
    font-size: 15px !important;
  }
}
body.exposhop-catalog .price del {
  color: var(--esc-text-3);
  font-weight: 400;
  opacity: .8;
}
body.exposhop-catalog .price ins {
  text-decoration: none;
}

/* ---- Add-to-cart / "select options" button — WooCommerce's own
   link/text (incl. its i18n for variable vs simple products)
   untouched, pink fill removed for a black outline. !important on
   color/background/border only, to reliably beat whatever
   specificity Astra's/WC's own button styling has on this exact
   element — not used anywhere else in this file.

   ИСПРАВЛЕНО 24.07.2026 (расследование п.4 плана правок): предыдущая
   версия этого комментария утверждала, что margin-top:auto прижимает
   кнопку к низу li.product's флекс-колонки. Проверено живьём (Playwright,
   computed margin-top) — это НЕ так: .button лежит не прямо в li.product,
   а внутри .astra-shop-summary-wrap, который сам НЕ flex (обычный
   display:block, без своего CSS-правила в этом файле вообще) — margin-
   top:auto внутри block-контекста не резолвится в push-to-bottom, а
   просто в 0px (подтверждено computed). Реальный эффект height:100% на
   li.product в смешанном по высоте фото ряду — свободное место оседает
   ПОСЛЕ .astra-shop-summary-wrap целиком (под кнопкой, в самом низу
   карточки), а не над кнопкой. margin-top:auto был декоративным, эффекта
   не имел — не переносится в правку ниже. */
/* РЕКОНСИЛЯЦИЯ №110 (историческая, неактуальна после деактивации №110 —
   см. docs/catalog-fixes-plan.md, п.4): у №110 (секция «11. Кнопка», два
   правила — .button и отдельно a.button) ВСЕ перечисленные свойства
   были с !important. */
/* Правка дизайна 24.07.2026 (docs/catalog-fixes-plan.md, п.4): реверс к
   макетной модели — кнопка на всю ширину карточки, текст центрирован
   через text-align, а не inline-flex+min-width. */
body.exposhop-catalog ul.products .button {
  display: block !important;
  background: transparent !important;
  border: 1px solid var(--esc-text-1) !important;
  color: var(--esc-text-1) !important;
  border-radius: var(--esc-radius-control);
  font-family: var(--esc-sans);
  font-size: 13px;
  font-weight: 700;
  text-align: center;
  width: 100% !important;
  padding: 12px 0 !important;
  text-decoration: none;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
/* Hover: light pink fill, accent border + text (was a dark-fill/
   white-text inversion) — oklch(0.97 0.005 340) for the background,
   hex fallback via the same OKLab-matrix conversion used for the
   --esc-* tokens. */
body.exposhop-catalog ul.products .button:hover {
  background: #f8f4f6 !important; /* oklch(0.97 0.005 340) */
  border-color: var(--esc-accent) !important;
  color: var(--esc-accent) !important;
}

/* ---- Единый компонент бейджа карточки (Sale / Out-of-stock /
   Preorder) — 24.07.2026, docs/tasks/task-badges-video-button.md,
   Этап 2.1. Одна геометрия — один блок объявлений на три реальных
   селектора (разметку самих .onsale/.ast-shop-product-out-of-stock
   менять нельзя — они чужие, WC core и Astra; .esc-badge-preorder —
   наш собственный, рендерится Exposhop_Badges). Показывается ровно
   один бейдж одновременно (правило приоритета — см. Exposhop_Badges,
   подавляет sale_flash при outofstock/onbackorder) — поэтому все три
   могут безопасно жить в одном углу карточки.

   История геометрии (Реконсиляция №110): WC core's default CSS
   делает .onsale ~52px кругом с отрицательным top/left (задумано
   перекрывать край карточки) — вылезало за overflow:hidden
   .esc-card__image. !important на позиции гарантированно бьёт ядро
   независимо от специфичности. font-size/line-height/width/min-width/
   max-width/margin/white-space — фактические значения №110
   (секция «8. Sale badge»). */
body.exposhop-catalog ul.products .onsale,
body.exposhop-catalog ul.products .ast-shop-product-out-of-stock,
body.exposhop-catalog ul.products li.product.outofstock .stock.out-of-stock,
body.exposhop-catalog ul.products .out-of-stock-badge,
body.exposhop-catalog ul.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-family: var(--esc-sans) !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;
}
/* Цветовые модификаторы — единственное, чем бейджи отличаются друг от
   друга. !important обязателен на background/color: у Astra есть
   собственное правило `.woocommerce-js ul.products li.product
   .ast-shop-product-out-of-stock{background-color:rgba(255,255,255,.88)}`
   специфичностью выше нашей прежней версии (4 класса против 3) —
   без !important цвет не гарантирован (то rgba(255,255,255,.88)
   Astra, то унаследованный #fff текста родителя вместо чёрного)
   (docs/badges-video-etap1-report.md, находка 1.4). Требование 2
   задания: белый фон, чёрный текст — сплошной #fff (не Astra'вская
   rgba(.88), чтобы фон не просвечивал фото под бейджем). */
body.exposhop-catalog ul.products .onsale {
  background: var(--esc-accent) !important;
  color: #fff !important;
}
body.exposhop-catalog ul.products .ast-shop-product-out-of-stock,
body.exposhop-catalog ul.products li.product.outofstock .stock.out-of-stock,
body.exposhop-catalog ul.products .out-of-stock-badge {
  background: #fff !important;
  color: var(--esc-text-1) !important;
}
body.exposhop-catalog ul.products .esc-badge-preorder {
  background: var(--esc-preorder) !important;
  color: #fff !important;
}

/* ---- Video badge (.exps-video-badge) — позиция и статусные бейджи
   (.onsale/out-of-stock/preorder) больше не делят карточку на 3 угла:
   с правилом приоритета (Exposhop_Badges) статусный бейдж всегда один,
   поэтому видео теперь тоже переехало в угол по макету — bottom-left,
   а не top-right (Этап 2.5, 24.07.2026, docs/tasks/task-badges-video-
   button.md).

   ИСПРАВЛЕНО на Этапе 3 (живой замер на стейджинге): первая версия
   держала компенсацию 24px (12 макет + 12 паддинг li.product) по
   аналогии с top/right-фиксом 1.8.57 — но это была ошибка. У top/right
   компенсация сработала, потому что верх карточки ≈ верх фото (первый
   элемент в карточке). У bottom это НЕ так — низ li.product это низ
   ВСЕЙ карточки (после названия/цены/кнопки), а не низ фото; бейдж
   улетал на ~150px мимо цели. Правильный фикс — не пересчёт числа, а
   перенос самого рендера: PHP теперь печатает бейдж на
   woocommerce_before_shop_loop_item@9 (class-exposhop-video-badge.php)
   — тот же хук/приоритет, что у sale-flash, до того как Astra закрывает
   .astra-shop-thumbnail-wrap (@8 на after_shop_loop_item) — бейдж
   теперь ВЛОЖЕН в зону изображения, как остальные три бейджа.
   Компенсация паддинга не нужна вовсе — 12px по макету буквально. */
body.exposhop-catalog ul.products .exps-video-badge {
  position: absolute !important;
  bottom: 12px !important;
  left: 12px !important;
  top: auto !important;
  right: auto !important;
  z-index: 3 !important;
}

/* ---- Out-of-stock/preorder — геометрия и цвет теперь в едином
   компоненте бейджа выше (Этап 2.1, 24.07.2026); этот отдельный блок
   (позиция bottom-right, отдельная геометрия) удалён — дублировал и
   спорил с общим правилом. Бейдж «нет в наличии» теперь в том же углу,
   что и «акция»/«предзаказ» (top-left), по требованию задания «в том
   же месте, где бейдж акции». Видео-бейдж остаётся на top-right (не
   конфликтует — одновременно с ним в углу top-left всегда ровно один
   из трёх статусных бейджей, см. Exposhop_Badges — правило
   приоритета). ---- */

/* ---- Star rating — de-emphasized rather than removed; this is a
   judgment call (the brief left it open — "минимализм ... или
   согласовать отдельно"), easy to revisit if it should be hidden
   entirely instead. WooCommerce's own .star-rating markup untouched;
   its star glyphs scale with font-size. ---- */
body.exposhop-catalog ul.products .star-rating {
  font-size: 12px;
  color: var(--esc-text-3);
  margin: 0 0 6px;
}

/* ================================================================
   Task 4 — sidebar, archive container, card background.

   Styles WooCommerce's own sidebar widgets (price filter, layered
   nav/attribute filters) in place — no widget markup is rebuilt,
   only restyled, same as every other section of this file. Replaces
   rules that used to live in a separate, now-deactivated custom-CSS
   snippet. Cart and checkout pages are untouched: this whole file
   only ever loads on is_shop()/is_product_category()/
   is_product_taxonomy() (see Exposhop_Catalog::is_catalog_archive()).
   ================================================================ */

/* ---- 0б: archive container + sidebar/content columns ----
   #primary/#secondary are Astra's (and underscores-based themes'
   generally) own stable IDs for the content/sidebar split; .ast-container
   is Astra's own outer max-width wrapper class. This only overrides
   width/padding — it doesn't touch display/float, so whichever layout
   mechanism Astra is actually using (flex or float) for the
   primary/secondary split keeps working, just at these numbers
   instead of Astra's own. 921px is Astra's own default tablet
   breakpoint (not a value chosen by this file) — deliberately reused
   instead of introducing a second, conflicting breakpoint at 768px.
   !important only on the two rules most likely to lose a specificity
   fight against Astra's own generated layout CSS. */
/* РЕКОНСИЛЯЦИЯ №110, третий проход: width:100% был у №110 (секция «1.
   Контейнер архива»), все свойства с !important — пропущен целиком в
   первых двух проходах, обнаружено пиксельной сверкой стейджинг↔прод
   (primary/pagNav шире на проде на фиксированные ~140px). */
body.exposhop-catalog .ast-container {
  width: 100% !important;
  max-width: 1380px !important;
  margin-left: auto !important;
  margin-right: auto !important;
}
/* Мобильный (≤921px) — было пусто в catalog.css на этом диапазоне,
   значения из №110 при реконсиляции (секция «14. Мобильный», первая
   часть про .site-content > .ast-container). */
@media (max-width: 921px) {
  body.exposhop-catalog .site-content > .ast-container {
    display: block !important;
    width: 100% !important;
    max-width: 100% !important;
    padding-left: 16px !important;
    padding-right: 16px !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
  }
}
/* РЕКОНСИЛЯЦИЯ №110 (полный проход после первого неполного, см.
   docs/catalog-render-baseline.md и пиксельную сверку стейджинг↔прод):
   первая попытка перенесла только width — пропустив min-width/
   max-width у #secondary и width/min-width у #primary, оба были у
   №110 в той же группе свойств. Второй проход — построчно по
   оригиналу №110, секция «2. Сайдбар и контент — десктоп». */
body.exposhop-catalog #secondary {
  /* Правка дизайна 24.07.2026 (пункт 1 — раскладка сайдбар/каталог):
     было 250px с padding:0 60px 0 0 — 60px справа были мёртвым полем
     ДО разделителя (контент сайдбара заканчивался на 190px, граница
     сидела ещё на 60px правее), из-за чего между сайдбаром и каталогом
     была большая пустота, а не «вплотную с линией», как в макете.
     Ширина уменьшена (250→225), освободившиеся 30px переданы колонке
     каталога (см. #primary ниже, формула ширины). */
  width: 225px !important;
  min-width: 225px !important;
  max-width: 225px !important;
  flex-shrink: 0 !important;
  /* Внутренний отступ: 20px слева (фильтры больше не липнут к краю),
     16px справа (скромный отступ перед разделителем — было 60px). */
  padding-left: 20px !important;
  padding-right: 16px !important;
  /* margin-top — из Additional CSS кастомайзера (astra-2), Волна 6
     Пакет B (docs/tasks/task-wave6-tokens-customizer.md,
     docs/customizer-render-baseline.md). Источник: `.ast-separate-
     container.tax-product_cat/.archive.woocommerce/.post-type-
     archive-product #primary/#secondary{margin-top:1em}` — реально
     матчится только на catalog-cat/shop (эти же зоны и покрывает
     is_catalog_archive()), эталон подтверждает 17px, не буквальный
     1em. Без !important — в источнике его тоже не было, проверка
     B4 конкурентов не нашла. */
  margin-top: 17px;
  /* Правка дизайна 24.07.2026 (сравнение сайдбара с макетом): живая
     заливка серым была не своим правилом сайдбара, а фоном body темы
     (rgb(249,249,249)), просвечивающим через #secondary — у него
     самого фона нет и никогда не было, как и у #primary; #primary
     просто перекрыт непрозрачным .ast-woocommerce-container{background:
     #fff} (тема), а #secondary — ничем, отсюда видимая серая колонка.
     Фикс — тот же белый, что и у контента. */
  background: #fff;
}
/* Правка дизайна 24.07.2026: вертикальный разделитель по макету
   (border-right:1px solid oklch(0.9 0.004 90) = --esc-border). Тема
   Astra уже пытается это сделать (`.ast-left-sidebar #secondary{
   border-right:1px solid var(--ast-border-color)}`), но тут же гасит
   собственным более специфичным `.ast-separate-container.ast-left-
   sidebar #secondary{border:0}` (2 класса+ID против 1 класса+ID) —
   разделителя не было видно. Наш селектор здесь — 3 класса+ID,
   специфичность строго выше обоих правил темы, независимо от порядка
   загрузки. */
body.exposhop-catalog.woocommerce.ast-left-sidebar #secondary {
  border-right: 1px solid var(--esc-border);
}
body.exposhop-catalog #primary {
  /* Правка дизайна 24.07.2026 (пункт 1): было calc(100% - 280px)
     (250 secondary + 30 padding-left) — теперь calc(100% - 245px)
     (225 secondary + 20 padding-left), разница (35px) уходит в ширину
     колонки каталога. padding-left тоже уменьшен (30→20) — вплотную к
     разделителю, без лишнего зазора после линии. */
  width: calc(100% - 245px) !important;
  min-width: 0 !important;
  padding-left: 20px !important;
}
/* margin-top для #primary — отдельным правилом с усиленной
   специфичностью (2 класса вместо 1), НЕ в блоке выше. Найдено
   регрессией B7: у темы Astra есть собственное правило
   `.ast-separate-container.ast-left-sidebar #primary{margin-top:4em}`
   — тоже 2 класса + 1 ID, та же специфичность, что у исходного
   селектора astra-2 (`.ast-separate-container.tax-product_cat
   #primary`). Одноклассовый `body.exposhop-catalog #primary`
   проигрывает Astra (меньше классов, тип body не компенсирует —
   специфичность считается по классам раньше типов). Тот же приём,
   что и `.exposhop-catalog.woocommerce` для #131 (реконсиляция №110,
   см. ниже по файлу) — второй класс, а не !important, которого не
   было в источнике. #secondary не нуждается — у Astra для него нет
   2-классового конкурента (проверено). */
body.exposhop-catalog.woocommerce #primary {
  margin-top: 17px;
}
@media (min-width: 922px) and (max-width: 1100px) {
  /* РЕКОНСИЛЯЦИЯ №110, третий проход: min-width/max-width у #secondary
     и width у #primary были у №110 (секция «13. Планшет») тоже —
     пропущены в предыдущих проходах. Без min-width/max-width здесь
     базовые 250px!important (заданные выше) побеждали 220px, поскольку
     min-width всегда выигрывает у width при конфликте. */
  body.exposhop-catalog #secondary {
    width: 220px !important;
    min-width: 220px !important;
    max-width: 220px !important;
  }
  /* Правка дизайна 24.07.2026 (пункт 1): было calc(100% - 240px)/22px —
     тот же пересчёт, что на десктопе (220 secondary + 16 padding-left =
     236, было 240) — чуть теснее, планшетной ширины меньше. */
  body.exposhop-catalog #primary {
    width: calc(100% - 236px) !important;
    padding-left: 16px !important;
  }
}
/* Мобильный (≤921px) — было в catalog.css только display:none на
   #secondary и padding-left:0 на #primary. Заменено полным набором
   свойств из №110 (секция «14. Мобильный») при реконсиляции — #primary
   получил float/flex/width/max-width/min-width/margin, ранее не
   заданные вообще; #secondary — тот же набор плюс display:block.

   Селектор `body.exposhop-catalog` (1 класс) — специфичность (0,1,1),
   ровно как у активного №131 (`body.woocommerce #secondary{display:
   none!important}`, тоже 1 класс) — при ничьей выигрыш зависит от
   порядка загрузки и оказался нестабильным на практике (пиксельная
   сверка стейджинг↔прод поймала расхождение именно на этом свойстве,
   воспроизводимо на shop, не на category — вероятно, LiteSpeed
   по-разному комбинирует CSS для разных URL). Добавлен второй класс
   `.woocommerce` (body реально имеет оба класса на всех архивных
   страницах) — специфичность (0,2,1), гарантированно выше №131,
   независимо от порядка загрузки. Тот же приём, что и у №110
   (`.woocommerce.archive`). */
@media (max-width: 921px) {
  body.exposhop-catalog.woocommerce #primary,
  body.exposhop-catalog.woocommerce #secondary {
    display: block !important;
    float: none !important;
    flex: none !important;
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
  }
}
/* ---- Sidebar widget spacing — было пусто в catalog.css, значение
   из №110 при реконсиляции. ---- */
body.exposhop-catalog #secondary .widget {
  margin-bottom: 26px;
  /* padding — из «Разбора солянки №131/№132» (№132), подтверждено
     эталоном: матчится ТОЛЬКО на catalog-category, не даже на shop —
     не глобальное, дописано сюда напрямую. !important — дословно из
     источника (`#secondary .widget{padding:5px!important}`); без него
     проигрывает стороннему `.wpc_show_bottom_widget
     .widget_wpc_filters_widget{padding:0!important}` (плагин WPC
     Filters, свой брейкпоинт ≤768px) — найдено регрессией Этапа 3. */
  padding: 5px !important;
}

/* ---- Filter section spacing ----
   Real markup (confirmed in DevTools on staging): the sidebar's single
   WordPress widget (#wpc_filters_widget-14.widget_wpc_filters_widget)
   wraps a WPC Filters plugin UI, .wpc-filters-main-wrap, whose actual
   filter groups are .wpc-filters-section elements (title
   .wpc-filter-title + body .wpc-filter-content) — .widget/.widget-title
   are WordPress's own outer wrapper and only appear once, around the
   whole plugin UI, not per filter group, so the old .widget-based
   rules here never matched WPC's own internal structure. Selectors
   below aren't scoped under #secondary — catalog.js now moves
   #secondary .sidebar-main as a whole into .esc-filtersheet__body on
   open, so the same .wpc-filters-section/.wpc-filter-title/
   .wpc-filter-content elements need identical styling in both
   places. */
body.exposhop-catalog .wpc-filters-section {
  /* Правка дизайна 24.07.2026 (сравнение сайдбара с макетом): было
     28px — макет задаёт 36px между группами (ФАСИ/ФЕРИ/QVEYANA). */
  margin-bottom: 36px;
}
body.exposhop-catalog .wpc-filters-section:last-child {
  margin-bottom: 0;
}

/* ---- 1: filter section titles — !important since the WPC plugin
   ships its own default styling for .wpc-filter-title that this needs
   to reliably beat, same reasoning as the old Astra widget-title
   override (different opponent, same risk). ---- */
body.exposhop-catalog .wpc-filter-title {
  font-family: var(--esc-sans) !important;
  font-size: 12px !important;
  font-weight: 700 !important;
  letter-spacing: 0.06em !important;
  text-transform: uppercase !important;
  color: var(--esc-text-3) !important;
  /* Правка дизайна 24.07.2026: было 12px — макет даёт 20px под первым
     заголовком («ФАСИ») и 16px под остальными («ФЕРИ»/«QVEYANA»), сам
     макет не единообразен на 4px; выбрано единое 16px (совпадает с
     двумя группами из трёх) вместо копирования разнобоя. */
  margin: 0 0 16px !important;
}

/* ---- 2: price filter (WC_Widget_Price_Filter) ----
   #min_price/#max_price are real <input> elements — browsers don't
   support ::before/::after generated content on form controls, so a
   literal "—" character can't be inserted between them without a
   markup change. Drawn instead via a flex order trick: the
   .price_slider_amount container's own ::before becomes a flex item
   like any real child and can be given an order between the two
   inputs, achieving the same visual result without new markup. The
   submit button isn't styled — not in this task's spec — pushed onto
   its own line so it doesn't sit inside the min/max/dash row. ---- */
body.exposhop-catalog .price_slider_amount {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 16px;
}
body.exposhop-catalog .price_slider_amount #min_price {
  order: 1;
}
body.exposhop-catalog .price_slider_amount::before {
  content: '—';
  order: 2;
  color: var(--esc-text-3);
  font-size: 14px;
  flex-shrink: 0;
}
body.exposhop-catalog .price_slider_amount #max_price {
  order: 3;
}
body.exposhop-catalog .price_slider_amount .button {
  order: 4;
  flex-basis: 100%;
}
body.exposhop-catalog #min_price,
body.exposhop-catalog #max_price {
  /* --esc-border-strong, not --esc-border — the mockup's price field
     uses oklch(0.85), a full tier darker than the divider color
     (0.90) this was pointed at before, which is why it read as
     nearly invisible on staging. */
  border: 1px solid var(--esc-border-strong);
  border-radius: var(--esc-radius-control);
  padding: 9px 12px;
  font-family: var(--esc-sans);
  font-size: 14px;
  color: var(--esc-text-2);
  flex: 1;
  /* min-width:0 (the usual flex-shrink-to-fit trick) let a 4-digit
     value like "3550 ₾" get clipped — these are number fields, not
     ellipsis-truncated labels, so they need real room instead. */
  min-width: 80px;
  background: #fff;
}

/* The real price-field classes (.wpc-filters-range-min/-max — the WPC
   Filters plugin's own inputs, not WooCommerce core's #min_price/
   #max_price above, which this site doesn't actually render; that
   rule block predates the WPC-markup discovery in a later round and
   has never matched anything live).

   v1.8.38 scoped this to desktop only (≥922px) and left it without
   !important — turned out insufficient. Measured live: computed
   padding was 8px 40px 8px 16px and font-size 17px, neither of which
   traces back to anything in this plugin (grepped catalog.css and the
   whole plugin tree for "wpc-range-clear", "40px", "17px" — the only
   17px hits are .price and .esc-filtersheet__title, both unrelated;
   nothing sets padding-right:40px anywhere in this codebase). That
   padding-right:40px is the WPC Filters plugin's own default CSS,
   reserving room for its own .wpc-range-clear reset button inside the
   field — not used here, but still visually present in the plugin's
   base styling, and it was winning outright (not a specificity fight
   we were narrowly losing, this file simply had no answer for
   font-size or the right-side padding at all before now).

   No longer desktop-only: .wpc-filters-range-min/-max is the same DOM
   node in the sidebar and the mobile panel (catalog.js moves
   #secondary .sidebar-main whole, never clones it), the mobile panel
   was already fine, and this fix doesn't touch anything mobile-
   specific — so there's no reason to keep gating it by viewport width
   now that it's !important instead of relying on desktop's narrower
   cascade context. */
/* НАЙДЕНО 24.07.2026 при регрессии стейджинга п.5: WPC Filters сам
   задаёт `input[type="number"].wpc-filters-range-min/-max{padding-
   right:40px!important}` — специфичность (0 id, 2 класса/атрибута, 1
   тип) РОВНО РАВНА прежней версии этого селектора здесь (тоже 2
   класса, 1 тип — body+.exposhop-catalog+.wpc-filters-range-*), при
   равенстве и обоюдном !important побеждает порядок загрузки (WPC
   позже) — правая часть padding молча откатывалась на 40px, ломая
   симметричный 9px 12px из макета. Добавлен тип-квалификатор `input`
   к нашему селектору (2 класса + 2 типа) — специфичность строго выше
   WPC независимо от порядка загрузки. */
body.exposhop-catalog input.wpc-filters-range-min,
body.exposhop-catalog input.wpc-filters-range-max {
  /* Правка дизайна 24.07.2026 (docs/catalog-fixes-plan.md, п.5): padding
     9px 12px по макету (было 8px 10px); border-radius не было задано
     вообще (живые 0px наследовались от базовой стилизации WPC) —
     добавлен по макету, тем же токеном, что кнопки/пагинация. */
  padding: 9px 12px !important;
  border-radius: var(--esc-radius-control) !important;
  font-size: 14px !important;
  width: 100% !important;
  min-width: 0 !important;
  box-sizing: border-box !important;
  appearance: textfield;
  -moz-appearance: textfield;
  /* Правка дизайна 24.07.2026 (сравнение сайдбара с макетом): border/
     color не были заданы вовсе — поле наследовало от WPC Filters
     собственный синевато-серый бордер (rgb(199,209,226), не наш тон)
     и блёклый текст (#666, macket хочет темнее, oklch(0.3 0.005 90)).
     Валютный символ внутри поля (как в макете, «6 ₾») сюда НЕ входит —
     макет рисует его как текст-контент статичного div, а не CSS; на
     живом input добавить символ можно только разметкой/JS
     (WPC-виджет — сторонний плагин), это отдельная задача. */
  border: 1px solid var(--esc-border-strong) !important;
  color: var(--esc-text-2) !important;
}
/* Selectors scoped to the two price-field classes specifically, not a
   bare input::-webkit-*-spin-button — this must not touch spinners on
   any other number input on the page. */
body.exposhop-catalog .wpc-filters-range-min::-webkit-inner-spin-button,
body.exposhop-catalog .wpc-filters-range-min::-webkit-outer-spin-button,
body.exposhop-catalog .wpc-filters-range-max::-webkit-inner-spin-button,
body.exposhop-catalog .wpc-filters-range-max::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
/* The clear-button padding:8px 40px this whole block works around
   belongs to .wpc-range-clear — not used in this UI, hidden outright
   rather than left to visually float over the now-full-width field. */
body.exposhop-catalog .wpc-range-clear {
  display: none !important;
}

/* jQuery UI's own slider classes — this restyles WooCommerce's
   standard jQuery UI slider in place, no JS/markup changes.
   No top margin — the price-input row above it (#min_price/#max_price)
   already has its own margin-bottom, so a top margin here just added
   extra, unwanted space on top of that. Bottom margin corrected to
   36px, matching the mockup's "ფასი" block (was 24px). */
body.exposhop-catalog .price_slider.ui-slider {
  height: 4px;
  border: 0;
  border-radius: 100px;
  background: var(--esc-border);
  margin: 0 0 36px;
}
body.exposhop-catalog .price_slider .ui-slider-range {
  position: absolute;
  top: 0;
  height: 4px;
  border-radius: 100px;
  background: var(--esc-accent);
}
body.exposhop-catalog .price_slider .ui-slider-handle {
  position: absolute;
  top: 50%;
  width: 16px;
  height: 16px;
  margin-top: -8px;
  margin-left: -8px;
  background: #fff;
  border: 2px solid var(--esc-accent);
  border-radius: 100%;
  box-shadow: none;
  outline: none;
  cursor: pointer;
}

/* ================================================================
   Task 5 — toolbar (result count + sort) and pagination.

   ПРАВКА из «Разбора солянки №131/№132»: комментарий ниже про
   «WooCommerce core уже флоатит result-count/ordering» оказался
   ОШИБКОЙ АТРИБУЦИИ (тот же класс ошибки, что и с «inline-блоком
   Astra» на пагинации, см. реконсиляцию №110) — на деле float:none
   и display:inline-block задавал №132 (`.woocommerce
   .woocommerce-result-count, .woocommerce .woocommerce-ordering{
   float:none!important; display:inline-block; vertical-align:middle;
   }`), не тема. Регрессия найдена в исчерпывающей регрессии Этапа 3
   (эталон подтвердил: без этого правила элементы возвращаются к
   WC-дефолту float:left/right;display:block) — закрыта здесь,
   значения дословно из №132. ---- */
body.exposhop-catalog .woocommerce-result-count {
  font-family: var(--esc-sans);
  font-size: 14px;
  color: var(--esc-text-3);
  margin: 0 0 28px;
  line-height: 38px; /* levels its baseline with the ~38px-tall sort control next to it */
  float: none !important;
  display: inline-block;
  vertical-align: middle;
}
body.exposhop-catalog ul.products {
  clear: both;
}

/* ---- Sort dropdown (woocommerce_catalog_ordering()'s own
   <form class="woocommerce-ordering"><select class="orderby">...)
   — the native <select> is kept (task explicitly asks for that, and
   it's what actually submits the sort), just restyled; a <select>
   doesn't reliably support ::before/::after in every browser, so the
   arrow is drawn on .woocommerce-ordering (the <form>, already
   wrapping the select — no extra markup needed) instead, with the
   select's own native arrow stripped via appearance:none. ---- */
body.exposhop-catalog .woocommerce-ordering {
  position: relative;
  display: inline-block;
  margin-bottom: 28px;
  /* margin-left — из «Разбора солянки №131/№132» (№132, было пусто
     здесь, источник: `margin-left:var(--exo-gap)`) — эталон
     подтверждает 24px реально применяется, а не 0. var() оставлен как
     есть (не литерализован), по указанию Вакхтанга — НЕ переносить
     резолвленное значение. Зависимость от №130, см. чек-лист Волны 6
     в css-migration-plan-v2.md. */
  margin-left: var(--exo-gap);
  /* float/vertical-align — тот же источник (№132), тот же пробел,
     закрыт вместе с .woocommerce-result-count выше. */
  float: none !important;
  vertical-align: middle;
}
@media (min-width: 922px) {
  body.exposhop-catalog .woocommerce-ordering {
    min-width: 220px;
  }
}
body.exposhop-catalog .woocommerce-ordering select.orderby {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  width: 100%;
  /* --esc-border-strong, not --esc-border — the mockup's sort control
     uses oklch(0.88), close enough to --esc-border-strong's 0.85 to
     reuse rather than add a fourth near-duplicate border token for a
     barely perceptible difference; --esc-border (0.90) was too pale,
     same class of mismatch task 4 already corrected for price
     fields/checkboxes. */
  border: 1px solid var(--esc-border-strong);
  border-radius: var(--esc-radius-control);
  /* 36px right padding, not 32 — KA option labels are the longest in
     the three languages and were crowding the ▾ arrow at 32px. */
  padding: 10px 36px 10px 16px;
  font-family: var(--esc-sans);
  font-size: 13px;
  font-weight: 600;
  color: var(--esc-text-2);
  background: #fff;
  cursor: pointer;
}
body.exposhop-catalog .woocommerce-ordering::after {
  content: '▾';
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--esc-text-3);
  font-size: 12px;
  pointer-events: none;
}

/* Пагинация вынесена в pagination.css (модуль Exposhop_Pagination) —
   docs/tasks/task-pagination-module.md. Причина: селекторы
   nav.woocommerce-pagination/ul.page-numbers жили одновременно здесь
   и в Code Snippets №112 «Pagination HARD RESET» — смешанный каскад,
   два владельца одного селектора. Один источник правды теперь —
   pagination.css; №112 деактивирован. Не восстанавливать правила
   здесь — при конфликте с другими зонами (аккаунт/поиск) решать в
   pagination.css, а не дублировать сюда. */

/* ---- 3: layered nav / attribute filters (Цвет, Страна, Размер,
   Открывание — all the same widget markup, one CSS block covers all
   four).

   Switched approach: rather than hiding the native checkbox and
   drawing a fake one via ::before/::after on <a> (two rounds of that
   never fully worked — the checkbox kept showing, native and blue),
   the real <input type="checkbox"> is restyled directly with
   appearance:none + :checked, same technique as any custom checkbox.
   This sidesteps the whole "what exactly wraps this widget" question
   — it works on the checkbox itself regardless of its surrounding
   markup, doesn't require hiding anything, and :checked is the
   browser's own real state (no guessing at a "chosen"/BEM class name
   for the active look). <a>'s own href/click behavior is completely
   untouched — this only ever styles the checkbox and the text next
   to it. Scoped broadly to body.exposhop-catalog (not to any WPC
   wrapper class) for the same reason as before: there's no other
   checkbox on this page, in either the sidebar or the mobile sheet,
   to accidentally style — and it needs to keep working whichever of
   the two places .sidebar-main currently lives in. ---- */
body.exposhop-catalog input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  position: relative;
  width: 16px;
  height: 16px;
  margin: 0;
  flex-shrink: 0;
  border: 1.5px solid var(--esc-border-control);
  border-radius: 4px;
  background: #fff;
  outline: none;
  cursor: pointer;
  box-sizing: border-box;
}
/* Visible keyboard-focus ring — outline was removed above, this
   replaces it (WCAG requires a visible focus indicator). */
body.exposhop-catalog input[type="checkbox"]:focus-visible {
  border-color: var(--esc-accent);
  box-shadow: 0 0 0 3px rgba(208, 0, 114, 0.25);
}
body.exposhop-catalog input[type="checkbox"]:checked {
  background: var(--esc-accent);
  border-color: var(--esc-accent);
}
/* Checkmark via a rotated border corner — not a Unicode glyph (font-
   dependent, can render inconsistently) and not an SVG data-URI (no
   markup to hang one on more reliably than this); this technique
   renders identically in Chrome and Safari. */
body.exposhop-catalog input[type="checkbox"]:checked::after {
  content: '';
  position: absolute;
  left: 4px;
  top: 1px;
  width: 5px;
  height: 9px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* Row lists — confirmed in DevTools to be <ul><li> inside each
   section's .wpc-filter-content (the price section's content isn't a
   list at all, so these selectors simply don't match there — no
   :not() exclusion needed the way the old WooCommerce-widget guess
   required). 2px between rows, matching the mockup's «ფერი» block. */
body.exposhop-catalog .wpc-filter-content ul {
  display: flex;
  flex-direction: column;
  gap: 2px;
  list-style: none;
  margin: 0;
  padding: 0;
}
/* Row — checkbox and name grouped tightly (10px gap, applies to every
   adjacent pair including name↔count by default); .count's own
   margin-left:auto below is what actually pushes it to the row's far
   right edge, so the checkbox↔name spacing stays exactly 10px
   regardless of how much room is left over. .wpc-checkbox-item
   included alongside .wpc-filter-content li in case that's the
   plugin's actual per-row class rather than a nested detail inside
   the <li> — untested live, harmless no-op if it doesn't match
   anything.

   Правка дизайна 24.07.2026 (сравнение сайдбара с макетом): вертикальный
   padding возвращён к макетным 8px (было 5px — сознательно уменьшено в
   более раннем заходе именно из-за того, что длинные списки терминов,
   например «Manufacturer»/«Размер кровати» на 12+ строк, читались
   заметно выше нужного при 8px). Это ИЗВЕСТНЫЙ компромисс, не забытая
   деталь — если после этой правки длинные списки снова будут выглядеть
   слишком высокими, откат — одна строка (8px 6px → 5px 6px).

   !important на padding обязателен — без него живьём проигрывал (не
   было видно вообще, ни 8px, ни прежние 5px): у WPC Filters есть
   собственное `body .wpc-filters-main-wrap li.wpc-term-item{padding:0}`
   ровно той же специфичности (2 класса+2 типа против наших же 2
   класса+2 типа) — при ничьей и обоюдном отсутствии !important
   побеждал порядок загрузки (WPC позже). Подтверждено
   CSS.getMatchedStylesForNode. */
body.exposhop-catalog .wpc-filter-content li,
body.exposhop-catalog .wpc-checkbox-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 6px !important;
}
body.exposhop-catalog .wpc-filter-content li a,
body.exposhop-catalog .wpc-checkbox-item a,
body.exposhop-catalog .wpc-checkbox-item label {
  display: block;
  flex: 1;
  min-width: 0;
  font-family: var(--esc-sans);
  font-size: 14px;
  line-height: 1.3;
  color: var(--esc-text-2);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
body.exposhop-catalog .wpc-filter-content li .count {
  flex-shrink: 0;
  margin-left: auto;
  white-space: nowrap;
  font-size: 13px;
  color: var(--esc-text-3);
}

/* ================================================================
   Task 6 — mobile sticky filter bar + bottom sheet.

   Markup: Exposhop_Catalog::render_mobile_filter_bar() (hooked to
   woocommerce_before_shop_loop @5).

   Widget node: real markup confirmed in DevTools —
   #secondary > .sidebar-main > .ast-filter-wrap >
   #wpc_filters_widget-14.widget.widget_wpc_filters_widget >
   .wpc-filters-main-wrap — is a single WPC Filters plugin UI, not a
   stack of separate WooCommerce widgets. catalog.js moves
   #secondary .sidebar-main whole into #esc-filters-body on open
   (one node, one appendChild — no per-child bookkeeping needed) and
   back into #secondary on close (single parent, so plain
   appendChild puts it back correctly). Whatever plugin bound the
   filter UI's own click handlers keeps them, since it's the same
   node — not a clone — moving, never rebuilt. Two earlier attempts
   are superseded by this: one overlaid #secondary in place via CSS
   without moving anything (DevTools showed #esc-filters-body simply
   empty — that approach never placed content there at all); the next
   moved individual #secondary > .widget children one at a time,
   which doesn't match this markup either — the whole filter UI lives
   under one single .widget wrapper, not several.

   Breakpoint: 921px, matching task 4's #primary/#secondary column
   split (not a new 768px breakpoint) — the sidebar already
   restructures at that width, so this is the one place it makes
   sense for it to disappear and the mobile bar to take over.

   The site's own filter plugin has its own trigger button(s) — not
   used here (this bar/sheet replaces it on mobile), hidden below
   rather than removed, so nothing else relying on it (elsewhere in
   that plugin) breaks. Both the originally-guessed class and the
   one confirmed in DevTools are covered. ---- */
/* Десктопная стилизация WPC-кнопки открытия фильтров — из «Разбора
   солянки №131/№132» (№132). На ≤921px эти кнопки скрыты правилом
   ниже (наша нижняя шторка их заменяет) — эти свойства действуют
   только там, где кнопки реально видны, т.е. на десктопе. catalog.css
   раньше их не стилизовал вовсе (только прятал на мобильном) — реальный
   пробел, подтверждён эталоном.
   ЗАВИСИМОСТЬ ОТ №130: --exo-black/--exo-radius, см. чек-лист Волны 6. */
body.exposhop-catalog .wpc-filters-open-button-container {
  position: sticky;
  top: 60px;
  z-index: 10;
  background: #fff;
  padding: 10px;
}
body.exposhop-catalog .wpc-filters-open-widget {
  width: 100%;
  background: var(--exo-black);
  color: #fff;
  padding: 12px;
  font-weight: 600;
  border-radius: var(--exo-radius);
}

body.exposhop-catalog .esc-mobile-filterbar {
  display: none;
}
@media (max-width: 921px) {
  body.exposhop-catalog .wpc-filters-open-widget,
  body.exposhop-catalog .wpc-filters-open-button-container {
    display: none;
  }
  body.exposhop-catalog .esc-mobile-filterbar {
    display: flex;
    gap: 10px;
    position: sticky;
    /* --esc-mobile-header-offset defaults to 0 (no offset) — if
       Astra's sticky/fixed mobile header is enabled on this site,
       set this custom property (e.g. in the Customizer's Additional
       CSS, or here) to that header's actual height in px so this bar
       sticks just below it instead of underneath/behind it:
         body.exposhop-catalog .esc-mobile-filterbar { --esc-mobile-header-offset: 56px; }
       Astra doesn't expose the sticky header's height as its own CSS
       variable to read automatically, and whether it's even enabled
       is a Customizer setting this file can't see — needs a live
       check with the sticky header actually turned on. */
    top: var(--esc-mobile-header-offset, 0px);
    z-index: 20;
    background: #fff;
    padding: 12px var(--pad-x, 16px);
    margin: 0 calc(-1 * var(--pad-x, 16px)) 20px;
    border-bottom: 1px solid var(--esc-border);
  }
}
body.exposhop-catalog .esc-mobile-filterbar__btn {
  flex: 1 1 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 44px;
  border-radius: var(--esc-radius-control-lg);
  font-family: var(--esc-sans);
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  background: #fff;
}
body.exposhop-catalog .esc-mobile-filterbar__btn--filters {
  border: 1px solid var(--esc-text-1);
  color: var(--esc-text-1);
}
body.exposhop-catalog .esc-mobile-filterbar__btn--sort {
  border: 1px solid var(--esc-border-strong);
  color: var(--esc-text-2);
}
body.exposhop-catalog .esc-mobile-filterbar__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--esc-accent);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
}

/* ---- Backdrop ---- */
body.exposhop-catalog .esc-filtersheet-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(10, 9, 7, .45);
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s ease;
  z-index: 998;
}
body.exposhop-catalog .esc-filtersheet-backdrop.is-open {
  opacity: 1;
  pointer-events: auto;
}

/* ---- Sheet ----
   Height lives ONLY on .is-open, as a fixed height (not max-height):
   max-height caps a flex container's size but doesn't give it one —
   with collapsed/empty content a max-height-only box just shrinks to
   fit that content, which is what was making the sheet a thin strip
   with the body squashed to nothing. 85dvh (dynamic viewport height,
   accounts for mobile browser chrome showing/hiding) declared after
   the 85vh fallback so unsupporting browsers keep the vh value and
   supporting ones get the more accurate dvh one. The base (closed)
   state deliberately has no height at all — transform:translateY(100%)
   already puts it fully off-screen regardless of height, so there's
   nothing to fix a size for until it's open. */
body.exposhop-catalog .esc-filtersheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  background: #fff;
  border-radius: 20px 20px 0 0;
  box-shadow: 0 -10px 40px rgba(10, 9, 7, .18);
  transform: translateY(100%);
  transition: transform .3s ease;
  z-index: 999;
}
body.exposhop-catalog .esc-filtersheet.is-open {
  transform: translateY(0);
  height: 85vh;
  height: 85dvh;
}
body.exposhop-catalog .esc-filtersheet__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px;
  border-bottom: 1px solid var(--esc-border);
  flex: 0 0 auto;
}
body.exposhop-catalog .esc-filtersheet__title {
  font-family: var(--esc-sans);
  font-weight: 800;
  font-size: 17px;
  color: var(--esc-text-1);
}
body.exposhop-catalog .esc-filtersheet__close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: 0;
  background: none;
  color: var(--esc-text-3);
  cursor: pointer;
}
/* Widgets land here at full width, no sidebar column constraints —
   catalog.js moves #secondary .sidebar-main here whole on open.
   min-height: 0 is required for the overflow-y:auto scroll to
   actually kick in inside a flex column — without it a flex item
   defaults to min-height:auto (its content's natural height), which
   lets the body grow to fit its content instead of scrolling
   internally within the space .esc-filtersheet.is-open's fixed
   height actually leaves for it. */
body.exposhop-catalog .esc-filtersheet__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 20px;
}
/* WPC's own chrome, duplicated once .sidebar-main lands here — our
   sheet already has an open trigger (the mobile bar) and a close
   button (.esc-filtersheet__close), so WPC's versions of both would
   be redundant/confusing inside our panel. Hidden with CSS only (not
   removed) since .sidebar-main is the same node used in the sidebar,
   where these need to stay exactly as WPC renders them. The active-
   filter chips (.wpc-filter-chips-list) are deliberately NOT in this
   list — those stay visible, they're useful here too. */
body.exposhop-catalog .esc-filtersheet__body .wpc-filters-open-button-container,
body.exposhop-catalog .esc-filtersheet__body .wpc-widget-close-container {
  display: none;
}
/* WPC's whole containment chain, reset to a plain in-flow block, one
   selector list instead of the two narrower, incomplete attempts this
   replaces (a .wpc-filters-widget-content-only rule, then a second one
   adding .wpc-filters-scroll-container/.wpc-filters-widget-containers-
   wrapper). A DOM walk on the live page found the real cause of the
   panel not scrolling to its own content: .wpc-filters-widget-
   containers-wrapper carries an *inline* height (321px, written by
   WPC's own JS) and was falling out of flow — #esc-filters-body was
   scrolling its own ~304px of empty space while ~1900px of real,
   already-rendered content sat visually on top of it, uninvolved in
   that scroll. !important throughout is required specifically to beat
   that inline style — a plain style="height:321px" attribute otherwise
   outranks any non-!important stylesheet rule regardless of selector
   specificity. Every ancestor between .sidebar-main (what catalog.js
   moves) and the actual filter sections is covered, not just the two
   levels caught by the previous, narrower rules — position:static +
   height/max-height/min-height + transform:none + overflow:visible on
   each one so nothing further down the chain can re-establish its own
   fixed/absolute box or its own inline height. */
body.exposhop-catalog .esc-filtersheet__body .sidebar-main,
body.exposhop-catalog .esc-filtersheet__body .ast-filter-wrap,
body.exposhop-catalog .esc-filtersheet__body .widget_wpc_filters_widget,
body.exposhop-catalog .esc-filtersheet__body .wpc-filters-main-wrap,
body.exposhop-catalog .esc-filtersheet__body .wpc-filters-widget-content,
body.exposhop-catalog .esc-filtersheet__body .wpc-filters-widget-containers-wrapper,
body.exposhop-catalog .esc-filtersheet__body .wpc-filters-scroll-container,
body.exposhop-catalog .esc-filtersheet__body .wpc-filters-widget-wrapper {
  position: static !important;
  height: auto !important;
  max-height: none !important;
  min-height: 0 !important;
  transform: none !important;
  overflow: visible !important;
}
/* .wpc-filters-widget-content specifically also renders as a
   standalone-popup-styled box by default (confirmed via
   getBoundingClientRect() in an earlier round) — properties the block
   above doesn't cover, so they stay here rather than being folded in
   (the other seven selectors in that list were never observed needing
   them). */
body.exposhop-catalog .esc-filtersheet__body .wpc-filters-widget-content {
  display: block !important;
  width: auto !important;
  opacity: 1 !important;
  visibility: visible !important;
  box-shadow: none !important;
  border-radius: 0 !important;
  padding: 0 !important;
}
/* Two footers would otherwise show once .sidebar-main lands inside
   the panel: ours (Очистить/Показать) and WPC's own
   (Show (N)/Cancel) — WPC's has a live filter count, ours doesn't, so
   WPC's is kept and ours is hidden. CSS only, not removed from
   markup — .esc-filtersheet__show's click handler (closes the sheet)
   stays wired up in catalog.js even though the button itself is no
   longer visible; harmless, since nothing can click it. */
body.exposhop-catalog .esc-filtersheet__footer {
  display: none;
}
body.exposhop-catalog .esc-filtersheet__clear {
  font-family: var(--esc-sans);
  font-size: 14px;
  font-weight: 700;
  color: var(--esc-text-2);
  text-decoration: none;
  padding: 15px 8px;
}
body.exposhop-catalog .esc-filtersheet__show {
  flex: 2;
  text-align: center;
  padding: 15px;
  background: var(--esc-accent);
  color: #fff;
  border: 0;
  border-radius: var(--esc-radius-control-lg);
  font-family: var(--esc-sans);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
}

/* Scroll lock while the sheet is open (catalog.js toggles this class
   on <body> — the real <body> element, not .exo/body.exposhop-catalog
   which are the same element here but this rule doesn't need the
   plugin-scope prefix since the class itself is plugin-specific). */
body.esc-filters-open {
  overflow: hidden;
}

/* ---- Motion preference — same pattern as the homepage's own CSS:
   kill every transition/animation this file adds (title hover color,
   button hover, checkbox focus/checked states) if the visitor asked
   for reduced motion, rather than leaving them to fall back to the
   browser default duration. ---- */
@media (prefers-reduced-motion: reduce) {
  body.exposhop-catalog *,
  body.exposhop-catalog *::before,
  body.exposhop-catalog *::after {
    transition-duration: 0.001ms !important;
    animation-duration: 0.001ms !important;
  }
}

/* ================================================================
   Волна 4 — довесок каталога (docs/tasks/task-wave4-catalog-addon.md).
   Периметр сужен до №72 + №81 после аудита: №131/№132 оказались
   смесью каталожных и НЕ-каталожных правил (товарная страница,
   About Us, GEO-лендинги, глобальная шапка/меню) — оставлены
   активными как есть, разбор по модулям — отдельная задача.

   Каскад: №81 (priority 3) уже сегодня побеждает существующие правила
   этого файла на пересекающемся селекторе (H1 margin) исключительно
   за счёт !important на margin-bottom — эталон "margin-bottom: 8px"
   сохраняется при переносе независимо от порядка/специфичности.
   Пересечение с breadcrumb-trail — аддитивное (typography здесь,
   position/transform у №81), конфликта нет. Проверено на живом
   каталоге прода до переноса.
   ================================================================ */

/* ---- №72 "CSS для бейджа предзаказа" — вербатим ---- */
.woocommerce ul.products li.product,
.woocommerce-page ul.products li.product {
  position: relative;
}

.badge-preorder{
  position: absolute;
  top: 12px;
  left: 12px;

  background: rgba(255,255,255,.92);
  color: #8A6D3B;

  font-size: 12px;
  font-weight: 600;
  letter-spacing: .2px;

  padding: 4px 12px;
  border-radius: 6px;

  border: 2px solid #E6D8B5;
  box-shadow: 0 6px 18px rgba(0,0,0,.10);

  z-index: 20;
  backdrop-filter: blur(2px);
}

/* ---- №81 "Регулировка расположения хлебных крошек и заголовка" — вербатим ---- */
:root{
  --exps-bc-shift: -35px;      /* крошки: + вниз, - вверх */
  --exps-filter-shift: -6px;   /* Filter: минус = вверх */
}

.woocommerce.archive .breadcrumb.breadcrumbs.woo-breadcrumbs{
  margin: 0 0 -36px !important;
  padding: 0 !important;
  position: relative;
  z-index: 2;
}

.woocommerce.archive .breadcrumb.breadcrumbs.woo-breadcrumbs .breadcrumb-trail{
  display: inline-block;
  transform: translateY(var(--exps-bc-shift));
}

.woocommerce.archive .breadcrumb.breadcrumbs.woo-breadcrumbs > *:not(.breadcrumb-trail){
  display: inline-block;
  transform: translateY(var(--exps-bc-shift));
}

.woocommerce.archive .ast-woo-shop-filter,
.woocommerce.archive .ast-shop-filter-button,
.woocommerce.archive .ast-woocommerce-shop-filter{
  position: relative;
  top: var(--exps-filter-shift);
}

.woocommerce.archive .ast-woo-shop-filter a,
.woocommerce.archive .ast-woo-shop-filter button,
.woocommerce.archive .ast-shop-filter-button a,
.woocommerce.archive .ast-shop-filter-button button,
.woocommerce.archive .ast-woocommerce-shop-filter a,
.woocommerce.archive .ast-woocommerce-shop-filter button{
  position: relative;
  top: var(--exps-filter-shift);
}

.woocommerce.archive .woocommerce-products-header{
  padding-top: 0 !important;
  margin-top: 0 !important;
}

.woocommerce.archive .breadcrumb.breadcrumbs.woo-breadcrumbs{
  margin-bottom: -36px !important;
}

.woocommerce.archive .woocommerce-products-header h1{
  margin-bottom: 8px !important;
}


@media (max-width: 768px){
  .woocommerce.archive #primary.content-area{
    padding-top: 0px !important;
  }

  .woocommerce.archive .breadcrumb.breadcrumbs.woo-breadcrumbs .breadcrumb-trail{
    transform: translateY(-54px);
  }
}
