/*
 * «Опись», доведённая до конца: глубина, отклик, оркестрация входа.
 *
 * ★ Отдельный файл, а не правки в site.css. Причина не в аккуратности:
 * site.css задаёт СТРУКТУРУ и должен читаться как описание раскладки. Всё, что
 * здесь, — это поведение при наведении, фокусе, прокрутке и переходе, то есть
 * ответы на действия человека. Разделение позволяет ответить на вопрос «почему
 * карточка так выглядит» одним файлом, а «почему она так себя ведёт» — другим.
 *
 * ★ Каждое движение здесь обязано что-то сообщать. Карточка поднимается —
 * значит её можно нажать. Цена подчёркивается — значит это главное в карточке.
 * Сердце пульсирует — значит действие засчитано. Движение, которое ничего не
 * сообщает, — это шум, и его тут нет.
 *
 * ВСЁ содержимое файла живёт внутри `prefers-reduced-motion: no-preference`,
 * кроме статических состояний (тень, рамка, фокус): человеку, попросившему
 * систему не двигать интерфейс, мы её не двигаем.
 */

/* ── Токены движения ─────────────────────────────────────────────────────── */

:root {
  /* Своя кривая для «подъёма»: быстрый старт, мягкая остановка. Материал так
     себя и ведёт — вещь трогают, она отзывается сразу, а замирает плавно. */
  --lift: cubic-bezier(0.2, 0.9, 0.3, 1);
  --pop: cubic-bezier(0.34, 1.56, 0.64, 1); /* с перелётом — только для «да» */

  --shadow-1: 0 1px 2px rgb(26 22 20 / 0.04), 0 2px 8px rgb(26 22 20 / 0.04);
  --shadow-2: 0 2px 4px rgb(26 22 20 / 0.06), 0 12px 28px rgb(26 22 20 / 0.10);
  --shadow-3: 0 4px 8px rgb(26 22 20 / 0.08), 0 24px 48px rgb(26 22 20 / 0.14);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    /* В темноте тень не видна — глубину даёт светлеющая поверхность. */
    --shadow-1: 0 1px 2px rgb(0 0 0 / 0.4);
    --shadow-2: 0 2px 6px rgb(0 0 0 / 0.5), 0 12px 32px rgb(0 0 0 / 0.4);
    --shadow-3: 0 4px 10px rgb(0 0 0 / 0.6), 0 24px 56px rgb(0 0 0 / 0.5);
  }
}
:root[data-theme="dark"] {
  --shadow-1: 0 1px 2px rgb(0 0 0 / 0.4);
  --shadow-2: 0 2px 6px rgb(0 0 0 / 0.5), 0 12px 32px rgb(0 0 0 / 0.4);
  --shadow-3: 0 4px 10px rgb(0 0 0 / 0.6), 0 24px 56px rgb(0 0 0 / 0.5);
}

/* ── Карточка каталога (Циан-стиль: фото сверху, текст под) ───────────────── */

.card {
  display: flex;
  flex-direction: column;
  border-radius: var(--r);
  background: var(--paper);
  border: 1px solid var(--rule-soft);
  overflow: hidden; /* фото обрезается по радиусу карточки */
  transition:
    transform 0.2s var(--lift),
    box-shadow 0.2s var(--lift),
    border-color 0.2s var(--lift);
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-2);
    border-color: var(--rule);
  }
}

/* Медиа-блок: фото во всю ширину карточки, фиксированная пропорция. Клик по нему
   ведёт на объявление (курсор-указатель), стрелки/сердце — свои цели. */
.card-media {
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--paper-2);
  overflow: hidden;
  cursor: pointer;
}

