/* ============================================================================
   Webmarket — шапка и навигация. Один файл на витрину и Mini App.
   ----------------------------------------------------------------------------
   Разметку рисует nav.js, стили лежат здесь. Порознь их держать нельзя:
   index.html и app.html — две реализации одного окна, и расходились они
   молча, каждая своей правкой. Общий файл делает расхождение невозможным.

   Цвета, радиусы, отступы и площадь касания — из kit.css. Здесь только
   композиция: бренд, одно поле поиска, одна строка действий. Разделов над
   выдачей нет — они целиком за кнопкой «Категории», а где ты находишься,
   говорят хлебные крошки.
   ============================================================================ */

:root {
  /* Поиск — главный орган страницы, но не баннер во весь экран. 44 —
     та же площадь касания, что у кнопок рядом. Ширина равна колонке
     шапки (--wm-head-w): делить строку не с кем — заявка и «ещё» стоят
     в hero, — и поле занимает её целиком. */
  --wm-search-h: 44px;
  --wm-search-w: 660px;
  /* Мера строки, а не колонка страницы. Заголовок первого экрана и поле
     поиска не растягиваются на всю ширину содержимого — читать строку в
     1240 точек нечем, — но и центрировать их за это нельзя: они стоят от
     левого края общей оси (.wm-nav__in), просто кончаются раньше неё. */
  --wm-head-w: 660px;
  /* Мера заголовка первого экрана — отдельная от --wm-head-w, и вот
     почему. 660 задумывались под строку в 15px: поясняющий абзац такой
     длины читается хорошо. Но на главной та же строка вырастает до 34px и
     становится заголовком в сорок шесть знаков, которому 660 точек мало —
     он переносился на две строки посреди пустого экрана в 1240 точек, и
     text-wrap: balance аккуратно делил надвое то, что просилось в одну.
     Мера абзаца, приложенная к заголовку, — вот и вся причина.

     1000 — не на глаз: браузером измерены все три варианта A/B-заголовка
     на трёх языках на предельном кегле 34px (24.09.2026). Длиннее всех
     узбекский вариант B — 974; прочие от 633 до 880. Прежние 960 мерились
     до A/B-теста, и вариант B на узбекском рвался надвое на 1024–1440.
     Запас до 1000 держит перевод чуть длиннее и всё ещё далёк от 1240 —
     уговор «строка кончается раньше колонки» остаётся в силе. Сторожит
     scripts/check-hero.mjs — по всем вариантам. */
  --wm-claim-w: 1000px;
  /* Крошки, счётчик выдачи и прошлые запросы — не поисковая колонка,
     а ширина сетки товаров под ними (.k-wrap в kit.css): иначе на
     широком экране они читались бы как отступ, а не как часть той же
     страницы.

     Берём саму переменную кита, а не её значение: пока здесь стояло
     число, оно разошлось с китом (1600 против 1280), и на 1440 счётчик с
     подсказками торчали на восемьдесят точек левее всего остального —
     страница выглядела съехавшей. Запасное значение на случай, если
     шапку когда-нибудь поднимут без кита. */
  --wm-wide-w: var(--wrap-w, 1280px);
}

/* ── каркас ───────────────────────────────────────────────────────────
   Шапка — три этажа-соседа, а не один липкий блок. Липкий этаж занимает
   в потоке ровно свою высоту, и пока схлопывание её меняло, оно двигало
   весь документ: браузер откатывал scrollY назад, порог переключался
   обратно, шапка раскрывалась и толкала страницу вперёд. На телефоне
   выдача запиралась на ста двадцати пяти пикселях (UI-01).

   Поэтому рост липкого этажа постоянен, а уезжает то, что стоит выше и
   ниже него. Соседями этажи обязаны быть на уровне страницы: липкий
   элемент прилипает внутри своего родителя и уехал бы вместе с общей
   обёрткой, кончись она на первом экране. Отсюда display: contents у
   host — своего ящика он не имеет, дети встают прямо в поток страницы. */
