/*
 * 3-рівневе мега-меню "ОБЕРІТЬ КАТЕГОРІЮ" на головній — порт
 * структури/поведінки з exist.ua (docs/refs/exist-ua-catalog-menu.md),
 * власний файл (не чіпає vendor style.css), підключається ПІСЛЯ нього.
 * Усе меню (усі 3 колонки) прихован за замовчуванням, з'являється на всю
 * ширину вікна браузера при наведенні/фокусі на кнопку "ОБЕРІТЬ
 * КАТЕГОРІЮ" — детальніше в коментарі над `.dropdown__categories--menu`
 * нижче. Колонка 1 (1-й рівень) — фіксованої ширини список ліворуч;
 * колонка 2 (2-й рівень) і колонка 3 (сітка 3-го рівня з іконками) —
 * праворуч, у спільній зоні `.catmenu__panel2-stack`. Яка саме
 * підкатегорія/панель активна — вирішує category-menu.js (hover-intent з
 * grace-period, класи `.hoverintent`/`.is-hover-active`), а чистий CSS
 * `:has(:hover)` (нижче, `:not(.hoverintent)`-правила) лишається no-JS
 * fallback.
 * Кольори/переходи — лише через CSS-змінні теми (style.css :root), без
 * хардкод-hex; та сама токен-логіка, що вже застосована в усій темі.
 */

/*
 * Кастомний скролбар + фікс "дрижання"/стрибків для всіх трьох
 * прокручуваних зон (колонка 1, колонка 2, сітка колонки 3) — бага-репорт
 * власника. `scrollbar-gutter: stable` резервує місце під смугу
 * прокрутки заздалегідь, тож вона не з'являється/зникає "стрибком", коли
 * список стає/перестає бути високим за контент. `overscroll-behavior:
 * contain` — це і є фікс "скрол блокує переміщення курсора": без нього
 * прокрутка списку до кінця "перетікає" на прокрутку сторінки позаду
 * мега-меню (класичний scroll chaining), що і відчувається як ривок.
 * Колір смуги — лише токенами теми (var(--secondary-color)/var(--bg-
 * offwhite-color)), `scrollbar-width: thin` — Firefox, `::-webkit-
 * scrollbar*` — Chrome/Safari/Edge; тач-пристрої скролять нативним
 * інерційним скролом без додаткових властивостей.
 */
.catmenu__list,
.catmenu__panel2-col2,
.catmenu__panel3 {
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
  scrollbar-width: thin;
  scrollbar-color: var(--secondary-color) var(--bg-offwhite-color);
}

.catmenu__list::-webkit-scrollbar,
.catmenu__panel2-col2::-webkit-scrollbar,
.catmenu__panel3::-webkit-scrollbar {
  width: 8px;
}

.catmenu__list::-webkit-scrollbar-track,
.catmenu__panel2-col2::-webkit-scrollbar-track,
.catmenu__panel3::-webkit-scrollbar-track {
  background: var(--bg-offwhite-color);
}

.catmenu__list::-webkit-scrollbar-thumb,
.catmenu__panel2-col2::-webkit-scrollbar-thumb,
.catmenu__panel3::-webkit-scrollbar-thumb {
  background: var(--secondary-color);
  border-radius: 4px;
}

.catmenu__list {
  list-style: none;
  margin: 0;
  padding: 0.6rem 0;
  flex: 0 0 280px;
  overflow-y: auto;
  border-right: 1px solid var(--border-color);
}

.catmenu__item {
  position: relative;
}

.catmenu__item:not(:last-child) {
  border-bottom: 1px solid var(--border-color);
}

.catmenu__link,
.catmenu__link2,
.catmenu__link3 {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
  color: var(--body-text-color);
  text-decoration: none;
  cursor: pointer;
}

.catmenu__link {
  padding: 1rem 1.7rem;
  line-height: 2rem;
  font-size: 1.5rem;
}

.catmenu__label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Обгортка іконка+текст 1-го рівня — окремий флекс-блок ЗБОКУ від стрілки,
   щоб `justify-content: space-between` на .catmenu__link і далі ділив
   простір рівно між двома групами (контент / стрілка), а не трьома
   (іконка / текст / стрілка), інакше з'явився б зайвий розрив між іконкою
   й текстом на вузьких пунктах. */
.catmenu__content {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  min-width: 0;
}

.catmenu__icon {
  display: inline-flex;
  flex-shrink: 0;
  color: var(--secondary-color);
  transform-origin: center;
}

.catmenu__icon svg {
  display: block;
}

/* Мікроанімація іконки — той самий тригер (:hover/:focus-within на
   .catmenu__item), що вже відкриває підменю, тож обидва ефекти стартують
   в один момент. `animation-fill-mode` не заданий (= none): по завершенню
   іконка сама повертається у стан спокою навіть якщо курсор ще на пункті —
   короткий "спалах активності", не безкінечний цикл (п.6 вимог). Кожна
   іконка — свій фізичний рух, не однакове scale/rotate на все (п.3). */
.catmenu__item:hover > .catmenu__link .catmenu__icon--wrench,
.catmenu__item:focus-within > .catmenu__link .catmenu__icon--wrench {
  animation: catmenu-icon-wrench 420ms ease-out;
}

.catmenu__item:hover > .catmenu__link .catmenu__icon--panel,
.catmenu__item:focus-within > .catmenu__link .catmenu__icon--panel {
  animation: catmenu-icon-panel 420ms ease-out;
}

.catmenu__item:hover > .catmenu__link .catmenu__icon--pour,
.catmenu__item:focus-within > .catmenu__link .catmenu__icon--pour {
  animation: catmenu-icon-pour 480ms ease-out;
}

.catmenu__item:hover > .catmenu__link .catmenu__icon--spin,
.catmenu__item:focus-within > .catmenu__link .catmenu__icon--spin {
  animation: catmenu-icon-spin 500ms ease-out;
}

.catmenu__item:hover > .catmenu__link .catmenu__icon--glow,
.catmenu__item:focus-within > .catmenu__link .catmenu__icon--glow {
  animation: catmenu-icon-glow 450ms ease-out;
}

.catmenu__item:hover > .catmenu__link .catmenu__icon--beat,
.catmenu__item:focus-within > .catmenu__link .catmenu__icon--beat {
  animation: catmenu-icon-beat 480ms ease-in-out;
}

.catmenu__item:hover > .catmenu__link .catmenu__icon--cushion,
.catmenu__item:focus-within > .catmenu__link .catmenu__icon--cushion {
  animation: catmenu-icon-cushion 420ms ease-out;
}

.catmenu__item:hover > .catmenu__link .catmenu__icon--adjust,
.catmenu__item:focus-within > .catmenu__link .catmenu__icon--adjust {
  animation: catmenu-icon-adjust 420ms ease-out;
}

.catmenu__item:hover > .catmenu__link .catmenu__icon--gear,
.catmenu__item:focus-within > .catmenu__link .catmenu__icon--gear {
  animation: catmenu-icon-gear 520ms ease-out;
}

