/* =========================================================================
   ММА в Перми — мир «Телестудия»

   Мир вырастает из настоящего факта о клубе: более 10 лет — эксперты
   Первого канала по самообороне. Отсюда язык страницы: студийные тёмные
   полосы, где ПОКАЗЫВАЮТ, чередуются со светлыми, где УСПОКАИВАЮТ.
   Первый экран и всё, что снимает страх новичка, остаётся светлым.

   Тёмное занимает примерно треть страницы прожилками: выбор группы,
   продвинутая группа, команда, зал и расписание. Акцент бордовый: запрет на
   красный относился к базовому курсу, а не к ММА.

   Авторский момент — один: переход в первую тёмную полосу. Студийный графит
   вытесняет светлую страницу снизу вверх, следом вырастает линия и титр с
   заголовком выезжает из-под неё. Остальные секции появляются ровно и
   одинаково — россыпь эффектов авторским моментом не считается.

   ДВЕ СЪЁМКИ, И ОНИ РАЗНЫЕ
   assets/img/mma/ — собственная съёмка клуба «Алмаз», основная на странице.
   Внизу по центру на ней стоит водяной знак «Алмаз»: убирать его не надо,
   но кадрировать эти снимки можно только так, чтобы знак не резался и не
   уходил под текст. Отсюда правило: рамки под эти кадры держат исходное
   3:2, а где раскладка всё-таки кроит — кадр прижат к низу.
   assets/img/perm/ — съёмка пермской площадки. Знака на ней нет, кроить
   можно свободно. Она живёт одним блоком «Зал» и больше нигде.

   Разметка следует договору с общим JS:
   .scratch/almaz-landing-variants/js-contract.md
   Ручки панели твиков — по договору:
   .scratch/almaz-motion-variants/tweaks-contract.md
   ========================================================================= */

/* =========================================================================
   1. Токены
   Все переменные ручек объявлены здесь и только здесь — панель пишет их
   инлайном на <html>, и объявление ниже по дереву перебило бы запись.
   ========================================================================= */

:root {
  /* --- Ручка «Гарнитура». Значения сняты с панели твиков: заказчик
         подобрал набор там и утвердил его как исходный. --- */
  --font-display: 'Wix Madefor Display', system-ui, sans-serif;
  --font-text: 'Wix Madefor Text', system-ui, sans-serif;
  --display-tight: -0.03em;
  --display-weight: 700;

  /* --- Ручка «Кегль»: один множитель на всю шкалу --- */
  --scale: 1;

  /* --- Ручка «Воздух»: один множитель на все отступы --- */
  --air: 1;

  /* --- Ручка «Скругления». Прямой угол по всей странице: скруглений в
         этом мире больше нет ни у кнопок, ни у кадров, ни у плашек. --- */
  --r-btn: 0px;
  --r-card: 0px;
  --r-pill: 0px;

  /* --- Ручка «Акцент». Бордовый: цвет единоборств, а не телестудии.
         --accent живёт на светлой бумаге, --accent-lift — на графите:
         на тёмном тот же тон даёт 3.3:1 и текстом уже не работает.
         Красный поднимается в светлый тон тяжелее синего — чтобы взять
         4.5:1 на самой светлой из тёмных полос (--dark-3), приходится
         уходить в лососевый. Ниже уходить нельзя: подписи времени в
         расписании набраны именно им. --- */
  --accent: #CD232D;
  --accent-ink: #A31C24;
  --accent-lift: #F2656C;

  /* --- Светлая полоса: студийный свет на бумаге --- */
  --paper: #F2F0EC;
  --paper-2: #E7E4DE;
  /* Подложка финальной полосы. Была стальной с синевой — под бордовым
     акцентом синева читалась как чужой цвет, поэтому подтон тёплый. */
  --tint: #EFE2E1;
  --card: #FFFFFF;
  --ink: #16191D;
  --muted: #565C64;
  --line: #D6D2CA;
  --line-soft: #E4E1DA;

  /* --- Тёмная полоса: студийный графит --- */
  --dark: #14171B;
  --dark-2: #1B1F25;
  --dark-3: #242A31;
  --dark-ink: #EDEFF1;
  --dark-muted: #A7AFB8;
  --dark-line: rgba(255, 255, 255, 0.13);

  /* --- Служебные тона --- */
  --ok: #2F7A5E;
  --err: #9C4630;

  /* --- Типографическая шкала: всё через множитель --scale --- */
  /* Unbounded заметно шире Manrope из ТЗ, поэтому верх шкалы сбавлен:
     на 60 px заголовок обложки уходил в четыре строки. */
  --t-h1: calc(clamp(30px, 3.6vw, 46px) * var(--scale));
  --t-h2: calc(clamp(26px, 3vw, 40px) * var(--scale));
  --t-h3: calc(clamp(19px, 1.7vw, 24px) * var(--scale));
  --t-h4: calc(clamp(17px, 1.3vw, 19px) * var(--scale));
  --t-lead: calc(clamp(17px, 1.4vw, 20px) * var(--scale));
  --t-body: calc(17px * var(--scale));
  --t-small: calc(14px * var(--scale));
  --t-cap: calc(13px * var(--scale));
  --t-num: calc(clamp(40px, 5.2vw, 68px) * var(--scale));
  --t-mega: calc(clamp(54px, 7vw, 104px) * var(--scale));

  /* --- Отступы: всё через множитель --air --- */
  --pad: calc(clamp(20px, 5vw, 72px) * var(--air));
  --sec-pad: calc(clamp(64px, 8vw, 128px) * var(--air));
  --gap: calc(24px * var(--air));
  --gap-lg: calc(48px * var(--air));

  /* --- Движение ---
     Появление секций намеренно тихое. Громкий въезд на каждой полосе —
     это не движение, а шум: планка качества прямо называет одинаковый
     въезд на каждой секции дефектом. Громко играет одна сцена перехода
     в эфир, а её жест повторяют швы между полосами. */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --rise: 10px;
  --drift: 2.2%;
  --drift-zoom: 1.1;
  --dur-tap: 140ms;
  --dur-state: 220ms;

  /* --- Каркас --- */
  --header-h: 76px;
  --maxw: 1280px;

  --focus-ring-color: var(--accent);
  --focus-ring-offset: 3px;
}

/* Ручка «Сила движения». Атрибут, а не переменная: гасить движение
   селектором надёжнее, чем пересчитывать десяток длительностей. */
[data-motion='bold'] {
  --rise: 16px;
  --drift: 3.4%;
  --drift-zoom: 1.14;
}

[data-motion='off'] *,
[data-motion='off'] *::before,
[data-motion='off'] *::after {
  animation: none !important;
  transition: none !important;
}

/* =========================================================================
   2. Основа
   ========================================================================= */

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: var(--t-body);
  line-height: 1.7;
  font-weight: 400;
  overflow-x: hidden;
}

/* Поверхности браузера тоже часть страницы. */
::selection {
  background: var(--accent);
  color: #fff;
}

.sec--live ::selection {
  background: var(--accent-lift);
  color: var(--dark);
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-tight);
  line-height: 1.16;
  text-wrap: balance;
}

p {
  max-width: 68ch;
}

b,
strong {
  font-weight: 600;
}

a {
  color: var(--accent);
  text-underline-offset: 0.22em;
  text-decoration-thickness: 1px;
}

a:hover {
  color: var(--accent-ink);
}

.skip {
  position: absolute;
  left: 12px;
  top: -80px;
  z-index: 100;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 18px;
  background: var(--ink);
  color: #fff;
  border-radius: var(--r-btn);
  text-decoration: none;
  transition: top var(--dur-state) var(--ease);
}

.skip:focus {
  top: 12px;
  color: #fff;
}

.container {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--pad);
}

.h3 {
  font-size: var(--t-h3);
  margin-bottom: calc(12px * var(--air));
}

.lead {
  font-size: var(--t-lead);
  line-height: 1.6;
  color: var(--muted);
}

.lead b {
  color: var(--ink);
}

/* =========================================================================
   3. Полосы
   Светлая — успокаивает. Тёмная — показывает.
   ========================================================================= */

.sec {
  position: relative;
  padding-block: var(--sec-pad);
  background: var(--paper);
}

.sec--paper2 {
  background: var(--paper-2);
}

/* Полосы стыкуются встык. Ступень, которой приходящая полоса заходила на
   предыдущую, снята по решению заказчика: на стыке она читалась не как
   переход, а как обрубленный угол. */

/* Тёмная студийная полоса. Верх и низ без рамок: кадр в неё входит
   встык, как в эфире. */
.sec--live {
  background: var(--dark);
  color: var(--dark-ink);
  --focus-ring-color: var(--accent-lift);
}

.sec--live a {
  color: var(--accent-lift);
}

.sec--live a:hover {
  color: #fff;
}

.sec--live .lead {
  color: var(--dark-muted);
}

/* Зал и расписание идут двумя тёмными полосами подряд: это единый эфирный
   блок, где ПОКАЗЫВАЮТ. Граница между ними держится волоском, иначе они
   слипаются в одну бесконечную тёмную простыню. */
.sec--live + .sec--live {
  border-top: 1px solid var(--dark-line);
}

/* Лид на тёмной полосе: --muted на графите даёт 3,4 : 1 и до планки не
   дотягивает. */
.lead--live {
  color: var(--dark-muted);
  margin-bottom: var(--gap-lg);
}

/* --- Заголовок секции --------------------------------------------------- */

.shead {
  margin-bottom: var(--gap-lg);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: calc(8px * var(--air)) var(--gap);
}