.card-strip {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
  height: 100%;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.card-strip::-webkit-scrollbar { display: none; }

.card-strip > .card-photo {
  scroll-snap-align: center;
  scroll-snap-stop: always;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.card-photo-empty {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  color: var(--ink-3);
  font-size: var(--fs-md);
}

/* Стрелки листания проявляются при наведении на медиа-блок. */
@media (hover: hover) and (pointer: fine) {
  .card-media:hover .nav-arrow { opacity: 1; }
  .card-media .nav-arrow:hover { background: var(--paper); }
}

/* Точки: активная — короткая полоска, как у Циана. Ставит `is-on` скрипт. */
.card-dots {
  position: absolute;
  left: 50%;
  bottom: 8px;
  transform: translateX(-50%);
  z-index: 2;
  display: flex;
  gap: 4px;
  padding: 5px 8px;
  border-radius: 999px;
  background: rgb(0 0 0 / 0.4);
  backdrop-filter: blur(6px);
  pointer-events: none;
}
.card-dot {
  width: 5px;
  height: 5px;
  border-radius: 999px;
  background: rgb(255 255 255 / 0.5);
  transition: width 0.2s var(--ease), background 0.2s var(--ease);
}
.card-dot.is-on { width: 16px; background: #fff; }

.card-more-shots {
  position: absolute;
  right: 8px;
  bottom: 8px;
  z-index: 2;
  padding: 3px 9px;
  border-radius: 999px;
  background: rgb(0 0 0 / 0.55);
  color: #fff;
  font-size: var(--fs-xs);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  backdrop-filter: blur(6px);
  pointer-events: none;
}

/* Цена — крупная, первая строка текста. Метро вторым. */
.card-metro { color: var(--ink); font-weight: 500; }

/* ── Стрелки листания галереи (десктоп) ──────────────────────────────────── */

/* ★ Стрелки вешает JS, а не разметка: на тач-устройстве листают пальцем, стрелки
   там лишние, и держать их в HTML значит грузить незрячим и мобильным то, что
   для них — шум. На десктопе они проявляются при наведении на снимок. Кнопки
   управляют снап-скроллером программно (site.js), листая по одному кадру. */
.nav-arrow {
  position: absolute;
  top: 50%;
  z-index: 3;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: color-mix(in srgb, var(--paper) 84%, transparent);
  backdrop-filter: blur(8px);
  color: var(--ink);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  box-shadow: var(--shadow-1);
  transform: translateY(-50%);
}
.nav-arrow--prev { left: 8px; }
.nav-arrow--next { right: 8px; }
.nav-arrow svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2.2; }

/* Плавность появления и приседание при нажатии — только когда движение
   разрешено. Под reduced-motion стрелка всё равно появляется (это не движение,
   а видимость управляющего элемента), но мгновенно и без transform. */
@media (prefers-reduced-motion: no-preference) {
  .nav-arrow {
    transition:
      opacity 0.18s var(--ease),
      background 0.18s var(--ease),
      transform 0.18s var(--lift);
  }
  @media (hover: hover) and (pointer: fine) {
    .nav-arrow:active { transform: translateY(-50%) scale(0.92); }
  }
}

/* Проявляются только на десктопе при наведении на галерею; на тач их не вешает
   сам JS, но правило hover-only — вторая линия защиты. */
@media (hover: hover) and (pointer: fine) {
  .gallery:hover .nav-arrow { opacity: 1; }
  .gallery .nav-arrow:hover { background: var(--paper); }
}
.nav-arrow:focus-visible {
  opacity: 1;
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* ★ Стрелки галереи ОБЪЯВЛЕНИЯ видны всегда (не только на hover) и крупнее —
   как в Циане. На десктопе листание мышью здесь основной способ, а спрятанное
   под наведение управление человек не находит (жалоба Егора 03.09: «нет
   стрелочек листать мышью в самой карточке»). Лента фото в карточках ВЫДАЧИ
   (`.card-media .nav-arrow`) сохраняет hover-поведение — там карточек много, и
   постоянные стрелки на каждой засорили бы сетку. На краю кадра неактивная
   сторона по-прежнему скрывается (`.nav-arrow[hidden]` ниже). Стрелки вешает JS
   только при fine-pointer, поэтому на тач этот блок ничего не показывает. */
.gallery > .nav-arrow {
  width: 44px;
  height: 44px;
  opacity: 0.9;
}
.gallery > .nav-arrow svg { width: 22px; height: 22px; }
@media (hover: hover) and (pointer: fine) {
  .gallery > .nav-arrow:hover { opacity: 1; }
}
/* На крайнем кадре соответствующая стрелка гаснет — листать дальше некуда. */
.nav-arrow[hidden] { display: none; }

/* В полноэкранном просмотре стрелки крупнее и видны всегда: наводить не на что,
   а листать десять кадров пальцем по краю экрана неудобно. */
.lightbox .nav-arrow {
  width: 48px;
  height: 48px;
  opacity: 0.85;
  background: color-mix(in srgb, var(--paper) 78%, transparent);
}
.lightbox .nav-arrow svg { width: 24px; height: 24px; }
@media (hover: hover) and (pointer: fine) {
  .lightbox .nav-arrow:hover { opacity: 1; background: var(--paper); }
}

/* ── Избранное: сердце вместо плашки ─────────────────────────────────────── */

.fav {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  min-height: 40px;
  border-radius: 999px;
  border: 0;
  background: color-mix(in srgb, #000 46%, transparent);
  backdrop-filter: blur(8px);
  color: #fff;
  box-shadow: var(--shadow-1);
  transition:
    transform 0.24s var(--pop),
    color 0.2s var(--ease),
    background 0.2s var(--ease);
}
.fav:hover { background: color-mix(in srgb, #000 62%, transparent); }
.fav:active { transform: scale(0.9); }
/* Активное избранное — красное сердце на белом кружке. */
.fav[aria-pressed="true"] { background: #fff; }
.fav[aria-pressed="true"] .fav-heart { fill: var(--brand); stroke: var(--brand); }

/* Подпись при наведении: иконки мало, а `.fav-on/.fav-off` спрятаны для читалки
   экрана и зрячему их не видно. Текст берётся из `aria-pressed`, поэтому не
   дублирует разметку карточки и не расходится с ней. На широкой кнопке
   (`.fav--wide` на странице объявления) подпись уже есть словами — там тултипа
   нет. Только hover и клавиатурный фокус, на тач-устройствах не всплывает. */
.fav:not(.fav--wide)::before {
  content: "В избранное";
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  padding: 4px 9px;
  border-radius: var(--r-sm);
  background: var(--ink);
  color: var(--paper);
  font-size: var(--fs-xs);
  font-weight: 500;
  white-space: nowrap;
  letter-spacing: 0;
  opacity: 0;
  transform: translateY(-2px);
  pointer-events: none;
  z-index: 3;
  transition: opacity 0.16s var(--ease), transform 0.16s var(--ease);
}
.fav[aria-pressed="true"]:not(.fav--wide)::before { content: "В избранном"; }
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .fav:not(.fav--wide):hover::before { opacity: 1; transform: translateY(0); }
}
@media (hover: hover) and (prefers-reduced-motion: reduce) {
  .fav:not(.fav--wide):hover::before { opacity: 1; transform: none; }
}
.fav:not(.fav--wide):focus-visible::before { opacity: 1; transform: translateY(0); }

/* Текст остаётся для читалки экрана: кнопка без имени бесполезна незрячему. */
.fav-on, .fav-off {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
/* ★ Видна ровно одна подпись по состоянию — иначе и читалка, и широкая кнопка
   объявления читают «В избранном В избранное» разом. */
.fav-on { display: none; }
.fav[aria-pressed="true"] .fav-on { display: inline; }
.fav[aria-pressed="true"] .fav-off { display: none; }

.fav-heart {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  transition: fill 0.24s var(--ease), transform 0.3s var(--pop);
}
.fav[aria-pressed="true"] .fav-heart { fill: var(--brand); stroke: var(--brand); }

@media (prefers-reduced-motion: no-preference) {
  /* Класс вешает JS на момент нажатия: анимация должна проигрываться на
     ДЕЙСТВИЕ, а не на состояние, иначе она сработает и при загрузке страницы,
     где половина карточек уже в избранном. */
  .fav.is-just-added .fav-heart { animation: heart-pop 0.42s var(--pop); }

  @keyframes heart-pop {
    0%   { transform: scale(1); }
    36%  { transform: scale(1.32); }
    62%  { transform: scale(0.92); }
    100% { transform: scale(1); }
  }

  /* Кольцо, расходящееся от сердца. Рисуется псевдоэлементом, а не сотней
     частиц: смысл — «засчитано», и одного кольца для него достаточно. */
  .fav.is-just-added::after {
    content: "";
    position: absolute;
    inset: -2px;
    border-radius: 999px;
    border: 2px solid var(--brand);
    animation: ring-out 0.6s var(--ease) forwards;
    pointer-events: none;
  }
  @keyframes ring-out {
    from { opacity: 0.7; transform: scale(1); }
    to   { opacity: 0;   transform: scale(1.7); }
  }
}

/* ── Кнопки: отклик под пальцем ──────────────────────────────────────────── */

.button, .filters button[type="submit"], .more {
  position: relative;
  overflow: hidden;
  transition:
    transform 0.2s var(--lift),
    box-shadow 0.2s var(--lift),
    background 0.2s var(--ease);
  box-shadow: var(--shadow-1);
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .button:hover, .filters button[type="submit"]:hover, .more:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-2);
  }
}
.button:active, .filters button[type="submit"]:active, .more:active {
  transform: translateY(0) scale(0.98);
}

/* Волна от точки нажатия. Координаты ставит JS через CSS-переменные — это
   единственный способ при `style-src 'self'` без `unsafe-inline`. */
@media (prefers-reduced-motion: no-preference) {
  .ripple {
    position: absolute;
    left: var(--rx, 50%);
    top: var(--ry, 50%);
    width: 8px;
    height: 8px;
    margin: -4px 0 0 -4px;
    border-radius: 999px;
    background: currentColor;
    opacity: 0.28;
    pointer-events: none;
    animation: ripple 0.62s var(--ease) forwards;
  }
  @keyframes ripple {
    to { transform: scale(28); opacity: 0; }
  }
}

/* ── Быстрые фильтры: чипы наверху ───────────────────────────────────────── */

/* ★ Правило проекта: частые фильтры и сортировки видны сразу, а не спрятаны в
   «Фильтрах». Здесь это сортировка — то, чем пользуются на каждой выдаче. */
.quick {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: 0 0 var(--sp-4);
  padding: 0;
  list-style: none;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  min-height: 36px;
  border: 1px solid var(--edge);
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink-2);
  font-size: var(--fs-sm);
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  transition:
    color 0.2s var(--ease),
    border-color 0.2s var(--ease),
    background 0.2s var(--ease),
    transform 0.2s var(--lift);
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .chip:hover { color: var(--ink); border-color: var(--ink-3); transform: translateY(-1px); }
}
.chip[aria-current="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}
.chip:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

.chip-arrow { font-size: 11px; opacity: 0.75; }

/* ── Панель фильтров ─────────────────────────────────────────────────────── */

.filters,
.filters[popover] {
  display: grid;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border: 1px solid var(--rule-soft);
  border-radius: var(--r);
  background: var(--paper-2);
  box-shadow: var(--shadow-1);
  margin-block: var(--sp-4);
}

.filters-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-4);
  align-items: end;
}

/* Первая строка — самая частая, и она отделена линией: «что и сколько комнат»
   выбирают почти всегда, остальное уточняют. */
.filters-row--primary {
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--rule-soft);
  align-items: start;
}

.field { display: grid; gap: 6px; min-width: 0; }
.field-label {
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--ink-3);
  letter-spacing: 0.01em;
}
.field input,
.field select {
  font: inherit;
  font-size: var(--fs-base);
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--edge);
  border-radius: var(--r-sm);
  padding: 9px var(--sp-3);
  min-height: 42px;
  transition: border-color 0.18s var(--ease), box-shadow 0.18s var(--ease);
}
.field input:hover, .field select:hover { border-color: var(--ink-3); }
.field input:focus-visible,
.field select:focus-visible {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent);
}

/* Пара «от — до» в одном поле: это один параметр, а не два соседних. */
.pair { display: flex; gap: 6px; }
.pair input { width: 7.5rem; }

/* ★ Пара не разрывается переносом. На телефоне `flex: 1 1 8rem` у полей
   раскидывал «от» и «до» по разным строкам, и «до» вставало рядом с площадью —
   то есть два разных параметра читались как один диапазон. */
.field--pair { flex: 1 1 100%; }
.field--pair .pair { flex-wrap: nowrap; }
.field--pair .pair input { flex: 1 1 0; min-width: 0; }

/* ── Переключатели «что снять» и «комнат» ────────────────────────────────── */

/* ★ Ссылки, а не радиокнопки. Три следствия, каждое важное: работает без JS,
   выбор копируется ссылкой, переход анимируется как переход между страницами.
   Радиокнопка потребовала бы отправки формы ради одного нажатия. */
.seg { border: 0; padding: 0; margin: 0; min-width: 0; }
.seg legend {
  padding: 0 0 6px;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--ink-3);
}
.seg-options {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.seg-option {
  display: inline-flex;
  align-items: center;
  min-height: 38px;
  padding: 7px 14px;
  border: 1px solid var(--edge);
  border-radius: var(--r-sm);
  background: var(--paper);
  color: var(--ink-2);
  font-size: var(--fs-base);
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  transition:
    color 0.16s var(--ease),
    border-color 0.16s var(--ease),
    background 0.16s var(--ease);
}
@media (hover: hover) {
  .seg-option:hover { color: var(--ink); border-color: var(--ink-3); }
}
.seg-option.is-on {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}
.seg-option:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

.filters-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  flex-wrap: wrap;
}
.filters button[type="submit"] {
  min-height: 42px;
  padding-inline: var(--sp-5);
  border-radius: var(--r-sm);
  font-weight: 600;
}
.filters-reset {
  color: var(--ink-3);
  font-size: var(--fs-sm);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
}
.filters-reset:hover { color: var(--ink); }

/* Вторичная кнопка рядом с «Показать» — «На карте». Контур, а не заливка:
   заливка чернилами тут только у главного действия. */
.button--ghost {
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--edge);
}
@media (hover: hover) {
  .button--ghost:hover { border-color: var(--ink-3); background: var(--paper-2); opacity: 1; }
}

/* ── «Ещё фильтры» — раскрывашка редких параметров ───────────────────────── */

/* Держит строку фильтров короткой: площадь и округ прячутся, пока не нужны.
   Родной `<details>` — стрелку сумматора убираем, рисуем свою подпись-ссылку. */