.wm-nav { display: contents; }
/* Колонка шапки — та же, что у содержимого страницы, и это единственная
   ось выравнивания на всю витрину.

   Прежде шапка тянулась во всю ширину окна, а её внутренности —
   бренд, поле поиска, ряд действий — центрировались каждая сама по себе
   в колонке шириной 660. На 1440 из-за этого заголовок первого экрана
   начинался на 390-й точке, а полки товаров под ним — на сотой: две
   независимые оси в одном кадре читаются как съехавшая вёрстка, и
   пустое поле слева было тому прямым доказательством. Ось теперь одна,
   и задаёт её этот блок: max-width и поля списаны с .k-wrap (kit.css)
   до пикселя — разойдись они, всё вернётся. */
.wm-nav__in {
  position: relative;
  max-width: var(--wrap-w, 1280px); margin: 0 auto;
  padding-left: var(--s-4); padding-right: var(--s-4);
}
@media (min-width: 480px) {
  .wm-nav__in { padding-left: var(--s-5); padding-right: var(--s-5); }
}

/* Первый этаж: кто мы, где мы, чем заняты и чем управляем. Уезжает
   потоком, сам. Просвет между брендом и полем задаёт этаж ниже, а не оба
   сразу: два отступа подряд — это лишняя строка на первом экране. */
.wm-nav__hero .wm-nav__in { padding-top: 30px; }

/* Верхняя строка: бренд слева, заявка на канал и «ещё» — общим углом
   справа. nowrap — намеренно: перенос увёл бы кнопки на вторую строку,
   а узкому экрану они и так тесны (--wm-cta__short ниже). Внутри левой
   половины бренд волен переноситься сам — .wm-brand__row про это. */
.wm-hero__top {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: nowrap; gap: var(--s-3); min-width: 0;
}
.wm-hero__actions {
  position: relative; display: flex; align-items: center; gap: var(--s-2);
  flex: 0 0 auto;
}

/* Второй этаж: липкий, и рост у него один и тот же всегда. */
.wm-nav__stick {
  position: sticky; top: 0; z-index: 30; background: var(--bg);
  border-bottom: 1px solid transparent;
  transition: border-color var(--t-base), box-shadow var(--t-base);
}
.wm-nav__stick .wm-nav__in { padding-top: var(--s-3); }
/* Прилипла — отделяется линией от уехавшего под неё содержимого. Больше
   этот класс не делает ничего и не должен: любое свойство, меняющее
   геометрию, вернёт feedback loop прокрутки (сторожит nav_test.go). */
.wm-nav--slim { border-bottom-color: var(--line); box-shadow: var(--shadow-1); }

/* Поле поиска — одна строка на всю колонку шапки. Настройки и заявка
   стоят в hero, углом, и делить с ними ширину здесь больше не с кем. */
/* Ряд с полем начинается там же, где логотип и заголовок. Ширину держит
   само поле (--wm-search-w): строка длиннее 660 точек читается хуже, а
   центрировать ради этого ряд — значит завести вторую ось. */
.wm-nav__row {
  display: flex; align-items: center; justify-content: flex-start; gap: var(--s-2);
  min-width: 0;
}

/* ── бренд ────────────────────────────────────────────────────────────
   Название, город и обещание — и ни одно не украшение: без них на первом
   экране оставалась эмблема, а о чём сайт — узнать неоткуда. Верхняя
   строка (имя и город) делит место с заявкой и «ещё» — wm-hero__top; сама
   же обещание-строка снизу не сжимается ради кнопок и получает всю
   ширину колонки. */