.shead__title {
  font-size: var(--t-h2);
  max-width: 22ch;
  flex: 1 1 min(100%, 22ch);
}

.shead__note {
  font-size: var(--t-cap);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}

.sec--live .shead__note {
  color: var(--dark-muted);
}

/* Титр: заголовок тёмной полосы стоит на подложке с эфирной линией
   слева — так он читается как надпись на экране, а не как текст. */
.shead--live .shead__title {
  position: relative;
  padding-left: calc(18px * var(--air));
  max-width: 26ch;
}

.shead--live .shead__title::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.16em;
  bottom: 0.16em;
  width: 2px;
  background: var(--accent-lift);
}

.titre,
.titre__in {
  display: block;
}

/* =========================================================================
   4. Кнопки, ссылки, выноски
   ========================================================================= */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;
  min-width: 44px;
  padding: 12px 26px;
  border: 1.5px solid transparent;
  border-radius: var(--r-btn);
  font-family: var(--font-text);
  font-size: calc(16px * var(--scale));
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--dur-state) var(--ease),
    border-color var(--dur-state) var(--ease), color var(--dur-state) var(--ease),
    transform var(--dur-tap) var(--ease), box-shadow var(--dur-state) var(--ease);
}

.btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.btn--primary:hover {
  background: var(--accent-ink);
  border-color: var(--accent-ink);
  color: #fff;
  transform: translateY(-1px);
  box-shadow: 0 8px 22px rgba(20, 23, 27, 0.18);
}

.btn--primary:active {
  transform: translateY(0);
}

.btn--ghost {
  background: transparent;
  border-color: var(--line);
  color: var(--ink);
}

.btn--ghost:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: rgba(47, 109, 140, 0.07);
}

.sec--live .btn--ghost {
  border-color: var(--dark-line);
  color: var(--dark-ink);
}

.sec--live .btn--ghost:hover {
  border-color: var(--accent-lift);
  color: var(--accent-lift);
  background: rgba(255, 255, 255, 0.06);
}

.btn--sm {
  min-height: 44px;
  padding: 8px 18px;
  font-size: calc(15px * var(--scale));
}

.btn--lg {
  min-height: 56px;
  padding: 15px 32px;
}

.btn--wide {
  width: 100%;
}

.btn[disabled] {
  opacity: 0.6;
  cursor: default;
  transform: none;
  box-shadow: none;
}

/* Выноска — реплика в эфире: подложка и тонкая линия слева. */
.callout {
  margin-top: calc(20px * var(--air));
  padding: calc(18px * var(--air)) calc(22px * var(--air));
  background: var(--card);
  border-left: 1px solid var(--accent);
  border-radius: 0 var(--r-card) var(--r-card) 0;
  font-size: var(--t-lead);
  line-height: 1.55;
  font-weight: 500;
  max-width: 60ch;
}

.sec--live .callout {
  background: var(--dark-2);
  border-left-color: var(--accent-lift);
  color: var(--dark-ink);
}

.sec--paper2 .callout {
  background: var(--card);
}

.sec__cta {
  margin-top: var(--gap-lg);
  max-width: none;
}

.undercta__tel {
  font-weight: 600;
  white-space: nowrap;
}

.prose {
  max-width: 74ch;
}

.prose > * + * {
  margin-top: calc(16px * var(--air));
}

.prose .h3 {
  margin-top: calc(36px * var(--air));
}

/* =========================================================================
   5. Шапка и меню
   ========================================================================= */

/* Якорная прокрутка отмеряет от --header-h, а настоящая шапка на пиксель
   выше: снизу у неё волосяная линейка. Заголовок секции вставал ровно под
   её край. Прибавка снимает и этот пиксель, и даёт заголовку отбивку. */
html {
  scroll-padding-top: calc(var(--header-h) + 12px);
}

.hdr {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--paper);
  border-bottom: 1px solid transparent;
  transition: background-color var(--dur-state) linear,
    border-color var(--dur-state) linear, box-shadow var(--dur-state) linear;
}

/* Прокрученная страница — шапка отделяется от содержания: полупрозрачная
   подложка с размытием, волосяная линейка и тень. Тень раньше висела на
   is-pinned и появлялась только при прокрутке вверх; теперь шапка видна
   всегда, и отделять её нужно всегда. */
.hdr.is-scrolled {
  background: rgba(242, 240, 236, 0.92);
  backdrop-filter: blur(10px);
  border-bottom-color: var(--line);
  box-shadow: 0 8px 24px rgba(20, 23, 27, 0.08);
}

/* Шапка приклеена к верху и не уезжает. Общий site.js прячет её при
   прокрутке вниз и возвращает при прокрутке вверх — вариант этот приём
   гасит: классы скрипт по-прежнему вешает, но оформление их не слушает.
   Правится здесь, а не в скрипте: скрипт один на все страницы сайта. */
.hdr.is-hidden,
.hdr.is-pinned {
  transform: none;
}

/* Шапка шире колонки содержания: восемь пунктов меню, плашка, телефон и
   кнопка в 1136 px основной сетки не помещаются и уезжают в три ряда. */
.hdr__inner {
  display: flex;
  align-items: center;
  gap: calc(18px * var(--air));
  min-height: var(--header-h);
  max-width: 1520px;
  margin-inline: auto;
  padding-inline: clamp(16px, 3vw, 48px);
}

.mark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: inherit;
  text-decoration: none;
  flex: none;
}

.mark__badge {
  display: block;
  width: 44px;
  height: 44px;
  overflow: hidden;
  border-radius: 50%;
  flex: none;
}

.mark__badge img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.06);
}

.mark__text {
  display: flex;
  flex-direction: column;
  line-height: 1.1;
}

.mark__name {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-size: calc(19px * var(--scale));
  letter-spacing: var(--display-tight);
}

/* Та же стилизованная Z, что на обложке. Ссылке проставлен aria-label:
   латинская буква посреди кириллицы читается диктором как отдельное
   слово, и без подписи логотип звучал бы «Алма зэт». */
.mark__z {
  color: var(--accent);
}

.mark__sub {
  font-size: calc(11px * var(--scale));
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.hdr__nav {
  flex: 1 1 auto;
  min-width: 0;
}

.hdr__menu {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 0;
  margin: 0;
}

.hdr__menu a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  min-width: 44px;
  padding: 0 9px;
  border-radius: var(--r-btn);
  color: var(--ink);
  font-size: calc(14px * var(--scale));
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--dur-state) var(--ease),
    background-color var(--dur-state) var(--ease);
}

.hdr__menu a:hover {
  color: var(--accent);
  background: rgba(47, 109, 140, 0.08);
}

.hdr__side {
  display: flex;
  align-items: center;
  gap: calc(12px * var(--air));
  flex: none;
}

.chip {
  margin: 0;
  padding: 6px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  font-size: calc(12px * var(--scale));
  color: var(--muted);
  white-space: nowrap;
}

.hdr__phone {
  display: flex;
  flex-direction: column;
  min-height: 44px;
  justify-content: center;
  color: var(--ink);
  text-decoration: none;
  line-height: 1.15;
}

.hdr__tel {
  font-weight: 600;
  font-size: calc(16px * var(--scale));
  white-space: nowrap;
}

.hdr__hours {
  font-size: calc(11px * var(--scale));
  color: var(--muted);
  white-space: nowrap;
}

.hdr__phone:hover .hdr__tel {
  color: var(--accent);
}

.hdr__mobile {
  display: none;
  align-items: center;
  gap: 4px;
  margin-left: auto;
}

.iconbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-btn);
  color: var(--ink);
  text-decoration: none;
  transition: background-color var(--dur-state) var(--ease);
}

.iconbtn:hover {
  background: rgba(20, 23, 27, 0.06);
}

.iconbtn__bars,
.iconbtn__bars::before,
.iconbtn__bars::after {
  display: block;
  width: 20px;
  height: 2px;
  background: currentColor;
  border-radius: 2px;
  transition: transform var(--dur-state) var(--ease),
    opacity var(--dur-state) var(--ease);
}

.iconbtn__bars {
  position: relative;
}

.iconbtn__bars::before,
.iconbtn__bars::after {
  content: '';
  position: absolute;
  left: 0;
}

.iconbtn__bars::before {
  top: -6px;
}

.iconbtn__bars::after {
  top: 6px;
}

[aria-expanded='true'] .iconbtn__bars {
  background: transparent;
}

[aria-expanded='true'] .iconbtn__bars::before {
  transform: translateY(6px) rotate(45deg);
}

[aria-expanded='true'] .iconbtn__bars::after {
  transform: translateY(-6px) rotate(-45deg);
}

/* --- Мобильное меню ----------------------------------------------------- */

.menu {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: var(--paper);
  opacity: 0;
  transition: opacity 260ms var(--ease);
  overflow-y: auto;
}

.menu.is-open {
  opacity: 1;
}

.menu__inner {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--gap-lg);
  padding: calc(var(--header-h) + 24px) var(--pad) calc(32px + env(safe-area-inset-bottom, 0px));
}

.menu__list {
  margin: 0;
}

.menu__list li + li {
  border-top: 1px solid var(--line);
}

.menu__list a {
  display: flex;
  align-items: center;
  min-height: 60px;
  font-family: var(--font-display);
  font-size: calc(24px * var(--scale));
  font-weight: 500;
  letter-spacing: var(--display-tight);
  color: var(--ink);
  text-decoration: none;
}

.menu__list a:hover {
  color: var(--accent);
}

.menu__foot {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}

.menu__foot .chip {
  margin-bottom: 10px;
}

.menu__tel {
  font-family: var(--font-display);
  font-size: calc(22px * var(--scale));
  font-weight: var(--display-weight);
  color: var(--ink);
  text-decoration: none;
}

