/* ==========================================================================
   Components — built on the tokens defined in main.css.
   Loaded as a second stylesheet so the two files download in parallel and
   layout-critical tokens are never blocked behind component rules.
   ========================================================================== */

/* --- icons ---------------------------------------------------------------- */

.icon { width: 1.15em; height: 1.15em; flex: none; vertical-align: -.16em; }
.icon--sm { width: 1em; height: 1em; }

/* --- media / placeholders ------------------------------------------------- */

.media { display: block; position: relative; overflow: hidden; background: var(--surface-alt); }
.media__img { width: 100%; height: 100%; object-fit: cover; }

.media__placeholder {
  display: grid;
  place-items: center;
  gap: .5rem;
  width: 100%;
  height: 100%;
  min-height: 180px;
  color: rgba(255, 255, 255, .34);
}
.media__placeholder-icon { width: 46px; height: 46px; }
.media__placeholder--lg { min-height: 260px; }
.media__placeholder-note {
  font-size: .82rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .5);
}

/* --- hero ----------------------------------------------------------------- */

.hero {
  position: relative;
  color: var(--text-invert);
  background: var(--neva);
  padding: 2.75rem 0 2.25rem;
  overflow: hidden;
}

/* Обложка. Кадр лежит слоем ниже вуали и текста; на телефоне <picture>
   подставляет прозрачный пиксель, поэтому там остаётся один градиент. */
.hero__art {
  position: absolute;
  inset: 0;
  display: block;
}
.hero__art img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Кадр 16:9 в плашке шире 2:1 обрезается сверху и снизу. Сдвигаем окно
     вверх: горизонт с огнями уходит в нижнюю треть, а шпиль Петропавловки
     остаётся в кадре. */
  object-position: 50% 38%;
  display: block;
}

/* На телефоне картинки нет — работает прежний градиент «Нева в сумерках». */
.hero__bg {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 90% at 78% -10%, rgba(216, 171, 72, .30), transparent 58%),
    radial-gradient(90% 70% at 8% 8%, rgba(120, 165, 210, .22), transparent 60%),
    linear-gradient(178deg, #16273c 0%, #0f1c2e 62%, #0c1725 100%);
}

/* Поверх кадра — только вуаль под текст: слева плотнее (заголовок и лид),
   сверху и снизу лёгкое затемнение под строку с цифрами. Справа кадр открыт:
   там Адмиралтейство и Исаакий, ради которых обложка и нужна. */
@media (min-width: 700px) {
  .hero__bg {
    background:
      linear-gradient(90deg, rgba(9, 17, 28, .78), rgba(9, 17, 28, .5) 44%, rgba(9, 17, 28, .16)),
      linear-gradient(180deg, rgba(9, 17, 28, .5), transparent 30%, transparent 58%, rgba(9, 17, 28, .72));
  }
}

.hero__inner { position: relative; }
.hero__title { margin: 0 0 .5rem; font-size: clamp(1.85rem, 1.2rem + 3vw, 3.15rem); letter-spacing: -.025em; }

/* Слоган. Набран золотым и в тот же серифный шрифт, что заголовки: рядом с
   белым заголовком и приглушённым лидом он иначе смотрелся бы третьим
   абзацем текста, а это отдельная строка-подпись. */
.hero__slogan {
  margin: 0 0 .9rem;
  font-family: var(--font-display);
  font-size: clamp(1.05rem, .9rem + .7vw, 1.35rem);
  color: var(--gold-bright);
  letter-spacing: .01em;
}

.hero__lead { max-width: 46ch; color: rgba(220, 231, 242, .84); font-size: 1.02rem; margin-bottom: 1.6rem; }

.hero__actions { display: flex; flex-wrap: wrap; gap: .7rem; margin: 0; }

/* Вторая кнопка на тёмном фоне. Обычный `.btn--ghost` здесь не годится: он
   белый и рядом с золотой кнопкой читается как вторая главная. Прозрачная
   с тонкой рамкой держит иерархию — журнал первый, квартиры вторые. */
.btn--ondark {
  background: rgba(247, 245, 241, .08);
  color: var(--text-invert);
  border-color: rgba(220, 231, 242, .45);
}
.btn--ondark:hover { background: rgba(247, 245, 241, .16); border-color: rgba(220, 231, 242, .75); }

.hero__stats {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem 1.75rem;
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
  font-size: .89rem;
  color: rgba(220, 231, 242, .72);
}
.hero__stats strong { color: var(--gold-bright); font-weight: 700; }

/* Плашке нужна высота, иначе от обложки видно только две полоски. Прежние
   44rem были посчитаны под карточку поиска в центре кадра: она занимала всё,
   кроме 72 px сверху и 55 px снизу. Карточка уехала в свой раздел, контента
   осталось на треть меньше — и на 44rem под кнопками зияла пустота во весь
   экран. 30rem держит панораму читаемой и не выталкивает журнал за сгиб.
   Контент центрируем по вертикали, слои фона лежат вне потока. */
