/* tellway — вариант 1 «Канон».
   Исполнение DESIGN-SYSTEM.md v2.0 §3.1–3.9 без скидок: палитра §3.1,
   шкала §3.2, сетка и воздух §3.3, порядок секций §3.5, слои шара §3.6,
   компоненты §3.7, движение §3.9.

   Слои страницы (без единого z-index выше 5, кроме чужой панели):
     z −1  земли секций (::before) и дальний план — снимок горного массива
     z  0  .sky: canvas с шаром
     z  1  содержимое секций
     z  5  шапка
   Отсюда и берётся глубина: шар идёт по земле секции, но под её текстом,
   и уходит за вырезанный по силуэту хребет. */

/* ------------------------------------------------------------------ токены */

:root {
  /* §3.1, дословно */
  --brand: #0C2661;
  --ink: #0A1D49;
  --brand-tint: #C1C8E2;
  --bg: #F6F6F2;
  --bg-alt: #FFFFFF;
  --bg-soft: #EAECF2;
  --text: #101B34;
  --text-mute: #5A6480;
  --accent: #D2703A;
  /* Та же терракота, взятая глубже. Нужна она там, где на заливке стоит
     БЕЛЫЙ текст: #D2703A под белым даёт 3.43:1 — этого хватает крупному
     начертанию кнопки (19px, 700 — «крупный текст» по 1.4.3, порог 3:1),
     но не хватает пояснению под заголовком двери (14px, порог 4.5:1).
     #B05727 даёт 5.00:1 и держит оба случая с запасом.

     Тон не выдуман здесь: витрина housing/ пришла к нему раньше и уже
     красит им своё действие (--accent-deep в housing/base.css). Один
     сайт — один тон действия. Светлый #D2703A остаётся там, где он
     работает не подложкой, а линией: focus-ring, подчёркивания, наведение
     на ссылку. */
  --accent-deep: #B05727;
  --accent-deep-hover: #9E4E23;
  --accent-deep-active: #8A431E;
  --accent-soft: #F2DFD1;
  --ice: #A9C4DA;
  --line: rgba(12, 38, 97, .12);

  /* Цвет focus-ring вынесен в токен, а не берётся акцентом напрямую.
     Причина арифметическая: терракота даёт 3.17:1 на снежной земле и
     3.43:1 на белой — 1.4.11 держит, — но на тёплой «Бумаге» это уже
     2.87:1, на «Льде» 2.96, на «Сумерках» 2.66, а на плашке регистрации
     (--brand-tint) и вовсе 2.06:1. Там кольцо уходит в синий: 8.6–12:1.
     Каждая земля U01 обязана объявить свой --focus. */
  --focus: var(--accent);

  /* §3.2 — гарнитуры. По умолчанию схема дословно. Имён шрифтов больше
     нигде в файле нет: колонка настроек (U01) подменяет ровно эти три
     токена и мимо них подменить ничего не может.
     Хвост каждого стека — настоящий системный, а не «sans-serif» ради
     галочки: без сети страница обязана остаться целой. */
  --font-head: Onest, "Segoe UI", system-ui, sans-serif;
  --font-body: Inter, system-ui, sans-serif;
  --font-hand: Caveat, "Segoe Script", cursive;

  /* Ошибка — единственный цвет вне §3.1: состояния ошибки схема не
     описывает, а требование её показать есть. Один тон на всю страницу,
     держит 4.5:1 и на белом, и на плашке --brand-tint; терракота на эту
     роль не годится — она занята действием. */
  --err: #8E2D16;
  --err-line: #A3341B;
  --err-bg: #FDF4F0;

  /* §3.3 — сетка */
  --container: 1280px;
  /* Предел текстовой колонки §3.3. Настройки вправе его только сузить:
     58ch — максимум схемы, а не цель, и превышать его нечем. */
  --measure: 58ch;
  --edge: 48px;
  /* Высота шапки. Она fixed и ничего не занимает в потоке, поэтому
     обложка обязана отступить сверху сама. Раньше отступ стоял долей
     экрана (9vh = 65px на ходовом окне) — меньше самой шапки, и логотип
     садился на первую строку заголовка: 34…69 против 65… (промерено на
     1280x800). Токен считается от самого высокого содержимого строки —
     кнопки: 46px + 10+10 поля строки + 18+18 поля шапки. */
  --head-h: 102px;
  --gutter: 28px;
  --r-card: 20px;
  --r-media: 24px;
  --r-pill: 999px;
  /* Скругление полей ввода. Раньше поля были капсулами (--r-pill), и
     однострочная сумма стояла капсулой рядом с прямоугольным полем
     запроса: две разные формы в одной строке читались несобранной
     вёрсткой. Капсула осталась там, где она уместна, — на кнопках и
     переключателях; поля ввода приведены к одному прямоугольнику. */
  --r-field: 12px;
  --r-hero: 28px;
  --shadow: 0 10px 36px rgba(20, 32, 26, .07);
  --shadow-lift: 0 18px 44px rgba(20, 32, 26, .12);

  /* §3.3 — воздух. Числа заданы явно и вниз не округляются. */
  --sec: 160px;         /* между секциями */
  --sec-quiet: 200px;   /* после тихой секции */
  --over-h2: 64px;      /* над заголовком */
  --under-h2: 24px;     /* под заголовком */
  --to-action: 40px;    /* текст → кнопка */

  --ease: cubic-bezier(.22, .61, .36, 1);
  --dur: 240ms;

  /* Колонка настроек U01: сколько ширины страница уступает панели.
     Ноль, пока панель закрыта, и ноль на узких экранах, где панель идёт
     поверх. --vw — то, что после этого остаётся: всё, что считалось от
     100vw, считается от неё. */
  --pane: 0px;
  --vw: calc(100vw - var(--pane));

  color-scheme: light;
  caret-color: var(--accent);
  scrollbar-color: var(--brand-tint) var(--bg);
  scrollbar-width: thin;
}

@media (max-width: 1024px) { :root { --sec: 96px; --sec-quiet: 128px; --edge: 32px; --over-h2: 48px; } }
@media (max-width: 768px)  { :root { --sec: 64px; --sec-quiet: 96px; --edge: 20px; --over-h2: 40px; --gutter: 20px; } }

/* -------------------------------------------- U01: земли, гарнитуры, колонка

   Требование заказчика: «сбоку колонка настройки — выбор шрифта, цвет
   заднего фона и колонки». Всё, что она умеет, живёт здесь: четыре набора
   токенов на <html>, и ни одной строки поверх готовых правил. Панель
   ничего не переопределяет — она переключает исходные значения.

   Границы U01.1, которые настройки не вправе отменить:
     · знак остаётся #0C2661 при любой земле. Поэтому все земли светлые:
       на тёмной синий контур логотипа перестал бы читаться, а красить
       знак запрещено. Худшая пара — «Сумерки»: 11.10:1, знак виден везде;
     · --brand, --ink, --text и --accent не меняются ни на одной земле,
       поэтому доля терракоты остаётся ровно той же, что в схеме, а сама
       она — только на действиях;
     · --text-mute и --focus каждая земля объявляет свои и держит 4.5:1
       и 3:1 соответственно на всех трёх своих плоскостях. Числа — в
       комментарии у каждой земли, промерены, а не прикинуты.
*/

/* --- гарнитуры. Пара «заголовок + текст», третьей быть не может: §3.2
   разрешает два шрифта и рукописный акцент на одно-два слова. --- */

/* Запасная пара — не выдумана: §3.2 сама называет её альтернативой
   («Onest (альтернатива — Manrope)», «Inter (альтернатива — Golos Text)»). */
.f-alt {
  --font-head: Manrope, "Segoe UI", system-ui, sans-serif;
  --font-body: "Golos Text", "Segoe UI", system-ui, sans-serif;
}
/* Системная — единственный набор, который не грузит ни байта: страница
   рисуется тем, что уже стоит у гостя. Рукописный акцент тоже уходит
   на системный курсив, иначе обещание «ничего не грузим» было бы ложью. */
.f-system {
  --font-head: system-ui, "Segoe UI", Roboto, Arial, sans-serif;
  --font-body: system-ui, "Segoe UI", Roboto, Arial, sans-serif;
  --font-hand: "Segoe Script", "Bradley Hand", "Apple Chancery", cursive;
}

/* --- земли. Числа: контраст по WCAG 2.x, фон → текст. --- */

/* Снежная земля — это :root выше, схема дословно.
   #101B34 15.78 / 17.10 / 14.47 · #5A6480 5.43 / 5.88 / 4.98
   (порядок: --bg, --bg-alt, --bg-soft). Кольцо — терракота: 3.17 / 3.43. */

/* Бумага — тёплая, под терракоту.
   #101B34 14.31 / 16.15 / 13.55 · #545D78 5.47 / 6.17 / 5.18
   Кольцо синее: 11.99 / 13.54 / 11.36 — терракота дала бы 2.87 / 3.24 / 2.72. */
.g-paper {
  --bg: #F2EADC;
  --bg-alt: #FCF8F1;
  --bg-soft: #EDE4D4;
  --text-mute: #545D78;
  --line: rgba(12, 38, 97, .14);
  --focus: var(--brand);
}

/* Лёд — холодная, под снег в синей тени.
   #101B34 14.74 / 16.77 / 13.53 · #545D78 5.63 / 6.41 / 5.17
   Кольцо синее: 12.36 / 14.05 / 11.34 — терракота дала бы 2.96 / 3.37 / 2.72. */
.g-ice {
  --bg: #E8EFF6;
  --bg-alt: #FBFDFF;
  --bg-soft: #DCE6F0;
  --text-mute: #545D78;
  --line: rgba(12, 38, 97, .14);
  --focus: var(--brand);
}

/* Сумерки — самая глубокая земля, какую держит требование ≥4.5:1.
   #101B34 13.25 / 15.64 / 12.61 · #4E5773 5.54 / 6.55 / 5.28
   Кольцо синее: 11.10 / 13.11 / 10.57 — терракота дала бы 2.66 / 3.14 / 2.53.
   --accent-soft поднят на два шага: на синеватой земле прежний #F2DFD1
   совпадал с ней по светлоте (0.762 против 0.763) и пилюля-тег
   переставала читаться как форма. */
