main {
  padding-top: 90px;
  min-height: calc(100vh - 90px);
}

/* ЗДЕСЬ БЫЛО `#products .hot-card:nth-child(n+26) { display: none }` — снято
   , из-за него в сетке зияла дыра.
      ------------------------------------------------------------------------
   Правило родом из времён КЛИЕНТСКОЙ пагинации: сервер отдавал все карточки
   категории разом, а js/product.page.js (ProductPagination) прятал лишние
   уже после DOMContentLoaded. Правило гасило вспышку «видно всё» до
   отработки скрипта, а сам скрипт затем перебивал его inline-стилями из
   showPage.

   Что сломалось. Пагинация давно стала СЕРВЕРНОЙ (lib/catalog-query.php:
   LIMIT/OFFSET), а js/product.page.js не подключён ни одной PHP-страницей —
   единственная ссылка на него осталась в semena-ovoschey/semena-tomata.html,
   демо-макете, который .htaccess отдаёт 301-редиректом. То есть отменять
   правило стало НЕЧЕМ, и оно молча резало выдачу до 25 карточек.

   Пока сервер тоже слал 25, это было незаметно — числа совпадали. Как только
   perPage подняли до 30, в разметку пошло 30 карточек, а показывалось 25:
   при сетке в 6 колонок последний ряд оставался с одной одинокой карточкой и
   пустотой на пять мест.

   Прятать нечего: сервер присылает ровно perPage карточек.
   */

/* === ХЛЕБНЫЕ КРОШКИ === */

/* Для мобильных устройств */
/* --- ФИЛЬТР СОРТИРОВКА --- */
/* ЕДИНСТВЕННЫЙ скролл-контейнер строки чипов тулбара. Внутри лежат две
   группы (#filter-chips-ui - выбранное, #quick-filters-ui - предложения),
   но скроллится и маскируется именно эта обёртка: два независимых скролла
   бок о бок делили тулбар пополам и каждый обрывался на своей половине. */
.toolbar-chips {
    display: flex;
    align-items: center;
    flex: 1;
    min-width: 0; /* без этого flex:1 не даёт сжаться меньше содержимого -
       строка чипов распирала бы .toolbar вместо горизонтального скролла. */
    gap: 8px;
    /* Отбивка от кнопок сортировки и фильтра слева. Кнопки и первый чип
       стояли на общем gap тулбара (12px) и читались одной сплошной лентой. 8px
       сверх общего дают 20px — группы разделены, но строка не разъезжается.
       */
    margin-left: 8px;
    overflow-x: auto;
    overflow-y: hidden;
    /* Полоса прокрутки не показывается ни в одном движке: Firefox/новые
       Chrome - scrollbar-width, старая Edge - -ms-overflow-style, WebKit -
       ::-webkit-scrollbar ниже. Глобальное правило `* { scrollbar-width:
       thin }` из main.css иначе рисует её прямо в планке тулбара. */
    scrollbar-width: none;
    -ms-overflow-style: none;
    /* Скролл со снапом по чипам - иначе при свободном скролле чип может
       остановиться на середине и выглядеть "обрезанным" с краю. */
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 4px;
    /* Последний чип упирается в правый край тулбара и режется вплотную -
       мягкая маска-затухание вместо жёсткого обреза. Список остаётся тем же
       горизонтальным скроллом (не помещающиеся чипы по-прежнему доступны
       прокруткой) - меняется только то, КАК выглядит их правый край.
       */
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent 100%);
    mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent 100%);
}
.toolbar-chips::-webkit-scrollbar {
    display: none;
    height: 0;
    width: 0;
}

/* Группы чипов - не боксы, а прозрачные обёртки: display:contents убирает
   их собственную раскладку, и чипы ОБЕИХ групп становятся прямыми
   flex-элементами .toolbar-chips - одна строка, один скролл, порядок по DOM
   (сначала выбранные, потом предложения). Сами контейнеры при этом остаются
   разными узлами: js/filters.js чистит innerHTML только у #filter-chips-ui. */
.filter-chips-container {
    display: contents;
}

/* Стиль активных чипов (выбранный фильтр, снимается кликом).
   <button>, а не <div>: чип снимает фильтр, значит это управляющий элемент -
   он обязан быть достижим с клавиатуры и озвучен скринридером. Поэтому здесь
   же гасятся дефолты кнопки (рамка, системный шрифт). */
.filter-chip {
    display: flex;
    align-items: center;
    gap: 8px;
    /* min-height, не только padding - та же причина, что у .quick-filter-chip
       ниже: 8px сверху/снизу давали кнопку ниже 44px, и рядом с ней в одной
       строке предложения были заметно выше - разнобой по высоте, не только
       на глаз (зона нажатия у "×" тоже была ниже минимума проекта). */
    min-height: 44px;
    padding: 8px 12px;
    background: #01A572;
    color: #fff;
    border: none;
    border-radius: 12px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    white-space: nowrap;
    flex-shrink: 0;
    cursor: pointer;
    user-select: none;
    scroll-snap-align: start;
}

.filter-chip .remove {
    font-size: 16px;
    line-height: 1;
    opacity: 0.9;
    margin-left: 4px;
}

/* Стиль быстрых фильтров (предложение, ещё не выбрано) */
.quick-filter-chip {
    display: inline-flex;
    align-items: center;
    /* 8px по вертикали давали кнопку 36px - ниже минимальной зоны нажатия
       проекта (44px, аудит под аудиторию 40-65+). Чипы лежат в горизонтальной
       ленте, рост высоты ничего не двигает.
       */
    min-height: 44px;
    padding: 8px 12px;
    background: rgba(1, 165, 114, 0.1);
    color: #01A572;
    border: 1px solid #01A572;
    border-radius: 12px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    white-space: nowrap;
    flex-shrink: 0;
    cursor: pointer;
    user-select: none;
    scroll-snap-align: start;
}

/* Чипы-ссылки области (витрина производителя: бренд, раздел, категория) - вид как у кнопок. */
a.filter-chip,
a.quick-filter-chip {
    text-decoration: none;
}

/* Включённый быстрый фильтр прячется - его показывает "×"-чип в начале
   строки (см. lib/filter-panel.php). Правило обязано быть ЗДЕСЬ: `display`
   из .quick-filter-chip выше перебивает `[hidden] { display: none }` из
   UA-стилей, и без этой строки скрытый чип остался бы видимым. */
.quick-filter-chip[hidden] {
    display: none;
}

/* Адаптивность */
@media (max-width: 1024px) {
    .toolbar-chips {
        margin-left: 0;
    }
}

@media (max-width: 768px) {
    .toolbar-chips {
        gap: 8px;
    }
}

.clear-btn{
  border:none; 
  background:none; 
  color: #01A572;
  font-size: 16px;
  font-weight:700;
}

/* --- TOOLBAR --- */
/* Тулбар (сортировка/фильтры) фиксирован и ходит вместе с пользователем,
   как меню. Крошки остаются ОБЫЧНЫМ потоком - просто уезжают под
   фиксированный тулбар при скролле, как любой другой контент страницы.
   */
.toolbar {
    height: 64px;
    background: #fff;
    /* Тени нет: обрезка карточек под
       fixed-планкой при скролле это нормальное поведение (как у .header), тень
       тут не нужна.
       */
    display: flex;
    align-items: center;
    gap: 12px;
    max-width: 1900px;
    margin: 0 auto;
    /* Тулбар - position:fixed, поэтому НЕ наследует padding-left/right у
       <main> (main.css: 20px на десктопе / 10px на ≤1024px, см. body main в
       media-запросе ниже) - fixed-элемент позиционируется от вьюпорта, а не от
       padding-box родителя. Раньше тут стоял padding:0 (полностью убран по
       ошибке - тогда казалось, что крошки выровнены без паддинга вовсе, но их
       20px на самом деле дают не они сами, а именно <main>). Значения здесь
       ДОЛЖНЫ буквально совпадать с main.css, иначе опять разъедется.
       */
    padding-left: 20px;
    padding-right: 20px;
    box-sizing: border-box;
    /* fixed, не sticky - <body> сайта сам имеет overflow-y:auto, из-за чего
       sticky-контейнингом для .toolbar становится body, а не вьюпорт, и планка
       просто уезжала бы вместе со страницей вместо приклеивания.
       */
    position: fixed;
    /* Сразу под шапкой. Токеном, а не числом: на ≤425px шапка ниже, и
       вписанные вручную 80px оставляли пустую полосу 12px. */
    top: var(--zd-header-h);
    left: 0;
    right: 0;
    z-index: 800;
    transition: transform 0.3s ease;
}

@media (max-width: 1024px) {
    .toolbar {
        padding-left: 12px;
        padding-right: 12px;
    }
}

/* Единая точка правды под высоту ПОСТОЯННО зафиксированной полосы (шапка +
   тулбар = 80+64) - весь остальной контент (крошки первыми) начинается
   сразу под ней, дальше живёт в обычном потоке без всякой фиксации. */
.has-catalog-toolbar main {
    /* 144 = 80 (шапка) + 64 (тулбар) - это ровно нижняя кромка планки, то
       есть текст начинался ВПЛОТНУЮ к кнопкам фильтра и сортировки. Пробовали
       +32 - оказалось много, вернулись на 24.
       Планка при этом остаётся на своём месте, двигается только контент.

       Считается от токена высоты шапки: на узких экранах она 68px, и зашитые
       156px опускали контент на 12px ниже, чем нужно. Формула одна на все
       ширины: шапка + 64 (планка) + 12 (воздух).
       */
    padding-top: calc(var(--zd-header-h) + 76px);
}

/* НЕ translateY(-100%) - сдвиг только на собственную высоту (64px) не
   перекрывает базовый top:80px, тулбар зависал бы на середине экрана вместо
   ухода за край. Нужен явный top+height = 80+64 = 144px. */
.toolbar.hide {
    transform: translateY(-144px);
}

/* AJAX-подгрузка списка (js/filters.js) - лёгкое затемнение на время
   запроса, вместо полного скрытия: список не должен "мигать" пустотой. */
[data-catalog-list].is-loading { opacity: .5; pointer-events: none; transition: opacity .15s; }

.btn-action {
    width: 46px;
    height: 46px;
    border-radius: 16px;
    border: none;
    background: #f2f2f2;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    position: relative;
}

.btn-action i {
  color: #1f1f1f;
    font-size: 19px;
}

.btn-sort-fil{
    border: none;
    background-color: transparent;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    position: relative;
    /* Это «закрыть» у выезжающих панелей - сортировки, фильтра и
       характеристик (три места, см. lib/filter-panel.php и product-card.php).
       Кнопка занимала 31x21 при иконке 19px: промахнуться по ней было легче, чем
       попасть, а закрыть панель больше нечем. Порог зоны нажатия в проекте -
       44px (аудит).
       */
    min-width: 44px;
    min-height: 44px;
    /* Отрицательный внешний отступ, чтобы выросшая кнопка не раздвинула
       шапку панели: зона нажатия увеличивается «внутрь» воздуха, который
       вокруг неё и так был. */
    margin: -11px;
}
.btn-sort-fil i {
  font-size: 19px;
  color: #1f1f1f;
}

.badge {
    position: absolute;
    top: -2px;
    right: -2px;
    background: #ff3b30;
    color: #fff;
    font-size: 12px;
    font-weight: 600;
    min-width: 18px;
    height: 18px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid #fff;
    visibility: hidden;
}

/* --- ГРИД ТОВАРОВ --- */
/* stretch, а не start: карточки ряда обязаны быть одной высоты, иначе цену в
   них нечем выровнять - её держит прижатый низ (.hot-price-box margin-top:
   auto), а прижимать не к чему, когда каждая карточка ровно по своему тексту.
   При start высоты в одном ряду расходились на 20px (замер 545 и 565). */
.products {
    display: grid;
    gap: 20px;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    align-items: stretch;
    width: 100%;
    box-sizing: border-box;
    padding: 12px 0;
}

.products > * {
    width: 100%;
    box-sizing: border-box;
}

@media (max-width: 1200px) {
    .products {
        grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
        gap: 16px;
        padding: 12px 0;
    }
}

@media (max-width: 1024px) {
    .products {
        grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
        gap: 16px;
    }
}

@media (max-width: 768px) {
    .products {
        grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
        gap: 15px;
        padding: 12px 0;
    }
}

@media (max-width: 600px) {
    .products {
        grid-template-columns: repeat(2, 1fr);
        gap: 32px 12px;
    }
    .products > * {
        min-width: 0;
    }
}