.wm-brand__row {
  display: flex; align-items: center; justify-content: flex-start;
  gap: var(--s-2); flex-wrap: wrap; min-width: 0; flex: 1 1 auto;
}
.wm-brand__link {
  display: inline-flex; align-items: center; gap: var(--s-2); flex: 0 0 auto;
  min-width: 0; text-decoration: none; color: inherit; border-radius: var(--r-sm);
}
.wm-brand__mark {
  display: block; flex: 0 0 auto; width: var(--wm-mark, 32px); height: var(--wm-mark, 32px);
}
.wm-brand__mark img { width: 100%; height: 100%; object-fit: contain; display: block; }
:root[data-theme="dark"] .wm-brand__mark {
  background: var(--logo-plate); border-radius: var(--r-sm);
  padding: 3px; box-sizing: content-box;
}
.wm-brand__name {
  font: 700 22px/1.1 var(--font); letter-spacing: -.02em; color: var(--text);
  white-space: nowrap;
}
.wm-brand__tag { font: 400 13px/1.15 var(--font); color: var(--text-3); white-space: nowrap; }
.wm-brand__claim {
  max-width: var(--wm-head-w); margin: var(--s-1) 0 0;
  font: 500 15px/1.35 var(--font); color: var(--text-2);
}

/* ── hero главной ─────────────────────────────────────────────────────
   На главной та же строка работает заголовком первого экрана, а не
   подписью бренда: за три-пять секунд она обязана сказать, что товары
   здесь собраны из Telegram-каналов. Под ней — вторая, про то, что
   одинаковое от разных продавцов сведено в одну карточку.

   Отдельного крупного поля поиска в hero нет и не будет: оно уже стоит
   этажом ниже, во всю ширину колонки. Два поля в двадцати пикселях друг
   от друга спрашивают человека, каким из них искать, — это уже было.

   Размер на clamp(), а не ступенями: между 360 и 1440 промежуточных
   ширин больше, чем ступеней, и на каждой пропущенной заголовок либо
   жмётся, либо распирает строку. */
.wm-nav__hero--home .wm-brand__claim {
  margin-top: var(--s-3);
  /* Своя мера, не абзацная: почему — в --wm-claim-w. Наследованные 660
     резали заголовок надвое на экране, где свободного места оставалось
     ещё шестьсот точек. */
  max-width: var(--wm-claim-w);
  font: 700 clamp(22px, 3.4vw, 34px)/1.15 var(--font);
  letter-spacing: -.02em; color: var(--text); text-wrap: balance;
}
.wm-hero__lead {
  max-width: var(--wm-head-w); margin: var(--s-2) 0 0;
  font: 400 15px/1.45 var(--font); color: var(--text-2); text-wrap: pretty;
}

/* ── поиск ────────────────────────────────────────────────────────────
   Поле одно на страницу. Их было два — липкое в шапке и крупное в hero, —
   и на первом экране они стояли друг под другом: два одинаковых поля
   спрашивают человека, каким из них искать. */
.wm-search {
  position: relative; display: flex; align-items: center;
  flex: 1 1 auto; width: 100%; max-width: var(--wm-search-w); min-width: 0;
}
.wm-search__ico { position: absolute; left: 13px; color: var(--text-3); pointer-events: none; }
.wm-search__in {
  width: 100%; height: var(--wm-search-h); padding: 0 44px;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--line-strong); border-radius: var(--r-md);
  /* Шестнадцать — не вкус: на меньшем кегле iOS приближает страницу,
     как только палец попадает в поле, и человек оказывается в увеличенной
     вёрстке, из которой сам не выберется. */
  font-size: 16px; -webkit-appearance: none; appearance: none;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.wm-search__in::-webkit-search-cancel-button { display: none; }
.wm-search__in::placeholder { color: var(--text-3); }
.wm-search__in:hover { border-color: var(--line-strong); }
.wm-search__in:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}
.wm-search__clear {
  position: absolute; right: 2px; width: 40px; height: 40px; display: grid;
  place-items: center; background: none; border: 0; border-radius: var(--r-sm);
  color: var(--text-3); cursor: pointer;
}
.wm-search__clear:hover { background: var(--surface); color: var(--text); }
/* Крестик подчиняется [hidden], а не спорит с ним. Правило выше объявляет
   display: grid, и оно перебивает правило браузера: модуль честно ставил
   hidden, а крестик всё равно висел в пустом поле и предлагал очистить то,
   чего нет. Договор держался в JS и не держался на экране. */
.wm-search__clear[hidden] { display: none; }

/* ── строка действий ──────────────────────────────────────────────────
   Три кнопки и ничего больше: что показать, чем сузить, где дешевле. */