.g-dusk {
  --bg: #DDE3EC;
  --bg-alt: #F2F5FA;
  --bg-soft: #D6DEEA;
  --text-mute: #4E5773;
  --accent-soft: #F7E7DA;
  --line: rgba(12, 38, 97, .18);
  --focus: var(--brand);
}

/* Плоскости, где земля не решает ничего, а кольцо решает.
   Фотография hero и тёмные секции: синее кольцо на них пропало бы, идёт
   терракота — 4.17:1 на --brand, 4.77 на --ink, 4.0+ на затемнении hero.
   Плашка регистрации — наоборот: терракота на --brand-tint даёт 2.06:1,
   синее кольцо 8.61. Это правило чинит и снежную землю тоже. */
.head, .hero, .voices, .foot { --focus: var(--accent); }
.apply { --focus: var(--brand); }
/* Холодная подложка --bg-soft — единственная плоскость, где терракота не
   добирает и на снежной земле: 2.91 / 2.72 / 2.72 / 2.53 по четырём землям.
   Фокусируемое на ней — переключатель сезона и кнопка в пустом подборе;
   у обоих кольцо синее, 10.57 и выше на всех четырёх. */
.empty { --focus: var(--brand); }

/* --- ширина колонки. Только вниз от схемы: 1280 / 58ch — это её
   максимум, и настройка вправе лишь поджать страницу к тексту. --- */
.w-narrow { --container: 1040px; --measure: 50ch; }
.w-mid    { --container: 1160px; --measure: 54ch; }

/* --------------------------------------------------------------- основание */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  /* Открытая колонка настроек не ложится поверх страницы, а забирает
     себе полосу: страница поджимается на ту же величину. Иначе панель
     закрывала бы правый край содержимого — а закрывать его нельзя. */
  padding-right: var(--pane);
  background: var(--bg);
  color: var(--text);
  font: 400 16px/1.65 var(--font-body);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

img { max-width: 100%; }

::selection { background: var(--accent-soft); color: var(--ink); }

::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb {
  background: var(--brand-tint);
  border: 3px solid var(--bg);
  border-radius: var(--r-pill);
}
::-webkit-scrollbar-thumb:hover { background: var(--brand); }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
  border-radius: 6px;
}

a {
  color: var(--brand);
  text-decoration-thickness: 1px;
  text-underline-offset: .22em;
  transition: color var(--dur) var(--ease);
}
a:hover { color: var(--accent); }
a:active { color: #B65E2E; }

h1, h2, h3 {
  font-family: var(--font-head);
  letter-spacing: -.02em;
  margin: 0;
  text-wrap: balance;
}

p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

/* Шкала §3.2. .h1 нужен служебным страницам: на главной заголовок первого
   уровня — это .hero__title, у него свой кегль под фотографией, а вот
   credits.html набирает <h1> общей шкалой и без этого правила падал на
   браузерный размер 2em мимо всей типографики. */
.h1 {
  font-size: clamp(34px, 4.4vw, 56px);
  font-weight: 700;
  line-height: 1.08;
  color: var(--brand);
}

.h2 {
  font-size: clamp(32px, 4vw, 52px);
  font-weight: 700;
  line-height: 1.12;
  color: var(--brand);
}

.wrap {
  position: relative;
  z-index: 1;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--edge);
}

/* Шапка закреплена — якорь не должен прятать заголовок секции под ней. */
#top, #assist, #flats, #form { scroll-margin-top: 96px; }

.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* Ссылка «к содержимому» — первая в табуляции, видна только при фокусе.
   Шапка закреплена и стоит на z 5, поэтому ссылка идёт выше неё. */
.skip {
  position: fixed;
  left: 12px;
  top: -100px;
  z-index: 20;
  padding: 12px 18px;
  border-radius: var(--r-pill);
  background: var(--bg-alt);
  color: var(--brand);
  font-weight: 600;
  text-decoration: none;
  box-shadow: var(--shadow-lift);
  transition: top var(--dur) var(--ease);
}
.skip:focus-visible { top: 12px; }

/* --------------------------------------------------- появление секций §3.9 */
/* Контент виден по умолчанию; прячет его только JS, и только когда движение
   разрешено. Без скриптов и без анимации страница целая. */

.js .reveal { opacity: 0; transform: translateY(16px); }
.js .reveal.is-in {
  opacity: 1;
  transform: none;
  transition: opacity 500ms var(--ease), transform 500ms var(--ease);
}
.is-still .reveal, .is-shot .reveal { opacity: 1 !important; transform: none !important; transition: none !important; }

/* --------------------------------------- уклонение карточек от знака (U02)

   Смещение карточки, уступающей дорогу знаку, живёт в отдельном свойстве
   translate и приходит из app.js покадрово. В transform его писать нельзя:
   там уже стоят въезд .reveal и подъём :hover, оба с переходом, и общая
   запись либо отменила бы их, либо потащила уклонение через чужой переход,
   оторвав его от прокрутки. translate складывается с transform и ничего не
   отменяет — поэтому у .flat и .voices__media
   свойство translate занимать не следует.

   .is-measuring — один синхронный кадр, на котором app.js снимает голую
   раскладку карточек: въезд .reveal на это время убран, иначе его 16px
   осели бы в кэше геометрии как часть вёрстки. Кадр между установкой и
   снятием класса не рисуется, мигания нет. */
.is-measuring .reveal { transform: none !important; transition: none !important; }

/* ------------------------------------------------------------------ кнопки */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 52px;
  padding: 0 28px;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  font: 700 19px/1 var(--font-head);
  letter-spacing: -.01em;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.btn::after {
  content: "";
  width: 18px; height: 10px;
  flex: none;
  background: currentColor;
  /* стрелка §3.7 — рисованная, не глиф */
  -webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 10'%3E%3Cpath d='M0 5h16M12 1l4 4-4 4' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center / contain;
  mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 10'%3E%3Cpath d='M0 5h16M12 1l4 4-4 4' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center / contain;
  transition: transform var(--dur) var(--ease);
}
.btn:hover::after { transform: translateX(3px); }

.btn--primary { background: var(--accent-deep); color: #fff; }
.btn--primary:hover { background: var(--accent-deep-hover); color: #fff; }
.btn--primary:active { background: var(--accent-deep-active); transform: translateY(1px); }

.btn--ghost { background: transparent; color: var(--brand); border-color: var(--line); }
.btn--ghost:hover { background: var(--bg-soft); color: var(--brand); border-color: rgba(12, 38, 97, .3); }
.btn--ghost:active { background: var(--brand-tint); transform: translateY(1px); }


.btn--sm { min-height: 46px; padding: 0 22px; font-size: 19px; }
.btn--sm::after { width: 15px; }

.btn[disabled], .btn[aria-disabled="true"] {
  background: var(--bg-soft);
  color: var(--text-mute);
  border-color: var(--line);
  cursor: not-allowed;
  transform: none;
}
.btn[disabled]::after { opacity: .5; }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--brand);
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: .28em;
  white-space: nowrap;
}
.link-arrow svg { width: 20px; height: 12px; flex: none; transition: transform var(--dur) var(--ease); }
.link-arrow:hover svg { transform: translateX(3px); }

/* --------------------------------------------------- слой 1: дальний план */

/* Слой −1, вместе с землями секций. Фотография доходит до верхней кромки
   секции подбора и там обрывается её землёй — одним прямым краем на
   границе блока.

   Недолго слой стоял на 0, чтобы фотография дотягивалась до силуэта
   ближней гряды: между кромкой секции и началом гряды зияла светлая
   полоса. Гряды больше нет (вырезанный по маске хребет читался наклейкой),
   тянуться не к чему — а поднятый слой стоил бы того, что фотография
   на полэкрана растворялась бы поверх светлой секции при прокрутке. */
.ground {
  position: fixed;
  inset: 0;
  right: var(--pane);
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
  will-change: opacity;
}
.ground__img {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 100%;
  height: 118%;
  transform: translate(-50%, -50%);
  object-fit: cover;
  object-position: 50% 42%;
  will-change: transform;
}
/* Затемнение снято не на глаз: белый текст поверх фотографии обязан
   держать 4.5:1 по худшему пикселю подложки, поэтому левая треть кадра
   уходит в тень, а правая, где идёт шар, остаётся открытой. */
.ground__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(10, 29, 73, .76) 0%, rgba(10, 29, 73, .42) 28%, rgba(10, 29, 73, .12) 56%, rgba(10, 29, 73, 0) 78%),
    linear-gradient(100deg, rgba(10, 29, 73, .92) 0%, rgba(10, 29, 73, .82) 30%, rgba(10, 29, 73, .35) 62%, rgba(10, 29, 73, 0) 84%);
}

/* ------------------------------------------------- слой 2: шар §3.6 */

/* Небо уступает полосу вместе со страницей: иначе шар уходил бы за
   панель на правых стоянках, а он — главный объект страницы. app.js
   строит трек по этой же ширине (VIEW_W), поэтому траектория и кадр
   остаются одним и тем же пространством. */
.sky {
  position: fixed;
  inset: 0;
  right: var(--pane);
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}
.sky__canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.sky__flat { position: absolute; left: 0; top: 0; will-change: transform; }
.sky__flat svg { display: block; overflow: visible; }

.is-still .sky, .is-flat-off .sky__canvas { display: none; }

/* Без движения и без скриптов дальний план перестаёт быть фиксированным
   слоем: иначе снимок дальнего плана светил бы в каждый просвет между
   секциями, где ему быть не должно.

   ВНИМАНИЕ ПРИ ПРАВКЕ. Закрывающая последовательность этого комментария
   однажды пропала, и он проглотил следующее за ним правило целиком —
   фотография оставалась fixed ровно в тех двух режимах, ради которых
   правило и написано, и светила в каждый просвет между секциями.
   Проверять глазами это бесполезно: в обычном режиме всё выглядит верно.
   Признак — правила .is-still .ground нет в document.styleSheets. */

.is-still .ground,
.no-js .ground {
  position: absolute;
  inset: 0 0 auto;
  height: 100vh;
  height: 100svh;
}

/* ------------------------------------------------------------------ шапка */

