/* ── Токены ───────────────────────────────────────────────────────────── */
:root {
  --bg: #0b0e14;
  --bg-soft: #121722;
  --surface: #161c28;
  --surface-2: #1c2433;
  --line: #263145;
  --text: #e6edf6;
  --text-dim: #93a1b8;
  --text-mute: #64748b;
  --accent: #38bdf8;
  --accent-strong: #0ea5e9;
  --hot: #fb7185;
  --hot-soft: rgba(251, 113, 133, .14);
  --ok: #34d399;
  --warn: #fbbf24;
  /*
   * Вуаль «прожектора». На светлой теме она заметно легче: там затемнение
   * читается как тень, а не как выключенный свет, и плотность тёмной темы
   * превращала бы страницу в чёрный экран с одной карточкой.
   */
  --dim: rgba(4, 7, 12, .55);
  --radius: 14px;
  --radius-sm: 9px;
  --shadow: 0 12px 34px rgba(0, 0, 0, .38);
  --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

/*
 * Светлая тема включается двумя путями: системной настройкой и кнопкой в шапке
 * (`data-theme` на `<html>`, ставит app.js). Набор значений поэтому написан
 * дважды — CSS не умеет применять один блок к селектору и медиазапросу сразу.
 * Меняете значение — меняйте в обоих местах.
 *
 * `:not([data-theme='dark'])` в медиазапросе обязателен: без него выбранная
 * вручную тёмная тема слетала бы обратно на светлую у тех, у кого система светлая.
 */
@media (prefers-color-scheme: light) {
  :root:not([data-theme='dark']) {
    --bg: #f4f7fb;
    --bg-soft: #ffffff;
    --surface: #ffffff;
    --surface-2: #f1f5f9;
    --line: #dfe6f0;
    --text: #0f172a;
    --text-dim: #475569;
    --text-mute: #7c8ba1;
    --shadow: 0 10px 28px rgba(15, 23, 42, .08);
    --dim: rgba(15, 23, 42, .34);
  }
}

:root[data-theme='light'] {
  --bg: #f4f7fb;
  --bg-soft: #ffffff;
  --surface: #ffffff;
  --surface-2: #f1f5f9;
  --line: #dfe6f0;
  --text: #0f172a;
  --text-dim: #475569;
  --text-mute: #7c8ba1;
  --shadow: 0 10px 28px rgba(15, 23, 42, .08);
  --dim: rgba(15, 23, 42, .34);
}

* { box-sizing: border-box; }

html {
  /*
   * Место под вертикальную полосу прокрутки резервируется всегда. Без этого
   * переключение видов меняло высоту страницы, полоса появлялась и исчезала,
   * и содержимое дёргалось по горизонтали — поля слева и справа переставали
   * совпадать.
   */
  scrollbar-gutter: stable;

  /*
   * Переход по якорю останавливается ниже липкой шапки, а не под ней:
   * ссылка «Подробнее» из подвала вела на `/about#hold`, и шапка накрывала
   * заголовок раздела. `--topbar-h` ставит JS на одностраничнике; на серверных
   * страницах его нет, поэтому запасное значение — высота их шапки.
   */
  scroll-padding-top: calc(var(--topbar-h, 72px) + 14px);
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

body {
  background-image:
    radial-gradient(720px 420px at 82% -8%, rgba(56, 189, 248, .13), transparent 65%),
    radial-gradient(560px 340px at 6% 4%, rgba(251, 113, 133, .09), transparent 60%);
  background-attachment: fixed;
  min-height: 100vh;
}

/* ── Шапка ────────────────────────────────────────────────────────────── */
.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}

.topbar__inner {
  max-width: 1440px;
  margin: 0 auto;
  padding: 14px 22px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.topbar__left {
  display: flex;
  align-items: center;
  gap: 18px;
  min-width: 0;
}

/*
 * Итоги занимают всё свободное место между названием и выбором языка
 * и центрируются в нём — поэтому лежат прямо в `.topbar__inner`, а не внутри
 * левой группы.
 *
 * Блок остаётся строчным потоком, а не flex-контейнером: во flex каждое слово
 * между кликабельными кнопками становится отдельным элементом, и строка
 * начинает жаться и рваться. Пробовали — текст сжался.
 */
.topbar__stats {
  flex: 1;
  min-width: 0;
  margin: 0;
  text-align: center;
  line-height: 34px;
  font-size: 13px;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/*
 * Итоги набраны одним серым: это фон, а не заголовок. Цветные вставки
 * и подчёркивания рябили в шапке и спорили с ценами в выдаче.
 * НЕ добавлять сюда ни подчёркивание, ни акцентный цвет — пробовали дважды.
 */
.topbar__stats b { font-weight: 650; }

/* Кликабельна вся строка целиком — она вся про одно предложение.
   Кликабельность выдают курсор и подсветка, не декор. */
.stat-line {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.stat-line:hover { color: var(--text); }

@media (max-width: 820px) {
  .topbar__stats { display: none; }
}

.brand {
  display: inline-flex;
  align-items: center;
  /* Крыло само по себе с воздухом по краям — большой зазор отрывал бы от него текст */
  gap: 4px;
  text-decoration: none;
  color: var(--text);
  font-size: 19px;
  letter-spacing: -.02em;
}

/*
 * Логотип-крыло. Прозрачный PNG, а не плашка с градиентом: фон у исходника
 * чёрный, и на светлой теме он проступал бы тёмным прямоугольником. Прозрачность
 * сделана по яркости — неон остаётся, фон уходит (см. CLAUDE.md).
 */
.brand__logo {
  width: auto;
  height: 46px;
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--accent) 45%, transparent));
}

@media (prefers-color-scheme: light) {
  /*
   * Светло-голубой неон на белом почти не виден: рисунок задуман светящимся
   * на чёрном. Притемняем и добавляем насыщенности, чтобы линии читались,
   * а не выцветали в фон.
   */
  .brand__logo {
    filter: saturate(1.5) brightness(.78) drop-shadow(0 1px 2px rgba(12, 74, 110, .35));
  }
}

.brand__stack {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1px;
  /*
   * Высота задана заранее и не зависит от текста: слоганы разной длины, и без
   * этого смена «Свобода в цене» на «Идеальный день для идеальной цены» дёргала
   * бы шапку, а вместе с ней и всю страницу под липким заголовком.
   */
  min-height: 40px;
}

.brand__text {
  font-weight: 700;
  letter-spacing: .14em;
  font-size: 17px;
}

/*
 * Слоган. Сменяется сам: старый уходит вниз и гаснет, новый приходит сверху.
 * Полоса под названием фиксированной ширины — иначе соседние элементы шапки
 * ездили бы туда-сюда на каждой смене.
 */
.brand__slogan {
  display: block;
  width: 240px;
  font-size: 11.5px;
  line-height: 1.2;
  color: var(--text-mute);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: opacity .3s ease, transform .3s ease;
}

/* Уходит вниз */
.brand__slogan.is-out { opacity: 0; transform: translateY(9px); }

/*
 * Исходное положение нового — выше строки и невидимо. Переход отключён
 * намеренно: иначе браузер анимировал бы и «перелёт» наверх, и слоган
 * пролетал бы через всю строку вместо появления сверху.
 */
.brand__slogan.is-pre { opacity: 0; transform: translateY(-9px); transition: none; }

@media (prefers-reduced-motion: reduce) {
  .brand__slogan { transition: opacity .3s ease; }
  .brand__slogan.is-out, .brand__slogan.is-pre { transform: none; }
}

/* На узком экране в шапке и так тесно — слоган уступает место кнопкам */
@media (max-width: 860px) {
  .brand__slogan { display: none; }
  .brand__stack { min-height: 0; }
}

.topbar__meta { display: flex; align-items: center; gap: 12px; }

/* Приложения — в шапке, правее выбора языка, по центру по вертикали */
.apps { display: flex; align-items: center; gap: 4px; }

.apps__btn {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-dim);
  cursor: pointer;
  transition: all .15s;
}

.apps__btn:hover { border-color: var(--accent); color: var(--accent); }

@media (max-width: 720px) {
  .apps { display: none; }
}

/* Бейдж планировщика и кнопка «Обновить сейчас» убраны из шапки 26.07.2026:
   состояние обхода читается через GET /api/crawl, ручной запуск — POST /api/refresh.
   В шапке теперь валюта — она меняет все цены на экране разом. */

/* ── Раскладка ────────────────────────────────────────────────────────── */
/*
 * Одна колонка. Панель-анкета на 336px убрана: выдача приходит за десятки
 * миллисекунд, и держать ради неё треть экрана под форму нечем оправдать.
 * Параметры живут в строке пилюль, подробности — в поповерах.
 */
.app {
  max-width: 1440px;
  margin: 0 auto;
  /* Снизу немного: подвал стоит близко к содержимому, пустой полосы между
     ними быть не должно. Запас под приколотые панели даёт сам подвал. */
  padding: 18px 22px 20px;
}

/* ── Строка параметров ────────────────────────────────────────────────── */
/*
 * Строка параметров тянется во всю ширину: пилюли делят её между собой, а не
 * жмутся влево, оставляя пустое место справа. Растут все, кроме «Сбросить» —
 * она появляется по ходу дела, и если бы тянулась вместе со всеми, то при
 * появлении сдвигала бы всю строку и уезжала на второй ряд.
 */
.searchbar {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 8px;
  margin-bottom: 14px;
}