@media (max-width: 480px) {
    .products {
        grid-template-columns: repeat(2, 1fr);
        gap: 28px 12px;
    }
}

@media (max-width: 360px) {
    .products {
        grid-template-columns: repeat(2, 1fr);
        gap: 24px 12px;
    }
}

@media (min-width: 1440px) {
    .products {
        grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
        gap: 24px;
        max-width: 1400px;
        margin: 0 auto;
    }
}

/* Стили выезжающих панелей (ОТКРЫТИЕ СЛЕВА) */
/* Затемнение появляется и гаснет вместе с панелью, а не мигает через
   display. Видимостью правит класс (js/panels.js), не inline-стиль.

   visibility в переходе нужна, чтобы погашенная подложка не перехватывала
   клики: opacity 0 сам по себе элемент не убирает. При закрытии она ждёт
   конца затухания (задержка), при открытии переключается сразу - иначе
   первые кадры появления пришлись бы на невидимый элемент. */
.overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.3);
    z-index: 1001;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity var(--zd-dur) var(--zd-ease-out),
                visibility 0s linear var(--zd-dur);
}

.overlay.is-visible {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: opacity var(--zd-dur) var(--zd-ease-out);
}

.tag,
.radio-item,
.price-inputs input,
.panel .btn-action,
[style*="border:none; background:none"] {
    -webkit-tap-highlight-color: transparent;
}

/* :not(:focus-visible) — гасим кольцо только под мышью. Раньше правило
   снимало фокус безусловно, и с клавиатуры на странице товара пропадали
   сразу теги, радио-варианты фасовки, поля цены и кнопки действий —
   выбрать фасовку табом было нельзя вслепую. */
.tag:focus:not(:focus-visible),
.radio-item:focus:not(:focus-visible),
.price-inputs input:focus:not(:focus-visible),
.panel .btn-action:focus:not(:focus-visible),
[style*="border:none; background:none"]:focus:not(:focus-visible) {
    outline: none;
}

.panel {
    position: fixed;
    background: #fff;
    z-index: 1002;
    /* Токены, а не 0.4s числом: иначе шторка не гаснет у того, кто отключил
       анимацию в системе. 320мс - потолок дизайн-закона для крупных панелей;
       кривая появления - ease-out, она тормозит в конце и даёт результат
       раньше, чем прежняя ease. */
    transition: transform var(--zd-dur-slow) var(--zd-ease-out);
    display: flex;
    flex-direction: column;
    /* Единственное объявление transform на весь компонент (обе точки останова
       пишут только в --panel-tx/--panel-ty, каждая свою ось) - раньше здесь
       было ДВА отдельных transform (translateY в мобильном @media, translateX
       в десктопном), и при каком-то порядке пересчёта стилей браузер мог
       применить транслейт не по той оси - панель улетала за пределы экрана
       вместо появления. С переменными конфликтующих объявлений transform
       физически быть не может. */
    --panel-tx: 0;
    --panel-ty: 0;
    transform: translate(var(--panel-tx), var(--panel-ty));
}

@media (max-width: 1024px) {
    .panel {
        left: 0;
        right: 0;
        bottom: 0;
        border-radius: 20px 20px 0 0;
        --panel-ty: 100%;
        /* Та же ловушка, что у .zd-packing-panel (css/main.css): vh меряет
           экран без адресной строки, шторка прижата к низу - и её подвал
           уезжает под видимую границу. dvh меряет текущую высоту. */
        max-height: 90vh;
        max-height: 90dvh;
    }

    .panel.active {
        --panel-ty: 0;
    }
}

@media (min-width: 1025px) {
    .panel {
        top: 0;
        left: 0;
        bottom: 0;
        width: 440px; /* 400px было тесно */
        height: 100vh; /* явная высота - top/bottom сами по себе тоже её определяют,
           но при position:fixed это должно исключить любую двусмысленность
           с процентным translateY, случайно взятым из мобильного блока */
        --panel-tx: -100%;
        border-top-right-radius: 30px;
        border-bottom-right-radius: 30px;
    }

    .panel.active {
        --panel-tx: 0;
    }
}

/* "Фигнюшка" - индикатор потяни-чтобы-свернуть, сверху ВСЕХ панелей (sort/
   filter/card-info). Видна только на мобиле, где панель - bottom-sheet;
   на десктопе панель выезжает слева, тащить вниз там нечего. */
.panel-handle {
    display: none;
    align-items: center;
    justify-content: center;
    /* 18px сверху были заметным куском экрана телефона при том, что сама
       полоска-ручка 4px. Хват пальцем от этого не страдает: зона остаётся
       ~20px по высоте. */
    padding: 12px 0 8px;
    touch-action: none;
    cursor: grab;
}

.panel-handle::before {
    content: "";
    width: 40px;
    height: 5px;
    border-radius: 4px;
    background: #d6d9dd;
}

@media (max-width: 1024px) {
    .panel-handle { display: flex; }
}

.panel.zd-panel-dragging {
    transition: none;
}

.panel-header {
    /* На телефоне шапка панели съедала верх экрана: 24px со всех сторон плюс
       ручка сверху. Ужато по вертикали; горизонтальные 16px совпадают с
       .panel-body, чтобы «Фильтры» и «Сброс» стояли по одной линии с содержимым.
       */
    /* Больше воздуха сверху: «Фильтры» и «Сброс» упирались в край. Вертикаль поднята с 12 до 20 по шкале отступов; к
       прежним 24 (до правки «сверху слишком много места») не возвращаемся - это
       была другая крайность.
       */
    padding: 20px 16px;
    border-bottom: 1px solid #d3d8dd;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

/* Ручка уже даёт верхний воздух - не дублировать его в заголовке */
.panel-handle + .panel-header {
    /* С ручкой сверху уже есть её собственная высота, поэтому меньше, чем у
       панели без ручки - но не 8px, как было: заголовок липнул к ручке. */
    padding-top: 14px;
}

/* Главный пожиратель высоты шапки — БРАУЗЕРНЫЙ margin у <h2>: 19.92px сверху
   и столько же снизу, то есть почти 40px поверх собственных отступов панели.
   Замер до правки: шапка 101px при padding 12px. Само слово «Фильтры»
   занимает 36px.
   */
.panel-header h2 {
    margin: 0;
    font-size: 18px;
    line-height: 1.25;
}

/* .panel-body (sort-side/card-info-panel) - прямой flex-ребёнок .panel,
   flex:1 работает как положено. У filter-side по-другому: .panel-header/
   .panel-body/.panel-footer лежат ВНУТРИ <form> (нужна одна GET-форма на
   все поля), а <form> - обычный block, не flex-child - flex:1/overflow
   у .panel-body внутри него ни на что не влияли, форма просто росла по
   высоте контента (~30 брендов+групп фильтров) и раздувала весь .panel
   выше экрана: свой скролл у списка фильтров не появлялся, колесо мыши
   над панелью крутило страницу ПОД ней. Правило ниже делает форму тоже
   flex-колонкой, вписанной в высоту .panel - тогда .panel-body внутри
   неё снова получает реальную flex-высоту и overflow работает. */
.panel > form {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.panel-body {
    overflow-y: auto;
    flex: 1;
    min-height: 0;
    /* Нижний запас — под фиксированную кнопку «Применить» (.panel-footer).
       Она position:absolute поверх списка, поэтому без запаса последняя группа
       остаётся ПОД кнопкой и до неё не долистать. 72px не хватало: у кнопки 20px
       паддинга сверху и снизу плюс ~48px сама кнопка = ~88, да ещё безопасная
       зона у айфонов. Считаем от реальной высоты футера, а не на глаз.
       */
    padding: 0 16px calc(96px + env(safe-area-inset-bottom, 0px));
}

/* Содержимое bottom-sheet "Характеристики" товара (мобиль, см. catalog.js
   openCardInfoPanel) - переиспользует .hot-props стили карточки как есть. */
/* card-info-panel - паддинги компактнее, чем у других панелей, чтобы 4
   характеристики + фото + название влезали без внутреннего скролла. */
#card-info-panel .panel-header {
    padding-bottom: 12px;
}

#card-info-panel .panel-body {
    /* Общий .panel-body даёт padding-top:0 - фото упиралось прямо в нижнюю
       границу заголовка без воздуха. */
    padding-top: 12px;
    /* Раньше тут резервировался запас под абсолютно спозиционированный
       футер (84px) - при малом числе характеристик (2-3 строки) это давало
       большую пустую полосу перед кнопкой "Подробнее". Футер теперь в
       обычном потоке (.card-info-panel__footer ниже), запас не нужен. */
    padding-bottom: 16px;
}

/* Фото - первый элемент листа (см. catalog.js openCardInfoPanel), крупный
   визуальный якорь панели. Заголовок с названием/брендом идёт сразу под ним,
   компактнее, чем раньше - вертикальный воздух между блоками убран там, где
   он был декоративным (border-bottom), а не функциональным. */
/* Было height:180px + padding:20px + object-fit:contain - фото висело в
   рамке с полями и не заполняло блок. Теперь бокс задаётся пропорцией, а
   фото кроется по нему целиком (cover) - тот же принцип, что уже принят для
   фото товара в card.css.
   */
/* ФОТО НЕ ОБРЕЗАЕТСЯ. НИКОГДА.
   Было 3/2 + cover: квадратное фото 500x500 теряло треть высоты - у пакета
   удобрений срезало и верх, и низ вместе с названием на упаковке.

   Пропорция 4/3, а не 1/1. Квадрат влезает в неё целиком (contain даёт поля
   по бокам, но НЕ режет), а высота растёт всего на ~30px против прежних 3/2
   - панель не должна занимать много места. У 1/1 панель на
   телефоне выросла бы ещё на сотню пикселей и уехала бы под скролл, а про
   скрытый скролл здесь уже обжигались.
   */
.card-info-panel__img {
    margin: 0 0 12px;
    /*
     * БЛОК ПО КАРТИНКЕ, А НЕ КАРТИНКА ПО БЛОКУ.
     *
     * Фиксированная пропорция 4/3 этого не давала: при contain картинка
     * рисовалась ВНУТРИ элемента, а радиус лежал на самом элементе - то есть
     * скруглялась рамка, а углы самой фотографии оставались прямыми. Плюс у
     * каждого фото не той пропорции оставались белые поля сверху и снизу,
     * которых никто не просил.
     *
     * Пропорции больше нет: высоту задаёт сама картинка, блок её обнимает, а
     * радиус переехал на <img> - скругляется именно фотография. Потолок по
     * высоте остался на картинке (см. ниже), панель бывает и на десктопе.
     */
    display: flex;
    align-items: center;
    justify-content: center;
    /* Место под фото занимаем ЗАРАНЕЕ. Без пропорции высоту задаёт картинка,
       а пока она грузится (в шторке это клон плитки с loading=lazy), её ещё
       нет - блок схлопывался в полоску, и панель прыгала под пальцем. Если
       файл вообще не отдался, останется ровная пустая плашка вместо скачка. */
    min-height: 180px;
    border-radius: 16px;
    overflow: hidden;
    /* Белый, а не #FBFBFB. При contain поля вокруг фото видно всегда, и
       сероватая подложка читалась как вторая рамка вокруг картинки. У фотографий
       товара фон тоже белый, так что поля теперь просто продолжают саму
       картинку. Рамка остаётся: без неё блок сливается с листом панели и
       перестаёт читаться как фото.
       */
    background: #fff;
    box-sizing: border-box;
    border: 1px solid #d3d8dd;
    /* Поля, чтобы фото не упиралось в рамку - при contain края картинки
       видны, и касание рамки читалось бы как обрезка. */
    padding: 6px;
}

/* Без своей border-bottom - раньше эта линия и верхняя граница первой
   строки .hot-props шли почти впритык (4px margin + 6px padding между ними)
   и читались как одна слипшаяся двойная черта. Список характеристик теперь
   единственный источник разделительных линий, .card-info-panel__title
   просто отделён отступом. */
.card-info-panel__title {
    padding: 0;
    margin-bottom: 12px;
}

.card-info-panel__name-ru {
    display: block;
    font-size: 16px;
    font-weight: 700;
    line-height: 1.25;
    color: #1f1f1f;
}

.card-info-panel__name-en {
    display: block;
    font-size: 12px;
    color: #8e8e93;
    margin-top: 1px;
}