/* Сжатие шапки анимируется только композитными свойствами: раскладка
   (padding, ширины, положение знака) в обоих состояниях одна и та же,
   меняются лишь transform строки и прозрачность пилюли под ней. Класс
   переключается на прокрутке, поэтому переход на padding пересчитывал бы
   раскладку в каждом кадре. */
.head {
  position: fixed;
  inset: 0 0 auto;
  right: var(--pane);
  z-index: 5;
  padding: 18px var(--edge);
}
.head__in {
  position: relative;
  z-index: 0;
  display: flex;
  align-items: center;
  gap: 24px;
  max-width: var(--container);
  margin-inline: auto;
  padding: 10px 12px 10px 4px;
  transition: transform var(--dur) var(--ease);
}
/* Белая пилюля §3.5 — отдельный слой под содержимым строки: проявляется
   прозрачностью и не трогает поток. */
/* Заливка, тень и размытие взяты у витрины (.top__in в housing/base.css)
   до последнего числа. Это единственное состояние, в котором шапка главной
   и шапка витрины видны рядом — при переходе по ссылке «Все квартиры», —
   и раньше они там расходились: тут плотное белое с рамкой, там полу-
   прозрачное с размытием и другой тенью. Один сайт — одна таблетка. */
.head__in::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -2px -8px -2px -16px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, .94);
  box-shadow: 0 8px 30px rgba(10, 29, 73, .14);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
@supports (backdrop-filter: blur(8px)) {
  .head__in::before { background: rgba(255, 255, 255, .88); backdrop-filter: blur(10px); }
}
.head.is-stuck .head__in { transform: translateY(-8px); }
.head.is-stuck .head__in::before { opacity: 1; }

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: #fff;
  font: 700 20px/1 var(--font-head);
  letter-spacing: -.02em;
  text-decoration: none;
  transition: color var(--dur) var(--ease);
}
.head.is-stuck .brand { color: var(--brand); }
.brand:hover { color: var(--accent); }
.brand__mark { display: block; width: 25px; height: 35px; flex: none; }
.brand__mark svg { display: block; width: 100%; height: 100%; }
/* Знак в шапке всегда цвета логотипа; поверх фото — светлая обводка снизу */
.head:not(.is-stuck) .brand__mark svg { filter: drop-shadow(0 1px 2px rgba(255, 255, 255, .55)); }

.head__nav { display: flex; gap: 24px; margin-left: auto; }
.head__nav a {
  color: rgba(255, 255, 255, .92);
  font-weight: 500;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
}
.head.is-stuck .head__nav a { color: var(--text); }
.head__nav a:hover { color: var(--accent); border-bottom-color: var(--accent); }

.head__menu { display: contents; }

/* Кнопка шапки поверх фотографии — светлая, а не терракотовая.

   Причина не во вкусе, а в счёте: терракотовая заливка на сайте означает
   «главное действие», и в первом экране их оказалось две — эта кнопка и
   «Подобрать» в строке подбора. Два главных действия в одном кадре — это
   ноль главных действий, глазу не за что зацепиться.

   Поэтому пока шапка висит над фотографией, кнопка идёт полупрозрачным
   белым: она видна, но не спорит. Как только шапка прилипает к белой
   странице — она становится обычной терракотовой, потому что там строки
   подбора рядом уже нет и спорить не с кем.

   Контраст: белый текст на rgba(255,255,255,.16) поверх тёмного скрима
   обложки держится за счёт самого скрима (он даёт 0.85-0.91 плотности
   на левой трети — промерено), плюс рамка в 1.5px очерчивает форму. */
.head:not(.is-stuck) .head__cta {
  background: rgba(255, 255, 255, .16);
  border-color: rgba(255, 255, 255, .55);
  color: #fff;
  backdrop-filter: blur(6px);
}
.head:not(.is-stuck) .head__cta:hover {
  background: rgba(255, 255, 255, .26);
  border-color: #fff;
  color: #fff;
}

/* Кнопка меню. На широком экране её нет вовсе: ссылки помещаются в строку,
   и лишний орган управления там только мешает. */
.head__burger { display: none; }

/* --- узкий экран: ссылки уходят под кнопку -------------------------------

   Прежде здесь стояло `.head__nav { display: none }` — и всё: с телефона
   на витрину жилья можно было попасть только из подвала. Теперь ссылки не
   исчезают, а складываются в панель под шапкой. Разметка та же самая,
   второго списка ссылок в файле нет. */
@media (max-width: 860px) {
  .head__burger {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-left: auto;
    min-height: 44px;          /* палец попадает */
    padding: 0 14px;
    border: 1px solid rgba(255, 255, 255, .34);
    border-radius: var(--r-pill);
    background: rgba(10, 29, 73, .28);
    color: #fff;
    font: 500 15px/1 var(--font-body);
    cursor: pointer;
    transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
                border-color var(--dur) var(--ease);
  }
  .head.is-stuck .head__burger {
    border-color: var(--line);
    background: transparent;
    color: var(--text);
  }
  .head__burgerBars { display: grid; gap: 4px; width: 18px; }
  .head__burgerBars i {
    display: block;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
    transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
  }
  /* Открытая кнопка становится крестом: три полосы — две в диагонали,
     средняя гаснет. Состояние кнопки должно читаться и без панели. */
  .is-menu .head__burgerBars i:nth-child(1) { transform: translateY(6px) rotate(45deg); }
  .is-menu .head__burgerBars i:nth-child(2) { opacity: 0; }
  .is-menu .head__burgerBars i:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

  .head__menu {
    display: flex;
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    left: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    padding: 12px;
    border: 1px solid var(--line);
    border-radius: var(--r-card);
    background: var(--bg-alt);
    box-shadow: var(--shadow-lift);
    /* Закрытая панель убрана из потока и недостижима с клавиатуры:
       visibility снимает её и с последовательности табуляции тоже. */
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease),
                visibility var(--dur);
  }
  .is-menu .head__menu { opacity: 1; visibility: visible; transform: none; }

  .head__nav { flex-direction: column; gap: 0; margin-left: 0; }
  .head__nav a,
  .head.is-stuck .head__nav a {
    display: block;
    padding: 12px 14px;
    border-bottom: 0;
    border-radius: 12px;
    color: var(--text);
    font-size: 16px;
  }
  .head__nav a:hover { background: var(--bg-soft); color: var(--brand); }
  .head__cta { margin: 8px 0 0; justify-content: center; }

  .head__scrim {
    position: fixed;
    inset: 0;
    z-index: 4;               /* под шапкой (5), над страницей */
    background: rgba(10, 29, 73, .3);
  }
}

/* На широком экране затемнение не нужно никогда: панели нет. */
@media (min-width: 861px) { .head__scrim { display: none; } }

/* Без скриптов открыть панель нечем — значит, прятать её нельзя.
   Кнопка уходит, ссылки встают в строку под шапкой и остаются
   достижимыми: страница обязана работать и с выключенным JS. */
.no-js .head__burger { display: none; }
.no-js .head__menu {
  position: static;
  opacity: 1;
  visibility: visible;
  transform: none;
  box-shadow: none;
}

/* «Зарегистрироваться» — надпись длинная, и ниже ~480px строка шапки
   перестаёт вмещать её рядом со знаком. Сокращать призыв нельзя — он должен
   читаться одинаково везде, поэтому ужимаются поля, кегль и стрелка.
   Высота остаётся 44px: палец по-прежнему попадает. */
@media (max-width: 480px) {
  .head__cta { min-height: 44px; padding: 0 14px; font-size: 15px; }
  .head__cta::after { display: none; }
}

/* ------------------------------------------------ 2. Hero — фото, тихая */

/* Копия живёт в верхней половине, гора — в нижней: белый текст никогда
   не ложится на снег. Это не вкус, это единственный способ удержать
   контраст на полноэкранной фотографии.

   Обложка ужата вдвое против прежней полноэкранной, и это не экономия
   места, а требование нового форм-фактора: главный элемент страницы —
   окно подбора, и оно обязано попадать в первый экран целиком, вместе
   с кнопкой. Полноэкранная обложка отодвигала кнопку за сгиб на любой
   ходовой высоте окна. Гора и шар при этом остались на месте: они
   рисуются своими слоями и от высоты секции не зависят. */
.hero {
  position: relative;
  /* Высота задана и в пикселях, и в долях экрана намеренно. Долей одной
     мало: на низком окне обложка сжималась настолько, что между лидом и
     карточкой подбора не оставалось полосы, куда встаёт знак, — и он
     уезжал под карточку. Пиксельные границы эту полосу удерживают.

     ЧИСЛА ВЫРОСЛИ ВДВОЕ, и это главная правка обложки. Было
     clamp(430px, 58vh, 640px) — обложка была нарочно ужата под белую
     плиту подбора шириной 1040 и высотой под 400px. Плиты больше нет:
     подбор стал горизонтальной строкой, и ограничение ушло вместе с ней.

     82vh, а не 100: под нижней кромкой обязана оставаться видимой макушка
     строки подбора — иначе первый экран не говорит, что страница
     продолжается. Потолок 860 не даёт кадру распухнуть на большом
     мониторе, пол 560 держит полосу для знака на низком окне. */
  min-height: clamp(560px, 82vh, 860px);
  display: flex;
  align-items: center;
  /* Сверху — ровно шапка плюс воздух: она fixed и места в потоке не
     занимает. Снизу — просвет до строки подбора, которая выезжает на
     обложку на 44px.

     Набор стоит по центру кадра, а не прижат к верху: обложка теперь
     высокая, и прижатый к шапке текст оставлял бы под собой полэкрана
     пустой фотографии — ровно тот дефект, из-за которого знак когда-то
     читался пятном. align-items: center решает это без единого числа. */
  padding: calc(var(--head-h) + clamp(14px, 3vh, 34px)) 0 clamp(96px, 12vh, 150px);
}
@media (max-width: 768px) {
  .hero {
    min-height: clamp(440px, 66vh, 580px);
    padding-top: calc(var(--head-h) + 12px);
  }
}

/* Надзаголовок. Тот же приём и та же строка, что на обложке витрины
   (.cover__eyebrow в housing/index.css): главная перенимает словарь
   витрины, а не заводит свой. Разрядка обязательна — прописные без неё
   слипаются. */