.menu__hours {
  font-size: var(--t-small);
  color: var(--muted);
  margin-bottom: 10px;
}

/* =========================================================================
   6. Блок 1. Обложка
   Три раскладки ручки «Обложка» и три кадра ручки «Кадр в обложке».
   Полоса светлая: первый экран снимает страх, темнота сюда не идёт.
   ========================================================================= */

/* Верх подрезан вдвое против низа. Полоса упиралась в нижний край окна:
   при высоте 960 низ обложки уходил за экран на 21px, а между шапкой и
   заголовком стояло 200px пустоты — 96 от отступа и ещё 104 оттого, что
   фигура выше текстовой колонки, а колонки выровнены по низу. */
.hero {
  position: relative;
  padding-block: calc(var(--sec-pad) * 0.3) var(--sec-pad);
  background: var(--paper);
  overflow: hidden;
}

/* Колонки выровнены по низу, а не по центру: низ вырезанной фигуры обязан
   встать на одну линию с последней строкой текста слева. */
/* Отступ по сетке висит на самой сетке, а не на колонке текста: процент в
   padding считается от содержащего блока, и на колонке он отмерялся бы от
   её ширины, а не от ширины полосы. Тот же приём, что у разворота и у
   сцены в блоке «Базовая программа». */
.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1fr);
  gap: var(--gap-lg);
  align-items: center;
  padding-left: max(var(--pad), calc((100% - var(--maxw)) / 2 + var(--pad)));
}

.hero__main {
  position: relative;
  z-index: 1;
  min-width: 0;
}

/* Отбивка места и года стоит студийным штампом под первым экраном,
   а не надзаголовком над H1: заголовок ведёт страницу сам. */
.hero__place {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: calc(28px * var(--air)) 0 0;
  font-size: var(--t-cap);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

.hero__place::before {
  content: '';
  width: 26px;
  height: 2px;
  background: var(--accent);
  flex: none;
}

/* Заголовок прибавил в кегле: на обложке он теперь ведёт один, кнопок под
   ним нет. Шкала своя, а не общая --t-h1, — та рассчитана на заголовки
   секций, и обложке её верха мало. */
.hero__title {
  font-size: calc(clamp(34px, 4.6vw, 62px) * var(--scale));
  line-height: 1.04;
  max-width: 16ch;
}

/* «Для взрослых» — единственное, что на обложке залито акцентом. Плашка
   набрана мельче заголовка и стоит отдельной строкой под ним: она уточняет,
   кому курс, а не спорит с ним за первое слово и не разрывает «ММА в Перми»
   посередине.

   width: fit-content на блочном элементе — плашка занимает ровно свои
   слова, а не всю ширину колонки. */
.hero__badge {
  display: block;
  width: fit-content;
  margin-top: 0.24em;
  padding: 0.1em 0.32em 0.16em;
  background: var(--accent);
  color: #fff;
  font-size: 0.52em;
  letter-spacing: 0;
  white-space: nowrap;
}

.hero__sub {
  margin-top: calc(14px * var(--air));
  font-family: var(--font-display);
  font-size: var(--t-h4);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-tight);
  color: var(--ink);
}

.hero__lead {
  margin-top: calc(20px * var(--air));
  font-size: var(--t-lead);
  line-height: 1.6;
  color: var(--muted);
  max-width: 46ch;
}

/* Факты обложки. Четыре ячейки в ряд под общей линейкой, каждая со своей
   меткой. Сплошной строкой через точки они читались случайной припиской;
   разложенные по ячейкам — это короткая спецификация курса.

   Метка — тот же квадрат акцентом, что у шагов пути в блоке «Что дальше».
   Знак на странице один, и повторяется он осознанно. */
.facts {
  display: flex;
  flex-wrap: wrap;
  gap: calc(10px * var(--air)) calc(26px * var(--air));
  margin: calc(26px * var(--air)) 0 0;
  padding: calc(20px * var(--air)) 0 0;
  border-top: 1px solid var(--line);
  list-style: none;
}

.facts__item {
  display: flex;
  align-items: baseline;
  gap: calc(10px * var(--air));
  font-size: var(--t-small);
  line-height: 1.5;
  color: var(--ink);
}

.facts__item::before {
  content: '';
  flex: none;
  width: 7px;
  height: 7px;
  background: var(--accent);
  /* Выключка по базовой линии тянет квадрат вниз к хвостам букв, поэтому
     он поднимается на свою половину: так метка встаёт в середину строчных. */
  transform: translateY(-0.15em);
}

.tally {
  display: flex;
  flex-wrap: wrap;
  gap: calc(24px * var(--air)) calc(40px * var(--air));
  margin: calc(18px * var(--air)) 0 0;
  padding-top: calc(24px * var(--air));
  border-top: 1px solid var(--line);
}