@media (min-width: 900px) {
  .hero {
    padding: 4rem 0 3.5rem;
    min-height: 30rem;
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
}

/* --- search form ---------------------------------------------------------- */

.search-form {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 1rem;
  box-shadow: var(--shadow-lg);
  color: var(--text);
}
/* Ширину не режем: форма стоит в том же `.wrap`, что заголовок, счётчики под
   ней и карточки следующей секции. Стояло 940px при контентной области 1148px —
   строка поиска не доходила до правого края и выпадала из общей сетки страницы.
   В каталоге такого ограничения нет, из-за чего две страницы выглядели по-разному. */
.search-form--hero { width: 100%; }
.search-form__grid { display: grid; gap: .75rem; grid-template-columns: 1fr; }
.search-form__city-input { background: var(--surface-alt); color: var(--text-muted); cursor: default; }
.search-form__submit { min-height: 46px; }
.search-form__note { margin: .85rem .25rem 0; font-size: .82rem; color: var(--text-muted); }

@media (min-width: 620px) {
  .search-form__grid { grid-template-columns: repeat(2, 1fr); }
  .search-form__submit { grid-column: 1 / -1; }
}

@media (min-width: 980px) {
  .search-form { padding: 1.1rem 1.25rem; }
  .search-form__grid { grid-template-columns: 1.3fr 1fr 1fr .9fr 1.1fr auto; align-items: end; }
  .search-form__submit { grid-column: auto; align-self: end; }
}

.catalog .search-form {
  box-shadow: var(--shadow-sm);
  border: 1px solid var(--border-soft);
  margin-bottom: 1.5rem;
}

/* --- apartment card ------------------------------------------------------- */

.apt-card { display: flex; flex-direction: column; }
.apt-card__media { aspect-ratio: 4 / 3; }

.apt-card__badge {
  position: absolute;
  top: .7rem; left: .7rem;
  background: rgba(15, 28, 46, .86);
  color: var(--gold-bright);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: .28rem .6rem;
  border-radius: 7px;
}

.apt-card__body { padding: .95rem 1rem 1.05rem; display: flex; flex-direction: column; gap: .55rem; flex: 1; }
.apt-card__meta { font-size: .82rem; color: var(--text-muted); }
.apt-card__metro { display: inline-flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.apt-card__walk { opacity: .8; }
.apt-card__title { margin: 0; font-size: 1.06rem; line-height: 1.34; }
.apt-card__title a { text-decoration: none; }
.apt-card__title a:hover { color: var(--gold); }

.apt-card__facts,
.apt-card__amenities {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  margin: 0;
  padding: 0;
  color: var(--text-muted);
}
.apt-card__facts { gap: .35rem .9rem; font-size: .86rem; }
.apt-card__amenities { gap: .3rem .75rem; font-size: .78rem; }
.apt-card__facts li,
.apt-card__amenities li { display: inline-flex; align-items: center; gap: .3rem; }

.apt-card__foot {
  margin-top: auto;
  padding-top: .7rem;
  border-top: 1px solid var(--border-soft);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
}

.price { margin: 0; display: flex; align-items: baseline; gap: .35rem; flex-wrap: wrap; }
.price__value { font-size: 1.16rem; font-weight: 700; letter-spacing: -.01em; }
.price__unit { font-size: .8rem; color: var(--text-muted); }

.apt-card__link {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  font-size: .87rem;
  font-weight: 600;
  color: var(--gold);
  text-decoration: none;
  white-space: nowrap;
}
.apt-card__link:hover { text-decoration: underline; }

/* --- сегментированный переключатель (гости) -------------------------------- */

/* Высота как у соседних полей: в строке поиска группа стоит рядом с датами,
   и без этого её подпись съезжала вниз относительно «ЗАЕЗД» и «РАЙОН». */
.segmented {
  display: flex;
  align-items: stretch;
  gap: 2px;
  min-height: 46px;
  padding: 2px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-alt);
}

/* Радиокнопку прячем, но оставляем в потоке: она должна получать фокус
   с клавиатуры, иначе группу не переключить стрелками. */
.segmented__input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.segmented__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 auto;
  min-width: 2.1rem;
  padding: .45rem .3rem;
  border-radius: calc(var(--radius-sm) - 2px);
  font-size: .88rem;
  font-weight: 600;
  line-height: 1.1;
  text-align: center;
  color: var(--text-muted);
  cursor: pointer;
  user-select: none;
  transition: background .15s ease, color .15s ease;
}
.segmented__btn:hover { color: var(--text); }

.segmented__input:checked + .segmented__btn {
  background: var(--neva);
  color: var(--text-invert);
}
.segmented__input:focus-visible + .segmented__btn {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
}

/* «Любое» — слово среди цифр, ему нужно больше места, но растягивать группу
   оно не должно. */
.segmented__btn:first-of-type { flex: 0 0 auto; padding-inline: .6rem; }


/* --- карточки районов ----------------------------------------------------- */

.dcards {
  display: grid;
  gap: .85rem;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}