.hero__eyebrow {
  margin-bottom: 18px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .82);
  text-shadow: 0 1px 12px rgba(10, 29, 73, .6);
}
.hero__in {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--edge);
}
/* Ниже 1040 текст занимает всю ширину кадра, и справа от него знаку встать
   уже некуда. Нижнее поле обложки поэтому шире: оно и есть та полоса, куда
   знак садится целиком. Без него он оказывался разрезанным краем карточки
   (промерено на 375x812). */
@media (max-width: 1040px) {
  .hero { padding-bottom: clamp(190px, 25vh, 280px); }
}
/* ЗАГОЛОВОК ОБЛОЖКИ КРУПНЕЕ ЗАГОЛОВКОВ СЕКЦИЙ, и до этой правки было
   наоборот. Промерено на 1280: H1 давал 3.8vw = 48.64px, а .h2 рядом —
   4vw = 51.2px. То есть главный заголовок страницы был мельче каждого
   второстепенного — типографическая инверсия, которую глаз читает как
   «страница собрана без иерархии», даже не умея её назвать.

   Раньше это было почти оправдано: обложка была ужата до 58vh, и крупный
   заголовок в неё не помещался. Обложка снова высокая — и заголовок
   занимает своё место. 5.2vw против 4vw у .h2: перевес заметный на любой
   ширине, а не только на одной. */
.hero__title {
  /* fit-content, а не 24ch, и это прямо связано с шаром.

     buildTrack ищет свободное поле справа от набора по ПРАВОЙ КРОМКЕ
     ЭЛЕМЕНТА — lines[i].getBoundingClientRect().right. У блока с
     max-width: 24ch кромка стоит там, где кончается коробка, а не там,
     где кончаются буквы; а коробка в ch растёт вместе с кеглем. Стоило
     увеличить заголовок, и поле справа упало с 365px до 81 — ниже порога
     130, при котором шар уходит вниз, под текст.

     fit-content ужимает коробку до самой длинной строки (перенос задан
     <br>, так что строк ровно две). Кромка совпадает с буквами, поле
     считается честно и не зависит от кегля вовсе.

     max-width: 100% — страховка на узкий экран, где строка длиннее кадра. */
  width: fit-content;
  max-width: 100%;
  font-size: clamp(38px, 5.2vw, 68px);
  font-weight: 700;
  line-height: 1.06;
  color: #fff;
  text-shadow: 0 2px 30px rgba(10, 29, 73, .45);
}
.hero__lead {
  max-width: 52ch;
  margin-top: 22px;
  font-size: clamp(17px, 1.5vw, 20px);
  line-height: 1.6;
  color: #fff;
  text-shadow: 0 1px 14px rgba(10, 29, 73, .6);
}
.hero__still { position: absolute; right: 8%; top: 16%; z-index: 1; }
.is-still .hero__still { display: block; }

/* Блока двери здесь больше нет.

   Это была терракотовая плитка на обложке — .doors и .door с модификатором
   .door--guest, заголовком, пояснением и стрелкой, — прижатая к верхнему
   правому углу кадра. Убрана вместе с разметкой: в углу обложки такой
   плашки не бывает ни на одном сайте аренды, и читалась она куском чужой
   вёрстки. Вход в каталог стоит теперь ссылкой под окном подбора
   (.assist__all), в шапке и в подвале.

   Правила удалены, а не закомментированы: мёртвый CSS никого не бережёт,
   а история правки лежит здесь. */

/* ------------------------------------------- 3. ПОМОЩНИК — главный элемент

   Заказчик просил окно, которое бросается в глаза, и поставил его входом
   на сайт. Бросается оно композицией, а не цветом: своя плоскость сразу
   под обложкой, карточка светлее её, поднятая тень и выезд на фотографию.
   Ни одного нового оттенка, ни одной анимации — палитра та же, что у
   страницы, и всё, что карточка красит, она берёт токенами. Значит, любая
   земля U01 и любая гарнитура U01 работают здесь сами собой.

   Размеры карточки подобраны под первый экран: обложка ужата (см. .hero),
   карточка выезжает на неё на 132px, поля стоят в две колонки, а не
   стопкой, — вместе это укладывает окно целиком, до кнопки, в окно
   браузера ходовой высоты. Стопкой кнопка уходила за сгиб, и главный
   элемент переставал быть главным. */
/* Своей плоскости у секции НЕТ — и это главное про неё.

   Раньше здесь лежал ::before цвета --bg-soft. Он и обрывал фотографию
   обложки по верхней кромке секции: карточка подбора оказывалась не на
   снимке, а на светлом поле, и вокруг неё зияла пустота. Сначала её
   маскировала гряда, потом гряду убрали — и пустота осталась одна.

   Теперь секция прозрачна, и за ней виден дальний план: карточка лежит
   прямо на фотографии. Гасить снимок нечем и не нужно — это делает сам
   слой .ground, и делает он это ровно до того места, где страницу
   перехватывает первая белая секция («Квартиры»), см. frame() в app.js. */
.assist {
  position: relative;
  padding-block: 0 clamp(72px, 9vw, 112px);
}

/* ...кроме двух случаев, когда её приходится вернуть.

   Прозрачная секция держится на том, что снимок гаснет по прокрутке, а
   гасит его кадр сцены. Без движения кадра нет вовсе: .is-still .ground
   стоит absolute высотой ровно в экран, непрозрачный, и обрывался бы
   собственной нижней кромкой — горизонтальной линией посреди секции,
   рядом с карточкой. Без скриптов измерять высоту тоже нечем.

   В этих двух режимах секция берёт свою плоскость обратно, и снимок
   обрезается по её верхней кромке — то есть по границе блока. Край при
   этом прямой и совпадает с началом секции: читается нарочным. */
.is-still .assist::before,
.no-js .assist::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--bg-soft);
}
/* ---------------------------------------------- строка подбора

   Была белая плита: 1040px шириной, под 400px высотой, с надзаголовком,
   заголовком в 34px, лидом, двумя крупными полями и кнопкой. Она
   занимала полтора первых экрана, ради неё обложку ужали вдвое, и на
   снимке экрана от заказчика она обрезана нижним краем окна.

   Стала горизонтальной строкой — приём из референса (Rent H&U): три
   поля и два действия в одну линию, внахлёст на нижнюю кромку обложки.

   Что ушло вместе с плитой и почему это не потеря:
     надзаголовок «Подбор жилья» — уехал в скрытый h2 (секции нужно имя
       для aria-labelledby, глазу — нет: строка поиска объясняет себя
       подписями полей);
     заголовок «Подберём под бюджет» — обещал отбор по деньгам, которого
       нет и не будет, пока владельцы не заполнят цены;
     лид в три строки — то же самое другими словами.

   Класс .assist__card СОХРАНЁН намеренно: buildTrack берёт у него верхнюю
   кромку и по ней считает полосу, в которой стоит знак на первом экране.
   Переименование уронило бы траекторию молча. */
.assist__card {
  position: relative;
  z-index: 1;
  max-width: 1120px;
  /* Нахлёст меньше прежнего (было 56): строка ниже плиты, и глубокий
     заход съедал бы её собственную высоту, а не пустое поле карточки. */
  margin: -44px auto 0;
  padding: 18px 20px;
  background: var(--bg-alt);
  border: 1px solid var(--line);
  border-radius: var(--r-hero);
  box-shadow: var(--shadow-lift);
}
@media (max-width: 768px) { .assist__card { margin-top: -32px; padding: 16px; } }

/* Поля и действия одной линией. Бюджет чуть шире соседей — в него пишут
   число, а не выбирают из трёх строк; кнопки берут ровно свою ширину. */
.assist__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.15fr) auto;
  align-items: end;
  gap: 4px;
}

/* Разделители-волоски между полями — как в панели подбора на витрине.
   Ставятся псевдоэлементом, а не border: рамка поля живёт своей жизнью
   и меняется на фокусе, а волосок обязан стоять неподвижно. */
.assist__f { position: relative; padding: 0 16px; }
.assist__f + .assist__f::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  height: 34px;
  margin-top: -8px;
  border-left: 1px solid var(--line);
}
.assist__f .field__label { font-size: 13px; }
/* Поля внутри строки без собственной рамки: рамка одна на всю строку —
   это она и есть, .assist__card. Две вложенные рамки читаются коробкой
   в коробке. */
.assist__f .field__input {
  min-height: 40px;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  font: 600 17px/1.4 var(--font-head);
  letter-spacing: -.01em;
  color: var(--brand);
}
.assist__f .field__input:hover { border-color: transparent; }
.assist__f .field__input::placeholder { color: var(--text-mute); font-weight: 400; }
.assist__f .field__input:focus-visible { outline-offset: 4px; }

/* Стрелка селекта — та же, что на витрине, до последнего числа. */
.assist__sel {
  padding-right: 22px !important;
  -webkit-appearance: none;
  appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%230C2661' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 2px center;
  background-size: 12px 8px;
}

/* Два действия, ровно одна заливка. «Подобрать» — главное; «Все квартиры» —
   второй путь, о котором просил заказчик, и он контурный: две заливки
   рядом означали бы, что главных действий два, а их не бывает два. */
.assist__acts { display: flex; align-items: center; gap: 10px; padding-left: 12px; }
.assist__go, .assist__toAll { white-space: nowrap; min-height: 52px; }
.assist__toAll { padding-inline: 22px; }

/* Подпись под строкой. Говорит ровно то, что правда: гостей и комнаты
   отбираем сейчас, деньги — нет, потому что цен ещё нет. */
.assist__hint { margin-top: 12px; padding-inline: 16px; }