/*
 * Ширины заданы жёстко и не зависят от содержимого. Тянущиеся пилюли выглядели
 * живо ровно до первого действия: выбрал страну — подпись стала длиннее, соседи
 * ужались, вся строка перекроилась. Параметры не должны прыгать под курсором.
 */
/*
 * Ширины подобраны так, чтобы на 1400 px строка держалась в один ряд вместе
 * с флажками и «Сбросить». Меняете числа — проверьте, что кнопка не уехала
 * на второй ряд: место под неё зарезервировано, но лишних 50 px там нет.
 */
.searchbar > .pill { flex: 0 0 auto; }
.searchbar > #pillOrigin,
.searchbar > #pillDest { width: 232px; }
.searchbar > #pillWhen { width: 202px; }
.searchbar > #pillBudget { width: 182px; }
.searchbar > #pillCurrency { width: 142px; }
.searchbar > .pill .pill__main { width: 100%; }

/*
 * «Сбросить» держит своё место всегда, даже пока не нужна: `display: none`
 * заставлял бы строку перекраиваться в момент появления кнопки — то есть ровно
 * тогда, когда человек только что менял параметры и смотрит на это место.
 */
/* `!important` здесь не каприз: общий `.is-hidden` объявлен с ним же (см. низ файла) */
.searchbar > .pill--reset.is-hidden {
  display: inline-flex !important;
  visibility: hidden;
  pointer-events: none;
}

/*
 * Пилюля — контейнер, а не кнопка: внутри неё живут основная кнопка (открывает
 * поповер) и крестик сброса. Кнопку в кнопку вложить нельзя.
 */
.pill {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  font-size: 14px;
  transition: border-color .16s, background .16s, box-shadow .16s;
}

.pill__main {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 8px 15px 8px 12px;
  border: 0;
  border-radius: inherit;
  background: none;
  color: inherit;
  font-family: inherit;
  font-size: inherit;
  cursor: pointer;
}

/* Крестик сброса — серый, разгорается под курсором */
.pill__clear {
  display: grid;
  place-items: center;
  width: 26px;
  padding: 0 9px 0 0;
  border: 0;
  border-radius: inherit;
  background: none;
  color: var(--text-mute);
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  transition: color .14s;
}

.pill__clear:hover { color: var(--hot); }

.pill:hover { border-color: var(--accent); }

/* Открытая пилюля подсвечена — видно, какой поповер сейчас на экране */
.pill.is-open {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}

.pill.is-set { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }

.pill__icon { font-size: 15px; line-height: 1; }

.pill__text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.2;
  min-width: 0;
}

.pill__label {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-mute);
}

.pill__value {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 190px;
}

/*
 * «Куда» — пилюля с полем ввода вместо готового значения. Направление набирают
 * прямо здесь, поэтому списка стран в поповере больше нет: одно поле вместо
 * поля, подписи и скроллящегося списка на 237 строк.
 *
 * Поле выглядит как `.pill__value`, а не как input: рамки и фона нет, шрифт тот
 * же. Иначе в строке параметров появился бы прямоугольник, которого нет
 * у соседних пилюль, и «Куда» читалась бы как что-то чужеродное.
 */
/* Нажимается вся пилюля, поэтому и курсор текстовый по всей её площади */
.pill--combo { padding-left: 12px; cursor: text; }
.pill--combo .pill__text { flex: 1; min-width: 0; }
.pill--combo .pill__label { cursor: text; }
.pill--combo .pill__clear { cursor: pointer; }

.pill__input {
  width: 100%;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
}

.pill__input:focus { outline: none; }
/* Плейсхолдер — это «Куда угодно», то есть текущее состояние, а не подсказка */
.pill__input::placeholder { color: var(--text); opacity: 1; font-weight: 600; }
.pill--combo .pill__text { justify-content: center; padding: 7px 0; }

/*
 * Свой крестик у `type="search"` браузер рисует сам, а в пилюле уже есть
 * `.pill__clear` — получалось два подряд, и они делали разное: наш сбрасывает
 * направление целиком, браузерный лишь чистит текст. Убираем чужой.
 */
.pill__input::-webkit-search-cancel-button,
.pill__input::-webkit-search-decoration {
  appearance: none;
  display: none;
}

.pill--combo .pill__clear { padding-right: 10px; }

/*
 * Подсказки к набранному — первым блоком в окне «Куда летим»: окно открывается
 * с первым же символом, и не нашлось нужного — рядом регионы и карта. Отдельным
 * выпадающим списком под пилюлей они бы оказались под окном: поповер лежит
 * в top layer и перекрывает всё, что нарисовано обычным z-index.
 */
.dest-drop {
  display: grid;
  gap: 2px;
  max-height: 232px;
  overflow-y: auto;
  margin-bottom: 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
}

.dest-drop.is-hidden { display: none; }

/* Стрелка маршрута между «Откуда» и «Куда» — та же, что в карточке */
.searchbar__arrow {
  align-self: center;
  color: var(--text-mute);
  font-size: 16px;
  padding: 0 1px;
}

/*
 * Переключатели прямо в строке параметров. Кнопки «Фильтры» нет: прятать
 * два флажка за поповером значило прятать одно нажатие за двумя.
 */
.switches {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  padding: 3px 4px 3px 10px;
  margin-left: 2px;
}

.switches .check { font-size: 12.5px; gap: 7px; }
.switches .check input { width: 14px; height: 14px; }

.pill__count {
  display: grid;
  place-items: center;
  min-width: 19px;
  height: 19px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--accent);
  color: #05131c;
  font-size: 11.5px;
  font-weight: 700;
}

/* Пилюля-кнопка без вложенной .pill__main — язык в шапке */
/*
 * Пилюля без внутренней `.pill__main` (язык): содержимое лежит прямо в ней,
 * поэтому отступ между бейджем «RU» и подписью задаётся здесь — тот же 9px,
 * что и внутри обычных пилюль. Без него они слипались.
 */
.pill--plain {
  align-items: center;
  gap: 9px;
  padding: 8px 14px;
  font-family: inherit;
  cursor: pointer;
}

/* «Сбросить всё» — обычная кнопка, поэтому паддинг задаётся ей самой */
.pill--reset {
  align-items: center;
  padding: 10px 15px;
  color: var(--text-mute);
  border-style: dashed;
  font-family: inherit;
  cursor: pointer;
}

.pill--reset:hover { color: var(--hot); border-color: var(--hot); }

/*
 * Списки выбора внутри поповеров (валюта, язык).
 *
 * Нативный <select> здесь не годится: его выпадающий список рисует система,
 * и оформить его в стиле остальных окон невозможно — он выбивался из ряда.
 */
.choice { display: grid; gap: 2px; }

/* Город, по которому нашлась страна: «Анталья» справа от «Турция» */
.choice__hint {
  margin-left: auto;
  font-size: 12px;
  color: var(--text-mute);
  white-space: nowrap;
}

.choice__item.is-active .choice__hint { color: inherit; }

.choice__empty {
  margin: 0;
  padding: 10px 11px;
  font-size: 13px;
  color: var(--text-mute);
}

.choice__item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 9px 11px;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
  transition: background .14s, color .14s;
}

.choice__item:hover { background: var(--surface-2); }

.choice__item.is-active {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
  font-weight: 600;
}

/* Галочка у выбранного — место под неё зарезервировано, чтобы строки не прыгали */
.choice__item::after {
  content: '✓';
  margin-left: auto;
  opacity: 0;
  font-size: 12px;
}

.choice__item.is-active::after { opacity: 1; }

.pop--narrow { width: min(230px, calc(100vw - 24px)); }
.pop--narrow .hint { margin-top: 12px; }

/* ── Поповеры ─────────────────────────────────────────────────────────── */
/* Нативный popover: закрытие по клику вне и по Esc достаётся без JS. */
.pop {
  position: fixed;
  margin: 0;
  width: min(340px, calc(100vw - 24px));
  padding: 16px 18px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow);
  /* Раскрытая карта делает поповер высоким — не даём ему уйти за край экрана. */
  max-height: calc(100vh - 110px);
  overflow-y: auto;
}

.pop--wide { width: min(620px, calc(100vw - 24px)); }

/*
 * Фильтры не гасят страницу. Затемнение под поповером было и убрано по просьбе
 * 29.07.2026: параметры меняют, глядя на выдачу, — а она в этот момент уходила
 * в темноту. Подсветка остаётся только у карточки и строки под курсором
 * (`body::after`) и у окна согласия: там как раз нужно увести взгляд от фона.
 */
.pop::backdrop { background: transparent; }

.pop__title {
  margin: 0 0 14px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--text-mute);
}

.pop__actions {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

.pop .field + .field { margin-top: 14px; }

/* «Куда угодно» — отдельной строкой над регионами: это режим поиска, а не страна */
.anywhere {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  margin-bottom: 16px;
  padding: 11px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color .16s, background .16s;
}

.anywhere:hover { border-color: var(--accent); }

.anywhere.is-active {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, var(--surface-2));
}

.anywhere__icon { font-size: 20px; line-height: 1; }
.anywhere__text { display: flex; flex-direction: column; gap: 2px; }
.anywhere__title { font-weight: 650; font-size: 14px; }
.anywhere__sub { font-size: 12px; color: var(--text-mute); }