.tally__cell {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.tally__num {
  font-family: var(--font-display);
  font-size: calc(clamp(28px, 3vw, 40px) * var(--scale));
  font-weight: var(--display-weight);
  letter-spacing: var(--display-tight);
  line-height: 1;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.tally__label {
  font-size: var(--t-cap);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Оговорка под строкой показателей: тише подписей, чтобы не спорить с
   цифрами, но читаемая — она отделяет счёт клуба от одной площадки. */
.tally__note {
  margin: calc(12px * var(--air)) 0 0;
  font-size: var(--t-cap);
  line-height: 1.5;
  color: var(--muted);
  max-width: 46ch;
}

/* Показатели на графите: линейка и подписи взяты из тёмной полосы. */
.tally--live {
  margin-top: var(--gap-lg);
  border-top-color: var(--dark-line);
}

.tally--live .tally__num {
  color: var(--accent-lift);
}

.tally--live .tally__label,
.tally__note--live {
  color: var(--dark-muted);
}

/* --- Сцена с кадром ----------------------------------------------------- */

/* Кадр выключен по центру колонки, а не по её низу. При вырезанной фигуре
   низ был содержанием — она стояла на бумаге; у рамочного кадра низа как
   опоры нет, и прижатая к низу рамка оставляла над собой всю пустоту
   разом. По центру пустота делится пополам и не читается провалом. */
.hero__stage {
  position: relative;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Кадр обложки. Соотношение совпадает с исходным 3:2, поэтому среза нет
   вовсе: object-fit оставлен на случай раскладок «Стопкой» и «Во весь
   экран», где высота задаётся явно.

   Резать этот кадр по бокам нельзя ни на сколько. Водяной знак клуба лежит
   внизу слева и начинается почти от края, левый боец — сразу за ним,
   правый доходит до противоположного края: симметричный срез разрубает
   знак, срез с одной стороны — человека. */
.hero__figure {
  position: relative;
  z-index: 3;
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  background: var(--paper-2);
}

/* Раскладка «Стопкой» */
[data-hero-layout='stack'] .hero__grid {
  grid-template-columns: minmax(0, 1fr);
}

[data-hero-layout='stack'] .hero__title {
  max-width: 20ch;
}

/* Рамки и скругления у сцены больше нет: в ней стоит вырез, а не кадр.
   Обрезать вырезанную фигуру рамкой — значит вернуть то, от чего уходили. */
[data-hero-layout='stack'] .hero__stage {
  max-height: 62vh;
}

/* Раскладка «Стопкой»: фигура ниже текста, поэтому ей нужен потолок по
   высоте, иначе первый экран уезжает. */
[data-hero-layout='stack'] .hero__figure {
  height: clamp(320px, 52vh, 460px);
}

/* Раскладка «Во весь экран»: кадр занимает полосу, текст лежит поверх
   на светлой заливке — контраст остаётся гарантированным. */
.hero[data-hero-layout='full']::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(
    100deg,
    var(--paper) 0%,
    var(--paper) 34%,
    rgba(242, 240, 236, 0.9) 48%,
    rgba(242, 240, 236, 0) 76%
  );
  pointer-events: none;
}

[data-hero-layout='full'] .hero__grid {
  grid-template-columns: minmax(0, 1fr);
  min-height: min(72vh, 720px);
  align-items: center;
}

[data-hero-layout='full'] .hero__main {
  max-width: 40rem;
}

[data-hero-layout='full'] .hero__stage {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  left: auto;
  width: min(64%, 900px);
  z-index: 0;
  align-items: stretch;
}

[data-hero-layout='full'] .hero__figure {
  height: min(76vh, 720px);
}

/* =========================================================================
   7. Авторский момент: переход в первую тёмную полосу
   Графит вытесняет светлую страницу снизу вверх, следом вырастает линия и
   титр выезжает из-под неё. Сцена одна на всю страницу. Кадр, входивший
   справа, снят по решению заказчика.
   ========================================================================= */

/* Своей подложки у полосы больше нет — она берёт тон секции. Бумага под ней
   была нужна вытеснению: графит приходил на светлое. Вместе со сценой ушла
   и она, а с ней исчезла причина белого волоска на дне полосы — он и был
   той бумагой, пробивавшейся сквозь сглаженную кромку графита. */
.onair {
  position: relative;
}

/* Одна колонка: кадр справа от титра снят, полоса держится вытеснением и
   заголовком. Отдельной высоты у сцены больше нет — её задаёт сам титр с
   отбивкой. Пока стоял кадр, высоту держал он; после его снятия та же
   мера оставляла над заголовком полосу пустого графита. */
.onair__grid {
  position: relative;
  z-index: 1;
  display: grid;
  padding-inline: max(var(--pad), calc((100% - var(--maxw)) / 2 + var(--pad)));
}

.onair__desk {
  align-self: end;
  padding: calc(48px * var(--air)) 0 calc(40px * var(--air));
  color: var(--dark-ink);
}

.onair__rule {
  display: block;
  width: 84px;
  height: 3px;
  margin-bottom: calc(20px * var(--air));
  background: var(--accent-lift);
  transform-origin: left center;
}

.onair__title {
  font-size: var(--t-h2);
  max-width: 20ch;
  margin: 0;
}

.onair__title .titre {
  overflow: hidden;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}


/* =========================================================================
   8. Блок 2. Выбор группы (тёмная полоса)

   Подпись стоит ПОД кадром, а не поверх него. Обычная для этого мира
   плашка с градиентом села бы ровно на водяной знак «Алмаз» внизу кадра,
   а рамка 3:2 повторяет исходное соотношение съёмки, поэтому знак не
   режется ни по одной стороне.
   ========================================================================= */

/* --- Способ подачи: МОЗАИКА С ГЛАВНЫМИ ----------------------------------
   Лента, уходившая за правый край, снята: две группы из шести всё время
   оставались за кадром, и увидеть весь выбор разом было нельзя.

   Шесть групп не равны друг другу. Весь довод страницы — что новички
   занимаются отдельно от опытных, поэтому эти двое идут крупно и во всю
   половину полосы, а остальные четыре — мелким рядом под ними. Это не
   сетка одинаковых карточек: карточек тут нет вовсе, ни рамок, ни
   подложек, только кадр, имя и строка на самой полосе. Разница в размере
   и есть содержание блока. */

/* Три колонки: девушкам отдан отдельный блок, и в перечне остались опытные,
   дети и занятия один на один. При четырёх колонках справа зияла пустая
   ячейка. */
.picks {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: calc(40px * var(--air)) var(--gap);
  margin: var(--gap-lg) 0 0;
  padding: 0;
  list-style: none;
}

.picks__item--lead {
  grid-column: span 2;
}

/* Съёмка клуба идёт со своим водяным знаком внизу по центру. Кроп 4:3 от
   исходных 3:2 режет только бока и знак не задевает; у главных кадров
   соотношение совпадает с исходным, там среза нет вовсе. */
.picks__shot {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--r-card);
  background: var(--dark-2);
  margin-bottom: calc(16px * var(--air));
}

.picks__item--lead .picks__shot {
  aspect-ratio: 3 / 2;
}

/* Цвета взяты для светлой полосы: мозаика переехала на бумагу, когда блок
   «Выберите свою группу» стал коротким «Если ваш случай другой». На графите
   те же имена были набраны --dark-ink и на бумаге читались бы белым по
   белому; правило для тёмной полосы стоит ниже и включается само. */
.picks__name {
  position: relative;
  padding-left: calc(14px * var(--air));
  font-size: var(--t-h4);
  color: var(--ink);
  margin-bottom: calc(8px * var(--air));
}

.sec--live .picks__name {
  color: var(--dark-ink);
}

.picks__item--lead .picks__name {
  font-size: var(--t-h3);
  margin-bottom: calc(12px * var(--air));
}

/* Та же линия, что у титра. На бумаге она идёт полным акцентом, на графите
   светлым: бордовый на тёмном берёт 3.3:1 и в двухпиксельной линейке тонет. */
.picks__name::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.16em;
  bottom: 0.16em;
  width: 2px;
  background: var(--accent);
}

.sec--live .picks__name::before {
  background: var(--accent-lift);
}

.picks__text {
  padding-left: calc(14px * var(--air));
  font-size: var(--t-cap);
  line-height: 1.65;
  color: var(--muted);
  margin: 0;
}

.sec--live .picks__text {
  color: var(--dark-muted);
}

.picks__item--lead .picks__text {
  font-size: var(--t-small);
}

@media (max-width: 960px) {
  .picks {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 560px) {
  .picks {
    grid-template-columns: minmax(0, 1fr);
  }

  .picks__item--lead {
    grid-column: auto;
  }
}

/* =========================================================================
   9. Способ подачи: РАЗВОРОТ
   Кадр упирается в край окна, а не заканчивается вместе с колонкой текста.
   Достался блоку «Если хотите выступать»: кадр уходит влево. Скругления
   остаются только на той стороне, которую край окна не режет — скруглённый
   угол вплотную к краю читается ошибкой.
   ========================================================================= */

/* Отступ по сетке висит на самом развороте, а не на колонке текста:
   процент в padding считается от содержащего блока, и на колонке он
   отмерялся бы от ширины колонки, а не от ширины полосы — текст съезжал
   бы влево от заголовка. Тот же приём, что у сцены в блоке «Выберите
   свою группу». */
.spread {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1fr);
  gap: var(--gap-lg);
  align-items: center;
  padding-left: max(var(--pad), calc((100% - var(--maxw)) / 2 + var(--pad)));
}

.spread__text {
  min-width: 0;
}

.spread__text > * + * {
  margin-top: calc(16px * var(--air));
}

.spread__text > * + .h3 {
  margin-top: calc(34px * var(--air));
}

.spread__text .btn {
  margin-top: var(--gap);
}

.spread__shot {
  clip-path: inset(0 round var(--r-card) 0 0 var(--r-card));
  border-radius: var(--r-card) 0 0 var(--r-card);
}

.spread--flip {
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr);
  padding-left: 0;
  padding-right: max(var(--pad), calc((100% - var(--maxw)) / 2 + var(--pad)));
}

.spread--flip .spread__text {
  order: 2;
}

.spread--flip .spread__shot {
  order: 1;
  clip-path: inset(0 round 0 var(--r-card) var(--r-card) 0);
  border-radius: 0 var(--r-card) var(--r-card) 0;
}

/* Кадр режется clip-path, а не overflow: hidden. Элемент с overflow: hidden
   считается контейнером прокрутки, и view() у смещения при прокрутке
   цепляется к нему — прогресс замирает на середине, кадр не едет. */
.shot {
  position: relative;
  margin: 0;
  clip-path: inset(0 round var(--r-card));
  border-radius: var(--r-card);
  background: var(--paper-2);
}

.shot img {
  display: block;
  width: 100%;
  height: auto;
}

/* Кадр под колонкой текста, а не рядом с ней: отбивка та же, что между
   блоками, иначе снимок липнет к последней строке. */
.shot--gap {
  margin-top: var(--gap-lg);
}

/* =========================================================================
   8д. Видео команды

   До нажатия YouTube не загружается: стоит афиша со ссылкой на ролик, и
   скрипт страницы подменяет её проигрывателем по щелчку. Без скрипта
   ссылка остаётся ссылкой и уводит на YouTube — видео доступно в любом
   случае.
   ========================================================================= */

.tape {
  margin: var(--gap-lg) 0 0;
  max-width: 900px;
}

.tape__play {
  position: relative;
  display: block;
  background: var(--dark-2);
}

.tape__poster {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  /* Лицо и поднятая рука сидят в верхней половине кадра: срез 16:9 из
     исходных 3:2 берёт середину, поэтому окно поднято к верху. */
  object-position: center 32%;
}

/* Треугольник набран рамками: одна фигура без файла и без шрифта значков. */
.tape__icon {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 76px;
  height: 76px;
  transform: translate(-50%, -50%);
  background: var(--accent);
  transition: background-color var(--dur-state) var(--ease);
}

.tape__icon::before {
  content: '';
  position: absolute;
  left: 52%;
  top: 50%;
  transform: translate(-50%, -50%);
  border-style: solid;
  border-width: 13px 0 13px 22px;
  border-color: transparent transparent transparent #fff;
}

.tape__play:hover .tape__icon,
.tape__play:focus-visible .tape__icon {
  background: var(--accent-ink);
}

/* Проигрыватель встаёт на место афиши тем же окном 16:9. */
.tape__frame {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 0;
  background: var(--dark-2);
}

.tape__cap {
  margin-top: calc(12px * var(--air));
  font-size: var(--t-cap);
  line-height: 1.55;
  color: var(--dark-muted);
}

/* Кадр на тёмной полосе: подложка под ним берётся из графита, иначе до
   загрузки в полосе светится бумажный прямоугольник. */
.shot--live {
  margin-top: var(--gap-lg);
  background: var(--dark-2);
}

/* =========================================================================
   8а. Строка для тех, у кого есть опыт

   Занимает одну строку сразу под обложкой. Страница ведёт предложение для
   новичков, но опытный человек должен на первом же экране увидеть, что он
   не ошибся адресом. Полоса нарочно тихая: это указатель, а не блок.
   ========================================================================= */

.forpro {
  background: var(--paper-2);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.forpro__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px var(--gap);
  padding-block: calc(18px * var(--air));
}

.forpro__text {
  margin: 0;
  max-width: 68ch;
  font-size: var(--t-small);
  color: var(--muted);
}

.forpro__link {
  flex: none;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  font-size: var(--t-small);
  font-weight: 600;
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid var(--accent-lift);
  transition: color var(--dur-state) var(--ease),
    border-color var(--dur-state) var(--ease);
}

.forpro__link:hover {
  color: var(--accent-ink);
  border-bottom-color: var(--accent-ink);
}

/* =========================================================================
   8б. Способ подачи: КАРТЫ — блок «Преимущества программы»

   Четыре пункта в два ряда по два, каждый под акцентной линейкой сверху.
   Ни рамок, ни подложек: линейка и подзаголовок держат пункт сами. От
   протокола отличается силуэтом — там полноширинные строки, здесь два
   столбца.
   ========================================================================= */

.gains {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: calc(34px * var(--air)) var(--gap-lg);
  margin: var(--gap-lg) 0 0;
  padding: 0;
  list-style: none;
}