/* Пожелания словами: свёрнуты, чтобы строка оставалась строкой. */
.assist__extra { margin-top: 10px; padding-inline: 16px; }
.assist__moreBtn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  background: none;
  border: 0;
  color: var(--accent-deep);
  font: 500 15px/1.2 var(--font-body);
  cursor: pointer;
}
.assist__moreBtn:hover { color: var(--accent-deep-hover); }
.assist__moreSign {
  position: relative;
  width: 14px;
  height: 14px;
  flex: none;
}
.assist__moreSign::before, .assist__moreSign::after {
  content: "";
  position: absolute;
  inset: 50% 0 auto;
  height: 1.6px;
  background: currentColor;
  border-radius: 2px;
  transform: translateY(-50%);
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.assist__moreSign::after { transform: translateY(-50%) rotate(90deg); }
.assist__moreBtn[aria-expanded="true"] .assist__moreSign::after {
  transform: translateY(-50%) rotate(0deg);
  opacity: 0;
}
.assist__more { margin-top: 10px; max-width: 640px; }
.assist__more .field__label { display: block; margin-bottom: 8px; }
.assist__form .assist__ask { min-height: 78px; }

/* Ниже 1040 строка распадается в сетку 2×2, ещё ниже — в стопку.
   Волоски при этом снимаются: между полями появляется настоящий отступ,
   и волосок посреди него читался бы мусором. */
@media (max-width: 1040px) {
  .assist__row { grid-template-columns: 1fr 1fr; gap: 16px 4px; }
  .assist__acts { grid-column: 1 / -1; padding-left: 16px; padding-top: 4px; }
  .assist__go, .assist__toAll { flex: 1; justify-content: center; }
}
/* На телефоне строка НЕ распадается в полную стопку, и это осознанно.
   Стопка из трёх полей плюс две кнопки друг под другом давала карточку
   в 554px при обложке в 585 — то есть ровно тот же дефект, ради которого
   всю эту переделку и затеяли, только на узком экране (промерено на
   375×812).

   Поэтому два селекта остаются в одной строке — они короткие, и «Гостей»
   рядом с «Комнат» читаются парой, — а во всю ширину идут только бюджет
   и кнопки. Волоски между полями снимаются: между колонками появляется
   настоящий отступ, и волосок посреди него читался бы мусором. */
@media (max-width: 620px) {
  .assist__row { grid-template-columns: 1fr 1fr; gap: 14px 10px; }
  .assist__f { padding: 0 4px; }
  .assist__f + .assist__f::before { display: none; }
  .assist__money { grid-column: 1 / -1; }
  .assist__acts { grid-column: 1 / -1; padding-left: 4px; gap: 8px; }
  .assist__go, .assist__toAll { padding-inline: 14px; }
  .assist__hint, .assist__extra { padding-inline: 4px; }
}
/* Совсем узкие окна: кнопкам в строке уже тесно, они встают стопкой. */
@media (max-width: 400px) {
  .assist__acts { flex-direction: column; align-items: stretch; }
}

/* Место под ответ помощника. Пока пусто — не занимает ничего: пустая рамка
   на полстраницы обещала бы ответ, которого ещё нет. */
.assist__out { margin-top: 28px; }
.assist__out:empty { display: none; }
.assist__box {
  padding: clamp(20px, 2.6vw, 28px);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
}
.assist__boxTitle { font-family: var(--font-head); font-size: 18px; font-weight: 600; color: var(--brand); }
.assist__boxText { max-width: var(--measure); margin-top: 10px; font-size: 15px; line-height: 1.6; color: var(--text); }

/* ------------------------------------------- 4. Квартиры — подборка

   Первый блок подборки: заказчик просил показывать сначала квартиры и
   только «чуть ниже» — досуг. Плоскость белая, как у прежней секции жилья,
   чтобы после серой плоскости помощника читался переход к результату. */

.flats {
  position: relative;
  margin-top: 0;
  padding-block: clamp(64px, 8vw, 104px) clamp(64px, 8vw, 104px);
}
.flats::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--bg-alt); }
/* Кикера над «Квартирами» больше нет: он назывался «Целая квартира, а не
   комната» и повторял лид обложки третий раз подряд. Отбивка заголовка
   ушла вместе с ним — он теперь первый в секции. */
.flats__title { margin-top: 0; }
.flats__sub { max-width: var(--measure); margin-top: var(--under-h2); color: var(--text-mute); }

/* Видимая пометка: подборка показана целиком, а не отобрана под деньги.
   Стоит над сеткой и набрана так, чтобы её нельзя было принять за
   рекламную строку: та же дырчатая рамка, что у заглушек значений. */
.picks-note {
  max-width: 72ch;
  margin-top: 28px;
  padding: 14px 18px;
  border: 1px dashed rgba(12, 38, 97, .4);
  border-radius: var(--r-card);
  background: var(--bg-soft);
  font-size: 14px;
  line-height: 1.55;
  color: var(--text-mute);
}
.picks-note__mark { font-weight: 600; color: var(--brand); }

.flats-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gutter);
  margin-top: 36px;
}
@media (max-width: 980px) { .flats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { .flats-grid { grid-template-columns: 1fr; } }

.flat {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--bg-alt);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  overflow: hidden;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.flat:hover { transform: translateY(-4px); box-shadow: var(--shadow-lift); }
/* Кольцо фокуса рисует карточка целиком: ссылка внутри растянута
   псевдоэлементом и своей рамки не имеет. */
.flat:focus-within { outline: 3px solid var(--focus); outline-offset: 3px; }
.flat__media { position: relative; aspect-ratio: 4 / 3; background: var(--bg-soft); }
.flat__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.flat__media svg { width: 100%; height: 100%; display: block; }
.flat__badge {
  position: absolute;
  left: 12px;
  top: 12px;
  padding: 5px 12px;
  border-radius: var(--r-pill);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.flat__badge.is-real { background: rgba(255, 255, 255, .92); color: var(--brand); }
.flat__badge.is-demo { background: var(--accent-soft); color: #7A3C16; }
/* Тело тянется на всю оставшуюся высоту, а плашка цены прижата к низу:
   в ряду карточек разной длины плашки должны стоять на одной линии. */
.flat__body { flex: 1; display: flex; flex-direction: column; gap: 8px; padding: 22px; }
.flat__title { font-size: 19px; font-weight: 600; line-height: 1.25; }
.flat__link { color: var(--brand); text-decoration: none; }
.flat__link:hover { color: var(--accent); }
/* Кликается вся карточка, а ссылка в разметке одна и с осмысленным
   текстом — названием объекта. */
.flat__link::after { content: ""; position: absolute; inset: 0; }
.flat__link:focus-visible { outline: none; }
.flat__meta { font-size: 14px; color: var(--text-mute); }
.flat__lead { font-size: 14px; line-height: 1.5; color: var(--text); }
.flat__foot { margin-top: auto; padding-top: 8px; }


/* ------------------------------------------------------- пустое состояние

   Не ошибка и не пустота: спокойная карточка, которая объясняет, чего
   не хватает, и даёт дорогу обратно. */
.empty {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  max-width: var(--measure);
  margin-top: 36px;
  padding: clamp(24px, 3vw, 34px);
  background: var(--bg-soft);
  border-radius: var(--r-card);
}
.empty__title { font-size: 20px; font-weight: 600; line-height: 1.25; color: var(--brand); }
.empty p { font-size: 15px; line-height: 1.55; color: var(--text-mute); }
.empty .btn { margin-top: 8px; }
/* Два выхода из пустого состояния: ослабить условия или уйти на витрину.
   Заливка ровно одна — та же дисциплина, что в строке подбора. */
.empty__acts { display: flex; flex-wrap: wrap; gap: 12px; }
.empty__acts .btn { margin-top: 8px; }

/* --------------------------------------------------------------- заглушка

   Значение, которого у нас ещё нет. Пунктирная рамка говорит «сюда впишут»,
   и это единственный способ показать пустое поле, не выдав его за данные.
   Через .stub проходит каждая строка в квадратных скобках — цена, контакты
   в подвале, реквизиты в служебной строке. Ни одна из них не набирается
   обычным текстом: незаметная заглушка читается как
   факт, а это ровно то, чего мы не делаем.

   Тот же компонент на витрине жилья зовётся .plate (housing/base.css) —
   вид у них общий намеренно. */
.stub {
  display: inline-block;
  max-width: 100%;
  padding: 7px 14px;
  border: 1px dashed var(--line);
  border-radius: 10px;
  background: rgba(255, 255, 255, .55);
  color: var(--text-mute);
  font: 500 14px/1.35 var(--font-body);
  letter-spacing: .01em;
}

/* [hidden] обязан побеждать display: flex/grid у форм и карточек. */
[hidden] { display: none !important; }

/* поля */
.field { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.field__label { font-size: 14px; font-weight: 500; color: var(--text-mute); }
.field__input {
  width: 100%;
  min-height: 52px;
  padding: 0 18px;
  background: var(--bg-alt);
  border: 1px solid var(--line);
  border-radius: var(--r-field);
  color: var(--text);
  font: 400 16px/1.4 var(--font-body);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.field__input:hover { border-color: rgba(12, 38, 97, .28); }
.field__input:focus { border-color: var(--brand); outline-offset: 2px; }
.field__input--area { min-height: 108px; padding: 14px 18px; border-radius: var(--r-field); resize: vertical; }
.field__input[aria-invalid="true"] { border-color: var(--err-line); background: var(--err-bg); }
.field__hint { margin-top: 2px; font-size: 14px; line-height: 1.5; color: var(--text-mute); }
.field__err { margin-top: 2px; font-size: 14px; line-height: 1.5; color: var(--err); }
select.field__input { cursor: pointer; }

/* ------------------------------- 4. Пауза — белый, ТИХАЯ, узкая колонка */

.pause {
  position: relative;
  margin-top: var(--sec);
  padding-block: clamp(120px, 17vw, 220px);
}
.pause::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--bg-alt); }
.pause__col {
  position: relative;
  z-index: 1;
  max-width: 640px;
  margin-inline: auto;
  padding-inline: var(--edge);
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.pause__title { margin-bottom: 8px; }
.pause__col p { max-width: var(--measure); font-size: 18px; line-height: 1.6; }

/* ------------------------- 8. Отзывы — тёмный синий, ТИХАЯ, край-в-край */

.voices {
  position: relative;
  margin-top: var(--sec);
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  align-items: stretch;
  min-height: 74vh;
}
.voices::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--brand); }
.voices__text {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--under-h2);
  padding: clamp(72px, 10vw, 140px) clamp(28px, 5vw, 96px) clamp(72px, 10vw, 140px)
           max(var(--edge), calc((var(--vw) - var(--container)) / 2 + var(--edge)));
}
.voices__title { color: #fff; }
.voices__slot {
  max-width: 22ch;
  margin: 0;
  padding-left: 22px;
  border-left: 1px solid var(--ice);
  font-family: var(--font-head);
  font-size: clamp(20px, 2.1vw, 28px);
  font-weight: 400;
  line-height: 1.35;
  letter-spacing: -.01em;
  color: var(--brand-tint);
}
.voices__media { position: relative; z-index: 1; margin: 0; }
/* <picture> обязан быть блоком во всю высоту, иначе снимок схлопнется.
   height у <img> задан в процентах, а проценты считаются от родителя —
   и родителем стал <picture>, строчный элемент с автоматической высотой.
   Без этой строки картинка садилась бы на свой min-height в 320px вместо
   того, чтобы заполнить ленту отзывов. */
.voices__media picture { display: block; width: 100%; height: 100%; }
.voices__media img { width: 100%; height: 100%; min-height: 320px; object-fit: cover; display: block; }
@media (max-width: 860px) {
  .voices { grid-template-columns: 1fr; min-height: 0; }
  .voices__text { padding-inline: var(--edge); }
}

/* -------------------------------- 9. Регистрация — цветная плашка, средняя */

.apply { position: relative; margin-top: var(--sec-quiet); padding-block: clamp(64px, 8vw, 96px) clamp(72px, 9vw, 120px); }
.apply::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--brand-tint); }
.apply__in { max-width: 860px; }
/* Надзаголовок на цветной плашке: тон тёмный, а не приглушённый серый —
   --text-mute на --brand-tint даёт всего 3.4:1, а это подпись, а не декор. */