.dcard {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  gap: .9rem;
  min-height: 132px;
  padding: .95rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: inherit;
  text-decoration: none;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.dcard:hover {
  transform: translateY(-3px);
  border-color: var(--gold);
  box-shadow: var(--shadow-md);
}

/* Силуэт стоит отдельной колонкой, а не подложкой под текстом: перекрывать его
   буквами пришлось бы растушёвкой, а она съедает как раз середину города, где
   и находится большинство районов. Обрезать край тоже нельзя — подсвеченный
   район попадёт в отрезанное, и карточка перестанет отвечать на свой
   единственный вопрос «где это». */
.dcard__map {
  flex: 0 0 104px;
  align-self: center;
  pointer-events: none;
}
.dcard__map svg { display: block; width: 100%; height: auto; }
.dcard__map use { fill: var(--surface-alt); }

/* Центральный район — сороковая часть города: залитый цветом, он превращается
   в точку. Обводка тем же цветом раздувает фигуру на пару пикселей и делает
   её заметной, не превращая в кляксу. */
.dcard__here {
  fill: var(--gold);
  stroke: var(--gold);
  stroke-width: 5;
  stroke-linejoin: round;
  paint-order: stroke;
}
.dcard:hover .dcard__here { fill: var(--gold-bright); stroke: var(--gold-bright); }

.dcard__body { display: grid; gap: .3rem; min-width: 0; }
.dcard__name { font-weight: 700; font-size: 1.05rem; line-height: 1.2; }
.dcard__note {
  font-size: .8rem;
  color: var(--text-muted);
  line-height: 1.35;
}
.dcard__facts {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: .5rem;
  margin-top: .2rem;
  font-size: .84rem;
}
.dcard__facts b { font-size: .95rem; }
.dcard__count { color: var(--text-muted); }

@media (prefers-color-scheme: dark) {
  .dcard__map use { fill: #223044; }
}


/* --- station list --------------------------------------------------------- */

.station-list {
  display: grid;
  gap: .5rem;
  grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
  list-style: none;
  margin: 0;
  padding: 0;
}

.station-list a {
  display: flex;
  align-items: center;
  gap: .55rem;
  padding: .7rem .85rem;
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm);
  text-decoration: none;
  font-size: .93rem;
  transition: border-color .18s var(--ease), transform .18s var(--ease);
}
.station-list a:hover { border-color: var(--gold); transform: translateX(2px); }
.station-list__name { flex: 1; }
.station-list__count {
  font-size: .78rem;
  color: var(--text-muted);
  background: var(--surface-alt);
  border-radius: 999px;
  padding: .1rem .5rem;
}

/* Закрытая станция: приглушаем, но не прячем — страница станции нужна, на ней
   написано, до какого срока закрыта. Одного цвета мало, поэтому есть и слово. */
.station-list a.is-closed .station-list__name { color: var(--text-muted); text-decoration: line-through; }
.station-list__closed {
  font-size: .78rem;
  color: var(--warn);
  background: var(--warn-bg);
  border-radius: 999px;
  padding: .1rem .5rem;
  white-space: nowrap;
}

/* --- notice --------------------------------------------------------------- */

.notice {
  display: flex;
  align-items: flex-start;
  gap: .55rem;
  margin: 1rem 0;
  padding: .75rem .9rem;
  border-radius: var(--radius-sm);
  font-size: .92rem;
  line-height: 1.45;
}
.notice .icon { flex: none; margin-top: .15rem; }
.notice--warning { color: var(--warn); background: var(--warn-bg); }

/* --- steps ---------------------------------------------------------------- */

.steps {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
}
.steps li { position: relative; padding-left: 3rem; }
.steps h3 { margin-bottom: .3rem; font-size: 1.05rem; }
.steps p { color: var(--text-muted); font-size: .92rem; margin: 0; }
.steps__num {
  position: absolute;
  left: 0; top: 0;
  display: grid;
  place-items: center;
  width: 34px; height: 34px;
  border-radius: 50%;
  background: var(--neva);
  color: var(--gold-bright);
  font-weight: 700;
  font-size: .95rem;
}

/* --- attraction / article cards ------------------------------------------ */

.attr-card__media, .art-card__media { aspect-ratio: 3 / 2; }
.attr-card__body, .art-card__body { padding: .9rem 1rem 1rem; }
.attr-card h3, .art-card h3 { font-size: 1.02rem; margin-bottom: .35rem; }
.attr-card h3 a, .art-card h3 a { text-decoration: none; }
.attr-card h3 a:hover, .art-card h3 a:hover { color: var(--gold); }
.attr-card p, .art-card p { color: var(--text-muted); font-size: .89rem; margin: 0 0 .5rem; }
.attr-card__meta, .art-card__meta {
  display: flex;
  gap: .4rem;
  flex-wrap: wrap;
  margin: 0;
  font-size: .82rem;
  color: var(--text-muted);
}

/* Рубрика над заголовком карточки — единственная подпись, которая говорит, о
   чём материал, до того как читатель дочитает заголовок.

   Селектор из двух классов не для красоты: правило `.art-card p` выше — это
   класс плюс тип, оно специфичнее одиночного `.art-card__rubric` и перебивало
   и кегль, и цвет. Рубрика выходила серым текстом в размер абзаца — выглядело
   правдоподобно ровно настолько, чтобы это пропустить. */
.art-card .art-card__rubric {
  margin: 0 0 .3rem;
  font-size: .74rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  /* Не `--gold`: на 12 px тот даёт 3.2:1 на белом при норме 4.5:1. */
  color: var(--gold-ink);
}
.art-card__rubric a { color: inherit; text-decoration: none; }
.art-card__rubric a:hover { text-decoration: underline; }

/* Ведущая статья журнального блока. До 760 px это обычная карточка, выше —
   две колонки: кадр слева, текст справа по центру высоты. Обложка тянется на
   всю высоту карточки (`aspect-ratio` снимаем — иначе колонки разъезжаются:
   у текста высота своя, у кадра своя).

   Крупнее делается только сам анонс (`.art-card__excerpt`), а не все абзацы
   карточки: `.art-card--lead p` тянул за собой рубрику и строку «мин чтения»,
   и подписи вырастали до размера основного текста. */
.art-card--lead .art-card__body { padding: 1.1rem 1.2rem 1.2rem; }
.art-card--lead h3 { font-size: 1.2rem; }
.art-card--lead .art-card__excerpt { font-size: .95rem; }

@media (min-width: 760px) {
  .art-card--lead { display: grid; grid-template-columns: 1.05fr 1fr; align-items: stretch; }
  .art-card--lead .art-card__media { aspect-ratio: auto; height: 100%; min-height: 17rem; }
  .art-card--lead .art-card__body {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 1.75rem 2rem;
  }
  .art-card--lead h3 { font-size: 1.55rem; line-height: 1.25; margin-bottom: .5rem; }
  .art-card--lead .art-card__excerpt { font-size: 1rem; }
}

/* --- catalog -------------------------------------------------------------- */

.catalog { padding-block: 1.75rem 1rem; }  /* только вертикальные: `.wrap catalog` теряет боковые от сокращённой записи */
.catalog__head { margin-bottom: 1.25rem; }
.catalog__head h1 { margin-bottom: .4rem; }
.catalog__intro { color: var(--text-muted); max-width: 68ch; }

.catalog__layout { display: grid; gap: 1.5rem; grid-template-columns: 1fr; align-items: start; }

@media (min-width: 960px) {
  .catalog__layout { grid-template-columns: 264px 1fr; gap: 2rem; }
}

/* Filters: a disclosure on mobile, a permanent panel on desktop. */
.filters { background: var(--surface); border: 1px solid var(--border-soft); border-radius: var(--radius); overflow: hidden; }

.filters__summary {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .85rem 1rem;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}
.filters__summary::-webkit-details-marker { display: none; }
.filters__summary::after { content: "▾"; margin-left: auto; opacity: .55; }
.filters__toggle[open] .filters__summary::after { content: "▴"; }

.filters__count {
  background: var(--gold);
  color: #23180a;
  font-size: .72rem;
  font-weight: 700;
  border-radius: 999px;
  padding: .05rem .45rem;
}

/* Форма — сосед <details>, поэтому её показывает состояние соседа. */
.filters__form { display: none; padding: 0 1rem 1.1rem; gap: 1rem; }
.filters__toggle[open] ~ .filters__form { display: grid; }
.filters__group { display: grid; gap: .35rem; }
.filters__range { display: flex; align-items: center; gap: .4rem; }
.filters__range input { min-width: 0; }

.filters__checks { list-style: none; margin: 0; padding: 0; display: grid; gap: .45rem; }
.filters__checks label { display: flex; align-items: center; gap: .5rem; font-size: .91rem; cursor: pointer; }
.filters__checks input { width: 18px; height: 18px; min-height: 0; accent-color: var(--gold); }

.filters__actions { display: grid; gap: .6rem; justify-items: center; }
.filters__reset { font-size: .85rem; color: var(--text-muted); }

@media (min-width: 960px) {
  /* Кнопка не нужна: панель открыта всегда. Прячем весь <details>, а форму
     показываем независимо от того, открыт он или нет. */
  .filters__toggle { display: none; }
  .filters__form { display: grid; padding-top: 1.1rem; }
  .filters { position: sticky; top: 78px; }
}

.catalog__toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.catalog__summary { margin: 0; font-weight: 600; }
.catalog__sort { display: flex; align-items: center; gap: .5rem; }
.catalog__sort .form-label { margin: 0; white-space: nowrap; }
.catalog__sort select { min-height: 40px; padding-block: .35rem; }

.btn--sm { padding: .45rem .9rem; font-size: .86rem; }

.catalog__active { margin-bottom: 1.15rem; }
.chip--removable { background: var(--neva); color: var(--text-invert); }
.chip--removable:hover { background: var(--err); border-color: transparent; color: #fff; }
.chip__muted { opacity: .7; }

/* --- apartment page ------------------------------------------------------- */

.apt { padding-block: 1.5rem 1rem; }  /* см. `.section`: сокращённая запись съедала боковые поля `.wrap` */
.apt__head { margin-bottom: 1rem; }
.apt__head h1 { margin-bottom: .5rem; }

.apt__location {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem 1.25rem;
  color: var(--text-muted);
  font-size: .93rem;
  margin: 0;
}
.apt__metro { display: inline-flex; align-items: center; gap: .4rem; }
.apt__location a { color: var(--gold); text-decoration: none; }
.apt__location a:hover { text-decoration: underline; }

.gallery { margin-bottom: 1.75rem; }
.gallery__main { aspect-ratio: 16 / 10; border-radius: var(--radius); box-shadow: var(--shadow-sm); }
@media (min-width: 760px) { .gallery__main { aspect-ratio: 2 / 1; } }

.gallery__thumbs {
  display: flex;
  gap: .5rem;
  list-style: none;
  margin: .6rem 0 0;
  padding: 0 0 .3rem;
  overflow-x: auto;
  scrollbar-width: thin;
}
.gallery__thumb {
  display: block;
  width: 96px;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 2px solid transparent;
  flex: none;
}
.gallery__thumb img { width: 100%; height: 100%; object-fit: cover; }
.gallery__thumb.is-active { border-color: var(--gold); }

.apt__layout { display: grid; gap: 2rem; grid-template-columns: 1fr; align-items: start; }

/* Левая колонка ровно в меру строки, правая забирает остаток. Раньше было
   наоборот — левая тянулась на всё свободное, а текст внутри упирался в свои
   672 px, и между ним и справкой оставался пустой коридор в полтораста
   пикселей. Теперь лишней ширины в колонке просто нет: она вся ушла вправо. */
@media (min-width: 960px) {
  .apt__layout { grid-template-columns: var(--measure) minmax(0, 1fr); gap: 2.5rem; }
}

.apt__facts {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem 1.5rem;
  list-style: none;
  margin: 0 0 1.25rem;
  padding: 0 0 1.25rem;
  border-bottom: 1px solid var(--border-soft);
  font-size: .95rem;
}
.apt__facts li { display: inline-flex; align-items: center; gap: .45rem; }
.apt__facts .icon { color: var(--text-muted); }

/* Лид не выключаем. Он короткий — две-три строки, и последняя всегда неполная,
   поэтому вся растяжка ложится на первую: без переносов там разъезжаются
   пробелы, и это первое, что видит читатель. У длинного текста ниже растяжка
   расходится по многим строкам и так не бросается в глаза. */
/* Лид места — тот же приём, что и у лида статьи: кегль, начертание 500,
   основной цвет. Разделяет их только размер: здесь под лидом сразу идёт текст,
   а не обложка, и слишком крупная строка спорила бы с подзаголовком. */
.apt__intro {
  max-width: var(--measure);
  font-size: 1.14rem;
  line-height: 1.6;
  font-weight: 500;
  margin-bottom: 1.1rem;
}

.apt__section { margin-bottom: 2rem; }
.apt__section h2 { font-size: 1.3rem; margin-bottom: .85rem; }
.apt__subhead { font-size: 1rem; margin: 1.1rem 0 .55rem; color: var(--text-muted); }
.apt__address { display: flex; align-items: center; gap: .5rem; color: var(--text-muted); }

.amenities { margin-bottom: 1.1rem; }
.amenities__title {
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--text-muted);
  margin-bottom: .5rem;
}
.amenities__list {
  display: grid;
  gap: .55rem 1rem;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: .93rem;
}
.amenities__list li { display: flex; align-items: center; gap: .55rem; }
.amenities__list .icon { color: var(--gold); }

.metro-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
.metro-list li { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; font-size: .95rem; }
.metro-list a { color: inherit; text-decoration: none; font-weight: 500; }
.metro-list a:hover { color: var(--gold); text-decoration: underline; }
.metro-list__dist { color: var(--text-muted); font-size: .85rem; }

.rules { list-style: none; margin: 0 0 .9rem; padding: 0; display: grid; gap: .55rem; }
.rules li { display: flex; align-items: center; gap: .6rem; font-size: .94rem; }
.rules .icon { color: var(--text-muted); }
.apt__min-nights { color: var(--text-muted); font-size: .9rem; }

/* --- booking box ---------------------------------------------------------- */

.booking-box {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.15rem;
  box-shadow: var(--shadow-md);
}

@media (min-width: 960px) { .booking-box { position: sticky; top: 78px; } }

.booking-box__price { margin-bottom: 1rem; }
.booking-box__price .price__value { font-size: 1.55rem; }

.booking-box__calc { margin: 0 0 1rem; font-size: .92rem; }
.booking-box__calc > div { display: flex; justify-content: space-between; gap: 1rem; padding: .35rem 0; }
.booking-box__calc dt { color: var(--text-muted); }
.booking-box__calc dd { margin: 0; font-variant-numeric: tabular-nums; }
.booking-box__total {
  border-top: 1px solid var(--border-soft);
  margin-top: .35rem;
  padding-top: .6rem;
  font-weight: 700;
}
.booking-box__total dt { color: var(--text); }

.booking-box__note { margin-top: .9rem; font-size: .81rem; color: var(--text-muted); line-height: 1.5; }
.booking-box__note .icon { color: var(--ok); }

/* --- booking form --------------------------------------------------------- */

.booking-form { display: grid; gap: .75rem; }
.booking-form__dates { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; }
.booking-form__consent { display: flex; gap: .55rem; align-items: flex-start; font-size: .8rem; color: var(--text-muted); line-height: 1.45; }
.booking-form__consent input { width: 18px; height: 18px; min-height: 0; margin-top: .1rem; accent-color: var(--gold); flex: none; }
.booking-form__consent a { color: var(--gold); }

/* --- booking confirmation ------------------------------------------------- */

.confirm { padding-block: 3rem; max-width: 640px; }
.confirm__mark {
  display: grid;
  place-items: center;
  width: 62px; height: 62px;
  border-radius: 50%;
  background: var(--ok-bg);
  color: var(--ok);
  margin-bottom: 1.25rem;
}
.confirm__mark .icon { width: 30px; height: 30px; }
.confirm__ref {
  display: inline-block;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: .06em;
  background: var(--surface-alt);
  border-radius: var(--radius-sm);
  padding: .5rem .9rem;
  margin: .35rem 0 1.25rem;
}
.confirm__summary { background: var(--surface); border: 1px solid var(--border-soft); border-radius: var(--radius); padding: 1rem 1.15rem; margin-bottom: 1.5rem; }
.confirm__summary dl { margin: 0; display: grid; gap: .5rem; }
.confirm__summary dl > div { display: flex; justify-content: space-between; gap: 1rem; font-size: .93rem; }
.confirm__summary dt { color: var(--text-muted); }
.confirm__summary dd { margin: 0; font-weight: 500; text-align: right; }

/* --- district / metro / attraction pages ---------------------------------- */


.metro-line { padding-top: 1.25rem; }
.metro-line__head {
  display: flex;
  align-items: center;
  gap: .6rem;
  flex-wrap: wrap;
  font-size: 1.15rem;
  margin-bottom: .9rem;
}
.metro-line__badge {
  display: grid;
  place-items: center;
  width: 28px; height: 28px;
  border-radius: 50%;
  color: #fff;
  font-size: .85rem;
  font-weight: 700;
  flex: none;
}
.metro-line__colour {
  font-size: .8rem;
  font-weight: 400;
  color: var(--text-muted);
  text-transform: none;
  letter-spacing: 0;
}

.station-meta { display: flex; flex-wrap: wrap; gap: .45rem; margin: 0 0 .85rem; }

.attr-hero {
  aspect-ratio: 16 / 9;
  border-radius: var(--radius);
  margin-bottom: 1.75rem;
  box-shadow: var(--shadow-sm);
}
@media (min-width: 760px) { .attr-hero { aspect-ratio: 21 / 9; } }

/* Соотношение сторон известного кадра шаблон ставит инлайн — оно перебивает
   фиксированные правила рядом. Остаётся удержать высоту в пределах экрана:
   ограничиваем ширину, потому что при заданном aspect-ratio высота следует за
   ней. Узкий кадр становится у́же колонки и встаёт по центру, панорамный
   занимает всю ширину. Один класс на обложку достопримечательности и статьи —
   поведение у них одно. */
.media--intrinsic { max-width: calc(64vh * var(--hero-ar)); margin-inline: auto; }

.factbox {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--factbox-pad);
  box-shadow: var(--shadow-sm);
}
/* Липкой справка остаётся, только когда она в колонке одна. Если под ней
   стоят «Статьи об этом месте», прилипший блок оставался бы на месте, а
   карточки уезжали бы под него — вместо колонки получалась бы каша. */