.filters-more { margin: 0; }
.filters-more > summary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: fit-content;
  padding: 7px 0;
  color: var(--ink-2);
  font-size: var(--fs-sm);
  font-weight: 500;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.filters-more > summary::-webkit-details-marker { display: none; }
/* Своя стрелка — поворачивается при раскрытии. */
.filters-more > summary::after {
  content: "";
  width: 7px;
  height: 7px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform 0.2s var(--ease);
}
.filters-more[open] > summary::after { transform: rotate(-135deg); }
@media (hover: hover) {
  .filters-more > summary:hover { color: var(--ink); }
}
.filters-more > summary:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: var(--r-sm); }
.filters-more[open] > .filters-row { margin-top: var(--sp-3); }

/* ── Телефон: панель прокручивается, а не растёт бесконечно ──────────────── */

/* ★ Прежняя панель занимала весь экран и не листалась: `popover` открывался
   на всю высоту, поля разъезжались, а кнопка «Показать» оказывалась за краем.
   Теперь панель — слой с ОГРАНИЧЕННОЙ высотой и собственной прокруткой, а
   кнопка прилипает к низу и видна всегда. */
@supports selector(:popover-open) {
  @media (max-width: 47rem) {
    .filters[popover]:popover-open {
      position: fixed;
      inset: auto 0 0;
      width: 100%;
      max-height: 86svh;
      margin: 0;
      border-radius: var(--r-lg) var(--r-lg) 0 0;
      overflow-y: auto;
      overscroll-behavior: contain;
      padding-bottom: calc(var(--sp-4) + env(safe-area-inset-bottom));
      box-shadow: var(--shadow-3);
      background: var(--paper);
    }
    .filters[popover]::backdrop {
      background: rgb(0 0 0 / 0.4);
    }
    .filters-actions {
      position: sticky;
      bottom: calc(var(--sp-4) * -1);
      margin: 0 calc(var(--sp-4) * -1) calc(var(--sp-4) * -1);
      padding: var(--sp-3) var(--sp-4) calc(var(--sp-4) + env(safe-area-inset-bottom));
      background: var(--paper);
      border-top: 1px solid var(--rule-soft);
    }
    .filters button[type="submit"] { flex: 1; }
    .pair input { width: 100%; }
    .filters-row { gap: var(--sp-3); }
    .field { flex: 1 1 8rem; }
  }
}

/* ── Заголовок страницы ──────────────────────────────────────────────────── */

/* Счётчик перестаёт быть строчкой под заголовком и встаёт рядом с ним: это
   не пояснение к названию, а второй факт того же уровня — сколько всего. */
h1 + .count {
  margin-top: calc(var(--sp-2) * -1);
  color: var(--ink-3);
  font-size: var(--fs-base);
  font-weight: 500;
  letter-spacing: 0.02em;
  text-transform: lowercase;
}

/* ── Пагинация и «показать ещё» ──────────────────────────────────────────── */

.more {
  display: block;
  margin: var(--sp-5) auto 0;
  min-width: 220px;
}

/* ── Оркестрация входа ───────────────────────────────────────────────────── */

/* ★ Появление по времени — ТОЛЬКО для первого экрана. Ниже работает
   scroll-driven из site.css, и это не дублирование: у них разные задачи.
   Первый экран должен собраться сам, потому что человек на него смотрит; всё
   остальное должно проявляться по мере прокрутки, потому что смотреть на
   пустое место в ожидании таймера — плохо.

   Прозрачности от нуля здесь нет нигде: ровно на этом Lighthouse поймал нас
   на этапе 9 — контент, не появившийся из-за сбоя таймлайна, невидим навсегда.
   Стартовое состояние — 0.001 от смещения, читаемый текст на месте. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .page-title,
    .page-lead,
    .quick,
    .filters {
      animation: rise 0.5s var(--lift) backwards;
    }
    .page-lead { animation-delay: 0.06s; }
    .quick     { animation-delay: 0.10s; }
    .filters   { animation-delay: 0.14s; }
  }

  @keyframes rise {
    from { transform: translateY(10px); opacity: 0.35; }
  }
}

/* ── Шапка: сжимается при прокрутке ──────────────────────────────────────── */

.site-head {
  position: sticky;
  top: 0;
  z-index: 20;
  transition: box-shadow 0.3s var(--ease), padding 0.3s var(--ease);
}
/* Тень появляется только когда под шапкой уже что-то проехало: у неподвижной
   страницы её быть не должно, иначе шапка выглядит оторванной без причины. */
.site-head.is-stuck { box-shadow: var(--shadow-1); }

/* Полоса прочитанного — на странице объявления, где есть длинный текст.
   Scroll-driven анимация: ноль слушателей прокрутки, ноль работы в JS. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    .read-bar {
      position: fixed;
      inset: 0 0 auto;
      height: 2px;
      background: var(--brand);
      transform-origin: 0 50%;
      z-index: 30;
      animation: read linear;
      animation-timeline: scroll();
    }
    @keyframes read { from { transform: scaleX(0); } to { transform: scaleX(1); } }
  }
}

/* ── Галерея объявления ──────────────────────────────────────────────────── */

/* ★ Здесь была анимация «снимок в центре кадра крупнее соседних», и её больше
   нет. Она масштабировала фотографию по ходу прокрутки, и при листании кадр
   заметно дёргался вверх-вниз — замечание Егора со скриншота 30.08. Движение
   мешало основному действию ради украшения, а собственное правило этого файла
   гласит: движение, которое ничего не сообщает, — шум.

   Галерея листается снапом, и этого достаточно: положение кадра сообщает всё
   нужное само. */

/* Листание по ОДНОМУ кадру. Без `always` быстрый смах пролистывает несколько
   снимков разом и останавливается между ними — на телефоне это читается как
   промах, а не как быстрая прокрутка. */
.gallery > img { scroll-snap-stop: always; }

/* Счётчик снимков поверх галереи: сколько всего и где мы сейчас. */
.shot-count {
  position: absolute;
  right: var(--sp-3);
  bottom: var(--sp-3);
  padding: 4px 10px;
  border-radius: 999px;
  background: rgb(0 0 0 / 0.62);
  color: #fff;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  backdrop-filter: blur(6px);
  pointer-events: none;
}

/* ── Страница объявления: две колонки ────────────────────────────────────── */

.listing--split {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-5);
  align-items: start;
}

.listing-main { min-width: 0; }

.listing-side {
  display: grid;
  gap: var(--sp-3);
  align-content: start;
  padding: var(--sp-5);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  background: var(--paper);
  box-shadow: var(--shadow-2);
}

/* ★ На узком экране порядок другой, и это не косметика. Панель решения стоит в
   разметке ПОСЛЕ галереи и фактов — на десктопе она справа, и это правильно.
   На телефоне тот же порядок отправлял цену и кнопку «Открыть в Telegram» вниз,
   под карту: человек видел десять фотографий и не видел, сколько это стоит.

   `display: contents` растворяет обёртку, дети становятся прямыми элементами
   сетки, и порядок задаётся `order`. Порядок в РАЗМЕТКЕ при этом не меняется —
   значит и в оглавлении для читалки экрана, и при обходе клавиатурой всё
   остаётся так, как задумано. */
@media (max-width: 61.999rem) {
  .listing-main { display: contents; }
  .listing--split .gallery { order: 1; }
  .listing-side { order: 2; }
  .listing--split .facts { order: 3; }
  .listing--split .where { order: 4; }

  /* Панель на телефоне — не карточка с тенью, а продолжение страницы:
     рамка вокруг всей ширины экрана выглядела бы окном в окне. */
  .listing-side {
    padding: var(--sp-4) 0 0;
    border: 0;
    border-top: 1px solid var(--rule);
    border-radius: 0;
    box-shadow: none;
    background: none;
  }
}

/* ★ Порог — 62rem, а не «десктоп вообще». Ниже него панель шириной 20rem
   отбирала бы у галереи больше, чем даёт: снимок становился меньше самой
   панели, и решение «подходит ли мне это» принималось по марке в углу. */
@media (min-width: 62rem) {
  .listing--split {
    grid-template-columns: minmax(0, 1fr) 21rem;
    gap: var(--sp-6);
  }
  .listing-side {
    position: sticky;
    /* Ниже липкой шапки, иначе панель уезжает под неё. */
    top: calc(var(--sp-6) + 40px);
  }
}

.listing-side h1 {
  margin: 0;
  font-size: var(--fs-xl);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-tight);
}

.listing-side .listing-price {
  margin: 0;
  font-size: var(--fs-3xl);
  font-weight: 600;
  letter-spacing: var(--track-display);
  font-variant-numeric: tabular-nums;
}

.side-facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-3);
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--ink-2);
  font-size: var(--fs-base);
}
.side-facts li + li::before {
  content: "·";
  margin-right: var(--sp-3);
  color: var(--ink-3);
}

/* Главное действие страницы — единственная заливка акцентом на всём сайте. */
.btn-primary {
  display: block;
  text-align: center;
  background: var(--brand);
  color: var(--on-brand);
  border: 0;
  border-radius: var(--r-sm);
  padding: 13px var(--sp-4);
  font-weight: 600;
  text-decoration: none;
  box-shadow: var(--shadow-1);
  transition: transform 0.2s var(--lift), box-shadow 0.2s var(--lift), filter 0.2s var(--ease);
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .btn-primary:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-2);
    filter: saturate(1.1);
  }
}
.btn-primary:active { transform: translateY(0) scale(0.985); }