/* На телефоне поповер — шторка снизу: попадать в маленькое окно пальцем плохо */
@media (max-width: 720px) {
  .pop, .pop--wide {
    left: 0 !important;
    top: auto !important;
    bottom: 0;
    width: 100vw;
    max-height: 82vh;
    overflow-y: auto;
    border-radius: var(--radius) var(--radius) 0 0;
    border-bottom: 0;
  }

  .pill__value { max-width: 130px; }
}

.form__title {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 12px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--text-mute);
}

/* Стрелки последовательности: ⤴ вылет — первый шаг, ⤵ прилёт — второй */
.step-arrow {
  display: inline-grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 6px;
  background: color-mix(in srgb, var(--ok) 18%, transparent);
  color: var(--ok);
  font-size: 13px;
  line-height: 1;
}

.step-arrow--in {
  background: color-mix(in srgb, var(--hot) 18%, transparent);
  color: var(--hot);
}

.field { display: block; margin-bottom: 12px; }
.field:last-child { margin-bottom: 0; }
.field--grow { flex: 1; }
.field--inline { display: flex; align-items: center; gap: 9px; margin: 0; }
.field--inline .field__label { margin: 0; white-space: nowrap; }

.field__label {
  display: block;
  margin-bottom: 6px;
  font-size: 13px;
  color: var(--text-dim);
}

.row { display: flex; gap: 10px; }

.input {
  width: 100%;
  padding: 9px 11px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  transition: border-color .15s, box-shadow .15s;
}

.input--sm { padding: 6px 9px; font-size: 13px; width: auto; }

/* У выпадающих списков курсор-указатель: они кликабельны, и это должно быть
   видно до нажатия — сортировка, язык, страны вылета и назначения. */
select.input { cursor: pointer; }

.input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}

.hint { display: block; margin-top: 6px; font-size: 12px; color: var(--text-mute); }
/* Пояснение в окне, где нет поля: отступ сверху ему не от чего отсчитывать */
.hint--pop { margin: 0; line-height: 1.45; }

.range { width: 100%; accent-color: var(--accent); }

/* Чипы городов */
.chips { display: flex; flex-wrap: wrap; gap: 6px; }

.chip {
  padding: 5px 10px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text-dim);
  font-size: 12.5px;
  cursor: pointer;
  transition: all .15s;
}

.chip:hover { border-color: var(--accent); color: var(--text); }

.chip.is-active {
  background: color-mix(in srgb, var(--accent) 18%, var(--surface-2));
  border-color: var(--accent);
  color: var(--text);
}

/* Переключатель */
.segmented {
  display: flex;
  gap: 3px;
  padding: 3px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  margin-bottom: 12px;
}

.segmented__btn {
  flex: 1;
  padding: 7px 8px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--text-dim);
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: all .15s;
}

.segmented__btn:hover { color: var(--text); }

/* Короткая подпись живёт только на узком экране, см. медиазапрос в конце файла */
.seg-short { display: none; }

.segmented__btn.is-active {
  background: var(--accent);
  color: #04121d;
  font-weight: 600;
}

/* Чекбоксы */
.checks { display: grid; gap: 8px; }

/* Переключатели прижаты вправо: там же, где кнопки закрытия поповера */
.checks--end { justify-items: end; }
.checks--end .check { flex-direction: row-reverse; }

.check {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 13.5px;
  color: var(--text-dim);
  cursor: pointer;
}

.check input { accent-color: var(--accent); width: 15px; height: 15px; cursor: pointer; }
.check:hover { color: var(--text); }

/* Кнопки */
.form__actions { padding: 16px 18px; display: grid; gap: 9px; }

.btn {
  padding: 10px 16px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all .15s;
}

.btn:hover { border-color: var(--accent); }
.btn--wide { width: 100%; }
.btn--ghost { background: transparent; }

.btn--primary {
  background: linear-gradient(140deg, var(--accent), var(--accent-strong));
  border-color: transparent;
  color: #04121d;
  font-weight: 650;
}

.btn--primary:hover { filter: brightness(1.08); }
.btn--sm { padding: 6px 11px; font-size: 12.5px; }
.btn:disabled { opacity: .55; cursor: progress; }

/* ── Месяцы квадратиками ──────────────────────────────────────────────── */
.month-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}

.month-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 9px 4px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text-dim);
  font-family: inherit;
  cursor: pointer;
  transition: all .14s;
}

.month-tile__name { font-size: 13px; font-weight: 600; text-transform: capitalize; }
.month-tile__year { font-size: 10.5px; color: var(--text-mute); letter-spacing: .04em; }

.month-tile:hover { border-color: var(--accent); color: var(--text); }

.month-tile.is-active {
  background: color-mix(in srgb, var(--accent) 20%, var(--surface-2));
  border-color: var(--accent);
  color: var(--text);
}

.month-tile.is-active .month-tile__year { color: var(--accent); }

/* ── Чипы регионов ────────────────────────────────────────────────────── */
.region-chips { display: flex; flex-wrap: wrap; gap: 6px; }

.region-chip {
  padding: 6px 11px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text-dim);
  font-family: inherit;
  font-size: 12.5px;
  cursor: pointer;
  transition: all .14s;
}

.region-chip:hover { border-color: var(--accent); color: var(--text); }

.region-chip.is-active {
  background: color-mix(in srgb, var(--accent) 20%, var(--surface-2));
  border-color: var(--accent);
  color: var(--text);
}

/* Подписи не переносятся: «по скидке» рвалось на две строки и группа
   становилась выше соседней. */
.segmented__btn { white-space: nowrap; }
.segmented--sm .segmented__btn { padding: 5px 12px; font-size: 12.5px; }

/* ── Панель инструментов ──────────────────────────────────────────────── */
.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}

.toolbar .segmented { margin-bottom: 0; }
.toolbar__tools { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }

/*
 * Поиск по выдаче. Занимает остаток строки между видом и сортировкой, но
 * не растягивается бесконечно: на широком экране поле во всю ширину выглядело
 * бы главным элементом тулбара, а это уточнение уже найденного.
 */
.toolbar__find { display: flex; align-items: center; gap: 8px; flex: 1 1 320px; max-width: 560px; }
.find__input { width: 100%; }
.find__count { font-size: 12px; color: var(--text-mute); white-space: nowrap; }

@media (max-width: 720px) {
  /* На узком экране поле переносится на свою строку целиком: делить её
     с переключателями значило бы оставить каждому по трети ширины. */
  .toolbar__find { flex-basis: 100%; max-width: none; order: 3; }
}

/* ── Карта регионов ───────────────────────────────────────────────────── */
/*
 * Карта живёт внутри поповера «Куда» и раскрывается только кнопкой.
 * Раньше она разворачивалась сама и занимала ~540px над выдачей — то есть
 * первая цена оказывалась ниже первого экрана.
 */
.map-panel {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  overflow: hidden;
  max-height: 900px;
  opacity: 1;
  transition: max-height .38s ease, opacity .28s ease, margin-top .38s ease, padding-top .38s ease;
}

.map-panel.is-collapsed {
  max-height: 0;
  opacity: 0;
  margin-top: 0;
  padding-top: 0;
  border-top-color: transparent;
}

.map-panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 10px;
}

.map-panel__sub { margin: 0; font-size: 13px; color: var(--text-dim); }

.map-wrap {
  width: 100%;
  overflow-x: auto;
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--accent) 5%, var(--surface-2));
}

#regionMap { display: block; width: 100%; min-width: 560px; height: auto; }

.map-land path {
  fill: color-mix(in srgb, var(--text-mute) 26%, transparent);
  stroke: color-mix(in srgb, var(--text-mute) 34%, transparent);
  stroke-width: 1;
}

.map-zones .zone {
  fill: transparent;
  stroke: color-mix(in srgb, var(--text-mute) 32%, transparent);
  stroke-width: 1.2;
  stroke-dasharray: 5 4;
  cursor: pointer;
  transition: fill .18s, stroke .18s;
}

.map-zones .zone:hover { fill: color-mix(in srgb, var(--accent) 14%, transparent); stroke: var(--accent); }

.map-zones .zone.is-active {
  fill: color-mix(in srgb, var(--accent) 30%, transparent);
  stroke: var(--accent);
  stroke-width: 2;
  stroke-dasharray: none;
}

.map-zones .zone-label {
  fill: var(--text-dim);
  font-family: var(--font);
  font-size: 15px;
  font-weight: 500;
  text-anchor: middle;
  pointer-events: none;
  user-select: none;
}

.map-zones .zone-label.is-active { fill: var(--text); font-weight: 650; }

.map-arcs .arc {
  fill: none;
  stroke: url(#arcGrad);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-dasharray: 7 6;
  animation: dash-flow 1.1s linear infinite;
}

@keyframes dash-flow { to { stroke-dashoffset: -26; } }

.map-arcs .plane {
  fill: var(--hot);
  font-size: 21px;
  text-anchor: middle;
  dominant-baseline: central;
}

.map-origin .origin-dot {
  fill: var(--ok);
  stroke: var(--bg);
  stroke-width: 2;
}

.map-origin .origin-pulse {
  fill: none;
  stroke: var(--ok);
  stroke-width: 2;
  animation: pulse-ring 1.9s ease-out infinite;
}

@keyframes pulse-ring {
  0% { r: 6; opacity: .85; }
  100% { r: 20; opacity: 0; }
}

.map-origin .origin-label {
  fill: var(--ok);
  font-family: var(--font);
  font-size: 13px;
  font-weight: 600;
  text-anchor: middle;
}

/* Точка и подпись страны назначения */
.map-arcs .dest-dot {
  fill: var(--hot);
  stroke: var(--bg);
  stroke-width: 2;
}

.map-arcs .dest-label {
  fill: var(--hot);
  font-family: var(--font);
  font-size: 14px;
  font-weight: 650;
  text-anchor: middle;
}

.map-note { margin: 8px 0 0; font-size: 11.5px; color: var(--text-mute); text-align: center; }

/* Карточки */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 14px;
}