@media (min-width: 960px) {
  .apt__aside > .factbox:only-child { position: sticky; top: 78px; }
}

/* Блок статей в правой колонке: ширину задаёт сама колонка, поэтому со
   справкой они совпадают по краям без единой цифры в CSS.

   Заголовок отступает ровно на поле справки — той же переменной, что задаёт
   её padding. Тогда «Статьи об этом месте» и «Как добраться» стоят на одной
   вертикали; карточки при этом остаются вровень с внешним краем справки, как
   и положено карточкам. */
.apt__related { margin-top: 1.5rem; }
.apt__related > h2 { padding-inline: var(--factbox-pad); }
.apt__related-list { display: grid; gap: 1rem; }

/* Хвост списка — простые строчки со ссылками. Они встают по той же вертикали,
   что и заголовок блока, то есть по внутреннему полю справки, а не по краю
   карточек. */
.apt__related-more {
  list-style: none;
  margin: 1rem 0 0;
  padding-inline: var(--factbox-pad);
  display: grid;
  gap: .55rem;
  font-size: .93rem;
}
/* Не `--gold`: на этом кегле он даёт 3.2:1 на белом при норме 4.5:1. */
.apt__related-more a { color: var(--gold-ink); text-decoration: none; }
.apt__related-more a:hover { text-decoration: underline; }