.gains__item {
  padding-top: calc(20px * var(--air));
  border-top: 2px solid var(--accent);
}

.gains__name {
  font-size: var(--t-h4);
  margin-bottom: calc(10px * var(--air));
}

.gains__text {
  margin: 0;
  font-size: var(--t-small);
  line-height: 1.7;
  color: var(--muted);
  max-width: 52ch;
}

@media (max-width: 720px) {
  .gains {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--gap);
  }
}

/* =========================================================================
   8в. Способ подачи: ТРАССА — путь новичка до профи

   Семь шагов идут вертикальной линией с метками. Номера нарочно не набраны
   крупно: крупная нумерация занята блоком «Как начать», и два нумерованных
   блока читались бы одним приёмом, повторённым дважды. Здесь считает сама
   линия, а не цифры.
   ========================================================================= */

.road {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Шаг — строка из метки и текста. Метка идёт первым элементом строки, а не
   висит на отрицательном отступе: так она не может разъехаться с текстом,
   какой бы ни была ширина колонки и величина воздуха. */
/* Кегль и интерлиньяж заданы здесь, а не на подписи. Метка — псевдоэлемент
   шага, и её em считается от кегля шага: пока текст был набран своим
   размером, а шаг наследовал базовый, отбивка метки отмерялась от чужой
   величины и метка вставала на два-три пикселя ниже строки. */
.road__step {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: calc(16px * var(--air));
  padding-bottom: calc(20px * var(--air));
  font-size: var(--t-small);
  line-height: 1.6;
}

/* Метка центруется в первой строке: половина разницы между строкой и самой
   меткой. Метка вместе с рамкой занимает 9px. */
.road__step::before {
  content: '';
  flex: none;
  position: relative;
  z-index: 1;
  width: 7px;
  height: 7px;
  margin-top: calc((1.6em - 9px) / 2);
  background: var(--paper-2);
  border: 1px solid var(--accent);
}

/* Последний шаг — цель пути, поэтому его метка залита, а не обведена. */
.road__step:last-child::before {
  background: var(--accent);
}

/* Отрезок линии от своей метки до следующей. Линия собирается из отрезков,
   а не рисуется одной на весь список: у последнего шага отрезка нет, и
   линия не обрывается в пустоту под ним. */
.road__step:not(:last-child)::after {
  content: '';
  position: absolute;
  left: 4px;
  top: calc((1.6em + 9px) / 2);
  height: calc(100% - 9px);
  width: 1px;
  /* Не --line: та мера разлинована для полос на бумаге и на подложке
     блока в один пиксель пропадает совсем. Здесь линия несёт смысл —
     она и есть путь, — поэтому взята чернилами с прозрачностью. */
  background: rgba(22, 25, 29, 0.22);
}

.road__label {
  color: var(--ink);
}

.road__step:last-child .road__label {
  font-weight: 600;
}

.road__note {
  margin: var(--gap-lg) 0 0;
  max-width: 72ch;
  font-size: var(--t-small);
  line-height: 1.7;
  color: var(--muted);
}

/* =========================================================================
   8г. Способ подачи: ЛЕНТА КАДРОВ — победы бойцов клуба

   Двенадцать снимков сеткой заняли бы пол-страницы, поэтому они идут
   лентой и прокручиваются вбок внутри своей области. Прокрутка живёт
   внутри блока и страницу вбок не тянет — это проверяется замером.
   ========================================================================= */

.wins__title {
  margin: var(--gap-lg) 0 calc(18px * var(--air));
  font-size: var(--t-h4);
  color: var(--dark-ink);
}

.wins {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  padding-bottom: calc(14px * var(--air));
  scrollbar-width: thin;
  scrollbar-color: var(--accent-lift) rgba(255, 255, 255, 0.1);
}

.wins__track {
  display: flex;
  gap: var(--gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

.wins__item {
  flex: none;
  width: clamp(200px, 22vw, 260px);
  scroll-snap-align: start;
}

.wins__shot {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 300 / 250;
  object-fit: cover;
  background: var(--dark-2);
  margin-bottom: calc(12px * var(--air));
}

.wins__cap {
  margin: 0;
  font-size: var(--t-cap);
  line-height: 1.55;
  color: var(--dark-muted);
}

/* =========================================================================
   8в. Способ подачи: РЕПЛИКИ — отзывы на тёмной полосе

   Карточек нет: каждый отзыв стоит прямо на графите, главная фраза набрана
   заголовочной гарнитурой, подробность идёт тише, автор подписан внизу.
   Разделяет отзывы волосяная линейка — та же мера, что у компаньона.
   ========================================================================= */

.says {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: calc(36px * var(--air)) var(--gap-lg);
  margin: var(--gap-lg) 0 0;
  padding: 0;
  list-style: none;
}

.says__item {
  padding-top: calc(24px * var(--air));
  border-top: 2px solid var(--accent-lift);
}

.says__line {
  margin: 0 0 calc(14px * var(--air));
  font-family: var(--font-display);
  font-size: var(--t-h4);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-tight);
  line-height: 1.3;
  color: var(--dark-ink);
}

.says__text {
  margin: 0 0 calc(16px * var(--air));
  font-size: var(--t-small);
  line-height: 1.7;
  color: var(--dark-muted);
}

/* Подпись отзыва: портрет и имя в одну строку. Портрет квадратный — этот
   мир держит прямой угол, круглый аватар был бы чужим приёмом. */
.says__by {
  display: flex;
  align-items: center;
  gap: calc(14px * var(--air));
  margin: 0;
}

/* Кадры сняты на пресс-стене клуба, лица сидят в верхней половине, поэтому
   квадратное окно среза прижато к верху, а не к центру: по центру срез
   резал бы подбородки. */
.says__face {
  flex: none;
  display: block;
  width: 72px;
  height: 72px;
  object-fit: cover;
  object-position: center 22%;
  background: var(--dark-3);
}

.says__who {
  margin: 0;
  font-size: var(--t-cap);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent-lift);
}

@media (max-width: 860px) {
  .says {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--gap);
  }
}

/* =========================================================================
   9а. Полоса кадра
   Кадр во всю ширину окна, без плашки поверх. Достался блоку «Если вы
   начинаете с нуля»: заголовок стоит под кадром, а не на нём.
   ========================================================================= */

.band {
  margin: 0 0 var(--gap-lg);
}

/* Секция начинается кадром или заголовком во всю ширину, поэтому верхнего
   поля у неё нет: иначе над ними встаёт полоса пустоты. Класс носят обе
   такие секции — полоса программы и полоса с кадром.

   Правило висит на классе, а не на идентификаторе секции. Раньше висело на
   идентификаторе, секции переименовали, и оно осталось снимать отступ у
   чужого блока. Класс едет вместе с разметкой, повторить это нельзя. */
.sec--flush {
  padding-top: 0;
}

/* Высота задана прямо, а не соотношением с потолком. Пара «соотношение +
   max-height» и была причиной брака: на широком экране потолок срабатывал,
   object-fit: cover доснимал разницу по вертикали, и от кадра оставалась
   полоса в три с половиной ширины — торсы без голов.

   Якорь 38% держит лица. Прежний center bottom берёг водяной знак внизу
   кадра, но при узком окне среза оставлял ровно то, что ниже лиц. Знак в
   срез не попадает — он не режется пополам, а остаётся за кадром, и на
   шести кадрах мозаики выше он виден целиком. */
.band img {
  display: block;
  width: 100%;
  height: clamp(320px, 34vw, 560px);
  object-fit: cover;
  object-position: center 38%;
  background: var(--paper-2);
}

/* На узком экране кадр стоит целиком в своём 3:2 — там места хватает, и
   водяной знак остаётся в кадре. */
@media (max-width: 720px) {
  .band img {
    height: auto;
    aspect-ratio: 3 / 2;
  }
}

/* Лид рядом с прилипающим заголовком компаньона. */
.pair__lead {
  margin: calc(18px * var(--air)) 0 0;
  font-size: var(--t-small);
  line-height: 1.7;
  color: var(--muted);
  max-width: 40ch;
}

/* =========================================================================
   9б. Способ подачи: ШАГИ
   Три колонки под акцентной линейкой, номер набран крупно и работает
   графикой. Ни рамок, ни подложек: это последовательность, а не набор
   равных плиток. Достался блоку «Как начать» и больше нигде не повторён —
   нумерация на странице одна.
   ========================================================================= */

.steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gap-lg);
  margin: var(--gap-lg) 0 0;
  padding: 0;
  list-style: none;
}

.steps__item {
  padding-top: calc(20px * var(--air));
  border-top: 2px solid var(--accent);
}

.steps__num {
  display: block;
  font-family: var(--font-display);
  font-size: var(--t-h2);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-tight);
  line-height: 1;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  margin-bottom: calc(16px * var(--air));
}

.steps__name {
  font-size: var(--t-h4);
  margin-bottom: calc(10px * var(--air));
}

.steps__text {
  font-size: var(--t-small);
  line-height: 1.7;
  color: var(--muted);
  margin: 0;
}

.steps__cta {
  margin: var(--gap-lg) 0 0;
}

@media (max-width: 860px) {
  .steps {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--gap);
  }
}

/* =========================================================================
   9б. Способ подачи: ПРОТОКОЛ
   Полноширинные строки с волосяной линейкой: ярлык слева, содержание
   справа. Силуэт — горизонтальные полосы. Достался блокам «Если вы уже
   занимались» и «Кому подойдут тренировки»; между ними лежат три блока
   других способов подачи, поэтому соседями они не оказываются.
   ========================================================================= */