/* Без контура: карточку и так отделяет фон, а сетка из рамок рябила.
   Граница остаётся прозрачной, чтобы состояния (наведение, избранное,
   вспышка) могли её показать, не сдвигая содержимое. */
/*
 * Карточка — subgrid на шесть строк родительской сетки (шапка, цены, «есть
 * дешевле», факты, теги, подвал). Так одноимённые блоки соседних карточек стоят
 * на одной высоте:
 * без этого длинное название города переносилось на вторую строку и сдвигало
 * вниз всё остальное — цены в ряду переставали читаться одной линией.
 *
 * `row-gap: 0` обязателен: subgrid наследует зазор родителя (14px), и он
 * добавился бы между блоками внутри карточки к их собственным отступам.
 * Число `span 6` привязано к разметке `renderCard()` в app.js — добавите блок,
 * поправьте здесь. Строка «есть дешевле» есть не у всех карточек; у остальных
 * она остаётся пустой, и это как раз держит ряд ровным.
 */
.card {
  position: relative;
  display: grid;
  grid-row: span 6;
  grid-template-rows: subgrid;
  row-gap: 0;
  background: var(--surface);
  border: 1px solid transparent;
  border-radius: var(--radius);
  padding: 16px;
  transition: transform .16s, border-color .16s, box-shadow .16s;
}

/* Браузер без subgrid: точного выравнивания не выйдет, но двухстрочный
   маршрут — основной источник разъезда, и высоту под него держим заранее. */
@supports not (grid-template-rows: subgrid) {
  .card { display: flex; flex-direction: column; }
  .card__cities { min-height: 46px; }
}

.card:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--accent) 55%, var(--line));
  box-shadow: var(--shadow);
}

/* Горящее больше не обводим — огонь у цены и так виден */
.card.is-hot { border-color: transparent; }

/* Короткая вспышка: показывает, к какой карточке привёл клик по итогам */
.card.is-flash {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent);
  transition: border-color .2s, box-shadow .2s;
}

/*
 * Шапка тянется во всю высоту своего трека (subgrid уравнял их между карточками
 * ряда), а внутри неё города прижаты к верху и страны — к низу. Иначе при
 * двухстрочном названии города подпись страны уезжала вниз и стояла ниже, чем
 * у соседей: сами блоки карточки выровнены, а их содержимое — нет.
 */
.card__top {
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}

.card__route {
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

/* Скидка остаётся у верхнего края: растягивать её вслед за шапкой незачем */
.card__top .discount { align-self: flex-start; }

.card__cities {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -.01em;
}

.card__arrow { color: var(--accent); font-size: 14px; }

.card__countries {
  margin-top: 3px;
  font-size: 12.5px;
  color: var(--text-mute);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.discount {
  flex-shrink: 0;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--hot-soft);
  color: var(--hot);
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
}

.discount--none { background: var(--surface-2); color: var(--text-mute); font-weight: 500; }

.card__prices {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 6px;
}

/*
 * «Есть дешевле через N дней». Своя строка под ценой, а не тег в общем ряду:
 * это не свойство рейса, а повод посмотреть другую дату, и теряться среди
 * «прямой · без багажа» ему нельзя.
 */
.card__cheaper-slot { min-height: 20px; margin-bottom: 10px; }

.card__cheaper {
  padding: 0;
  border: 0;
  background: none;
  color: var(--ok);
  font-family: inherit;
  font-size: 12.5px;
  text-align: left;
  cursor: pointer;
  border-bottom: 1px dashed color-mix(in srgb, var(--ok) 45%, transparent);
  transition: color .14s, border-color .14s;
}

.card__cheaper b { font-weight: 700; }
.card__cheaper:hover { color: var(--text); border-color: var(--text); }

/*
 * Живое обновление. Раскупленный рейс не исчезает рывком, а сжимается и гаснет:
 * иначе выдача моргает, и непонятно, пропало предложение или сбился поиск.
 * Длительности совпадают с `LEAVE_MS` и `FLASH_MS` в app.js.
 */
.card.is-leaving,
.offers tbody tr.is-leaving {
  animation: leave .38s ease forwards;
  pointer-events: none;
}

@keyframes leave {
  to { opacity: 0; transform: scale(.96); filter: grayscale(1); }
}

/* Подешевело — зелёная вспышка, подорожало — красная. Цвет тот же, что
   у скидок и «горит», чтобы не заводить ещё один язык сигналов. */
.price.is-cheaper,
.offers__price.is-cheaper { animation: flash-cheaper 2s ease; }

.price.is-dearer,
.offers__price.is-dearer { animation: flash-dearer 2s ease; }

@keyframes flash-cheaper {
  0%   { color: var(--ok); transform: scale(1.08); }
  30%  { color: var(--ok); transform: scale(1); }
  100% { color: inherit; }
}

@keyframes flash-dearer {
  0%   { color: var(--hot); transform: scale(1.04); }
  30%  { color: var(--hot); transform: scale(1); }
  100% { color: inherit; }
}

@media (prefers-reduced-motion: reduce) {
  /* Движение убираем, но сам факт изменения показать надо — остаётся цвет. */
  .card.is-leaving,
  .offers tbody tr.is-leaving { animation: none; opacity: 0; }
  .price.is-cheaper, .offers__price.is-cheaper { color: var(--ok); animation: none; }
  .price.is-dearer, .offers__price.is-dearer { color: var(--hot); animation: none; }
}

/* Та же подсказка в таблице — колонка «Дешевле» */
.offers__cheaper { white-space: nowrap; }

.cheaper-link {
  padding: 0;
  border: 0;
  background: none;
  color: var(--ok);
  font-family: inherit;
  font-size: 12.5px;
  line-height: 1.25;
  text-align: left;
  cursor: pointer;
}

.cheaper-link__price { display: block; font-weight: 700; }
.cheaper-link:hover { color: var(--text); text-decoration: underline; }

.price {
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -.03em;
}


/* Время вылета рядом с датой — местное для аэропорта отправления */
/*
 * Время вылета — главное в этой ячейке, поэтому оно крупное и жирное,
 * а дата уходит строкой ниже. Время местное для аэропорта отправления.
 */
.fact__time {
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}

.fact__date {
  font-size: 12.5px;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Огонь перед ценой вместо тега «горит» */
.price-fire {
  font-size: 22px;
  margin-right: 2px;
  filter: drop-shadow(0 0 8px color-mix(in srgb, var(--hot) 60%, transparent));
  animation: flicker 2.2s ease-in-out infinite;
}

@keyframes flicker {
  0%, 100% { transform: scale(1) rotate(-3deg); opacity: 1; }
  50% { transform: scale(1.13) rotate(3deg); opacity: .88; }
}

@media (prefers-reduced-motion: reduce) {
  .price-fire { animation: none; }
}


.price--old {
  font-size: 15px;
  font-weight: 400;
  color: var(--text-mute);
  text-decoration: line-through;
}

.card__facts {
  display: grid;
  /* Три факта в один ряд: вылет, до вылета и время в пути — это один вопрос
     «когда и сколько лететь», и разносить его по строкам незачем.
     Авиакомпании здесь нет: на выбор дня она не влияет, а место занимала. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px 10px;
  padding: 12px 0;
  border-top: 1px solid var(--line);
  margin-bottom: 12px;
  font-size: 13px;
}

.fact__value--next { color: var(--accent); }

/* «Следующий рейс» — кнопка: открывает остальные даты этого маршрута.
   Без подчёркивания: кликабельность передаёт цвет и курсор. */
.fact__link {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.fact__link:hover { color: var(--hot); }
.fact__value--muted { color: var(--text-mute); }

/* Последние сутки перед вылетом — то, ради чего сервис и существует */
.fact__value--urgent { color: var(--hot); font-weight: 650; }

.fact { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fact__label { font-size: 11.5px; color: var(--text-mute); text-transform: uppercase; letter-spacing: .05em; }
.fact__value { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }

.tag {
  padding: 3px 8px;
  border-radius: 6px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-size: 11.5px;
  color: var(--text-dim);
}

.tag--kind { border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); color: var(--accent); }
.tag--fire { border-color: color-mix(in srgb, var(--hot) 40%, var(--line)); color: var(--hot); }

/* Багаж: норма известна — зелёный, тариф без багажа — приглушённый.
   Когда условие не разобрано, тега нет вовсе: молчание честнее догадки. */
/*
 * Цвета разведены по смыслу: «прямой» — свойство самого перелёта, зелёный;
 * багаж — про условия тарифа, голубой. Раньше было наоборот, и «прямой»
 * сливался с тегом типа рейса.
 */
.tag--direct { border-color: color-mix(in srgb, var(--ok) 45%, var(--line)); color: var(--ok); }
.tag--bag { border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); color: var(--accent); }
.tag--nobag { color: var(--text-mute); }

.card__cta {
  margin-top: auto;
  display: block;
  padding: 9px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--text);
  text-align: center;
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
  transition: all .15s;
}

/* Продавец — отдельной строкой под действием: видно, куда именно ведёт переход,
   и длинное имя не сжимает основную надпись. */
.card__cta { line-height: 1.3; }

.card__cta-seller {
  display: block;
  margin-top: 2px;
  color: var(--text-mute);
  font-size: 12px;
  font-weight: 400;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.card__cta:hover .card__cta-seller { color: inherit; opacity: .75; }

.card__cta:hover { background: var(--accent); border-color: var(--accent); color: #04121d; }

/* Основание старой цены живёт в `title` у самой скидки: строкой оно занимало
   место, значок ⓘ рябил, но выбросить его совсем нельзя — это защита
   от «скидок» с потолка. */


/* Пустое состояние и скелетоны */
.empty { padding: 56px 20px; text-align: center; }
.empty__title { margin: 0 0 6px; font-size: 17px; font-weight: 600; }
.empty__text { margin: 0; color: var(--text-dim); font-size: 14px; }

.skeleton {
  height: 258px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: linear-gradient(100deg, var(--surface) 30%, var(--surface-2) 50%, var(--surface) 70%);
  background-size: 220% 100%;
  animation: shimmer 1.3s infinite linear;
}

@keyframes shimmer { to { background-position: -220% 0; } }

/* ── Календарь ────────────────────────────────────────────────────────── */
.cal__head {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  margin-bottom: 14px;
}

.cal__title {
  margin: 0;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -.02em;
  text-transform: capitalize;
  min-width: 260px;
  text-align: center;
}

.cal__nav {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  transition: all .15s;
}

.cal__nav:hover { border-color: var(--accent); color: var(--accent); }

.cal__weekdays {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 8px;
}

.cal__weekdays span {
  text-align: center;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-mute);
}

/*
 * Календарь вписывается в экран целиком — прокручивать месяц незачем:
 * его смысл в том, чтобы сравнить дни одним взглядом.
 *
 * Высоту задаёт JS (`fitCalendar`), а не формула в CSS: над календарём стоят
 * шапка, строка параметров и тулбар, и их суммарная высота плавает от того,
 * перенеслись ли пилюли на вторую строку.
 */
#calendarView {
  display: flex;
  flex-direction: column;
  min-height: 430px;
}

/* В режиме календаря нижний отступ страницы лишний — из-за него и был скролл */
body.is-calendar .app { padding-bottom: 12px; }

.cal__grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  grid-auto-rows: minmax(0, 1fr);
  gap: 8px;
  flex: 1;
  min-height: 0;
}

.cal-day {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 0;
  /* Что не поместилось — скрываем: полный список дня открывается в «Карточках» */
  overflow: hidden;
  padding: 7px 9px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  transition: border-color .15s, transform .15s;
}

.cal-day--empty { background: transparent; border-color: transparent; min-height: 0; }
.cal-day--past { opacity: .38; }
.cal-day--has:hover { border-color: var(--accent); transform: translateY(-2px); }
.cal-day--best { border-color: var(--hot); box-shadow: 0 0 0 1px color-mix(in srgb, var(--hot) 40%, transparent); }

.cal-day__num {
  font-size: 19px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -.04em;
}

.cal-day--today .cal-day__num { color: var(--accent); }

/* День недели в ячейке не нужен — он уже стоит в шапке сетки, это дублирование,
   а место в ячейке дороже. */
.cal-day__dow { display: none; }

.cal-day__list {
  display: grid;
  gap: 3px;
  margin-top: auto;
  min-height: 0;
  overflow: hidden;
}

/* Кнопка, а не ссылка: ведёт в карточки, а не к продавцу */
.cal-item {
  width: 100%;
  border: 0;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px;
  padding: 3px 6px;
  border-radius: 5px;
  background: var(--surface-2);
  color: var(--text);
  text-decoration: none;
  font-size: 11.5px;
  transition: background .14s;
}

.cal-item:hover { background: color-mix(in srgb, var(--accent) 24%, var(--surface-2)); }

.cal-item__to {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-dim);
}