/* ── Раскрытие контакта ──────────────────────────────────────────────────── */

.contact {
  display: grid;
  gap: var(--sp-2);
}
.contact .btn-primary { width: 100%; }

/* Раскрытый контакт: крупная строка с самим номером/логином. Появляется на месте
   кнопки, поэтому центрирована и заметна. */
.contact-result {
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--edge);
  border-radius: var(--r-sm);
  background: var(--paper-2);
  text-align: center;
  font-size: var(--fs-base);
  color: var(--ink-2);
  line-height: var(--lh);
}
.contact-result[hidden] { display: none; }
.contact-link {
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 2px solid var(--brand);
  word-break: break-word;
}
.contact-link:hover { color: var(--brand); }

/* Ссылка на исходный пост демотирована во вторичную: не заливка акцентом, а
   тихая обводка. Трафик в канал остаётся, но не спорит с «Открыть контакты». */
.contact-origin {
  display: block;
  text-align: center;
  padding: 11px var(--sp-4);
  border: 1px solid var(--edge);
  border-radius: var(--r-sm);
  color: var(--ink-2);
  text-decoration: none;
  font-weight: 500;
  transition: border-color 0.18s var(--ease), color 0.18s var(--ease);
}
@media (hover: hover) {
  .contact-origin:hover { border-color: var(--ink-3); color: var(--ink); }
}
.contact-origin:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Избранное в панели — не круглая иконка, а полноширинная кнопка со словами:
   здесь есть место, и подпись полезнее пиктограммы. */
.fav--wide {
  position: static;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  width: 100%;
  height: auto;
  padding: 11px var(--sp-4);
  border-radius: var(--r-sm);
  background: var(--paper);
  backdrop-filter: none;
}
.fav--wide .fav-on,
.fav--wide .fav-off {
  position: static;
  width: auto;
  height: auto;
  clip-path: none;
  font-size: var(--fs-base);
  font-weight: 500;
}

.listing-side .sources {
  margin: 0;
  color: var(--ink-3);
  font-size: var(--fs-sm);
}
.listing-side .contact-note {
  margin: 0;
  color: var(--ink-3);
  font-size: var(--fs-sm);
  line-height: var(--lh);
}

/* ── Галерея: лента со снапом ────────────────────────────────────────────── */

.gallery {
  position: relative;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
  /* ★ Строку грида жёстко держим в высоту контейнера (её задаёт `aspect-ratio`
     ниже). Без этого при `object-fit: contain` строка растёт под intrinsic-высоту
     портретного снимка (648×972 в ленте 648×432), сам снимок «вписывается» в этот
     переросший бокс и обрезается верхом, а не показывается целиком с полями.
     `100%` фиксирует высоту кадра, и contain letterbox'ит портрет как в Циане. */
  grid-auto-rows: 100%;
  gap: var(--sp-2);
  margin-bottom: var(--sp-5);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  border-radius: var(--r);
  /* ★ Нейтральная подложка кадра. Снимок теперь вписывается целиком
     (`object-fit: contain`), и у портретной фотографии по бокам остаются поля —
     они обязаны быть спокойным фоном, а не белым провалом. `--paper-3` — третий
     уровень поверхности (см. site.css), спокойнее фона страницы. */
  background: var(--paper-3);
  /* ★ Высоту задаёт КОНТЕЙНЕР, а не снимок. Пока пропорция стояла на самой
     картинке, широкий кадр 4:3 не дотягивался до низа ленты и под ним висела
     серая полоса в треть экрана. Соотношение 3:2 ближе к тому, как снимают
     квартиры телефоном в горизонтальной ориентации. */
  aspect-ratio: 3 / 2;
  /* Полосу прокрутки прячем: листание тут снапом, стрелками и пальцем, а
     тонкая серая черта под снимком выглядит браком вёрстки. */
  scrollbar-width: none;
}
.gallery::-webkit-scrollbar { display: none; }

.gallery > img {
  scroll-snap-align: center;
  width: 100%;
  height: 100%;
  /* ★ `contain`, а не `cover`: cover резал портретные фото (обрезал верх и низ),
     а квартиру часто снимают вертикально. Как в Циане — кадр показывается
     ЦЕЛИКОМ, по центру, с полями на нейтральном фоне контейнера. Жалоба Егора
     03.09. Лайтбокс уже был `contain` — там не трогаем. */
  object-fit: contain;
  border-radius: var(--r);
  display: block;
}
.gallery:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }

/* ★ На десктопе (мышь/тачпад) свободный скролл колесом ВНУТРИ ленты отключён:
   листание — стрелками и миниатюрами. Жалоба Егора 03.09: наведя курсор, лента
   листалась колёсиком внутри рамки, как отдельный скролл-контейнер. `hidden`, а
   не `clip`: элемент остаётся ПРОГРАММНО прокручиваемым, и `scrollTo/scrollBy`
   от стрелок и миниатюр (site.js) работают по-прежнему. На тач `overflow-x:auto`
   не трогаем — там нативный свайп пальцем остаётся единственным способом. То же
   для ленты фото в карточках выдачи (`.card-strip`) — та же раздражающая
   прокрутка колесом. */
@media (hover: hover) and (pointer: fine) {
  .gallery,
  .card-strip { overflow: hidden; }
}

/* ── Где это ─────────────────────────────────────────────────────────────── */

.where { margin-top: var(--sp-6); }
.where h2 {
  margin: 0 0 var(--sp-3);
  font-size: var(--fs-xl);
  letter-spacing: var(--track-tight);
}
.mini-map {
  height: 320px;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  overflow: hidden;
  background: var(--paper-2);
}
.where-note {
  margin: var(--sp-3) 0 0;
  color: var(--ink-3);
  font-size: var(--fs-sm);
  max-width: var(--measure);
}

/* Метка-точка для мини-карты: цены здесь нет, объявление и так одно. */
.pin--dot {
  width: 18px;
  height: 18px;
  padding: 0;
  border-radius: 50%;
  border-width: 2px;
  border-style: solid;
  border-color: var(--paper);
}
.pin--near.pin--dot { border-style: dashed; border-color: var(--brand); }

/* ── Шапка: непрозрачная, выровненная, компактная на телефоне ────────────── */

/* ★ Фон НЕПРОЗРАЧНЫЙ. Полупрозрачная плашка с `backdrop-filter` выглядит
   нарядно ровно до первой прокрутки: под ней просвечивают фотографии и карта,
   буквы шапки ложатся на чужой контент и становятся нечитаемыми. На телефоне
   `backdrop-filter` вдобавок стоит кадра — эффект, который платит собой за
   ухудшение читаемости, платит дважды.

   Полупрозрачность остаётся ТОЛЬКО там, где под шапкой заведомо ровный фон:
   этого случая у нас нет, поэтому её нет вовсе. */
.site-head {
  background: var(--paper);
  backdrop-filter: none;
  /* Выравнивание по центру, а не по базовой линии: логотип и пункты меню имеют
     разный кегль, и `baseline` опускал меню на пару пикселей ниже — глаз
     читает это как «съехало». */
  align-items: center;
  gap: var(--sp-4) var(--sp-5);
  padding-block: var(--sp-4);
  /* Тонкая линия вместо жирной чернильной: шапка липкая, и толстая граница
     через весь экран висит над контентом слишком тяжело. */
  border-bottom: 1px solid var(--rule);
}
.site-head.is-stuck {
  border-bottom-color: var(--rule);
  box-shadow: var(--shadow-1);
}

/* ── Лого со знаком-дверью + правая группа шапки (редизайн под Циан) ──────── */