.apply__kicker {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink);
  opacity: .72;
}
.apply__title { margin-top: 10px; color: var(--ink); }
.apply__sub { max-width: var(--measure); margin-top: var(--under-h2); color: var(--text); }

.form { margin-top: 40px; }

/* Ряд один и полей в нём ровно три: имя, телефон, почта. Колонки равные —
   ни одно из трёх не длиннее остальных настолько, чтобы просить себе
   больше места, а равные ширины не оставляют в ряду дыр. */
.form__row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gutter); }
.form__row + .form__row { margin-top: var(--gutter); }
/* Ниже 760px три поля рядом уже не помещаются по-человечески: адрес почты
   упирается в собственную рамку. Одна колонка. */
@media (max-width: 760px) {
  .form__row { grid-template-columns: 1fr; }
}
.apply .field__label { color: var(--text); }
.apply .field__input { border-color: rgba(12, 38, 97, .22); }
.apply .field__err { color: var(--err); }

/* ------------------------------------------- согласие на обработку данных

   Стоит НАД кнопкой, а не под ней и не мелким шрифтом сбоку. Место здесь
   не декоративное: человек читает сверху вниз и обязан увидеть, на что
   соглашается, до того как нажмёт, а не после.

   Кегль тот же, что у полей, и цвет обычного текста. Согласие, набранное
   серым в десять пунктов, — приём, которым его прячут, и на сайте,
   который не печатает выдуманных цен, ему не место. */
.agree {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 12px;
  align-items: start;
  max-width: var(--measure);
  margin-top: 24px;
}
.agree__box {
  width: 22px;
  height: 22px;
  margin: 1px 0 0;
  flex: none;
  accent-color: var(--accent-deep);
  cursor: pointer;
}
.agree__label { font-size: 15px; line-height: 1.5; color: var(--text); cursor: pointer; }
.agree__label a { color: var(--accent-deep); text-underline-offset: 3px; }
.agree__box[aria-invalid="true"] { outline: 2px solid var(--err-line); outline-offset: 3px; }
/* Ошибка согласия — под самой галочкой, а не в общей строке статуса:
   иначе объяснение стоит в одном конце формы, а причина в другом. */
#aAgreeErr { max-width: var(--measure); margin-top: 8px; }

.form__foot { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 24px; margin-top: var(--to-action); }
.form__status { margin-top: 16px; font-size: 14px; color: var(--err); min-height: 1px; }
.form__status:empty { margin: 0; }

.done {
  max-width: var(--measure);
  margin-top: 40px;
  padding: 40px;
  background: var(--bg-alt);
  border-radius: var(--r-hero);
  box-shadow: var(--shadow);
}
.done__title { font-size: 28px; font-weight: 700; line-height: 1.2; color: var(--brand); }
.done__text { margin-top: 16px; color: var(--text-mute); }
.done .btn { margin-top: var(--to-action); }

/* --- вход для тех, кто уже зарегистрирован -------------------------------

   Запасная дверь, а не второе главное действие: отбита волосяной линией,
   набрана строкой и ведёт кнопкой-призраком. Спорить с «Зарегистрироваться»
   она не должна — на плашке ровно одно сплошное действие, и это оно. */
.signin {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 18px;
  max-width: var(--measure);
  margin-top: clamp(32px, 4vw, 44px);
  padding-top: clamp(24px, 3vw, 32px);
  border-top: 1px solid rgba(12, 38, 97, .22);
}
.signin__ask { color: var(--text); font-size: 16px; }
/* Кнопка-призрак на плашке --brand-tint: рамка синяя, иначе на цветном
   фоне её края теряются. */
.signin__go { border-color: rgba(12, 38, 97, .38); }
.signin__go:hover { border-color: var(--brand); }

/* Ответ шва. Занимает всю строку под кнопкой и появляется только когда
   в нём что-то есть — пустая рамка под формой не висит. */
.signin__out { flex: 1 0 100%; }
.signin__out:empty { display: none; }
.signin__box {
  margin-top: 4px;
  padding: 18px 20px;
  border-radius: var(--r-card);
  background: var(--bg-alt);
  box-shadow: var(--shadow);
}
.signin__boxTitle { font-size: 16px; font-weight: 600; color: var(--brand); }
.signin__boxText { margin-top: 6px; font-size: 15px; line-height: 1.6; color: var(--text-mute); }

.apply__still { position: absolute; right: 100%; margin-right: 48px; bottom: -24px; }
.is-still .apply__still { display: block; }
/* Слева от колонки поля уже нет — и статичный знак встаёт туда же, куда
   садится летящий на этой ширине: над заголовком, на верхней кромке
   плашки. Прежнее display:none оставляло страницу при prefers-reduced-motion
   с одним шаром вместо двух, хотя §3.6 требует второй именно у формы. */
@media (max-width: 1240px) {
  .apply__still {
    position: static;
    margin: 0 0 24px;
  }
  .apply__still svg { display: block; max-width: 100%; height: auto; }
}

/* ------------------------------------------- 9. Футер — тёмный, сетка

   Три колонки: бренд, «Гостям», контакты. Ниже — служебная строка за
   разделителем: год, реквизиты, оговорка про оплату и ссылка на
   источники снимков.

   Файла логотипа здесь больше нет. На нём нарисованы тот же шар и то же
   слово «tellway», что стоят строкой выше, — бренд повторялся трижды
   подряд, и третье вхождение было самым громким. */

.foot { position: relative; margin-top: var(--sec); padding-block: clamp(64px, 7vw, 96px) 40px; }
.foot::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--ink); }
/* Три колонки: бренд, «Гостям», контакты. Колонки «Владельцам» здесь нет,
   и причина теперь другая, чем была: раньше комментарий ссылался на блок
   «Владельцам» на самой странице — его сняли, а объяснение осталось
   указывать на несуществующее. Условий размещения на страницах сейчас нет
   вовсе: владелец узнаёт их лично, после регистрации, — и заводить в
   подвале колонку, ведущую в ту же общую форму, незачем. */