.proto {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--line);
}

/* Протокол внутри колонки разворота, а не во всю ширину полосы: строки
   короче, поэтому отбивка внутри строки убавлена, иначе четыре пункта
   растягивают колонку вдвое против кадра рядом. */
.proto--tight {
  margin-top: var(--gap);
}

.proto--tight .proto__row {
  padding-block: calc(14px * var(--air));
}

.proto__row {
  display: grid;
  grid-template-columns: minmax(0, 16rem) minmax(0, 1fr);
  gap: calc(6px * var(--air)) var(--gap-lg);
  align-items: baseline;
  padding: calc(22px * var(--air)) 0;
  border-bottom: 1px solid var(--line);
}

.proto__head {
  font-family: var(--font-display);
  font-size: var(--t-h4);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-tight);
  line-height: 1.25;
  margin: 0;
}

.proto__text {
  font-size: var(--t-small);
  line-height: 1.65;
  color: var(--muted);
  margin: 0;
  max-width: 62ch;
}

.sec--live .proto {
  border-top-color: var(--dark-line);
}

.sec--live .proto__row {
  border-bottom-color: var(--dark-line);
}

.sec--live .proto__head {
  color: var(--dark-ink);
}

.sec--live .proto__text {
  color: var(--dark-muted);
}

@media (max-width: 720px) {
  .proto__row {
    grid-template-columns: minmax(0, 1fr);
    gap: calc(8px * var(--air));
  }
}

/* =========================================================================
   9в. Способ подачи: РЕПЛИКА
   Одна фраза во весь экран заголовочной гарнитурой, прямо на полосе, без
   карточки. Всё остальное — приглушённой колонкой сбоку. Достался блоку
   «ALMAZ FIGHT TEAM».
   ========================================================================= */

.utter {
  display: grid;
  grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
  gap: var(--gap-lg);
  align-items: start;
}

.utter__line {
  position: relative;
  padding-left: calc(24px * var(--air));
  margin: 0;
  max-width: 26ch;
  font-family: var(--font-display);
  font-size: calc(clamp(23px, 2.6vw, 38px) * var(--scale));
  font-weight: var(--display-weight);
  letter-spacing: var(--display-tight);
  line-height: 1.22;
  color: var(--dark-ink);
  text-wrap: balance;
}

/* Эфирная линия во всю высоту реплики: то же, что у титра, но длиной в
   целое высказывание. */
.utter__line::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.14em;
  bottom: 0.1em;
  width: 2px;
  background: var(--accent-lift);
}

.utter__side {
  padding-top: calc(8px * var(--air));
  color: var(--dark-muted);
  font-size: var(--t-small);
  line-height: 1.7;
}

.utter__side > * + * {
  margin-top: calc(18px * var(--air));
}

@media (max-width: 900px) {
  .utter {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--gap);
  }

  .utter__line {
    max-width: 30ch;
  }
}

/* =========================================================================
   10. Способ подачи: КОМПАНЬОН
   Узкая колонка с заголовком слева прилипает при прокрутке, содержание
   идёт одной колонкой справа. Достался блокам «Как клуб держит уровень»
   и «Частые вопросы». Пропорция колонок нарочно обратна реплике: там
   тяжёлая сторона слева, здесь справа, и соседями они не путаются.
   ========================================================================= */

.pair {
  display: grid;
  grid-template-columns: minmax(0, 0.58fr) minmax(0, 1fr);
  gap: var(--gap-lg) calc(var(--gap-lg) * 1.3);
  align-items: start;
}

.pair__head {
  position: sticky;
  top: calc(var(--header-h) + 24px);
  min-width: 0;
}

.pair__title {
  font-size: var(--t-h2);
  max-width: 16ch;
  margin: 0;
}

.pair__note {
  margin: calc(12px * var(--air)) 0 0;
  font-size: var(--t-cap);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.pair__body {
  margin: 0;
  padding: 0;
  list-style: none;
  min-width: 0;
}

/* Карточек нет: пункты разделяет волосяная линейка. Одна декларация
   высоты вместо рамки и подложки на каждом пункте. */
.pair__item + .pair__item {
  margin-top: calc(28px * var(--air));
  padding-top: calc(28px * var(--air));
  border-top: 1px solid var(--line);
}

.pair__name {
  font-size: var(--t-h4);
  margin-bottom: calc(10px * var(--air));
}

.pair__text {
  font-size: var(--t-small);
  line-height: 1.7;
  color: var(--muted);
  margin: 0;
  max-width: 64ch;
}

@media (max-width: 860px) {
  .pair {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--gap);
  }

  /* Прилипание на узком экране только мешает: заголовок занял бы верх
     экрана на всё время чтения списка. */
  .pair__head {
    position: static;
  }
}

/* =========================================================================
   12. Блок 13. Стоимость
   ========================================================================= */

/* Цены стоят прямо на полосе крупным кеглем, без карточек: сумма и есть
   содержание блока, подложка вокруг неё ничего не добавляла. */
.duo {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: calc(30px * var(--air)) var(--gap-lg);
  margin-top: var(--gap-lg);
}

.duo__col {
  padding-top: calc(22px * var(--air));
  border-top: 2px solid var(--accent);
  min-width: 0;
}

.duo__mark {
  display: block;
  font-family: var(--font-display);
  font-size: var(--t-num);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-tight);
  line-height: 1;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  margin-bottom: calc(16px * var(--air));
}

.duo__who {
  font-size: var(--t-h3);
  margin-bottom: 2px;
}

.duo__when {
  font-size: var(--t-small);
  color: var(--muted);
  margin: 0;
}

/* =========================================================================
   14. Блок 12. Расписание (тёмная полоса)
   Классы внутри [data-schedule] рисует site.js — вариант их только красит.
   ========================================================================= */

.board {
  background: var(--dark-2);
  border: 1px solid var(--dark-line);
  border-radius: var(--r-card);
  overflow: hidden;
}

.schedule-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-small);
}

.schedule-table thead th {
  padding: calc(14px * var(--air)) calc(20px * var(--air));
  background: var(--dark-3);
  color: var(--dark-muted);
  font-family: var(--font-text);
  font-size: var(--t-cap);
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  text-align: left;
}

.schedule-row {
  border-top: 1px solid var(--dark-line);
  transition: background-color var(--dur-state) var(--ease);
}

.schedule-row:hover {
  background: rgba(255, 255, 255, 0.04);
}

.schedule-row__day,
.schedule-row__time,
.schedule-row__group {
  padding: calc(14px * var(--air)) calc(20px * var(--air));
  text-align: left;
  color: var(--dark-ink);
  font-weight: 400;
}

.schedule-row__day {
  font-weight: 600;
  white-space: nowrap;
}

/* Повтор имени дня во второй строке остаётся для экранного диктора,
   но глаз им не грузим. */
.schedule-row[data-repeat] .schedule-row__day {
  color: transparent;
}

.schedule-row__time {
  font-variant-numeric: tabular-nums;
  color: var(--accent-lift);
  white-space: nowrap;
}

.schedule-row[data-empty] .schedule-row__time,
.schedule-row[data-empty] .schedule-row__group {
  color: var(--dark-muted);
}

.schedule-row.is-today {
  background: rgba(255, 255, 255, 0.05);
  box-shadow: inset 2px 0 0 var(--accent-lift);
}

.schedule-mobile {
  display: none;
  padding: calc(16px * var(--air));
}

.schedule-days {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding-bottom: 8px;
  scrollbar-width: thin;
}

/* position: relative обязателен. Внутри кнопки лежит .visually-hidden с
   полным именем дня для экранного диктора, а он объявлен
   position: absolute !important. Без позиционированного предка его
   содержащим блоком становится корень страницы: лента дней с overflow-x
   его уже не режет, и на 360 документ получал лишние 21 px вбок — при том
   что сам он невидим. Кнопка берёт роль содержащего блока, и подпись
   уезжает вместе с лентой, а не с документом. */
.schedule-day {
  position: relative;
  flex: none;
  min-width: 46px;
  min-height: 44px;
  padding: 0 10px;
  border-radius: var(--r-btn);
  background: var(--dark-3);
  color: var(--dark-muted);
  font-family: var(--font-text);
  font-size: var(--t-cap);
  font-weight: 600;
  letter-spacing: 0.04em;
  transition: background-color var(--dur-state) var(--ease),
    color var(--dur-state) var(--ease);
}

.schedule-day:hover {
  color: var(--dark-ink);
}

.schedule-day.is-active {
  background: var(--accent-lift);
  color: var(--dark);
}

.schedule-panel {
  padding-top: calc(18px * var(--air));
}

.schedule-panel__day {
  margin: 0 0 calc(12px * var(--air));
  font-family: var(--font-display);
  font-size: var(--t-h4);
  font-weight: var(--display-weight);
  color: var(--dark-ink);
}

.schedule-cards {
  display: grid;
  gap: 8px;
  margin: 0;
}

.schedule-card {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 14px;
  padding: calc(14px * var(--air));
  background: var(--dark-3);
  border-radius: var(--r-btn);
}

.schedule-card__time {
  font-weight: 600;
  color: var(--accent-lift);
  font-variant-numeric: tabular-nums;
}

.schedule-card__group {
  color: var(--dark-ink);
  font-size: var(--t-small);
}

.schedule-empty {
  margin: 0;
  color: var(--dark-muted);
  font-size: var(--t-small);
}

/* =========================================================================
   15. Блок 11. Зал (тёмная полоса)

   Съёмка пермской площадки живёт только здесь. Водяного знака на ней нет,
   поэтому эти кадры, в отличие от съёмки клуба, кроить можно свободно —
   ведущий снимок взят кинематографической полосой 16:9.
   ========================================================================= */