.factbox__title { font-size: 1.05rem; margin-bottom: .85rem; }
.factbox__list { margin: 0; display: grid; gap: .8rem; }
.factbox__list > div { display: grid; gap: .2rem; }
.factbox__list dt {
  font-size: .74rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--text-muted);
}
.factbox__list dd { margin: 0; font-size: .93rem; }
.factbox__list a { color: var(--gold); }
.factbox__metro { display: flex; align-items: center; gap: .4rem; text-decoration: none; padding: .12rem 0; }
.factbox__metro:hover { text-decoration: underline; }
.factbox__note {
  margin-top: .9rem;
  padding-top: .8rem;
  border-top: 1px solid var(--border-soft);
  font-size: .8rem;
  color: var(--text-muted);
  line-height: 1.5;
}

/* --- article -------------------------------------------------------------- */

.article { max-width: 860px; }
.article__head { margin-bottom: 1.5rem; }
.article__head .chip { margin-bottom: .8rem; }
.article__head h1 { margin-bottom: .5rem; }
/* Колонка чтения. Замер на живой статье: во всю ширину `.article` (860 px)
   в строку влезало 93 знака при комфортных 45–75 — глаз промахивается мимо
   начала следующей строки. 76ch дают ≈68 знаков.

   Ограничен текст, а не вся статья: заголовок, обложка и блоки «Места из
   статьи» остаются во всю ширину колонки, и левый край у всего общий. */