.cal-item__price { flex-shrink: 0; font-weight: 650; font-variant-numeric: tabular-nums; }
.cal-item--hot .cal-item__price { color: var(--hot); }
.cal-day__more { font-size: 10.5px; color: var(--text-mute); padding-left: 6px; }

/* ── Всплывающая таблица дня ──────────────────────────────────────────── */
/*
 * В ячейку помещается три направления, а в дне их бывает два десятка.
 * По наведению показываем весь список. Всплывашка — потомок ячейки и примыкает
 * без зазора, поэтому курсор переходит на неё, не теряя наведения, и по строкам
 * можно кликать.
 */
.cal-pop {
  position: absolute;
  top: 100%;
  left: -1px;
  z-index: 40;
  width: max(260px, 100%);
  padding: 10px 0 4px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
  box-shadow: var(--shadow);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity .14s, transform .14s, visibility .14s;
}

/* Ячейка обрезает своё содержимое, поэтому на время показа снимаем обрезку
   и поднимаем её над соседями. Список внутри прячет лишнее сам. */
.cal-day--has:hover,
.cal-day--has:focus-within { overflow: visible; z-index: 30; }

.cal-day--has:hover .cal-pop,
.cal-day--has:focus-within .cal-pop {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

/* У правых колонок всплывашка уходила бы за край экрана */
.cal__grid > .cal-day:nth-child(7n) .cal-pop,
.cal__grid > .cal-day:nth-child(7n-1) .cal-pop { left: auto; right: -1px; }

/* У нижних строк — раскрывается вверх. Класс ставит JS: строк в месяце
   от четырёх до шести, и селектором это надёжно не выразить. */
.cal-day--up .cal-pop { top: auto; bottom: 100%; transform: translateY(4px); }
.cal-day--up:hover .cal-pop,
.cal-day--up:focus-within .cal-pop { transform: translateY(0); }

.cal-pop__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 0 12px 8px;
  border-bottom: 1px solid var(--line);
  font-size: 12px;
  color: var(--text-dim);
}

.cal-pop__count { color: var(--text-mute); white-space: nowrap; }

.cal-pop__rows { max-height: 250px; overflow-y: auto; padding: 4px; }

.cal-pop__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto auto;
  gap: 10px;
  align-items: baseline;
  width: 100%;
  padding: 5px 8px;
  border-radius: 5px;
  background: none;
  font-size: 12.5px;
  text-align: left;
}

.cal-pop__row:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.cal-pop__to { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-pop__time { color: var(--text-dim); font-variant-numeric: tabular-nums; }
.cal-pop__stops { color: var(--text-mute); white-space: nowrap; }
.cal-pop__price { font-weight: 700; white-space: nowrap; }
.cal-pop__price.is-hot { color: var(--hot); }
.cal-pop__more { padding: 6px 12px 4px; font-size: 11.5px; color: var(--text-mute); }

/* День с предложениями кликабелен целиком — открывает его в «Карточках» */
.cal-day--has { cursor: pointer; }
.cal-day--has:hover { border-color: color-mix(in srgb, var(--accent) 55%, var(--line)); }
.cal-day--has:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── Вид: таблица ─────────────────────────────────────────────────────── */
/*
 * Плотный список для сравнения многих рейсов сразу. Карточки хороши на десяток
 * предложений, на две сотни взгляду нужны ряды и колонки.
 */
/*
 * Обёртка НЕ должна иметь overflow на широком экране: любой предок со скроллом
 * становится контейнером для `position: sticky`, и заголовки начинают липнуть
 * внутри него, а не к окну — на практике они прилипали к низу первой строки.
 * Горизонтальный скролл включаем только там, где таблица не помещается,
 * и там же отключаем липкость.
 */
.table-wrap {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  /*
   * `clip`, а не `hidden`: он обрезает содержимое по скруглённым углам,
   * но НЕ создаёт скролл-контейнер — значит липкие заголовки продолжают
   * липнуть к окну. С `hidden` или `auto` они бы снова прилипли внутрь.
   */
  overflow: clip;
}

.offers {
  width: 100%;
  border-collapse: collapse;
  font-size: 13.5px;
}

/*
 * Заголовки липнут под шапкой сайта. Высоту шапки не зашиваем константой:
 * она плавает от переноса строки параметров, и промах давал наезд заголовков
 * на первую строку. Значение ставит JS в `--topbar-h`.
 */
.offers th {
  position: sticky;
  top: var(--topbar-h, 63px);
  z-index: 5;
  padding: 10px 14px;
  text-align: left;
  white-space: nowrap;
  /*
   * Фон совпадает с таблицей: отдельная плашка выпирала из скруглённых углов
   * контейнера. Совсем прозрачным его сделать нельзя — заголовок липкий,
   * и сквозь него просвечивали бы уезжающие строки.
   */
  background: var(--surface);
  box-shadow: inset 0 -1px 0 var(--line);
  font-size: 11.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-mute);
}

/*
 * Скругления у заголовков нет: при прокрутке шапка отрывается от верха
 * таблицы, и закруглённый угол посреди списка выглядел поломкой.
 * Углы контейнера обрезает `overflow: clip` у `.table-wrap`.
 */

/* Сортируемые заголовки: курсор, подсветка активного и стрелка направления */
.offers th.is-sortable { cursor: pointer; user-select: none; }
.offers th.is-sortable:hover { color: var(--text); }
.offers th.is-active { color: var(--accent); }

/*
 * Стрелка всегда занимает место, меняется только её видимость: иначе появление
 * символа при наведении раздвигало колонку и таблица дёргалась.
 */