/* Автозапчастини — гайковий ключ: короткий закручувальний рух. */
@keyframes catmenu-icon-wrench {
  0% {
    transform: rotate(0deg);
  }
  35% {
    transform: rotate(24deg);
  }
  65% {
    transform: rotate(-8deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

/* Кузовні запчастини — дверна панель: пружне "прилягання" при монтажі. */
@keyframes catmenu-icon-panel {
  0% {
    transform: scale(1);
  }
  40% {
    transform: scale(0.86);
  }
  70% {
    transform: scale(1.08);
  }
  100% {
    transform: scale(1);
  }
}

/* Автохімія — флакон: легкий нахил-"переливання" рідини. */
@keyframes catmenu-icon-pour {
  0% {
    transform: rotate(0deg) translateY(0);
  }
  35% {
    transform: rotate(-20deg) translateY(-1px);
  }
  70% {
    transform: rotate(5deg) translateY(0.5px);
  }
  100% {
    transform: rotate(0deg) translateY(0);
  }
}

/* Шини та диски — колесо: одне повне обертання (360°, без ривка в кінці). */
@keyframes catmenu-icon-spin {
  0% {
    transform: rotate(0deg);
  }
  60% {
    transform: rotate(220deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

/* Автосвітло — фара: короткий імпульс яскравості (масштаб + власне світіння). */
@keyframes catmenu-icon-glow {
  0% {
    opacity: 1;
    transform: scale(1);
    filter: drop-shadow(0 0 0 transparent);
  }
  45% {
    opacity: 0.6;
    transform: scale(1.12);
    filter: drop-shadow(0 0 4px currentColor);
  }
  100% {
    opacity: 1;
    transform: scale(1);
    filter: drop-shadow(0 0 0 transparent);
  }
}

/* Аудіо та електроніка — динамік: пульс у такт, як звукова хвиля. */
@keyframes catmenu-icon-beat {
  0%,
  100% {
    transform: scale(1);
  }
  25% {
    transform: scale(1.16);
  }
  50% {
    transform: scale(0.94);
  }
  75% {
    transform: scale(1.08);
  }
}

/* Інтер'єр — сидіння: м'яке "просідання" оббивки. */
@keyframes catmenu-icon-cushion {
  0% {
    transform: translateY(-2px) rotate(0deg);
  }
  50% {
    transform: translateY(1px) rotate(-4deg);
  }
  100% {
    transform: translateY(0) rotate(0deg);
  }
}

/* Екстер'єр — бокове дзеркало: коротке регулювання нахилу. */
@keyframes catmenu-icon-adjust {
  0% {
    transform: rotate(0deg);
  }
  30% {
    transform: rotate(-11deg);
  }
  65% {
    transform: rotate(8deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

/* Інструменти і обладнання — шестерня: коротке коливання зубців. */
@keyframes catmenu-icon-gear {
  0% {
    transform: rotate(0deg);
  }
  30% {
    transform: rotate(-16deg);
  }
  60% {
    transform: rotate(14deg);
  }
  85% {
    transform: rotate(-4deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

.catmenu__arrow {
  flex-shrink: 0;
  opacity: 0.6;
  transition: var(--transition);
}

.catmenu__item:hover > .catmenu__link,
.catmenu__item:focus-within > .catmenu__link,
.catmenu__item.is-open > .catmenu__link,
.catmenu__item2:hover > .catmenu__link2,
.catmenu__item2:focus-within > .catmenu__link2,
.catmenu__item2.is-open > .catmenu__link2 {
  background: var(--bg-offwhite-color);
  color: var(--secondary-color);
}

.catmenu__item:hover > .catmenu__link > .catmenu__arrow,
.catmenu__item:focus-within > .catmenu__link > .catmenu__arrow,
.catmenu__item2:hover > .catmenu__link2 > .catmenu__arrow,
.catmenu__item2:focus-within > .catmenu__link2 > .catmenu__arrow {
  opacity: 1;
  transform: translateX(2px);
}

/*
 * Ціле мега-меню (усі 3 колонки) — прихований за замовчуванням full-bleed
 * оверлей на всю ширину ВІКНА БРАУЗЕРА (буквально `100vw`, не ширина
 * `.container` сайту — власник явно перевідкрив цю вимогу після першої
 * ітерації й попросив саме так), що з'являється при наведенні/фокусі на
 * `.categories__menu` (кнопка "ОБЕРІТЬ КАТЕГОРІЮ" + сам дропдаун — див.
 * нижче). Вендорські класи `active collapse show` на `#categoriesAccordion`
 * тримали список 1-го рівня видимим ЗАВЖДИ (без жодного CSS, що ховає
 * `.collapse`/reaguє на `show`) — це й був баг: меню лежало поверх контенту
 * сторінки одразу після завантаження, замість з'являтись по наведенню.
 * Тут ця видимість повністю перевизначена через opacity/visibility.
 *
 * Full-bleed трюк: `left: 50%; transform: translateX(-50%); width: 100vw;`
 * коректно розтягує елемент на всю ширину viewport ЛИШЕ якщо його
 * позиційний предок сам центрований у вікні браузера (`left: 50%`
 * рахується як % ВІД ШИРИНИ ПРЕДКА, тож предок має бути настільки ж
 * центрованим, як сам viewport). `.categories__menu` (вузький сайдбар-
 * кнопка, притиснутий ліворуч у своєму рядку) для цього НЕ підходить —
 * дало б панель, зсунуту на сотні пікселів ліворуч за екран (перевірено
 * живим рендером). Тому тут `.categories__menu.mobile-v-none` навмисно
 * `position: static` (нижче), а позиційним предком для `.dropdown__
 * categories--menu` стає найближчий REAL positioned-предок вище —
 * `.header__bottom--inner.position__relative` (той самий рядок хедера,
 * центрований `.container`) — саме він і центрований у вікні, тому
 * математика full-bleed працює коректно. Вертикальний збіг з нижньою
 * межею кнопки лишається точним: обидва — прямі флекс-діти одного рядка
 * однакової висоти, тож `top: 100%` відносно контейнера рядка = та сама
 * Y-координата, що й `top: 100%` відносно самої кнопки.
 */
.categories__menu.mobile-v-none {
  position: static;
}

/*
 * Те саме, але для решти сторінок — і це не дубль, а фікс (02.10).
 *
 * Клас `mobile-v-none` є лише в шаблоні ГОЛОВНОЇ: там вендор віддав дві
 * копії меню (десктопну з цим класом і окрему мобільну `mobile-v-block`).
 * На contact/catalog/product/cart/blog/about/privacy/warranty/checkout/
 * account копія одна й БЕЗ класу — тож правило вище її не чіпало,
 * `.categories__menu` лишався `position: relative`, і full-bleed рахувався
 * від вузької кнопки: панель виїжджала на сотні пікселів ліворуч за екран
 * (власник побачив це на /uk/contact, перша колонка була обрізана).
 *
 * Прив'язка до ширини viewport потрібна однаково на всіх сторінках, а
 * мобільна видимість керується окремо (`.mobile-v-none`/`.mobile-v-block`
 * вище/нижче) — тому тут саме desktop-медіа, а не глобальне правило: нижче
 * 992px десктопна панель не показується взагалі й позиціювання їй ні до
 * чого.
 */
@media only screen and (min-width: 992px) {
  .categories__menu {
    position: static;
  }
}

/*
 * 2026-09-20 → 2026-09-24 (переглянуто): цей блок раніше пришпилював
 * `.header__bottom` (рядок з кнопкою "ОБЕРІТЬ КАТЕГОРІЮ" + мега-меню +
 * дублікат nav-посилань + мовний перемикач) під білою `.header__sticky.
 * sticky`-панеллю під час скролу, щоб мега-меню категорій не ховалось під
 * час наведення (реальний баг: `.header__bottom` — СУСІД `.main__header.
 * header__sticky` у розмітці, а не нащадок, тож без фіксації просто їхав
 * геть зі сторінкою й ховав відкрите мега-меню за фіксованою панеллю).
 * 2026-09-24: власник порівняв результат із вендорським демо
 * (risingtheme.com/.../shop.html) — там при скролі лишається ОДНА біла
 * панель (лого + меню + іконки), бо `.header__bottom` там просто їде геть
 * зі сторінкою, а vendor-правило `.header__sticky.sticky .header__menu.
 * header__sticky--block` (style.css:1667) підміняє пошуковий віджет
 * компактним меню всередині ТІЄЇ Ж панелі. Спитав власника напряму (два
 * рядки лишаються функціональними, але виглядають "двома хедерами" vs один
 * вендорський рядок) — обрав точну вендорську відповідність: кнопка
 * категорій зникає під час скролу так само, як у вендора, доступна знову
 * після повернення нагору. Тому фіксацію `.header__bottom` тут прибрано
 * повністю (замість неї — нижче знову дозволено vendor-підміну меню, яку
 * попередній фікс від 2026-09-24 вимикав саме через дублювання з цим
 * пришпиленим рядком; тепер дублювання немає, бо рядка більше немає).
 * Разом з фіксацією прибрано й компаньйон-перефарбування (2026-09-24,
 * колишній сусідній блок): воно фарбувало саме цей закріплений рядок у
 * білий — сенсу більше немає, бо рядок знову в звичайному потоці й ніколи
 * не накладається на білу sticky-панель.
 */

/*
 * 2026-09-23 → 2026-09-24 (переглянуто): раніше компенсував потік для ДВОХ
 * фіксованих рядків (65px + 55px = 120px), поки `.header__bottom` теж було
 * пришпилено (фікс вище). Відколи `.header__bottom` знову в звичайному
 * потоці (власник обрав точну вендорську відповідність — див. коментар
 * вище), фіксованим лишається лише сам `.header__sticky.sticky` (те саме
 * vendor-правило, style.css:1656-1666) — 65px, виміряно живим рендером,
 * той самий `padding: 1rem 0.5rem` при висоті рядка лого/іконок на цьому
 * брейкпоінті. Значення зменшено зі 120px до 65px відповідно; сам механізм
 * (`:has()`-реакція на JS-клас `.sticky`) не змінився.
 */
@media only screen and (min-width: 992px) {
  body:has(.header__sticky.sticky) {
    padding-top: 65px;
  }
}

/*
 * 2026-09-23 → 2026-09-24 (переглянуто): доповнення до фіксу вище — WCAG
 * 2.2 §2.4.11 (Focus Not Obscured), той самий механізм (`scroll-padding-top`
 * на `<html>`, не `<body>` — обґрунтування без змін). Значення зменшено зі
 * 120px до 65px синхронно з сусіднім правилом, бо фіксованою лишилась лише
 * одна панель (65px) — див. коментар вище.
 */
@media only screen and (min-width: 992px) {
  html:has(.header__sticky.sticky) {
    scroll-padding-top: 65px;
  }
}

/*
 * 2026-09-24: accessibility-lead рев'ю фіксу вище знайшло суміжний, не
 * пов'язаний із сьогоднішньою зміною, але реальний ґеп: `.shop__sidebar--
 * widget` (сайдбар категорій на /uk/catalog, `role="region"` + `tabindex="0"`,
 * render-shop-page.ts) — це vendor-правило `position: sticky; top: 0;`
 * (style.css:8132-8139). `body`/`html`-компенсація вище (`padding-top`/
 * `scroll-padding-top`) стосується лише скролу ДОКУМЕНТА — вона не сягає
 * власного `top` іншого sticky-елемента. Тому щойно `.header__sticky` стає
 * `.sticky` (займає верхні 65px), верхні пункти сайдбара, який сам
 * "прилипає" до `top: 0`, опиняються під фіксованою панеллю (z-index 99) —
 * той самий клас бага WCAG 2.4.11, що й фікс вище, просто в іншому місці,
 * яке той фікс структурно не покриває. Той самий принцип: коли з'являється
 * `.sticky`, зсуваємо точку прилипання сайдбара на ту саму виміряну висоту.
 */
@media only screen and (min-width: 992px) {
  body:has(.header__sticky.sticky) .shop__sidebar--widget {
    top: 65px;
  }
}

/*
 * 2026-09-25: сам "флікер" (клас `.sticky` то з'являється, то зникає на
 * межі скролу) виправлений у `header-sticky.js` (JS-поріг, не CSS) — тут
 * лише візуальний бік прохання власника ("професійна дорога анімація").
 *
 * Вендорське правило (style.css:1656-1665) вже оголошує `transition: 0.3s`
 * — але ТІЛЬКИ на самому класі `.sticky`, тож він працює лише В ОДИН БІК:
 * коли клас з'являється, властивості (padding/box-shadow) плавно їдуть до
 * нового значення; коли клас ЗНІМАЄТЬСЯ (users scrolls back up), transition
 * зникає РАЗОМ із класом, і повернення до базового стану — миттєвий стрибок.
 * Оголошуємо той самий список властивостей на базовому (завжди присутньому)
 * класі `.header__sticky` — тепер симетрично в обидва боки — і замінюємо
 * лінійний вендорський таймінг на easing-криву, яку використовує Material
 * Design для входу/виходу елементів (плавний старт і плавне гальмування,
 * читається як "дорожче", ніж лінійний рух).
 *
 * `position: fixed` саму по собі анімувати не можна (не є animatable
 * властивістю) — перемикання в/із фіксованого позиціювання завжди миттєве;
 * transition тут згладжує лише кольори/тінь/відступи, які й формують
 * основне візуальне враження переходу.
 *
 * `prefers-reduced-motion` — той самий принцип, що в скілі port-partsix-
 * section ("Анімації... поважай prefers-reduced-motion"): вимикаємо
 * transition повністю, стан і так змінюється миттєво класом.
 *
 * 2026-09-25, рев'ю accessibility-lead: обидва правила нижче спершу були
 * написані на голому `.header__sticky` (специфічність 0,1,0). Вендорське
 * `.header__sticky.sticky { transition: 0.3s; }` (style.css:1656, без
 * медіа-умови) має ВИЩУ специфічність (0,2,0) і тому перемагало в каскаді,
 * щойно з'являвся клас `.sticky`, — незалежно від порядку підключення
 * файлів. Живий вимір з `prefers-reduced-motion: reduce` це підтвердив:
 * при ВХОДІ в sticky-стан `transitionDuration` лишався "0.3s" (вендорський),
 * а не "0s" — анімація все одно програвалась, хоча коментар вище обіцяє
 * протилежне. Симетрично це ж різило й "дорожчий" easing лише для стану
 * "вийти" (для входу далі використовувався лінійний вендорський таймінг).
 * Фікс: додаємо `.header__sticky.sticky` в обидва селектори — специфічність
 * зрівнюється (0,2,0 у 0,2,0), і тоді вирішує порядок підключення
 * (category-menu.css вантажиться ПІСЛЯ style.css) — наше правило виграє.
 * На reduced-motion-правилі додатково `!important` (той самий канонічний
 * MDN/WCAG патерн, що вже є в apps/web/app/globals.css) — це правило
 * accessibility-критичне (не просто "краще виглядає"), тож не покладаємось
 * лише на специфічність/порядок проти будь-якого майбутнього вендорського
 * правила з такою ж парою класів.
 */
@media only screen and (min-width: 992px) {
  .header__sticky,
  .header__sticky.sticky {
    transition:
      background-color 0.35s cubic-bezier(0.4, 0, 0.2, 1),
      box-shadow 0.35s cubic-bezier(0.4, 0, 0.2, 1),
      padding 0.35s cubic-bezier(0.4, 0, 0.2, 1);
  }
}
/*
 * 2026-09-28, той самий скріншот власника ("два хедери"): JS-поріг вище
 * (header-sticky.js, фікс 2026-09-28) вже прибрав момент, коли білий
 * sticky-рядок і оригінальний чорний `.header__bottom` видно одночасно.
 * Окремо від цього власник попросив, щоб сама поява білого рядка виглядала
 * "дорожче" — миттєвий class-toggle різкий.
 *
 * `transition` тут не підходить: щойно додається клас `.sticky`, вендорське
 * правило (style.css:1656) в тому самому кадрі дає елементу `position: fixed`
 * і фінальну геометрію — браузер ніколи не рендерить проміжний кадр із
 * `transform: translateY(-100%)`, тож transition-у нема ВІД чого переходити
 * (без ручного forced-reflow хаку в JS, якого свідомо уникаємо). `animation`
 * цієї проблеми не має — вона завжди програється заново від `from`
 * незалежно від того, чи існував такий кадр на екрані раніше.
 *
 * Специфічність/каскад (той самий клас бага, що зловив accessibility-lead
 * 2026-09-25 вище): анімацію оголошено на `.header__sticky.sticky` (0,2,0) —
 * так само, як вендорське `transition: 0.3s` на style.css:1656 (теж 0,2,0,
 * без медіа-умови). Специфічність рівна, тож вирішує порядок підключення:
 * category-menu.css вантажиться ПІСЛЯ style.css (підтверджено:
 * apps/web/lib/legacy-shop/categories-menu.ts додає <link> на category-menu.css
 * перед </head>, вже після style.css), наше правило застосовується останнім.
 * Перевірено (grep по style.css і цьому файлу): жодне інше правило не
 * оголошує `transform` чи `animation` на `.header__sticky`/`.main__header` у
 * будь-якому стані — тож кінцевий кадр (`translateY(0)`, `opacity: 1`)
 * дорівнює природному стану спокою без анімації. Тому `animation-fill-mode`
 * лишаємо дефолтним (`none`): після завершення анімації властивості просто
 * повертаються до "не заданих" — це ті самі значення, без стрибка в кінці,
 * `forwards` не потрібен.
 *
 * Таймінг узгоджений з transition вище (0.35s, той самий easing) — зсув і
 * зміна кольору/тіні читаються як один рух.
 *
 * Вихід (скрол угору, клас знімається) навмисно БЕЗ анімації — власник просив
 * лише про появу, а `position: fixed` все одно не є animatable властивістю,
 * тож зникнення завжди миттєве незалежно від keyframes.
 *
 * 2026-09-28, accessibility-lead рев'ю перед мержем: єдиний знайдений
 * нюанс (Minor, не блокер) — якщо клавіатурний користувач тримає фокус на
 * елементі всередині `.main__header` (лого/пошук/акаунт/кошик — вони
 * фокусовані завжди, sticky чи ні) і прокрутить повз поріг МИШКОЮ/колесом,
 * не рухаючи фокус, той сфокусований контрол на 350мс стає прозорим
 * (opacity: 0 → 1) замість миттєвої появи як було. Раніше прийнятний той
 * самий клас ризику вже існує в transition вище (2026-09-25, background-
 * color/box-shadow/padding під сфокусованим контролом) — не новий тип
 * ризику, лише трохи глибший приклад того самого; власник явно просив і
 * translateY, і fade (opacity), тому лишаємо як просив, а не мовчки
 * прибираємо частину запитаної анімації. Якщо колись знадобиться прибрати
 * навіть цей крайній випадок — прибрати `opacity` з обох keyframes нижче,
 * лишити лише `transform`.
 */
@media only screen and (min-width: 992px) {
  .header__sticky.sticky {
    animation: header-sticky-enter 0.35s cubic-bezier(0.4, 0, 0.2, 1);
  }
}

@keyframes header-sticky-enter {
  from {
    transform: translateY(-100%);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .header__sticky,
  .header__sticky.sticky {
    transition: none !important;
    animation: none !important;
  }
}

.dropdown__categories--menu {
  position: absolute;
  top: 100%;
  left: 50%;
  width: 100vw;
  transform: translateX(-50%);
  margin-top: 0;
  max-height: min(80vh, 620px);
  overflow: hidden;
  background: var(--body-background-color);
  border: 2px solid var(--secondary-color);
  border-top: none;
  box-shadow: 0 15px 35px rgba(0, 0, 0, 0.15);
  opacity: 0;
  visibility: hidden;
  /*
   * 2026-09-20: реальна причина бага "меню випливає само по собі, курсор
   * ще й не наводився на кнопку" (бага-репорт власника). `visibility:
   * hidden` ховає ВІЗУАЛЬНО, але сама панель — це `position: absolute`
   * блок 100vw завширшки й до 620px заввишки, що лежить одразу під
   * хедером (реальна геометрія в DOM, `visibility` цього не змінює). Курсор
   * дійсно був "десь внизу" в сенсі скролу — власник мав на увазі "не на
   * кнопці", а десь у контенті нижче хедера — рівно там, де ця невидима
   * панель фізично лежить. Через те, що вона DOM-нащадок `.categories__
   * menu`, будь-яке наведення на цю зону (навіть коли панель невидима)
   * рахувалось як наведення на `.categories__menu` — і `:hover`-правило
   * нижче відкривало меню. `pointer-events: none` тут прибирає саму
   * панель з-під курсора, поки вона закрита: тепер `.categories__menu:hover`
   * може стати true ЛИШЕ через наведення на реальну малу кнопку
   * (categories__menu--header), а не на привид-геометрію прихованої панелі.
   */
  pointer-events: none;
  transition: var(--transition);
  z-index: 50;
}

/*
 * `:not(.menu-js)` — лише no-JS fallback. `category-menu.js` додає
 * `.menu-js` на wrapper одразу при ініціалізації й далі керує видимістю
 * ВИКЛЮЧНО через `.menu-open` (нижче) — той самий принцип, що вже є в цьому
 * файлі для колонок 2/3 (`.hoverintent`/`.is-hover-active`). Без цього
 * розділення клік/Enter/Escape зі скрипта не мали ефекту: клік по кнопці
 * (tabindex="0") сам надає їй фокус — і сире `:focus-within` тримало б
 * меню видимим завжди, ігноруючи стан, який виставляє JS (живий
 * Playwright-тест: після Escape панель лишалась visible, бо фокус
 * лишався на кнопці всередині wrapper).
 */
.categories__menu:not(.menu-js):hover .dropdown__categories--menu,
.categories__menu:not(.menu-js):focus-within .dropdown__categories--menu {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

/*
 * `.menu-open` — єдине джерело правди видимості, коли JS ініціалізувався
 * (`.menu-js`). Виставляється наведенням/фокусом усередині групи АБО
 * кліком/Enter/Space по кнопці (рівноправна друга точка входу — власник:
 * "лише при наведенні або натисканні"); знімається відведенням курсора,
 * виходом фокуса з групи, кліком поза меню чи Escape. Уся логіка —
 * category-menu.js.
 */
.categories__menu.menu-js.menu-open .dropdown__categories--menu {
  opacity: 1;
  visibility: visible;
  /* Після відкриття панель має лишатись клікабельною/наводжуваною — саме
     наведення НА НЕЇ (2/3 колонки, пункти) підтримує відкритий стан. */
  pointer-events: auto;
}

/* Видимий фокус-стан на самій кнопці-тригері (WCAG 2.4.7) — раніше кнопка
   не була фокусованою взагалі (tabindex додано разом із цим фіксом,
   categories-menu.ts). */
.categories__menu--header:focus-visible {
  outline: 2px solid var(--body-background-color);
  outline-offset: -4px;
}

.catmenu__shell {
  display: flex;
  align-items: stretch;
  height: 100%;
  max-height: min(80vh, 620px);
}

/*
 * Колонка 2/3 для ОДНОГО пункту колонки 1 — усі 9 `.catmenu__panel2`
 * накладені один на одного всередині `.catmenu__panel2-stack` (той самий
 * принцип, що й нижче для колонки 3 всередині кожного `.catmenu__panel2`):
 * яка саме показана, вирішує CSS `:has()` за ПОЗИЦІЄЮ (:nth-child)
 * наведеного/сфокусованого пункту колонки 1, з дефолтом на перший пункт.
 * Завдяки стеку панель завжди займає ту саму зону праворуч від колонки 1
 * (не "з'їжджає" вниз за Y-координатою наведеного рядка, як було б при
 * позиціюванні `.catmenu__panel2` відносно свого власного `<li>`).
 */
.catmenu__panel2-stack {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
}

.catmenu__panel2 {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: stretch;
  opacity: 0;
  visibility: hidden;
  /*
   * 2026-09-20: та сама проблема, що й нижче в `.catmenu__panel3` (той
   * самий Playwright-репродукований бага-репорт власника про 3-й рівень),
   * але ще на рівень вище: усі 9 `.catmenu__panel2` (по одному на кожен
   * пункт колонки 1) — теж накладені сиблінги в `.catmenu__panel2-stack`.
   * Без `pointer-events: none` тут кожен НЕАКТИВНИЙ `.catmenu__panel2`
   * (наприклад, "Інструменти і обладнання", поки наведено "Автозапчастини")
   * усе одно лишався клікабельним — а оскільки category-menu.js ініціалізує
   * дефолтну колонку-2→3 групу для КОЖНОГО з 9 panel2 одразу при завантаженні
   * (не лише для активного), його ВЛАСНИЙ дефолтний `.catmenu__panel3.is-
   * hover-active` (з поверненим нижче `pointer-events: auto`) лишався
   * "видимим для курсора", перехоплюючи наведення на пункти 3-го рівня
   * зовсім іншої, візуально закритої категорії (підтверджено: наведення на
   * "Моторна олива" під "Автозапчастини" фактично влучало в "Ключі та
   * набори ключів" з панелі іншого пункту колонки 1). Той самий принцип
   * фіксу: закритий panel2 — поза hit-test, активний повертає auto нижче.
   */
  pointer-events: none;
  transition: var(--transition);
}

.catmenu__shell:not(.hoverintent) .catmenu__panel2-stack > .catmenu__panel2:first-child {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:not(:first-child):hover)
  .catmenu__panel2-stack
  > .catmenu__panel2:first-child,
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:not(:first-child):focus-within)
  .catmenu__panel2-stack
  > .catmenu__panel2:first-child {
  opacity: 0;
  visibility: hidden;
}

/*
 * Робочий стан з JS (category-menu.js): скрипт додає `.hoverintent` на
 * корінь групи й сам вирішує, який пункт активний, через `.is-hover-active`
 * (з grace-period перед скиданням на дефолт — фікс "флешингу" підменю при
 * діагональному русі курсора до колонки 2/3, бага-репорт власника,
 * скріншот 3). Усі `:has(:hover)`-правила вище — no-JS fallback, працюють
 * лише поки `.hoverintent` відсутній (`:not(.hoverintent)` guard), щоб два
 * механізми не змагались за видимість однієї й тієї ж панелі.
 */
.catmenu__shell.hoverintent .catmenu__panel2-stack > .catmenu__panel2 {
  opacity: 0;
  visibility: hidden;
}

.catmenu__shell.hoverintent .catmenu__panel2-stack > .catmenu__panel2.is-hover-active {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.catmenu__item.is-hover-active > .catmenu__link {
  background: var(--bg-offwhite-color);
  color: var(--secondary-color);
}

/* Позиційне зіставлення "пункт N колонки 1 → панель N колонки 2/3" — no-JS
   fallback, з запасом до 20 пунктів (реально 9 гілок, запас на майбутнє). */
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(2):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(2),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(2):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(2),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(3):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(3),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(3):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(3),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(4):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(4),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(4):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(4),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(5):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(5),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(5):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(5),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(6):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(6),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(6):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(6),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(7):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(7),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(7):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(7),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(8):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(8),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(8):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(8),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(9):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(9),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(9):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(9),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(10):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(10),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(10):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(10),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(11):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(11),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(11):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(11),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(12):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(12),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(12):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(12),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(13):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(13),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(13):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(13),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(14):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(14),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(14):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(14),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(15):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(15),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(15):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(15),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(16):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(16),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(16):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(16),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(17):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(17),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(17):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(17),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(18):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(18),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(18):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(18),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(19):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(19),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(19):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(19),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(20):hover) .catmenu__panel2-stack > .catmenu__panel2:nth-child(20),
.catmenu__shell:not(.hoverintent):has(.catmenu__list > .catmenu__item:nth-child(20):focus-within) .catmenu__panel2-stack > .catmenu__panel2:nth-child(20) {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.catmenu__panel2-col2 {
  flex: 0 0 260px;
  overflow-y: auto;
  border-right: 1px solid var(--border-color);
}

.catmenu__list2 {
  list-style: none;
  margin: 0;
  padding: 0.6rem 0;
}

.catmenu__item2 {
  position: relative;
}

.catmenu__link2 {
  padding: 0.7rem 1.5rem;
  line-height: 1.9rem;
  font-size: 1.4rem;
  white-space: normal;
}

.catmenu__item2.has-children > .catmenu__link2 {
  padding-right: 1rem;
}

/*
 * Колонка 3 — стек `.catmenu__panel3` (по одній на кожен пункт колонки 2,
 * навіть порожній — common.ts/categories-menu.ts тримає їх ПОЗИЦІЙНО
 * синхронними), усі накладені один на одного (position:absolute; inset:0)
 * і перемикаються видимістю. Яка саме показана — вирішує `:has()` за
 * ПОЗИЦІЄЮ (:nth-child) навела/фокусу відповідного пункту колонки 2, а
 * не по slug — і працює ОДНАКОВО для всіх 9 мега-панелей одразу (кожна
 * `.catmenu__panel2` — власний корінь :has(), тому позиція не плутається
 * між різними верхніми категоріями). Дефолт — перший пункт активний одразу
 * після відкриття (як на exist.ua), без жодного JS.
 */
.catmenu__panel2-col3 {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
}

.catmenu__panel3 {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  padding: 1.4rem 1.6rem;
  opacity: 0;
  visibility: hidden;
  /*
   * 2026-09-20: баг-репорт власника — на 3-му рівні (сітка "Моторна олива"/
   * "Фільтр салону" тощо) наведення на пункт не підсвічує його, і саме
   * меню "збивається". Причина та сама, що вже була знайдена й пофіксена
   * вище для `.dropdown__categories--menu` (Playwright підтвердив
   * ідентичний механізм): усі `.catmenu__panel3` для ОДНІЄЇ колонки 2 —
   * сиблінги, накладені один на одного (`position:absolute; inset:0`), і
   * лише один з них видимий (`.is-hover-active`/`:first-child`). Без
   * `pointer-events: none` тут invisible-сиблінги (пізніші в DOM, отже
   * "зверху" в стеку за замовчуванням) усе одно перехоплюють курсор:
   * `document.elementFromPoint` на пікселі видимого пункту "Моторна олива"
   * фактично повертав `<a>` з ЗОВСІМ ІНШОЇ, невидимої панелі ("Ключі та
   * набори ключів") — тому `:hover` ніколи не спрацьовував на тому пункті,
   * який власник бачив і наводив, а сам рух курсору "провалювався" в чужу
   * невидиму розмітку. Той самий фікс: закрита панель — поза межами
   * hit-test, активна повертає собі `pointer-events: auto` в кожному
   * правилі видимості нижче.
   */
  pointer-events: none;
  transition: var(--transition);
}

.catmenu__panel2:not(.hoverintent) .catmenu__panel2-col3 > .catmenu__panel3:first-child {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:not(:first-child):hover)
  .catmenu__panel2-col3
  > .catmenu__panel3:first-child,
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:not(:first-child):focus-within)
  .catmenu__panel2-col3
  > .catmenu__panel3:first-child {
  opacity: 0;
  visibility: hidden;
}

/* Робочий стан з JS — той самий принцип, що вище для колонки 1 → 2/3
   (`.hoverintent`/`.is-hover-active`, category-menu.js), лише корінь групи
   тут — сам `.catmenu__panel2` (кожна активна мега-панель ініціалізує
   власну вкладену hover-intent групу для своєї колонки 2 → 3). */
.catmenu__panel2.hoverintent .catmenu__panel2-col3 > .catmenu__panel3 {
  opacity: 0;
  visibility: hidden;
}

/*
 * 2026-09-20: `.catmenu__panel2.hoverintent` (без `.is-hover-active`)
 * тут навмисно — це правило мало б спрацьовувати ТІЛЬКИ для панелі, що
 * зараз активна на 1-му рівні. Але `visibility`/`pointer-events`
 * успадковуються, а НЕ блокують явний override у нащадка: НЕАКТИВНИЙ
 * panel2 (visibility:hidden, pointer-events:none від батьківського
 * правила вище) все одно містив свій ВЛАСНИЙ дефолтний
 * `.catmenu__panel3.is-hover-active` (JS ставить його на кожен з 9 panel2
 * одразу при ініціалізації, не лише на активний) — і це правило без
 * додаткової умови на `.is-hover-active` САМОГО panel2 повертало
 * visibility/pointer-events назад для нащадка, "проколюючи" приховану
 * панель. Підтверджено Playwright: наведення на "Моторна олива" під
 * "Автозапчастини" фактично влучало в "Ключі та набори ключів" з панелі
 * прихованої категорії "Інструменти і обладнання". Фікс — додаткова умова
 * `.is-hover-active` на САМОМУ `.catmenu__panel2` в селекторі нижче: тепер
 * дефолтна колонка 3 неактивної групи 1-го рівня показується лише коли
 * ця сама група активна.
 */
.catmenu__panel2.hoverintent.is-hover-active .catmenu__panel2-col3 > .catmenu__panel3.is-hover-active {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.catmenu__item2.is-hover-active > .catmenu__link2 {
  background: var(--bg-offwhite-color);
  color: var(--secondary-color);
}

/* Позиційне зіставлення "пункт N колонки 2 → панель N колонки 3" — no-JS
   fallback, генерично для всіх 9 мега-панелей одразу, з запасом до 20
   пунктів (найбільша гілка, "Автозапчастини", має 19). Якщо колись з'явиться
   гілка з ще більшою
   кількістю підкатегорій — додати ще нумерованих пар за тим самим шаблоном. */
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(2):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(2),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(2):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(2),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(3):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(3),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(3):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(3),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(4):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(4),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(4):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(4),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(5):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(5),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(5):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(5),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(6):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(6),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(6):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(6),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(7):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(7),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(7):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(7),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(8):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(8),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(8):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(8),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(9):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(9),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(9):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(9),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(10):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(10),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(10):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(10),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(11):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(11),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(11):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(11),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(12):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(12),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(12):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(12),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(13):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(13),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(13):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(13),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(14):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(14),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(14):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(14),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(15):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(15),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(15):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(15),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(16):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(16),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(16):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(16),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(17):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(17),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(17):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(17),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(18):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(18),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(18):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(18),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(19):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(19),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(19):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(19),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(20):hover) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(20),
.catmenu__panel2:not(.hoverintent):has(.catmenu__list2 > .catmenu__item2:nth-child(20):focus-within) .catmenu__panel2-col3 > .catmenu__panel3:nth-child(20) {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

/* Пункт колонки 2, чия панель зараз активна в колонці 3 — те саме hover-
   підсвічування, що вже є на 1-му рівні (.catmenu__link/.catmenu__link2). */
.catmenu__item2:hover > .catmenu__link2,
.catmenu__item2:focus-within > .catmenu__link2 {
  background: var(--bg-offwhite-color);
  color: var(--secondary-color);
}

.catmenu__list3 {
  display: grid;
  /*
   * 2026-09-23: фіксовані 2 колонки давали до 18 рядків для великих
   * категорій (35+ пунктів "Запчастини для ТО", до 76 у "Вузли та деталі
   * двигуна") у панелі заввишки лише ~416px -- 8 рядків видно одразу, решта
   * ховається за внутрішнім скролом .catmenu__panel3. Панель -- 864px
   * завширшки (майже вся ширина 100vw-дропдауна), а 2 колонки лишали
   * величезний запас вільної ширини невикористаним. auto-fill розкладає
   * стільки колонок по >=200px, скільки влазить у реальну ширину -- на
   * десктопі це 4 колонки замість 2, тобто вдвічі менше рядків для тієї ж
   * кількості пунктів, і більшість категорій тепер влазять без скролу
   * замість "розтягнутого" вузького стовпця.
   */
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 0.3rem 2rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.catmenu__item3 {
  min-width: 0;
}

.catmenu__link3 {
  display: flex;
  align-items: center;
  /* `.catmenu__link`/`.catmenu__link2` (спільне правило вище, рядок ~80)
     задають `justify-content: space-between` — з двома дітьми (фото+текст)
     це розсовує їх по краях колонки, лишаючи порожнечу замість щільної
     пари "фото поруч з підписом". Перебиваємо тут же, де вже й так
     власний блок оголошень для 3-го рівня. */
  justify-content: flex-start;
  gap: 0.8rem;
  /* Горизонтальний padding + компенсуючий -margin: сам пункт лишається
     притиснутим до країв колонки (як було), але фон підсвічування нижче
     отримує "подих" по боках — інакше на hover виділявся б лише текст
     впритул, а не пункт-контейнер цілком (бага-репорт власника: "не
     контейнер а просто текст"). */
  padding: 0.5rem 0.6rem;
  margin: 0 -0.6rem;
  border-radius: 8px;
  line-height: 1.8rem;
  font-size: 1.4rem;
  white-space: normal;
}

/* Той самий "контейнер підсвічується цілком" стиль, що вже є на 1-му й
   2-му рівнях (.catmenu__link, .catmenu__item2:hover > .catmenu__link2) —
   власник явно попросив, щоб наведення на пункт 3-го рівня виділяло сам
   пункт, а не лише змінювало колір тексту.
   2026-09-24: власник попросив підсилити цей сірий — замінено токен
   `--bg-offwhite-color` (#F7F7F7) на крок темніший наявний токен
   `--border-color` (#E5E5E5), а не вигаданий hex. TODO(spec) — accessibility
   рев'ю виміряло: контраст `--secondary-color` (#ED1D24) тексту на цьому
   тлі ~3.47:1, гірше за попередній ~4.08:1 і все одно нижче порогу WCAG AA
   4.5:1 для звичайного тексту — те саме вже було правдою й для попереднього
   фону, і однаково правдиво для 1-го й 2-го рівнів (той самий текстовий
   колір на світлому тлі, category-menu.css рядок ~330); навіть чисто білий
   фон дає лише ~4.37:1, тобто цей колір тексту структурно не проходить AA
   на жодному світлому тлі — не нова, і не повністю закрита цією правкою
   вада, власника попереджено окремо. */
.catmenu__link3:hover,
.catmenu__link3:focus-visible {
  background: var(--border-color);
  color: var(--secondary-color);
}

/* Іконка/фото 3-го рівня — квадратне поле-"фото" зі стилю exist.ua
   (Скріншоти 5/6 з бага-репорту), 40x40px (власник явно попросив
   36-40px), лише токенами теми (без хардкод-hex): біла картка з тінню.
   Растрові фото — реальні ліцензовані фото деталей з Wikimedia Commons
   (CC0/CC BY/CC BY-SA, перевірені вручну; АТРИБУЦІЯ — img/parts/
   ATTRIBUTIONS.json), по одному на кожен кластер CATEGORY_ICONS
   (leafIconFor у categories-menu.ts), не по одному унікальному фото на
   кожен з 1258 пунктів — образ exist.ua свідомо НЕ тягнеться (copyright
   конкурента), лише сам принцип "реальне фото, не контурна іконка".
   2026-09-20 (третє коло): фолбек-ротація й "ароматизатор" більше не
   ведуть на 2 кластери без фото (package/airFreshener) — кожен з 1258
   пунктів тепер завжди рендерить `<img>`, `svg`-гілка в `.catmenu__icon3`
   лишається лише як розмітковий рудимент на випадок майбутнього нового
   кластера без фото, а не як активний шлях сьогодні. */
.catmenu__icon3 {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 8px;
  background: var(--body-background-color);
  color: var(--secondary-color);
  border: 1px solid var(--border-color);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
  overflow: hidden;
}

.catmenu__icon3 svg {
  display: block;
}

.catmenu__icon3 img {
  display: block;
  width: 100%;
  height: 100%;
  /* cover, не contain: фото деталей мають різні пропорції (широкі/квадратні/
     видовжені) — contain лишав летербокс-поля з фоном картки навколо фото
     й виглядав неохайно; cover заповнює всю картку без спотворення
     (кадрується, не стискається), overflow:hidden на .catmenu__icon3 не
     дає нічому вилізти за межі 40×40. */
  object-fit: cover;
}

.catmenu__label3 {
  min-width: 0;
}

/* Той самий стиль іконки, менший розмір — для мобільного акордеона
   (category__sub--menu, script.js), де 3-й рівень лишається одноколонковим
   списком, не сіткою. */
.catmenu__icon3m {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  border-radius: 5px;
  background: var(--bg-offwhite-color);
  color: var(--secondary-color);
  margin-right: 0.8rem;
  vertical-align: middle;
}

.catmenu__icon3m svg {
  display: block;
}

.catmenu__icon3m img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 5px;
}

/* Клавіатура: видимий фокус-стан на всіх трьох рівнях (WCAG 2.4.7) */
.catmenu__link:focus-visible,
.catmenu__link2:focus-visible,
.catmenu__link3:focus-visible {
  outline: 2px solid var(--secondary-color);
  outline-offset: -2px;
}

@media (prefers-reduced-motion: reduce) {
  .dropdown__categories--menu,
  .catmenu__panel2,
  .catmenu__panel3,
  .catmenu__arrow {
    transition: none;
  }

  .catmenu__icon--wrench,
  .catmenu__icon--panel,
  .catmenu__icon--pour,
  .catmenu__icon--spin,
  .catmenu__icon--glow,
  .catmenu__icon--beat,
  .catmenu__icon--cushion,
  .catmenu__icon--adjust,
  .catmenu__icon--gear {
    animation: none;
  }
}

/* На вузьких екранах десктопна версія мега-меню не показується (d-none
   d-lg-block на самому catmenu__list, плюс явний фолбек тут — не
   покладаємось лише на bootstrap-утиліти) — мобільна копія нижче в
   розмітці лишається на власному акордеоні (category__sub--menu, script.js). */
@media only screen and (max-width: 991px) {
  /*
   * ≤991px ховаємо саме ДЕСКТОПНУ розмітку мега-меню (`.catmenu__shell` і
   * його панелі), а не весь `.dropdown__categories--menu`.
   *
   * Було навпаки — і це вбивало мобільне меню категорій на ВСІХ сторінках:
   * вендорський мобільний акордеон (`.category__mobile--menu`) лежить
   * усередині того самого `#categoriesAccordion`, тож `display: none` на
   * контейнері ховав і його. Кнопка «ОБЕРІТЬ КАТЕГОРІЮ» на телефоні
   * натискалась, `.menu-open` чесно з'являвся — і нічого не відбувалось
   * (перевірено живим рендером на 390px: головна, контакти, каталог —
   * висота панелі 0 скрізь).
   *
   * Сам контейнер лишається прихованим, поки меню закрите —
   * видимістю завідують `.menu-open`/`:hover`/`:focus-within` нижче, та
   * сама механіка, що на десктопі.
   */
  .catmenu__shell,
  .catmenu__panel2,
  .catmenu__panel3 {
    display: none;
  }
}

/*
 * 2026-09-20 (п'яте коло): додатковий бага-репорт власника — порожня зона
 * ПІД усім хедером (де б там не було іншого контенту, зокрема новий
 * .catshowcase нижче) при наведенні "відкриває" мега-меню. Причина —
 * ГЛИБША за вже пофіксовану "привид-геометрію" `.dropdown__categories--
 * menu` вище: "дефолтна активна" гілка колонки 2/3 (перша категорія,
 * `.catmenu__panel2:first-child`/`.is-hover-active` і вкладений
 * `.catmenu__panel3.is-hover-active`, ~750 рядків вище) отримує
 * `pointer-events: auto` БЕЗУМОВНО — саме так, щоб щось було готове
 * показатись одразу, щойно мега-меню реально відкриють. Але це "безумовно"
 * не враховує, чи меню взагалі зараз відкрите: `.dropdown__categories--
 * menu` як ціле лишається `pointer-events: none` поки закрите, проте
 * pointer-events дозволяє нащадку явно ПОВЕРНУТИ собі auto — і саме цей
 * нащадок ("Автозапчастини" → "Запчастини для ТО" → перша сітка 3-го
 * рівня, напр. "Повітряний фільтр") лежить `position:absolute` рівно в
 * потоці сторінки під хедером (Playwright підтвердив: `elementFromPoint`
 * на тому місці повертає саме цей `<a>`, не те, що там реально видно).
 * Наведення на неї — реальний `mouseenter`, який `category-menu.js`
 * рахує "курсор усередині групи" й відкриває меню по-справжньому.
 * Фікс — чиста адитивна варта, без жодної зміни наявних правил: доки
 * `.categories__menu` НЕ відкрите легітимно (немає ні `.menu-open` від
 * JS, ні `:hover`/`:focus-within` від реальної кнопки), уся "дефолтна
 * активна" геометрія 2/3 колонок примусово `pointer-events: none`. Це не
 * створює замкненого кола: `pointer-events: none` прибирає елемент із
 * хіт-тесту ПОВНІСТЮ, тож наведення на цю зону більше не породжує
 * `:hover`/`mouseenter` на `.categories__menu` через неї — курсор
 * "проходить" до того, що реально під нею (напр. .catshowcase нижче).
 * Коли меню відкривають ЛЕГІТИМНО (реальна кнопка), умова `:not()` стає
 * false і все наявне вище поведінка (яка вже пройшла Playwright-
 * верифікацію) працює як і раніше — це правило просто перестає діяти.
 * Відомий залишковий гап (не новий, не посилюється цим фіксом): Tab на
 * клавіатурі теж може сфокусувати такий глибокий `<a>` і через
 * `:focus-within` тимчасово зняти цю варту — той самий механізм, що вже
 * існував і раніше для видимості мега-меню, окрема, ширша задача.
 */
.categories__menu:not(.menu-open):not(:hover):not(:focus-within) .catmenu__panel2,
.categories__menu:not(.menu-open):not(:hover):not(:focus-within) .catmenu__panel3,
/*
 * Та сама варта для відкритої копії меню в hero головної (`.catmenu-hero`,
 * нижче): і CSS-фолбек (`.catmenu__panel2:first-child`), і hover-intent зі
 * скрипта (`activeIndex = 0` на старті) вважають першу гілку активною за
 * замовчуванням. Для випадайки, яку щойно відкрили, це правильно; для
 * меню, що стоїть відкритим постійно — ні: панель першої категорії висіла
 * б поверх слайдера весь час (зміряно: 380–1340 поверх слайдера 395–1325).
 * Правило дописане саме СЮДИ, а не окремим блоком, бо обидва дефолтні
 * правила мають специфічність (0,5,0) — власна варта нижче за текстом
 * програвала їм і не спрацьовувала; тут `!important` уже є й пояснений.
 */
.catmenu-hero:not(:hover):not(:focus-within) .catmenu__panel2,
.catmenu-hero:not(:hover):not(:focus-within) .catmenu__panel3 {
  visibility: hidden !important;
  pointer-events: none !important;
}

/* ==========================================================================
   Другий, статичний варіант меню категорій (.catshowcase) — плаский список,
   завжди видимий одразу під хедером, для порівняння з основним мега-меню
   вище. Навмисно ЖОДНОГО спільного класу/стану з .categories__menu,
   .dropdown__categories--menu, .catmenu__* — цей блок і його CSS повністю
   незалежні, щоб не міняти поведінку основного меню.
   ========================================================================== */
.catshowcase {
  background: var(--body-background-color);
  padding: 16px 0 24px;
}

/* Обрамлена картка (власник надіслав скрін-референс вендора з рамкою) —
   один суцільний бордер навколо всього списку, тонкі роздільники лише
   МІЖ пунктами всередині, не хардкод-hex (тільки токени теми).
   `display: inline-block` — власник попросив ширину "де закінчується
   текст, там і закінчується рамка" (замість розтягування на всю ширину
   `.container`): inline-block-контейнер стискається до найширшого рядка
   (найдовшої назви категорії), а не займає 100% батьківського блоку. */
.catshowcase__list {
  display: inline-block;
  max-width: 100%;
  list-style: none;
  margin: 0;
  padding: 0;
  border: 2px solid var(--secondary-color);
  border-radius: 12px;
  overflow: hidden;
}

.catshowcase__item {
  border-bottom: 1px solid var(--border-color);
}

.catshowcase__item:last-child {
  border-bottom: none;
}

.catshowcase__link {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  color: var(--body-text-color);
  text-decoration: none;
  transition: var(--transition);
}

.catshowcase__link:hover,
.catshowcase__link:focus-visible {
  color: var(--secondary-color);
}

.catshowcase__link:focus-visible {
  outline: 2px solid var(--secondary-color);
  outline-offset: -2px;
}

.catshowcase__icon {
  display: inline-flex;
  flex: none;
  color: var(--secondary-color);
  transition: transform 0.25s ease;
}

/* Анімація іконки — власник явно попросив рух саме на іконці при наведенні
   й натисканні (не лише зміну кольору тексту, як для решти рядка вище). */
.catshowcase__link:hover .catshowcase__icon,
.catshowcase__link:focus-visible .catshowcase__icon {
  transform: scale(1.2) rotate(-8deg);
}

.catshowcase__link:active .catshowcase__icon {
  transform: scale(0.9) rotate(0deg);
  transition-duration: 0.1s;
}

/* "Інструменти і обладнання" / "Шини та диски" — той самий фізичний рух,
   що вже є в основному мега-меню (catmenu-icon-gear/spin keyframes вище),
   замість generic scale/rotate: закручування ключа й обертання колеса.
   `transform: none` тут перекриває статичний scale(1.2)/rotate(-8deg)
   generic-правила вище (та сама специфічність, останнє правило в каскаді
   перемагає) — інакше після завершення keyframe (без fill-mode) стан різко
   стрибав би в generic-transform, доки курсор ще на пункті. */
.catshowcase__link:hover .catshowcase__icon--gear,
.catshowcase__link:focus-visible .catshowcase__icon--gear {
  animation: catmenu-icon-gear 520ms ease-out;
  transform: none;
}

.catshowcase__link:hover .catshowcase__icon--spin,
.catshowcase__link:focus-visible .catshowcase__icon--spin {
  animation: catmenu-icon-spin 500ms ease-out;
  transform: none;
}

.catshowcase__label {
  flex: 1 1 auto;
  font-size: 1.5rem;
}

.catshowcase__link .catmenu__arrow {
  flex: none;
  color: var(--foreground-sub-color);
}

@media (prefers-reduced-motion: reduce) {
  .catshowcase__link,
  .catshowcase__icon {
    transition: none;
  }

  .catshowcase__link:hover .catshowcase__icon,
  .catshowcase__link:focus-visible .catshowcase__icon,
  .catshowcase__link:active .catshowcase__icon {
    transform: none;
  }

  .catshowcase__link:hover .catshowcase__icon--gear,
  .catshowcase__link:focus-visible .catshowcase__icon--gear,
  .catshowcase__link:hover .catshowcase__icon--spin,
  .catshowcase__link:focus-visible .catshowcase__icon--spin {
    animation: none;
  }
}

/*
 * .home-hero-row__menu — сайдбар-версія .catshowcase, що стоїть РАЗОМ з
 * hero-банером в один рядок (власник побачив банер+меню окремими рядками
 * одне під одним і попросив об'єднати). Заповнює РІВНО ту зону, яку сам
 * вендорський `.hero__slider--ml` (style.css) резервує зліва відступом
 * (`margin-left: 255px`/`280px` — перевірено в reference/partsix
 * _slider.scss, не вигадане число): `position: absolute` тут не "хак", а
 * заповнення вже готового порожнього місця в оригінальній розмітці
 * шаблону. `.hero__slider--section > .container` отримує `position:
 * relative` як точку відліку — більше ніде на сторінці цей селектор не
 * зустрічається, тож жоден інший блок не зачеплений.
 * Нижче 992px `.hero__slider--ml` не має відступу (сам вендор вимикає
 * його там), тож і сайдбар лишається звичайним блоком у потоці (стек над
 * банером), без position:absolute — той самий брейкпоінт, що й вендорський.
 */
.hero__slider--section > .container {
  position: relative;
}

.home-hero-row__menu.catshowcase {
  padding: 0;
  margin-bottom: 16px;
}

.home-hero-row__menu .catshowcase__list {
  display: block;
  max-width: none;
}

@media only screen and (min-width: 992px) {
  .home-hero-row__menu.catshowcase {
    position: absolute;
    top: 0;
    left: 0;
    width: 255px;
    margin-bottom: 0;
  }

  .home-hero-row__menu .catshowcase__list {
    max-height: 100%;
    overflow-y: auto;
  }
}

@media only screen and (min-width: 1200px) {
  .home-hero-row__menu.catshowcase {
    width: 280px;
  }
}

/*
 * .catmenu-hero — меню категорій у hero головної: колонка 1 стоїть
 * ВІДКРИТОЮ в лівій колонці банера, підрівні виїжджають праворуч поверх
 * слайдера при наведенні (власник: «тепер я хочу щоб коли наводиш курсором
 * то вибивало як тут», зі скріншотом відкритої випадайки шапки).
 *
 * Геометрія: обгортка розтягується на ВЕСЬ контейнер hero (не на 255px
 * колонки), бо панелі 2/3 мають місце праворуч — а сама вона прозора й
 * `pointer-events: none`, тож не перехоплює кліки по слайдеру; видимі
 * частини (список і активна панель) повертають собі `auto`. Перша спроба
 * робила навпаки — непрозора панель на всю ширину hero накривала слайдер.
 *
 * `.hero__slider--section > .container` уже `position: relative` (правило
 * вище, для `.home-hero-row__menu`), тож нової точки відліку не треба.
 *
 * Нижче 992px увесь шел і так невидимий (`d-none d-lg-block` на
 * `.catmenu__list` + `display: none` на панелях у блоці `max-width:
 * 991px` вище) — там лишається плаский `.catshowcase`, який на десктопі
 * навпаки ховається.
 */
.catmenu-hero {
  padding: 0;
}

@media only screen and (min-width: 992px) {
  .catmenu-hero {
    position: absolute;
    /* На всю висоту hero, а не по висоті свого вмісту: так колонка стоїть
       врівень зі слайдером (як стояв `.catshowcase` до цього — 196–674
       проти 196–686 у слайдера), а підрівням праворуч дістається вся
       висота банера, а не тільки висота списку з 9 пунктів. */
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    pointer-events: none;
    /*
     * Вище слайдера: `.hero__slider--inner` — це `position: relative;
     * z-index: 1` (вендорський стиль шаблону), тож без власного z-index
     * панелі 2/3 малювались ПІД ним — рамка була видима, а вміст ні
     * (перевірено: `elementFromPoint` у зоні панелі повертав заголовок
     * слайда). Беремо мінімум, що перекриває: 2, а не «щось велике» —
     * липка шапка при скролі має лишатись поверх.
     */
    z-index: 2;
  }

  /* Шел у hero не обмежений висотою випадайки шапки (min(80vh, 620px)) —
     він тягнеться на всю висоту банера. `.catmenu__shell` має `height:
     100%`, але відсоток рахується від батька, а між ним і обгорткою стоїть
     `<nav>` з авто-висотою — без цього рядка 100% розв'язувалось в auto і
     колонка виходила на 38px коротшою за слайдер. */
  .catmenu-hero > nav {
    height: 100%;
  }

  .catmenu-hero .catmenu__shell {
    max-height: none;
  }

  /* Рамка й радіус — ті самі, що в `.catshowcase`, який стояв тут досі й
     який власник уже бачив: червона 2px + 12px радіус, а не дефолтна сіра
     рамка випадайки. `border-right` з базового `.catmenu__list` знімаємо —
     там він розділяв колонки всередині спільної білої панелі, а тут список
     сам собі окремий бокс. */
  .catmenu-hero .catmenu__list {
    pointer-events: auto;
    flex: 0 0 255px;
    max-height: none;
    overflow: hidden;
    background: var(--body-background-color);
    border: 2px solid var(--secondary-color);
    border-right: 2px solid var(--secondary-color);
    border-radius: 12px;
    /*
     * Пункти розтягуються на всю висоту колонки, а не тиснуться догори
     * (власник: «розтягни на весь розмір» — знизу лишалась порожня смуга
     * 38px). Колонка тут заввишки як банер, а пунктів рівно 9, тож ділимо
     * висоту між ними: кожен `flex: 1`. Вертикальні падінги списку
     * знімаємо — інакше зверху й знизу лишались би смужки тла між рамкою
     * і першим/останнім пунктом.
     */
    /*
     * `!important` тут не з примхи: на самому `.catmenu__list` висить
     * bootstrap-утиліта `d-lg-block`, а вона — `display: block !important`.
     * Без цього список лишався блоком, `flex: 1` на пунктах ні на що не
     * впливав, і смуга внизу нікуди не дівалась (перевірено: computed
     * display був `block`). Той самий прийом, що вже застосований у цьому
     * файлі до vendor-утиліт вище.
     */
    display: flex !important;
    flex-direction: column;
    padding: 0;
  }

  .catmenu-hero .catmenu__item {
    display: flex;
    flex: 1 1 auto;
  }

  /*
   * Іконки в hero трохи більші за ті, що у випадайці шапки (власник:
   * «зроби ці іконочки трошки більшими»). Розмір задається саме тут, а не
   * числом у `renderTopLevelIcon(top.slug, 24)`: розмітку шела ділять
   * обидві копії меню, і зміна в TS збільшила б їх заразом і в шапці, де
   * рядки нижчі (45px проти 51–67px тут) і 24px пасують. SVG має власні
   * width/height-атрибути, тож перекриваємо їх стилем на самому елементі.
   */
  .catmenu-hero .catmenu__icon svg {
    width: 30px;
    height: 30px;
  }

  .catmenu-hero .catmenu__link {
    flex: 1;
  }

  /*
   * Панелі 2/3 отримують власне тло: у шапці його давала спільна біла
   * випадайка, якої тут нема — без нього текст лягав би просто на слайдер.
   * Позиція НЕ чіпається: `.catmenu__panel2` — це `inset: 0` всередині
   * `.catmenu__panel2-stack`, а стек уже стоїть праворуч від списку
   * (`.catmenu__list` — флекс-елемент фіксованої ширини).
   */
  /* Назви категорій переносяться на другий рядок, а не обрізаються
     трикрапкою: у списку рівно 9 пунктів і місця вистачає, а «Інструменти
     і обладнання» в один рядок не влізає — саме так було й у
     `.catshowcase`, який власник бачив. */
  .catmenu-hero .catmenu__label {
    overflow: visible;
    white-space: normal;
    text-overflow: clip;
  }

  .catmenu-hero .catmenu__panel2 {
    background: var(--body-background-color);
    border: 2px solid var(--secondary-color);
    border-radius: 12px;
    overflow: hidden;
  }

  /* Плаский `.catshowcase` лишається лише мобільним фолбеком. */
  .home-hero-row__menu.catshowcase {
    display: none;
  }
}

@media only screen and (min-width: 1200px) {
  .catmenu-hero .catmenu__list {
    flex-basis: 280px;
  }
}