.article__lead,
.article__body { max-width: var(--measure); }

/* Лид статьи — по той же причине, что и лид места: короткий абзац на выключке
   растягивает пробелы в первой же строке.

   Выделяется кеглем, начертанием 500 и основным цветом, но остаётся абзацем.
   Заголовком его делать нельзя: по заголовкам строится структура документа,
   а лид — пересказ, а не название раздела. Полужирным целиком — тоже: сплошной
   жирный абзац читается тяжелее и обесценивает выделения внутри текста. */
.article__lead {
  font-size: 1.2rem;
  line-height: 1.55;
  font-weight: 500;
  color: var(--text);
}
.article__meta {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem 1.25rem;
  font-size: .85rem;
  color: var(--text-muted);
  margin: 0;
}
.article__meta span { display: inline-flex; align-items: center; gap: .3rem; }

.article__cover {
  aspect-ratio: 16 / 9;
  border-radius: var(--radius);
  margin-bottom: 1.75rem;
  box-shadow: var(--shadow-sm);
}

/* `max-width` тут больше не отменяем: он задан выше вместе с лидом. Раньше
   стояло `none`, и статья была единственным местом на сайте, где текст шёл
   шире, чем позволяет `.prose`. */
.article__body { margin-bottom: 2rem; }

/* --- схема метро ---------------------------------------------------------- */