.brand {
  line-height: 1;
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.brand-door {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  background: var(--brand);
  color: var(--on-brand);
}
.brand-door svg { width: 20px; height: 20px; }

.head-actions { gap: 10px; }

/* Служебные иконки-кнопки шапки: избранное (ссылка) в общем виде с темой. */
.head-icon {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 999px;
  border: 1px solid var(--edge);
  color: var(--ink-2);
  background: var(--paper);
  transition: color var(--fast) var(--ease), border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.head-icon svg { width: 20px; height: 20px; }
@media (hover: hover) {
  .head-icon:hover { color: var(--ink); border-color: var(--edge-2); background: var(--paper-2); }
}
.head-icon:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Главная кнопка шапки — «Разместить»: единственная заливка акцентом здесь. */
.head-place {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 42px;
  padding: 0 18px;
  border-radius: 999px;
  background: var(--brand);
  color: var(--on-brand);
  font-weight: 700;
  font-size: var(--fs-base);
  text-decoration: none;
  box-shadow: var(--shadow-1);
  transition: background var(--fast) var(--ease), transform var(--fast) var(--lift), box-shadow var(--fast) var(--lift);
}
.head-place svg { width: 18px; height: 18px; }
@media (hover: hover) {
  .head-place:hover { background: var(--brand-2); transform: translateY(-1px); box-shadow: var(--shadow-2); }
}
.head-place:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Гость — крупная заметная «Войти» (пилюля с обводкой), а не мелкая ссылка. */
.head-login {
  display: inline-flex;
  align-items: center;
  height: 42px;
  padding: 0 20px;
  border-radius: 999px;
  border: 1px solid var(--edge-2);
  color: var(--ink);
  font-weight: 600;
  font-size: var(--fs-base);
  text-decoration: none;
  background: var(--paper);
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease), color var(--fast) var(--ease);
}
@media (hover: hover) {
  .head-login:hover { border-color: var(--brand); color: var(--brand); background: var(--paper); }
}
.head-login:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Вошёл — аватар с инициалами + имя и «Кабинет». */
.head-avatar {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 4px 12px 4px 4px;
  border-radius: 999px;
  border: 1px solid var(--edge);
  background: var(--paper);
  text-decoration: none;
  color: var(--ink);
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
@media (hover: hover) {
  .head-avatar:hover { border-color: var(--edge-2); background: var(--paper-2); }
}
.head-avatar:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.head-ava {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--brand-2), var(--brand-2) 0%, var(--brand) 60%, #b3120f 100%);
  color: #fff;
  font-weight: 800;
  font-size: var(--fs-md);
}
.head-who {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
  font-weight: 600;
  font-size: var(--fs-sm);
  max-width: 12ch;
}
.head-who { overflow: hidden; }
.head-who small { color: var(--ink-3); font-weight: 500; font-size: var(--fs-xs); }

/* Телефон: оставляем знак, тему и вход/аватар; убираем избранное-иконку (оно в
   нижней панели), «Разместить» и подпись имени — экран узкий. */
@media (max-width: 40rem) {
  .head-fav, .head-place, .head-who { display: none; }
}

/* ── Строка разделов (как верхний ряд категорий Циана) ───────────────────── */

.cat-row {
  /* Полосой во всю ширину: разъезжается за поля body (у него боковой padding),
     чтобы линия-разделитель шла от края до края, как строка категорий Циана. */
  margin: 0 calc(var(--sp-5) * -1);
  padding: 0 var(--sp-5);
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  /* Тают края: подсказка, что за краем ещё есть разделы. Маска, а не наложенная
     плашка, — фон под ней остаётся живым, а не закрашивается. Прогрессивно:
     без поддержки просто резкий край, разделы на месте. */
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 16px, #000 calc(100% - 16px), transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, #000 16px, #000 calc(100% - 16px), transparent 100%);
}

.cat-row-track {
  display: flex;
  gap: var(--sp-2);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  /* Тянется мышью: курсор-ладонь ставит JS, когда есть что прокручивать. */
  scroll-snap-type: none;
}
.cat-row-track::-webkit-scrollbar { display: none; }
.cat-row-track.is-dragging { cursor: grabbing; user-select: none; }

.cat-link {
  flex: 0 0 auto;
  padding: var(--sp-3) var(--sp-2);
  color: var(--ink-3);
  font-size: var(--fs-base);
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  transition: color 0.16s var(--ease), border-color 0.16s var(--ease);
}
@media (hover: hover) {
  .cat-link:hover { color: var(--ink); }
}
/* Активный раздел — чернилами и линией снизу: строка отвечает «где я сейчас»,
   а не просто «куда можно пойти». */
.cat-link.is-on {
  color: var(--ink);
  border-bottom-color: var(--ink);
}
.cat-link:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; border-radius: var(--r-sm); }

/* На телефоне разделы живут внизу в `.tabbar`; верхняя строка там лишняя. */
@media (max-width: 40rem) {
  .cat-row { display: none; }
}

/* ── Переключатель темы ──────────────────────────────────────────────────── */

/* Тихая служебная кнопка: на десктопе стоит за меню у правого края, на телефоне
   уезжает вправо сама (меню там скрыто в пользу нижней панели). */
.theme-toggle {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid var(--edge);
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink-2);
  cursor: pointer;
  transition:
    color 0.2s var(--ease),
    border-color 0.2s var(--ease),
    background 0.2s var(--ease);
}
@media (hover: hover) {
  .theme-toggle:hover { color: var(--ink); border-color: var(--ink-3); background: var(--paper-2); }
}
.theme-toggle:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
/* Всегда у правого края шапки: меню уехало в строку разделов ниже, толкать
   кнопку больше некому. */
.theme-toggle { margin-left: auto; }

/* Видна иконка того, ВО ЧТО переключит: светлая тема — луна, тёмная — солнце.
   Правила зеркалят токены темы из site.css, поэтому кнопка верна до всякого JS
   и в системном режиме тоже. */
.theme-icon--sun { display: none; }
.theme-icon--moon { display: block; }
:root[data-theme="dark"] .theme-icon--sun { display: block; }
:root[data-theme="dark"] .theme-icon--moon { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-icon--sun { display: block; }
  :root:not([data-theme="light"]) .theme-icon--moon { display: none; }
}

/* На телефоне меню переносится на вторую строку и занимает её целиком —
   выровненное по левому краю, как и логотип, а не прижатое вправо. */
@media (max-width: 40rem) {
  .site-head {
    padding-block: var(--sp-3);
    gap: var(--sp-2) var(--sp-4);
  }
  .brand { font-size: var(--fs-lg); }
}

/* ── Номер позиции: тише и без красного ──────────────────────────────────── */

/* ★ Ярко-красный номер тянул на себя взгляд первым — раньше цены, ради которой
   карточку и открывают. Акцент дорог: на всём сайте он отведён главному
   действию, активному избранному и фокусу. Номер — это служебный идентификатор,
   его читают, только когда он уже понадобился. */
.card-no {
  color: var(--ink-3);
  font-weight: 400;
  letter-spacing: 0.06em;
  font-size: var(--fs-xs);
  text-transform: uppercase;
}
.card-no::after { background: var(--ink-3); }

/* ── Скелетоны для «показать ещё» ────────────────────────────────────────── */

.skeleton {
  border-radius: var(--r);
  background: var(--paper-2);
  border: 1px solid var(--rule-soft);
  padding: var(--sp-3);
  display: grid;
  gap: var(--sp-3);
}
.skeleton-shot { aspect-ratio: 4 / 3; border-radius: var(--r-sm); }
.skeleton-line { height: 12px; border-radius: 6px; }
.skeleton-line--wide { width: 70%; }
.skeleton-line--narrow { width: 40%; }

.skeleton-shot, .skeleton-line {
  background: linear-gradient(
    90deg,
    var(--rule-soft) 0%,
    color-mix(in srgb, var(--rule-soft) 45%, var(--paper)) 50%,
    var(--rule-soft) 100%
  );
  background-size: 300% 100%;
}
@media (prefers-reduced-motion: no-preference) {
  /* 1,6 с — середина диапазона, который читается как «идёт загрузка», а не
     как мигание: короче — дёргается, длиннее — кажется зависшим. Движение
     слева направо, а не пульсация: направленное ожидание субъективно короче. */
  .skeleton-shot, .skeleton-line { animation: sheen 1.6s linear infinite; }
  @keyframes sheen { to { background-position: -300% 0; } }
}

/* ── Переходы между страницами ───────────────────────────────────────────── */

@media (prefers-reduced-motion: no-preference) {
  /* Общая длительность перехода — короче, чем кажется правильным: переход
     должен подсказать связь между страницами, а не задержать чтение. */
  ::view-transition-group(root) { animation-duration: 0.26s; }

  ::view-transition-old(root) {
    animation: fade-out 0.2s var(--ease) both;
  }
  ::view-transition-new(root) {
    animation: rise-in 0.3s var(--lift) both;
  }
  @keyframes fade-out { to { opacity: 0; } }
  @keyframes rise-in {
    from { opacity: 0; transform: translateY(8px); }
  }

  /* ★ Фото и цена переезжают между страницами САМИ и потому исключены из
     общего затухания: их анимирует браузер как одну сохранившуюся вещь. */
  ::view-transition-group(hero-photo),
  ::view-transition-group(hero-price) {
    animation-duration: 0.36s;
    animation-timing-function: var(--lift);
  }
}


/* Пояснение над лентой анкет: страница выглядит как каталог, и без строки о
   том, что это встречные запросы, читалась бы как «предложения без фото». */
.lead--seekers {
  max-width: var(--measure);
  margin: 0 0 var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border-left: 2px solid var(--brand);
  background: var(--paper-2);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  color: var(--ink-2);
}

/* Поле поиска шире прочих: в нём пишут словами, а не выбирают из списка. */
.field--search { flex: 1 1 100%; }

/* ─────────────────────────────────────────────────────────────────────────────
   Возраст объявления
   ★ Сайт молчал о возрасте, при том что 90 карточек из 154 старше недели, 21
   старше месяца, самой старой 46 дней. Человек звонил по протухшему
   объявлению, слышал «сдано» и не возвращался. Молчание о возрасте обходилось
   дороже любой анимации.
   ───────────────────────────────────────────────────────────────────────── */

.card-age {
  position: absolute;
  inset-block-start: var(--sp-2);
  inset-inline-start: var(--sp-2);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 3px var(--sp-2);
  border-radius: 999px;
  /* Плашка поверх фотографии: полупрозрачная бумага, а не сплошная заливка —
     кадр под ней должен читаться. */
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: blur(6px);
  color: var(--ink-2);
  font-size: var(--fs-xs);
  line-height: 1.4;
  letter-spacing: 0.01em;
  white-space: nowrap;
  pointer-events: none;
}