.offers th.is-sortable::after {
  content: '↕';
  display: inline-block;
  width: 10px;
  margin-left: 5px;
  font-size: 10px;
  opacity: 0;
  transition: opacity .12s;
}

.offers th.is-sortable:hover::after { opacity: .55; }
.offers th.is-active[data-dir='asc']::after { content: '↑'; opacity: 1; }
.offers th.is-active[data-dir='desc']::after { content: '↓'; opacity: 1; }

.offers td {
  padding: 9px 14px;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}

.offers tr:last-child td { border-bottom: 0; }

/* Строка кликабельна целиком и ведёт к продавцу */
.offers tbody tr { cursor: pointer; }
.offers tbody tr:hover td { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.offers tbody tr:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.offers tbody tr:hover .offers__seller { color: var(--accent); }

/* Горящее в таблице отмечено огнём у цены — полоса слева была лишней */

.offers__num { text-align: right; }

.offers__route { min-width: 210px; }
.offers__cities { display: block; font-weight: 600; }
.offers__countries { display: block; font-size: 12px; color: var(--text-mute); }

.offers__time { font-weight: 700; font-variant-numeric: tabular-nums; margin-right: 6px; }
.offers__date { color: var(--text-dim); white-space: nowrap; }

.offers__airline { display: block; }
.offers__stops { display: block; font-size: 12px; color: var(--text-mute); }

.offers__bag { color: var(--ok); white-space: nowrap; }
.offers__nobag { color: var(--text-mute); }

.offers__price { display: block; font-weight: 700; white-space: nowrap; }

/* Скидка в таблице приглушённая: колонка цен и так справа, и красная цифра
   в каждой строке превращала правый край в сплошную красную полосу. */
.offers__discount { display: block; font-size: 12px; color: var(--text-mute); }

/* Продавец — указатель, куда ведёт строка, а не отдельная кнопка */
.offers__seller {
  white-space: nowrap;
  color: var(--text-mute);
  font-size: 12.5px;
  transition: color .15s;
}

@media (max-width: 1100px) {
  /* Таблица перестала помещаться — включаем прокрутку и снимаем липкость:
     вместе они не работают, см. комментарий у .table-wrap. */
  .table-wrap { overflow-x: auto; }
  .offers th { position: static; }
  .offers th, .offers td { padding: 8px 10px; }
}

/* ── Условия тарифа по наведению на цену ──────────────────────────────── */
/*
 * Только то, чего нет в самой карточке: сумка, ручная кладь, обмен, возврат.
 * Багаж, пересадки и авиакомпания уже на виду — дублировать их незачем.
 * Открывается и по наведению, и по фокусу с клавиатуры, без единой строки JS.
 */
/* Подчёркивания у цены нет и не должно быть — цена читается как цена,
   а подсказку выдаёт курсор. Не возвращать пунктир. */
.price-wrap {
  position: relative;
  display: inline-block;
  cursor: help;
}

.fare {
  position: absolute;
  left: 0;
  top: calc(100% + 8px);
  z-index: 30;
  display: block;
  width: max-content;
  max-width: min(300px, 78vw);
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
  box-shadow: var(--shadow);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity .16s, transform .16s, visibility .16s;
  pointer-events: none;
}

.price-wrap:hover .fare,
.price-wrap:focus-visible .fare {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.fare__title {
  display: block;
  margin-bottom: 9px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-mute);
}

.fare__rows {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 5px 14px;
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0;
}

.fare__k { color: var(--text-mute); }
.fare__v { color: var(--ok); text-align: right; }
.fare__v--no { color: var(--text-mute); }

.fare__note {
  display: block;
  margin-top: 10px;
  padding-top: 9px;
  border-top: 1px solid var(--line);
  font-size: 11.5px;
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: 0;
  color: var(--text-mute);
}

/* ── Плашка выбранного дня над карточками ─────────────────────────────── */
.focus-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 14px;
  padding: 10px 16px;
  border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--line));
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  font-size: 14px;
}

.focus-bar__text b { font-weight: 700; }

/* Подпись только для скринридеров: у селекта валюты нет видимого лейбла */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.cal__note { margin: 14px 0 0; font-size: 12px; color: var(--text-mute); text-align: center; }

@media (max-width: 900px) {
  /* На телефоне ячейки слишком узкие, чтобы делить экран поровну, —
     возвращаем прокрутку и фиксированную высоту строки. */
  #calendarView { height: auto; }
  .cal__grid { grid-auto-rows: minmax(84px, auto); }
  .cal-day { padding: 6px 7px; }
  .cal-day__num { font-size: 16px; }
  .cal-item { font-size: 10px; }
  .cal__grid, .cal__weekdays { gap: 4px; }
  .cal__title { font-size: 20px; min-width: 0; }
}

/* Тост */
.toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translate(-50%, 20px);
  padding: 11px 20px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  box-shadow: var(--shadow);
  font-size: 13.5px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s, transform .2s;
  z-index: 50;
}

.toast.is-visible { opacity: 1; transform: translate(-50%, 0); }
.toast.is-error { border-color: var(--hot); color: var(--hot); }

.is-hidden { display: none !important; }

/* ── Посадочные страницы (серверный рендер) ───────────────────────────── */
/* Отдельная сетка: у лендинга нет левой панели поиска, только текст и таблицы. */

.seo {
  max-width: 1040px;
  margin: 0 auto;
  padding: 26px 22px 20px;
}

.seo-crumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  font-size: 13px;
  color: var(--text-mute);
}

.seo-crumbs a { color: var(--text-dim); text-decoration: none; }
.seo-crumbs a:hover { color: var(--accent); }
.seo-crumbs__sep { color: var(--line); }

.seo-title {
  margin: 14px 0 10px;
  font-size: 30px;
  line-height: 1.15;
  letter-spacing: -.02em;
}

.seo-lead {
  margin: 0 0 22px;
  max-width: 74ch;
  color: var(--text-dim);
  line-height: 1.6;
}

.seo-cta { margin: 0 0 28px; }

.seo-block {
  margin: 0 0 26px;
  padding: 18px 20px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.seo-block--muted { color: var(--text-dim); }
.seo-block h2 { margin: 0 0 14px; font-size: 17px; }

.seo-list { margin: 0; padding: 0; list-style: none; }

.seo-list__item {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, .8fr) auto;
  gap: 10px;
  align-items: baseline;
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
}

.seo-list__item:last-child { border-bottom: 0; }
.seo-list__name { color: var(--text); text-decoration: none; font-weight: 600; }
.seo-list__name:hover { color: var(--accent); }
.seo-list__city, .seo-list__date { color: var(--text-mute); font-size: 13.5px; }
.seo-list__price { color: var(--ok); font-weight: 700; white-space: nowrap; }

/* Таблица шире экрана телефона — прокручиваем её, а не всю страницу. */
.seo-table-wrap { overflow-x: auto; }

.seo-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.seo-table th {
  text-align: left;
  padding: 8px 12px 8px 0;
  color: var(--text-mute);
  font-weight: 500;
  font-size: 12.5px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.seo-table td { padding: 10px 12px 10px 0; border-bottom: 1px solid var(--line); }
.seo-table tr:last-child td { border-bottom: 0; }
.seo-table__price { color: var(--ok); font-weight: 700; white-space: nowrap; }
.seo-table a { color: var(--accent); }

.seo-chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.seo-chips li {
  padding: 6px 11px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 13.5px;
}

.seo-code { color: var(--text-mute); font-size: 12px; }

.seo-links {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 6px 18px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.seo-links--dense { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
.seo-links a { color: var(--text-dim); text-decoration: none; font-size: 14px; }
.seo-links a:hover { color: var(--accent); }

.seo-note { margin: 12px 0 0; color: var(--text-mute); font-size: 13px; }

/* ── Подвал сайта ─────────────────────────────────────────────────────── */
/*
 * Один и тот же подвал у поиска и у посадочных страниц (см. siteFooter
 * в src/seo/render.ts). Приглушённый серый и выравнивание по центру: это
 * служебный текст, он обязан быть виден, но не должен спорить с ценами.
 */
.sitefoot {
  max-width: 720px;
  /* Панели «Избранное» и «Топ выгодных» приколоты к нижним углам окна —
     без нижнего отступа подвал оказывался бы прямо под ними.
     Сверху отступ маленький: подвал должен читаться как продолжение
     содержимого, а не как отдельный этаж за пустой полосой. */
  margin: 16px auto 0;
  padding: 12px 22px 56px;
  border-top: 1px solid var(--line);
  color: var(--text-mute);
  font-size: 12px;
  line-height: 1.5;
  text-align: center;
}

.sitefoot__line { margin: 0 0 3px; }
.sitefoot__line a { color: var(--text-dim); }

.sitefoot__nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 7px;
  margin: 7px 0 0;
}

/* Копирайт отдельной строкой под ссылками — так подвал читается как подпись */
.sitefoot__copy { margin: 7px 0 0; }

.sitefoot__nav a { color: var(--text-dim); text-decoration: none; }
.sitefoot__nav a:hover { color: var(--accent); }
.sitefoot__sep { color: var(--line); }

/* Документы: те же блоки, что и на посадочных, плюс списки внутри текста */
.seo-doc-list { margin: 8px 0 0; padding-left: 20px; color: var(--text-dim); }
.seo-doc-list li { margin-bottom: 6px; }

@media (max-width: 720px) {
  .seo-title { font-size: 24px; }
  .seo-list__item { grid-template-columns: minmax(0, 1fr) auto; }
  .seo-list__city, .seo-list__date { display: none; }
}



/* Бейдж языка вместо флага: Windows не рисует региональные индикаторы */
.lang-badge {
  display: inline-grid;
  place-items: center;
  min-width: 26px;
  padding: 2px 5px;
  border: 1px solid var(--line);
  border-radius: 5px;
  background: var(--surface-2);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--text-dim);
}

.choice__item.is-active .lang-badge { border-color: var(--accent); color: var(--accent); }

/* ── Избранное ────────────────────────────────────────────────────────── */
.fav {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
}

/* Кнопка «наверх» стоит в одном ряду с переключателем избранного, слева */
.fav__row { display: flex; align-items: center; gap: 8px; order: 2; }

.fav__totop {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--surface);
  color: var(--text-dim);
  box-shadow: var(--shadow);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
  transition: border-color .15s, color .15s, transform .15s;
}