.metro-scheme {
  margin: 0 0 1.75rem;
  padding: .75rem;
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
}

.metro-scheme__svg {
  display: block;
  width: 100%;
  height: auto;
  /* Схема вытянута по вертикали: город тянется с юга на север. Ограничиваем
     высоту, иначе на узком экране она занимает несколько экранов подряд. */
  max-height: 78vh;
  /* hidden, а не visible: при увеличении содержимое выходило за пределы рамки
     и наезжало на страницу. Подписи у правого края теперь разворачиваются
     внутрь, поэтому обрезка им не мешает. */
  overflow: hidden;
}

/* Схема высокая — на широком экране рядом с ней помещается справка, а под
   картой она только отодвигала бы списки станций вниз. */
@media (min-width: 1000px) {
  .metro-scheme {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(17rem, 23rem);
    gap: 1.5rem;
    align-items: start;
  }
  /* Ширину карты ограничиваем так, чтобы её высота уложилась в экран: иначе
     SVG растянулся бы на всю колонку, вписал схему по высоте и оставил пустые
     поля по бокам — ровно то, из-за чего карта выглядела мелкой. Ограничение
     стоит на всей левой колонке, а не на самой карте: легенда под картой
     должна быть ровно её ширины. */
  .metro-scheme__main { max-width: calc(84vh * var(--metro-ratio, 0.92)); }
  .metro-scheme__svg { max-height: none; }
  .metro-scheme__caption { margin-top: 0; }
}

.metro-scheme__line {
  fill: none;
  stroke-width: 3.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: .9;
}

.metro-scheme__hit { fill: transparent; }

.metro-scheme__dot {
  fill: var(--surface);
  stroke: currentColor;
  stroke-width: 2.4;
}
.metro-scheme__dot.is-interchange { stroke-width: 3.2; }

/* Станция — ссылка, поэтому обязателен видимый фокус с клавиатуры. */
.metro-scheme__station:focus { outline: none; }
.metro-scheme__station:hover .metro-scheme__dot,
.metro-scheme__station:focus-visible .metro-scheme__dot {
  fill: currentColor;
}

/* --metro-scale — величина, обратная приближению: её выставляет main.js при
   зуме. Кегль на неё умножается, поэтому подпись остаётся одного экранного
   размера на любом масштабе — увеличивать надо карту, а не буквы. Умножение,
   а не деление: делить в calc() можно только на число, и любая осечка в
   значении сделала бы правило невалидным, а подписи — огромными. Без скрипта
   переменная равна 1 и подписи ведут себя как раньше. */
.metro-scheme__label {
  font-size: calc(13px * var(--metro-scale, 1));
  fill: var(--text);
  paint-order: stroke;      /* обводка под текстом, а не поверх */
  stroke: var(--surface);
  stroke-width: calc(3.5px * var(--metro-scale, 1));
  stroke-linejoin: round;
  pointer-events: none;
  opacity: 0;
}
/* Со скриптом подписями заведует он: гасит те, что легли бы друг на друга, и
   добавляет новые по мере приближения. Без скрипта показываем конечные — как
   и раньше, схема остаётся читаемой. */
.metro-scheme:not(.is-interactive) .metro-scheme__label.is-always,
.metro-scheme__station.is-labelled .metro-scheme__label { opacity: 1; }
.metro-scheme__station:hover .metro-scheme__label,
.metro-scheme__station:focus-visible .metro-scheme__label { opacity: 1; }

.metro-scheme__station.is-closed .metro-scheme__dot { opacity: .45; }
.metro-scheme__station.is-closed .metro-scheme__label { text-decoration: line-through; }

/* Колонка со справкой: легенда, как читать схему, тарифы и режим работы.
   Карточки те же, что в общей справке ниже по странице, — своих стилей им не
   заводим, только раскладываем в столбец. */
.metro-scheme__caption {
  margin-top: .6rem;
  display: grid;
  gap: .9rem;
  align-content: start;
  color: var(--text);
  font-size: .9rem;
  line-height: 1.5;
}
.metro-scheme__caption .metro-facts__card p {
  margin: 0 0 .6rem;
  font-size: .87rem;
  color: var(--text-muted);
}
.metro-scheme__caption .metro-facts__card p:last-child { margin-bottom: 0; }