/* Две колонки, а не три: кадров площадки осталось три — общий план и два
   в ряд. При трёх колонках после снятия четвёртого кадра оставалась дыра
   в правой ячейке. */
.gallery {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: calc(14px * var(--air));
  margin-bottom: var(--gap-lg);
}

.gallery figure {
  margin: 0;
  overflow: hidden;
  border-radius: var(--r-card);
  background: var(--dark-2);
}

.gallery img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.gallery__wide {
  grid-column: 1 / -1;
}

.gallery__wide img {
  aspect-ratio: 16 / 9;
}

.gallery__cell img {
  aspect-ratio: 3 / 2;
}

@media (max-width: 760px) {
  .gallery {
    grid-template-columns: minmax(0, 1fr);
  }

  .gallery__wide img {
    aspect-ratio: 3 / 2;
  }
}

/* --- Адрес --------------------------------------------------------------- */

/* Три колонки разной ширины, а не три равные: адресу нужна строка, куда
   влезет «ТЦ „Домино“, 4 этаж», а портрету — узкая колонка. */
.place {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr) minmax(0, 0.7fr);
  gap: var(--gap-lg);
  align-items: start;
  margin-top: var(--gap-lg);
}

@media (max-width: 900px) {
  .place {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
    gap: var(--gap);
  }
}

.place__card {
  padding: calc(26px * var(--air));
  background: var(--card);
  border-radius: var(--r-card);
}

.place__addr {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-tight);
  line-height: 1.35;
}

/* Клуб, на чьей базе идут тренировки, набран как обычная строка адреса:
   без выделения и без цвета. Это ориентир, а не второй бренд. */
.place__base,
.place__phone {
  margin: calc(14px * var(--air)) 0 0;
  font-size: var(--t-small);
  color: var(--muted);
}

.place__marks {
  display: flex;
  flex-direction: column;
  gap: calc(14px * var(--air));
  margin: 0;
  padding: calc(4px * var(--air)) 0 0;
}

.place__mark {
  position: relative;
  padding-left: 28px;
  font-size: var(--t-small);
  line-height: 1.55;
  color: var(--muted);
}

/* Эфирная отбивка вместо маркера — та же линия, что у места на обложке. */
.place__mark::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 16px;
  height: 2px;
  background: var(--accent);
}

/* Адрес стоит на тёмной полосе, поэтому карточка берёт студийный графит,
   а не белую бумагу: --muted на графите даёт 3,4 : 1 и до планки не
   дотягивает. */
.sec--live .place__card {
  background: var(--dark-2);
  border: 1px solid var(--dark-line);
}

.sec--live .place__base,
.sec--live .place__phone,
.sec--live .place__mark {
  color: var(--dark-muted);
}

.sec--live .place__mark::before {
  background: var(--accent-lift);
}

/* Портрет тренера площадки. Подписи со званиями нет намеренно — имя и
   регалии заказчик не передал. Поэтому кадр стоит третьей колонкой
   адреса, а не отдельным блоком «наши тренеры»: он часть рассказа о зале. */
.place__coach {
  margin: 0;
}

.place__coach img {
  display: block;
  width: 100%;
  height: auto;
  /* Кадр вертикальный, 2:3. Берём 4:5 и держим верх: голова и награды
     остаются, отрезаются только ноги — и колонка не уезжает вниз вдвое
     дальше соседних. */
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: center top;
  border-radius: var(--r-card);
  background: var(--dark-2);
}

.place__coach-cap {
  margin-top: calc(12px * var(--air));
  font-size: var(--t-cap);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--dark-muted);
}

/* =========================================================================
   16. Блок 14. Подвал
   ========================================================================= */

.foot {
  background: var(--paper-2);
}

.foot__cta-wrap {
  background: var(--tint);
  padding-block: var(--sec-pad);
}

.foot__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  padding: calc(36px * var(--air));
  background: var(--card);
  border-radius: calc(var(--r-card) * 1.5);
}

.foot__cta-title {
  font-size: var(--t-h2);
  margin-bottom: calc(12px * var(--air));
}

/* Строка призыва. Стоит между заголовком и телефоном, поэтому отбивка
   снизу крупнее, чем сверху: телефон набран заголовочной гарнитурой и
   без воздуха липнет к тексту. */
.foot__cta-lead {
  margin: 0 0 calc(18px * var(--air));
  max-width: 52ch;
  font-size: var(--t-lead);
  line-height: 1.55;
  color: var(--muted);
}

.foot__cta-tel {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--font-display);
  font-size: calc(clamp(24px, 2.6vw, 34px) * var(--scale));
  font-weight: var(--display-weight);
  letter-spacing: var(--display-tight);
  color: var(--accent);
  text-decoration: none;
  font-variant-numeric: tabular-nums;
}

.foot__cta-note {
  margin-top: 6px;
  font-size: var(--t-small);
  color: var(--muted);
}

/* Полоса вопросов в подвале. Правила ленты новостей удалены вместе с
   самой лентой: заказчик снял её со страницы. */
.foot__faq-wrap {
  padding-block: calc(var(--sec-pad) * 0.66);
  border-top: 1px solid var(--line);
}

.foot__legal-wrap {
  padding-block: calc(var(--sec-pad) * 0.5);
  border-top: 1px solid var(--line);
  font-size: var(--t-cap);
  color: var(--muted);
}

.foot__legal-top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  margin-bottom: calc(20px * var(--air));
}

.foot__sitemap {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--ink);
  font-size: var(--t-small);
}

.socials {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0;
}

.social {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: var(--r-btn);
  color: var(--muted);
  transition: color var(--dur-state) var(--ease),
    background-color var(--dur-state) var(--ease);
}

.social:hover {
  color: var(--accent);
  background: rgba(47, 109, 140, 0.1);
}

.foot__copy {
  margin-bottom: calc(16px * var(--air));
  max-width: none;
}

.foot__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin-bottom: calc(20px * var(--air));
}

.foot__tags a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  min-width: 44px;
  color: var(--muted);
  text-decoration: none;
}

.foot__tags a:hover {
  color: var(--accent);
  text-decoration: underline;
}

.foot__fine {
  max-width: 90ch;
  line-height: 1.6;
}

.foot__fine + .foot__fine {
  margin-top: 10px;
}

/* =========================================================================
   17. Липкая полоса действия
   ========================================================================= */

.actionbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  display: none;
  gap: 10px;
  padding: 10px var(--pad) calc(10px + env(safe-area-inset-bottom, 0px));
  padding-right: calc(var(--pad) + var(--scrollbar-gap, 0px));
  background: var(--card);
  border-top: 1px solid var(--line);
  box-shadow: 0 -6px 20px rgba(20, 23, 27, 0.1);
  transform: translateY(110%);
  transition: transform 300ms var(--ease);
}

.actionbar.is-visible {
  transform: translateY(0);
}

.btn--bar {
  flex: 1 1 0;
  min-height: 48px;
  padding: 10px 14px;
  font-size: calc(15px * var(--scale));
}

/* =========================================================================
   18. Модальные окна и формы
   Скрытие берёт на себя скрипт: здесь описано только открытое состояние.
   ========================================================================= */

.modal {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--pad);
  opacity: 0;
  transition: opacity 260ms var(--ease);
}

.modal.is-open {
  opacity: 1;
}

.modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20, 23, 27, 0.55);
  backdrop-filter: blur(4px);
}

.modal__window {
  position: relative;
  z-index: 1;
  width: min(520px, 100%);
  max-height: 88vh;
  overflow-y: auto;
  padding: calc(34px * var(--air));
  background: var(--card);
  border-radius: calc(var(--r-card) * 1.25);
  box-shadow: 0 24px 60px rgba(20, 23, 27, 0.3);
  transform: translateY(14px) scale(0.985);
  transition: transform 300ms var(--ease);
}

.modal.is-open .modal__window {
  transform: none;
}

.modal__close {
  position: absolute;
  top: 10px;
  right: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-btn);
  color: var(--muted);
  transition: color var(--dur-state) var(--ease),
    background-color var(--dur-state) var(--ease);
}

.modal__close:hover {
  color: var(--ink);
  background: rgba(20, 23, 27, 0.06);
}

.modal__title {
  font-size: calc(clamp(21px, 2.2vw, 28px) * var(--scale));
  padding-right: 44px;
}

.modal__sub {
  margin-top: 6px;
  margin-bottom: calc(24px * var(--air));
  font-size: var(--t-small);
  color: var(--muted);
}

.form {
  display: grid;
  gap: 4px;
}

.field {
  position: relative;
  margin-top: calc(16px * var(--air));
}

.field__input {
  width: 100%;
  min-height: 52px;
  padding: 20px 2px 6px;
  background: transparent;
  border: 0;
  border-bottom: 1.5px solid var(--line);
  border-radius: 0;
  font-size: calc(16px * var(--scale));
  color: var(--ink);
  transition: border-color var(--dur-state) var(--ease);
}

select.field__input {
  padding-right: 24px;
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 12px) 62%, calc(100% - 6px) 62%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}

.field__input:focus {
  outline: none;
  border-bottom-color: var(--accent);
}

.field__input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.field__label {
  position: absolute;
  left: 2px;
  top: 16px;
  font-size: calc(16px * var(--scale));
  color: var(--muted);
  pointer-events: none;
  transition: transform 180ms var(--ease), font-size 180ms var(--ease),
    color 180ms var(--ease);
  transform-origin: left top;
}