/* Свежее суток — зелёная точка. Цветом сообщается ровно одно состояние, и это
   не «старое»: выделять надо редкое и хорошее, а не частое и обычное. */
.card-age-fresh {
  color: var(--ok);
  font-weight: 500;
}

.card-age-fresh::before {
  content: "";
  inline-size: 6px;
  block-size: 6px;
  border-radius: 50%;
  background: currentColor;
}

/* Старше двух недель — карточка тише соседей. Не серая и не перечёркнутая:
   объявление живое, просто менее вероятное. Фотография приглушается сильнее
   текста, потому что именно она тянет взгляд. */
.card.is-stale .card-photo {
  opacity: 0.72;
  filter: saturate(0.85);
}

.card.is-stale .card-price {
  color: var(--ink-2);
}

.card.is-stale:hover .card-photo,
.card.is-stale:focus-within .card-photo {
  opacity: 1;
  filter: none;
}

/* ─────────────────────────────────────────────────────────────────────────────
   Текст объявления
   ★ Появился 30.08. До этого страница объявления состояла из характеристик и
   карты: ни срока, ни залога, ни слова о том, что внутри. Всё, ради чего
   человек её открывал, оставалось в Telegram.
   ───────────────────────────────────────────────────────────────────────── */

.about {
  margin-block: var(--sp-5);
}

.about h2 {
  font-size: var(--fs-lg);
  margin-block-end: var(--sp-3);
}

.about-text {
  /* Переносы строк в посте значимы: автор разделяет ими условия, адрес и
     описание. `pre-wrap` сохраняет их, не превращая текст в моноширинный. */
  white-space: pre-wrap;
  max-inline-size: var(--measure);
  color: var(--ink-2);
  line-height: var(--lh-read);
  overflow-wrap: anywhere;
}

/* ─────────────────────────────────────────────────────────────────────────────
   Текст карточки — под фото, естественной высоты
   ★ Прежняя версия тянула карточки до общей высоты ряда (`grid-auto-rows: 1fr`
   + `height: 100%`), и у коротких карточек снизу зияла пустота — замечание
   Егора. Теперь фото фиксировано пропорцией (`.card-media` 4:3), а текст занимает
   ровно свою высоту; ряд выровнен по верху (`align-items: start`).
   ───────────────────────────────────────────────────────────────────────── */

.grid { align-items: start; }

.card-link {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: var(--sp-3);
  text-decoration: none;
  color: inherit;
}

.card-metro {
  color: var(--ink);
  font-weight: 500;
  font-size: var(--fs-base);
}

.card-facts {
  color: var(--ink-3);
  font-size: var(--fs-md);
}

/* ─────────────────────────────────────────────────────────────────────────────
   Просмотренные объявления
   ★ Каталог обозрим — 146 карточек, человек проходит почти весь. Отметка
   «уже смотрел» экономит ему повторные открытия; у площадок с бесконечной
   выдачей она полезна меньше, чем нам.
   ───────────────────────────────────────────────────────────────────────── */

.card.is-seen .card-price {
  color: var(--ink-2);
}

.card.is-seen .card-shot::after {
  /* Тонкая вуаль поверх снимка вместо приглушения самой картинки: так
     карточка читается как «уже видел», а не как «плохое качество». */
  content: "";
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--paper) 22%, transparent);
  pointer-events: none;
  border-radius: inherit;
}

/* При наведении вуаль уходит: человек вернулся к карточке намеренно. */
@media (hover: hover) {
  .card.is-seen:hover .card-shot::after { opacity: 0; }
  .card.is-seen .card-shot::after { transition: opacity var(--fast) var(--ease); }
}

/* Чип свежести — активный виден как выбранный, а не как соседняя ссылка.
   Зелёный тот же, что у отметки «сегодня» на карточке: одно состояние — один
   цвет, иначе человеку приходится учить палитру. */
.chip--fresh[aria-current="true"] {
  color: var(--ok);
  border-color: currentColor;
}

/* ─────────────────────────────────────────────────────────────────────────────
   Станции быстрым выбором
   ★ Замер 30.08: 94 станции на 146 карточек, три и больше только у 15. Селект
   на 91 пункт означал прокрутку вслепую, в восьми случаях из десяти — ради
   выдачи из одного объявления.
   ───────────────────────────────────────────────────────────────────────── */

.filters-row--stations {
  display: grid;
  gap: var(--sp-2);
}

.station-chips {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

/* «Выбрано» — чернилами, как у сегментов и сорт-чипов. Акцент отведён главному
   действию, фокусу и активному избранному; выбранный фильтр в их число не
   входит, иначе панель говорит на двух языках выделения. */
.chip--station.is-on {
  color: var(--paper);
  background: var(--ink);
  border-color: var(--ink);
}

/* Число рядом со станцией — сразу видно, стоит ли туда идти. Тише названия:
   это уточнение, а не сама подпись. */
.chip-count {
  margin-inline-start: var(--sp-1);
  color: var(--ink-3);
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
}

.chip--station.is-on .chip-count { color: inherit; opacity: 0.8; }

/* Подпись под полем, когда введённое значение не сработало. Не красная:
   человек не ошибся, он просто назвал место иначе, чем справочник. */
.field-note {
  font-size: var(--fs-sm);
  color: var(--ink-3);
}

.field-note--warn { color: var(--ink-2); }

/* ─────────────────────────────────────────────────────────────────────────────
   Полноэкранный просмотр фотографий
   ★ В колонке страницы снимок шириной с ладонь: разглядеть ремонт и вид из
   окна по нему нельзя, и человек уходит смотреть в Telegram — со страницы,
   где мы ему что-то предлагаем.
   ───────────────────────────────────────────────────────────────────────── */

.lightbox {
  /* Явный `position: fixed`, а не UA-дефолт модального `<dialog>`: абсолютно
     позиционированные стрелки внутри опираются на этот контейнер, и полагаться
     на неявное поведение здесь незачем. */
  position: fixed;
  inset: 0;
  inline-size: 100vw;
  block-size: 100svh;
  max-inline-size: none;
  max-block-size: none;
  margin: 0;
  padding: 0;
  border: 0;
  overflow: hidden;
  background: #000;
}

.lightbox::backdrop { background: rgb(0 0 0 / 0.7); }

.lightbox-strip {
  block-size: 100%;
  inline-size: 100%;
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  overscroll-behavior: contain;
  /* Полоса прокрутки под фото на весь экран выглядит браком: листаем стрелками,
     снапом и пальцем, а серая черта внизу тут ни к чему. */
  scrollbar-width: none;
}
.lightbox-strip::-webkit-scrollbar { display: none; }

.lightbox-strip img {
  flex: 0 0 100%;
  scroll-snap-align: center;
  /* ★ `scroll-snap-stop: always` — иначе быстрый свайп пролистывает через три
     кадра, и человек теряет место в галерее. Та же причина, что в ленте
     карточки. */
  scroll-snap-stop: always;
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
}

.lightbox-close {
  position: fixed;
  inset-block-start: max(var(--sp-3), env(safe-area-inset-top));
  inset-inline-end: var(--sp-3);
  z-index: 2;
  /* 44 px — минимальная зона нажатия: крестик меньше означает промах пальцем
     по фотографии, то есть открытие соседнего кадра вместо закрытия. */
  min-inline-size: 44px;
  min-block-size: 44px;
  border: 0;
  border-radius: 999px;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  color: var(--ink);
  font-size: var(--fs-xl);
  line-height: 1;
  cursor: pointer;
}

/* Курсор говорит, что снимок можно открыть. Без этого полноэкранный просмотр
   существует, но о нём никто не узнаёт. */
.gallery > img { cursor: zoom-in; }

/* ─────────────────────────────────────────────────────────────────────────────
   Нижняя панель разделов (телефон)
   ★ Пять пунктов меню строкой в шапке на 390 px переносились в две строки и
   съедали первый экран, а до самого частого действия — «вернуться в каталог» —
   надо было тянуться в верхний край экрана.
   ───────────────────────────────────────────────────────────────────────── */

.tabbar { display: none; }

@media (max-width: 40rem) {
  .tabbar {
    position: fixed;
    inset: auto 0 0;
    z-index: 40;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    /* Непрозрачный фон, а не размытие: полупрозрачная панель просвечивала
       карточками — то же замечание, что было к шапке. */
    background: var(--paper);
    border-top: 1px solid var(--rule);
    padding-block-end: env(safe-area-inset-bottom);
    transition: transform var(--mid) var(--ease);
  }

  .tabbar a {
    display: grid;
    justify-items: center;
    gap: 2px;
    /* 56 px по высоте: 44 — минимум для пальца, плюс место под подпись. */
    min-block-size: 56px;
    padding-block: var(--sp-2);
    color: var(--ink-3);
    text-decoration: none;
    font-size: var(--fs-xs);
  }

  .tabbar a[aria-current="page"] { color: var(--brand); }
  .tabbar-icon { font-size: var(--fs-lg); line-height: 1; }

  /* Прячется при прокрутке вниз — экран телефона отдаётся содержимому.
     Возвращается на первом же движении вверх: класс ставит craft.js. */
  .tabbar.is-hidden { transform: translateY(100%); }

  /* Место под панель, иначе она накрывает подвал и последнюю карточку. */
  body { padding-bottom: calc(56px + env(safe-area-inset-bottom)); }

  /* Строка разделов на телефоне не нужна: те же разделы внизу в `.tabbar`, а две
     навигации сразу — выбор без причины. Скрывает её собственное правило
     `.cat-row` выше; здесь только компактная шапка со знаком и темой. */
  .site-head { padding-block: var(--sp-3); }
}

@media (prefers-reduced-motion: no-preference) {
  /* Полноэкранный просмотр открывается ростом от центра, а не мгновенной
     подменой экрана: подмена читается как переход на другую страницу, и
     человек ищет кнопку «назад» вместо того, чтобы закрыть. 180 мс — ровно
     столько, чтобы связь «нажал на снимок → он вырос» была видна. */
  .lightbox[open] {
    animation: lightbox-in 0.18s var(--ease);
  }

  @keyframes lightbox-in {
    from { opacity: 0; transform: scale(0.96); }
    to   { opacity: 1; transform: none; }
  }
}

/* ★ WCAG 2.2, 2.4.11 «фокус не перекрыт». Нижняя панель на телефоне
   зафиксирована поверх содержимого, и элемент, получивший фокус у нижнего края
   экрана, оказывался под ней: человек, идущий по странице табом, не видел, где
   он находится.

   `scroll-margin-bottom` заставляет браузер прокручивать чуть дальше, оставляя
   сфокусированный элемент над панелью. Липкая шапка требует того же сверху. */
@media (max-width: 40rem) {
  :focus {
    scroll-margin-block-end: calc(56px + var(--sp-4) + env(safe-area-inset-bottom));
    scroll-margin-block-start: calc(var(--sp-6) + 40px);
  }
}

/* ─────────────────────────────────────────────────────────────────────────────
   Красные акценты (Циан-энергия)
   ★ Направление сменено на Циан: активные состояния подсвечиваются красным, а не
   чернилами. Егор снял прежнее ограничение «акцент только действию».
   ───────────────────────────────────────────────────────────────────────── */

/* Активный раздел в строке категорий — красный текст и линия. */
.cat-link.is-on {
  color: var(--brand);
  border-bottom-color: var(--brand);
}

/* Активный сегмент («Квартиру», выбранная комнатность) — красная заливка. */
.seg-option.is-on {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--on-brand);
}