.metro-legend {
  list-style: none;
  margin: .7rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: .4rem 1.1rem;
  font-size: .88rem;
  color: var(--text-muted);
}
.metro-legend li { display: flex; align-items: center; gap: .4rem; }

/* Колонок столько, сколько влезает: под широкой картой это три и легенда
   складывается в две строки — ключ к цветам сканируют взглядом, и чем плотнее
   блок, тем быстрее это делается. На узком экране колонок становится две, а
   ниже 1000 px правило и вовсе не действует: там работает флекс с переносом.
   Жёсткое число колонок ставить нельзя — «Красносельско-Калининская» начнёт
   переноситься на вторую строку.

   Правило стоит после базового объявления: то же самое выше по файлу
   перекрывалось им и молча не срабатывало. */
@media (min-width: 1000px) {
  .metro-legend {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: .45rem 1.1rem;
  }
}

/* На узком экране подписи конечных станций налезают друг на друга и на линии;
   там схема работает как обзор, а имена читаются в списках ниже. */
@media (max-width: 640px) {
  .metro-scheme:not(.is-interactive) .metro-scheme__label.is-always { opacity: 0; }
  .metro-scheme__station:hover .metro-scheme__label,
  .metro-scheme__station:focus-visible .metro-scheme__label { opacity: 1; }
}

/* --- переключатель «схема / список» --------------------------------------- */

/* Оба вида остаются в разметке: ссылки на 75 станций нужны поисковику и
   программе чтения с экрана независимо от того, что показано на экране. */
.metro-views__radio { position: absolute; opacity: 0; pointer-events: none; }

.metro-views__switch {
  display: inline-flex;
  gap: .25rem;
  margin-bottom: 1rem;
  padding: .25rem;
  background: var(--surface-alt);
  border-radius: 999px;
}
.metro-views__switch label {
  padding: .45rem 1.1rem;
  border-radius: 999px;
  font-size: .9rem;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.metro-views__switch label:hover { color: var(--text); }

#view-scheme:checked ~ .metro-views__switch label[for="view-scheme"],
#view-list:checked   ~ .metro-views__switch label[for="view-list"] {
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-sm);
}
/* Переключатель управляется с клавиатуры — фокус должен быть виден. */
#view-scheme:focus-visible ~ .metro-views__switch label[for="view-scheme"],
#view-list:focus-visible   ~ .metro-views__switch label[for="view-list"] {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

#view-scheme:checked ~ .metro-views__list,
#view-list:checked ~ .metro-scheme { display: none; }

/* --- подложка и зум схемы -------------------------------------------------- */

/* Якорь для кнопок зума — обёртка карты, а не вся figure: на широком экране
   figure это две колонки, и кнопки уехали бы к тексту. */
.metro-scheme__main { min-width: 0; }
.metro-scheme__map { position: relative; min-width: 0; }

/* Вода даёт схеме узнаваемый силуэт города. Приглушена намеренно: это фон,
   читаться должны линии метро. */
.metro-scheme__water { fill: var(--water); }

.metro-scheme__svg {
  background: var(--map-bg);
  border-radius: var(--radius-sm);
  cursor: grab;
  /* pan-y, а не none: вертикальный свайп должен прокручивать страницу.
     Схема занимает почти экран, и если она забирает жест себе, до текста
     под ней на телефоне не добраться. */
  touch-action: pan-y;
}
.metro-scheme__svg.is-dragging { cursor: grabbing; }

.metro-scheme__zoom {
  position: absolute;
  top: 1.15rem; right: 1.15rem;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: .3rem;
}
.metro-scheme__btn {
  min-width: 34px;
  min-height: 34px;
  padding: 0 .5rem;
  font-size: 1.05rem;
  line-height: 1;
  font-weight: 600;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
}
.metro-scheme__btn:hover { border-color: var(--gold); }
.metro-scheme__btn--wide { font-size: .78rem; padding: 0 .55rem; }
/* Кнопки бесполезны без JavaScript — тогда их просто нет. */
.metro-scheme__zoom { display: none; }
.metro-scheme.is-interactive .metro-scheme__zoom { display: flex; }

/* --- справка о метро ------------------------------------------------------- */

.metro-facts { border-top: 1px solid var(--border-soft); padding-top: 2rem; }
.metro-facts__grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;
  margin-top: 1.25rem;
}
@media (min-width: 720px)  { .metro-facts__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.metro-facts__card {
  padding: 1.1rem 1.2rem;
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
}
.metro-facts__card h3 { margin: 0 0 .7rem; font-size: 1.02rem; }
.metro-facts__list { margin: 0; padding: 0 0 0 1.1rem; display: grid; gap: .5rem; font-size: .92rem; line-height: 1.5; }
.metro-facts__note { margin: .8rem 0 0; font-size: .87rem; color: var(--text-muted); line-height: 1.5; }
.metro-facts__source { margin: 1.25rem 0 0; font-size: .84rem; color: var(--text-muted); }

/* Служебная строка: она обязана быть, но не должна спорить за внимание с
   самой фотографией. Мельче основного текста и приглушена. */
.gallery__credit {
  margin: .45rem 0 0;
  font-size: .68rem;
  line-height: 1.4;
  color: var(--text-muted);
  opacity: .65;
}