.fav__totop:hover { border-color: var(--accent); color: var(--accent); transform: translateY(-2px); }

/*
 * `order: 2` нужен обеим панелям: список раскрывается НАД кнопкой.
 * В избранном кнопка лежит внутри `.fav__row` (там порядок задаёт строка),
 * а в топе — прямым ребёнком `.fav`, и без order он уезжал наверх,
 * из-за чего кнопка прыгала при открытии.
 */
.fav__toggle {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 10px 16px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow);
  font-family: inherit;
  font-size: 14px;
  cursor: pointer;
  transition: border-color .15s;
  order: 2;
}

.fav__toggle:hover { border-color: var(--accent); }
.fav__star { color: var(--warn); }

.fav__count {
  display: grid;
  place-items: center;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--accent);
  color: #05131c;
  font-size: 12px;
  font-weight: 700;
}

.fav.is-empty .fav__count { background: var(--surface-2); color: var(--text-mute); }

.fav__body {
  order: 1;
  width: min(370px, calc(100vw - 36px));
  max-height: min(460px, 62vh);
  display: flex;
  flex-direction: column;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-soft);
  box-shadow: var(--shadow);
}

.fav.is-collapsed .fav__body { display: none; }

.fav__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.fav__title { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .08em; color: var(--text-mute); }
.fav__actions { display: flex; gap: 6px; }
.fav__list { overflow-y: auto; display: grid; gap: 4px; }
.fav__blank { margin: 6px 0; color: var(--text-mute); font-size: 13px; }
.fav__note { margin: 10px 0 0; padding-top: 9px; border-top: 1px solid var(--line); font-size: 11.5px; color: var(--text-mute); }

.fav-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto auto;
  align-items: center;
  gap: 8px;
  padding: 7px 8px;
  border-radius: var(--radius-sm);
}

.fav-item:hover { background: var(--surface-2); }
.fav-item__main { min-width: 0; }
.fav-item__route { display: block; font-weight: 600; font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fav-item__meta { display: block; font-size: 11.5px; color: var(--text-mute); }
.fav-item__price { font-weight: 700; white-space: nowrap; font-size: 13.5px; }

.fav-item__go, .fav-item__del {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--text-mute);
  text-decoration: none;
  font-size: 13px;
  cursor: pointer;
  transition: color .14s, background .14s;
}

.fav-item__go:hover { background: var(--surface-2); color: var(--accent); }
.fav-item__del:hover { background: var(--surface-2); color: var(--hot); }

@media (max-width: 720px) {
  .fav { right: 12px; bottom: 12px; }
  .fav__label { display: none; }
}

/* ── Звезда избранного ────────────────────────────────────────────────── */
/*
 * В карточке стоит справа от кнопки бронирования, рядом с «поделиться»:
 * оба действия над предложением собраны в одном месте. В таблице — отдельной
 * первой колонкой, чтобы взгляд находил её в одном месте у всех строк.
 */
.star {
  padding: 0;
  border: 0;
  background: none;
  color: var(--text-mute);
  font-size: inherit;
  line-height: 1;
  cursor: pointer;
  transition: color .14s, transform .14s;
}

/* Крупная звезда — в подвале карточки и в таблице: по ней целятся мышью */
.star--lg {
  display: grid;
  place-items: center;
  width: 38px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  font-size: 21px;
}

.star--lg:hover { transform: none; border-color: var(--warn); background: color-mix(in srgb, var(--warn) 12%, var(--surface-2)); }
.star--lg.is-on { border-color: color-mix(in srgb, var(--warn) 45%, var(--line)); }

.star:hover { color: var(--warn); transform: scale(1.12); }
.star.is-on { color: var(--warn); }
.star.is-on:hover { color: var(--hot); }

/* Отмеченное — бледно-жёлтой заливкой, одинаково в карточках и в таблице */
.card.is-fav {
  background: color-mix(in srgb, var(--warn) 12%, var(--surface));
  border-color: color-mix(in srgb, var(--warn) 40%, var(--line));
}

.offers tbody tr.is-fav td { background: color-mix(in srgb, var(--warn) 11%, transparent); }
.offers tbody tr.is-fav:hover td { background: color-mix(in srgb, var(--warn) 18%, transparent); }

/* Колонка звезды: сама кнопка крупная, по ней целятся мышью в длинном списке */
.offers__star-col { width: 1%; padding: 4px 4px 4px 8px !important; text-align: center; }
.offers__star-col .star--lg { width: 34px; height: 34px; font-size: 19px; }

/* ── Кнопка «поделиться» ──────────────────────────────────────────────── */
.card__foot { display: flex; gap: 8px; align-items: stretch; margin-top: auto; }
.card__foot .card__cta { flex: 1; margin-top: 0; }

.share-btn {
  display: grid;
  place-items: center;
  width: 38px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text-dim);
  cursor: pointer;
  transition: all .15s;
}

.share-btn:hover { background: var(--accent); border-color: var(--accent); color: #04121d; }

/* В таблице кнопка такая же, как в карточке, и одного размера со звездой */
.offers .share-btn { width: 34px; height: 34px; }

/* ── Топ выгодных: зеркало избранного в левом углу ────────────────────── */
.fav--left { right: auto; left: 18px; align-items: flex-start; }

/*
 * Панель «Топ выгодных» скрыта по просьбе 26.07.2026. Разметка, `renderTop()`
 * и переходы к карточке оставлены нетронутыми: вернуть панель — снять это
 * одно правило, а не собирать её заново.
 */
#topPanel { display: none; }

/*
 * Панель накладная, как избранное справа: страницу при открытии не двигаем.
 * Сдвиг всей выдачи пробовали — карточки перестраивались при каждом открытии,
 * и это оказалось хуже перекрытия.
 */
.fav__star--hot { filter: drop-shadow(0 0 6px color-mix(in srgb, var(--hot) 55%, transparent)); }

/* Топ показывается целиком, без прокрутки: десять строк и так помещаются,
   а прокрутка внутри маленькой панели только мешает. */
.top-list { gap: 3px; overflow: visible; }
.fav--left .fav__body { max-height: none; }

.top-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 9px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: background .14s, border-color .14s, transform .14s;
}

.top-item:hover {
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  border-color: color-mix(in srgb, var(--accent) 35%, transparent);
  transform: translateX(2px);
}

/* Номер в топе — крупной цифрой, первые три выделены */
.top-item__rank {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  background: var(--surface-2);
  color: var(--text-mute);
  font-size: 11.5px;
  font-weight: 700;
}

.top-item:nth-child(1) .top-item__rank { background: color-mix(in srgb, var(--warn) 22%, var(--surface-2)); color: var(--warn); }
.top-item:nth-child(2) .top-item__rank,
.top-item:nth-child(3) .top-item__rank { background: color-mix(in srgb, var(--accent) 16%, var(--surface-2)); color: var(--accent); }

.top-item__main { min-width: 0; }
.top-item__route { display: block; font-weight: 600; font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.top-item__meta { display: block; font-size: 11.5px; color: var(--text-mute); }

.top-item__right { text-align: right; }
.top-item__price { display: block; font-weight: 700; font-size: 13.5px; white-space: nowrap; }
/* Скидка того же цвета, что в карточках — одно значение, один цвет */
.top-item__off { display: block; font-size: 11.5px; font-weight: 700; color: var(--hot); }

@media (max-width: 720px) {
  .fav--left { left: 12px; }
}

/* ── Календарь: скользящее окно на пять недель ────────────────────────── */
/* Первое число месяца подписано, иначе в окне не видно границы месяцев. */
.cal-day__num { display: flex; align-items: baseline; gap: 5px; }

.cal-day__month {
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--accent);
}

.cal-day--month-start { border-color: color-mix(in srgb, var(--accent) 32%, var(--line)); }

.cal__nav:disabled { opacity: .3; cursor: not-allowed; }
.cal__nav:disabled:hover { background: none; border-color: var(--line); color: inherit; }

/* ── Согласие на хранение данных ──────────────────────────────────────── */
/*
 * Разметку строит consent.js, здесь только оформление. Баннер показывается
 * один раз до ответа, поэтому лежит выше всего остального (панели избранного
 * и топа — 60, тост — 50) и на это время перекрывает нижние углы.
 *
 * Не растягивается на всю ширину: карточка по центру оставляет видимой хотя бы
 * часть выдачи, и человек понимает, о каком сайте его спрашивают.
 */