/* Активный чип сортировки/свежести и выбранная станция — красным. */
.chip[aria-current="true"],
.chip--fresh[aria-current="true"],
.chip--station.is-on {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--on-brand);
}
.chip--station.is-on .chip-count { color: inherit; opacity: 0.85; }

/* Ссылки пагинации — акцентом, а не браузерным синим. */
.pagination a,
.crumbs a:hover {
  color: var(--brand);
}
.pagination a { text-decoration: none; font-weight: 500; }
.pagination a:hover { text-decoration: underline; }

/* Кнопка «Показать N» — главная, красной заливкой (Циан CTA). */
.filters button[type="submit"] {
  background: var(--brand);
  color: var(--on-brand);
  border: 0;
}
.filters button[type="submit"]:hover { filter: brightness(1.08); }

/* ─────────────────────────────────────────────────────────────────────────────
   Компактная строка фильтров на десктопе (Циан)
   ★ Прежняя панель разворачивалась в высокий столбец на пол-экрана до карточек —
   замечание Егора. На широком экране растворяем строки-обёртки и кладём контролы
   одной лентой: поиск сверху во всю ширину, под ним тип/комнаты/цена/метро в ряд.
   ───────────────────────────────────────────────────────────────────────── */
@media (min-width: 48rem) {
  .filters,
  .filters[popover] {
    display: flex;
    flex-wrap: wrap;
    align-items: end;
    gap: var(--sp-3) var(--sp-4);
  }
  /* Строки-обёртки растворяются — их дети становятся прямыми элементами ленты. */
  .filters-row,
  .filters-row--primary { display: contents; }

  .field--search { flex: 1 1 100%; }
  .field { flex: 0 1 auto; }
  .filters .seg { flex: 0 0 auto; }
  .field--pair { flex: 0 1 auto; }
  .pair input { width: 6.5rem; }
  .field input[type="text"] { width: 11rem; }

  /* Станции и «Ещё фильтры» — на всю ширину под основным рядом. */
  .filters-row--stations,
  .filters-more { flex: 1 1 100%; }

  .filters-actions { flex: 1 1 100%; margin-top: var(--sp-2); }

  /* Компактные подписи полей — тоньше, ближе к Циану. */
  .field-label,
  .seg legend { font-size: var(--fs-xs); margin-bottom: 2px; }
}

/* ── Панель помощи ───────────────────────────────────────────────────────────
 *
 * Кнопка-пузырь + слайд-ин <dialog> справа. Модаль (showModal) даёт фокус-ловушку
 * и Escape даром; слайд и анимация фона — из гайда top-layer (@starting-style +
 * allow-discrete + overlay).
 */

.help-fab {
  position: fixed;
  /* Выше таббара (тоже z-index 40): порядок не должен зависеть от места в DOM. */
  z-index: 41;
  right: var(--sp-4);
  bottom: var(--sp-4);
  width: 52px;
  height: 52px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--brand);
  color: var(--on-brand);
  border: 0;
  cursor: pointer;
  box-shadow: 0 4px 16px rgb(0 0 0 / 0.24);
  transition: transform var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
@media (hover: hover) {
  .help-fab:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgb(0 0 0 / 0.28); }
}
.help-fab:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
/* На телефоне — выше нижней панели разделов, чтобы её не перекрывать. Таббар
   добавляет env(safe-area-inset-bottom); без того же слагаемого пузырь на
   notched-устройствах заезжал бы на последнюю вкладку. */
@media (max-width: 40rem) {
  .help-fab { bottom: calc(var(--sp-4) + 60px + env(safe-area-inset-bottom)); }
}

.help-panel {
  /* Модаль по умолчанию центрируется — прижимаем вправо во всю высоту. */
  margin: 0 0 0 auto;
  /* svh, а не dvh: dvh дёргается при появлении/скрытии адресной строки на
     мобиле — панель прыгала бы при скролле FAQ. Так же сделан лайтбокс. */
  height: 100svh;
  max-height: 100svh;
  width: min(360px, 100vw);
  max-width: 100vw;
  padding: 0;
  border: 0;
  border-left: 1px solid var(--rule);
  border-radius: 0;
  background: var(--paper);
  color: var(--ink);
  box-shadow: -8px 0 32px rgb(0 0 0 / 0.18);
  overflow: hidden;
  /* Закрытое состояние — уехала за правый край. */
  transform: translateX(100%);
  transition:
    transform 0.3s var(--ease),
    display 0.3s allow-discrete,
    overlay 0.3s allow-discrete;
}
.help-panel[open] {
  transform: translateX(0);
  @starting-style { transform: translateX(100%); }
}
.help-panel::backdrop {
  background: rgb(0 0 0 / 0);
  transition:
    display 0.3s allow-discrete,
    overlay 0.3s allow-discrete,
    background-color 0.3s var(--ease);
}
.help-panel[open]::backdrop {
  background: rgb(0 0 0 / 0.4);
  @starting-style { background: rgb(0 0 0 / 0); }
}
@media (prefers-reduced-motion: reduce) {
  .help-panel,
  .help-panel::backdrop { transition-duration: 0.01s; }
  .help-panel,
  .help-panel[open] { transform: none; }
}

.help-panel .help-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-4);
  border-bottom: 1px solid var(--rule);
}
.help-head h2 { margin: 0; font-size: var(--fs-xl); letter-spacing: var(--track-tight); }
.help-close {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 0;
  background: none;
  color: var(--ink-2);
  cursor: pointer;
  border-radius: var(--r-sm);
}
@media (hover: hover) { .help-close:hover { background: var(--paper-2); color: var(--ink); } }
.help-close:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }

.help-body {
  padding: var(--sp-4);
  height: calc(100svh - 65px);
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.help-q { border: 1px solid var(--rule); border-radius: var(--r-sm); }
.help-q > summary {
  list-style: none;
  cursor: pointer;
  padding: var(--sp-3) var(--sp-4);
  font-weight: 500;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
}
.help-q > summary::-webkit-details-marker { display: none; }
.help-q > summary::after {
  content: "⌄";
  color: var(--ink-3);
  transition: transform var(--fast) var(--ease);
}
.help-q[open] > summary::after { transform: rotate(180deg); }
.help-q[open] > summary { border-bottom: 1px solid var(--rule-soft); }
.help-q > summary:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.help-q p {
  margin: 0;
  padding: var(--sp-3) var(--sp-4);
  color: var(--ink-2);
  font-size: var(--fs-sm);
  max-width: none;
  line-height: 1.5;
}

.help-support {
  margin-top: var(--sp-2);
  text-align: center;
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-sm);
  background: var(--ink);
  color: var(--paper);
  text-decoration: none;
  font-weight: 500;
}
@media (hover: hover) { .help-support:hover { opacity: 0.9; } }
.help-support:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* ═════════════════════════════════════════════════════════════════════════════
   ГЛАВНАЯ ПОД ЦИАН: фото-герой, панель поиска, полоса доверия
   Редизайн 03.09 по артефакту, одобренному Егором. Фон героя — локальный asset
   (CSP запрещает внешние картинки и инлайновые стили).
   ═══════════════════════════════════════════════════════════════════════════ */