.wm-bar {
  position: relative; display: flex; align-items: center; justify-content: flex-start; gap: var(--s-2);
  padding: var(--s-3) 0;
  min-width: 0; overflow-x: auto; scrollbar-width: none;
}
.wm-bar::-webkit-scrollbar { display: none; }
.wm-bar > * { flex: 0 0 auto; }
.wm-bar::after {
  content: ''; position: absolute; right: 0; top: 0; bottom: 0; width: 40px;
  pointer-events: none; background: linear-gradient(90deg, transparent, var(--bg));
  opacity: 0; transition: opacity var(--t-fast);
}
.wm-bar--more::after { opacity: 1; }
.wm-bar .k-btn { min-height: var(--tap); }
/* Счётчик наложенных фильтров: кнопка обязана отвечать, сужено ли уже. */
.wm-bar__filters { position: relative; }
.wm-bar__filters[hidden] { display: none !important; }
.wm-bar__filters[data-count]:not([data-count="0"])::after {
  content: attr(data-count); position: absolute; top: -5px; right: -5px;
  min-width: 17px; height: 17px; padding: 0 4px; border-radius: var(--r-pill);
  background: var(--accent); color: var(--accent-ink);
  font: 700 10.5px/17px var(--font); text-align: center;
}
/* Нечем сузить — кнопка гаснет, но остаётся кнопкой. Спрятать её нельзя:
   ряд из трёх действий превратился бы в ряд из двух, и человек решил бы,
   что фильтров у каталога нет вовсе. Приглушённость и площадь касания
   приходят из kit.css вместе со всем выключенным; здесь возвращается
   только курсор — kit гасит указатели целиком, и причина переставала быть
   видна. Нажатие всё равно не пройдёт: его не пускает сам disabled. */
.wm-bar__filters[disabled] { pointer-events: auto; cursor: not-allowed; }

/* Включённое действие в ряду — одним видом на все три способа сказать
   «включено». Способов действительно три, и это не избыточность:
   aria-pressed у переключателя («Цена ниже рынка»), aria-expanded у кнопки,
   которая раскрывает («Фильтры»), и класс wm-on там, где состояние ставит
   страница, а не признак доступности.

   aria-expanded здесь появился не сразу, и его отсутствие стоило дороже
   всего: «Фильтры» честно ставили себе aria-expanded="true", разметка была
   безупречна, чтец экрана доволен — а глазами кнопка не отличалась от
   ненажатой ни на телефоне, ни на настольном. Соседняя «Цена ниже рынка»
   в том же ряду загоралась, потому что ходит через aria-pressed. Разница
   в одном слове атрибута; поймать её можно только сравнив вид до и после,
   чем и занимается scripts/check-controls.mjs.

   Только --secondary: у «Категорий» тот же aria-expanded, но она залита
   акцентом целиком (.k-btn без модификатора), и эта тройка свойств
   превратила бы залитую кнопку в контурную — то есть погасила бы главное
   действие экрана ровно в тот момент, когда им пользуются. */
.wm-bar .k-btn[aria-pressed="true"],
.wm-bar .k-btn--secondary[aria-expanded="true"],
.wm-bar .k-btn.wm-on {
  border-color: var(--accent); color: var(--accent); background: var(--accent-soft);
}

/* ── заявка на канал ──────────────────────────────────────────────────
   Кнопка была пунктом в панели «ещё»: панель закрыта по умолчанию и лежит
   за тремя точками, то есть единственная дорога к пополнению каталога
   начиналась с нажатия, о котором надо догадаться. Позже она встала
   отдельным этажом под рядом действий — и вышла хуже: этаж спорил со
   счётчиком за пустое место, а сам счётчик, вырванный из строки «где ты
   находишься», повис ни к селу. Место кнопки — верхний угол hero, рядом
   с брендом: она про содержание каталога, и там же ей самое видное место.

   Акцент линией, а не заливкой: заметной кнопка быть обязана, но спорить
   с «Категориями» за главное действие экрана ей нечем.

   flex-shrink: 0 — намеренно. Сжатая кнопка не ужимает текст внутри себя,
   она просто рисует его поверх соседей: так подпись «Предложить канал»
   заезжала на бренд на 390 точках при живом промере, хотя formально влезала
   в бюджет. Здесь кнопка всегда занимает ровно свою натуральную ширину, а
   бюджет узкого экрана держит короткая подпись (.wm-cta__short) — не сжатие. */