.foot__in {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 2.6fr) minmax(0, 3.4fr);
  gap: 48px var(--gutter);
}
@media (max-width: 900px) { .foot__in { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .foot__in { grid-template-columns: 1fr; gap: 36px; } }

/* Знак и название — одной строкой и одной ссылкой наверх. */
.foot__logo {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  color: #fff;
}
.foot__logo:hover { color: var(--accent); }
.brand__mark--foot { width: 30px; height: 40px; flex: none; }
.foot__name { font: 700 24px/1 var(--font-head); letter-spacing: -.02em; color: currentColor; }
.foot__slogan { max-width: 34ch; margin-top: 16px; color: var(--brand-tint); font-size: 14px; line-height: 1.55; }

.foot__h { font-size: 14px; font-weight: 600; letter-spacing: .02em; color: #fff; }
.foot__list { margin-top: 16px; display: flex; flex-direction: column; gap: 10px; }
.foot__list a { color: var(--brand-tint); text-decoration: none; border-bottom: 1px solid transparent; }
.foot__list a:hover { color: #fff; border-bottom-color: var(--accent); }
.foot__list--plain li { color: var(--brand-tint); font-size: 14px; line-height: 1.5; }

/* Заглушка на тёмном. Пунктир и на светлой земле, и здесь означает одно и
   то же — «сюда впишут», — поэтому меняются только тона, а не приём. */
.stub--dark,
.foot__list--plain .stub {
  background: rgba(193, 200, 226, .12);
  border-color: rgba(193, 200, 226, .45);
  color: #D8DDEE;
}

/* --- служебная строка ---------------------------------------------------

   Отбита волосяной линией и большим отступом: она не продолжение колонок,
   а другой уровень — год, реквизиты и ссылки, которые ищут глазами внизу
   любого сайта. */
.foot__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px 32px;
  margin-top: clamp(40px, 5vw, 64px);
  padding-top: 24px;
  border-top: 1px solid rgba(193, 200, 226, .2);
}
.foot__legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
  color: var(--brand-tint);
  font-size: 13px;
  line-height: 1.55;
}
.foot__legal .stub { font-size: 13px; padding: 5px 11px; }

.foot__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 22px;
  color: var(--brand-tint);
  font-size: 13px;
  line-height: 1.55;
}
.foot__meta a { color: #D8DDEE; text-decoration: underline; text-decoration-color: rgba(216, 221, 238, .5); }
.foot__meta a:hover { color: #fff; text-decoration-color: var(--accent); }

@media (max-width: 560px) {
  .foot__bottom { flex-direction: column; align-items: flex-start; }
}


/* ------------------------------------ простые страницы (credits.html)

   Служебная страница без обложки, сцены и колонки настроек: только текст.
   Шапка на ней та же, но плоскости под ней нет — значит, ей нужна своя
   земля и тёмная строка, иначе белые ссылки повисли бы на белом.

   Знак в шапке рисует app-plain.js той же геометрией, что и главная. */

.page-plain { background: var(--bg); }

.head--plain .head__in::before { opacity: 1; }
.head--plain .brand,
.head--plain .head__nav a { color: var(--text); }
.head--plain .brand__mark svg { filter: none; }
.head--plain .head__nav a:hover,
.head--plain .brand:hover { color: var(--accent); }

.plain { padding-block: clamp(120px, 14vh, 168px) clamp(72px, 9vw, 120px); }
.plain__in { max-width: 860px; }
.plain__kicker {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-mute);
}
.plain__title { margin-top: 10px; color: var(--brand); }
.plain__lead {
  max-width: var(--measure);
  margin-top: var(--under-h2);
  font-size: 18px;
  line-height: 1.6;
}
.plain__note {
  max-width: var(--measure);
  margin-top: 20px;
  padding: 18px 20px;
  border-radius: var(--r-card);
  background: var(--bg-soft);
  color: var(--text-mute);
  font-size: 14px;
  line-height: 1.6;
}
.plain__block { margin-top: clamp(44px, 5vw, 64px); }
.plain__h2 { font-size: clamp(22px, 2.4vw, 30px); color: var(--brand); }
.plain__sub {
  max-width: var(--measure);
  margin-top: 12px;
  color: var(--text-mute);
  font-size: 15px;
  line-height: 1.6;
}
.plain__back { margin-top: clamp(44px, 5vw, 64px); }

/* Список атрибуции. На светлой земле, в отличие от прежнего подвала:
   строки длинные, и читать их серым по тёмно-синему было тяжело. */
.credits { margin-top: 20px; display: flex; flex-direction: column; gap: 14px; }
.credits li {
  padding-left: 16px;
  border-left: 2px solid var(--line);
  color: var(--text-mute);
  font-size: 15px;
  line-height: 1.6;
}
.credits b { color: var(--brand); font-weight: 600; }
.credits a { color: var(--brand); text-decoration: underline; text-decoration-color: rgba(12, 38, 97, .35); }
.credits a:hover { color: var(--accent); text-decoration-color: var(--accent); }
/* Путь к файлу — техническая подробность: моноширинным и тише текста,
   чтобы он не спорил с именем автора, ради которого строка и стоит. */
.credits__file {
  font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;
  font-size: 13px;
  color: var(--text-mute);
  opacity: .85;
}


/* ------------------------------------- U01: сама колонка настроек

   Панель — часть этого мира, а не виджет поверх него: те же токены, те
   же радиусы, та же пилюля, что у переключателя сезона. Ни одного
   собственного цвета, ни одной собственной длительности.

   Терракоты в ней нет ни пикселя, и это не случайность: выбранная строка
   держится на --brand, как season[aria-pressed], — доля терракоты на
   странице остаётся ровно той, что была в схеме. Единственное
   терракотовое пятно, которое панель может показать, — focus-ring, а он
   и есть действие.

   Поведение по ширине:
     >=1240px  панель забирает себе полосу (--pane), страница поджимается,
               затемнения нет, читать и крутить можно с открытой панелью —
               в этом весь смысл настроек: их видно на живой странице;
     <1240px   полосы нет, панель идёт поверх с затемнением и закрывается
               по Esc, по клику мимо и кнопкой. На 390px это 88vw, почти
               весь экран, и это осознанно: настройка выбирается целиком,
               одним движением, и панель уходит. Спрятать её на телефоне
               совсем было бы отказом от требования, а половинчатая
               колонка на 390px нечитаема.
*/

/* Колонка настроек не показывается сама по себе.

   Она задумана как инструмент показа: на ней перебирают гарнитуру, фон и
   ширину, когда сайт обсуждают. Гостю она не нужна и выдаёт незаконченный
   макет — настоящие сайты вкладку «Настройки вида» у края экрана не
   держат. Поэтому по умолчанию её нет вовсе, а открывается она адресом
   index.html?cfg — класс has-cfg ставит app.js.

   Правило .no-js оставлено отдельной строкой: без скриптов класс поставить
   некому, но и панель без них не работает, и полагаться на одно лишь
   отсутствие has-cfg тут не стоит — правило говорит это прямо. */
.cfg-root { display: none; }
.has-cfg .cfg-root { display: block; }
.no-js .cfg-root { display: none; }

/* --- язычок: единственное, что видно, пока панель закрыта --- */

.cfg-tab {
  position: fixed;
  right: 0;
  top: 50%;
  z-index: 6;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 18px 9px;
  border: 1px solid var(--line);
  border-right: 0;
  border-radius: var(--r-pill) 0 0 var(--r-pill);
  background: var(--bg-alt);
  box-shadow: var(--shadow);
  color: var(--brand);
  font: 500 13px/1 var(--font-body);
  letter-spacing: .02em;
  cursor: pointer;
  transform: translateY(-50%);
  /* visibility — мгновенно при появлении и с задержкой на всю длину
     перехода при уходе. Плавная visibility означала бы, что узел ещё
     скрыт, когда на него ставят фокус, и focus() молча не сработал бы. */
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease),
              opacity var(--dur) var(--ease), visibility 0s;
}
.cfg-tab:hover { color: var(--accent); }
.cfg-tab svg { display: block; width: 17px; height: 17px; flex: none; }
/* Слово стоит вертикально: язычок закладки, а не кнопка поверх текста.
   Подпись видимая, а не только для скринридера: панель адресована
   заказчику, а не разработчику. */
.cfg-tab__word { writing-mode: vertical-rl; text-orientation: mixed; }
.cfg-open .cfg-tab {
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur) var(--ease), visibility 0s linear var(--dur);
}

/* На телефоне язычок стоит на той же полосе, что и текст: колонка занимает
   всю ширину за вычетом --edge (20px), а язычок съедает 34px справа —
   и заходил на строку до 10px. Промерено на 375: обложка и пауза.

   Лечится не сдвигом язычка (двигать его некуда — он и так у самого края),
   а тем, что колонка уступает ему полосу: --edge справа становится шире
   язычка. Слева поле остаётся прежним — намеренно: одинаковые поля увели
   бы весь текст от левого края ради элемента, который стоит справа. */
@media (max-width: 620px) {
  .wrap, .pause__col, .hero__in { padding-right: 54px; }
}

/* --- затемнение: только там, где панель идёт поверх --- */

.cfg-scrim {
  position: fixed;
  inset: 0;
  z-index: 6;
  background: rgba(10, 29, 73, .42);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur) var(--ease), visibility 0s linear var(--dur);
}
.cfg-open .cfg-scrim {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--dur) var(--ease), visibility 0s;
}
@media (min-width: 1240px) { .cfg-scrim { display: none; } }

/* --- панель --- */

@media (min-width: 1240px) { .cfg-open { --pane: 340px; } }

.cfg {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 7;
  width: min(340px, 88vw);
  display: flex;
  flex-direction: column;
  background: var(--bg-alt);
  border-left: 1px solid var(--line);
  box-shadow: -18px 0 44px rgba(20, 32, 26, .10);
  transform: translateX(100%);
  visibility: hidden;
  transition: transform var(--dur) var(--ease), visibility 0s linear var(--dur);
}
.cfg-open .cfg {
  transform: none;
  visibility: visible;
  transition: transform var(--dur) var(--ease), visibility 0s;
}

/* Выключенное движение выключается и здесь: обещали, что стоит всё. */
.is-still .cfg, .is-still .cfg-scrim, .is-still .cfg-tab { transition: none; }

.cfg__head {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 20px 24px 14px;
  border-bottom: 1px solid var(--line);
}
.cfg__title { font-size: 20px; font-weight: 700; line-height: 1.2; color: var(--brand); }
.cfg__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex: none;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--brand);
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.cfg__close:hover { background: var(--bg-soft); color: var(--accent); }
.cfg__close svg { display: block; width: 15px; height: 15px; }

.cfg__body {
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 20px 24px 28px;
}
.cfg__note { margin-bottom: 24px; font-size: 13px; line-height: 1.5; color: var(--text-mute); }

.cfg__group { margin: 0; padding: 0; border: 0; min-width: 0; }
.cfg__group + .cfg__group { margin-top: 28px; }
.cfg__legend { padding: 0; margin-bottom: 10px; font-size: 14px; font-weight: 500; color: var(--text-mute); }
.cfg__opts { display: flex; flex-direction: column; gap: 6px; }
.cfg__hintOff { margin-top: 10px; font-size: 13px; line-height: 1.45; color: var(--text-mute); }

/* Строка выбора — настоящий radio в настоящем fieldset: имя группы,
   состояние и стрелки клавиатуры достаются от браузера, а не
   переписываются на JS. */