/* Герой во всю ширину контента (за боковые поля body, как строка разделов). */
.hero {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  min-height: min(560px, 74vh);
  margin: 0 calc(var(--sp-5) * -1);
  overflow: hidden;
}

/* Фото + затемняющий оверлей. image-set отдаёт webp тем, кто умеет; jpg — фолбэк
   первой строкой (её видит браузер без image-set). Позиция 42% сверху держит в
   кадре светлый акцент справа-вверху. */
.hero-media {
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: url("/static/hero/hero.jpg");
  background-image: image-set(url("/static/hero/hero.webp") type("image/webp"),
                              url("/static/hero/hero.jpg") type("image/jpeg"));
  background-size: cover;
  background-position: center 42%;
}
.hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--hero-tint);
}

.hero-inner {
  position: relative;
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: clamp(40px, 6vw, 72px) var(--sp-5) clamp(36px, 4vw, 56px);
}

.hero-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
  color: #fff;
  font-weight: 600;
  font-size: var(--fs-sm);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.92;
}
.hero-pip {
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: var(--brand);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand) 30%, transparent);
}

.hero .hero-title {
  margin: 0;
  max-width: 16ch;
  color: #fff;
  font-size: clamp(32px, 5vw, 58px);
  line-height: 1.02;
  font-weight: 800;
  letter-spacing: -0.03em;
  text-wrap: balance;
  text-shadow: 0 2px 40px rgba(0, 0, 0, 0.35);
}
.hero-em { color: var(--brand-2); }

.hero .hero-lead {
  margin: 16px 0 0;
  max-width: 52ch;
  color: rgba(255, 255, 255, 0.86);
  font-size: clamp(16px, 1.7vw, 20px);
}

/* Панель поиска — стеклянная плашка поверх фото. */
.hero .hero-filter {
  /* ★ Поднимаем весь блок поиска НАД пресетами. `backdrop-filter` уже создаёт
     стекинг-контекст и у панели, и у каждого пресета; пресеты — сиблинги ПОСЛЕ
     формы в `.hero-inner`, поэтому без явного z-index они рисуются поверх
     выпадающей панели дропдауна (сквозь неё видно пилюлю «Снять 2-комнатную» —
     жалоба Егора 03.09). Позиционирование обязательно, иначе z-index не
     применяется; панель дропдауна (`.drop-panel`, z-index:30) поднимается вместе
     со всей формой. Число 20 безопасно против глобальной шкалы (таббар 40,
     лайтбокс 41): весь `.hero` изолирован `isolation: isolate` выше по файлу,
     так что z-index:20 живёт ВНУТРИ его контекста и с ними не конкурирует. */
  position: relative;
  z-index: 20;
  margin: 30px 0 0;
  max-width: 900px;
  padding: 14px;
  background: color-mix(in srgb, var(--paper) 82%, transparent);
  backdrop-filter: blur(16px);
  border: 1px solid color-mix(in srgb, #fff 12%, transparent);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-3);
}
.hero .hero-drops {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 12px;
}

/* Дропдаун-пилюля с аккуратным SVG-шевроном (правка «тупорылой стрелки»). */
.hero .drop > summary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 44px;
  min-height: 44px;
  padding: 0 16px;
  border: 1px solid var(--edge-2);
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  font-weight: 600;
}
.hero .drop > summary::after { content: none; }
.drop-cap { color: var(--ink-3); font-weight: 500; font-size: var(--fs-sm); }
.drop-val { font-weight: 600; font-size: var(--fs-base); }
.drop-chev {
  width: 16px; height: 16px;
  fill: none; stroke: var(--ink-3); stroke-width: 2.2;
  stroke-linecap: round; stroke-linejoin: round;
  transition: transform var(--fast) var(--ease);
}
.hero .drop[open] > summary { border-color: var(--brand); }
.hero .drop[open] > summary .drop-chev { transform: rotate(180deg); }

.hero .hero-search {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: stretch;
  margin: 0;
}
.hero-search-field {
  flex: 1 1 20rem;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  height: 56px;
  padding: 0 18px;
  border: 1px solid var(--edge-2);
  border-radius: 14px;
  background: var(--paper);
}
.hero-search-ic { flex: none; width: 22px; height: 22px; fill: none; stroke: var(--ink-3); stroke-width: 2; }
.hero .hero-search-field input {
  flex: 1;
  min-width: 0;
  min-height: auto;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  font-weight: 500;
  font-size: var(--fs-lg);
  outline: none;
}
.hero .hero-search-field input::placeholder { color: var(--ink-3); }
.hero-map {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 56px;
  padding: 0 20px;
  border: 1px solid var(--edge-2);
  border-radius: 14px;
  background: var(--paper);
  color: var(--ink);
  font-weight: 600;
  text-decoration: none;
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.hero-map svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.9; }
@media (hover: hover) { .hero-map:hover { border-color: var(--ink-3); background: var(--paper-2); } }
.hero .hero-search .hero-go {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 56px;
  min-height: 56px;
  padding: 0 30px;
  border-radius: 14px;
  background: var(--brand);
  color: var(--on-brand);
  font-weight: 700;
  font-size: var(--fs-lg);
}
.hero .hero-search .hero-go svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2.4; }
@media (hover: hover) { .hero .hero-search .hero-go:hover { background: var(--brand-2); opacity: 1; } }

/* Пресеты-пилюли поверх фото — стеклянные, без чисел. */
.hero .quick-strip { margin-top: 22px; }
.hero .preset {
  display: inline-flex;
  align-items: center;
  height: 40px;
  padding: 0 16px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--paper) 52%, transparent);
  backdrop-filter: blur(10px);
  border: 1px solid color-mix(in srgb, #fff 16%, transparent);
  color: #fff;
  font-weight: 600;
  font-size: var(--fs-sm);
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
@media (hover: hover) { .hero .preset:hover { background: var(--brand); border-color: var(--brand); } }
.hero .preset:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

@media (max-width: 40rem) {
  .hero { min-height: 0; }
  .hero .hero-title { font-size: clamp(28px, 8vw, 40px); }
  .hero .hero-filter { padding: 10px; }
  .hero .hero-search .hero-go { flex: 1; justify-content: center; }
}

/* ── Полоса доверия ──────────────────────────────────────────────────────── */
.trust {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin: var(--sp-6) 0 0;
}
.trust-item {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 20px 22px;
  border: 1px solid var(--edge);
  border-radius: var(--r);
  background: var(--paper-2);
  transition: transform var(--fast) var(--lift), box-shadow var(--fast) var(--lift), border-color var(--fast) var(--ease);
}
@media (hover: hover) {
  .trust-item:hover { transform: translateY(-2px); box-shadow: var(--shadow-2); border-color: var(--edge-2); }
}
.trust-ic {
  display: grid;
  place-items: center;
  flex: none;
  width: 52px;
  height: 52px;
  border-radius: 14px;
  background: linear-gradient(140deg, var(--brand-2), #b3120f);
  color: #fff;
  box-shadow: 0 6px 18px color-mix(in srgb, var(--brand) 30%, transparent);
}
.trust-ic svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.trust-text b { display: block; font-family: var(--font-display); font-weight: 800; font-size: var(--fs-lg); letter-spacing: -0.01em; }
.trust-text span { color: var(--ink-2); font-size: var(--fs-md); }
@media (max-width: 47rem) { .trust { grid-template-columns: 1fr; } }

/* ── Лента «Свежие объявления»: заголовок + «Все объявления» ──────────────── */
.feed { margin-top: var(--sp-6); }
.feed-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}
.feed-head h2 { margin: 0; }
.see-all {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--brand);
  font-weight: 700;
  text-decoration: none;
}
.see-all svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 2.4; }
@media (hover: hover) { .see-all:hover { color: var(--brand-2); } }

/* Карточки — чуть мягче радиус под Циан (разметка не тронута). */
.card { border-radius: var(--r-lg); }

/* ── Галерея объявления: лента миниатюр под кадром ────────────────────────── */
/* Когда JS добавил миниатюры сразу под галереей, большой нижний отступ галереи
   лишний — прижимаем ленту к кадру. */
.gallery:has(+ .thumbs) { margin-bottom: 12px; }
.thumbs {
  display: flex;
  gap: 10px;
  margin: 0 0 var(--sp-5);
  padding-bottom: 2px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.thumbs::-webkit-scrollbar { display: none; }
.thumb {
  flex: none;
  width: 96px;
  aspect-ratio: 4 / 3;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 12px;
  overflow: hidden;
  background: var(--paper-3);
  opacity: 0.58;
  cursor: pointer;
  transition: opacity 0.16s var(--ease), border-color 0.16s var(--ease);
}
.thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.thumb.is-on { opacity: 1; border-color: var(--brand); }
@media (hover: hover) { .thumb:hover { opacity: 1; } }
.thumb:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