.wm-cta {
  flex: 0 0 auto; min-width: 0;
  background: transparent; border-color: var(--accent); color: var(--accent);
}
.wm-cta:hover  { background: var(--accent-soft); border-color: var(--accent); }
.wm-cta:active { background: var(--accent-soft); }
.wm-cta__sign { font-size: 15px; line-height: 1; }
/* Две подписи вместо обрезанной одной. Показана всегда ровно одна, а имя
   для чтеца экрана задано самой кнопке: спрятанное display: none выпадает
   и из доступного имени, и кнопка осталась бы без названия на телефоне.
   Короткая подпись — одно слово: «Предложить» уже сказано знаком «＋», и
   «＋ Предложить канал» на 390 точках вместе с брендом и «ещё» не помещался
   ни при каком сжатии — только замена текста освобождала нужные пиксели. */
.wm-cta__short { display: none; }

/* ── «ещё»: язык, тема, вход ──────────────────────────────────────────
   Настройки не должны спорить с поиском за первый экран, но и прятать их
   некуда: в Telegram у приложения своих настроек нет вовсе. */
.wm-more {
  flex: 0 0 auto;
  display: grid; place-items: center; width: var(--tap); height: var(--tap);
  background: transparent; border: 1px solid transparent; border-radius: var(--r-md);
  color: var(--text-2); cursor: pointer;
}
.wm-more:hover { background: var(--surface); color: var(--text); }
/* Меню отсчитывается от строки поиска, а не от края шапки: кнопка стоит в
   строке, и раскрыться панель обязана под ней. */
.wm-menu {
  position: absolute; right: 0; top: calc(100% + var(--s-1)); z-index: 45;
  width: min(300px, 92vw); padding: var(--s-2);
  background: var(--elevated); border: 1px solid var(--line);
  border-radius: var(--r-md); box-shadow: var(--shadow-3);
}
.wm-menu__row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  min-height: var(--tap); padding: 0 var(--s-2); border-radius: var(--r-sm);
}
.wm-menu__lbl { font-size: 14px; color: var(--text-2); }
.wm-menu__sel { width: auto; min-width: 92px; }
button.wm-menu__row {
  width: 100%; background: none; border: 0; cursor: pointer; text-align: left;
  font: 550 14px/1.2 var(--font); color: var(--text);
}
button.wm-menu__row:hover { background: var(--surface); }
button.wm-menu__row.wm-on { color: var(--accent); }
.wm-menu__sep { height: 1px; background: var(--line); margin: var(--s-2) var(--s-1); }
.wm-theme { width: 40px; padding: 0; }
.wm-theme svg { display: none; }
.wm-theme svg.on { display: block; }

/* ── где я нахожусь ───────────────────────────────────────────────────
   Взамен подсвеченной вкладки: выбранный раздел и категория названы
   словами, и каждое слово — кнопка «вернуться на шаг назад». */
.wm-sub {
  display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap;
  max-width: var(--wm-wide-w); margin: 0 auto; padding: 0 0 var(--s-3);
}
.wm-crumbs {
  display: flex; align-items: center; gap: var(--s-1); flex-wrap: wrap;
  min-width: 0; font-size: 13.5px; color: var(--text-2);
}
.wm-crumbs button {
  min-height: var(--tap); padding: 0 var(--s-1); background: none; border: 0;
  border-radius: var(--r-xs); color: var(--text-2); cursor: pointer; font: inherit;
}
.wm-crumbs button:hover { color: var(--accent); text-decoration: underline; }
.wm-crumbs__sep { color: var(--text-3); font-size: 12px; }
.wm-crumbs__cur { color: var(--text); font-weight: 600; }
.wm-chips { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; min-width: 0; }