.field__input:focus + .field__label,
.field__input:not(:placeholder-shown) + .field__label,
.field--filled .field__label {
  transform: translateY(-14px) scale(0.78);
  color: var(--accent);
}

.range {
  margin-top: calc(20px * var(--air));
  padding: 0;
  border: 0;
}

.range__legend {
  padding: 0;
  font-size: var(--t-cap);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.range__row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap);
}

.form .btn {
  margin-top: calc(26px * var(--air));
}

.consent {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 10px;
  align-items: start;
  margin-top: calc(18px * var(--air));
}

.consent__box {
  width: 20px;
  height: 20px;
  margin: 2px 0 0;
  accent-color: var(--accent);
  flex: none;
}

.consent__label {
  font-size: var(--t-cap);
  line-height: 1.5;
  color: var(--muted);
}

/* Подсказка, а не выговор: приглушённый тон, не сигнальный. */
.form-error {
  margin: 0;
  min-height: 0;
  font-size: var(--t-cap);
  color: var(--err);
}

.form-error:empty {
  display: none;
}

.field.has-error .field__input,
[data-field].has-error .field__input {
  border-bottom-color: var(--err);
}

/* Экран успеха подменяет [data-modal-body] целиком. */
.form-success {
  display: grid;
  justify-items: center;
  gap: calc(16px * var(--air));
  padding: calc(20px * var(--air)) 0;
  text-align: center;
}

.form-success:focus {
  outline: none;
}

.form-success__mark {
  color: var(--ok);
}

.form-success__text {
  font-size: var(--t-lead);
  max-width: 34ch;
}

.form-success__close {
  min-height: 48px;
  padding: 12px 26px;
  background: var(--accent);
  color: #fff;
  border-radius: var(--r-btn);
  font-weight: 600;
  transition: background-color var(--dur-state) var(--ease);
}

.form-success__close:hover {
  background: var(--accent-ink);
}

/* =========================================================================
   19. Движение
   Содержание видимо по умолчанию: стартовое состояние живёт только внутри
   .js, и упавший скрипт страницу не спрячет.
   ========================================================================= */

@media (prefers-reduced-motion: no-preference) {
  /* Ровное появление секций. Переход, а не анимация: site.js расставляет
     соседям ступенчатую задержку через transition-delay. */
  /* Исключения из общего появления больше нет: полоса с заголовком
     появляется тем же тихим движением, что и остальные блоки. Отдельная
     сцена с вытеснением, выездом титра и ростом линейки снята — она была
     единственным громким движением на странице и на одном заголовке из
     десяти читалась вспышкой, а не приёмом. */
  html.js:not([data-motion='off']) [data-reveal] {
    opacity: 0;
    transform: translateY(var(--rise));
    transition: opacity 520ms var(--ease), transform 520ms var(--ease);
  }

  html.js:not([data-motion='off']) [data-reveal].is-visible {
    opacity: 1;
    transform: none;
  }
}

/* Лёгкое смещение фотографии относительно текста. Связь с прокруткой
   тут и есть смысл приёма, поэтому берём scroll-driven там, где он есть;
   где его нет — снимок просто стоит на месте. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* Длительность пишется отдельной строкой и только как auto: сокращённая
       запись animation сбрасывает её в 0s, и связь с прокруткой пропадает —
       кадр замирает в начальном положении. */
    html.js:not([data-motion='off']) [data-drift] img {
      animation-name: drift;
      animation-duration: auto;
      animation-timing-function: linear;
      animation-fill-mode: both;
      animation-timeline: view();
      animation-range: entry 0% exit 100%;
    }
  }
}

@keyframes drift {
  from {
    transform: translate3d(0, calc(var(--drift) * -1), 0) scale(var(--drift-zoom));
  }
  to {
    transform: translate3d(0, var(--drift), 0) scale(var(--drift-zoom));
  }
}

/* =========================================================================
   20. Панель твиков и переключатель вариантов
   Только перекраска объявленными переменными: раскладку вариант не трогает.
   ========================================================================= */

.tweaks {
  --tweaks-bg: var(--card);
  --tweaks-fg: var(--ink);
  --tweaks-muted: var(--muted);
  --tweaks-border: rgba(20, 23, 27, 0.16);
  --tweaks-line: rgba(20, 23, 27, 0.09);
  --tweaks-hover-bg: rgba(20, 23, 27, 0.04);
  --tweaks-on-bg: #14171b;
  --tweaks-on-fg: #ffffff;
  --tweaks-field-bg: rgba(20, 23, 27, 0.04);
  --tweaks-shadow: 0 10px 30px rgba(20, 23, 27, 0.2);
  --tweaks-radius: 14px;
  --tweaks-radius-sm: 9px;
}


/* =========================================================================
   21. Ширины
   ========================================================================= */

/* Восемь пунктов меню, плашка, телефон и кнопка встают в один ряд только
   на широком экране. Ниже плашка уходит — второй ряд меню в шапке высотой
   72 px выглядит поломкой. На мобильном она возвращается в меню. */
@media (max-width: 1420px) {
  .hdr__side .chip {
    display: none;
  }
}

/* Восемь пунктов меню перестают помещаться в один ряд раньше, чем
   ломается раскладка страницы, поэтому у шапки свой порог. */
@media (max-width: 1219px) {
  .hdr__nav,
  .hdr__side {
    display: none;
  }

  .hdr__mobile {
    display: flex;
  }
}

@media (max-width: 960px) {
  :root {
    --header-h: 62px;
  }

  /* На узком экране выход за поля теряет смысл: колонка одна, и кадр во
     всю ширину упирался бы в оба края, а текст под ним — только в левый.
     Поля возвращаются с обеих сторон. */
  .hero__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--gap);
    padding-inline: var(--pad);
  }

  /* Кадр встаёт между заголовком и текстом. Заказчик: на первом экране
     телефона не хватает картинки — и он прав, до правки там были одни
     буквы, а вырезанный боец начинался под сгибом.

     display: contents распускает левую колонку на её части, и они
     становятся ячейками той же сетки, что и сцена. Порядок задаётся
     свойством order, разметку менять не пришлось. */
  .hero__main {
    display: contents;
  }

  .hero__head {
    order: 1;
  }

  .hero__stage {
    order: 2;
  }

  .hero__body {
    order: 3;
  }

  /* На телефоне кадр стоит целиком в своём 3:2 и во всю ширину колонки.
     Заданная высота здесь всё испортила бы: она заставила бы object-fit
     резать кадр по бокам, а резать его нельзя — см. правило выше. */
  .hero__figure {
    height: auto;
  }

  /* Разворот в одну колонку. Кадр не уезжает в сторону, а ложится полосой
     во всю ширину окна — на узком экране это тот же жест выхода за поля,
     только по обеим сторонам сразу. */
  .spread,
  .spread--flip {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--gap);
    padding-inline: 0;
  }

  .spread__text,
  .spread--flip .spread__text {
    order: 0;
    padding-inline: var(--pad);
  }

  .spread__shot,
  .spread--flip .spread__shot {
    order: 1;
    clip-path: none;
    border-radius: 0;
  }

  .hero__stage {
    max-width: 460px;
    margin-inline: auto;
  }

  [data-hero-layout='full'] .hero__stage,
  [data-hero-layout='stack'] .hero__stage {
    position: static;
    width: auto;
    max-width: 460px;
  }

  .hero[data-hero-layout='full']::after {
    display: none;
  }

  [data-hero-layout='full'] .hero__figure {
    height: clamp(300px, 46vh, 420px);
  }

  [data-hero-layout='full'] .hero__grid {
    min-height: 0;
  }

  .onair__grid {
    padding-inline: var(--pad);
    min-height: 0;
  }

  .onair__desk {
    padding: calc(28px * var(--air)) 0 calc(32px * var(--air));
  }

  .place__coach {
    max-width: 320px;
  }
}

@media (max-width: 768px) {
  /* Шкала на телефоне не уменьшается, а растёт. Прежние 16px в теле и 13px
     в подписях считались от настольного экрана, где до текста полметра; с
     телефона в дороге читают ближе и хуже, и заказчик правильно указал, что
     мелкий кегль там бьёт по читаемости.

     Переопределяются сами меры, а не только тело: подписи, лид и мелкий
     текст набраны ими и до правки оставались прежними. Множитель --scale
     внутри сохранён, поэтому ручка «Кегль» продолжает работать. */
  :root {
    --t-body: calc(18px * var(--scale));
    --t-lead: calc(19px * var(--scale));
    --t-small: calc(16px * var(--scale));
    --t-cap: calc(14px * var(--scale));
    --t-h4: calc(19px * var(--scale));
  }

  body {
    font-size: var(--t-body);
  }

  .actionbar {
    display: flex;
  }

  /* Панель твиков и переключатель вариантов поднимаются над полосой. */
  .tweaks {
    --tweaks-lift: 74px;
  }


  .foot {
    padding-bottom: 78px;
  }

  .schedule-table {
    display: none;
  }

  .schedule-mobile {
    display: block;
  }
}

@media (max-width: 560px) {
  .range__row {
    grid-template-columns: minmax(0, 1fr);
  }

  .foot__cta {
    padding: calc(26px * var(--air));
  }

  .modal {
    padding: 0;
    align-items: flex-end;
  }

  .modal__window {
    width: 100%;
    max-height: 92vh;
    border-radius: calc(var(--r-card) * 1.25) calc(var(--r-card) * 1.25) 0 0;
    padding: calc(28px * var(--air)) var(--pad) calc(32px * var(--air));
  }
}

@media print {
  .hdr,
  .actionbar,
  .menu,
  .modal {
    display: none !important;
  }
}