.opt { position: relative; display: block; min-width: 0; }
.opt__in { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; pointer-events: none; }
.opt__face {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 48px;
  padding: 8px 18px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--text);
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.opt:hover .opt__face { background: var(--bg-soft); }
.opt__in:checked ~ .opt__face { background: var(--brand); border-color: var(--brand); color: #fff; }
.opt:hover .opt__in:checked ~ .opt__face { background: var(--ink); border-color: var(--ink); }
.opt__in:focus-visible ~ .opt__face { outline: 2px solid var(--focus); outline-offset: 3px; }
.opt__in:disabled ~ .opt__face { opacity: .55; cursor: not-allowed; }

.opt__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.opt__name { font-size: 16px; font-weight: 500; line-height: 1.25; }
.opt__hint { font-size: 13px; line-height: 1.35; color: var(--text-mute); }
.opt__in:checked ~ .opt__face .opt__hint { color: var(--brand-tint); }

/* Образец земли — круглая капля её цвета. Не пилюля 26x18: вытянутая,
   она в строке выбора читалась бы выключателем, а выключателя здесь нет. */
.opt__chip {
  width: 20px;
  height: 20px;
  flex: none;
  border: 1px solid rgba(12, 38, 97, .25);
  border-radius: var(--r-pill);
}
.opt__chip--snow  { background: #F6F6F2; }
.opt__chip--paper { background: #F2EADC; }
.opt__chip--ice   { background: #E8EFF6; }
.opt__chip--dusk  { background: #DDE3EC; }

.cfg__foot {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  padding: 16px 24px calc(20px + 76px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--line);
}
/* Панель сравнения вариантов стоит внизу экрана и на узких переносится
   в два-три ряда: низ колонки уступает ей место, а не спорит с ней. */
@media (max-width: 760px) {
  .cfg__foot { padding-bottom: calc(20px + 116px + env(safe-area-inset-bottom, 0px)); }
}
/* Кнопка возврата — тот же ghost, только в масштабе панели. Стрелка
   вправо у неё снимается: она уводит вперёд, а эта кнопка возвращает. */
.cfg__reset { min-height: 46px; padding: 0 20px; font-size: 16px; }
.cfg__reset::after { display: none; }
.cfg__saved { font-size: 13px; line-height: 1.45; color: var(--text-mute); }

@media (max-width: 700px) {
  .cfg__head { padding-inline: 20px; }
  .cfg__body { padding-inline: 20px; }
  .cfg__foot { padding-inline: 20px; }
  .cfg-tab { padding: 15px 8px; }
}

/* ---------------------------------------------------------- reduced motion */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .js .reveal { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------- без скриптов

   Сообщение в <noscript>. Видно только тому, у кого выключен JavaScript,
   поэтому оформление намеренно скромное: это не блок страницы, а
   объяснение, почему часть страницы пуста. Тон предупреждения, а не
   ошибки — сайт не сломан, он просто наполовину. */
.nojs {
  max-width: var(--measure);
  margin: calc(var(--head-h) + 24px) auto 0;
  padding: 22px 24px;
  background: var(--accent-soft);
  border-radius: var(--r-card);
  color: var(--text);
}
.nojs__title { font-family: var(--font-head); font-size: 18px; font-weight: 600; color: var(--brand); }
.nojs p { margin-top: 8px; font-size: 15px; line-height: 1.6; }
.nojs p:first-child { margin-top: 0; }
.nojs a { color: var(--accent-deep); }


/* Tourism entry keeps the measured balloon anchors: #form and .assist__card. */
.hero{min-height:0!important;height:auto!important;padding-top:135px!important;padding-bottom:125px!important}
.hero__title{width:fit-content;font-size:clamp(40px,5.2vw,68px)}
.hero__lead{max-width:40ch;font-size:17px;margin-top:18px}
.assist__card{margin-top:-38px!important;padding:25px 30px!important}
.trip-eyebrow{font-size:10px;font-weight:650;letter-spacing:.17em;margin:0 0 12px;color:#a46d48}
.trip-prompt{font-size:clamp(21px,2.3vw,29px);line-height:1.25;margin:0 0 16px;letter-spacing:-.7px}
.trip-compose{display:flex;gap:14px;align-items:center;border:1px solid #d7dfe8;border-radius:15px;padding:10px 12px 10px 18px;background:#fff}
.trip-compose:focus-within{border-color:#ae704b;box-shadow:0 0 0 3px #b3582910}
.trip-input{font:inherit;font-size:15px;line-height:1.6;resize:vertical;width:100%;min-width:0;min-height:50px;max-height:150px;border:0;background:transparent;outline:none;color:#142b51}
.trip-compose .btn{font-size:13px;white-space:nowrap;padding:14px 18px;flex:none}
.trip-compose .btn span{margin-left:16px}
.trip-examples{display:flex;flex-wrap:wrap;gap:8px;margin-top:13px}
.trip-examples button{border:1px solid #e2e5e9;border-radius:20px;padding:8px 12px;font:inherit;font-size:11px;color:#5c6a7f;background:#fff;cursor:pointer}
.trip-examples button:hover{border-color:#b3582c;color:#a14e24}
.trip-doors{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px;margin-top:30px}
.trip-door{display:flex;flex-direction:column;border:1px solid #dce2e8;border-radius:22px;padding:27px;min-height:300px;color:#153154;background:#f4f6f8;text-decoration:none;overflow:hidden}
.trip-door--activity{background:#153154;color:#fff;border-color:#153154}.trip-door--help{background:#f2e9df;border-color:#e5d4c3}
.trip-door__number{font-size:9px;font-weight:600;letter-spacing:.15em;opacity:.7}.trip-door__icon{font-size:58px;line-height:1.4;font-weight:300;color:#b97950;margin:10px 0}.trip-door--activity .trip-door__icon{color:#dbb084}
.trip-door h3{font-size:25px;letter-spacing:-.7px;margin:5px 0 12px}.trip-door p{font-size:13px;line-height:1.75;max-width:28ch;opacity:.8;margin:0 0 24px}.trip-door__link{display:flex;align-items:center;justify-content:space-between;border-top:1px solid #8090a333;padding-top:16px;margin-top:auto;font-size:12px}.trip-door__link span{font-size:20px}
.trip-door:focus-visible,.trip-examples button:focus-visible{outline:3px solid #b3582c;outline-offset:4px}
@media(min-width:1500px){.hero{padding-top:160px!important;padding-bottom:150px!important}}
@media(max-width:1040px){.hero{padding-top:125px!important;padding-bottom:130px!important}.hero__lead{max-width:34ch}}
@media(max-width:700px){.hero{padding-top:110px!important;padding-bottom:125px!important}.hero__title{font-size:44px}.hero__lead{max-width:30ch;font-size:15px;line-height:1.55}.hero__eyebrow{font-size:10px}.assist__card{padding:20px!important;margin-top:-20px!important}.trip-compose{display:block;padding:10px 12px}.trip-input{font-size:16px;min-height:76px}.trip-compose .btn{width:100%;margin-top:8px;display:flex;justify-content:space-between}.trip-examples{gap:6px}.trip-examples button{font-size:10px;padding:7px 9px}.trip-doors{grid-template-columns:1fr;gap:14px}.trip-door{min-height:240px;padding:24px}.trip-door__icon{font-size:48px;margin:0}.trip-door h3{margin-top:0}.trip-door p{max-width:35ch;margin-bottom:16px}}
@media(prefers-reduced-motion:no-preference){.trip-door{transition:transform .2s ease,box-shadow .2s ease}.trip-door:hover{transform:translateY(-4px);box-shadow:0 12px 26px #10265010}}

.trip-compose .btn::after{display:none}

body:has(.trip-compose) .tw-launcher{display:none}

.journey-section{padding:32px 0 70px;background:#f4f6f8;color:#153154}.journey-heading{display:flex;align-items:end;justify-content:space-between;gap:28px;margin:0 0 28px}.journey-heading h2{max-width:15ch;margin:0}.journey-heading p{font-size:14px;line-height:1.75;color:#647386;margin:0}.journey-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}.journey-idea{display:flex;flex-direction:column;padding:0;text-align:left;background:#fff;border:1px solid #dce2e8;border-radius:22px;overflow:hidden;cursor:pointer;font:inherit;color:inherit;min-width:0}.journey-art{display:block;position:relative;width:100%;height:155px;overflow:hidden;background:#d9e5e8}.journey-art b{position:absolute;top:18px;left:22px;font-size:11px;font-weight:500;letter-spacing:2px;opacity:.6}.journey-art:before,.journey-art:after,.journey-art i{content:'';position:absolute;display:block}.journey-idea--mountains .journey-art:before{width:160px;height:160px;background:#7996a4;transform:rotate(45deg);left:18%;top:75px;border-radius:9px}.journey-idea--mountains .journey-art:after{width:130px;height:130px;background:#43677c;transform:rotate(45deg);left:52%;top:94px;border-radius:9px}.journey-idea--mountains .journey-art i{width:42px;height:42px;border-radius:50%;background:#fbf6e9;left:65%;top:27px}.journey-idea--north .journey-art{background:#173955}.journey-idea--north .journey-art:before{width:260px;height:130px;transform:rotate(-24deg);left:10%;top:25px;border-radius:50%;border-top:26px solid #78b1a9;filter:blur(14px)}.journey-idea--north .journey-art:after{width:4px;height:4px;left:20%;top:35px;background:#fff;border-radius:50%;box-shadow:85px 64px #fff,155px -10px #fff,190px 50px #fff}.journey-idea--north .journey-art b{color:white}.journey-idea--active .journey-art{background:#eedfcf}.journey-idea--active .journey-art:before{width:250px;height:200px;left:15%;top:70px;border-radius:50%;border:2px dashed #aa7755;transform:rotate(-30deg)}.journey-idea--active .journey-art:after{width:120px;height:120px;left:50%;top:65px;background:#c58a60;clip-path:polygon(0 100%,50% 0,100% 100%)}.journey-idea--active .journey-art i{width:32px;height:32px;left:23%;top:50px;background:#ad6540;border-radius:50%}.journey-copy{display:flex;flex:1;flex-direction:column;padding:24px}.journey-copy small{font-size:9px;letter-spacing:1.3px;color:#9b6b4c;margin-bottom:12px}.journey-copy strong{font-size:24px;line-height:1.2;font-weight:500;letter-spacing:-.7px;margin-bottom:13px}.journey-copy>span{font-size:13px;line-height:1.8;color:#647386;margin-bottom:25px}.journey-copy em{font-style:normal;font-size:12px;border-top:1px solid #e3e8ed;padding-top:16px;margin-top:auto}.journey-note{font-size:12px;color:#647386;line-height:1.7;max-width:720px;margin:20px 0 0}.journey-idea:focus-visible{outline:3px solid #b3582c;outline-offset:4px}@media(prefers-reduced-motion:no-preference){.journey-idea{transition:transform .2s,box-shadow .2s}.journey-idea:hover{transform:translateY(-4px);box-shadow:0 12px 24px #1531540c}}@media(max-width:850px){.journey-grid{gap:12px}.journey-copy{padding:18px}.journey-copy strong{font-size:21px}.journey-heading{display:block}.journey-heading p{margin-top:16px}}@media(max-width:600px){.journey-section{padding:30px 0 42px}.journey-grid{grid-template-columns:1fr;gap:16px}.journey-art{height:135px}.journey-copy{padding:22px}.journey-copy strong{font-size:26px}}