/* ── «часто ищут» ─────────────────────────────────────────────────────
   Таблички по ширине текста, одной строкой. Не сетка: у сетки колонка
   одинаковая, и короткое «Туры» растягивается до ширины «Футболок и
   кофт», а шесть равных плиток во всю ширину — это уже второй каталог.
   На телефоне ряд едет вбок и правый край гаснет: видно, что он длиннее. */
.wm-hints {
  position: relative; display: flex; align-items: center; gap: var(--s-3);
  justify-content: flex-start;
  /* Та же колонка, что у счётчика и у сетки товаров: подсказки — вход в
     выдачу, и стоять шире неё они не должны. С max-width: 100% они
     занимали всю ширину окна и на 1440 начинались левее всего
     остального. */
  max-width: var(--wm-wide-w); margin: 0 auto;
  font-size: 13.5px; color: var(--text-3);
}
.wm-hints > b { font-weight: 500; color: var(--text-3); flex: 0 0 auto; }
.wm-hints__row {
  display: flex; flex-wrap: nowrap; align-items: center; gap: var(--s-2);
  flex: 1 1 auto; min-width: 0; padding: 3px 0;
  overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
}
.wm-hints__row::-webkit-scrollbar { display: none; }
.wm-hints__row > * { flex: 0 0 auto; }
.wm-hints::after {
  content: ''; position: absolute; right: 0; top: 0; bottom: 0; width: 40px;
  pointer-events: none; background: linear-gradient(90deg, transparent, var(--bg));
  opacity: 0; transition: opacity var(--t-fast);
}
.wm-hints--more::after { opacity: 1; }
/* Ряд ждёт справочника: место занято, ничего не видно (WMNav.showHints).
   Высота — одна табличка и поля ряда: min-height кнопки плюс 2×3px. */
.wm-hints--wait { visibility: hidden; }
.wm-hints--wait .wm-hints__row { min-height: 44px; }
.wm-hints__row button {
  display: inline-flex; align-items: center; gap: var(--s-1); white-space: nowrap;
  min-height: 38px; padding: 0 var(--s-3);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md);
  color: var(--text-2); font: 550 13.5px/1 var(--font); cursor: pointer;
  transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
}
.wm-hints__row button:hover { background: var(--bg); border-color: var(--line-strong); color: var(--text); }
/* Счётчик вторичен: он подтверждает, что подсказка не ведёт в пустоту,
   но названием не является. */
.wm-hints__row button i {
  font-style: normal; color: var(--text-3); font-weight: 400; font-size: 11.5px;
}

/* ── счётчик выдачи ───────────────────────────────────────────────────
   Вторичная строка сразу перед карточками — не в ряду действий и не
   рядом с заявкой на канал, которым нечем поделиться с числом, а прямо
   там, где о числе и спрашивают: одним взглядом выше самой выдачи.
   Пустой текст ничего не должен рисовать — hidden ставит сам JS
   (WMNav.setCount), а не разметка: до первого ответа сервера и между
   перезагрузками фильтра строка пуста дольше, чем занята. */
.wm-count {
  display: block; max-width: var(--wm-wide-w); margin: 0 auto;
  padding: 0 0 var(--s-2); color: var(--text-3); font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.wm-count[hidden] { display: none; }

/* ── порядок выдачи: табы (WMNav.setSort) ─────────────────────────────
   Строкой со счётчиком: счётчик слева, табы справа; на телефоне табы
   уходят строкой ниже четырьмя равными колонками, иконка над подписью.
   Ленту вбок, как было сначала, не листали: на 390 «Популярные» стоял
   обрезанным до «По» без намёка, что за краем что-то есть (26.09.2026). */
.wm-resbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
             gap: var(--s-1) var(--s-3); min-width: 0; max-width: var(--wm-wide-w); margin: 0 auto;
             padding: 0 0 var(--s-2); }
.wm-resbar .wm-count { margin: 0; padding: 0; }
.wm-sort { display: flex; gap: var(--s-1); overflow-x: auto; scrollbar-width: none; min-width: 0;
           max-width: 100%; }