.card-info-panel__brand {
    display: block;
    height: 14px;
    margin-top: 5px;
}

/* НЕ cover (важно, чтобы не откатили по старому комментарию выше): cover
   пробовали и отказались - фото не должно обрезаться. cover ВСЕГДА режет всё, что не совпало с пропорцией
   бокса, а на витрине таких фото большинство.
   */
.card-info-panel__img img {
    display: block;
    /* auto + max-* : элемент становится РОВНО размером с фотографию, поэтому
       border-radius скругляет её саму, а не пустую рамку вокруг. */
    width: auto;
    height: auto;
    max-width: 100%;
    /* Потолок высоты - здесь, а не на блоке: блок теперь тянется за
       картинкой, и ограничивать надо её. 38vh оставляет место названию,
       характеристикам и кнопкам без внутреннего скролла у панели. */
    max-height: 38vh;
    object-fit: contain;
    border-radius: 12px;
}

/* Список характеристик - аккуратные строки с разделителями вместо сплошного
   текста (переиспользует .hot-props/.hot-prop-icon из карточки, см. блок
   card-base в main.css). */
#cardInfoPanelBody .hot-props {
    display: flex;
    flex-direction: column;
    gap: 0;
    margin: 0 0 8px;
    padding: 0;
}

/* Шторка «Характеристики» на телефоне: иконка - главное, что опознаёт глаз,
   поэтому крупно (глиф 20px); при 12px рядом с текстом её было не разглядеть. */
#cardInfoPanelBody .hot-props li {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 0;
    border-bottom: 1px solid #d3d8dd;
    font-size: 15px;
    color: #1f1f1f;
}

#cardInfoPanelBody .hot-props li:last-child {
    border-bottom: none;
}

/* В шторке место есть - подпись переносится, а не обрезается троеточием. */
#cardInfoPanelBody .hot-props li > span {
    white-space: normal;
    overflow: visible;
    line-height: 1.35;
}

#cardInfoPanelBody .hot-prop-icon {
    width: 32px;
    height: 32px;
}

#cardInfoPanelBody .hot-prop-icon i {
    font-size: 20px;
}

#cardInfoPanelBody .hot-prop-icon img {
    width: 24px;
    height: 24px;
}

/* Подвал bottom-sheet: сравнение слева, "Подробнее" по центру, избранное справа.
   Обычный поток (не position:absolute, как .panel-footer у фильтра) - раньше
   абсолютный футер "прибивался" к низу листа независимо от длины контента,
   и при 2-3 коротких характеристиках между ними и кнопкой оставалась
   большая пустая полоса. В потоке футер идёт сразу после списка. */
.card-info-panel__footer {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 24px;
    background: #fff;
    border-top: 1px solid #d3d8dd;
}

/* compare/fav в футере - те же реальные .hot-compare/.hot-fav (клон с карточки,
   см. catalog.js openCardInfoPanel), без переопределения цветов - подсветка
   default/active должна выглядеть идентично листингу (синий компэр, оранжевый
   фав), только высота подровнена под кнопку "Подробнее". */
.card-info-panel__footer .hot-compare,
.card-info-panel__footer .hot-fav {
    flex: 0 0 48px;
    width: 48px;
    height: 48px;
}

.card-info-panel__more-btn {
    flex: 1;
    text-align: center;
    background: #01A572;
    color: #fff;
    border: none;
    height: 48px;
    line-height: 48px;
    border-radius: 16px;
    font-size: 16px;
    font-weight: 700;
    text-decoration: none;
}

.section {
    padding: 24px 0;
    border-bottom: 1px solid #f8f9fa;
}

.section h3 {
    margin: 0 0 16px 0;
    font-size: 14px;
    text-transform: uppercase;
    color: #8e8e93;
    letter-spacing: 1px;
}

/* ─── Панель фильтров: одна группа = одна карточка ──────────────────────
   ПОЧЕМУ. Единственным разделителем групп был border-bottom цвета #f8f9fa на
   белом фоне панели - контраст к фону ~1.03:1, т.е. линия физически не
   читалась, и десяток групп выглядел одной сплошной простынёй тегов. Группа
   теперь карточка: рамка + свой фон + воздух между карточками - разделение
   видно тремя независимыми способами сразу, а не одной волосяной линией.

   Скоуп именно #filter-side, а не .section вообще: те же .section
   переиспользуют панель сортировки и bottom-sheet «Характеристики» товара,
   где список сплошной по смыслу и карточки только добавили бы шума.
   */
#filter-side .section {
    /* Отступы ужаты, чтобы не забирали лишнее место. Разделение групп при этом не теряется: его держат рамка, фон и
       скругление — три независимых признака, а не только воздух. Было 14/16/18,
       на шести группах это съедало ~250px вертикали.
       */
    margin: 8px 0;
    padding: 12px 12px 12px;
    border: 1px solid var(--zd-border-subtle);
    border-radius: 12px;
    background: var(--zd-surface-soft);
}

/* Заголовок группы - якорь, по которому глаз отбивает блоки друг от друга,
   поэтому он контрастнее общего .section h3 (#8e8e93 на светлом фоне почти
   пропадал). Метка слева нарисована псевдоэлементом, а НЕ иконкой: иконки
   в проекте только шрифтовые, а отдельного глифа под каждую группу фильтра
   нет и заводить его незачем. */
#filter-side .section h3 {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
    color: var(--zd-text-muted);
}

#filter-side .section h3::before {
    content: "";
    flex: none;
    width: 3px;
    height: 14px;
    border-radius: 2px;
    background: var(--zd-border);
}

/* Подсветка группы, в которой уже что-то выбрано. Панель длинная (у бренда
   до 30 значений), и без неё, чтобы понять «где я уже нафильтровал»,
   приходится глазами перебирать все группы подряд.
   :has() - не новая зависимость: на нём же держится .tag:has(input:checked)
   выше, вся подсветка выбранного в панели и так работает только с ним. */
#filter-side .section:has(input:checked) {
    border-color: var(--zd-green);
    background: var(--zd-green-soft);
}

#filter-side .section:has(input:checked) h3 {
    color: var(--zd-green);
}

#filter-side .section:has(input:checked) h3::before {
    background: var(--zd-green);
}

/* БРЕНД. Порядок («сверху») задаёт PHP - zd_filter_groups_sorted(), а не
   CSS-order: тогда «первый» одинаково верно и для скринридера, и для
   страницы без стилей, и для HTML, который уходит в AJAX-фрагмент.
   Модификатор здесь лишь помечает главный фильтр категории - рамка темнее
   соседних и зелёная метка у заголовка. Фон НЕ переопределяем: теги внутри
   белые, и на белой же карточке они держались бы только рамкой, тогда как
   на общем светло-сером фоне читаются заливкой И рамкой сразу. */
#filter-side .section--brand {
    border-color: var(--zd-border);
}

#filter-side .section--brand h3::before {
    background: var(--zd-green);
}

/* Сами значения на светлой карточке: раньше серый #F2F2F2 лежал на белом и
   держался только заливкой - на карточке того же светлого тона его края
   расплывались. Рамка возвращает тегу собственный контур. */
#filter-side .tag {
    background: #fff;
    border: 1px solid var(--zd-border-subtle);
}

/* Выбранное значение - зелёная заливка, как и было. Правило нужно повторить
   со скоупом #filter-side: у общего .tag:has(input:checked) специфичность
   ниже, чем у #filter-side .tag выше, и белый фон перебил бы зелёный. */
#filter-side .tag:has(input:checked) {
    background: var(--zd-green);
    border-color: var(--zd-green);
    color: #fff;
}

/* Длинный список значений свёрнут до первых (lib/filter-panel.php), раскрывает
   «Показать ещё» - как у маркетплейсов. Отмеченное сворачиванию не подлежит. */
#filter-side .section:not(.is-expanded) .tag--more {
    display: none;
}

.tag-more-toggle {
    min-height: 44px;
    margin-top: 4px;
    padding: 0;
    background: none;
    border: 0;
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    color: var(--zd-green);
    cursor: pointer;
}

.tag-more-toggle:hover {
    text-decoration: underline;
}

/* UI Элементы фильтра */
.price-inputs {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

.input-box {
    background: #F2F2F2;
    padding: 12px 12px;
    border-radius: 12px;
}

.input-box label {
    display: block;
    font-size: 12px;
    color: #8e8e93;
}

.input-box input {
    border: none;
    background: none;
    width: 100%;
    font-size: 16px;
    font-weight: 700;
}

/* Слайдер диапазона (тип фильтра "range" - цена/вес). Два input[type=range]
   наложены друг на друга (стандартная техника dual-thumb range на чистом
   CSS/HTML без библиотек), зелёная заливка между ползунками синхронизируется
   в js/product.page.js::initPriceRangeSlider(). Тип фильтра - см. agroadmin/edit-filter.php
   §6 - на сайте пока единственный экземпляр, резолвер диапазоны не обрабатывает. */
.range-slider {
    position: relative;
    height: 32px;
    margin: 20px 2px 4px;
}

.range-slider__track,
.range-slider__fill {
    position: absolute;
    top: 50%;
    height: 4px;
    border-radius: 4px;
    transform: translateY(-50%);
}

.range-slider__track {
    left: 0;
    right: 0;
    background: #F2F2F2;
}

.range-slider__fill {
    background: #01A572;
    left: 0%;
    right: 0%;
}

.range-slider__input {
    position: absolute;
    top: 50%;
    left: 0;
    width: 100%;
    height: 4px;
    margin: 0;
    background: none;
    pointer-events: none;
    -webkit-appearance: none;
    appearance: none;
    transform: translateY(-50%);
}

.range-slider__input::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    pointer-events: auto;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #fff;
    border: 3px solid #01A572;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
    cursor: pointer;
}

.range-slider__input::-moz-range-thumb {
    pointer-events: auto;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #fff;
    border: 3px solid #01A572;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
    cursor: pointer;
    box-sizing: border-box;
}

.range-slider__input::-moz-range-track {
    background: none;
    border: none;
}

.tag-list {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.tag {
    padding: 12px 16px;
    border-radius: 16px;
    background: #F2F2F2;
    font-size: 14px;
    cursor: pointer;
    /* Поимённо: запись без свойства - это `all` по умолчанию. */
    transition: background var(--zd-dur-fast) var(--zd-ease),
                color var(--zd-dur-fast) var(--zd-ease);
}

/* ВИЗУАЛЬНО СКРЫТ, А НЕ display:none. display:none выкидывает элемент из
   порядка табуляции целиком — с клавиатуры до чекбокса нельзя было дойти
   вообще, и покупатель мог отметить только 12 «быстрых» фильтров из тулбара,
   а не полный список из панели (проверено на /semena-ovoschey/semena-tomata/:
   45 значений в панели, 33 из них не выбрать без мыши). Приём стандартный
   («visually hidden»): элемент остаётся в DOM-порядке и фокусируется, но
   не занимает места и не виден. */
.tag input {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.tag:has(input:checked) {
    background: #01A572;
    color: #fff;
}

/* Кольцо фокуса — на самой плашке, потому что фокус физически стоит на
   спрятанном input внутри неё. :focus-visible, а не :focus: чекбокс кладут
   кликом мыши так же часто, как табом, и обводка не должна мигать на
   каждый клик. Токены — из css/tokens.css (подключён везде, где грузится
   этот файл). */
.tag:has(input:focus-visible) {
    outline: none;
    box-shadow: var(--zd-focus-ring);
}

.radio-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* Чуть просторнее по высоте - было 20px, строки сортировки выглядели тесно. */
    padding: 26px 0;
    cursor: pointer;
    border-bottom: 1px solid #d3d8dd;
}

/* Та же замена display:none -> визуально скрыт, что у .tag input выше:
   с клавиатуры сортировку выбрать было нельзя вообще (три радио-варианта
   выпадали из порядка табуляции целиком). */
.radio-item input {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.radio-dot {
    width: 22px;
    height: 22px;
    border: 2px solid #c2c8ce;
    border-radius: 50%;
}

.radio-item input:checked+.radio-dot {
    background: #01A572;
    border-color: #01A572;
    box-shadow: inset 0 0 0 4px #fff;
}

.radio-item:has(input:focus-visible) {
    outline: none;
    box-shadow: var(--zd-focus-ring);
}

.panel-footer {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px));
    background: #fff;
    border-top: 1px solid #d3d8dd;
    border-bottom-right-radius: 30px;
}