.consent {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 70;
  display: flex;
  justify-content: center;
  padding: 14px;
  pointer-events: none;
}

/*
 * Оформлен как всплывающее окно, которым отвечают кнопки приложений (`.toast`):
 * та же поверхность, граница и тень. Красная заливка была пробована 26.07.2026
 * и заменена по просьбе — не возвращать. Текст берётся из токенов, поэтому
 * читается в обеих темах сам, без заданного вручную чёрного.
 */
.consent__box {
  pointer-events: auto;
  width: 100%;
  max-width: 640px;
  padding: 16px 18px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  animation: consent-in .22s ease-out;
}

/* Появление снизу — то же движение, что у тоста, интерфейс говорит одним языком */
@keyframes consent-in {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: translateY(0); }
}

.consent__title {
  margin: 0 0 8px;
  font-size: 15px;
  font-weight: 700;
}

.consent__text {
  margin: 0 0 10px;
  font-size: 13px;
  line-height: 1.5;
}

/* Оговорки про цену и удержание места — фон, поэтому тем же серым, что подвал */
.consent__note {
  margin: 0 0 13px;
  padding-top: 11px;
  border-top: 1px solid var(--line);
  color: var(--text-mute);
  font-size: 12px;
  line-height: 1.5;
}

/*
 * Кнопка слева, ссылка на документ справа: действие и справка не спорят
 * за одно место. Кнопка по центру пробовалась 26.07.2026 и откачена по просьбе.
 */
.consent__actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 9px;
}

.consent__link {
  margin-left: auto;
  font-size: 12.5px;
  color: var(--text-dim);
  text-decoration: none;
}

.consent__link:hover { color: var(--accent); }

/*
 * Та же кнопка, что «Перейти к бронированию» в карточке: спокойная поверхность,
 * а на наведении заливка акцентом. Главное действие в интерфейсе выглядит
 * одинаково везде — сплошной акцент без наведения пробовали и откатили.
 */
.consent__btn {
  padding: 9px 26px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all .15s;
}

.consent__btn:hover { background: var(--accent); border-color: var(--accent); color: #04121d; }
.consent__btn:active { transform: translateY(1px); }

@media (max-width: 720px) {
  .consent { padding: 0; }

  /* На телефоне это шторка снизу: скруглять нижние углы у края экрана нечего */
  .consent__box {
    max-width: none;
    border-radius: var(--radius) var(--radius) 0 0;
    border-bottom: none;
  }

  /* Ссылка уезжает на свою строку — иначе кнопка сжимается до нечитаемой */
  .consent__link { margin-left: 0; width: 100%; }
}

/* ── Фокус на карточке: остальное гасится ─────────────────────────────── */
/*
 * При наведении страница затемняется, а сама карточка (или строка таблицы)
 * остаётся поверх затемнения — взгляд не отвлекается на соседние предложения.
 *
 * Затемнение — `body::after`, отдельного элемента в разметке нет: он понадобился
 * бы и в index.html, и в layout() серверных страниц, а держать одно и то же
 * в двух файлах здесь уже пробовали с подвалом.
 *
 * Слои: затемнение 64 — выше панелей избранного и топа (60) и тоста (50),
 * поэтому гаснут и они; поднятое поверх него — 65; баннер согласия 70 остаётся
 * над всем, он важнее подсветки.
 */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 64;
  background: var(--dim);
  opacity: 0;
  pointer-events: none;
  transition: opacity .16s ease;
}

/*
 * Баннер согласия гасит страницу без всякого наведения и на любом устройстве:
 * это вопрос, на который ждут ответа, а не подсветка по касанию.
 */
body:has(.consent)::after { opacity: 1; }

/*
 * Наведение — только под мышью (`hover: hover`): на тач-устройствах оно
 * эмулируется и залипает после касания, экран остался бы затемнённым.
 */
@media (hover: hover) {
  body:has(.card:hover)::after,
  body:has(#topPanel:hover)::after,
  body:has(.offers tbody tr:hover)::after { opacity: 1; }

  .card:hover { z-index: 65; }

  /*
   * Топ выгодных — предложение сервиса, и при наведении оно выходит вперёд
   * так же, как карточка. Панель накладная, фон у неё непрозрачный, поэтому
   * достаточно поднять слой.
   */
  #topPanel:hover { z-index: 65; }

  .offers tbody tr:hover {
    position: relative;
    z-index: 65;
  }

  /*
   * Фон подсвеченной строки обязан быть непрозрачным: затемнение лежит под ней,
   * и сквозь полупрозрачную заливку просвечивало бы, гася саму строку.
   * Поэтому не `transparent` в третьем аргументе `color-mix`, а `--surface`.
   */
  .offers tbody tr:hover td { background: color-mix(in srgb, var(--accent) 6%, var(--surface)); }
  .offers tbody tr.is-fav:hover td { background: color-mix(in srgb, var(--warn) 18%, var(--surface)); }
}

/* ══ Телефон: компактная шапка параметров ══════════════════════════════ */
/*
 * На узком экране параметры занимали пять строк подряд, и до первой цены
 * приходилось прокручивать полэкрана. Раскладка задана жёстко: маршрут
 * в первой строке, «когда/бюджет/валюта» во второй, флажки в третьей.
 * Сортировка и «Сбросить» уезжают вниз к кнопке «наверх» — они нужны редко,
 * а места в верхней части экрана стоят дорого.
 */
@media (max-width: 720px) {
  .app { padding: 12px 12px 16px; }

  .searchbar { gap: 6px; margin-bottom: 10px; }

  /* Первая строка: откуда → куда, пополам */
  .searchbar > #pillOrigin,
  .searchbar > #pillDest { width: auto; flex: 1 1 calc(50% - 16px); min-width: 0; }
  .searchbar__arrow { flex: 0 0 auto; }

  /* Вторая строка: когда, бюджет, валюта — по трети */
  .searchbar > #pillWhen,
  .searchbar > #pillBudget,
  .searchbar > #pillCurrency { width: auto; flex: 1 1 calc(33.333% - 4px); min-width: 0; }

  .pill__main { padding: 6px 10px; gap: 6px; }
  .pill--combo { padding-left: 10px; }
  .pill__label { font-size: 9.5px; letter-spacing: .06em; }
  .pill__value, .pill__input { font-size: 13px; }
  /* Подпись обрезается по своей пилюле, а не по 190px десктопа: иначе
     «Ближайшие 7 дней» уезжало за край без многоточия. */
  .pill__value { max-width: 100%; }
  .pill__icon { display: none; }

  /* Флажки в строку, а не столбиком: две короткие подписи занимали две строки */
  .switches {
    flex: 1 1 100%;
    flex-direction: row;
    justify-content: flex-start;
    gap: 16px;
    padding: 2px 2px 0;
    margin-left: 0;
  }

  /*
   * «Сбросить» и сортировка уходят в нижний край экрана, к кнопке «наверх»:
   * это не параметры поиска, а действия над уже полученной выдачей.
   * `position: fixed` вместо переноса в разметке — она одна на все ширины.
   */
  /*
   * Нижний край делят четверо: сортировка слева, справа — «Сбросить», «наверх»
   * и «Избранное». На 390 px это впритык, поэтому подписи и отступы урезаны;
   * проверять надо именно на такой ширине, на 430 всё сходится и без этого.
   */
  .searchbar > .pill--reset {
    position: fixed;
    right: 148px;
    bottom: 12px;
    z-index: 60;
    height: 42px;
    padding: 0 11px;
    border-style: solid;
    border-radius: 999px;
    background: var(--surface);
    box-shadow: var(--shadow);
    font-size: 12px;
  }

  /* Скрытая кнопка не должна перехватывать нажатия у соседей внизу экрана */
  .searchbar > .pill--reset.is-hidden { display: none !important; }

  #sortSwitch {
    position: fixed;
    left: 12px;
    bottom: 12px;
    z-index: 60;
    background: var(--surface);
    box-shadow: var(--shadow);
    border-radius: 999px;
  }

  #sortSwitch .segmented__btn { padding: 9px 8px; font-size: 12px; }

  /* Короткие подписи вместо полных — только здесь, внизу экрана тесно */
  .seg-full { display: none; }
  .seg-short { display: inline; }

  /* Ряд видов и поиск остаются наверху — ими пользуются постоянно */
  .toolbar { gap: 8px; margin-bottom: 10px; }

  /* Выдаче нужен запас снизу: под ней теперь висят сортировка и «Сбросить» */
  .cards, #tableView { padding-bottom: 64px; }

  /* Название не переносится: «X-TRACT.ME» в две строки задирает шапку */
  .brand__text { white-space: nowrap; font-size: 15px; letter-spacing: .1em; }
  .brand__logo { height: 38px; }
  .topbar__inner { padding: 10px 12px; }

  /*
   * Карточка на телефоне короче: теги убраны совсем, факты сжаты в три колонки.
   * «Следующий рейс» встаёт в одну строку с вылетом — это одна мысль «когда»,
   * и разносить её по строкам на узком экране незачем. Авиакомпания уходит
   * под них на всю ширину: длинных названий хватает, в треть колонки они рвутся.
   */
  .card { padding: 13px; }
  .tags { display: none; }

  .card__facts {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px 8px;
    padding: 10px 0;
    margin-bottom: 8px;
    font-size: 12.5px;
  }


  .card__cheaper-slot { min-height: 0; margin-bottom: 8px; }
  .card__cheaper-slot:empty { display: none; }
}