.wm-sort::-webkit-scrollbar { display: none; }
.wm-sort[hidden] { display: none; }
.wm-sort button {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; min-height: 36px;
  padding: 0 var(--s-3); border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--text-2); font: 550 13px/1 var(--font); cursor: pointer;
  transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
}
.wm-sort button:hover { border-color: var(--line-strong); color: var(--text); }
.wm-sort button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wm-sort button.wm-sort--on { background: var(--accent-soft); border-color: var(--accent-line); color: var(--text); }
.wm-sort svg { flex: 0 0 auto; }
@media (max-width: 640px) {
  .wm-resbar { flex-direction: column; align-items: stretch; }
  .wm-sort { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); overflow: visible; }
  .wm-sort[hidden] { display: none; }
  .wm-sort button {
    flex-direction: column; justify-content: center; gap: 3px; min-width: 0;
    min-height: var(--tap, 44px); padding: 6px 2px; border-radius: 12px; font-size: 12px;
  }
  .wm-sort button span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

/* Прошлые запросы — там же, где подсказки, и по тем же правилам ряда. */
.wm-recent {
  display: flex; flex-wrap: nowrap; gap: var(--s-2); align-items: center;
  max-width: var(--wm-wide-w); margin: 0 auto var(--s-3);
  overflow-x: auto; scrollbar-width: none;
}
.wm-recent::-webkit-scrollbar { display: none; }
.wm-recent > * { flex: 0 0 auto; }

/* ── телефон ──────────────────────────────────────────────────────────
   Название и город остаются — это единственное место, где написано, что
   здесь такое. Слоган hero на главной («Сравните цену и детали») и вторая
   строка под ним — нет: живой скриншот с телефона показал первый экран
   без единой карточки каталога, целиком отданный шапке и объяснению.
   На узком экране первый экран — это место, где искать, а не обещание;
   на широком, где рядом с ним есть каталог, а не выбор между ним и
   заголовком, слоган остаётся (правило выше, вне этого медиа-блока). */
@media (max-width: 559px) {
  .wm-nav__hero .wm-nav__in { padding-top: 18px; }
  .wm-brand__link { --wm-mark: 28px; }
  .wm-brand__name { font-size: 18px; }
  .wm-brand__tag { font-size: 12px; min-width: 0; white-space: normal; overflow-wrap: anywhere; }
  .wm-brand__claim { font-size: 12.5px; line-height: 1.3; }
  /* На главной заголовок первого экрана гасится целиком: место отдаётся
     каталогу. На выдаче ту же подпись бренда правило не касается — она
     мельче и не претендует на первый экран. */
  .wm-nav__hero--home .wm-brand__claim { display: none; }
  .wm-hero__lead { font-size: 13.5px; line-height: 1.4; }
  .wm-nav__hero--home .wm-hero__lead { display: none; }
  /* Подпись уходит над рядом: сбоку она съедала треть ширины, и ряду
     оставалась половина экрана. Ширину ряду она возвращает, но сама по
     себе числа табличек в кадре не решает — его решают поля ниже. */
  .wm-hints { display: block; width: 100%; }
  .wm-hints > b { display: block; margin: 0 0 var(--s-2); }
  /* На 390 точках ряд шириной 358px, а три первые таблички с прежними
     полями занимали 114.7 + 111.0 + 135.1 и два промежутка по 6px — 372.8:
     третья обрывалась на 388.8 за правым краем, и в кадре оставались две.
     Две — это не ряд, который листают, а пара кнопок. Сжимаются поля и
     кегль, не сама раскладка: ширина по-прежнему по тексту, строка одна,
     ряд по-прежнему уезжает вбок, а высота касания остаётся прежней (44px
     у пальца). С этими значениями те же три занимают 337.8 из 358. */
  .wm-hints__row { gap: var(--s-1); }
  .wm-hints__row button { padding: 0 6px; gap: var(--s-1); font-size: 12px; }
  .wm-hints__row button i { font-size: 11px; }
  /* Поля и кегль решали задачу для тех имён, на которых их мерили, но не
     для любых: «Легковые автомобили 7 211» одна занимает 179 точек, и с
     «Квартирами» и «Телефонами» рядом в кадре снова оставалось две
     (e2e nav-a-header, 390). Число табличек в кадре не должно зависеть от
     того, какие категории сегодня популярны, — поэтому у таблички потолок
     в треть ряда (минус два промежутка), и три встают всегда, на 360 и на
     390. Длинное имя не обрезается, а переносится на вторую строку внутри
     таблички: две строки по 12px (26 точек) входят в её рост (38/44), ряд
     остаётся одной строкой, и место, занятое до ответа справочника
     (.wm-hints--wait), не меняется. Слово длиннее строки — редкость, но
     ломается по букве, а не вылезает за рамку; третья строка обрезается. */
  .wm-hints__row button {
    max-width: calc((100% - 2 * var(--s-1)) / 3);
    white-space: normal; text-align: left;
  }
  .wm-hints__row button > span {
    min-width: 0; line-height: 1.1; overflow-wrap: anywhere;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    overflow: hidden;
  }
  .wm-hints__row button i { flex: none; white-space: nowrap; }
}