.btn-submit {
    width: 100%;
    background: #01A572;
    color: #fff;
    border: none;
    height: 56px;
    border-radius: 16px;
    font-size: 16px;
    font-weight: 700;
    cursor: pointer;
}

.icon-svg {
    width: 24px;
    height: 24px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* 30.02 Горячие товары - ОПТИМИЗИРОВАНО */
.products {
    display: grid;
    grid-template-columns: 1fr;
    align-items: stretch;
    gap: 20px;
    max-width: 1900px;
    margin: 0 auto;
}

@media (min-width: 768px) {
    /* НЕ БОЛЬШЕ ШЕСТИ КАРТОЧЕК В РЯДУ - иначе они слишком узкие. Отменяет уплотнение от (220px/12px), которое давало
       восемь карточек в ряду на широком экране.

       Минимум колонки - max из двух величин, и обе нужны:

       • calc((100% - 5×20px)/6) - ШЕСТАЯ ЧАСТЬ РЯДА. Колонка не может быть уже
         неё, значит седьмая никогда не влезет: потолок держится сам, на любой
         ширине, без жёсткого repeat(6, 1fr).
       • 280px - НИЖНИЙ ПРЕДЕЛ ширины карточки. Жёсткая шестёрка на ноутбуке
         1280px дала бы колонки по 190px - уже прежней тесноты; здесь вместо этого
         auto-fill честно сбрасывает ряд до четырёх
       колонок, сохранив ширину карточки.
       */
    .products {
        /* 220px, не 280px: с порогом 280 на планшете 768-899px помещались
           только ДВЕ карточки по ~374px - шире, чем на десктопе 1900px (~300px), и
           ряд падал с трёх до двух при РОСТЕ экрана. Замер: 767px - 3 по 246px,
           768px - 2 по 374px. Верхнее ограничение (не больше шести в ряд) при этом
           сохраняется.
           */
        grid-template-columns: repeat(auto-fill, minmax(max(220px, calc((100% - 100px) / 6)), 1fr));
        gap: 20px;
    }
}
.hot-card {
    --card-bg: #ffffff;
    background: var(--card-bg);
    border-radius: 12px;
    position: relative;
    display: flex;
    flex-direction: column;
    /* Рамка плитки темнее линий внутри неё: соседние плитки читаются отдельными карточками. */
    border: 1px solid var(--zd-line-strong, #C2C8CE);
    /* без overflow:hidden — иначе тултип на .hip клипится */
}

/* .brand-country вынесен в блок card-base main.css */

/* Выравнивание карточек в гриде по высоте (десктоп): .hot-top и .hot-main-row
   растягиваются, чтобы .hot-add-flex и .hot-toggle-row прилипали к низу. */
@media (min-width: 768px) {
    .hot-card .hot-top { flex: 1; }
    .hot-card .hot-main-row { flex: 1; }
}

/* Скругления через сами элементы — БЕЗ overflow:hidden, чтобы тултипы
   на .hip и абсолютные элементы могли свободно выходить за границы. */
.hot-card > .hot-top { border-radius: 12px 12px 0 0; }
.hot-card > .hot-toggle-row { border-radius: 0 0 12px 12px; }

/* Скругление самого фото задаёт правило .hot-card .hot-img-box img ниже
   (радиус 10px там был поднят до 12px именно затем, чтобы совпадать с
   этими 12px карточки — раньше на месте недогруженного/битого фото было
   видно шов между двумя разными скруглениями). Здесь отдельного правила
   для img больше нет — было дублирующим и всё равно перебивалось тем,
   что ниже по каскаду в этом же файле. */
.hot-top {
    display: flex; 
    flex-direction: column; 
}

.hot-main-row {
    display: flex;
    flex-direction: row;
}

.hot-card .hot-img-box {
    position: relative;
    min-width: 130px;
    flex-shrink: 0;
    background: var(--card-bg);
}

.hot-card .hot-img-box a {
    display: block;
    width: 100%;
    height: 100%;
}

/* === ICON STRIP === */
/* Мобиле: под фото в потоке; Десктоп: абсолютно в левом нижнем углу фото */
.hot-icon-strip {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
}

/* Иконки поверх фото, снизу слева — на всех ширинах */
.hot-icon-strip {
    position: absolute;
    bottom: 8px;
    left: 8px;
    z-index: 2;
}

/* Когда есть баннер «Ждём поступления» — иконки поднимаем над ним */
.hot-card--out .hot-icon-strip {
    bottom: 28px;
}

@media (max-width: 767px) {
    .hot-icon-strip {
        gap: 8px;
    }
    /* отступ снизу карточки-картинки, чтобы «В корзину» и пр. были ниже */
    .hot-card .hot-img-box { margin-bottom: 12px; }
}

/* Размер, фон и тултип .hip — единый источник правды в блоке card-base
   main.css (был отдельным файлом card-base.css, слит; был дублирован здесь с
   меньшим размером и без media-запроса на десктоп, из-за чего чипы на
   карточке товара всегда рисовались 24px/11px вместо положенных 24→28px /
   16→20px; правка).
   */

/* Цвета иконок чипов по типу (через data-tip — единый источник правды) */
/* Цвета чипов перенесены в блок card-base main.css (единый источник правды).
   Здесь оставлены пустыми для обратной совместимости. */

/* === ЦВЕТ КАРТОЧКИ ПО СТАТУСУ ===
   Базовая .hot-card остаётся белой (нейтральный/без статуса).
   Модификатор задаёт тонированный фон + цветной левый акцент-бордюр.
   Цвета согласованы с палитрой иконок чипов (data-tip). */
.hot-card--sale     { --card-bg: #FFF6EE; border-color: #FFD9B8; }
.hot-card--hit      { --card-bg: #FFF1F0; border-color: #F5C2BE; }
.hot-card--new      { --card-bg: #FFFBE5; border-color: #F0DF8C; }
.hot-card--preorder { --card-bg: #ECF5FC; border-color: #B9D9EE; }

/* === НЕТ В НАЛИЧИИ ===
   Карточка остаётся кликабельной, но визуально приглушается.
   На фото — фиолетовая плашка «Ждём поступления» с иконкой даты слева. */
.hot-card--out {
    --card-bg: #EFEEF2;
    border-color: #D8D5DF;
}
.hot-card--out .hot-img-box img,
.hot-card--out .brand-logo {
    filter: grayscale(0.7) brightness(0.92);
    opacity: 0.75;
}
.hot-card--out .hot-price,
.hot-card--out .hot-old,
.hot-card--out .hot-name-ru,
.hot-card--out .hot-name-en,
.hot-card--out .hot-rating {
    opacity: 0.6;
}
.hot-card--out .hot-add {
    background: #B7B3C2;
    color: #fff;
}

/* Фиолетовая плашка-баннер на фото */
.hot-out-overlay {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 8px 8px;
    background: linear-gradient(135deg, #6D28D9 0%, #7C3AED 100%);
    color: #fff;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.1;
    letter-spacing: 0.1px;
    white-space: nowrap;
    pointer-events: none;
    box-shadow: 0 -2px 8px rgba(109, 40, 217, 0.25);
}
.hot-out-overlay i {
    font-size: 12px;
    line-height: 1;
    flex-shrink: 0;
}
.hot-out-overlay span {
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
/* Баннер живёт внутри <a> и прижат к низу фото — на десктопе и мобиле одинаково */
.hot-card--out .hot-img-box a { position: relative; }
@media (max-width: 767px) {
    .hot-out-overlay { font-size: 10px; padding: 5px 6px; gap: 4px; }
    .hot-out-overlay i { font-size: 11px; }
}

.hot-card .hot-img-box img {
    width: 100%;
    height: 100%;
    /* cover, не contain: белые поля на непропорциональном снимке выглядят
       хуже небольшой обрезки краёв. Для
       доминирующего случая (4 из 5 реальных фото проекта - точный квадрат
       500x500) cover и contain дают идентичный результат без единого обрезанного
       пикселя - разница только на исключениях.
       */
    object-fit: cover;
    display: block;
    /* 12px, не 10px — совпадает с радиусом самой карточки (.hot-card,
       12px). При недогруженном/битом фото видна не сама картинка, а её
       белый фон с этой рамкой вплотную к краю карточки — рассинхрон в
       2px давал заметный прямоугольный шов на скруглённом углу. */
    border-radius: 12px;
    border: 1.5px solid #01A572;
}

.hot-main-row {
    position: relative;
}

.hot-label {
    position: absolute;
    top: 0;
    left: 0;
    font-weight: 600;
    padding: 4px 9px;
    font-size: 12px;
    z-index: 2;
    /* Top-left повторяет скругление .hot-top (12px), чтобы бейдж не «съедался»
       overflow:hidden родителя. Bottom-right — обычный 8px. */
    border-radius: 12px 0 8px 0;
    color: #fff;
    letter-spacing: 0.3px;
    text-transform: uppercase;
}

.hot-sale {
    background: #01A572;
}

/* Кнопка «избранное» в углу превью-карточки. Только внутри .hot-card,
   иначе на странице товара ломает inline-меню справа от рейтинга. */
.hot-card .hot-like {
    position: absolute;
    top: 7px;
    right: 7px;
    width: 35px;
    height: 35px;
    background: rgba(255, 255, 255, 0.9);
    border-radius: 8px;
    border: none;
    cursor: pointer;
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 5;
}

.hot-like i {
    font-size: 18px;
    color: #FF7700;
    transition: transform 0.3s ease;
}

@keyframes heartBeat {
    0% { transform: scale(1); }
    25% { transform: scale(1.2); }
    50% { transform: scale(0.85); }
    100% { transform: scale(1); }
}

.content-wrapper {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
    justify-content: center;
    /* position: static — позиционирующий родитель для .mini-info теперь .hot-main-row,
       чтобы оверлей перекрывал и картинку, и текст */
}

.hot-info {
    padding: 8px 12px;
    flex-grow: 1;
    display: flex;
    flex-direction: column;
}

/* Атомы карточки (название, бренд-лого, рейтинг, цена, старая цена)
   — единый источник правды в блоке card-base css/main.css (был отдельным
     файлом card-base.css, слит). Здесь оставлены только
   правила, специфичные для гридовой .hot-card (layout/state).
   */

/*
 * РАЗМЕР КНОПОК РЕШАЕТ ШИРИНА САМОЙ ПЛИТКИ, А НЕ ШИРИНА ОКНА.
 *
 * ЗАМЕР, а не ощущение. Считали, сколько надписи НУЖНО и сколько ей дают
 * (клон кнопки с width:auto против фактической ширины), на каталоге
 * «Луковицы тюльпанов», где 61 позиция с договорной ценой: 1366px - ряд 245,
 * запас +15 390px - ряд 364, запас +134 1280px - ряд 228, ЗАПАС -2 320px -
 * ряд 294, запас +64 1024px - ряд 230, запас 0 То есть ломается не «на
 * мобильном», а на ноутбуке: там колонок больше и плитка уже всего. На
 * телефоне колонка одна и места вдоволь.
 *
 * Поэтому порог привязан к ряду кнопок, а не к брейкпойнту окна: одно и то
 * же окно даёт разную плитку в каталоге, в рекомендациях на карточке и в
 * избранном, и media-запрос всё равно попал бы мимо в двух случаях из трёх.
 * Заодно надпись остаётся 15px везде, где место есть - её поднимали до 15px
 * ради читаемости для аудитории 40-65+, и отменять это на всём сайте ради
 * одного тесного случая нельзя.
 */
.hot-add-flex {
    container-type: inline-size;
    container-name: zd-buyrow;
    width: 100%;
    display: flex;
    align-items: stretch;
    gap: 8px;
    padding: 0 8px 8px;
    box-sizing: border-box;
}

.hot-add {
    flex: 1 1 auto;
    /* 40 -> 44px: главная кнопка покупки должна попадаться пальцем с первого
       раза (минимум 44x44 по Apple HIG), а у аудитории 40-65+ точность нажатия
       ниже средней. Замер.
       */
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    background: #FF7700;
    color: #ffffff;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    font-weight: 700;
    /* 12 -> 15px. Надпись на самой важной кнопке каталога была мельче
       подписей в футере. Прописные буквы сняты: «В КОРЗИНУ» капслоком
       читается медленнее строчных, а для этой аудитории важна скорость
       распознавания, а не акцент. */
    font-size: 15px;
    /*
     * НАДПИСЬ НЕ ЛОМАЕТСЯ НА ДВЕ СТРОКИ.
     *
     * Запрета переноса тут не было вовсе, поэтому при узкой плитке «В корзину» и
     * «Узнать цену» разрывались по пробелу: кнопка распухала вдвое, ряд плиток
     * шёл вразнобой по высоте.
     *
     * nowrap + min-width:0 - пара: без второго флекс-элемент не сжимается ниже
     * своего содержимого и вместо переноса вылезал бы за плитку. Высота 44px и
     * размер 15px не тронуты: их поднимали ради читаемости.
     */
    white-space: nowrap;
    min-width: 0;
    /* Последний рубеж. nowrap + min-width:0 запрещают перенос и разрешают
       сжатие - но без overflow надпись вылезала БЫ поверх плитки. Теперь в
       худшем случае она обрежется внутри кнопки, а вёрстка ряда устоит. */
    overflow: hidden;
    /* Токены вместо .25s: цвет - быстрая ступень (120мс). Отдельно transform -
       им кнопка отвечает на нажатие; он не трогает раскладку и считается
       видеокартой, в отличие от размеров. */
    transition: background var(--zd-dur-fast) var(--zd-ease),
                transform var(--zd-dur-fast) var(--zd-ease-out);
}

/* Отклик на нажатие. Пальцу на телефоне ховера не достаётся вовсе, и до сих
   пор главная кнопка каталога никак не показывала, что нажатие дошло.
   scale(.97) - ровно столько, чтобы заметить и не отвлечься. */
.hot-add:active {
    transform: scale(.97);
}

/* Ховер - только под мышью. На тач-экране :hover остаётся ВИСЕТЬ после тапа,
   пока человек не ткнёт в другое место: кнопка оставалась тёмной, будто её
   заело. Правило дизайн-закона, здесь его не было. */
@media (hover: hover) and (pointer: fine) {
    .hot-add:hover {
        background: #e56900;
    }

    .hot-add.added:hover {
        background: #018f63;
    }
}

.hot-add.added {
    background: #01A572;
}

/* Модификатор «Уведомить» — заменяет «В корзину» на .hot-card--out.
   Фиолетовый default; чуть темнее после клика (toggle через catalog.js).
   Hover ничего не меняет — статика по требованию UX. */
.hot-add--notify,
.hot-add--notify:hover,
.hot-card--out .hot-add--notify,
.hot-card--out .hot-add--notify:hover {
    background: linear-gradient(135deg, #7C3AED 0%, #8B5CF6 100%);
    color: #fff;
}
.hot-add--notify.is-active,
.hot-add--notify.is-active:hover,
.hot-card--out .hot-add--notify.is-active,
.hot-card--out .hot-add--notify.is-active:hover {
    background: linear-gradient(135deg, #5B21B6 0%, #6D28D9 100%);
    color: #fff;
}
.hot-add--notify .notify-icon,
.hot-add--notify .notify-bell {
    font-size: 14px;
    line-height: 1;
}

/* === Кнопка «Избранное» рядом с «В корзину» ===
   44x44 - правило проекта для зоны нажатия (аудитория 40-65+). Было 42x40,
   и в одном ряду с «В корзину» (44px) кнопки стояли разной высоты - замер
   21.09 на 375px. Ширина «В корзину» тянется flex'ом, лишние 4px на каждой
   из двух кнопок она отдаёт сама. */
.hot-fav {
    flex: 0 0 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #fff;
    border: 1px solid #c2c8ce;
    border-radius: 8px;
    cursor: pointer;
}

.hot-fav i {
    font-size: 18px;
    color: #FF7700;
}

.hot-fav.is-active {
    background: #FF7700;
    border-color: #FF7700;
}

.hot-fav.is-active i {
    color: #fff;
}

/* === Кнопка «Сравнение» рядом с «В корзину» слева === */
.hot-compare {
    flex: 0 0 44px;
    height: 44px;
    background: #fff;
    border-radius: 8px;
    border: 1px solid #c2c8ce;
    cursor: pointer;
    display: flex;
    justify-content: center;
    align-items: center;
}

.hot-compare i {
    font-size: 16px;
    color: #474647;
}

.hot-compare.is-active { background: #168bd4; }

.hot-compare.is-active i { color: #fff; }

.hot-toggle-row {
    display: flex;
    align-items: stretch;
    border-top: 1px solid var(--zd-line, #E0E0E0);
}

/* 44px и 14px - правило проекта: зона нажатия не ниже 44, текст не мельче 14
   (аудитория 40-65+). Было 40px высоты и 12px шрифта. Ряд широкий (349px на
   375px экрана), надпись помещается с запасом. */
.hot-toggle {
    flex: 1;
    height: 44px;
    border: none;
    background: transparent;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 12px;
    font-weight: 600;
    font-size: 14px;
    color: #8a8a8a;
    letter-spacing: 0.3px;
    transition: color 0.2s ease;
}

.hot-toggle::before {
    content: "Характеристики";
}

.hot-card.info-switched .hot-toggle::before {
    content: "Свернуть";
}

/* Казахская версия (/kk/): подпись кнопки на языке страницы. */
html[lang="kk"] .hot-toggle::before {
    content: "Сипаттамалар";
}

html[lang="kk"] .hot-card.info-switched .hot-toggle::before {
    content: "Жию";
}

/* «Свернуть» тоже по центру */
.hot-card.info-switched .hot-toggle {
    justify-content: center;
}

.hot-toggle-more {
    /* всегда в потоке, но схлопнута до нулевой ширины */
    display: flex;
    align-items: center;
    overflow: hidden;
    max-width: 0;
    padding: 0;
    opacity: 0;
    pointer-events: none;
    /* 12 -> 14px: ссылка «Подробнее» ведёт в карточку товара, её должно быть
       видно, а не угадывать. */
    font-size: 14px;
    font-weight: 600;
    color: #01A572;
    text-decoration: none;
    white-space: nowrap;
    border-left: none;
    transition: max-width 0.4s ease, opacity 0.35s ease, padding 0.4s ease;
}

/* плавно раскрывается при открытых характеристиках */
.hot-card.info-switched .hot-toggle-more {
    max-width: 120px;
    opacity: 1;
    padding: 0 12px;
    border-left: 1px solid #eee;
    pointer-events: auto;
}

.hot-toggle-more:hover { color: #018f63; }

/* Товар без заполненных характеристик (lib/product-card.php не печатает у
   него кнопку — открывать нечего): «Подробнее» занимает всю строку и видно
   его сразу, а не после раскрытия. Переходы те же, что у обычной карточки,
   поэтому визуально строка не отличается ничем, кроме подписи. */
.hot-toggle-row--nospecs .hot-toggle-more {
    flex: 1;
    max-width: none;
    height: 40px;
    padding: 0 12px;
    opacity: 1;
    pointer-events: auto;
    justify-content: center;
}

/* === MINI-INFO OVERLAY ===
   Единый подход: position:absolute overlay с opacity/visibility/transform.
   Мобиле → позиционируется внутри .hot-main-row (перекрывает img + content).
   Десктоп → позиционируется внутри .content-wrapper (overlay только под img). */
.mini-info {
    display: flex;
    flex-direction: column;
    box-sizing: border-box;
    /* скрытое состояние */
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: translateY(8px);
    transition: opacity 0.28s ease, transform 0.28s ease, visibility 0s linear 0.28s;
}

.hot-card.info-switched .mini-info {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translateY(0);
    transition: opacity 0.28s ease, transform 0.28s ease, visibility 0s linear 0s;
}

/* Мобиле: плавное in-flow, все анимации синхронны (0.3s ease) */
@media (max-width: 767px) {
    /* img-box: сжимается */
    .hot-card .hot-img-box {
        max-width: 150px;
        transition: max-width 0.3s ease, min-width 0.3s ease, opacity 0.3s ease;
    }
    .hot-card.info-switched .hot-img-box {
        max-width: 0;
        min-width: 0;
        opacity: 0;
        overflow: hidden;
    }

    /* main-info части — те же тайминги */
    .main-info .hot-name-en,
    .main-info .brand-logo,
    .main-info .brand-country,
    .main-info .hot-rating,
    .main-info .hot-price-box {
        overflow: hidden;
        transition: opacity 0.3s ease, max-height 0.3s ease, margin 0.3s ease;
    }
    /*
     * Потолки ниже нужны только затем, чтобы блок было куда схлопывать при
     * перевороте карточки (max-height: 0). Но overflow: hidden режет их и в
     * обычном состоянии, поэтому каждое число обязано быть НЕ МЕНЬШЕ реальной
     * высоты содержимого. Замер на 375px: name-en 21, rating 21, цена 42
     * (12px отступ + строка 30px), со старой ценой строк две - 72.
     * Прежние 18/18/28 срезали цену на 14px: «15 500 ₸» и «Цена договорная»
     * были разрезаны пополам по всему каталогу на телефоне.
     */
    .main-info .hot-name-en { max-height: 44px; } /* две строки (main.css: line-clamp 2) */
    /* Потолок анимации = высота слота + запас на отступ. Слот опущен
       40 -> 32px, потолок едет за ним: оставь 42px - на мобильной раскладке под
       знаком повиснет 10px пустоты в свёрнутом состоянии.
       */
    /* Логотип (32px) и чип страны (14px + отступ 22px) занимают одинаковое
       место по высоте - см. блок .hot-card ниже; потолок у них поэтому общий и
       считается по большему. Прежние 18px у чипа срезали бы его вместе с
       флагом ровно пополам. */
    .main-info .brand-logo,
    .main-info .brand-country { max-height: 36px; }
    /* 44px = две строки. Подпись рейтинга не переносится (white-space: nowrap
       ниже), но если на каком-то экране перенос всё же случится, пусть карточка
       станет выше - это видно и чинится, а обрезанная строка молчит. */
    .main-info .hot-rating { max-height: 44px; }
    .main-info .hot-price-box { max-height: 72px; }

    .hot-card.info-switched .main-info .hot-name-en,
    .hot-card.info-switched .main-info .brand-logo,
    .hot-card.info-switched .main-info .brand-country,
    .hot-card.info-switched .main-info .hot-rating,
    .hot-card.info-switched .main-info .hot-price-box {
        opacity: 0;
        max-height: 0;
        margin-bottom: 0;
    }
    .hot-card.info-switched .main-info {
        flex-grow: 0;
        padding-bottom: 0;
        transition: padding 0.3s ease, flex-grow 0.3s ease;
    }
    .hot-card.info-switched .main-info .hot-name-ru {
        -webkit-line-clamp: 2;
        margin-bottom: 0;
    }

    /* mini-info: расширение синхронно с остальными */
    .mini-info {
        position: static;
        transform: none;
        max-height: 0;
        overflow: hidden;
        padding: 0 12px;
        opacity: 0;
        visibility: hidden;
        transition: max-height 0.3s ease, opacity 0.3s ease,
                    padding 0.3s ease, visibility 0s linear 0.3s;
    }
    .hot-card.info-switched .mini-info {
        max-height: 400px;
        padding: 10px 8px 48px; /* нижний паддинг под пилюлю «Подробнее» */
        opacity: 1;
        visibility: visible;
        transition: max-height 0.3s ease, opacity 0.3s ease,
                    padding 0.3s ease, visibility 0s linear 0s;
    }
}

/* Десктоп: overlay только над content-wrapper, картинка остаётся */
@media (min-width: 768px) {
    /*
     * РАСТЁТ ПОД СОДЕРЖИМОЕ, А НЕ РЕЖЕТ ЕГО.
     *
     * Было жёстко 170px с overflow: hidden. Блок с длинным названием в них не
     * влезал: замер на /proizvoditel/china/ - содержимое 195px в окне 170px,
     * то есть 12px срезано сверху (верх заголовка) и 13px снизу. Владелец:
     * «почему названия улетело куда-то».
     *
     * min-height оставляем прежним - ряд не должен схлопываться на коротких
     * карточках. overflow: hidden тоже остаётся: этот блок - позиционирующий
     * родитель для оверлея .mini-info (inset: 0), который при перевороте
     * карточки не должен вылезать за её края.
     */
    .content-wrapper {
        position: relative;
        flex: 1 1 auto;
        min-height: 170px;
        overflow: hidden;
    }
    .mini-info {
        position: absolute;
        inset: 0;
        z-index: 3;
        padding: 12px 12px;
        justify-content: flex-start;
        background: var(--card-bg);
    }
}

/* Все li в hot-props — обрезаются по ширине через ellipsis (nowrap уже задан выше) */

/* === Мобиле: "Подробнее" приподнята к характеристикам, "Свернуть" растягивается === */
@media (max-width: 767px) {
    .hot-card.info-switched .hot-toggle-more {
        position: absolute;
        left: 50%;
        bottom: 96px; /* сидит точно над .hot-add-flex независимо от высоты пропов/заголовка */
        transform: translateX(-50%);
        max-width: none;
        width: auto;
        padding: 7px 16px;
        background: #f4f5f7;
        border-left: 0;
        border-radius: 8px;
        font-size: 14px;
        z-index: 4;
    }
    .hot-card.info-switched .hot-toggle {
        flex: 1 1 100%;
        justify-content: center;
    }
}

/* Like скрываем при открытом overlay (label остаётся видимым) */
.hot-card.info-switched .hot-like {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s ease;
}

.hot-props {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    gap: 7px;
}

.hot-props li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 16px;
    font-weight: 600;
    color: #333333;
    min-width: 0; /* чтобы flex-ребёнок мог сжаться и сработал ellipsis */
}

.hot-props li > span {
    flex: 1;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.hot-prop-icon {
    width: 26px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

/* Цвет задаёт РАЗДЕЛ товара (sections.icon_color, миграция 102): переменную
   ставит lib/product-card.php прямо на .hot-props, поэтому она уезжает и в
   мобильную шторку «Характеристики», которая этот список клонирует. Не задан
   - фирменный зелёный, как было у всех разделов до. Имя переменной то же,
   что на странице товара (card.css): один цвет - одно имя.
   */
.hot-prop-icon i {
    font-size: 14px;
    color: var(--zd-feature-icon, #01A572);
}

.hot-prop-icon img {
    width: 18px;
    height: 18px;
}

.mini-desc {
    font-size: 12px;
    color: #666666;
    margin-top: 12px;
    line-height: 1.4;
    border-top: 1px solid #c2c8ce;
    padding-top: 8px;
}

@media (max-width: 768px) {
  .hot-img-box{
    width: 150px;
    height: 150px;        /* квадрат — одинаковый размер для всех карточек */
    aspect-ratio: 1 / 1;
  }
    .hot-card .hot-like {
        top: 5px;
        right: 5px;
        width: 30px;
        height: 30px;
    }

    /* Характеристики на мобильных — крупнее */
    .mini-info .hot-props { gap: 10px; }
    .mini-info .hot-props li { font-size: 14px; gap: 10px; }
    .mini-info .hot-prop-icon { width: 34px; height: 34px; }
    .mini-info .hot-prop-icon i { font-size: 16px; }
}

@media (max-width: 480px) {
    .mini-info .hot-props { gap: 8px; }
    .mini-info .hot-props li { font-size: 13px; gap: 9px; }
    .mini-info .hot-prop-icon { width: 30px; height: 30px; }
    .mini-info .hot-prop-icon i { font-size: 15px; }
}

@media (min-width: 768px) {
    .mini-info .hot-props { gap: 7px; }
    .mini-info .hot-props li { font-size: 13px; gap: 10px; }
    .mini-info .hot-prop-icon { width: 32px; height: 32px; }
    .mini-info .hot-prop-icon i { font-size: 15px; }
}
@media (min-width: 768px) {
    .hot-card .hot-top { flex-direction: column; }
    .hot-card .hot-main-row { flex-direction: column; }
    .hot-card .hot-img-box {
        width: 100%;
        height: auto;
        aspect-ratio: 1 / 1;
        padding-bottom: 0;   /* убираем мобильный padding — aspect-ratio сам задаёт высоту */
    }
}

.title-category-h1{
  overflow-x: auto;
  white-space: nowrap;
  scrollbar-width: none;
}
.title-category-h1 h1{
  max-width: 1900px;
  margin: 0 auto;
  padding: 5px 0;
  /* Переносом, а не в одну строку: «Результаты: «томат» - 233 товара» и
     категория с брендом уезжали под скрытую прокрутку и читались обрезанными. */
  white-space: normal;
  font-size: 28px;
  /* Цвет заголовка здесь не задавался вовсе, поэтому наследовался
     браузерный чёрный #000. Замер: H1 витрины разъехались на пять «чёрных»
     (#1F1F1F, #000, #2C2C31, #1A1A1A, #333) при том, что размеры везде верные.
     DESIGN.md: цвет H1 ВСЕГДА ink.
     */
  color: var(--zd-ink);
}
@media (max-width: 992px) {
  .title-category-h1 h1{
    /* Было 18px - мельче, чем текст в карточках товара под ним:
       заголовок страницы не может быть меньше своего содержимого.
       22px - ближайшая ступень шкалы 12/14/16/18/22/28/36. */
    font-size: 22px;
  }
}

/* === СТАРЫЕ СКЕЛЕТОНЫ УДАЛЕНЫ — заменены на .hot-card--skel ниже === */

        /* Пагинация */
.pagination-container {
    margin: 40px 0;
    display: flex;
    justify-content: center;
}

.pagination {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: center;
}

.page-btn {
    min-width: 40px;
    height: 40px;
    padding: 0 8px;
    border: 1px solid #c2c8ce;
    background: white;
    border-radius: 8px;
    font-size: 14px;
    color: #333;
    cursor: pointer;
    /* Кнопка страницы меняет только цвета - `all` заставлял браузер сторожить
       и её размеры на каждом кадре (DESIGN.md, «Движение»). */
    transition: background var(--zd-dur-fast) var(--zd-ease),
                border-color var(--zd-dur-fast) var(--zd-ease),
                color var(--zd-dur-fast) var(--zd-ease);
    display: flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    box-sizing: border-box;
}

.page-btn:hover:not(.disabled):not(.active) {
    background: #f5f5f5;
    border-color: #999;
}

.page-btn.active {
    background: #01A572;
    border-color: #01A572;
    color: white;
}

.page-btn.disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.page-dots {
    color: #666;
    font-size: 14px;
    padding: 0 4px;
}

.pagination-info {
    margin-left: 16px;
    color: #666;
    font-size: 14px;
}

/* ============================================
   SKELETON для карточек товара
   1-в-1 повторяет layout .hot-card на всех размерах.
   Переиспользует классы .hot-card / .hot-top / .hot-main-row /
   .hot-img-box / .content-wrapper / .hot-info / .main-info /
   .hot-add-flex — поэтому автоматически совпадает с любыми брейкпойнтами.
   ============================================ */
.hot-card--skel {
    pointer-events: none;
    user-select: none;
}

/* Базовый плейсхолдер .skel + @keyframes skelShimmer переехали в
   css/main.css (единый источник для всех страниц со списком товаров,
   не только каталога) - main.css здесь подключён раньше этого файла,
   каскад не меняется. */

/* Картинка — заполняет .hot-img-box 1:1 */
.hot-card--skel .skel-img {
    width: 100%;
    height: 100%;
    min-height: 130px;
    border-radius: 12px;
    border: 1.5px solid #c2c8ce;
}

/* Icon strip скелетон — зеркалит .hot-icon-strip (абсолют поверх фото) */
.hot-card--skel .skel-icon-strip {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    position: absolute;
    bottom: 8px;
    left: 8px;
    z-index: 2;
}
.hot-card--skel .skel-hip {
    width: 24px;
    height: 24px;
    border-radius: 6px;
}

/* Контент карточки — отступ совпадает с .hot-info (padding:10px) */
.hot-card--skel .main-info {
    gap: 8px;
    display: flex;
    flex-direction: column;
}

.hot-card--skel .skel-name-1   { height: 12px; width: 90%; }
.hot-card--skel .skel-name-2   { height: 12px; width: 65%; }
.hot-card--skel .skel-name-en  { height: 10px; width: 55%; margin-top: 2px; }
.hot-card--skel .skel-brand    { height: 14px; width: 70px; margin-top: 2px; }
.hot-card--skel .skel-rating   { height: 10px; width: 110px; }

.hot-card--skel .skel-price-box {
    display: flex;
    gap: 8px;
    align-items: baseline;
    margin-top: 4px;     /* как у реальной карточки — сразу под рейтингом */
}
.hot-card--skel .skel-price    { height: 16px; width: 80px; }
.hot-card--skel .skel-old      { height: 11px; width: 55px; }

/* Кнопка «В корзину» — повторяет .hot-add (flex:1, 40px, radius 9px) */
.hot-card--skel .skel-btn {
    flex: 1 1 auto;
    height: 40px;
    border-radius: 8px;
    background: var(--zd-skel);
    background-size: 250% 100%;
    animation: skelShimmer 1.8s linear infinite;
}

/* Кнопка «Избранное» — повторяет .hot-fav (42×40, radius 9px) */
.hot-card--skel .skel-fav {
    flex: 0 0 42px;
    height: 40px;
    border-radius: 8px;
    border: 1px solid #c2c8ce;
    background: var(--zd-skel);
    background-size: 250% 100%;
    animation: skelShimmer 1.8s linear infinite;
}

/* Кнопка «Сравнение» — повторяет .hot-compare */
.hot-card--skel .skel-compare {
    flex: 0 0 42px;
    height: 40px;
    border-radius: 8px;
    border: 1px solid #c2c8ce;
    background: var(--zd-skel);
    background-size: 250% 100%;
    animation: skelShimmer 1.8s linear infinite;
}

/* hot-toggle-row скелет — повторяет .hot-toggle-row (40px) */
.hot-card--skel .skel-toggle-row {
    display: flex;
    align-items: stretch;
    border-top: 1px solid var(--zd-line, #E0E0E0);
    height: 40px;
}

.hot-card--skel .skel-toggle {
    flex: 1;
    height: 40px;
    background: transparent;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 12px;
}
.hot-card--skel .skel-toggle::before {
    content: "";
    display: block;
    width: 110px;
    height: 10px;
    border-radius: 4px;
    background: var(--zd-skel);
    background-size: 250% 100%;
    animation: skelShimmer 1.8s linear infinite;
}

/* В реальной карточке «Подробнее» скрыто пока не открыты характеристики */
.hot-card--skel .skel-more {
    display: none;
}
.hot-card--skel .skel-more::before {
    content: "";
    display: block;
    width: 50px;
    height: 10px;
    border-radius: 4px;
    background: var(--zd-skel);
    background-size: 250% 100%;
    animation: skelShimmer 1.8s linear infinite;
}

/* Адаптив скелетона — повторяет мобильный layout карточки */
@media (max-width: 768px) {
    .hot-card--skel .skel-img { min-height: 150px; }
    .hot-card--skel .main-info { gap: 6px; }
    .hot-card--skel .skel-name-1 { height: 11px; }
    .hot-card--skel .skel-name-2 { height: 11px; }
    .hot-card--skel .skel-brand  { height: 12px; width: 60px; }
    .hot-card--skel .skel-price  { height: 14px; width: 70px; }
    .hot-card--skel .skel-old    { height: 10px; width: 48px; }
}

@media (max-width: 480px) {
    .hot-card--skel .skel-img { min-height: 130px; }
    .hot-card--skel .skel-brand { width: 50px; }
}

/* =====================================================================
   ПЛИТКА КАТАЛОГА И ПОИСКА - КРУПНЕЕ
      ---------------------------------------------------------------------
   ПОЧЕМУ ИМЕННО ЗДЕСЬ. Страницы категории и поиска подключают только
   tokens/main/icon-fa/product-page - card.css там НЕ грузится вовсе
   (card-base слит в main.css, эти правила доезжают), хотя плитка носит его
   классы (.hot-name-ru, .hot-price, .stars). Правки, положенные в card.css,
   на витрине просто не работали - проверено замером: правило есть в файле, а
   до страницы не доезжает.

   Базовые размеры в блоке card-base main.css общие ещё и для корзины,
   избранного и сравнения - поднимать их там значило бы раздуть узкие строки
   корзины. Здесь контекст .hot-card, то есть только плитка.
   =====================================================================
   */
.hot-card .hot-name-ru  { font-size: 16px; line-height: 1.25; }
.hot-card .hot-name-en  { font-size: 14px; }

/* === ЦЕНА В РЯДУ СТОИТ НА ОДНОЙ ЛИНИИ ===
   В одном ряду цена стояла на трёх разных высотах.

   ДЕРЖИТ ЕЁ ПРИЖАТЫЙ НИЗ, А НЕ РЕЗЕРВ ВЫСОТЫ. Первый заход задал каждому слоту
   над ценой постоянную высоту - линия выровнялась, но у товара с коротким
   названием и без подзаголовка резерв превратился в пустоту сразу под
   заголовком. Теперь наоборот: текст идёт как идёт, вплотную к
   названию, а блок цены отжимается вниз - у всех карточек ряда он оказывается
   на одной высоте, потому что высота ячейки грида у них общая.

   Тот же приём уже применён в блоке «Также рекомендуем» (card.css,
   .recommend__list) по такой же просьбе - держим одинаково. */
.hot-card .hot-price-box { margin-top: auto; }
/* На ПК цена чуть выше кнопок: прижатый низ давал пустоту под рейтингом. */
@media (min-width: 1025px) { .hot-card .hot-price-box { margin-bottom: 14px; } }

/* Логотип и чип страны делят ОДИН слот: разойдись они по высоте - разъедется и
   строка отзывов под ними. 32px задаёт логотип (main.css), чип подстраивается.
   Отступов по бокам у чипа нет: подложку убрали, и любой padding сдвинул бы
   флаг вправо относительно названия над ним. */
.hot-card .brand-logo {
  height: 32px;
  min-height: 32px;
  margin-bottom: 4px;
}

/* ЛОГОТИП, СТРАНА И СТРОКА ОТЗЫВОВ - ССЫЛКИ НА ТОВАР.
   Покупатель целится в них не реже, чем в название, а промах по пустому месту
   читается как «карточка не открывается». Ведут туда же,
   куда название. Выглядят по-прежнему: цвет свой, подчёркивания нет. */
.hot-card .hot-slot-link { display: block; align-self: flex-start; line-height: 0; }
/* Цвет НЕ переопределяем: чип красит .brand-country, число отзывов -
   .hot-review-count. Задай тут color - и оба правила молча перестанут
   действовать, ссылка спорит с ними по специфичности. Снимаем только
   подчёркивание, которое браузер ставит ссылке сам. */
.hot-card .hot-slot-link,
.hot-card a.brand-country,
.hot-card a.hot-rating { text-decoration: none; }

/* ЧИП СТРАНЫ ЗАНИМАЕТ РОВНО СВОЮ ВЫСОТУ - НИ ЦЕНТРОВКИ, НИ РЕЗЕРВА.
   История в два шага. Сначала чип растягивался на 32px слота логотипа, а
   содержимого в нём 14px: пустота делилась поровну, и флаг стоял на 9px ниже
   текста, тогда как логотип начинался сразу под ним. Прижали вверх, сохранив
   высоту слота (14 + 22 = 32 + 4), - и те же 22px вылезли снизу, между
   страной и строкой отзывов.
   Резерв убран совсем: пустое место в карточке заметнее, чем несовпадение
   строки отзывов с соседней плиткой, у которой логотип. Линию цен в ряду
   держит не он, а прижатый низ блока цены (.hot-price-box{margin-top:auto}). */
.hot-card .brand-country {
  height: auto;
  min-height: 0;
  margin-bottom: 4px;
}
/* Строка цены одной высоты при любом содержимом: число набрано 20px, а «Цена
   договорная» - 16px. */
.hot-card .hot-price { line-height: 30px; }

/* Подпись рейтинга - строго в одну строку. Перенос делает слот вдвое выше
   соседних, и ряд опять расходится. */
.hot-card .hot-review-count { white-space: nowrap; }

/* Телефоны уже 360px: фото 150px забирает больше половины карточки, и текстовой
   колонке остаётся 112px - «Нет отзывов» (92px) в неё уже не встаёт. Ужимаем
   СНИМОК, а не кегль: аудитория 40-65+, текст мельче 14px не опускаем. */
@media (max-width: 359.98px) {
  .hot-card .hot-img-box { max-width: 120px; }
}
.hot-card .hot-price    { font-size: 20px; }
.hot-card .hot-old      { font-size: 14px; }
.hot-card .hot-rating   { font-size: 14px; }
.hot-card .stars        { font-size: 14px; }

/* Плитка без оценок: строка остаётся (иначе ряд разъезжается по высоте),
   но приглушена - одна зелёная звезда без цифр читалась как обрубок. */
.hot-card .hot-rating--empty .stars { color: #c9cdd2; }
.hot-card .hot-rating--empty .hot-review-count {
  font-weight: 500;
  /* #9aa0a6 давал 2.5:1 - почти невидимо. Строка «Нет отзывов» должна
     читаться, а приглушённость даёт уже сам серый. */
  color: #616161;
}

/* Договорная цена: текст вместо цифры. Тише обычной цены - это не число,
   которое сравнивают, а признак «уточняйте у менеджера». Кнопка «Узнать
   цену» ведёт в карточку, где есть «Связаться». */
.hot-price--contract {
  font-size: 16px !important;
  font-weight: 700;
  /* #8a9099 = 3.2:1. «Цена договорная» стоит на месте цены, то есть это
     ключевая для покупателя строка. */
  color: #616161;
  white-space: nowrap;
}
.hot-add--contract {
  display: flex;
  align-items: center;
  justify-content: center;
  /*
   * 8 -> 4px. «Узнать цену» длиннее «В корзину» на три буквы, и в узкой плитке
   * ноутбука ей не хватало ровно 5px: нужно 117px, доступно 112. Раньше
   * недостачу «решал» перенос на две строки - кнопка распухала вдвое и ряд
   * плиток шёл вразнобой; теперь перенос запрещён, поэтому место надо было
   * найти честно.
   *
   * Ужимали ЗАЗОР до значка - до 2px, и значок прилипал к букве «у» вплотную.
   * Место искать этим способом больше не нужно: тесную плитку разруливает
   * контейнерный запрос ниже, он уменьшает надпись там, где не помещается.
   * Возвращаем зазор, который видно, но оставляем его меньше базовых 8px -
   * «Узнать цену» длиннее «В корзину» на три буквы, и лишнего места у неё нет.
   */
  gap: 6px;
  text-decoration: none;
  background: #1E88E5;   /* синий «Связаться», а не оранжевый «В корзину» */
}
/* Значок-стрелка декоративный: смысл несёт надпись. Ужимаем его и зазор, а не
   её: 15px здесь подняты ради читаемости. Замер на самой узкой плитке (230px
   при окне 1280) - надписи нужно 114px, а было доступно 112. */
.hot-add--contract i { font-size: 12px; }
.hot-add--contract:hover { background: #1976D2; }

/* ТЕСНЫЙ РЯД: 250px - порог с запасом. Самый узкий «нормальный» ряд у нас
   294px (телефон 320px), самый широкий проблемный - 230px (ноутбук). Между
   ними 64px, порог посередине не заденет ни одну рабочую раскладку. */
@container zd-buyrow (max-width: 250px) {
    /* 15 -> 14px: минус ~7% ширины надписи. Ниже не опускаемся - 13px уже
       мельче подписей футера, а список товаров читают в первую очередь. */
    .hot-add { font-size: 14px; }
    /* Значки «в избранное» и «сравнить» подписи не несут: они уступают
       по 6px каждый, и эти 12px уходят надписи. Уступка только по ШИРИНЕ -
       высота осталась 44px, как требует правило зоны нажатия; в тесном ряду
       палец всё равно ведут по вертикали. */
    .hot-fav,
    .hot-compare { flex: 0 0 38px; }
}

/* Старые браузеры без контейнерных запросов (до Chrome 105 / Safari 16).
   Ширину плитки они не умеют спросить - подставляем диапазон окна, в котором
   плитка заведомо узкая: от планшета до ноутбука включительно. */
@supports not (container-type: inline-size) {
    @media (min-width: 992px) and (max-width: 1439px) {
        .hot-add { font-size: 14px; }
        .hot-fav,
        .hot-compare { flex: 0 0 38px; }
    }
}

/* ------------------------------------------------------------------
   Опция фильтра, которая ничего не найдёт
      ------------------------------------------------------------------
   Между группами фильтры складываются по И, поэтому пара живых на вид опций
   часто не пересекается: замер по «Семенам томата» дал 519 пар из разных
   групп, и 98 (18.9%) не находили ни одного товара. Панель при этом
   выглядела рабочей - счётчик считался по всей подкатегории и про уже
   нажатые чекбоксы не знал. Человек выбирал «Черри», затем «Крупный» и
   упирался в пустой экран.

   Теперь такие опции видно ДО клика: приглушены и не нажимаются. Класс
   ставит js/filters.js по счётчикам с сервера.

   Приглушение сделано цветом и прозрачностью, а не display:none - исчезающие
   на каждом клике опции перестраивают панель под пальцем, и человек теряет
   место, куда целился. Аудитория 40-65+, это важнее компактности. Контраст
   приглушённого текста держим выше 4.5:1.
   ------------------------------------------------------------------
   */
/* ПРОЗРАЧНОСТЬ ЗДЕСЬ НЕ ГОДИТСЯ. Первая версия гасила чип через
   opacity: 0.55, и замер тут же показал 2.4:1 - то же самое, что я весь
   день убирал по сайту как нечитаемое. Недоступная опция должна ЧИТАТЬСЯ:
   человек по ней понимает, чего нет в наличии при его выборе. Поэтому
   «выключенность» показываем цветом, зачёркиванием и фоном, а не
   растворением: #757575 даёт 4.6:1 и явно отличается от активных. */
.tag--empty {
    cursor: not-allowed;
    background: #F5F5F5;
    border-color: #E0E0E0;
}

.tag--empty span {
    color: #757575;
    text-decoration: line-through;
    text-decoration-thickness: 1px;
}

.tag--empty input {
    cursor: not-allowed;
}

/* Быстрый чип, который при текущем выборе ничего не найдёт. Тот же смысл и
   тот же приём, что у .tag--empty: читаемый серый и зачёркивание вместо
   растворения прозрачностью. */
.quick-filter-chip--empty {
    cursor: not-allowed;
    color: #757575;
    background: #F5F5F5;
    border-color: #E0E0E0;
    text-decoration: line-through;
    text-decoration-thickness: 1px;
}

/* Пусто в категории/выборке/поиске (lib/catalog-list-fragment.php).
   Здесь, а не в categories.css: поиск тот файл не грузит, и блок выходил
   голым - узкой колонкой с фиолетовой ссылкой.
   grid-column: 1 / -1 обязателен: блок лежит внутри .products, а это grid c
   auto-fill-колонками - без растяжки на всю строку он занимал первую колонку
   слева и text-align:center центрировал текст внутри неё, а не на странице.
   */
.cat-empty {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    min-height: 300px;
    margin: 0;
    padding: 48px 20px;
    text-align: center;
    color: var(--zd-text-muted, #6b7280);
}

.cat-empty__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 72px;
    height: 72px;
    margin-bottom: 8px;
    border-radius: 50%;
    background: var(--zd-green-soft, #eaf7f1);
    color: var(--zd-green, #01A572);
    font-size: 30px;
}

.cat-empty__title {
    margin: 0;
    color: #1f1f1f;
    font-size: 22px;
    font-weight: 700;
    line-height: 1.3;
}

.cat-empty__hint {
    margin: 0;
    max-width: 420px;
    font-size: 16px;
    line-height: 1.5;
}

.cat-empty__reset {
    margin-top: 8px;
    padding: 12px 24px;
    border-radius: 12px;
    background: var(--zd-green, #01A572);
    color: #fff;
    font-size: 16px;
    font-weight: 600;
    text-decoration: none;
    transition: background 0.2s ease, transform 0.1s ease;
}

.cat-empty__reset:hover {
    background: #027652;
}

.cat-empty__reset:active {
    transform: translateY(1px);
}

@media (max-width: 600px) {
    .cat-empty {
        min-height: 240px;
        padding: 32px 12px;
    }

    .cat-empty__title {
        font-size: 18px;
    }
}

/* Шторки снизу (сортировка, фильтры, характеристики): по бокам и снизу зазор, чтобы
   страница была видна по краям и окно читалось как всплывающее, а не как карточка;
   ручка с большой зоной хвата (полоска прежняя, тянуть можно за широкую область). */
@media (max-width: 1024px) {
    .panel {
        left: 8px; right: 8px; bottom: var(--zd-sheet-bottom);
        border-radius: 22px;
        max-height: calc(92dvh - var(--zd-sheet-bottom));
        --panel-ty: calc(100% + var(--zd-sheet-bottom) + 8px);
    }
    .panel.active { --panel-ty: 0; }
    .panel-handle { padding: 20px 0 14px; min-height: 44px; }
}
/* Крестик закрытия панелей: кружок 44px с иконкой 22px вместо голой 19px. */
.btn-sort-fil { min-width: 44px; min-height: 44px; border-radius: 50%; background-color: #F2F2F2; }
.btn-sort-fil i { font-size: 22px; }

/* Тянуть вниз оставлено только у фильтра и сортировки; у «Характеристик» жест запускал обновление страницы - закрывают крестиком или нажатием мимо. */
#card-info-panel .panel-handle { display: none; }

/* ===== Шторка «Характеристики»: характеристики, название, фото с метками ===== */
.card-info-panel__img { position: relative; margin: 14px 0 4px; border-radius: 18px; }
.card-info-panel__img .hot-disc { top: 12px; right: 12px; min-height: 34px; padding: 0 12px; border-radius: 17px; font-size: 18px; }
.card-info-panel__marks {
    position: absolute; left: 12px; right: 12px; bottom: 12px; z-index: 3;
    display: flex; flex-direction: column; align-items: center; gap: 8px;
}
.card-info-panel__pills { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.card-info-panel__pills .hbl {
    display: inline-flex; align-items: center; gap: 8px; min-height: 40px; padding: 0 14px 0 10px;
    border-radius: 20px; background: rgba(255, 255, 255, .88); color: #1f1f1f;
    font-size: 15px; font-weight: 700; line-height: 1.1;
}
.card-info-panel__pills .hbl i { font-size: 24px; line-height: 1; }
.card-info-panel__pills .hbl[data-badge="hit"] i      { color: #E53935; }
.card-info-panel__pills .hbl[data-badge="new"] i      { color: #F5B400; }
.card-info-panel__pills .hbl[data-badge="preorder"] i { color: #8E44AD; }
.card-info-panel__marks .hot-express {
    position: static; width: 100%; box-sizing: border-box; min-height: 44px;
    background: rgba(255, 255, 255, .7); font-size: 15px; gap: 8px;
}
.card-info-panel__marks .hot-express i { font-size: 22px; }


/* Правый верхний угол фото в шторке: скидка вплотную к углу (скругление даёт рамка фото), под ней метки столбиком вровень по ширине. */
.card-info-panel__flags {
    position: absolute; top: 0; right: 0; z-index: 3;
    display: flex; flex-direction: column; align-items: stretch; width: max-content; max-width: 70%;
}
.card-info-panel__flags .hot-disc {
    position: static; justify-content: center; min-height: 36px; padding: 0 16px;
    border-radius: 0 0 0 0; font-size: 18px;
}
.card-info-panel__flags .hbl {
    display: flex; align-items: center; gap: 8px; min-height: 40px; padding: 0 14px 0 10px;
    background: rgba(255, 255, 255, .9); color: #1f1f1f; font-size: 15px; font-weight: 700; line-height: 1.1;
    border-bottom: 1px solid rgba(0, 0, 0, .08);
}
.card-info-panel__flags .hbl:last-child { border-bottom: 0; border-radius: 0 0 0 14px; }
.card-info-panel__flags .hot-disc:last-child { border-radius: 0 0 0 14px; }
.card-info-panel__flags .hbl i { font-size: 22px; line-height: 1; }
.card-info-panel__flags .hbl[data-badge="hit"] i      { color: #E53935; }
.card-info-panel__flags .hbl[data-badge="new"] i      { color: #F5B400; }
.card-info-panel__flags .hbl[data-badge="preorder"] i { color: #8E44AD; }
/* Плашка экспресса: по центру снизу, с полями справа и слева. */
.card-info-panel__marks { left: 14%; right: 14%; bottom: 14px; }

@media (max-width: 340px) {
    .card-info-panel__more-btn { font-size: 14px; padding-left: 8px; padding-right: 8px; }
    .card-info-panel__footer { gap: 6px; }
}

/* Одна карточка в сетке не шире экрана (min-content у 1fr раздувал колонку). */
.products { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 768px) {
    .products { grid-template-columns: repeat(auto-fill, minmax(max(220px, calc((100% - 100px) / 6)), 1fr)); }
}
.products > .hot-card { min-width: 0; }

/* Шторка «Характеристики»: фото без рамки и подложки; плашка экспресса как на странице товара; размеры по ширине экрана. */
.card-info-panel__img { border: 0; background: transparent; padding: 0; }
.card-info-panel__marks { left: 8px; right: 8px; bottom: 10px; }
.card-info-panel__marks .hot-express {
    width: auto; max-width: 100%; min-height: clamp(34px, 9.5vw, 40px); padding: 0 clamp(10px, 3.4vw, 18px);
    border-radius: 12px; gap: clamp(6px, 2vw, 10px); justify-content: center;
    background: linear-gradient(135deg, #FF8C1A 0%, #F57600 100%); color: #fff;
    box-shadow: 0 5px 14px rgba(245, 118, 0, .38), inset 0 1px 0 rgba(255, 255, 255, .25);
    font-size: clamp(10.5px, 3.2vw, 12.5px); font-weight: 700; letter-spacing: .2px; text-transform: uppercase; white-space: nowrap;
}
.card-info-panel__marks .hot-express i { color: #fff; font-size: clamp(15px, 4.4vw, 18px); }
.card-info-panel__marks .hot-express span { overflow: visible; text-overflow: clip; }
.card-info-panel__flags .hot-disc { min-height: clamp(30px, 8.5vw, 36px); font-size: clamp(15px, 4.6vw, 18px); padding: 0 clamp(10px, 4vw, 16px); }
.card-info-panel__flags .hbl { min-height: clamp(34px, 9.5vw, 40px); font-size: clamp(13px, 3.9vw, 15px); padding: 0 clamp(10px, 3.4vw, 14px) 0 clamp(8px, 2.6vw, 10px); }
.card-info-panel__flags .hbl i { font-size: clamp(18px, 5.4vw, 22px); }
.card-info-panel__img { width: fit-content; max-width: 100%; margin-left: auto; margin-right: auto; }
@media (max-height: 500px) and (orientation: landscape) {
    .card-info-panel__marks { left: 4px; right: 4px; bottom: 6px; }
    .card-info-panel__marks .hot-express { min-height: 28px; padding: 0 6px; gap: 4px; font-size: 9px; letter-spacing: 0; border-radius: 9px; }
    .card-info-panel__marks .hot-express i { font-size: 13px; }
}
.card-info-panel__marks .hot-express span { white-space: nowrap; }
@media (max-height: 500px) and (orientation: landscape) {
    .card-info-panel__marks .hot-express { white-space: normal; line-height: 1.05; }
    .card-info-panel__marks .hot-express span { white-space: normal; text-align: left; }
}
/* Контейнер строго по фото: метки (скидка, экспресс) не выходят за край, минимальная высота - у самой картинки. */
.card-info-panel__img { min-height: 0; }
.card-info-panel__img img { min-height: 120px; }
/* Плашка экспресса чуть прозрачная. */
.card-info-panel__marks .hot-express {
    background: linear-gradient(135deg, rgba(255, 140, 26, .86) 0%, rgba(245, 118, 0, .86) 100%);
}
/* Шторка «Характеристики»: больше воздуха сверху, нижние углы скруглены. */
@media (max-width: 1024px) {
    #card-info-panel { border-radius: 22px; }
    #card-info-panel .panel-header { padding-top: 24px; padding-bottom: 14px; }
    #card-info-panel .panel-body { padding-top: 18px; }
    #card-info-panel .card-info-panel__footer { border-radius: 0 0 22px 22px; padding-bottom: 16px; }
}
#card-info-panel .panel-header .btn-sort-fil { margin-right: 0; }

/* Логотип-надпись без знака (пропорция от 6:1) ниже общего слота: при 32px буквы крупнее, чем у остальных логотипов. */
.hot-card .brand-logo.brand-logo--wide { width: 130px; max-width: 100%; object-fit: contain; object-position: left center; }

/* Шторка «Характеристики»: крестик на равном расстоянии от верха и правого края. */
@media (max-width: 1024px) {
    /* Крестик по центру высоты шапки: сверху, справа и снизу одинаково ~12px. */
    #card-info-panel .panel-header { position: relative; padding: 22px 68px 22px 16px; }
    #card-info-panel .panel-header .btn-sort-fil { position: absolute; top: 50%; right: 12px; transform: translateY(-50%); margin: 0; }
}
/* Метки на фото: скидка в углу, под ней каждая метка отдельной вкладкой с зазором, вровень с правым краем. */
.card-info-panel__flags { gap: 6px; }
.card-info-panel__flags .hot-disc { border-radius: 0 12px 0 14px; }
.card-info-panel__flags .hbl,
.card-info-panel__flags .hbl:last-child { border-bottom: 0; border-radius: 14px 0 0 14px; box-shadow: 0 1px 4px rgba(0, 0, 0, .12); }
.card-info-panel__flags .hot-disc:last-child { border-radius: 0 12px 0 14px; }

/* Фильтр цены: обводка у всей плашки «От/До», а не у поля внутри неё - кольцо поля обрезалось краем. */
.price-inputs .input-box { cursor: text; transition: box-shadow .15s ease; }
.price-inputs .input-box input,
.price-inputs .input-box input:focus,
.price-inputs .input-box input:focus-visible { outline: none !important; box-shadow: none !important; border: 0 !important; width: 100%; }
.price-inputs .input-box:focus-within { box-shadow: inset 0 0 0 2px #01A572; }

/* Телефон: фильтр и сортировка - шторка с полями 8px по бокам до нижнего меню, без скругления снизу; меню поверх затемнения.
   «Характеристики» остаются окном со скруглениями (правило выше). */
@media (max-width: 1024px) {
    #filter-side, #sort-side {
        left: 8px; right: 8px; bottom: calc(var(--zd-nav-base) + var(--zd-nav-lift));
        border-radius: 22px 22px 0 0;
        max-height: calc(92dvh - var(--zd-nav-base) - var(--zd-nav-lift));
        --panel-ty: calc(100% + var(--zd-nav-base) + var(--zd-nav-lift));
    }
    #filter-side.active, #sort-side.active { --panel-ty: 0; }
    body:has(#filter-side.active, #sort-side.active) .mobile-nav { z-index: 1003; }
}
/* Крестик закрытия: зона нажатия 44px, видимый кружок 36px светлее, значок тоньше и мельче. */
.btn-sort-fil { background-color: transparent; display: inline-flex; align-items: center; justify-content: center; }
.btn-sort-fil i {
    display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 50%;
    background: #F1F3F5; color: #3A3F44; font-size: 15px; transition: background .15s ease, color .15s ease;
}
.btn-sort-fil:hover i, .btn-sort-fil:focus-visible i { background: #E3E7EB; color: #111; }
.btn-sort-fil:active i { transform: scale(.92); }
/* Цена в фильтре: после вставки/автозаполнения Chrome красил поле голубым - фон остаётся прозрачным. */
.price-inputs .input-box input { background: transparent; }
.price-inputs .input-box input:-webkit-autofill,
.price-inputs .input-box input:-webkit-autofill:focus { -webkit-text-fill-color: #1F1F1F; transition: background-color 600000s 0s, color 600000s 0s; }
/* Низ фильтра и сортировки на телефоне прямой - у кнопки «Показать» тоже без скругления. */
@media (max-width: 1024px) { #filter-side .panel-footer, #sort-side .panel-footer { border-radius: 0; } }

/* Скелетон плитки под размеры настоящей (замер): название в две строки + англ., строка фасовки вместо бренда,
   цена 30px, кнопки 44px, «Характеристики» 45px - при подмене на карточки ничего не прыгает. */
.hot-card--skel .skel-name-1,
.hot-card--skel .skel-name-2 { height: 16px; }
.hot-card--skel .skel-name-en { height: 13px; }
.hot-card--skel .skel-brand { height: 14px; width: 60%; }
.hot-card--skel .skel-rating { height: 14px; }
.hot-card--skel .skel-price-box { min-height: 30px; align-items: center; margin-top: 10px; }
.hot-card--skel .skel-price { height: 22px; width: 80px; }
.hot-card--skel .skel-btn,
.hot-card--skel .skel-fav,
.hot-card--skel .skel-compare { height: 44px; }
.hot-card--skel .skel-toggle-row,
.hot-card--skel .skel-toggle { height: 44px; }
.hot-card--skel .skel-toggle-row { height: 45px; box-sizing: border-box; }
@media (max-width: 768px) {
  .hot-card--skel .skel-name-1,
  .hot-card--skel .skel-name-2 { height: 15px; }
  .hot-card--skel .skel-price { height: 20px; width: 75px; }
}
