/* Задача 119, 19.08 — CSS шаблона вынесен из header.php в отдельный кэшируемый файл, дословно,
   без переписывания. Первый блок ниже — общий CSS шаблона (был инлайновым стилевым блоком в
   header.php, строки 129-1185 на момент переноса). Второй блок (маркер ниже) — CSS первого экрана
   главной (#v12), раньше рендерился условно только на / (строки 1920-2115), но целиком заскоупен
   под #v12 — безопасно грузить на всех страницах, на остальных этого id просто нет в DOM. */

	  *{box-sizing:border-box;margin:0;padding:0}
	  html{scroll-behavior:smooth}
	  @media (prefers-reduced-motion: reduce){html{scroll-behavior:auto}}
	  /* Задача 093, 17.08 — мокап шапка-B4.html просил ТОЧНЫЕ #BF5C72/#A8264A/#2F3134, но задача
	     была ограничена только этим файлом — заводились локальные --phx-hd-acc/--phx-hd-acc-h,
	     чтобы не трогать общий tokens.css вслепую. Задача 094, 17.08 — тёплый пион стал основным
	     цветом действия ВО ВСЁМ шаблоне, --acc-btn/--acc-btn-h в tokens.css теперь и есть
	     #BF5C72/#A8264A побайтово (см. комментарий там) — локальные --phx-hd-acc/-h стали
	     дублем и убраны, остался только --phx-hd-graphite (#2F3134, кнопка телефона в шапке —
	     задача 094 явно просила её не трогать, а общего токена графита в tokens.css нет и не
	     заводился — не тот масштаб правки, графит остаётся локальной особенностью шапки). */
	  :root{--phx-hd-graphite:#2F3134;--phx-hd-neutral:#F5F3F1}
	  /* задача 069 — подвал прижат к низу окна раскладкой (flex-колонка на всю высоту окна),
	     а не подпоркой в пикселях у #phx-content: то держало подвал ниже нижней границы окна
	     только до высоты подпорки, на экранах выше промахивалось. #phx-main{flex:1 0 auto} ниже
	     забирает всё свободное место между шапкой и подвалом — на длинных страницах просто
	     не растягивается сверх содержимого, подвал остаётся сразу после него, как раньше.
	     100dvh, не 100vh — учитывает высоту адресной панели телефона, которая то есть, то нет. */
	  body{font-family:var(--font-body);color:var(--ink);background:var(--bg);line-height:1.55;display:flex;flex-direction:column;min-height:100dvh}
	  /* задача 076 — 069 прижимала подвал раскладкой (flex:1 0 auto), но это не мешает подвалу
	     быть ВИДНЫМ в окне, пока #phx-main короче доступной высоты (например #catalog на входе на
	     /catalog/ теряет CSS-резерв :empty ровно в момент, когда JS уже начал класть в него
	     "Загружаю раздел…", а настоящий контент ещё не пришёл — детали в reports/076-*.md).
	     min-height ниже не даёт #phx-main быть короче "окно минус шапка" ни в какой momент,
	     независимо от того, что происходит внутри с JS/сетью. --phx-header-h ставится синхронным
	     скриптом сразу после </nav> (см. выше) — 160px здесь только запасной вариант на случай
	     отключённого JS, реальное число всегда приходит раньше первой раскладки #phx-main. */
	  #phx-main{flex:1 0 auto;min-height:calc(100dvh - var(--phx-header-h, 160px))}
	  /* Задача 125, 19.08 — Алексей с живого телефона: мало воздуха между рядом кнопок шапки и
	     содержимым (крошками на большинстве страниц, героем на главной). Один padding-top на
	     #phx-main вместо правки в каждом шаблоне — box-sizing:border-box (глобальный *{...} выше)
	     держит его внутри min-height, лишнего скролла не добавляет. На страницах с крошками
	     .phx-crumbs{padding:14px 0} — это ВНУТРЕННИЙ отступ до текста ссылки, к внешней позиции
	     самой крошки (что меряем) отношения не имеет, поэтому не складывается с этим правилом.
	     На главной #v12 ничего своего не добавлял — 24px, что было видно раньше, оказались
	     margin-top:var(--sp-3) баннера (.v12-banner), просочившимся наружу через пустые обёртки
	     схлопыванием внешних отступов (сам #v12/.wrap — без padding/border, ничего не мешало) —
	     ровно то, о чём предупреждала задача: не «сложить дважды», а один явный источник вместо
	     случайного. padding-top на #phx-main блокирует это схлопывание (родитель с padding-top
	     не даёт отступу первого потомка просочиться наружу) — весь зазор задаётся этим одним
	     числом, var(--sp-3) внутри просто перестаёт быть видимым снаружи блока. Только мобильный
	     диапазон — тот же порог ≤900px, что у .phx-subnav (десктопная строка меню) выше;
	     десктопная раскладка эту переменную не использует вообще.
	     Задача 133, 20.08 — первый заход (padding-top 30px→56px) отменён: увеличение на главной
	     читалось как «отступ до картинки баннера», не то, что имелось в виду. Уточнено голосом:
	     отсчёт — от нижней границы шапки (border-bottom у header.phx, тот же ориентир, что и
	     раньше), но по факту нужно было не увеличить, а уменьшить — до 16px. Правило и механизм
	     (порог ≤900px, блокировка схлопывания через #v12) не менялись, изменилось только число. */
	  @media(max-width:900px){
	    #phx-main{padding-top:16px}
	  }

	  /* задача 076, шаг 3 — страховка сверх min-height выше: даже после резерва высоты на 390px
	     остался узкий (~22px) кадр, где нижний край подвала уже показался в окне (см. отчёт,
	     до/после видео) — доля дюйма, но глазами это то же самое мелькание. .phx-ready ставится
	     inline-скриптом сразу после закрывающего </footer> (footer.php) — то есть ровно в момент,
	     когда парсер дошёл до конца документа и весь контент над подвалом уже разобран. До этого
	     подвал visibility:hidden (не display:none — тот убирает подвал из потока и вернул бы
	     прыжок раскладки, ровно то, что чинили в 069). Без JS класс не появится никогда —
	     noscript-страховка в <head> обязана вернуть подвал видимым. */
	  html:not(.phx-ready) footer{visibility:hidden}
	  h1,h2,h3{font-family:var(--font-display);font-weight:600;line-height:1.1;letter-spacing:-.01em}
	  ::selection{background:var(--acc);color:var(--white)}
	  a{color:inherit;text-decoration:none}
	  .phx-skip{position:absolute;left:-9999px;top:0;background:var(--prim);color:var(--bg);padding:12px 24px;z-index:200;border-radius:var(--btn-radius);font-size:var(--btn-fs-main)}
	  .phx-skip:focus{left:0;top:0}
	  a:focus-visible,button:focus-visible,input:focus-visible,.btn:focus-visible{outline:2px solid var(--acc-text);outline-offset:2px}
	  /* B27 15.08 (tasks/036-container-1680-and-empty-cart.md, пункт 1) — решение Алексея:
	     потолок ширины контейнера на этом проекте поднят с 1400 до 1680px (разбор mirrey.ru).
	     Это осознанное отступление от общего правила website-quality.md (1440) для ЭТОГО
	     конкретного токена — остальные его пункты (типографика/цвета/8pt-сетка) не менялись.
	     B29 15.08 — замечание архитектора по приёмке пункта 1: на 1440/1366 контейнер упирается
	     почти в самые края (боковой зазор был ~9–10px против прежних 20 на 1440, см. отчёт
	     036-container-1680.md). Отступ поднят с 20 до 24px с каждой стороны — минимальный
	     воздух между содержимым и краем экрана сохраняется при любой ширине сжатия. */
	  .wrap{max-width:1680px;margin:0 auto;padding:0 24px}
	  /* === Задача 170, 21.08 — единая система кнопок, вариант Б (скруглённый прямоугольник) ===
	     Живой замер до правки (5 страниц x 3 ширины): 426 кнопок, 12 разных скруглений,
	     29 сочетаний «радиус+шрифт+размер», 275 кнопок рисовались системным Arial.
	     Причина Arial — ровно то, что чинит первое правило ниже: <button>/<input> НЕ наследуют
	     font-family от body (браузерный дефолт), а ни одно правило кнопки его явно не задавало.
	     Поэтому шрифт задаётся один раз здесь, по типу элемента, а не точечно каждому классу —
	     новая кнопка получит Manrope сама, без отдельной строки в CSS.
	     Форма и ступени размера — только через токены --btn-* (tokens.css), там же роли. */
	  button,input[type=submit],input[type=reset],input[type=button],.btn{font-family:var(--font-body)}
	  /* inline-flex вместо inline-block — чтобы мобильный пол высоты (min-height:44px ниже)
	     центрировал подпись, а не оставлял её прижатой к верху бокса. */
	  .btn{display:inline-flex;align-items:center;justify-content:center;border-radius:var(--btn-radius);padding:12px 22px;font-weight:600;font-size:var(--btn-fs-main);cursor:pointer;border:none;transition:.15s}
	  /* роль «главное действие» */
	  .btn-cta{background:var(--cta);color:var(--white)}
	  .btn-cta:hover{background:var(--cta-d)}
	  /* роль «второстепенное» — задача 170: белый фон, обводка пион, текст --acc-text (#913B58),
	     при наведении фон светлеет (--cta-bg), а не заливается тёмным. До 170 обводка и текст
	     были графитовыми (--blue) — это читалось как ещё одна нейтральная кнопка. */
	  .btn-ghost{background:var(--white);color:var(--acc-text);border:1.5px solid var(--acc-btn)}
	  .btn-ghost:hover{background:var(--cta-bg)}
	  /* роль «рабочее мелкое» — та же заливка, ступень шрифта ниже */
	  .btn-sm{padding:8px 12px;font-size:var(--btn-fs-work);border-radius:var(--btn-radius)}
	  /* Этап C, C3: стандартная форма входа Bitrix (bx-auth) тянет свой Bootstrap
	     btn-primary поверх нашего .btn — конфликт цвета (чужой синий вместо акцента). */
	  .bx-auth .btn-primary{background:var(--cta);border-color:var(--cta-d);color:var(--white)}
	  .bx-auth .btn-primary:hover{background:var(--cta-d);border-color:var(--cta-d);color:var(--white)}
	  /* MASTER QA/Refactor 13.08 — кнопка "Отправить" формы обратной связи (bitrix:form.result.new,
	     /contacts/) была белым текстом на светло-сером фоне (rgb(255,255,255) на rgb(240,240,240)
	     — контраст ~1:1, кнопка фактически нечитаема). Шаблон компонента не трогаю (ядровой,
	     возможно переиспользуется), только цвет через класс, который компонент уже проставляет. */
	  .sendWebFormDw{background:var(--cta);color:var(--white);border:none;border-radius:var(--btn-radius);padding:12px 22px;font-weight:600;font-size:var(--btn-fs-main);cursor:pointer}
	  .sendWebFormDw:hover{background:var(--cta-d)}
	  /* MASTER QA/Refactor 13.08 — ссылки .sale-order-history-link в bitrix:sale.order.list
	     (/personal/order/) шли дефолтным цветом rgb(74,144,226) на прозрачном/белом фоне
	     — контраст 3.29:1, ниже порога 4.5:1 для обычного текста ссылки (axe color-contrast,
	     serious). Шаблон компонента не трогаю (ядровой), только цвет через токен. */
	  .sale-order-history-link{color:var(--blue-l)}
	  /* UX Overhaul 13.08, Batch E — вкладки личного кабинета (#personalMenu, ядровой Bitrix
	     bitrix:menu, без единого нашего класса) на 390px обрезались горизонтально — «Моя
	     корзина»/«Взаиморасчёт» были недоступны без прокрутки, которой тоже не было (обнаружено
	     скриншотом order-mobile-390.png). Шаблон компонента не трогаю, только layout через ID,
	     который компонент уже проставляет — flex-wrap, а не horizontal scroll, чтобы все 4
	     вкладки были видны и доступны без skрытого discovery-жеста. */
	  #personalMenu{display:flex;flex-wrap:wrap;list-style:none;padding:0;margin:16px 0;gap:6px 18px}
	  #personalMenu li{list-style:none}
	  #personalMenu a{display:inline-block;padding:4px 0}
	  /* Родитель #personalMenuWrap — ядровой Bitrix-стиль, фиксированная height:40px + overflow-y:
	     hidden (рассчитан на ОДНУ строку с горизонтальным скроллом, overflow-x:auto). Наш
	     flex-wrap выше переносит пункты на 2-ю строку, но без этого override вторая строка
	     физически обрезалась контейнером (обнаружено сверкой getBoundingClientRect — координаты
	     верные, но overflow:hidden родителя высотой 40px визуально прятал всё ниже). */
	  #personalMenuWrap{height:auto;overflow:visible}

	  .top{background:var(--blue-d);color:var(--on-blue-1);font-size:13px}
	  .top .wrap{display:flex;justify-content:space-between;align-items:center;height:38px;flex-wrap:wrap}
	  .top a{color:var(--on-blue-1)}
	  header.phx{position:sticky;top:0;z-index:40;background:hsl(40 27% 98% / .92);backdrop-filter:blur(10px);border-bottom:1px solid var(--line);box-shadow:0 1px 8px rgba(31,39,51,.04)}
	  .hd{display:flex;align-items:center;gap:22px;height:72px}
	  /* B33 15.08 (tasks/057-home-desktop-v2.md, п.1, критерий 6) — .btn-cta (общий класс .btn,
	     padding:12px 22px, без явной высоты) фактически выходил 43.3px — ниже порога 44×44
	     (замер getBoundingClientRect на живом 1680px). Не трогаю .btn глобально (используется
	     по всему сайту) — точечно только на кнопку в строке меню (задача 085, 16.08 — кнопка
	     переехала из .hd в .phx-subnav, см. правило ниже вместо прежнего .hd .btn-cta). */
	  .logo{font-size:23px;font-weight:800;color:var(--blue);letter-spacing:.5px;display:flex;align-items:center;gap:9px}
	  /* B33 15.08 (tasks/057-home-desktop-v2.md, п.1) — решение Алексея по мокапу V2: «Главная/
	     Акции/Прайс-листы/Контакты» на десктопе переехали из основной строки шапки во вторую,
	     тонкую строку под ней (.phx-subnav, разметка — ниже, вне .wrap.hd) — это освободило место
	     в основной строке под всегда раскрытое поле поиска. «Каталог» тогда туда не входил — был
	     отдельной кнопкой в основной строке (.phx-cat-btn). Задача 093 17.08 (мокап B4) переместила
	     и его в .phx-subnav, первым пунктом — комментарий ниже про .wrap.hd описывает устаревшее
	     промежуточное состояние, актуальная разметка мега-меню — в .phx-subnav (HTML ниже). */
	  .phx-subnav{display:none}
	  /* Каталог: Визуальные улучшения 14.08, п.5 — мега-меню «Каталог» в шапке, доступно с любой
	     страницы. Открытие/закрытие — чистый CSS (:hover/:focus-within на обёртке), закрывается
	     само при уходе курсора/фокуса с панели, без лишнего JS-состояния. Смена активного раздела в
	     левой колонке — JS (переключает готовый .active-класс, панели уже в разметке, картинки
	     подгружаются лениво по первому наведению на раздел — см. скрипт ниже и subcat_images.php). */
	  /* B33 15.08 — обёртка мега-меню переехала из <nav class="main"> прямо в .wrap.hd (была
	     видна только на ≥901px и внутри вложенного nav, теперь сама отвечает за свою видимость —
	     без этого на мобильном/планшете кнопка «Каталог» вылезла бы прямо в тесную строку 052,
	     для которой там не было места). */
	  .phx-megamenu-wrap{position:relative;display:none;align-items:center}
	  .phx-megamenu-trigger{color:inherit}
	  /* Плавное появление (opacity+transform, не display) — сама панель всегда в разметке, но
	     закрытая скрыта через visibility:hidden (не транзишится — переключается мгновенно, зато
	     не даёт Tab уводить фокус в невидимое содержимое; то же самое, что раньше давал display:none).
	     Открытие — прозрачность+лёгкий сдвиг вниз, .18s. */
	  .phx-megamenu{position:absolute;top:100%;left:0;z-index:45;background:var(--white);border:1px solid var(--line);border-radius:14px;box-shadow:0 20px 50px hsl(210 6% 13% / .18);padding:14px;width:min(760px,80vw);display:flex;visibility:hidden;opacity:0;transform:translateY(-6px);transition:opacity .18s ease,transform .18s ease}
	  .phx-megamenu-wrap:hover .phx-megamenu,.phx-megamenu-wrap:focus-within .phx-megamenu{visibility:visible;opacity:1;transform:translateY(0)}
	  @media(prefers-reduced-motion:reduce){.phx-megamenu{transition:none}}
	  /* Тот же тонкий скроллбар, что и у .phx-tile-sublist (см. комментарий там) — здесь фон белый,
	     тон скроллбара под него, не под тёмную панель. */
	  .phx-mega-left,.phx-mega-right{scrollbar-width:thin;scrollbar-color:hsl(214 4% 38% / .35) transparent}
	  .phx-mega-left::-webkit-scrollbar,.phx-mega-right::-webkit-scrollbar{width:6px}
	  .phx-mega-left::-webkit-scrollbar-track,.phx-mega-right::-webkit-scrollbar-track{background:transparent}
	  .phx-mega-left::-webkit-scrollbar-thumb,.phx-mega-right::-webkit-scrollbar-thumb{background:hsl(214 4% 38% / .3);border-radius:20px}
	  .phx-mega-left{flex:0 0 220px;border-right:1px solid var(--line);padding-right:10px;max-height:420px;overflow-y:auto;display:flex;flex-direction:column;gap:2px}
	  .phx-mega-cat-link{display:block;padding:9px 10px;border-radius:var(--btn-radius);font-size:var(--btn-fs-work);font-weight:600;color:var(--ink)}
	  .phx-mega-cat-link:hover,.phx-mega-cat-link:focus-visible{background:var(--t2);color:var(--blue-l)}
	  /* Задача 101, решение Алексея 17.08 — третье розовое пятно в шапке (было #F5E5EC, то же
	     самое, что у иконок кабинета/корзины) убрано и здесь: активный пункт мегаменю теперь
	     нейтральная подложка + текст пионом, не заливка. «Где я нахожусь» по-прежнему читается —
	     два независимых признака (подложка + цвет+вес текста), не один. */
	  /* !important — живой замер показал, что обычная специфичность (два класса, позже в файле)
	     почему-то не побеждала :hover/:focus-visible соседнего правила (общий класс + псевдокласс,
	     формально та же специфичность 0,2,0) даже без реального наведения; не нашёл, что именно
	     переигрывало объявление, — форсирую явно, а не гадаю дальше. */
	  .phx-mega-cat-link.active{background:var(--phx-hd-neutral) !important;color:var(--acc-btn) !important;font-weight:700 !important}
	  .phx-mega-right{flex:1;min-width:0;padding-left:20px;max-height:420px;overflow-y:auto}
	  .phx-mega-panel{display:none}
	  .phx-mega-panel.active{display:block}
	  .phx-mega-panel-head{margin-bottom:12px}
	  .phx-mega-panel-head a{font-family:var(--font-display);font-size:var(--step-0);font-weight:600;color:var(--ink)}
	  .phx-mega-panel-head a:hover{color:var(--blue-l)}
	  .phx-mega-sub-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:6px 16px}
	  .phx-mega-sub-item{display:flex;align-items:center;gap:10px;padding:5px 6px;border-radius:var(--btn-radius);font-size:var(--btn-fs-work);color:var(--ink);min-height:var(--btn-h-touch)}
	  .phx-mega-sub-item:hover,.phx-mega-sub-item:focus-visible{background:var(--t3)}
	  .phx-mega-sub-ph{width:36px;height:36px;flex:none;border-radius:8px;background:var(--t3);background-size:cover;background-position:center;border:1px solid var(--line)}
	  .phx-mega-empty{font-size:13px;color:var(--muted)}
	  @media(max-width:900px){.phx-megamenu{display:none !important}}
	  .phx-burger{display:none;background:none;border:none;border-radius:var(--btn-radius);font-size:var(--btn-ico);line-height:1;cursor:pointer;color:var(--ink);padding:6px;width:44px;height:var(--btn-h-touch);flex-shrink:0;align-items:center;justify-content:center}
	  .phx-mobnav-overlay{position:fixed;inset:0;background:rgba(20,26,34,.4);z-index:80;display:none}
	  .phx-mobnav-overlay.open{display:block}
	  .phx-mobnav{position:fixed;top:0;left:0;bottom:0;width:280px;max-width:82vw;background:var(--white);z-index:81;box-shadow:8px 0 30px rgba(0,0,0,.2);transform:translateX(-100%);transition:transform .25s ease;display:flex;flex-direction:column;padding:18px}
	  .phx-mobnav.open{transform:translateX(0)}
	  .phx-mobnav-close{align-self:flex-end;background:none;border:none;border-radius:var(--btn-radius);font-size:var(--btn-ico);cursor:pointer;color:var(--muted);width:44px;height:var(--btn-h-touch)}
	  .phx-mobnav a{padding:13px 6px;font-size:16px;font-weight:600;border-bottom:1px solid var(--line);color:var(--ink)}
	  .phx-mobnav a.active{color:var(--blue);text-decoration:underline;text-underline-offset:4px}
	  /* Задача 095 — плашка города, тот же вид-заглушка, что и десктопная (задача 093): рамка,
	     точка-маркер тёплым пионом, «Тольятти» жирным, стрелка справа. cursor:default и обычный
	     <span> — так же, как на десктопе, не кликается и не выглядит кнопкой. */
	  .phx-mobnav-city{display:flex;align-items:center;gap:9px;height:44px;padding:0 12px;border:1px solid var(--line);border-radius:9px;margin-bottom:10px;font-size:14px;color:var(--ink);cursor:default}
	  .phx-mobnav-city b{font-weight:700}
	  .phx-mobnav-city .phx-city-pin{color:var(--acc-btn);font-size:14px}
	  .phx-mobnav-city .phx-city-arw{color:var(--muted);font-size:11px;margin-left:auto}
	  .phx-mobnav-phone{margin-top:16px;display:flex;flex-direction:column;gap:8px}
	  /* Задача 095, п.4 — попутно найдено при замере зон нажатия ≥44×44 в этом же меню: у ссылок
	     телефона реальная высота была 35px (padding:6px + строка 15px, без явной высоты) — ниже
	     порога. Не по заданию этой задачи впрямую, но тот же файл, тот же критерий приёмки самой
	     задачи 095 («кликаемые элементы ≥44×44 — замер по каждому») — почему бы не поправить сразу,
	     а не заводить отдельную задачу на 2 строки CSS. */
	  .phx-mobnav-phone a{display:flex;align-items:center;min-height:44px;border:none;padding:6px;font-size:15px;font-weight:700;color:var(--blue)}
	  .hd .phone{margin-left:auto;text-align:right;font-size:13px;color:var(--muted)}
	  .hd .phone b{display:block;font-size:18px;color:var(--ink)}

	  .phx-search-toggle{background:none;border:none;font-size:var(--btn-ico);cursor:pointer;color:var(--ink);width:44px;height:var(--btn-h-touch);flex-shrink:0;border-radius:var(--btn-radius);display:flex;align-items:center;justify-content:center}
	  .phx-search-toggle:hover,.phx-search-toggle:focus-visible{background:var(--blue-pale)}
	  /* Задача 095 — быстрый доступ к каталогу в один тап на мобильной/планшетной шапке (<901px,
	     см. display:none в @media(min-width:901px) ниже — там каталог уже есть пилюлью в строке
	     меню). Залита тёплым пионом (--acc-btn), как и десктопная пилюля — задача явно требует тот
	     же цвет действия, не нейтральную заливку, как у кабинета/корзины рядом. */
	  .phx-catalog-quick{display:flex;align-items:center;justify-content:center;width:44px;height:var(--btn-h-touch);flex-shrink:0;border-radius:var(--btn-radius);font-size:var(--btn-ico);background:var(--acc-btn);color:var(--white)}
	  .phx-catalog-quick:hover,.phx-catalog-quick:focus-visible{background:var(--acc-btn-h)}
	  .phx-catalog-quick .lbl,.phx-search-toggle .lbl{display:none}
	  /* B33 15.08 (tasks/057-home-desktop-v2.md, п.1) — раскрытое поле поиска в основной строке
	     шапки, ≥901px (см. @media выше). Скрыто по умолчанию (mobile/tablet используют
	     .phx-search-toggle + .phx-search-panel, задача 052 их не трогала). Живой поиск —
	     тот же stock.php?action=search, debounce и рендер результатов — общие вспомогательные
	     функции (esc/highlight/iconFor/fmt) вынесены из IIFE ниже на уровень скрипта, чтобы не
	     дублировать код между двумя независимыми полями ввода. */
	  .phx-search-desktop{display:none;position:relative;flex:1;align-items:center;gap:10px;background:var(--white);border:1.5px solid var(--line);border-radius:12px;height:52px;padding:0 8px 0 18px;max-width:640px}
	  .phx-search-desktop:focus-within{border-color:var(--blue-l);box-shadow:0 0 0 3px var(--blue-pale)}
	  .phx-search-desktop .ico{flex-shrink:0;color:var(--muted);width:19px;height:19px}
	  .phx-search-desktop input{border:none;outline:none;flex:1;min-width:0;font-size:15px;font-family:var(--font-body);background:transparent;color:var(--ink)}
	  .phx-search-desktop input::placeholder{color:var(--muted)}
	  .phx-search-desktop-go{background:var(--acc-btn);border:none;border-radius:var(--btn-radius);height:var(--btn-h-touch);padding:0 16px;font-weight:600;font-size:var(--btn-fs-main);color:var(--white);flex-shrink:0;cursor:pointer}
	  .phx-search-desktop-go:hover{background:var(--acc-btn-h)}
	  /* Задача 093, п.3 — плашка выбора города, пока заглушка (решение Алексея: без поведения,
	     не кликается). display:none по умолчанию — как у .phx-search-desktop выше, показывается
	     только в десктопном брейкпоинте ниже, на мобильной/планшетной шапке (052) её нет. */
	  .phx-city-badge{display:none}
	  .phx-search-desktop-results{position:absolute;top:calc(100% + 8px);left:0;right:0;background:var(--white);border:1px solid var(--line);border-radius:12px;box-shadow:0 18px 40px rgba(31,39,51,.15);max-height:70vh;overflow-y:auto;z-index:50}
	  .phx-search-desktop-results:empty{display:none}
	  /* Задача 101, решение Алексея 17.08 — иконки кабинета/корзины были залиты бледно-розовым
	     (#F5E5EC, тот же var(--blue-pale)) без рамки, рядом с белым полем поиска и белой плашкой
	     города это читалось как «кнопки из другого набора». Сведены к тому же виду: белый фон,
	     рамка var(--line) (тот же токен, что у поиска/плашки города), десктопный радиус 12px
	     (переопределён ниже, в брейкпоинте ≥901px) — сам мокап B4 (шапка-B4.html) это и показывает. */
	  .phx-account-btn{display:flex;align-items:center;gap:7px;background:var(--white);border:1px solid var(--line);border-radius:var(--btn-radius);height:var(--btn-h-touch);padding:0 14px;flex-shrink:0;color:var(--blue);font-weight:600;font-size:var(--btn-fs-work);white-space:nowrap}
	  .phx-account-btn:hover,.phx-account-btn:focus-visible{background:var(--phx-hd-neutral)}
	  .phx-account-btn .ico{font-size:17px;line-height:1}
	  /* Селектор ".phx-mobnav a" ниже (общий стиль пунктов меню) специфичнее одного класса
	     ".phx-mobnav-account" (тег+класс против класса) и перебивал бы паддинг/рамку — поэтому
	     переопределяем тем же составным селектором, а не полагаемся на порядок в файле.
	     Задача 101, п.2 — то же самое бледно-розовое пятно в бургер-меню, второе рядом с
	     пионовой «Оставить заявку»: сведено к вторичной кнопке (белый фон, та же рамка), первичное
	     действие в списке остаётся одно — «Оставить заявку». */
	  .phx-mobnav a.phx-mobnav-account{display:flex;align-items:center;gap:9px;background:var(--white);border:1px solid var(--line);border-radius:var(--btn-radius);font-size:var(--btn-fs-main);padding:13px 12px;margin-bottom:8px;border-bottom:none}
	  .phx-mobnav-account .ico{font-size:18px}
	  /* Задача 104 — находка отчёта 101: «Оставить заявку» в бургер-меню была голой строкой
	     списка (тот же вид, что «Главная»/«Контакты»), хотя на десктопе (задача 085) это уже
	     пионовая пилюля. Единственное первичное действие списка — пион, белый текст, высота
	     ≥52px (пункты меню и так 52px по факту паддингов, но здесь задаётся явно, не через
	     content-driven высоту), скругление то же 9px, что у вторичной «Войти в кабинет» рядом. */
	  .phx-mobnav a.phx-mobnav-cta{display:flex;align-items:center;justify-content:center;min-height:52px;background:var(--acc-btn);color:var(--white);border:none;border-radius:var(--btn-radius);padding:13px 12px;margin-bottom:8px;border-bottom:none;font-weight:600;font-size:var(--btn-fs-main)}
	  @media(hover:hover){.phx-mobnav a.phx-mobnav-cta:hover{background:var(--acc-btn-h)}}
	  .phx-search-overlay{position:fixed;inset:0;background:rgba(20,26,34,.35);z-index:75;display:none}
	  .phx-search-overlay.open{display:block}
	  /* Задача 117, честные находки подряд, все — по живой проверке реальными тапами и реальным
	     скроллом, не программными событиями (обычный page.evaluate/click их не ловил).
	     1) top:0 клал панель поверх шапки (header.phx{position:sticky;top:0}) — обе стартуют от
	        верхнего края, у панели z-index выше, шапка визуально «пропадала» под белым полем
	        поиска. Пробовал top:var(--phx-header-h) — та же переменная уже верно считает высоту
	        шапки для #phx-main (задача 076/080). Не подошла и сама всплыла новой находкой:
	     2) --phx-header-h — это АБСОЛЮТНАЯ позиция низа шапки НА СТРАНИЦЕ (bottom + scrollY),
	        посчитанная один раз при загрузке, когда над шапкой ещё видна плашка «Тестовый шаблон»
	        (56px). Как только пользователь прокручивает достаточно, чтобы плашка ушла — sticky-шапка
	        «прилипает» к самому верху экрана, её реальный отступ становится МЕНЬШЕ на высоту плашки,
	        а переменная остаётся старой (не пересчитывается на scroll, только на resize/load).
	        Открытая после скролла панель вставала на 56px ниже настоящего низа шапки — заметный
	        зазор, воспринимался как «поиск открывается нестабильно» (иногда визуально ломался).
	     3) От top:var(--phx-header-h) ещё и закрытое состояние сначала ломалось: translateY(-100%)
	        сдвигает панель на высоту самой панели (92px), а не шапки — «закрытая» панель
	        перехватывала тапы по кнопкам под собой («...intercepts pointer events» в логе
	        Playwright). pointer-events:none чинил клик, но не сам факт наложения.
	     Правильное решение — не полагаться ни на какую CSS-переменную вообще: top всегда 0,
	     закрытое состояние — фиксированный translateY(-100%) от СВОЕЙ высоты (не зависит от шапки,
	     всегда полностью над экраном). Для открытого состояния JS меряет реальный нижний край
	     шапки ПРЯМО В МОМЕНТ клика (header.getBoundingClientRect().bottom, не заранее вычисленная
	     переменная) и подставляет через --phx-search-open-y — учитывает и скролл, и то, что плашка
	     уже могла уехать. См. функцию openPanel() в скрипте ближе к концу файла. */
	  .phx-search-panel{position:fixed;top:0;left:0;right:0;z-index:76;background:var(--white);box-shadow:0 12px 30px rgba(0,0,0,.15);transform:translateY(-100%);transition:transform .2s ease;pointer-events:none}
	  .phx-search-panel.open{transform:translateY(var(--phx-search-open-y, 0px));pointer-events:auto}
	  .phx-search-panel-inner{padding:18px 20px}
	  .phx-search-input-row{display:flex;align-items:center;gap:10px;border:1.5px solid var(--line);border-radius:10px;padding:0 14px;background:var(--bg)}
	  .phx-search-input-row:focus-within{border-color:var(--blue-l);box-shadow:0 0 0 3px var(--blue-pale)}
	  .phx-search-input-row .ico{font-size:15px;color:var(--muted)}
	  .phx-search-input-row input{flex:1;border:none;background:none;padding:13px 0;font-size:15px;color:var(--ink);outline:none}
	  .phx-search-close{background:none;border:none;font-size:var(--btn-ico);cursor:pointer;color:var(--muted);width:44px;height:var(--btn-h-touch);flex-shrink:0;border-radius:var(--btn-radius)}
	  .phx-search-close:focus-visible,.phx-search-toggle:focus-visible,.phx-search-item:focus-visible{outline:2px solid var(--blue-l);outline-offset:2px}
	  .phx-search-results{margin-top:10px;max-height:60vh;overflow-y:auto}
	  .phx-search-item{display:flex;gap:12px;align-items:center;padding:11px 8px;border-radius:var(--btn-radius);font-size:var(--btn-fs-work);cursor:pointer;min-height:var(--btn-h-touch)}
	  .phx-search-item:hover,.phx-search-item:focus-visible{background:var(--bg)}
	  .phx-search-item .em{font-size:22px;width:30px;text-align:center;flex-shrink:0}
	  /* Задача 212, 23.08 — в слоте эмодзи теперь может стоять миниатюра товара или кружок его
	     цвета. Размер выбран не на глаз: слот .em шириной 30px, а высота строки подсказки (76px
	     замером) держится текстовым блоком .nm (название + мелкая строка, ~54px) — картинка в
	     30px в него укладывается, и строка не становится ни на пиксель выше. object-fit:contain —
	     снимки не квадратные, обрезать товар в подсказке незачем. */
	  .phx-search-item .phx-search-thumb{width:30px;height:30px;object-fit:contain;border-radius:6px;background:var(--white);display:block}
	  .phx-search-item .phx-search-sw{display:inline-block;width:22px;height:22px;border-radius:50%;border:1px solid var(--line);vertical-align:middle}
	  /* Кружок цвета на карточке полной выдачи — там места больше, чем в строке подсказки. */
	  .phx-search-card-sw{display:block;width:56px;height:56px;border-radius:50%;border:1px solid var(--line);margin:0 auto 8px}
	  .phx-search-item .nm{font-size:13.5px;line-height:1.35;flex:1;min-width:0}
	  .phx-search-item .nm mark{background:var(--warn-bg);color:inherit;border-radius:2px;padding:0 1px}
	  .phx-search-item .meta{font-size:11.5px;color:var(--muted);margin-top:2px}
	  .phx-search-item .pr{font-size:13.5px;font-weight:700;white-space:nowrap;flex-shrink:0}
	  .phx-search-status{padding:16px 8px;text-align:center;color:var(--muted);font-size:13.5px}
	  /* Задача 106 — строка перехода на полную выдачу, визуально отделена от товаров тонкой линией
	     сверху, текст пионом (тот же цвет, что и остальные ссылки-действия сайта). min-height 44px —
	     зона нажатия, даже если сама строка занимает меньше по контенту. */
	  .phx-search-showall{display:flex;align-items:center;justify-content:center;min-height:44px;padding:10px 8px;border-top:1px solid var(--line);color:var(--acc-btn);font-size:13.5px;font-weight:600;text-decoration:none;text-align:center}
	  .phx-search-showall:hover,.phx-search-showall:focus-visible{background:var(--bg);color:var(--acc-btn-h)}
	  /* Задача 107 — переход в раздел каталога первой строкой, до товаров: своя граница снизу,
	     чтобы отделить от карточек, фон чуть темнее подсказок — это не товар, это переход. */
	  /* Задача 111 — было неотличимо от заголовка/служебной подписи (нейтральный цвет, ни стрелки,
	     ни следа кликабельности). Пион по умолчанию + стрелка справа + фон-неутрал на наведении —
	     тот же приём, что уже применён к иконкам шапки (--phx-hd-neutral, задача 101), новых
	     цветов не заводил. */
	  .phx-search-section{display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:44px;padding:10px 12px;background:var(--bg);border-bottom:1px solid var(--line);color:var(--acc-btn);font-size:13.5px;font-weight:600;text-decoration:none}
	  .phx-search-section:hover,.phx-search-section:focus-visible{background:var(--phx-hd-neutral);color:var(--acc-btn-h)}
	  .phx-search-section .arw{flex-shrink:0;transition:transform .15s}
	  .phx-search-section:hover .arw,.phx-search-section:focus-visible .arw{transform:translateX(3px)}
	  .hd .btn{padding:10px 18px}

	  .phx-cart-btn{position:relative;background:var(--white);border:1px solid var(--line);border-radius:var(--btn-radius);color:var(--ink);width:44px;height:var(--btn-h-touch);flex-shrink:0;font-size:var(--btn-ico);cursor:pointer;display:flex;align-items:center;justify-content:center}
	  .phx-cart-btn:hover{background:var(--phx-hd-neutral)}
	  /* B26 15.08 (tasks/026-mobile-overflow.md) — второй, отдельный источник переполнения на
	     узких экранах, найден тем же живым промером (offenders-скан с исключением потомков
	     position:fixed — сама .phx-cart-drawer на document.scrollWidth, проверено принудительным
	     открытием/закрытием с чистого состояния, не влияет вообще, ни в каком состоянии — это
	     не тот виновник, на которого грешил текст задачи). Счётчик-бейдж на кнопке корзины —
	     position:absolute с намеренным выносом за край кнопки (top/right:-6px, «плашка на
	     уголке»), у бейджа нет position:fixed-предка, поэтому он честно считается в overflow
	     документа. На стянутой ≤430px шапке (см. правку выше) кнопка и так стоит вплотную к
	     правому краю — вынос ещё на 6px добавлял те самые лишние ~4px горизонтальной прокрутки.
	     Вынос уменьшен до -2px/-4px — бейдж всё ещё сидит на уголке кнопки, просто чуть скромнее.
	     Ширина бейджа растёт от закреплённого right — при 2-й/3-й цифре («12», «150») правый край
	     не сдвигается, значит фикс одинаково верен для всех разрядов счётчика. */
	  .phx-cart-count{position:absolute;top:-4px;right:-2px;background:var(--cta);color:var(--white);font-size:11px;font-weight:700;min-width:18px;height:18px;border-radius:9px;display:flex;align-items:center;justify-content:center;padding:0 4px}

	  .phx-cart-overlay{position:fixed;inset:0;background:rgba(20,26,34,.4);z-index:70;display:none}
	  .phx-cart-overlay.open{display:block}
	  .phx-cart-drawer{position:fixed;top:0;right:0;bottom:0;width:400px;max-width:100vw;background:var(--white);z-index:71;box-shadow:-8px 0 30px rgba(0,0,0,.2);display:flex;flex-direction:column;transform:translateX(100%);transition:transform .25s ease}
	  .phx-cart-drawer.open{transform:translateX(0)}
	  .phx-cart-head{padding:18px 20px;border-bottom:1px solid var(--line);display:flex;align-items:center;justify-content:space-between}
	  .phx-cart-head h2{font-size:17px}
	  .phx-cart-close{background:none;border:none;border-radius:var(--btn-radius);font-size:var(--btn-ico);cursor:pointer;color:var(--muted);line-height:1;width:44px;height:var(--btn-h-touch);margin:-10px -12px -10px 0;flex-shrink:0;display:flex;align-items:center;justify-content:center}
	  .phx-cart-body{flex:1;overflow-y:auto;padding:14px 20px}
	  .phx-cart-item{display:flex;gap:10px;padding:12px 0;border-bottom:1px solid var(--line)}
	  /* B38 16.08 (tasks/042-photo-placeholders.md, п.3) — .em (эмодzhi-заглушка) заменена на
	     настоящее превью/нейтральную заглушку — та же плитка-слот, что у карточки каталога
	     (.phx-card-thumb), только компактнее под ширину строки корзины. */
	  .phx-cart-item-thumb{width:52px;height:52px;flex-shrink:0;border-radius:8px;background:var(--blue-pale);display:flex;align-items:center;justify-content:center;overflow:hidden}
	  img.phx-cart-item-thumb{object-fit:cover}
	  .phx-cart-item-info{flex:1;min-width:0}
	  .phx-cart-item-name{font-size:13.5px;font-weight:600;margin-bottom:2px}
	  .phx-cart-item-sku{font-size:11.5px;color:var(--muted);margin-bottom:6px}
	  .phx-cart-qty{display:flex;align-items:center;gap:6px}
	  .phx-cart-qty button{width:24px;height:24px;border:1px solid var(--line);background:var(--white);border-radius:var(--btn-radius);cursor:pointer;font-size:var(--btn-ico);line-height:1}
	  .phx-cart-qty span{font-size:13px;min-width:16px;text-align:center}
	  .phx-cart-item-price{font-size:13.5px;font-weight:700;white-space:nowrap;margin-left:8px;text-align:right}
	  /* B30 15.08 (tasks/051-prices-correctness-and-units.md) — цена за единицу под суммой
	     позиции, чтобы «500 ₽» не пришлось разгадывать — за одну штуку или за все пять. */
	  .phx-cart-item-perunit{display:block;font-size:10.5px;font-weight:500;color:var(--muted);white-space:nowrap}
	  .phx-cart-item-remove{background:none;border:none;border-radius:var(--btn-radius);color:var(--muted);cursor:pointer;font-size:var(--btn-ico);padding:0 4px}
	  .phx-cart-item-remove:hover{color:var(--danger)}
	  /* B28 15.08 (tasks/036-container-1680-and-empty-cart.md, пункт 2) — пустая корзина была
	     тупиком с одной строкой текста. Теперь: короткая шапка-заглушка, блок реальных условий
	     работы (дословно ДАННЫЕ_для_главной.md) и блок «может пригодиться» — переиспользует
	     карточку .phx-card/.phx-card-thumb/.phx-card-name/.phx-card-price (те же классы, что
	     каталог и «В наличии сегодня» на Главной), просто в узкой 2-колоночной сетке под
	     ширину дровера (400px), а не в 5-колоночной сетке главной. */
	  .phx-cart-empty{padding:28px 0 4px}
	  .phx-cart-empty-head{text-align:center;padding:0 8px 20px;color:var(--muted)}
	  .phx-cart-empty-ico{font-size:30px;margin-bottom:6px}
	  .phx-cart-empty-head p{font-size:15px;font-weight:700;color:var(--ink);margin-bottom:2px}
	  .phx-cart-empty-head span{font-size:13px}
	  .phx-cart-conditions{border-top:1px solid var(--line);padding-top:16px}
	  .phx-cart-conditions h4,.phx-cart-recs h4{font-size:11.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--muted);margin-bottom:10px}
	  .phx-cart-conditions ul{list-style:none;display:flex;flex-direction:column;gap:9px}
	  .phx-cart-conditions li{font-size:13px;line-height:1.5;padding-left:20px;position:relative;color:var(--ink)}
	  .phx-cart-conditions li::before{content:'✓';position:absolute;left:0;color:var(--acc-text);font-weight:700}
	  .phx-cart-recs{border-top:1px solid var(--line);padding-top:16px;margin-top:20px}
	  .phx-cart-recs-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
	  .phx-cart-recs-grid .phx-card{padding:8px}
	  .phx-cart-recs-grid .phx-card-thumb{margin-bottom:6px}
	  .phx-cart-recs-grid .phx-card-name{font-size:12px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
	  .phx-cart-recs-grid .phx-card-price{font-size:13px}
	  .phx-cart-foot{padding:16px 20px;border-top:1px solid var(--line)}
	  /* Задача 175, 21.08 — правила .phx-cart-tier-hint убраны вместе с самой подсказкой:
	     оптовая цена применяется всегда, порогов на цену нет (см. js/main.js и footer.php). */
	  .phx-cart-total{display:flex;justify-content:space-between;font-size:15px;font-weight:700;margin-bottom:12px}
	  /* Дизайн: Каталог/Товар/Корзина/Контакты 13.08, п.4 — «Оформить заказ» прячется после
	     раскрытия формы (свою роль уже выполнила), на её месте некликабельный заголовок шага —
	     единственный активный CTA дальше «Отправить заказ». Подписи полей постоянные, не только
	     placeholder (бэклог п.8 «формы без label» — этот конкретный набор полей закрыт). */
	  .phx-checkout-step-label{font-size:13px;font-weight:700;color:var(--ink);margin-top:12px;padding-top:12px;border-top:1px dashed var(--line)}
	  .phx-checkout-form{display:none;margin-top:10px}
	  .phx-checkout-form.open{display:block}
	  .phx-field{margin-bottom:8px}
	  .phx-field label{display:block;font-size:11.5px;font-weight:600;color:var(--muted);margin-bottom:4px}
	  /* задача 062, п.3: шрифт в полях был 13.5px — на мобильном браузер зумит страницу при
	     фокусе на поле с font-size<16px, автозум и даёт эффект «поплывшей» ширины экрана.
	     16px — порог, ниже которого не опускаться (то же в .phx-chat-form и .webFormDw ниже). */
	  .phx-checkout-form input{width:100%;padding:10px 11px;border:1px solid var(--line);border-radius:8px;font-size:16px;box-sizing:border-box}

	  .phx-crumbs{padding:14px 0;font-size:13px;color:var(--muted)}
	  .phx-crumbs a:hover{color:var(--blue)}
	  /* Кнопка возврата в раздел с карточки товара (просьба Алексея 21.08 — «увеличь,
	     сделай читабельнее») — не строка крошек (.phx-crumbs above, 13px мелкий текст
	     уместен только там), отдельный pill того же языка, что .btn-ghost (белая заливка,
	     графитовые обводка/текст — не пион, это вторичное действие, не спорит весом с
	     «В корзину»). 44px высоты — не только читаемость, но и цель касания на мобильном
	     (тот же порог, что уже применён к кружкам-образцам, задача 160). */
	  .phx-back-btn{display:inline-flex;align-items:center;gap:6px;height:var(--btn-h-touch);padding:0 18px;border-radius:var(--btn-radius);border:1.5px solid var(--blue);color:var(--blue);font-weight:600;font-size:var(--btn-fs-main);background:var(--white)}
	  .phx-back-btn:hover,.phx-back-btn:focus-visible{background:var(--blue-pale)}
	  /* Задача 200, 22.08 (нашёл Алексей на телефоне) — кнопка возврата стояла ВПРИТЫК к названию
	     товара: у h1 margin-bottom:0, у обёртки кнопки padding был только снизу (0 0 16px), и
	     зазор между низом заголовка и верхом кнопки выходил РОВНО 0 px на всех ширинах. На
	     телефоне заголовок переносится на две-три строки, и хвосты букв почти касались рамки.
	     Отступ сверху делаем таким же, как снизу, — 16 px, симметрично, без подгонки под ширину.
	     Заодно стиль уезжает из инлайна в класс: инлайновый style= в разметке из JS — ровно тот
	     случай, который разбирала задача 176 (там он бил любое CSS-правило и ломал мобильную
	     раскладку). */
	  .phx-back-row{padding:16px 0}

	  /* min-height:200px убран задачей 069 — заглушка в пикселях промахивалась на любом экране
	     выше ~400px, подвал висел под шапкой на долю секунды до прихода контента. Прижимает
	     теперь body{display:flex} + #phx-main{flex:1 0 auto} выше, без числа для конкретного экрана. */
	  #phx-content{padding-bottom:20px}

	  .phx-badge{background:var(--warn-bg);border:1px solid var(--warn-border);color:var(--warn-text);font-size:12.5px;padding:8px 14px;text-align:center}

	  /* #catalog заполняется JS в самом низу документа — до этого браузер уже красит пустой div,
	     резервируем место заранее, иначе первая покраска идёт с нулевой высотой и заполнение даёт
	     CLS (см. ЭТАП_E_итог.md, было CLS ~0.7 на /catalog/). 1200px — под экран из 13 фото-плиток
	     (частый случай захода без ?cat=); полностью не решает сдвиг для товарной сетки внутри уже
	     открытого раздела (там счёт карточек заранее неизвестен) — известное ограничение, не Этап E.
	     Дизайн: Каталог/Товар/Корзина/Контакты 13.08, п.3 — резерв высоты был БЕЗУСЛОВНЫМ и
	     оставался висеть под карточкой товара (короче 1200px), создавая пустую область на desktop
	     (GPT-аудит). Резерв нужен только до первой отрисовки — #catalog:empty матчит ровно это
	     окно (до mount.innerHTML), как только внутри появляется контент любого вида (плитки/сетка/
	     товар), селектор перестаёт действовать сам, без дополнительного JS. */
	  #catalog:empty{min-height:1200px}
	  /* Каталог: Подразделы, Скролл и Виды 13.08 — единый sticky-отступ (замерено на живом
	     test.lavrpack.ru: header.phx держит 73px и на 1440px, и на 390/900px — один и тот же
	     отступ подходит для обоих брейкпоинтов, переопределять на mobile не потребовалось). Один
	     источник вместо разбросанных чисел — используется и сайдбаром, и панелью подразделов. */
	  .phx-catalog-layout{display:grid;grid-template-columns:240px 1fr;gap:24px;align-items:start;--phx-sticky-offset:88px}
	  .phx-cat-sidebar{background:var(--bg);border:1px solid var(--line);border-radius:14px;padding:16px;position:sticky;top:var(--phx-sticky-offset)}
	  .phx-cat-sidebar h2,.phx-cat-sidebar h3{font-size:14px;margin-bottom:10px}
	  /* Задача 176 — стиль ссылки «← Все 13 разделов» переехал из инлайнового style= в класс:
	     инлайн бьёт любое правило по специфичности, и мобильная раскладка ниже не смогла бы
	     убрать нижний отступ без !important. Значения — те же, что были инлайном. */
	  .phx-cat-alllink{display:block;font-size:12.5px;color:var(--muted);margin-bottom:10px}
	  /* Сайдбар V3 «Мини-обложки» — мокап sidebar-v3, выбран Алексеем 13.08 */
	  .phx-cat-item{display:flex;align-items:center;gap:12px;padding:6px 8px;min-height:52px;font-size:var(--btn-fs-work);border-radius:var(--btn-radius);cursor:pointer}
	  .phx-cat-ava{width:40px;height:40px;flex:none;border-radius:50%;object-fit:cover;border:1px solid var(--line);background:var(--t3)}
	  .phx-cat-ava-i{display:flex;align-items:center;justify-content:center;font-size:18px}
	  .phx-cat-nm{display:flex;flex-direction:column;min-width:0;font-weight:600;line-height:1.25}
	  .phx-cat-nm em{font-style:normal;font-size:11px;font-weight:400;color:var(--muted)}
	  .phx-cat-item:hover{background:var(--t3)}
	  .phx-cat-item.active{background:var(--blue-pale);color:var(--blue-l)}
	  .phx-cat-item.active .phx-cat-ava{border:2px solid var(--cta)}
	  .phx-cat-item:focus-visible{outline:2px solid var(--blue-l);outline-offset:-2px}
	  .phx-cat-main{min-width:0}
	  .phx-filter-label{font-size:12px;color:var(--muted);font-weight:600;white-space:nowrap}
	  .phx-chips{display:flex;flex-wrap:wrap;gap:6px}
	  .phx-chip{border:1px solid var(--line);background:var(--white);color:var(--ink);font-size:var(--btn-fs-mini);padding:6px 12px;border-radius:var(--btn-radius);cursor:pointer;min-height:32px}
	  .phx-chip:hover{border-color:var(--blue-l);background:var(--phx-hd-neutral)}
	  .phx-chip.active{background:var(--blue);color:var(--white);border-color:var(--blue)}
	  .phx-chip:focus-visible{outline:2px solid var(--blue-l);outline-offset:2px}
	  /* Подразделы (Формат/Отделка/Подкатегория) + переключатель вида — один закреплённый
	     контейнер над сеткой товаров в .phx-cat-main, не в сайдбаре (см. ЗАДАНИЕ_ClaudeCode_
	     Каталог_Подразделы_и_Скролл.md, п.2.1). grid-columns:minmax(0,1fr) auto — левая зона
	     (чипсы) гибкая и может скроллиться по X, правая (переключатель) фиксированной ширины и
	     никогда не уезжает вместе с чипсами. Свой класс, не .phx-toolbar — тот скрыт mobile-
	     правилом ниже. z-index между карточками (auto/0) и шапкой/корзиной/чатом/поиском (40–76). */
	  /* Плашка окрашена мягким «пионом» — по просьбе Алексея 13.08, тон и пара текста повторяют
	     активный пункт раздела в сайдбаре (.phx-cat-item.active: --blue-pale/--blue-l, тот же
	     --t2/--acc-text из tokens.css), а не насыщенный --acc (первая версия была слишком
	     яркой). Чипсы/переключатель — свои непрозрачные пилюли (белая/var(--t3)), их внутренний
	     контраст фоном плашки не затронут, менять не нужно. */
	  .phx-subcat-sticky{position:sticky;top:var(--phx-sticky-offset);z-index:20;display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:16px;background:var(--blue-pale);border:none;border-radius:12px;padding:10px 16px;margin-bottom:16px;box-shadow:0 6px 18px hsl(210 6% 13% / .07)}
	  /* Задача 184 — кнопка, за которой на телефоне свёрнута панель фильтров. На десктопе
	     скрыта: там места хватает и панель раскрыта всегда (правило ниже, @media до 900px).
	     Вид — роль «нейтральное» системы кнопок задачи 170, форма и ступень из токенов. */
	  .phx-filters-toggle{display:none;align-items:center;gap:8px;min-height:var(--btn-h-touch);padding:0 14px;background:var(--white);border:1px solid var(--line);border-radius:var(--btn-radius);color:var(--ink);font-family:var(--font-body);font-weight:600;font-size:var(--btn-fs-work);cursor:pointer;white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis}
	  .phx-filters-toggle .ico{font-size:var(--btn-fs-work);color:var(--muted);line-height:1}
	  /* выбранный фильтр виден без раскрытия — кнопка получает акцентную обводку и текст */
	  .phx-filters-toggle.has-active{border-color:var(--acc-btn);color:var(--acc-text)}
	  .phx-filters-toggle.has-active .ico{color:var(--acc-btn)}
	  .phx-filters-toggle[hidden]{display:none}
	  .phx-subcat-scroll{position:relative;min-width:0}
	  .phx-subcat-bar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 28px;min-width:0}
	  .phx-subcat-block{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
	  .phx-subcat-block .phx-filter-label{white-space:nowrap;color:var(--blue-l)}
	  .phx-chip .cnt{color:var(--muted)}
	  .phx-chip.active .cnt{color:hsl(0 0% 100% / .85)}
	  /* Переключатель «Вид каталога» — сегментированный контрол из 3 текстовых кнопок (в проекте
	     нет набора SVG-иконок — эмодзи и самодельные SVG заданием запрещены, поэтому текст). */
	  .phx-view-switch{display:flex;align-items:center;gap:2px;flex:none;background:var(--t3);border-radius:9px;padding:3px}
	  .phx-view-btn{display:flex;align-items:center;justify-content:center;min-width:44px;min-height:var(--btn-h-touch);padding:0 12px;border:none;border-radius:var(--btn-radius);background:transparent;color:var(--muted);font-size:var(--btn-fs-mini);font-weight:600;font-family:var(--font-body);cursor:pointer;white-space:nowrap}
	  .phx-view-btn:hover{color:var(--ink)}
	  /* Активная кнопка — графит (--blue/--prim), как активные чипсы подразделов
	     (.phx-chip.active) — тот же паттерн «выбрано» по всему каталогу. */
	  .phx-view-btn.active{background:var(--blue);color:var(--white);box-shadow:0 1px 3px hsl(210 6% 13% / .14)}
	  .phx-view-btn:focus-visible{outline:2px solid var(--blue-l);outline-offset:2px}
	  /* Дизайн: Каталог/Товар/Корзина/Контакты 13.08, п.2 — mobile-попап «Вид»: одна кнопка вместо
	     трёх, показывает текущий выбор («Вид: Крупная»), открывает меню с 3 вариантами. Скрыт по
	     умолчанию — включается только в mobile-медиа-запросе ниже, на desktop работает .phx-view-switch. */
	  .phx-view-popup{position:relative;display:none;flex:none}
	  .phx-view-popup-trigger{display:flex;align-items:center;gap:4px;min-height:var(--btn-h-touch);padding:0 12px;border:1px solid var(--line);border-radius:var(--btn-radius);background:var(--white);color:var(--ink);font-size:var(--btn-fs-mini);font-weight:600;font-family:var(--font-body);cursor:pointer;white-space:nowrap}
	  .phx-view-popup-trigger:focus-visible{outline:2px solid var(--blue-l);outline-offset:2px}
	  .phx-view-menu{display:none;position:absolute;right:0;top:calc(100% + 6px);z-index:25;min-width:160px;background:var(--white);border:1px solid var(--line);border-radius:12px;box-shadow:0 12px 30px hsl(210 6% 13% / .18);padding:6px;flex-direction:column;gap:2px}
	  .phx-view-menu.open{display:flex}
	  .phx-view-menu-item{display:block;width:100%;text-align:left;min-height:var(--btn-h-touch);padding:0 12px;border:none;border-radius:var(--btn-radius);background:transparent;color:var(--ink);font-size:var(--btn-fs-work);font-family:var(--font-body);cursor:pointer}
	  .phx-view-menu-item:hover{background:var(--t3)}
	  .phx-view-menu-item.active{background:var(--blue);color:var(--white);font-weight:600}
	  .phx-view-menu-item:focus-visible{outline:2px solid var(--blue-l);outline-offset:-2px}
	  /* 3 вида каталога — один источник разметки карточки (.phx-card), представление только
	     классом на .phx-cat-grid (ЗАДАНИЕ п.2.2). Каталог: Визуальные улучшения 14.08, п.3 —
	     «Крупная» (grid-large) убрана полностью, остались Мелкая (grid-compact, новый дефолт)
	     и Список. */
	  /* СРОЧНО 14.08 — страховка от регрессии «Похожие товары» (см. ЗАДАНИЕ_ClaudeCode_СРОЧНО_
	     Похожие_товары_размер.md): базовый класс раньше не был самодостаточным (0 колонок без
	     модификатора вида) — сетка без .phx-view-* схлопывалась в 1 колонку на всю ширину.
	     Дефолт ниже — тот же рецепт, что у .phx-view-grid-compact — теперь работает сам по себе,
	     модификаторы (специфичнее: класс+класс) по-прежнему переопределяют его как раньше. */
	  /* minmax(0,1fr), не голый 1fr — иначе трек не может сжаться меньше min-content содержимого
	     карточки (текст цены/фото с width-атрибутом), сетка вылезает за контейнер (горизонтальный
	     скролл на mobile, найдено 14.08 при переходе на 8 колонок). Тот же фикс во всех
	     .phx-view-grid-compact ниже (900px/560px) и в .phx-view-list (список — 1 колонка, тоже
	     на всякий случай, ту же природу бага проще исключить сразу). */
	  .phx-cat-grid{display:grid;gap:14px;grid-template-columns:repeat(5,minmax(0,1fr))}
	  /* Финал числа колонок на desktop по прямым правкам Алексея 14.08 — каталог 5, «Похожие
	     товары» 6 (у них уже свой модификатор .phx-view-grid-similar, ниже). */
	  .phx-cat-grid.phx-view-grid-compact{grid-template-columns:repeat(5,minmax(0,1fr));gap:10px}
	  .phx-cat-grid.phx-view-list{grid-template-columns:1fr;gap:8px}
	  /* «Похожие товары» на карточке — по правке Алексея 14.08 больше не следует за размером
	     основного каталога выше (тот менялся отдельно). Три класса специфичнее двух —
	     переопределяет .phx-view-grid-compact без !important. */
	  .phx-cat-grid.phx-view-grid-compact.phx-view-grid-similar{grid-template-columns:repeat(7,minmax(0,1fr))}
	  /* Мелкая сетка — те же карточки, компактнее фото/отступы/второстепенный текст; фото,
	     название, цена, наличие и корзина остаются читаемыми (ЗАДАНИЕ п.2.2). */
	  .phx-view-grid-compact .phx-card{padding:8px}
	  .phx-view-grid-compact .phx-card-ph{margin-bottom:6px}
	  .phx-view-grid-compact .phx-card-name{font-size:12.5px;margin-bottom:1px}
	  /* Дизайн: Каталог/Товар/Корзина/Контакты 13.08, п.12 — второстепенный текст мелкой сетки
	     подрос на 1px (без нового 6-го размера в шкале — это внутренняя микро-подстройка плотной
	     карточки, не входила в формальную шкалу --step-* и раньше). */
	  .phx-view-grid-compact .phx-card-var{font-size:11.5px;margin-bottom:6px;min-height:15px}
	  /* Задача 160, 21.08 — .phx-card-pack (артикул/размер/«Выбрать») делил строку с ценой
	     через justify-content:space-between (базовое правило .phx-card-pricebox ниже по
	     файлу) — на плитке в 5 колонок (решение Алексея 14.08, число не трогаю) карточка
	     местами сжималась до 115-134px, и на подпись «...· опт с НДС» оставалось всего
	     36-48px из нужных ~68 при живом замере (архитектор поймал именно 928/1024px).
	     Цена и подпись — то, ради чего вообще открывают карточку опта, артикул/«Выбрать» —
	     не соперник за строку. Ставлю их друг под другом вместо рядом: обоим по всей ширине
	     блока, конкурировать больше не за что. Действует и на «Похожие товары» (138) — тот
	     же компонент карточки (buildCardsHtml, 137/158/138), тот же дефект был бы и там;
	     единая карточка для сетки и похожих — уже принятое решение 138, не завожу вторую
	     версию ради этой правки. */
	  .phx-view-grid-compact .phx-card-pricebox{padding:6px 8px;margin-bottom:6px;flex-direction:column;align-items:flex-start;gap:2px}
	  .phx-view-grid-compact .phx-card-pack{text-align:left;max-width:none}
	  .phx-view-grid-compact .phx-card-pr{font-size:14px}
	  .phx-view-grid-compact .phx-card-per{font-size:10.5px}
	  .phx-view-grid-compact .phx-card-pack{font-size:10.5px}
	  .phx-view-grid-compact .phx-card-ov{font-size:10.5px;padding:3px 7px}
	  /* Каталог: Визуальные улучшения 14.08, п.5 — зум фото на ховере/фокусе карточки товара,
	     только вид «Мелкая» (как в задании). Зумится только фото внутри .phx-card-ph (уже
	     overflow:hidden) — не вся карточка/цена/кнопки. */
	  .phx-view-grid-compact .phx-card-thumb{transition:transform .3s ease}
	  @media(hover:hover){.phx-view-grid-compact .phx-card:hover .phx-card-thumb{transform:scale(1.05)}}
	  .phx-view-grid-compact .phx-card:focus-within .phx-card-thumb{transform:scale(1.05)}
	  @media(prefers-reduced-motion:reduce){.phx-view-grid-compact .phx-card-thumb{transition:none}}
	  /* Список — карточка становится горизонтальной строкой через grid-areas на тех же дочерних
	     элементах (фото/название/вариант/цена/корзина), без второго HTML-шаблона (ЗАДАНИЕ п.2.2). */
	  /* Дизайн: Каталог/Товар/Корзина/Контакты 13.08, п.6 — настоящая табличная раскладка вместо
	     «имя слева, цена и кнопка далеко справа, середина пустая». Явные колонки: фото → товар/
	     вариант → упаковка → наличие → цена → корзина. .phx-card-ph/.phx-card-pricebox — обычные
	     обёртки в grid-large/compact (фото+бейдж, цена+упаковка) — здесь их не удаляем из HTML
	     (один источник разметки, ЗАДАНИЕ п.2.2), а «растворяем» через display:contents только в
	     list-режиме, так их дети (фото/бейдж, цена/упаковка) становятся independent grid-item и
	     получают каждый свою колонку, без второго HTML-шаблона. */
	  /* Задача 158, 21.08, дефект 1 — колонка имени была "1fr" без minmax(0,...): без явного
	     минимума grid-трек сайзится по MIN-CONTENT содержимого соседних неименованных областей,
	     не по остатку ширины. У карточки-группы .phx-card-swatches не имел grid-area вовсе (ниже
	     это же исправлено) — авто-размещение утаскивало трек name в почти ноль. minmax(0,1fr) —
	     тот же приём, что уже стоит на самом .phx-card (см. комментарий про 8pt-сетку выше), здесь
	     не хватало именно на внутреннем гриде строки списка. */
	  /* Дефект 1, продолжение — даже после adjacent-фикса выше суммы фиксированных колонок
	     (72+104+92+92+148=508px) и зазоров (5×14=70px) на типичной ширине списка (928px viewport,
	     карточка ~588px по контенту за вычетом padding) почти не оставляли места колонке имени —
	     она была самой узкой, а не самой широкой, как требует задание. Плотнее фото/упаковку/
	     наличие/цену/кнопку — это вторичная информация в списке, имя первично. */
	  /* Задача 166, 21.08 — колонка имени ужималась тремя задачами подряд (158 дала minmax(0,1fr),
	     160 забрала 8px в пользу цены) и на 928px стала 132px при живом замере: 36 из 46 карточек-
	     групп (78%) обрезали название на первой строке. Причина не в ширинах, а в раскладке:
	     шесть колонок фиксированной ширины в строке ~590px — бюджет исчерпан, любая следующая
	     правка любой колонки снова заберёт у имени.
	     Раскладка Миррэй (ЭТАЛОНЫ_и_ориентиры.md): имя занимает ВСЮ ширину карточки, служебное
	     (варианты/упаковка/наличие/цена/кнопка) идёт под ним. Треки колонок НЕ трогаю ни на пиксель
	     (76/72/84/116 откалиброваны задачей 160 — трогать их значит повторить ту же ошибку):
	     меняется только grid-template-areas — область name растянута на все пять колонок первой
	     строки, вторая строка осталась ровно прежней. Высота ряда не растёт: строк как было две,
	     а фото (60px, span обеих строк) выше суммы «имя 18px + gap 4px + кнопка 33px» — плотность
	     списка сохраняется (замер до/после в reports/166-*). */
	  .phx-view-list .phx-card{display:grid;grid-template-columns:60px minmax(0,1fr) 76px 72px 84px 116px;grid-template-areas:"ph name name name name name" "ph var pack avail price ctl";align-items:center;gap:4px 10px;padding:10px 12px}
	  .phx-view-list .phx-card-ph{display:contents}
	  .phx-view-list .phx-card-thumb{grid-area:ph;margin-bottom:0}
	  .phx-view-list .phx-card-ov{grid-area:avail;position:static;background:none;box-shadow:none;padding:0;font-size:11px;justify-self:start;white-space:normal}
	  .phx-view-list .phx-card-name{grid-area:name;margin-bottom:0}
	  /* Задача 166 — min-height:2.6em у .phx-card-name-clamp2 (задача 137) резервирует две строки,
	     чтобы в ПЛИТКЕ ряд карточек стоял ровно. В списке ряд один, выравнивать нечего, а лишние
	     18px первой строки грида толкали бы карточку выше фото и съедали плотность. Клампинг в
	     2 строки при этом остаётся — длинное имя обрезается, но не раньше второй строки (условие 1
	     задачи), просто без принудительного резерва высоты у коротких. */
	  .phx-view-list .phx-card-name-clamp2{min-height:0}
	  .phx-view-list .phx-card-var{grid-area:var;margin-bottom:0;min-height:0}
	  /* Дефект 1 — кружки-образцы карточки-группы явно встают в ту же ячейку, что .phx-card-var
	     у одиночной (вторая строка, колонка имени) — без grid-area браузер авто-размещал их в
	     первую свободную ячейку built-in алгоритмом, и это и утаскивало ширину колонки имени. */
	  .phx-view-list .phx-card-swatches{grid-area:var;margin-bottom:0;min-height:0}
	  .phx-view-list .phx-card-pricebox{display:contents}
	  .phx-view-list .phx-card-pack{grid-area:pack;text-align:left;max-width:none}
	  .phx-view-list .phx-card-prwrap{grid-area:price}
	  .phx-view-list .phx-card-ctl{grid-area:ctl;margin-top:0;justify-self:end;min-width:0}
	  .phx-view-list .phx-card-ctl .phx-addcart-btn{width:auto}
	  /* Карточка V3 «Цена и упаковка» — мокап catalog-card-v3, выбран Алексеем 13.08 */
	  /* min-width:0 — грид-айтем по умолчанию не сжимается меньше min-content своего содержимого
	     (текст цены/упаковки), даже когда сам трек уже сузился через minmax(0,1fr) — тот же класс
	     переполнения, но на уровень глубже. Остаточные ~17px горизонтального скролла на mobile
	     (найдено 14.08 при переходе на 8 колонок) устранены этим правилом. */
	  .phx-card{position:relative;min-width:0;background:var(--white);border:1px solid var(--line);border-radius:14px;padding:12px;display:flex;flex-direction:column}
	  .phx-card-ph{position:relative;aspect-ratio:1/1;border-radius:10px;background:var(--t3);overflow:hidden;display:flex;align-items:center;justify-content:center;margin-bottom:10px}
	  .phx-card-ph .phx-card-thumb{width:100%;height:100%;display:flex;align-items:center;justify-content:center;font-size:36px;margin-bottom:0;background:transparent}
	  .phx-card-ov{position:absolute;left:8px;bottom:8px;font-size:10.5px;font-weight:700;color:var(--ok);background:var(--white);padding:4px 9px;border-radius:20px;box-shadow:0 2px 8px hsl(210 6% 13% / .10);white-space:nowrap}
	  .phx-card-ov.out{color:var(--warn-text)}
	  .phx-card-var{font-size:12px;color:var(--muted);margin-bottom:10px;min-height:17px}
	  /* Задача 137, 21.08 — карточка-группа (мокап «схлопывание вариантов», вариант B). Название
	     занимает то же место в разметке, что раньше .phx-card-name+.phx-card-var у одиночного
	     товара — клампится в 2 строки (min-height держит высоту ряда карточек одинаковой, даже
	     если у части названия в одну строку). */
	  .phx-card-name-clamp2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-height:2.6em;margin-bottom:10px}
	  .phx-card-swatches{display:flex;align-items:center;gap:5px;margin-bottom:10px;min-height:17px;flex-wrap:wrap}
	  /* Задача 158, дефект 2 — кружок теперь настоящая цель клика/Tab (role="link", см. JS
	     wireCardSwatches), не декорация: курсор и видимая рамка фокуса — как у любой ссылки сайта,
	     тот же токен фокуса, что и везде (см. правило a:focus-visible… в начале файла). */
	  .phx-swatch{position:relative;width:17px;height:17px;border-radius:50%;border:1px solid var(--line);flex:none;display:block;cursor:pointer}
	  .phx-swatch:focus-visible{outline:2px solid var(--acc-text);outline-offset:2px}
	  /* Задача 160, 21.08 — цель касания 17×17px мельче требования доступности (44×44).
	     Прозрачное поле вокруг кружка через ::before, не сам кружок — видимый размер и
	     плотность ряда (до 12 образцов в карточке, задание 158) не трогаю. Честная
	     находка 21.08 — при плотном ряде (gap:5px, шаг между центрами ~22px) 44px-зона
	     неизбежно перекрывает соседний кружок, живой отчёт задачи 160 это прямо
	     предупреждал. На практике перекрытие мешало именно точным устройствам (мышь):
	     клик почти на границе двух кружков иногда попадал не в тот кружок. Требование
	     44×44 — про TOUCH TARGET (WCAG 2.5.5), не про мышь: ограничиваю расширенную зону
	     media(pointer:coarse) — только сенсорные экраны, где палец объективно менее
	     точен мыши. На точных указателях (pointer:fine — мышь/трекпад) кликабельна ровно
	     видимая область кружка, без невидимого нахлёста на соседей. */
	  @media(pointer:coarse){
	    .phx-swatch::before{content:"";position:absolute;top:50%;left:50%;width:44px;height:44px;transform:translate(-50%,-50%)}
	  }
	  /* Не-цвет (размер, «прозрачный» и т.п.) — пилюля текстом, не кружок (задание, п.3). */
	  /* Задача 167 — «Прозрачный» это не «нет цвета», а особый случай: шахматная подложка,
	     как «нет цвета» в графических редакторах, вместо подписи буквами. Клетка 4px —
	     читается и в кружке 17px в плитке каталога, и в 36px на карточке товара. */
	  .phx-swatch-transparent{background-color:var(--white);background-image:linear-gradient(45deg,var(--line) 25%,transparent 25%,transparent 75%,var(--line) 75%),linear-gradient(45deg,var(--line) 25%,transparent 25%,transparent 75%,var(--line) 75%);background-size:8px 8px;background-position:0 0,4px 4px}
	  .phx-swatch-pill{font-size:9.5px;font-weight:600;color:var(--muted);background:var(--t3);border:1px solid var(--line);border-radius:20px;padding:2px 6px;line-height:1.4;white-space:nowrap;max-width:52px;overflow:hidden;text-overflow:ellipsis;cursor:pointer}
	  .phx-swatch-pill:focus-visible{outline:2px solid var(--acc-text);outline-offset:2px}
	  .phx-swatch-more{font-size:11px;font-weight:700;color:var(--muted);flex:none;cursor:pointer}
	  .phx-swatch-more:focus-visible{outline:2px solid var(--acc-text);outline-offset:2px}
	  /* === Задача 163, 21.08 — выбор варианта прямо в карточке сетки === */
	  /* Кольцо выбранного образца рисуется box-shadow, а не border/outline: border сдвинул бы сам
	     кружок (17px, до 4 штук в ряд плюс «+N») и поехала бы вся строка карточки, а outline уже
	     занят состоянием фокуса (правило выше) — одно перекрывало бы другое. Белая прослойка
	     первым слоем — чтобы кольцо читалось и на светлом кружке (белый/шампань). */
	  .phx-swatch.is-on{box-shadow:0 0 0 2px var(--white),0 0 0 4px var(--blue)}
	  .phx-swatch-pill.is-on{border-color:var(--blue);color:var(--blue);background:var(--blue-pale);font-weight:700}
	  /* Подпись выбранного варианта дописывается к названию товара (требование задачи, п.1).
	     Отдельный узел, а не переписанный текст названия, — базовое название остаётся тем же
	     .phx-card-name-clamp2 и клампится по тем же правилам. */
	  .phx-card-selvar{color:var(--blue);font-weight:700}
	  /* Приёмка глазами (правило 21.08): на 928px колонка имени в списке всего ~140px, базовое
	     название уже занимает обе строки клампа — дописанная подпись варианта физически не
	     попадала в кадр, и понять, что именно выбрано, было можно только по кольцу на кружке.
	     Выбранной карточке даём третью строку. Только выбранной: без выбора высота карточек и
	     строк сетки прежняя, до пикселя. min-height не трогаем — иначе на ≤560px, где фото
	     растянуто на три строки грида, все 44 карточки-группы разом стали бы выше без причины. */
	  .phx-card-pick.is-picked .phx-card-name{-webkit-line-clamp:3}
	  /* Подсказка на месте кнопки, пока вариант не выбран (требование задачи, п.2). Не «неактивная
	     кнопка»: по неактивной кнопке клиент жмёт и не понимает, почему ничего не произошло.
	     Пунктирная рамка занимает ту же строку, что кнопка «В корзину» у одиночного товара —
	     высота карточек в ряду не прыгает в момент выбора. */
	  .phx-card-pickhint{display:block;text-align:center;font-size:11px;line-height:1.25;font-weight:600;color:var(--muted);border:1px dashed var(--line);border-radius:8px;padding:8px 4px}
	  /* Задача 166, 21.08 — «Выберите вариант» стояла бледной серой пунктирной рамкой рядом с
	     яркой розовой «В корзину» соседней карточки, и ряд читался как «этот товар купить можно,
	     а этот нельзя», хотя разница только в том, что не выбран цвет.
	     Отдельный модификатор, а не правка общего .phx-card-pickhint: тем же классом рисуется
	     «Уточните цену у менеджера» (ctlHtml, hasPrice===false) — там приглушённый вид ЧЕСТЕН,
	     действия на карточке для такого товара действительно нет.
	     Вид — акцентная рамка того же семейства, что и кнопка (--acc-btn), но контурная с лёгкой
	     заливкой, не сплошная: читается как активная и приглашающая, и при этом не обещает
	     «нажми — положу в корзину» (кнопкой она не является, кладёт в корзину только настоящая
	     .phx-addcart-btn после выбора кружка). Текст — --acc-text (тот же токен, что везде для
	     мелкого акцентного текста, контраст ≥4.5:1 на белом), не --acc-btn: 11px требует 4.5:1,
	     а --acc-btn калиброван под белый текст НА нём, не под текст ИМ. */
	  .phx-card-pickhint-var{color:var(--acc-text);border:1.5px solid var(--acc-btn);border-style:solid;background:var(--cta-bg);font-weight:700;cursor:pointer}
	  @media(hover:hover){.phx-card-pickhint-var:hover{background:var(--t2);border-color:var(--acc-btn-h)}}
	  /* «Выбрать» — там, где у одиночного товара обычно артикул/кратность (.phx-card-pack), тот же
	     слот переиспользован намеренно: карточки группы и одиночного товара держат одинаковую
	     раскладку ценового блока, ничего не прыгает между соседними карточками в сетке. */
	  .phx-card-choose{color:var(--acc-btn-h);font-weight:700}
	  .phx-card-pricebox{margin-top:auto;display:flex;align-items:center;justify-content:space-between;gap:8px;background:var(--blue-pale);border-radius:10px;padding:8px 12px;margin-bottom:8px}
	  .phx-card-prwrap{min-width:0}
	  .phx-card-pr{display:block;font-size:16.5px;font-weight:800;line-height:1.1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
	  /* B7 15.08 (tasks/009-price-vat-site.md) — позиции без валидной цены с НДС (PRICE_WHOLESALE_VAT
	     == 0 в фиде), молча подставлять цену без НДС нельзя, показываем текстом вместо числа. */
	  .phx-card-pr-noprice{font-size:13px;font-weight:700;color:var(--muted)}
	  /* Задача 158, дефект 4 — «за шт · опт, с НДС» переносилось по словам на 3-4 строки в узкой
	     плитке, толкая цену/«Выбрать»/«В корзину» вбок и рассинхронизируя высоту блока цены между
	     одиночной карточкой и карточкой-группой в одном ряду. Одна строка, не влезает — троеточие,
	     не перенос (задание прямо требует «сокращается, а не рвётся»). */
	  .phx-card-per{display:block;font-size:10.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
	  .phx-card-pack{font-size:10.5px;color:var(--blue-l);font-weight:600;text-align:right;max-width:46%}
	  .phx-card-thumb{aspect-ratio:1/1;height:auto;border-radius:10px;background:var(--blue-pale);display:flex;align-items:center;justify-content:center;font-size:36px;margin-bottom:10px}
	  img.phx-card-thumb{object-fit:contain;width:100%;background:var(--white)}
	  .phx-card-ph img.phx-card-thumb{background:transparent}
	  /* Дизайн: Каталог/Товар/Корзина/Контакты 13.08, п.8 — нейтральная заглушка вместо
	     эмодzhi-банта, поверх любого размера фото-слота (карточка/карточка товара/корзина).
	     B38 16.08 (tasks/042-photo-placeholders.md, п.4) — раньше был только текст «Фото
	     готовится», теперь название и артикул — задание прямо просит, чтобы клиент прочитал,
	     какой это товар, а не просто узнал, что фото нет. flex-column — название и артикул
	     разными строками, оба центрированы и обрезаны, чтобы длинное название не распирало
	     маленький квадратный слот карточки. */
	  .phx-photo-pending{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;text-align:center;padding:6px 8px}
	  .phx-photo-pending-nm{font-size:11px !important;font-weight:600;color:var(--ink);letter-spacing:.01em;line-height:1.25;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
	  .phx-photo-pending-sku{font-size:10px !important;font-weight:500;color:var(--muted)}
	  img.phx-pd-thumb{object-fit:contain;width:100%;display:block;background:var(--white)}
	  .phx-badge-in{align-self:flex-start;background:var(--ok-bg);color:var(--ok);font-size:11px;font-weight:700;padding:3px 8px;border-radius:20px;margin-bottom:8px}
	  .phx-badge-out{align-self:flex-start;background:var(--cta-bg);color:var(--cta-d);font-size:11px;font-weight:700;padding:3px 8px;border-radius:20px;margin-bottom:8px}
	  .phx-card-name{font-size:13.5px;font-weight:700;line-height:1.3;margin-bottom:2px}
	  .phx-card-sku{font-size:11.5px;color:var(--muted);margin-bottom:10px}
	  .phx-card-price{margin-top:auto;font-size:17px;font-weight:800}
	  .phx-card-price small{font-size:11.5px;font-weight:500;color:var(--muted)}
	  .phx-pd{display:grid;grid-template-columns:360px 1fr;gap:32px;padding-bottom:30px}
	  .phx-pd-thumb{aspect-ratio:1/1;height:auto;border-radius:16px;background:var(--blue-pale);display:flex;align-items:center;justify-content:center;font-size:80px}
	  .phx-pd-meta{font-size:13px;color:var(--muted);display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin-bottom:14px}
	  .phx-pd-priceBox{background:var(--bg);border:1px solid var(--line);border-radius:14px;padding:18px}
	  .phx-pd-prow{display:flex;justify-content:space-between;padding:7px 0;font-size:14px;border-bottom:1px dashed var(--line)}
	  .phx-pd-prow:last-of-type{border:none}
	  .phx-pd-prow b{font-size:16px}
	  /* B30 15.08 (tasks/051-prices-correctness-and-units.md) — единица рядом с каждым
	     уровнем цены в карточке (была только в списке каталога). */
	  .phx-pd-unit{font-size:11.5px;font-weight:500;color:var(--muted)}
	  /* Задача 157 — порог уровня цены («от 5 000 ₽ за заказ») под названием уровня, той же
	     приглушённой строкой, что и единица измерения справа, только слева от суммы. */
	  .phx-pd-threshold{display:block;font-size:11.5px;font-weight:500;color:var(--muted)}
	  /* Задача 139, 21.08 — переключатель варианта в карточке товара. Подпись нейтральная
	     («Вариант»), не «Цвет»: часть групп различается размером («15*10*H25см») или узором,
	     а не оттенком (разметка словаря задачи 132). Визуальный язык тот же, что у образцов в
	     сетке каталога (.phx-swatch/.phx-swatch-pill, задача 158) — кружок для цвета, пилюля для
	     не-цвета, — но крупнее: здесь это орган управления заказом, а не подсказка на плитке.
	     Ряд ПЕРЕНОСИТСЯ (flex-wrap), а не скроллится по горизонтали: правило 19.08 — элемент в
	     ряду у края экрана обязан целиком помещаться в innerWidth, у переноса это выполняется
	     конструктивно. Цвета образцов — не токены, а данные товара из colors.json (тот же приём,
	     что уже принят в сетке): они приходят инлайновым style, палитра шаблона не расширяется. */
	  .phx-pd-variants{margin-bottom:16px}
	  .phx-pd-varhead{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-bottom:8px}
	  .phx-pd-varname{font-size:13px;color:var(--muted)}
	  .phx-pd-varname b{color:var(--ink);font-size:14px}
	  .phx-pd-varcount{font-size:11.5px;color:var(--muted);flex:none;white-space:nowrap}
	  .phx-pd-varrow{display:flex;flex-wrap:wrap;gap:8px;padding:3px}
	  /* Развёрнутый ряд на 63 варианта — своя прокрутка, чтобы он не отодвинул «Похожие товары»
	     на пол-экрана. Свёрнутый (по умолчанию) потолка не имеет: 12 образцов и так две строки. */
	  .phx-pd-varrow.is-expanded{max-height:196px;overflow-y:auto}
	  .phx-pd-sw{width:36px;height:36px;min-width:36px;border-radius:50%;border:1px solid var(--line);padding:0;flex:none;cursor:pointer;background-color:var(--t3)}
	  .phx-pd-sw-pill,.phx-pd-sw-more{width:auto;min-width:0;max-width:100%;height:36px;border-radius:var(--btn-radius);padding:0 14px;font:inherit;font-size:var(--btn-fs-mini);font-weight:600;color:var(--ink);background:var(--t3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
	  .phx-pd-sw-more{color:var(--acc-text);background:var(--white)}
	  .phx-pd-sw:focus-visible{outline:2px solid var(--acc-text);outline-offset:2px}
	  /* Выбранный вариант — двойное кольцо (белый зазор + графит), а не только заливка: у белого и
	     кремового образца обычная рамка неразличима на светлом фоне карточки. Честная находка
	     21.08 (кадр с телефона) — раньше кольцо было того же пиона, что и рамка фокуса чуть выше
	     (--acc-text/--acc-btn — соседние оттенки одного акцента), на фото с телефона два разных
	     состояния (просто нажат vs выбран) сливались в одно и то же розовое кольцо. Кольцо
	     «выбрано» переведено на --blue (графит — тот же приём уже стоит у кружков в сетке
	     каталога, .phx-swatch.is-on ниже по файлу, только там до этой правки дошли раньше) —
	     третьего цвета в палитре не завожу, беру существующий нейтральный токен. */
	  .phx-pd-sw.is-on{border-color:var(--blue);box-shadow:0 0 0 2px var(--white),0 0 0 4px var(--blue)}
	  .phx-pd-actions{display:flex;gap:10px;margin-top:14px}
	  .phx-pd-actions .btn{flex:1;text-align:center;min-width:0}
	  /* Задача 134, 20.08 — «Спросить ассистента» никогда не получала .btn-sm (только «В корзину»
	     через .phx-addcart-btn), поэтому жила на паре ступеней крупнее: padding 12px 22px/шрифт
	     15px против 8px 12px/13px у соседней кнопки — на 360-430px подпись переносилась в две
	     строки, кнопка становилась на 16px выше пары и забирала себе больше половины ряда (min-
	     width:auto по умолчанию у flex-элемента не даёт ужаться меньше содержимого — с более
	     крупным текстом «Спросить ассистента» это и раздвигало ряд неровно, «В корзину» доставался
	     меньший остаток). min-width:0 выше — снимает этот перекос сам по себе (стандартный приём
	     для flex:1 через контент разной длины); правило ниже — сводит второстепенную кнопку к
	     тем же цифрам, что и .btn-sm у главной, дословно, чтобы визуально осталась одна пара. */
	  .phx-pd-actions .btn-ghost{padding:6.5px 12px;font-size:var(--btn-fs-work);border-radius:var(--btn-radius)}
	  /* padding-top/bottom 6.5px, не 8px, как у .btn-sm — компенсация border:1.5px solid у
	     .btn-ghost (соседняя .btn-cta border:none). Без этого высоты совпадали только на
	     мобильном случайно (там .phx-addcart-btn{min-height:44px} снизу перекрывал разницу
	     значением-полом) — на десктопе, где такого пола нет, было 31px против 33px. 6.5+6.5+
	     1.5+1.5 = 16 = 8+8+0+0 — та же итоговая высота бокса, что у .btn-cta, на любой ширине. */
	  .phx-card-ctl{margin-top:8px}
	  .phx-card-ctl .phx-addcart-btn{width:100%}
	  .phx-pd-ctl{flex:1;margin-top:0}
	  .phx-pd-ctl .phx-addcart-btn{width:100%}
	  .phx-card-stepper{display:flex;align-items:center;justify-content:space-between;background:var(--blue-pale);border-radius:var(--btn-radius);padding:4px}
	  .phx-card-stepper button{width:36px;height:36px;border:none;background:var(--white);border-radius:var(--btn-radius);font-size:var(--btn-ico);cursor:pointer;color:var(--blue);font-weight:700}
	  .phx-card-stepper span{font-size:13.5px;font-weight:700;color:var(--ink)}
	  .phx-pd-ctl .phx-card-stepper{padding:6px}
	  .phx-pd-ctl .phx-card-stepper button{width:40px;height:40px}
	  .phx-similar-title{font-size:18px;font-weight:700;margin:8px 0 14px}
	  @media(max-width:900px){
	    /* Задача 184 — в одну колонку gap:24px превращается в вертикальный воздух ровно между
	       блоком разделов и строкой фильтров. На десктопе это горизонтальный зазор между
	       сайдбаром и лентой и остаётся 24px — правило только для этой ширины. */
	    .phx-catalog-layout{grid-template-columns:1fr;gap:8px}
	    .phx-cat-grid.phx-view-grid-compact{grid-template-columns:repeat(4,minmax(0,1fr))}
	    .phx-cat-grid.phx-view-grid-compact.phx-view-grid-similar{grid-template-columns:repeat(5,minmax(0,1fr))}
	    .phx-pd{grid-template-columns:1fr}
    /* Дизайн: Каталог/Товар/Корзина/Контакты 13.08, п.3 — квадратное фото во всю ширину
       экрана (aspect-ratio:1/1) на узком mobile само по себе высотой почти с экран, уводя
       цену/наличие/«В корзину» за пределы первого экрана. Реальное фото не обрезаем
       (object-fit:contain внутри уже центрирует/вписывает) — просто ограничиваем высоту рамки. */
    .phx-pd-thumb{max-height:220px}
    /* Задача 153, 20.08 (аудит MOB-PDP-01, P1) — ограничения высоты фото (правка выше,
       13.08) не хватило: даже 220px фото + артикул/раздел/наличие + 4 строки цены + кратность
       перед кнопкой всё равно уводили «В корзину» за экран на 360×800/390×844 (замер живьём —
       до 140px ниже видимой области). Не сжимаю дальше и не убираю ни одну строку цены (нельзя
       трогать состав данных) — переставляю порядок визуально: на ≤900px фото уходит ПОСЛЕ
       цены/остатка/кнопки, а не перед ними. `order` на grid-детях `.phx-pd`, разметка и DOM-
       порядок (а значит и порядок для скринридера/Tab) не меняются — только то, что видно
       первым на экране. */
    .phx-pd-gallery{order:2}
    .phx-pd-info{order:1}
    .phx-pd-priceBox{padding:12px}
    .phx-pd-prow{padding:5px 0}
    /* Задача 139 — на mobile образец обязан быть настоящим touch-target'ом (≥44px, правило
       дизайн-системы), а не уменьшенной копией десктопного кружка. Развёрнутый ряд здесь
       ограничен жёстче, чем на десктопе: блок цены и кнопка «В корзину» на ≤900px стоят ВЫШЕ
       фото (задача 153), запас до нижней границы первого экрана был 111–279px — длинный ряд
       съел бы его целиком. */
    .phx-pd-sw{width:44px;height:44px;min-width:44px}
    .phx-pd-sw-pill,.phx-pd-sw-more{width:auto;min-width:0;height:44px}
    /* 112px = две полные строки образцов (44+8+44) плюс 16px третьей, которая намеренно
       «выглядывает» из-под нижнего края. Ровно 96px (две строки впритык) выглядели как полный
       список — человек нажимал «Ещё 59» и видел 12 кружков без единого намёка, что внутри есть
       прокрутка. Обрезанный ряд — тот же приём-подсказка, что fade у чипсов подразделов.
       Верхняя граница числа не произвольна: при 390×844 кнопка «В корзину» выходит за первый
       экран, когда весь блок переключателя перерастает ~180px (замер, см. отчёт 139). */
    .phx-pd-varrow.is-expanded{max-height:112px}
	    /* Backlog 12.08, п.2 — на ≤900px сайдбар с чипсами/разделами встаёт ОДНОЙ колонкой
	       над лентой товаров (grid схлопнулся в 1fr), но position:sticky с него не снимался —
	       сайдбар (высотой в сотни px, до 13 разделов + чипсы подкатегорий) прилипал к верху и
	       перекрывал первые карточки товаров при скролле (проверено: первая карточка полностью
	       пряталась под сайдбаром). На мобильной ширине sticky не нужен — весь сайдбар и так
	       виден целиком перед лентой, просто отключаем прилипание. */
	    .phx-cat-sidebar{position:static}
	    /* Задача 176, 21.08 (решение Алексея «рамку раздела сжимай») — на телефоне блок разделов
	       занимал 107px при почти пустом содержимом: одна ссылка и одна кнопка, остальное — рамка,
	       скругление и 16px паддинга со всех сторон. Живой замер на 390: до первой карточки 358px
	       от низа шапки. Сворачиваем оформление, а не функцию: ссылка и кнопка встают в один ряд,
	       рамка/фон/паддинг уходят, раскрытый список разделов переносится на свою строку целиком
	       (flex-basis:100%) и работает как раньше. Десктоп (>=901px) не затронут — там сайдбар
	       остаётся колонкой со своим sticky и прокруткой списка. */
	    .phx-cat-sidebar{background:none;border:none;border-radius:0;padding:0;display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:0}
	    .phx-cat-alllink{margin-bottom:0;flex:0 0 auto;min-height:var(--btn-h-touch);display:inline-flex;align-items:center}
	    .phx-cat-list{flex:1 1 100%}
	    /* UX Overhaul 13.08, Batch B — на mobile список «Разделы» (все 13 категорий) свёрнут по
	       умолчанию за кнопкой-toggle: дублирует навигацию, которую пользователь уже прошёл, и
	       раньше добавлял 872px ДО первого товара. На desktop контент виден и так, кнопка скрыта. */
	    .phx-cat-list-toggle{display:flex;align-items:center;gap:6px;width:auto;flex:0 0 auto;min-height:var(--btn-h-touch);background:var(--white);border:1px solid var(--line);border-radius:var(--btn-radius);padding:0 14px;font-weight:700;font-family:var(--font-body);font-size:var(--btn-fs-work);color:var(--ink);cursor:pointer;text-align:left}
	    .phx-cat-list-toggle .ico{transition:transform .2s;color:var(--muted);font-size:12px}
	    .phx-cat-list-toggle[aria-expanded="true"] .ico{transform:rotate(180deg)}
	    .phx-cat-list{display:none}
	    .phx-cat-list.open{display:block;margin-top:4px}
	    /* Каталог: Подразделы, Скролл и Виды 13.08 — панель подразделов над товарами становится
	       одной горизонтально прокручиваемой строкой (свайп); каждая группа (Формат/Отделка) —
	       цельный flex-блок, чтобы подпись группы не отрывалась от «своих» чипсов при скролле.
	       Переключатель вида — вне #phxSubcatNav (сосед по .phx-subcat-sticky), поэтому со
	       свайпом чипсов не уезжает (п.2.1/mobile). Сама sticky-панель компактнее по высоте. */
	    /* Задача 184, 22.08 (решение Алексея «свернуть в кнопку») — на телефоне панель
	       фильтров занимала 112-152px: два ряда плашек «Формат» и «Отделка» в розовом блоке,
	       выше заголовка раздела и блока разделов вместе взятых. Сворачиваем оформление,
	       а не функцию: в строке остаётся кнопка (и переключатель вида, если он на этой
	       ширине показан), сами плашки — те же, просто до нажатия скрыты. Фон и паддинг
	       блока уходят к чипсам: свёрнутая строка не должна выглядеть панелью. */
	    .phx-subcat-sticky{gap:8px;padding:0;background:none;box-shadow:none;border-radius:0;margin-bottom:8px}
	    /* Задача 196, 22.08 (решение Алексея по отчёту 195) — кнопка во всю ширину строки плюс
	       невидимый запас снизу. Диагностика на живом телефоне показала: все пять нажатий Алексея
	       попали НИЖЕ кнопки — на 1, 2, 9, 15 и 26 px, — а прямо там начинается карточка товара,
	       и это ссылка на всю площадь. Кнопка занимала 103 px из 440: промахнуться мимо неё легко,
	       а цена промаха — уход со страницы.
	       Ширина: вторая колонка грида на этой ширине пуста (и .phx-view-switch, и .phx-view-popup
	       здесь display:none — замерено), поэтому растягивание ничего не сдвигает. Содержимое
	       прижато влево, поэтому глазом меняется только ширина рамки.
	       overflow:visible — обязателен: в базовом правиле стоит overflow:hidden ради многоточия,
	       и он бы обрезал собственный псевдоэлемент по коробке кнопки. Многоточие здесь больше не
	       нужно — подпись короткая, а места теперь вся строка (проверено на 360 и 440: не
	       переносится и не обрезается). Тот же приём с ::before у .phx-swatch-pill в этом файле
	       однажды молча не сработал именно из-за overflow.
	       position:relative + z-index — тоже обязательны: у .phx-subcat-sticky на этой ширине
	       position:static, поэтому её z-index:20 не действует вовсе, а карточки идут в DOM позже
	       и перекрыли бы зону.
	       Высота зоны 34 px, а не 32: коробка высотой 32 накрывает смещения 0…31, и точка ровно
	       на +32 в неё уже не попадает — а критерий приёмки требует, чтобы +32 попадал
	       ВКЛЮЧИТЕЛЬНО. Замеренные промахи Алексея доходят до 26 px, так что запас сохраняется. */
	    .phx-filters-toggle{display:flex;grid-column:1 / -1;justify-self:stretch;width:100%;
	      justify-content:flex-start;overflow:visible;position:relative;z-index:2}
	    .phx-filters-toggle::after{content:'';position:absolute;left:0;right:0;top:100%;height:34px}
	    /* Панель раскрыта — под кнопкой уже не карточки, а чипсы фильтров. Зона обязана уйти,
	       иначе она крала бы клики по первому ряду чипсов. */
	    .phx-subcat-sticky.filters-open .phx-filters-toggle::after{display:none}
	    .phx-subcat-scroll{display:none;grid-column:1 / -1;background:var(--blue-pale);border-radius:12px;padding:10px 12px}
	    .phx-subcat-sticky.filters-open .phx-subcat-scroll{display:block}
	    /* B36 16.08 (tasks/043-filter-chips-sorting.md) — независимый аудит зафиксировал «чипы
	       слипаются и обрезаются»: горизонтальная прокрутка технически работала (проверено —
	       .phx-subcat-bar реально прокручивался), но в любой промежуточной точке прокрутки крайний
	       чип показывался наполовину — критерий приёмки требует, чтобы обрезанного чипа не было
	       НИКОГДА, а не «пока не докрутишь». Меняю модель на задании разрешённую альтернативу —
	       перенос на несколько строк вместо горизонтальной прокрутки: каждый чип либо виден
	       целиком, либо не виден вообще, третьего не дано. Раскладка растёт по высоте — снимаю
	       position:sticky только на этой узкой ширине (тот же приём и то же обоснование, что уже
	       есть для .phx-cat-sidebar чуть выше по файлу: sticky-панель в несколько строк рискует
	       перекрыть первые карточки при прилипании к верху, а весь список и так помещается перед
	       лентой без остатка). */
	    .phx-subcat-sticky{position:static}
	    .phx-subcat-bar{flex-wrap:wrap;overflow-x:visible;gap:8px}
	    .phx-subcat-block{flex-wrap:wrap}
	    .phx-subcat-block .phx-chips{flex-wrap:wrap}
	    /* задача 060, п.3 16.08 — «Рулоны640», «Матовая611»: название и число слипались в одно
	       слово. Причина — обычный пробел-текст перед <span class="cnt"> в разметке чипа, без
	       гарантированного зазора и без разницы в размере/весе; тот же inline-flex здесь уже был
	       (задача 043), не хватало gap. Оформление — то же, что у чипов-счётчиков разделов на
	       главной (задача 057, .v12-chip: gap:6px + мельче/светлее число), единый вид чипа с числом
	       по всему сайту, а не два разных. */
	    .phx-subcat-bar .phx-chip{min-height:44px;display:inline-flex;align-items:center;gap:6px}
	    .phx-subcat-bar .phx-chip .cnt{font-size:11px;font-weight:500}
	    .phx-subcat-scroll::after{display:none}
	    .phx-view-btn{min-width:40px;padding:0 8px;font-size:var(--btn-fs-mini)}
    /* Дизайн: Каталог/Товар/Корзина/Контакты 13.08, п.2 — mobile: 3 кнопки вида прячем, вместо
       них попап-кнопка «Вид». min-height на обёртке чипсов держит панель одной высоты и для
       категорий без подразделов (Мягкие игрушки/Фоамиран) — не прыгает при смене раздела.
       Fade у правого края — явный намёк, что список чипсов длиннее одного экрана. */
    .phx-view-switch{display:none}
    .phx-view-popup{display:block}
    .phx-subcat-scroll{min-height:44px}
    .phx-subcat-scroll::after{content:'';position:absolute;top:0;right:0;bottom:0;width:28px;background:linear-gradient(to right, transparent, var(--blue-pale));pointer-events:none}
	  }
	  @media(min-width:901px){
	    .phx-cat-list-toggle{display:none}
	    /* Каталог: Подразделы и Скролл 13.08 — sticky-сайдбар был не ограничен высотой вьюпорта и
	       без своего скролла: на 1440×900 нижние разделы (напр. «Фоамиран») оказывались ниже
	       видимой области и оставались недостижимы (top держит 88px при любом скролле страницы).
	       Ограничиваем сайдбар высотой вьюпорта, прокручиваемым делаем только список разделов —
	       ссылка «Все 13 разделов» и заголовок остаются на месте, скролл списка не ловит страницу. */
	    .phx-cat-sidebar{max-height:calc(100dvh - (var(--phx-sticky-offset) + 16px));display:flex;flex-direction:column;min-height:0}
	    .phx-cat-list{overflow-y:auto;overscroll-behavior:contain;scrollbar-gutter:stable;min-height:0}
	  }
	  @media(max-width:560px){
	    /* Задача 139 — на самых узких экранах подпись «Вариант: <название>» снимается: то же
	       название варианта уже стоит в <h1> страницы целиком («Пленка Корейская матовая
	       50см*10м, Розово-бежевый (01)»), а число вариантов читается с кнопки «Ещё N». Это не
	       косметика — 30px, которые она занимает вместе с отступом, решают, останется ли кнопка
	       «В корзину» в первом экране (критерий задачи 153): на 360×844 без этой правки кнопка
	       уезжала на 28px ниже границы экрана. Для скринридера подпись не теряется — у ряда есть
	       role="group" + aria-label, у каждого образца aria-label с названием и aria-pressed. */
	    .phx-pd-varhead{display:none}
	    .phx-pd-variants{margin-bottom:8px}
	    /* Попутно исправлена собственная регрессия сегодняшней сессии — при удалении «Крупной»
	       (п.3) сюда по ошибке попало её значение (1fr) вместо родного значения «Мелкой»
	       (repeat(2,1fr), подтверждено сравнением с _архив/backup-20260814-design-p2/
	       header.php.pre-deploy) — на ≤560px «Мелкая» рендерилась в 1 колонку вместо 2 весь день.
	       Дальше поверх уже верного repeat(2,1fr) — вдвое мельче по правке Алексея → repeat(4,1fr). */
	    .phx-cat-grid.phx-view-grid-compact{grid-template-columns:repeat(2,minmax(0,1fr))}
	    /* Задача 135, 20.08 — 3 колонки (~110px/карточка) были узкими: название переносилось в
	       3 строки, подпись размера наезжала на цену, третья карточка резалась краем экрана.
	       Решение Алексея — 2 колонки (~170px), 4 товара остаются (см. phxSimilarN в main.js),
	       просто в 2 ряда вместо 1-2. Только этот модификатор — обычная сетка каталога
	       (.phx-view-grid-compact без -similar, строка выше) не трогается. */
	    .phx-cat-grid.phx-view-grid-compact.phx-view-grid-similar{grid-template-columns:repeat(2,minmax(0,1fr))}
	    /* Обрезка переполнения — тоже только у «Похожих», не у обычного каталога (там колонок
	       больше и текст обычно и так помещается, задача явно просит не трогать общую сетку).
	       Название — 2 строки максимум, дальше многоточие; размер и вариант — 1 строка. */
	    .phx-view-grid-similar .phx-card-name{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
	    .phx-view-grid-similar .phx-card-var{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
	    .phx-view-grid-similar .phx-card-pack{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
	    /* Нижний ряд под круглой кнопкой чата (48px + 16px отступ) — тот же приём, что уже есть
	       у #phx-content{padding-bottom:88px} чуть ниже, но тот резерв стоит в конце ВСЕЙ
	       страницы (после блока «Похожих» на карточке товара есть ещё контент) и до этого блока
	       не дотягивался. Резерв нужен именно после блока «Похожих» — там и добавлен. */
	    #phxSimilarBlock{margin-bottom:88px}
	    /* Список на узком телефоне — 6 колонок desktop-списка (п.6) не помещаются по ширине:
	       упаковка/наличие/цена/корзина аккуратно переносятся под фото+название отдельными
	       строками во всю ширину вместо сжатия в одну тесную строку (ЗАДАНИЕ, mobile п.10). */
	    .phx-view-list .phx-card{grid-template-columns:64px 1fr;grid-template-areas:"ph name" "ph var" "ph pack" "avail avail" "price price" "ctl ctl";gap:2px 12px;padding:10px 12px}
	    .phx-view-list .phx-card-pack{margin-top:2px}
	    .phx-view-list .phx-card-ov{justify-self:start;margin-top:4px}
	    .phx-view-list .phx-card-prwrap{justify-self:stretch;margin-top:6px}
	    .phx-view-list .phx-card-ctl{justify-self:stretch;min-width:0;margin-top:6px}
	    .phx-view-list .phx-card-ctl .phx-addcart-btn{width:100%}
	    /* === Задача 166, 21.08 — перекрытие зон касания образцов на телефоне ===
	       Отчёт 160 честно зафиксировал: зона 44×44 через ::before есть, но при шаге между
	       центрами 22px (17px кружок + 5px gap) соседние зоны накладываются, и палец реально
	       выбирает из ~22px. Это не документируется, а лечится шагом: зона не может быть шире
	       расстояния между центрами, сколько ни пиши в ::before.
	       Шаг = 24px кружок + 17px зазор = 41px, зона 40×40 — на 1px меньше шага, значит зоны
	       соседей физически не пересекаются, и каждая ≥40px (требование задачи). Кружок заодно
	       вырос с 17 до 24px — на телефоне его и глазом видно лучше.
	       Ширина не страдает: 4 кружка + «+N» = 4×24+4×17+18 ≈ 182px при колонке 240px на 390.
	       ::before объявлен здесь БЕЗ @media(pointer:coarse) (в отличие от базового правила 160):
	       при шаге 41px наложения нет вообще, значит и точному указателю невидимая зона не мешает —
	       ровно та причина, по которой 160 пришлось прятать 44px за pointer:coarse, здесь снята.
	       Правило специфичнее базового (два класса против одного) — 44×44 не возвращается на
	       touch-устройстве. Плиточный вид и «Похожие товары» не затронуты: селектор через
	       .phx-view-list (задача прямо просит плитку не трогать). */
	    .phx-view-list .phx-card-swatches{gap:17px}
	    .phx-view-list .phx-swatch{width:24px;height:24px}
	    .phx-view-list .phx-swatch::before{content:"";position:absolute;top:50%;left:50%;width:40px;height:40px;transform:translate(-50%,-50%)}
	    /* Пилюли (размер/«прозрачный»/подпись без цвета) — та же цель касания в том же ряду, но
	       приём с невидимым ::before здесь НЕ работает и был бы враньём в замере: у .phx-swatch-pill
	       стоит overflow:hidden (базовое правило, ради многоточия в подписи), а overflow клиппит
	       собственные абсолютно спозиционированные потомки — расширенная зона обрезалась бы по
	       коробке самой пилюли и по клику, и по касанию. Поэтому пилюле даётся НАСТОЯЩИЙ размер:
	       12px + line-height 16px + 12px = ровно 40px по высоте, min-width 40px по ширине.
	       13px + line-height 14px + 13px = ровно 40px по высоте, min-width 40px по ширине.
	       Шрифт 10.5px (уже есть в шкале карточки — .phx-card-per/.phx-card-pack) вместо 9.5px:
	       в цели 40px совсем мелкая подпись читалась плохо. Чтобы более крупный шрифт не съел
	       подпись, потолок ширины поднят с базовых 52px до 64px — под 10.5px помещается примерно
	       столько же знаков, сколько раньше под 9.5px в 52px, то есть подпись не потеряна.
	       Ряд от этого не переполняется: он и раньше переносился (flex-wrap), а перенос при
	       row-gap 17px даёт вертикальный шаг 40+17=57px — зоны соседних строк тоже не касаются. */
	    .phx-view-list .phx-swatch-pill{font-size:10.5px;line-height:14px;padding:13px 6px;min-width:40px;max-width:64px}
	    .phx-view-list .phx-swatch-more{position:relative;min-width:24px;text-align:center}
	    .phx-view-list .phx-swatch-more::before{content:"";position:absolute;top:50%;left:50%;width:40px;height:40px;transform:translate(-50%,-50%)}
	    /* задача 060, п.1 16.08 — на телефоне «плитка» не нужна вообще (решение Алексея), только
	       список. Кнопка «Вид: Список» раньше висела абсолютом поверх панели фильтров и накрывала
	       чипы группы «Отделка» — правым краем уезжала за границу панели. Не прячем стилями сам
	       текст, а полностью снимаем оба узла (переключатель на ≥561px устроен иначе — там 3 кнопки
	       .phx-view-switch, их не трогаем): display:none — ноль в раскладке, offsetParent===null,
	       касания не перехватывает. JS ниже (getSavedView) тем же порогом принудительно держит
	       список, даже если в localStorage лежит «плитка» с более широкого экрана. */
	    .phx-view-switch{display:none}
	    .phx-view-popup{display:none}
	  }

	  footer.phx{background:var(--blue-d);color:var(--on-blue-3);padding:44px 0 26px;font-size:14px;margin-top:8px}
	  .fcols{display:grid;grid-template-columns:1.6fr 1fr 1fr 1.1fr 1.5fr;gap:26px;padding-bottom:26px;border-bottom:1px solid rgba(255,255,255,.12)}
	  /* MASTER QA/Refactor 13.08 — на страницах без другого h2 (напр. /price-list-catalog/) эти
	     заголовки шли сразу после h1, создавая пропуск уровня (axe: heading-order). Раньше это
	     не проявлялось на большинстве страниц — там до футера уже был свой h2 (главная, разделы
	     каталога), маскируя проблему. h3→h2 — на "Корзина" в дровере (тоже h3) не влияет, у неё
	     свой селектор ниже, ей landmark role="dialog" уже даёт отдельный контекст. */
	  footer.phx h2{font-family:var(--font-body);font-weight:700;color:var(--white);font-size:15px;margin-bottom:12px;line-height:1.55;letter-spacing:normal}
	  footer.phx a{display:block;color:var(--on-blue-3);margin:6px 0}
	  footer.phx a:hover{color:var(--white)}
	  /* === Задача 171, 21.08 — ссылки на соцсети (подвал и страница контактов) ===
	     Форма — из системы кнопок задачи 170: скругление и ступень шрифта только токенами,
	     зона касания не меньше --btn-h-touch. В подвале — монохром в цвете подвала
	     (--on-blue-3, рамка тем же currentColor), на контактах — роль «нейтральное»
	     (белый фон, обводка --line, текст графит). Наведение и фокус в обоих случаях —
	     пион --acc-btn, как просит задача.
	     Подпись внутри — словесная марка («VK», «MAX»), не фирменный SVG: настоящих
	     векторов брендов в проекте нет, а рисовать чужой логотип по памяти нельзя —
	     см. честный пробел в reports/171-social-links.md. Куда ведёт ссылка, скринридер
	     берёт из aria-label в разметке, а не из этих двух-трёх букв. */
	  .phx-social{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:12px}
	  .phx-social-link{display:inline-flex;align-items:center;justify-content:center;min-width:var(--btn-h-touch);min-height:var(--btn-h-touch);padding:0 12px;border:1px solid var(--line);border-radius:var(--btn-radius);background:var(--white);color:var(--ink);font-family:var(--font-body);font-weight:700;font-size:var(--btn-fs-work);letter-spacing:.06em;text-decoration:none}
	  .phx-social-link:hover,.phx-social-link:focus-visible{color:var(--acc-btn);border-color:var(--acc-btn);text-decoration:none}
	  /* составная специфичность — .phx-contact-card a{color:var(--acc-text)} на самой странице
	     контактов иначе перебивает цвет одиночного класса выше */
	  .phx-contact-card a.phx-social-link{color:var(--ink);text-decoration:none}
	  .phx-contact-card a.phx-social-link:hover,.phx-contact-card a.phx-social-link:focus-visible{color:var(--acc-btn);border-color:var(--acc-btn);text-decoration:none}
	  /* подвал: footer.phx a{display:block;color:...;margin:6px 0} выше — перебиваем всё три */
	  footer.phx a.phx-social-link{display:inline-flex;margin:0;background:transparent;color:var(--on-blue-3);border-color:currentColor}
	  footer.phx a.phx-social-link:hover,footer.phx a.phx-social-link:focus-visible{color:var(--acc-btn);border-color:var(--acc-btn)}
	  .copy{padding-top:18px;font-size:12.5px;color:var(--on-blue-4)}

	  .chat-fab{position:fixed;right:22px;bottom:22px;z-index:60;background:var(--blue);color:var(--white);border-radius:var(--btn-radius);padding:13px 20px;font-weight:600;font-size:var(--btn-fs-main);box-shadow:0 8px 26px rgba(46,90,136,.36);cursor:pointer;display:flex;align-items:center;gap:9px}
	  .chat-fab:hover{background:var(--blue-d)}
	  /* P1 Repair 13.08: на Главной постоянно плавающий чип перекрывал цену/остаток/CTA/футер
	     (независимый аудит) — на homepage вход в чат остаётся только через inline-CTA
	     «Спросить ассистента»; на остальных страницах чип живёт как раньше. */
	  .phx-home .chat-fab{display:none}
	  /* Дизайн: Каталог/Товар/Корзина/Контакты 13.08, п.1 — компактный кружок вместо полной
	     плашки на коммерческих страницах (не перекрывает цену/В корзину/Скачать Excel), чип не
	     убран — доступ к ассистенту остаётся. safe-отступ снизу у контента — на случай, если
	     что-то всё равно долистает до нижнего правого угла. */
	  .phx-compact-chip .chat-fab{width:48px;height:48px;padding:0;justify-content:center;border-radius:var(--btn-radius);font-size:var(--btn-ico)}
	  .phx-compact-chip .chat-fab .lbl{display:none}
	  .phx-compact-chip #phx-content{padding-bottom:88px}
	  .chat-panel{position:fixed;right:22px;bottom:82px;z-index:60;width:340px;max-width:calc(100vw - 44px);background:var(--white);border-radius:16px;box-shadow:0 18px 50px rgba(31,39,51,.28);overflow:hidden;display:none;flex-direction:column}
	  .chat-panel.open{display:flex}
	  /* на Главной чипа нет — открытую панель сажаем к нижнему краю, место чипа не резервируем */
	  .phx-home .chat-panel{bottom:22px}
	  .cp-h{background:var(--blue);color:var(--white);padding:14px 16px;display:flex;align-items:flex-start;justify-content:space-between;gap:10px}
	  .cp-h b{font-size:15px}
	  .cp-h span{display:block;font-size:12px;color:var(--on-blue-2)}
	  .cp-close{background:none;border:none;color:var(--white);font-size:var(--btn-ico);line-height:1;cursor:pointer;width:44px;height:var(--btn-h-touch);margin:-10px -12px -10px 0;flex-shrink:0;display:flex;align-items:center;justify-content:center;border-radius:var(--btn-radius)}
	  .cp-close:hover,.cp-close:focus-visible{background:hsl(0 0% 100% / .16)}
	  .cp-b{padding:14px;background:var(--bg);max-height:320px;overflow-y:auto}
	  .cp-b .b{background:var(--white);border:1px solid var(--line);border-radius:12px;padding:10px 12px;font-size:13.5px;margin-bottom:8px}
	  .cp-actions{display:flex;gap:8px;padding:12px;border-top:1px solid var(--line);background:var(--white)}
	  .phx-chat-form{padding:0 12px 12px}
	  .phx-chat-form input{width:100%;padding:10px 11px;border:1px solid var(--line);border-radius:8px;margin-bottom:8px;font-size:16px;box-sizing:border-box}
	  /* задача 062, п.2/3 — поля Bitrix-формы обратной связи (webFormDw, /callback/) были 14.4px
	     по стандартной вёрстке компонента; тот же автозум. Настройки формы в админке не трогаем
	     (правило задачи form.result.new), это чисто внешний CSS-оверрайд размера шрифта. */
	  .webFormDw input[type="text"],.webFormDw input[type="email"],.webFormDw input[type="tel"],.webFormDw textarea{font-size:16px}
	  .phx-chat-form button{width:100%}
	  .cp-actions .btn{flex:1;padding:9px;font-size:13px;text-align:center}

	  @media(max-width:900px){
	    .top{display:none}
	    .phx-burger{display:flex}
	    .fcols{grid-template-columns:1fr 1fr}
	  }
	  @media(min-width:901px) and (max-width:1130px){
	    /* UX Overhaul 13.08, Batch C — на ~1024px (tablet) .hd — flex-row без wrap — не хватало
	       места для logo+nav+.phone+search+account+cart+CTA на одной строке, и блок «Отдел опта
	       +7 (8482) 63-53-54» переносился в 4 строки (обнаружено скриншотом category-tablet-1024).
	       Тот же номер уже виден в чёрной .top-плашке над шапкой на этой ширине (.top скрывается
	       только на ≤900px) — скрываем дублирующий .hd .phone только в этом промежутке. */
	    .hd .phone{display:none}
	  }
	  /* B33 15.08 (tasks/057-home-desktop-v2.md, п.1) — вариант V2: основная строка шапки на
	     ≥901px целиком перестроена под мокап. «Отдел опта +7...» в .hd убран полностью (не
	     только в диапазоне 901–1130, как раньше) — номер уже есть в верхней тонкой полосе
	     (.top), а освободившееся место в строке нужно раскрытому полю поиска. Выше 901px — весь
	     новый блок: кнопка «Каталог», поле поиска, второй ряд ссылок под шапкой, иконки кабинета/
	     корзины без подписи. Всё внутри одного @media — ничего из этого не должно просочиться
	     в мобильную раскладку 052 (там свой, отдельный набор правил на ≤560px). */
	  @media(min-width:901px){
	    .hd{height:92px;gap:20px}
	    .hd .phone{display:none}
	    /* Просьба Алексея 21.08 — «Каталог» вернулся в эту строку, слева от поиска (см.
	       HTML — .phx-megamenu-wrap физически стоит здесь же, между .logo и
	       .phx-search-desktop). Особый margin-right:160px задачи 093 держал зазор
	       «логотип → 180px → поиск» под мокап B4, когда между ними не стояло ничего —
	       сейчас в этом промежутке пилюля «Каталог», прежнее число смысла не имеет,
	       обычного .hd{gap:20px} достаточно (тот же зазор, что у всех остальных соседних
	       элементов строки). */
	    .phx-search-toggle{display:none}
	    /* Задача 095 — быстрая иконка каталога только для <901px, здесь на десктопе каталог уже
	       пилюлей в строке меню (.phx-subnav ниже). */
	    .phx-catalog-quick{display:none}
	    .phx-search-desktop{display:flex;max-width:660px}
	    .phx-city-badge{display:inline-flex;align-items:center;gap:9px;height:52px;padding:0 18px;border:1px solid var(--line);border-radius:12px;background:var(--white);color:var(--ink);font:600 15px/1 var(--font-body);white-space:nowrap;flex:none;margin-left:auto;cursor:default}
	    .phx-city-badge .phx-city-pin{color:var(--acc-btn);font-size:16px}
	    .phx-city-badge .phx-city-arw{color:var(--muted);font-size:12px;margin-left:2px}
	    .phx-account-btn{width:52px;height:52px;padding:0;justify-content:center}
	    .phx-account-btn .lbl{display:none}
	    .phx-cart-btn{width:52px;height:52px}
	    /* задача 064 16.08 — было 13.5px/обычное начертание/приглушённый цвет на строке высотой
	       44px: Алексей — «мелкая, теряется под шапкой». Шрифт и начертание подняты, высота строки
	       выросла вместе с ними (44→52px), активный пункт теперь отличается и цветом (--ink тёмный
	       нейтральный у обычных против --blue-l розового у активного — разные оттенки, не один и
	       тот же чуть светлее/темнее), и подчёркиванием, не только начертанием — начертание теперь
	       у всех пунктов одинаково жирное.
	       Задача 085 16.08 — Алексей: строка меню всё ещё «мелкая», сделать заметно крупнее (высота
	       ≥64px, шрифт на ступень больше нынешнего 16px) и перенести сюда кнопку «Оставить заявку»
	       из основной строки шапки — margin-left:auto на самой кнопке прижимает её к правому краю
	       строки, остальные пункты остаются слева как были.
	       Задача 093 17.08 — мокап B4: высота строки 68→84px, пункты 18px/700 → 20px/500/разрядка
	       0.8px, промежуток 32→44px, первым элементом пилюля «Каталог» (перенесена сюда из .hd
	       выше), подчёркивание активного пункта — не text-decoration, а полоса 3px на всю высоту
	       строки снизу (мокап), нужен position:relative на самой ссылке под ::after. Кнопка
	       «Оставить заявку» и телефон справа собраны в свою обёртку .phx-subnav-right (margin-left:
	       auto один раз на обёртке, а не на каждой кнопке по отдельности). */
	    .phx-subnav{display:block;border-bottom:1px solid var(--line);background:var(--white)}
	    .phx-subnav .wrap{display:flex;gap:44px;height:84px;align-items:center;font-size:20px;font-weight:500;letter-spacing:.8px;color:var(--ink)}
	    .phx-subnav a{display:inline-flex;align-items:center;height:100%;position:relative}
	    .phx-subnav a:hover{color:var(--blue-l)}
	    .phx-subnav a.active{color:var(--acc-text);font-weight:600}
	    .phx-subnav a.active::after{content:'';position:absolute;left:0;right:0;bottom:0;height:3px;background:var(--acc)}
	    /* Просьба Алексея 21.08 — пилюля «Каталог» переехала из .phx-subnav в .hd (слева от
	       поиска, разметка — header.php). Прежде здесь была составная специфичность
	       .phx-subnav .phx-cat-btn (два класса), чтобы перебить соседнее правило .phx-subnav
	       a{height:100%} — теперь пилюля вне .phx-subnav, тот конфликт специфичности больше
	       не возникает, обычного одиночного класса достаточно. .phx-megamenu-wrap{margin-
	       right:0} работает независимо от того, где стоит блок, оставлен как есть. */
	    .phx-megamenu-wrap{position:relative;display:flex;align-items:center;margin-right:0}
	    /* Просьба Алексея 21.08 (кадры с ноутбука) — высота пилюли не совпадала с
	       остальными элементами этой строки: поле поиска, «Войти», корзина — все 52px
	       (см. .phx-search-desktop/.phx-account-btn/.phx-cart-btn выше), у пилюли
	       оставался старый 48px из мокапа строки меню, где она раньше стояла рядом с
	       более высокими CTA/телефон (56px), не с этими элементами. 48→52 — теперь
	       совпадает с прямыми соседями по этой же строке. */
	    .phx-cat-btn{display:inline-flex;align-items:center;gap:10px;background:var(--acc-btn);color:var(--white);border:none;border-radius:var(--btn-radius);padding:0 24px;height:52px;font-weight:600;font-size:var(--btn-fs-main);letter-spacing:.4px;flex-shrink:0;white-space:nowrap}
	    .phx-cat-btn:hover,.phx-cat-btn:focus-visible{background:var(--acc-btn-h);color:var(--white)}
	    .phx-subnav-right{margin-left:auto;display:flex;align-items:center;gap:14px}
	    /* .phx-subnav a{height:100%} иначе перебивает фиксированную высоту пилюль CTA/
	       телефона ниже (составная специфичность .phx-subnav .phx-subnav-cta/-tel, два
	       класса) — эти две пилюли, в отличие от «Каталог» выше, остались внутри
	       .phx-subnav, приём для них ещё нужен. */
	    .phx-subnav .phx-subnav-cta{margin-left:0;min-height:0;height:56px;padding:0 30px;border-radius:var(--btn-radius);display:inline-flex;align-items:center;justify-content:center;font-size:var(--btn-fs-main);font-weight:600;background:var(--acc-btn);color:var(--white)}
	    .phx-subnav .phx-subnav-cta:hover{background:var(--acc-btn-h);color:var(--white)}
	    .phx-subnav .phx-subnav-tel{display:inline-flex;align-items:center;gap:10px;height:56px;padding:0 28px;border-radius:var(--btn-radius);background:var(--phx-hd-graphite);color:var(--white);font-size:var(--btn-fs-main);font-weight:600;white-space:nowrap}
	    .phx-subnav .phx-subnav-tel:hover{filter:brightness(1.15);color:var(--white)}
	  }
	  /* Задача 159, 21.08 — дыра 901–1099px: живой замер архитектора на 928px дал scrollWidth 1095
	     против innerWidth 928 — .phx-subnav (5 пунктов меню + CTA + телефон, рассчитан на 1680px,
	     поджат только для >=901px до 1400px, но не ниже) и .hd (бейдж города 239px нерастяжимый +
	     широкое поле поиска) в сумме требуют больше 1100px, а десктопный набор включается уже с
	     901px — отсюда дыра, в которую попадают ноутбуки 1024 и планшеты в альбомной ориентации.
	     Дожимать десктопный набор ещё туже (пятый раз в этом файле поджимать одни и те же пилюли)
	     решил не читаемым — вместо этого чиню тем способом, что сама задача разрешает явным
	     текстом: поднимаю порог переключения на мобильный набор элементов шапки (бургер + иконка
	     каталога + иконка поиска — тот же набор, что уже работает на <=900px) до 1099px включи-
	     тельно. Всё, что этим скрывается из первой строки и полностью убирается строкой меню
	     (бейдж города, широкое поле поиска, весь .phx-subnav с 5 пунктами/CTA/телефоном) — без
	     изменений уже есть в бургер-меню #phxMobnav (город, «Войти», все 5 пунктов, «Оставить
	     заявку», оба телефона, см. header.php) — состав бургер-меню не менялся ни на строку,
	     только его видимость расширена. Корзина и «Войти» — единственные две кнопки, которые
	     задача прямо требует оставить в шапке видимыми и кликабельными на всём диапазоне — не
	     трогаю их вообще, только .hd .logo{margin-right} и .hd{gap} возвращаю к мобильным
	     числам, иначе после исчезновения бейджа/поиска между логотипом и кнопками остался бы
	     неестественно большой зазор в 160px. */
	  @media(min-width:901px) and (max-width:1099px){
	    .phx-burger{display:flex}
	    .phx-catalog-quick{display:flex}
	    .phx-search-toggle{display:flex}
	    .phx-search-desktop{display:none}
	    .phx-city-badge{display:none}
	    .hd{height:72px;gap:16px}
	    .hd .logo{margin-right:0}
	    .hd .phone{display:none}
	    .phx-account-btn{width:auto;height:var(--btn-h-touch);padding:0 14px}
	    .phx-account-btn .lbl{display:inline}
	    .phx-cart-btn{width:44px;height:var(--btn-h-touch)}
	    .phx-subnav{display:none}
	    /* Просьба Алексея 21.08 — пилюля «Каталог» переехала из .phx-subnav в .hd. Раньше
	       её прятало вот это самое правило (.phx-subnav{display:none} выше) — она
	       физически жила внутри спрятанной строки меню. Теперь она в .hd, которая в этом
	       узком диапазоне переключена на мобильный набор (бургер+иконка каталога вместо
	       полной пилюли+поиска) — без явного скрытия пилюля осталась бы видна поверх
	       мобильного набора и снова открыла бы ту же дыру, что чинила 159 (живой замер
	       поймал переполнение scrollWidth 1007 против 928 innerWidth на 928px). */
	    .phx-megamenu-wrap{display:none}
	  }
	  /* Задача 093, критерий 11 — мокап B4 рассчитан на 1680px (44px промежуток, полные паддинги
	     пилюль). На живом промере 1280px пять пунктов + пилюля + CTA + телефон перестают помещаться
	     — 1303px нужно против 1265px доступных (getBoundingClientRect, живой замер). 1920/1440 —
	     без переполнения (проверено тем же способом), поджимать нужно только этот промежуток.
	     Только тут — не 901px, чтобы не откатить проверенные точные числа задачи на 1440+. */
	  @media(min-width:901px) and (max-width:1400px){
	    .phx-subnav .wrap{gap:20px}
	    .phx-subnav-right{gap:8px}
	    .phx-subnav .phx-subnav-cta{padding:0 20px}
	    .phx-subnav .phx-subnav-tel{padding:0 16px}
	    .phx-cat-btn{padding:0 18px}
	  }
	  @media(max-width:560px){
	    .hd .phone{display:none}
	    /* MASTER QA/Refactor 13.08 — шапка (.hd, flex-row без wrap) на узких мобильных реально
	       переполнялась по горизонтали (подтверждено Playwright: scrollWidth 571px при
	       viewport 390px — вся страница скроллилась вбок). Кнопка "Оставить заявку" дублирует
	       такой же пункт в мобильном меню (бургер) — на компактной шапке не нужна, там и так
	       мало места; корзина/поиск/вход — нет. */
	    .hd > .btn.btn-cta{display:none}
	    /* Задача 117, 19.08 — решение Алексея: пятая кнопка (иконка каталога, задача 095) в одну
	       строку с логотипом не помещалась, корзина уходила за правый край экрана (повтор бага 026
	       с ещё одной кнопкой в той же строке). Вместо того чтобы снова ужимать промежутки —
	       освобождаем строку: поле поиска второй строкой (было с 052) убрано, на его место встаёт
	       ряд из пяти кнопок. .hd переходит на flex-wrap, у логотипа flex-basis:100% — он один
	       занимает всю первую строку, все элементы с order выше переносятся на вторую независимо
	       от того, сколько их — кнопка, которая раньше требовала подбирать новый порог, теперь
	       просто перетекает на свою строку сама. DOM-порядок узлов не менял (бургер в разметке
	       идёт раньше лого — на десктопе не видно, там display:none), только визуальный порядок
	       через order — тот же приём, что и в 059/095, только с явным переносом строки. */
	    /* Задача 133 (продолжение), 20.08 — отдельная жалоба от прошлой (там был зазор ПОСЛЕ
	       шапки, до контента). Здесь — зазор ВНУТРИ шапки: на ≤560px .wrap.hd переходит на
	       flex-wrap (117) и height:auto — высота шапки строго равна высоте контента, вторая
	       строка кнопок утыкается прямо в border-bottom (замер живьём: 1px, по сути 0).
	       padding-bottom даёт кнопкам дышать от собственной нижней границы шапки. 16px — тот
	       же порядок, что и внешний зазор ниже шапки (см. #phx-main выше), 8pt-сетка.
	       --phx-sticky-offset (88px, используется .phx-cat-sidebar/.phx-subcat-sticky) не
	       пересчитывал: оба у ≤900px переходят в position:static (строки выше в этом файле) —
	       высота шапки на этой ширине для sticky-позиционирования уже не используется. */
	    .wrap.hd{flex-wrap:wrap;height:auto;gap:10px;row-gap:10px;justify-content:space-between;padding-bottom:16px}
	    .logo{order:1;flex:1 1 100%}
	    .phx-burger{order:2}
	    .phx-catalog-quick{order:3}
	    .phx-search-toggle{order:4}
	    .phx-account-btn{order:5;margin-left:0}
	    .phx-cart-btn{order:6}
	    /* Задача 117, п.4 — было четыре разных вида (бургер/поиск без фона и рамки, каталог залит
	       пионом, кабинет — белая пилюля с подписью, корзина — белый квадрат без явного color, из-за
	       чего браузер подставлял системный синий иконке — честная находка задачи, п.5). Сводим все
	       пять к одному виду мокапа: белый фон, рамка var(--line), скругление 9px, иконка графитом
	       var(--ink) — через currentColor у SVG (везде уже stroke="currentColor").
	       Бейдж-счётчик на корзине (.phx-cart-count, задача 026) не задет — правило ниже не трогает
	       его позиционирование/цвет, только контейнер-кнопку. */
	    .phx-burger,.phx-catalog-quick,.phx-search-toggle,.phx-account-btn,.phx-cart-btn{
	      height:44px;padding:0;justify-content:center;flex-shrink:0;
	      background:var(--white);border:1px solid var(--line);border-radius:var(--btn-radius);color:var(--ink)
	    }
	    .phx-burger,.phx-account-btn,.phx-cart-btn{width:44px}
	    /* Живая жалоба Алексея 19.08 (после этого же дня деплоя) — пять одинаковых квадратов с
	       пустыми промежутками «выглядят криво», предложил заполнить строку. Каталог и поиск — два
	       самых частых действия с телефона — получают подпись и растягиваются (flex:1) на
	       освободившееся место; бургер/кабинет/корзина остаются точными квадратами-иконками — их
	       смысл и так однозначен по одной иконке, подпись не добавляет пользы. */
	    .phx-catalog-quick,.phx-search-toggle{flex:1;gap:6px;padding:0 12px;font-size:var(--btn-fs-work);font-weight:600;white-space:nowrap}
	    .phx-catalog-quick .lbl,.phx-search-toggle .lbl{display:inline}
	    .phx-account-btn .lbl{display:none}
	    /* Задача 117 отменяет решение 052 (search-panel второй строкой шапки) — поиск возвращается
	       к исходному замыслу: лупа в ряду кнопок выше, по нажатию выезжает фиксированная панель
	       (базовые правила .phx-search-panel/.phx-search-toggle/.phx-search-close/.phx-search-results
	       выше по файлу, вне медиазапросов — тот же вид, что уже работает на планшете/десктопе
	       >560px). Разметку/JS не трогал — тот же #phxSearchPanel, тот же обработчик открытия и
	       закрытия панели (скрипт сразу после закрывающего тега nav), меняется только то, что на
	       ≤560px эти правила больше не переопределяются: без override здесь действуют базовые. */
	    /* Задача 052, п.3 (было 012) — на мобильном чип «Ассистент» становится тем же компактным
	       кружком, что уже есть на /catalog/ и /price-list-catalog/ (.phx-compact-chip, P1 Repair
	       13.08) — но теперь везде, где .chat-fab вообще показан (кроме Главной — там его нет,
	       см. .phx-home .chat-fab выше), а не только на двух конкретных разделах. Причина —
	       живой промер на /contacts/ (аудит 15.08): полная плашка «💬 Ассистент» (154×51px)
	       на 390px реально перекрывала .phx-contact-card (карточка адреса/почты) — 154px
	       ширины на узком экране слишком много. env(safe-area-inset-bottom) — уже используется
	       в проекте нигде раньше не было, но это ровно тот случай (плавающий fixed-элемент у
	       нижнего края) на который эта safe-area и рассчитана — на телефонах с жестовой
	       панелью снизу (iPhone) не даёт чипу оказаться под системной полосой. */
	    .chat-fab{width:48px;height:48px;padding:0;justify-content:center;border-radius:var(--btn-radius);font-size:var(--btn-ico);bottom:calc(16px + env(safe-area-inset-bottom));right:16px}
	    .chat-fab .lbl{display:none}
	    .chat-panel{right:16px;bottom:calc(76px + env(safe-area-inset-bottom));max-width:calc(100vw - 32px)}
	    #phx-content{padding-bottom:88px}
	    /* Задача 170 — общий пол высоты для всех .btn на телефоне (был только у «В корзину»:
	       «Оформить заказ» жила 41px, ниже порога зоны касания). */
	    .btn{min-height:var(--btn-h-touch)}
	    .phx-addcart-btn{min-height:var(--btn-h-touch)}
	    .phx-card-stepper button{width:var(--btn-h-touch);height:var(--btn-h-touch)}
	    .phx-cat-item{min-height:52px;padding:6px 8px}
	    .phx-chip{min-height:var(--btn-h-touch);padding:0 14px}
	    .phx-price-input{min-height:var(--btn-h-touch)}
	    .phx-cart-qty button{width:var(--btn-h-touch);height:var(--btn-h-touch)}
	    .phx-cart-item-remove{min-width:var(--btn-h-touch);min-height:var(--btn-h-touch)}
	    .phx-carousel-dot{width:12px;height:12px}
	    .fcols{grid-template-columns:1fr}
	  }
	  @media(max-width:430px){
	    /* На самых узких экранах подписи кнопки входа не хватает места рядом с поиском и
	       корзиной — оставляем только иконку (aria-label остаётся для доступности). На
	       десктопе и планшете (>560px) подпись видна всегда — прямое требование Алексея.
	       Порог поднят с 380 до 430px (MASTER QA/Refactor 13.08) — на 390px (частый реальный
	       viewport, Pixel/iPhone) шапка всё ещё переполнялась по горизонтали даже без подписи
	       кнопки входа, пока не сжали заодно gap — см. .hd{gap:12px} ниже, подтверждено
	       Playwright на 375px и 390px: scrollWidth === clientWidth после обеих правок. */
	    .phx-account-btn{padding:0;width:44px;justify-content:center}
	    .phx-account-btn .lbl{display:none}
	    .hd{gap:12px}
	  }
	  @media(max-width:430px){
	    /* P1 Repair 13.08 — на 360px шапка реально переполнялась (scrollWidth 352 vs clientWidth
	       345, корзина обрезана справа — независимый аудит). Только шапка, только сжатие
	       промежутков и визуальной высоты логотипа; burger/поиск/вход/корзина остаются 44×44.
	       Никакого overflow-x:hidden — контент должен сам помещаться в clientWidth.
	       Логотип — inline style="height:46px" в разметке, поэтому здесь !important.
	       B26 15.08 (tasks/026-mobile-overflow.md) — порог поднят с 374 до 430px. Прямым
	       промером (getBoundingClientRect всех детей .hd) подтверждено: на 390px — самом
	       частом реальном viewport телефона (iPhone 12/13/14 и большинство Android) — этот
	       порог просто не срабатывал, логотип оставался на полной высоте (46px/164px), и
	       .hd (flex, nowrap, все соседи кроме логотипа — flex-shrink:0) не помещал корзину:
	       кнопка рендерилась с right:408 при viewport 371 — не обрезана, а физически за
	       кадром, отсюда и «кнопки корзины на экране нет» с телефона Алексея. Ровно тот же
	       мехнизм чинит и 390, и 360 одним порогом — проверено на обеих ширинах живым Chrome.
	       Честная поправка к собственной первой гипотезе задачи: панель корзины
	       (.phx-cart-drawer, position:fixed) проверена отдельно (принудительно открыта и
	       закрыта с чистого состояния) — на document.documentElement.scrollWidth не влияет
	       вообще, ни в одном состоянии. Единственная причина — эта самая шапка. */
	    /* padding:0 10px 16px — не 0 10px: shorthand на 3 значения (top|right-left|bottom),
	       иначе эта строка (тот же .wrap.hd, идёт позже в файле — побеждает) стирала бы до 0
	       padding-bottom:16px из задачи 133 на 360/390/430px — как раз тех самых ширинах,
	       где сайт обычно проверяется. */
	    .wrap.hd{gap:6px;padding:0 10px 16px}
	    .logo img{height:36px !important}
	  }

	  /* category tiles — Главная и /catalog/. Задачи 070/083 (мозаика на Главной, класс .phx-tile
	     с шахматкой/фиксированной высотой/подписью под фото) отменены правкой Алексея 16.08
	     («не нравится, верни старые плитки») — блок удалён целиком, обе страницы используют
	     .phx-ctile* ниже, как и было до 070. */

	  /* /catalog/ и Главная — плитки разделов, состояние до 070 (задача 084, 16.08; на Главную
	     вернул той же правкой 16.08, что отменила 070/083). Дословно прежняя логика (панель подкатегорий по наведению/фокусу, 12-колоночная
	     сетка), просто под именем .phx-ctile* вместо .phx-tile* — Главная (выше) и /catalog/
	     (ниже) больше не делят ни одного класса, у каждой страницы теперь свой набор правил. */
	  .phx-ctile-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:clamp(.6rem,.4rem + .6vw,1rem)}
	  .phx-ctile{position:relative;overflow:hidden;min-height:210px;border-radius:14px;display:flex;flex-direction:column;justify-content:flex-end;padding:var(--sp-s);border:1px solid var(--line);isolation:isolate;transition:.3s;background:var(--t3);color:inherit;cursor:pointer}
	  .phx-ctile-inner{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:flex-end;padding:var(--sp-s);color:inherit;cursor:pointer;z-index:0}
	  .phx-ctile-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;transition:transform .3s ease,filter .3s ease}
	  .phx-ctile:not(:has(.phx-ctile-inner))::before,.phx-ctile-inner::before{content:'';position:absolute;inset:0;background:linear-gradient(to top,rgba(20,16,14,.75) 0%,rgba(20,16,14,.32) 48%,rgba(20,16,14,.06) 72%);z-index:1}
	  @media(hover:hover){.phx-ctile:hover{transform:translateY(-8px);box-shadow:0 22px 40px hsl(210 6% 13% / .18)}}
	  @media(prefers-reduced-motion:reduce){.phx-ctile{transition:none}}
	  @media(hover:hover){.phx-ctile:hover .phx-ctile-img{transform:scale(1.05)}}
	  .phx-ctile:focus-within .phx-ctile-img{transform:scale(1.05)}
	  @media(hover:hover){.phx-ctile:hover .phx-ctile-inner:has(~ .phx-ctile-subpanel) .phx-ctile-img{filter:blur(2px) brightness(.97) saturate(1.05)}}
	  .phx-ctile:focus-within .phx-ctile-inner:has(~ .phx-ctile-subpanel) .phx-ctile-img{filter:blur(2px) brightness(.97) saturate(1.05)}
	  /* Задача 087 (16.08) — заголовок плитки был белым только под h2: на /catalog/ заголовок и есть
     h2, всё видно; на Главной та же плитка правильно получила h3 (единственный h1 на странице,
     секция — h2 «Категории товаров», плитка внутри неё — h3, иерархия верная), а правило цвета
     за уровнем не пошло — заголовок остался тёмным (--ink) поверх тёмного фото. :is(h2..h6) ловит
     заголовок плитки на любом уровне разом, не завязано на то, какой уровень выберет разметка
     конкретной страницы, и не сломается, если уровень поменяется ещё раз. */
  .phx-ctile :is(h2,h3,h4,h5,h6),.phx-ctile .phx-ctile-cnt,.phx-ctile .phx-ctile-go{position:relative;z-index:2}
	  .phx-ctile :is(h2,h3,h4,h5,h6){font-size:var(--step-1);font-weight:600;color:var(--white);margin:0}
	  .phx-ctile-cnt{font-size:var(--step--1);color:hsl(0 0% 100% / .82)}
	  .phx-ctile-go{font-size:var(--step--1);letter-spacing:.14em;text-transform:uppercase;margin-top:.4rem;font-weight:700;color:var(--acc-soft)}
	  @media(hover:hover){.phx-ctile-go{opacity:0;transform:translateY(8px);transition:.3s}.phx-ctile:hover .phx-ctile-go{opacity:1;transform:none}}
	  .phx-ctile.big{grid-column:span 6;min-height:330px}
	  .phx-ctile.half{grid-column:span 6}
	  .phx-ctile.third{grid-column:span 4}
	  /* Плашка «Все разделы каталога» — только Главная, /catalog/ её не рендерит (там уже сам
	     каталог). Возвращена той же правкой 16.08, что отменила 070/083. */
	  .phx-ctile.phx-cta-tile{background:var(--prim);border-color:var(--prim);justify-content:center;align-items:flex-start}
	  .phx-ctile.phx-cta-tile h3{color:var(--bg);font-size:var(--step-1)}
	  .phx-ctile.phx-cta-tile .phx-ctile-go2{color:var(--acc-soft);font-size:var(--step--1);letter-spacing:.14em;text-transform:uppercase;font-weight:700;margin-top:.6rem}
	  @media(hover:hover){.phx-ctile.phx-cta-tile:hover{background:var(--ink)}}
	  .phx-ctile-subpanel{position:absolute;inset:0;z-index:3;background:hsl(336 44% 93% / .3);padding:var(--sp-s);display:flex;flex-direction:column;opacity:0;pointer-events:none;transition:opacity .2s ease}
	  @media(hover:hover){.phx-ctile:hover .phx-ctile-subpanel,.phx-ctile:focus-within .phx-ctile-subpanel{opacity:1}}
	  @media(hover:hover){.phx-ctile:hover .phx-ctile-inner:has(~ .phx-ctile-subpanel) :is(h2,h3,h4,h5,h6),.phx-ctile:hover .phx-ctile-inner:has(~ .phx-ctile-subpanel) .phx-ctile-cnt,.phx-ctile:hover .phx-ctile-inner:has(~ .phx-ctile-subpanel) .phx-ctile-go{opacity:0}}
	  .phx-ctile:focus-within .phx-ctile-inner:has(~ .phx-ctile-subpanel) :is(h2,h3,h4,h5,h6),.phx-ctile:focus-within .phx-ctile-inner:has(~ .phx-ctile-subpanel) .phx-ctile-cnt,.phx-ctile:focus-within .phx-ctile-inner:has(~ .phx-ctile-subpanel) .phx-ctile-go{opacity:0}
	  .phx-ctile-subhead{display:flex;align-items:center;justify-content:space-between;gap:8px;color:var(--blue-l);text-shadow:0 1px 6px hsl(336 44% 93% / .9),0 1px 2px hsl(336 44% 93% / .9);font-family:var(--font-display);font-size:var(--step-0);font-weight:600;padding-bottom:8px;margin-bottom:8px;border-bottom:1px solid var(--blue-pale-d);flex:none;opacity:0;transform:translateY(-4px);transition:opacity .2s ease,transform .2s ease}
	  .phx-ctile-subarrow{color:var(--acc-btn)}
	  .phx-ctile-sub-viewall{display:inline-flex;align-items:center;justify-content:center;text-align:center;align-self:flex-start;flex:none;background:var(--white);border:1px solid var(--acc-btn);border-radius:var(--btn-radius);color:var(--acc-text);font-size:var(--btn-fs-work);font-weight:600;line-height:1.2;padding:5px 10px;min-height:30px;opacity:0;transform:translateY(6px);transition:opacity .22s ease .05s,transform .22s ease .05s,background .15s,border-color .15s}
	  .phx-ctile-sublist ~ .phx-ctile-sub-viewall{margin-top:6px}
	  .phx-ctile-sub-viewall:hover,.phx-ctile-sub-viewall:focus-visible{color:var(--acc-text);background:var(--cta-bg);border-color:var(--acc-btn-h)}
	  @media(hover:hover){
	    .phx-ctile:hover .phx-ctile-sub-viewall,.phx-ctile:focus-within .phx-ctile-sub-viewall{opacity:1;transform:translateY(0);pointer-events:auto}
	    .phx-ctile:hover .phx-ctile-subhead,.phx-ctile:focus-within .phx-ctile-subhead{opacity:1;transform:translateY(0);pointer-events:auto}
	  }
	  .phx-ctile-sublist{display:flex;flex-direction:column;gap:1px;overflow-y:auto;min-height:0;scrollbar-width:thin;scrollbar-color:hsl(340 42% 40% / .3) transparent}
	  .phx-ctile-sublist::-webkit-scrollbar{width:6px}
	  .phx-ctile-sublist::-webkit-scrollbar-track{background:transparent}
	  .phx-ctile-sublist::-webkit-scrollbar-thumb{background:hsl(340 42% 40% / .3);border-radius:20px}
	  .phx-ctile-sublink{color:var(--ink);text-shadow:0 1px 5px hsl(336 44% 93% / .9);font-size:var(--btn-fs-work);padding:5px 4px;border-radius:var(--btn-radius);min-height:28px;display:flex;align-items:center;opacity:0;transform:translateY(6px);transition:opacity .22s ease,transform .22s ease}
	  .phx-ctile-sublink:hover,.phx-ctile-sublink:focus-visible{color:var(--blue-l);background:var(--blue-pale-d)}
	  @media(hover:hover){
	    .phx-ctile:hover .phx-ctile-sublink,.phx-ctile:focus-within .phx-ctile-sublink{opacity:1;transform:translateY(0);pointer-events:auto}
	    .phx-ctile:hover .phx-ctile-sublink:nth-child(1){transition-delay:.05s}
	    .phx-ctile:hover .phx-ctile-sublink:nth-child(2){transition-delay:.09s}
	    .phx-ctile:hover .phx-ctile-sublink:nth-child(3){transition-delay:.13s}
	    .phx-ctile:hover .phx-ctile-sublink:nth-child(4){transition-delay:.17s}
	    .phx-ctile:hover .phx-ctile-sublink:nth-child(5){transition-delay:.21s}
	    .phx-ctile:hover .phx-ctile-sublink:nth-child(6){transition-delay:.25s}
	    .phx-ctile:hover .phx-ctile-sublink:nth-child(7){transition-delay:.29s}
	    .phx-ctile:hover .phx-ctile-sublink:nth-child(8){transition-delay:.33s}
	    .phx-ctile:hover .phx-ctile-sublist:has(.phx-ctile-sublink:nth-child(5)) .phx-ctile-sublink:nth-child(1){transition-delay:.03s}
	    .phx-ctile:hover .phx-ctile-sublist:has(.phx-ctile-sublink:nth-child(5)) .phx-ctile-sublink:nth-child(2){transition-delay:.06s}
	    .phx-ctile:hover .phx-ctile-sublist:has(.phx-ctile-sublink:nth-child(5)) .phx-ctile-sublink:nth-child(3){transition-delay:.09s}
	    .phx-ctile:hover .phx-ctile-sublist:has(.phx-ctile-sublink:nth-child(5)) .phx-ctile-sublink:nth-child(4){transition-delay:.12s}
	    .phx-ctile:hover .phx-ctile-sublist:has(.phx-ctile-sublink:nth-child(5)) .phx-ctile-sublink:nth-child(5){transition-delay:.15s}
	    .phx-ctile:hover .phx-ctile-sublist:has(.phx-ctile-sublink:nth-child(5)) .phx-ctile-sublink:nth-child(6){transition-delay:.18s}
	    .phx-ctile:hover .phx-ctile-sublist:has(.phx-ctile-sublink:nth-child(5)) .phx-ctile-sublink:nth-child(7){transition-delay:.21s}
	    .phx-ctile:hover .phx-ctile-sublist:has(.phx-ctile-sublink:nth-child(5)) .phx-ctile-sublink:nth-child(8){transition-delay:.24s}
	  }
	  @media(prefers-reduced-motion:reduce){
	    .phx-ctile-img,.phx-ctile-subpanel,.phx-ctile-subhead,.phx-ctile-sublink{transition:none}
	  }
	  @media(max-width:860px){
	    .phx-ctile.big,.phx-ctile.half,.phx-ctile.third{grid-column:span 6;min-height:170px}
	  }
	  @media(max-width:520px){
	    .phx-ctile.big,.phx-ctile.half,.phx-ctile.third{grid-column:span 6;min-height:140px;padding:12px}
	    .phx-ctile :is(h2,h3,h4,h5,h6){font-size:var(--step-0)}
	  }

	  /* homepage */
	  .phx-carousel{position:relative;margin:24px 0;border-radius:14px;overflow:hidden;aspect-ratio:1181/460;background:var(--blue-pale)}
	  .phx-carousel-track{display:flex;width:100%;height:100%;transition:transform .5s ease}
	  .phx-carousel-slide{position:relative;flex:0 0 100%;width:100%;height:100%;display:flex;align-items:center;justify-content:center;background:var(--blue-pale);overflow:hidden}
	  .phx-carousel-slide::before{content:'';position:absolute;inset:0;background-image:var(--bg);background-size:cover;background-position:center;filter:blur(28px) brightness(.82) saturate(1.15);transform:scale(1.18);z-index:0}
	  .phx-carousel-slide img{position:relative;z-index:1;width:100%;height:100%;object-fit:contain;display:block}
	  .phx-carousel-arrow{position:absolute;top:50%;transform:translateY(-50%);width:40px;height:40px;border-radius:var(--btn-radius);border:none;background:rgba(255,255,255,.85);color:var(--ink);font-size:var(--btn-ico);line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 10px rgba(0,0,0,.15)}
	  .phx-carousel-arrow:hover{background:var(--white)}
	  .phx-carousel-prev{left:14px}
	  .phx-carousel-next{right:14px}
	  .phx-carousel-dots{position:absolute;bottom:14px;left:50%;transform:translateX(-50%);display:flex;gap:8px}
	  .phx-carousel-dot{width:8px;height:8px;border-radius:50%;background:rgba(255,255,255,.55);cursor:pointer;transition:.2s}
	  .phx-carousel-dot.active{background:var(--white);width:22px;border-radius:5px}
	  @media(max-width:560px){.phx-carousel-arrow{width:var(--btn-h-touch);height:var(--btn-h-touch)}}


/* --- было условно только на главной (#v12, строки 1920-2115 header.php) --- */

	  /* Задача 125, 19.08 — padding-top:1px здесь не декоративный, а техническая заглушка: без
	     собственного padding/border у #v12 margin-top:var(--sp-3) баннера (.v12-banner ниже)
	     схлопывался НАСКВОЗЬ через #v12 и .wrap и добавлялся к отступу #phx-main выше (30+24=54px
	     вместо 30) — тот самый повторный счёт, от которого предупреждала задача. 1px рвёт цепочку
	     схлопывания (родитель с любым, даже минимальным padding-top не пропускает margin потомка
	     наружу) и сам по себе не заметен глазом. */
	  #v12{background:var(--bg);color:var(--ink);padding-top:1px}
	  #v12 .wrap{max-width:1680px}
	  #v12 .v12-over{font-size:var(--step--1);letter-spacing:.22em;text-transform:uppercase;color:var(--acc-text);font-weight:700;margin:0 0 .5rem}
	  #v12 .v12-btn{font-family:var(--font-body);font-weight:600;font-size:var(--btn-fs-main);min-height:var(--btn-h-touch);padding:12px 24px;border:1px solid var(--acc-btn);color:var(--acc-text);background:var(--white);cursor:pointer;letter-spacing:.02em;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--btn-radius);transition:.25s}
	  #v12 .v12-btn.v12-solid{background:var(--prim);color:var(--bg)}
	  #v12 .v12-btn.v12-accent{background:var(--acc-btn);border-color:var(--acc-btn);color:var(--white)}
	  /* Задача 093, п.3 — сначала перекрашивалась точечным классом только кнопка «Открыть каталог»
	     первого экрана (задача была ограничена first screen, «Войти в кабинет» и второе «Открыть
	     каталог» ниже по странице сознательно оставались старым тоном — открытый вопрос архитектору
	     в отчёте 093). Задача 094, 17.08 — тёплый пион стал основным цветом действия ВО ВСЁМ
	     шаблоне, вопрос снят: все три кнопки на .v12-btn.v12-accent унифицированы через общий
	     токен tokens.css, точечный класс (.phx-b4-accent) стал не нужен и убран — как и явно
	     просила задача 094, п.2 («локальные токены из 093 убрать»). Наведение — тоже класс
	     .v12-accent целиком (не общий .v12-btn:hover ниже, у него более тёмный --prim, не тот
	     тон): специфичность двух классов (.v12-btn.v12-accent:hover) выше одного (.v12-btn:hover),
	     побеждает корректно для всех трёх кнопок. */
	  @media(hover:hover){#v12 .v12-btn.v12-accent:hover{background:var(--acc-btn-h);border-color:var(--acc-btn-h);color:var(--white)}}
	  @media(hover:hover){#v12 .v12-btn:hover{background:var(--cta-bg);color:var(--acc-text);border-color:var(--acc-btn-h)}}

	  /* Backlog 12.08, п.1 — герой на десктопе (1440×900/1920×1080) требовал скролла: тройной
	     удар по высоте — верхний/нижний паддинг на --sp-xl (до 128px), h1 на --step-3 (до 80px,
	     переносился в 4 строки) и портретная картинка (aspect-ratio 4/5) — суммарно ~944px
	     самого героя + ~148px шапки/плашек = ~1092px, шире 900-1080px высоты экрана. Только
	     десктопные правила ниже (мобильная вёрстка — свои правила в @media(max-width:...) ниже
	     по файлу, не трогал). Подобрано так, чтобы после шапки помещался герой + начало ленты
	     разделов, проверено на живых 1440×900 и 1920×1080 (не только на глаз): паддинг и отступ
	     — на существующие 8pt-токены (--sp-6/--sp-4), заголовок — на существующую ступень шкалы
	     (--step-2, без нового 6-го размера шрифта), картинка — менее вытянутое соотношение
	     сторон 4/3 вместо 4/5 (меньше кропа, а не только меньше по высоте). */
	  #v12 .v12-hero{padding:var(--sp-6) 0 var(--sp-4)}
	  #v12 .v12-hero-grid{display:grid;grid-template-columns:1.15fr .85fr;gap:var(--sp-l);align-items:center}
	  #v12 .v12-hero h1{font-size:var(--step-2);margin:.4rem 0 var(--sp-m)}
	  #v12 .v12-hero h1 em{font-style:normal;color:var(--acc)}
	  #v12 .v12-hero-lead{font-size:var(--step-1);color:var(--mut);max-width:32ch;font-weight:400;margin:0}
	  #v12 .v12-hero-actions{display:flex;gap:.8rem;margin-top:var(--sp-m);flex-wrap:wrap}
	  /* B33 15.08 (tasks/057-home-desktop-v2.md, п.2) — список условий опта вместо трёх цифр,
	     та же вёрстка (кружок-иконка + строка), что уже проверена на мокапе V2. */
	  #v12 .v12-cond-list{margin-top:var(--sp-l);display:flex;flex-direction:column;gap:12px;max-width:480px}
	  #v12 .v12-cond-item{display:flex;align-items:center;gap:12px;font-size:var(--step--1);color:var(--ink)}
	  #v12 .v12-cond-ico{flex:none;width:32px;height:32px;border-radius:50%;background:var(--t2);color:var(--acc-text);display:flex;align-items:center;justify-content:center;font-size:15px;font-weight:700}
	  /* Задача 157, 20.08 — цифры доверия рядом со списком условий, тот же контейнер max-width,
	     чтобы не расширять блок случайно шире текста лида. */
	  #v12 .v12-trust-list{margin-top:var(--sp-m);display:flex;gap:var(--sp-l);max-width:480px}
	  #v12 .v12-trust-item{display:flex;flex-direction:column}
	  #v12 .v12-trust-item b{font-family:var(--font-display);font-size:var(--step-2);color:var(--ink);line-height:1.1}
	  #v12 .v12-trust-item span{font-size:var(--step--1);color:var(--mut)}
	  @media(max-width:520px){
	    /* Задача 157 — на 390×844 лид-абзац сам по себе уже заканчивается за пределами первого
	       экрана (замер живьём до этой правки, отчёт 157) — компактная одна строка вместо
	       двухколоночного блока и меньший отступ сверху отвоёвывают место, не трогая баннер. */
	    #v12 .v12-h1zone .v12-trust-list{margin-top:0;gap:var(--sp-2);flex-wrap:wrap}
	    #v12 .v12-h1zone .v12-trust-item{flex-direction:row;align-items:baseline;gap:4px}
	    #v12 .v12-h1zone .v12-trust-item b{font-size:var(--step-0)}
	    #v12 .v12-h1zone .v12-trust-item span{font-size:var(--step--1)}
	  }
	  #v12 .v12-hero-visual{position:relative;aspect-ratio:4/3;background:linear-gradient(155deg,var(--t2),var(--t1) 55%,var(--t3));border:1px solid var(--line);overflow:hidden;display:flex;align-items:flex-end;padding:var(--sp-m);isolation:isolate}
	  #v12 .v12-hero-visual img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0}
	  #v12 .v12-hero-visual::after{content:'';position:absolute;inset:0;background:linear-gradient(to top,rgba(20,16,16,.68) 0%,rgba(20,16,16,.22) 45%,rgba(20,16,16,.02) 68%);z-index:1}
	  #v12 .v12-hv-badge{position:absolute;top:var(--sp-m);left:var(--sp-m);background:var(--prim);color:var(--bg);font-size:var(--step--1);font-weight:700;padding:8px 16px;letter-spacing:.04em;z-index:2}
	  #v12 .v12-hv-tag{position:relative;z-index:2;font-family:var(--font-display);font-size:var(--step-1);line-height:1.15;color:var(--white);margin:0}
	  #v12 .v12-hv-tag small{display:block;font-family:var(--font-body);font-size:var(--step--1);letter-spacing:.18em;text-transform:uppercase;color:hsl(0 0% 100% / .82);margin-bottom:.5rem;font-weight:700}

	  #v12 .v12-section{padding:var(--sp-xl) 0}
	  /* P2 Repair 13.08 — commerce depth: категории ближе к hero (desktop: первая карточка
	     ≤880px при 1440×900), лишний воздух между кабинетом и финальным CTA убран */
	  #v12 #v12catalog{padding-top:var(--sp-6)}
	  #v12 .v12-account{padding-bottom:var(--sp-6)}
	  #v12 .v12-sec-head{display:flex;justify-content:space-between;align-items:center;gap:var(--sp-m);margin-bottom:var(--sp-l);flex-wrap:wrap}
	  #v12 .v12-sec-head h2{font-size:var(--step-2);max-width:24ch;margin:0}
	  /* Задача 085 16.08 — чипы-счётчики разделов (задача 057, п.3) и кнопка «Все разделы →»
	     справа от заголовка убраны по просьбе Алексея, ничего взамен не поставлено. Секция
	     теперь состоит из одного заголовка — .v12-sec-head с одним ребёнком, justify-content
	     не мешает (space-between с одним элементом ведёт себя как flex-start). */

	  #v12 .v12-value{background:var(--prim)}
	  #v12 .v12-value .v12-over{color:var(--acc-soft)}
	  #v12 .v12-value h2{color:var(--bg);font-size:var(--step-2);max-width:22ch;margin:0}
	  #v12 .v12-val-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-m);margin-top:var(--sp-l)}
	  #v12 .v12-val{border-top:1px solid hsl(40 27% 98% / .22);padding-top:var(--sp-s)}
	  #v12 .v12-val b{font-family:var(--font-display);font-size:var(--step-2);color:var(--bg);display:block;margin-bottom:.4rem;font-weight:600}
	  #v12 .v12-val p{font-size:var(--step--1);color:hsl(40 20% 82%);margin:0}

	  /* UXD Homepage 13.08: пустая градиентная половина (.v12-feat-img «Кабинет клиента») убрана —
	     ~650px декоративной высоты без контента; блок кабинета стал компактной полосой текст+кнопка */
	  #v12 .v12-feat{display:grid;grid-template-columns:1fr 1fr;gap:0;border:1px solid var(--line)}
	  #v12 .v12-feat-compact{grid-template-columns:1fr auto;align-items:center}
	  #v12 .v12-feat-txt{padding:var(--sp-l)}
	  #v12 .v12-feat-txt h2{font-size:var(--step-2);margin:.6rem 0 var(--sp-s)}
	  #v12 .v12-feat-txt p{color:var(--mut);max-width:52ch;margin-bottom:0}
	  #v12 .v12-feat-side{padding:var(--sp-l)}

	  /* «В наличии сегодня» — примыкает к категориям как единый commerce-блок (без двойного --sp-xl);
	     карточки — те же .phx-card, что в каталоге */
	  #v12 .v12-avail{padding-top:0}
	  /* B20 15.08 (tasks/023-home-row-five.md) — решение Алексея: 5 карточек в ряд на широком
	     экране, было 4 (контейнер .wrap 1400px просто не заполнялся). Лесенка 5→4→3→2 — три
	     новых промежуточных состояния до уже существующего мобильного (860px, ниже по каскаду,
	     не трогаю). Источник карточек (footer.php, top-N разделов тизера) тоже расширен под 5. */
	  #v12 .v12-prod-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:clamp(.6rem,.4rem + .6vw,1rem)}
	  #v12 .v12-prod-qty{font-size:var(--step--1);color:var(--muted);margin-top:2px}

	  #v12 .v12-cta{text-align:center;padding:var(--sp-6) 0 var(--sp-xl)}
	  #v12 .v12-cta h2{font-size:var(--step-2);max-width:20ch;margin:0 auto var(--sp-s)}
	  #v12 .v12-cta p{color:var(--mut);margin-bottom:var(--sp-m)}
	  #v12 .v12-hero-actions.v12-center{justify-content:center}

	  /* B20 15.08 — 5→4 между широким десктопом и тем диапазоном, где карточка на 5 колонок
	     стала бы теснее ~230px и имя товара рисковало разъехаться на лишнюю строку. */
	  @media(max-width:1160px){
	    #v12 .v12-prod-grid{grid-template-columns:repeat(4,1fr)}
	  }
	  /* B20 15.08 — 4→3: тот же порог тесноты карточки, что и выше, просто на следующей ступени. */
	  @media(max-width:1000px){
	    #v12 .v12-prod-grid{grid-template-columns:repeat(3,1fr)}
	  }

	  @media(max-width:860px){
	    #v12 .v12-hero-grid{grid-template-columns:1fr}
	    #v12 .v12-hero-visual{aspect-ratio:16/11;order:-1}
	    #v12 .v12-val-grid{grid-template-columns:1fr 1fr}
	    #v12 .v12-feat,#v12 .v12-feat-compact{grid-template-columns:1fr}
	    #v12 .v12-feat-side{padding:0 var(--sp-l) var(--sp-l)}
	    #v12 .v12-prod-grid{grid-template-columns:1fr 1fr}
	    /* mobile category discovery: top-4 + широкая CTA-плитка «Все разделы», без 7 карточек
	       подряд — возвращено той же правкой 16.08, что отменила мозаику 070/083. */
	    #v12 .phx-home-extra{display:none}
	    #v12 .phx-cta-tile{grid-column:span 12;min-height:96px}
	    #v12 #v12catalog{padding-top:var(--sp-3)}
	    /* UX Overhaul 13.08 — до этой правки мобильный герой (картинка+эйфорию+H1 крупным
	       --step-3+подзаголовок) занимал 1.77 viewport ДО первого коммерческого элемента
	       (FIRST_PRODUCT_VIEWPORT=1.77, ux-before-metrics.json) — на первом экране 390×844
	       не было видно ни одной CTA-кнопки. Раньше здесь намеренно возвращали крупный H1 и
	       большие отступы «мобильную не трогали» (см. архив git/коммент) — теперь мобильная
	       иерархия — предмет этой задачи, уменьшаем картинку/паддинги/заголовок, чтобы CTA
	       «Открыть каталог» помещалась в первый экран. */
	    #v12 .v12-hero{padding:var(--sp-4) 0 var(--sp-3)}
	    #v12 .v12-hero-visual{aspect-ratio:21/9}
	    #v12 .v12-hero h1{font-size:var(--step-1)}
	    #v12 .v12-hero-lead{font-size:var(--step-0)}
	    #v12 .v12-cond-list{margin-top:var(--sp-2);gap:8px}
	  }
	  @media(max-width:520px){
	    /* P2 Repair 13.08 — бейдж «Опт от 1 коробки» и строка «Склад · Тольятти» в hero-картинке
	       сталкивались на 390/360 (независимый аудит): прячем дублирующую подпись (Тольятти уже
	       есть в эйфории hero), claim «Актуальные остатки напрямую из 1С» остаётся. */
	    #v12 .v12-hv-tag small{display:none}
	    #v12 .v12-val-grid{grid-template-columns:1fr}
	  }

	  /* Задача 071, 17.08 — баннер-слайдер первым экраном (мокап баннер-главной-A.png, вариант А,
	     согласован 17.08 в пять заходов). Слайды заданы данными ($phxBannerSlides ниже), не
	     вёрсткой — задача явно это требует. Трек — горизонтальный flex, translateX по индексу:
	     тот же приём, что и везде на сайте («листание пальцем» через touch-события руками, без
	     сторонней библиотеки карусели — задача прямо запрещала её подключать). Анимация трека —
	     обычный CSS transition; глобальное правило prefers-reduced-motion (tokens.css,
	     `*{transition-duration:.001ms!important}`) само гасит именно анимацию, автоплей выключен
	     отдельно в JS (двойная защита, не полагаемся только на то, что transition незаметен). */
	  #v12 .v12-banner{position:relative;margin-top:var(--sp-3);border-radius:18px;overflow:hidden;height:400px;background:var(--t3)}
	  #v12 .v12-banner-track{display:flex;height:100%;transition:transform .5s ease}
	  #v12 .v12-banner-slide{position:relative;flex:0 0 100%;min-width:0;display:block;color:inherit;text-decoration:none;overflow:hidden}
	  #v12 .v12-banner-bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0}
	  #v12 .v12-banner-inner{position:relative;z-index:1;height:100%;display:flex;flex-direction:column;justify-content:center;padding:0 var(--sp-6);max-width:900px}
	  #v12 .v12-banner-kicker{font-size:14px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--phx-hd-graphite);margin-bottom:18px}
	  /* Задача 227, 24.08 — правило осиротело: метка «[РЫБА] Пример» снята со слайдов вместе
	     с признаком 'fish' в данных (header.php). Класс больше нигде не используется,
	     поэтому правило удалено, а не оставлено висеть. */
	  #v12 .v12-banner-inner h2{font-family:var(--font-display);font-size:44px;font-weight:600;line-height:1.1;margin:0 0 10px;letter-spacing:-.01em;color:var(--ink)}
	  #v12 .v12-banner-meta{font-size:18px;color:#4b4a4c;margin:0}
	  /* Задача 071, критерий 8 — плашка промокода графитом слева/белым справа, розового на слайде
	     нет вообще (пион — только шапка/кнопки действия, отдельное решение Алексея). Промокод —
	     текст в разметке (<b> с реальным символьным содержимым), не картинка — копируется мышью,
	     находится Ctrl+F. */
	  #v12 .v12-promo{display:inline-flex;align-items:stretch;border-radius:14px;overflow:hidden;margin-top:22px;box-shadow:0 4px 14px rgba(0,0,0,.06);width:fit-content}
	  #v12 .v12-promo-l{background:var(--phx-hd-graphite);color:var(--white);padding:10px 18px;display:flex;flex-direction:column;justify-content:center}
	  #v12 .v12-promo-l b{font-size:26px;font-weight:800;letter-spacing:.02em;line-height:1.2}
	  #v12 .v12-promo-l span{font-size:10px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;opacity:.9}
	  #v12 .v12-promo-r{background:var(--white);padding:10px 18px;display:flex;flex-direction:column;justify-content:center;border:1px solid var(--line);border-left:0}
	  #v12 .v12-promo-r b{font-size:15px;font-weight:700;line-height:1.3}
	  #v12 .v12-promo-r span{font-size:13px;color:var(--mut)}
	  #v12 .v12-banner-dots{position:absolute;left:var(--sp-6);bottom:24px;z-index:2;display:flex;gap:7px;align-items:center}
	  /* Зона нажатия у полоски — не сама видимая полоска 5px (критерий 6: ≥44px по высоте) —
	     видимый индикатор внутри псевдоэлемента, у самой кнопки прозрачная область больше. */
	  #v12 .v12-banner-dot{position:relative;width:26px;height:44px;padding:0;border:none;background:none;cursor:pointer}
	  #v12 .v12-banner-dot::after{content:'';position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:5px;border-radius:5px;background:rgba(31,33,35,.22);transition:width .2s ease}
	  #v12 .v12-banner-dot.on::after{width:52px;background:var(--acc-btn)}
	  #v12 .v12-banner-dot.on{width:52px}
	  #v12 .v12-banner-dot:focus-visible{outline:2px solid var(--acc-text);outline-offset:2px}

	  #v12 .v12-h1zone{padding:var(--sp-4) 0 0}

	  /* ═════ Задача 219, 23.08 — условия работы в правой колонке первого экрана ═════
	     Замер до правки при 1920: подзаголовок 500px, цифры 480px, справа от них 1296px пустоты;
	     сами условия стояли отдельной секцией .v12-terms-standalone ниже и страдали тем же.
	     Решение Алексея по мокапу `_дизайн_мокапы/главная-пустота-справа.html`, вариант A.
	     Секции больше нет — блок переехал внутрь .v12-h1zone как .v12-h1side. Отступ прежней
	     секции (padding-top var(--sp-2)) перенесён сюда ДОСЛОВНО: ниже порога блок обязан стоять
	     ровно там же, где стоял, мобильная версия не меняется ни на пиксель. */
	  #v12 .v12-h1side{padding:var(--sp-2) 0 0}

	  @media(min-width:1280px){
	    /* ═════ Задача 223, 23.08 — композиция первого экрана, вторая итерация ═════
	       Замер после 219 при 1920 (отчёт архитектора и мой собственный): левая колонка 1096px
	       при тексте в 500, то есть 596px пустоты ВНУТРИ неё, и 652px разрыва до условий.
	       Пустоту не убрали, а переставили внутрь колонки — Алексей: «смотрится убого».
	       Причина числовая: колонки задавались как «остаток и 480», а не от содержимого.

	       Теперь наоборот, от содержимого:
	         левая  640 — подзаголовку положено 500 (норма читаемости, менять нельзя), заголовку
	                      при 640 достаётся 3 строки по ~53 знака: это рабочая длина строки,
	                      не «простыня» и не лесенка;
	         правая 520 — потолок из мокапа; самый длинный пункт «Собираем заказ в течение
	                      24 часов» с иконкой 32px и внутренними отступами занимает ~430px,
	                      520 даёт запас и не даёт карточке разъехаться;
	         промежуток 56 — из мокапа, середина разрешённого диапазона 48–64.
	       Итого блок 1216px. Контейнер на 1920 — 1632, значит справа от блока остаётся 416px.
	       Это осознанный размен, и он назван в отчёте: при подзаголовке 500 и карточках 520
	       нельзя одновременно держать колонки рядом И упирать их в правый край. 219 выбрала
	       правый край и получила разрыв в 652; 223 выбирает соседство.

	       Порог 1280, а не 1200: блоку нужно 640+56+520=1216, плюс поля 2×24 — окно от 1264.
	       Взято 1280 как ближайшая стандартная ступень, запас 16px. */
	    #v12 .v12-h1zone{display:grid;grid-template-columns:640px 520px;
	      column-gap:56px;row-gap:0;align-items:start;justify-content:start}
	    /* Заголовок И надзаголовок теперь ВНУТРИ левой колонки — ради этого задача и затевалась:
	       колонка шириной 640 должна быть чем-то занята, иначе она читается как дыра. Первый
	       экран из-за переноса заголовка уезжает вниз; насколько — измерено и названо в отчёте. */
	    /* Строки задаём ВСЕМ детям поимённо. Если указать только колонку, автораскладка
	       посадит следующий элемент в первую свободную ячейку — у меня так подзаголовок уехал
	       в правую колонку рядом с заголовком. Явные строки убирают эту неоднозначность. */
	    #v12 .v12-h1zone > .v12-over{grid-column:1;grid-row:1}
	    #v12 .v12-h1zone > h1{grid-column:1;grid-row:2}
	    #v12 .v12-h1zone > .v12-hero-lead{grid-column:1;grid-row:3}
	    #v12 .v12-h1zone > .v12-trust-list{grid-column:1;grid-row:4}
	    /* Правая колонка начинается с самого верха, вровень с надзаголовком: теперь, когда
	       заголовок внутри левой колонки, обе колонки обязаны стартовать от одной линии —
	       иначе это снова не композиция, а текст и приписка сбоку.
	       ВНИМАНИЕ на `span 4`, а не `1 / -1`: явных строк у сетки нет, все они неявные,
	       и `-1` в такой сетке указывает на последнюю линию ЯВНОЙ части — то есть на первую же.
	       Запись `1 / -1` схлопывается в одну строку, и та растягивается под высоту условий:
	       заголовок уезжает вниз на 232px. Проверено живьём, не по документации. */
	    #v12 .v12-h1side{grid-column:2;grid-row:1 / span 4;padding:0;align-self:start}
	    #v12 .v12-h1side .v12-cond-list{margin-top:0;gap:10px;max-width:520px}
	    /* Оформление пунктов — из мокапа, вариант A: тонкая рамка, светлая подложка, скругление,
	       внутренние отступы. До 223 пункт был голым текстом 14.4px на белом. Цвета только
	       токенами: --line рамка, --t3 подложка. Ничего своего не изобретено.
	       Применяется ТОЛЬКО от 1280 — ниже порога условия стоят как раньше, и мобильная
	       вёрстка обязана совпасть побайтово. */
	    #v12 .v12-h1side .v12-cond-item{padding:11px 14px;border:1px solid var(--line);
	      border-radius:12px;background:var(--t3)}
	  }

	  @media(max-width:900px){
	    #v12 .v12-banner-inner h2{font-size:34px}
	    #v12 .v12-banner-meta{font-size:16px}
	  }
	  @media(max-width:560px){
	    /* Данные задачи 071 — мобильная раскладка слайда принципиально другая, не то же самое
	       поверх картинки, сжатое по ширине: фото полосой сверху (фиксированная высота, снимок
	       МАКЕТ-cvetyexpo-390x420.png — те же 390×420 общей высоты баннера на мобильном), весь
	       текст под ней столбцом, плашка промокода на всю ширину. */
	    #v12 .v12-banner{height:420px}
	    #v12 .v12-banner-slide{display:flex;flex-direction:column}
	    #v12 .v12-banner-bg{position:static;width:100%;height:170px;flex:none}
	    #v12 .v12-banner-inner{position:static;flex:1;padding:16px;max-width:none;justify-content:flex-start;overflow-y:auto}
	    #v12 .v12-banner-kicker{margin-bottom:10px;font-size:12px}
	    #v12 .v12-banner-inner h2{font-size:26px;margin-bottom:6px}
	    #v12 .v12-banner-meta{font-size:14px}
	    #v12 .v12-promo{width:100%;margin-top:14px}
	    #v12 .v12-promo-l,#v12 .v12-promo-r{flex:1}
	    #v12 .v12-banner-dots{left:16px;bottom:10px}
	    /* Задача 157 — отступ над заголовком был рассчитан без учёта того, что под лидом
	       появится ещё одна строка (цифры доверия); на 390×844 лид и без того уже заканчивался
	       за пределами первого экрана (замер живьём, отчёт 157). Уже, не тоньше — на 8pt сетке. */
	    #v12 .v12-h1zone{padding-top:var(--sp-2)}
	    #v12 .v12-h1zone .v12-over{margin-bottom:2px}
	    /* Честная находка по ходу задачи 157: у H1 в этой ветке (баннер есть → .v12-h1zone, не
	       .v12-hero) не было СВОЕГО правила font-size вообще — размер брался из браузерного
	       умолчания h1 (~2em), а не из токенов шрифтов сайта, в отличие от .v12-hero h1 на
	       строке 1179/1285 этого файла. На трёх строках такой незаданный крупный текст и был
	       главной причиной, что лид (а тем более что-то под ним) не помещался в первый экран —
	       не только новый блок цифр доверия. Ставлю на токен --step-1, тот же, что уже применяет
	       .v12-hero h1 на этой же ширине (строка 1285) — не выдумываю новый размер, привожу к
	       уже принятой на сайте логике «на 390px H1 -1 ступень меньше десктопного». */
	    #v12 .v12-h1zone h1{font-size:var(--step-1);margin:.3rem 0 .5rem}
	  }

	  /* ═════ Задача 205, 23.08 — первый экран карточки товара на телефоне, вариант B ═════
	     Решение Алексея по мокапу `_дизайн_мокапы/карточка-товара-мобайл.html`, колонка B.
	     Что было (живой замер 390×844 до правки): до фотографии 774px, фотографии видно 32%,
	     кнопка «В корзину» на 685..729 — покупатель открывал карточку ленты и ленты не видел.
	     Порядок варианта B: строка навигации → название → «фото | цена и кнопка» → таблица уровней.

	     Порог 560px, а не 900px. Причина числом, а не на глаз: колонка фото — 48% ширины контента.
	     На 390 это 164px при правой колонке 166px — ровно пропорция мокапа. На 768 те же правила
	     дают фото 344px и правую колонку 360px под цену в две строки и одну кнопку — половина
	     планшетной ширины под пустоту. Планшет 561..900 остаётся на раскладке задачи 153.

	     Приём — display:contents на .phx-pd-info/.phx-pd-priceBox/.phx-pd-actions: DOM не
	     перестраивается (значит порядок для скринридера и Tab прежний, и вся логика 139 —
	     #phxPdMeta, .phx-pd-ctl[data-uuid], #phxPdGallery — работает как работала), но их дети
	     становятся прямыми ячейками сетки .phx-pd и раскладываются поштучно. Плата за это —
	     рамка блока цен: display:contents убирает её вместе с контейнером, поэтому фон/обводка
	     возвращаются самим строкам (.phx-pd-prow ниже), а не рисуются заново на обёртке. */
	  .phx-pd-sum{display:none}
	  .phx-pd-navline{display:none}
	  @media(max-width:560px){
	    /* Строка навигации. Четыре звена крошек занимали 68px (две строки), рамочная кнопка
	       возврата — ещё 76px; обе схлопнуты в одну строку «← Раздел · Арт. N» — то же, что
	       мокап показывает в колонке B. Ни одна цель не потеряна: путь в раздел остался ссылкой,
	       артикул виден там же, где раньше стоял в мелкой строке .phx-pd-meta. */
	    body.phx-pdp #phxCrumbs{padding:8px 0}
	    body.phx-pdp #phxCrumbs > a,
	    body.phx-pdp #phxCrumbs > span{display:none}
	    body.phx-pdp .phx-pd-navline{display:block;font-size:13px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
	    /* Ссылка возврата — единственная кликабельная цель этой строки, и рамочной кнопки на
	       44px (задача 200) на телефоне больше нет. Цель делаем не глазом, а вертикальным
	       паддингом 13px, погашенным отрицательным полем: область нажатия 44px (13+18+13),
	       высота строки при этом не растёт ни на пиксель. Выше и ниже неё — шапка и <h1>,
	       некликабельные, так что перехватить чужое нажатие (грабли задачи 192) нечему. */
	    body.phx-pdp .phx-pd-navback{color:var(--acc-text);font-weight:600;display:inline-block;padding:13px 0;margin:-13px 0}
	    /* Название на ступень мельче: h1 без собственного font-size — это браузерные 2em (32px),
	       на телефоне три строки. --step-2 даёт 25.6px на 390 — ровно «25px» мокапа, и это
	       ступень шкалы из tokens.css, а не новое число. */
	    body.phx-pdp #phx-content h1{font-size:var(--step-2);margin:4px 0 8px}
	    body.phx-pdp .phx-back-row{display:none}

	    .phx-pd{grid-template-columns:48% minmax(0,1fr);grid-template-rows:auto auto 1fr;column-gap:12px;row-gap:0}
	    .phx-pd-info,.phx-pd-priceBox,.phx-pd-actions{display:contents}
	    /* Фото слева на все три строки правой колонки. `1fr` третьей строкой — чтобы лишнюю
	       высоту фотографии забирала именно она: тогда align-self:end прижимает «В корзину»
	       к низу колонки (мокап), а плашка и цена не разъезжаются воздухом. */
	    .phx-pd-gallery{grid-column:1;grid-row:1 / span 3;order:0;align-self:start}
	    .phx-pd-thumb{max-height:none}
	    /* Из мелкой строки в правой колонке остаётся только плашка наличия: артикул уехал в
	       строку навигации выше, раздел — в ссылку «← Раздел» там же, и повторять их в колонке
	       шириной 166px значит отдать под дубли две строки из трёх (замер 360: правая колонка
	       была 214px против 149px фотографии — кнопка уходила НИЖЕ снимка). Ничего не потеряно:
	       оба значения видны на том же экране, на строку выше. Селектор `>span:not([class])`
	       бьёт ровно по этим двум — у плашки наличия свой класс (.phx-badge-in/.phx-badge-out). */
	    .phx-pd-meta{grid-column:2;grid-row:1;margin-bottom:0;gap:8px;font-size:12px}
	    body.phx-pdp .phx-pd-meta > span:not([class]){display:none}
	    .phx-pd-sum{display:block;grid-column:2;grid-row:2;margin-top:8px}
	    .phx-pd-sum-price{font-family:var(--font-body);font-size:26px;font-weight:800;line-height:1.1;color:var(--ink)}
	    .phx-pd-sum-price small{font-size:13px;font-weight:600;color:var(--muted)}
	    .phx-pd-sum-note{font-size:12px;color:var(--muted);margin-top:4px}
	    .phx-pd-ctl{grid-column:2;grid-row:3;align-self:end;margin-top:8px}
	    .phx-pd-variants{grid-column:1 / -1;grid-row:4;margin:16px 0 0}
	    /* Таблица уровней — все четыре строки, ничего не свёрнуто. Рамку блока цен, снятую
	       display:contents, держат сами строки: боковые границы у каждой, верх/низ и скругления
	       у крайних. :nth-last-of-type(2) — последняя .phx-pd-prow: последним ребёнком блока цен
	       остаётся .phx-pd-actions, а строка кратности (RATIO>1) — тоже .phx-pd-prow, поэтому
	       считать надо от конца, а не по фиксированному номеру. */
	    .phx-pd-prow{grid-column:1 / -1;background:var(--bg);border-left:1px solid var(--line);border-right:1px solid var(--line);padding:7px 12px}
	    .phx-pd-prow:first-of-type{margin-top:16px;border-top:1px solid var(--line);border-radius:14px 14px 0 0;padding-top:11px}
	    .phx-pd-prow:nth-last-of-type(2){border-bottom:1px solid var(--line);border-radius:0 0 14px 14px;padding-bottom:11px}
	    /* «Спросить» никуда не делась — переехала под таблицу цен во всю ширину. */
	    .phx-pd-actions .btn-ghost{grid-column:1 / -1;margin-top:16px;width:100%}
	  }

	  /* ═════ Задача 207, 23.08 — кнопка чата уступает место контенту ═════
	     Замер «до» (elementFromPoint в пяти точках рамки кнопки, 360/390/440, две позиции
	     прокрутки): на карточке товара вверху страницы кнопка накрывала строку уровня цены
	     в 4 точках из 5 на 360 и 390 (тот самый закрытый VIP с кадра задачи 205), в списке
	     каталога — кнопку «В корзину» и цену карточки, до 3 точек из 5. Прайс-лист чист.
	     В корзине кнопка не перекрывает ничего: выдвижная панель имеет z-index 71 против её 60,
	     то есть кнопка лежит ПОД панелью — замер это подтвердил (сверху панель во всех точках).

	     Почему «кнопка уступает», а не «нижний отступ у контента». Отступ снизу уже стоит
	     (`#phx-content{padding-bottom:88px}` на ≤560px, задача 052) и от этого дефекта не спасает
	     в принципе: он резервирует место в КОНЦЕ страницы, а `position:fixed` накрывает то, что
	     проплывает под кнопкой ПРИ ПРОКРУТКЕ. Никакой отступ этого не лечит — лечит только то,
	     что кнопка убирается, когда под ней оказывается цена, счётчик или кнопка действия.

	     Вид и место кнопки не меняются: класс снимается сразу, как только под ней снова пусто. */
	  @media(max-width:900px){
	    .chat-fab{transition:opacity .18s ease,transform .18s ease}
	    .chat-fab.is-yield{opacity:0;visibility:hidden;pointer-events:none;transform:translateY(28px);
	      transition:opacity .18s ease,transform .18s ease,visibility 0s linear .18s}
	  }
	  @media(prefers-reduced-motion:reduce){.chat-fab,.chat-fab.is-yield{transition:none}}