/* Узкий телефон: подпись кнопки короче. «Предложить Telegram-канал» на
   390 точках занимает строку целиком и выталкивает счётчик на второй
   ряд — при том, что «канал» здесь всегда телеграмный, и слово Telegram
   ничего не добавляет к сказанному. */
@media (max-width: 480px) {
  .wm-cta__long  { display: none; }
  .wm-cta__short { display: inline; }
}

/* ── низкий viewport: телефон повёрнут боком ────────────────────────────
   844×390 — самый частый случай, но правило про высоту, а не про ширину:
   такой же низкий десктопный экран занимал бы шапкой ту же долю обзора,
   а portrait-телефон (390×844, height за порогом) под него не попадает.

   На 390 точках высоты полная шапка стояла 267px — 68% обзора, до выдачи
   было видно только верхнюю кромку карточки. Здесь снята одна секция
   (фраза-обещание, вторая по значимости после названия и города — на
   стольких пикселях высоты выбирать приходится между ней и выдачей) и
   срезаны вертикальные поля sticky-этажа. Поиск, кнопка настроек, ряд
   действий и заявка на канал остаются той же высоты касания — сжимаются
   только пустые промежутки вокруг них.

   Запас нужен не только на бумаге: у настоящего пальца (@media
   pointer: coarse, ниже) ссылка бренда обязана быть тридцать восемь на
   тридцать восемь минимум, и это забирает у строки бренда лишних 12px
   сверх её собственного содержимого — их надо срезать здесь же, иначе
   на живом телефоне (isMobile+hasTouch) шапка выйдет за 55% там, где на
   мыши укладывалась.

   Геометрия внутри этого режима — такая же константа, как обычные 181px
   вне его: схлопывание (.wm-nav--slim) её не трогает ни здесь, ни там. */
@media (max-height: 430px) {
  .wm-nav__hero .wm-nav__in { padding-top: 6px; }
  .wm-brand__claim { display: none; }
  /* Пояснение hero — третье по значимости после названия и города, и на
     390 точках высоты выбирать приходится между ним и выдачей. */
  .wm-hero__lead { display: none; }
  .wm-nav__stick .wm-nav__in { padding-top: var(--s-1); }
  .wm-bar { padding: var(--s-1) 0; }
}

/* Крупный палец: добираем площадь касания там, где её не даёт текст. */
@media (pointer: coarse) {
  .wm-brand__link { min-height: var(--tap); }
  .wm-hints__row button { min-height: var(--tap); }
  .wm-hints--wait .wm-hints__row { min-height: calc(var(--tap) + 6px); }
  .wm-menu__sel { min-height: var(--tap); }
  /* Крестик очистки — тоже палец, а не мышь. Растёт только площадь: поле
     под ним прежнего роста, иначе кнопка вылезет за его края. */
  .wm-search__clear { width: var(--tap); height: var(--tap); top: 50%; transform: translateY(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .wm-nav__stick, .wm-menu, .wm-hints::after,
  .wm-search__in, .wm-hints__row button { transition: none; }
}
