
/* ═══════════════════════════════════════════════════════════
   Токены. Единственный источник правды — DESIGN.md.
   Смена гарнитуры — одна строка: --font.
   ═══════════════════════════════════════════════════════════ */


/* Кандидаты в гарнитуру. Тимур предложил Manrope или Inter в тексте и акцентную
   антикву в заголовках (fonts.uprock.ru). Оставляем TT Firs Neue как точку отсчёта:
   пара переключается на живой странице, выбор делается глазами, а не по описанию. */
@font-face {
  font-family: 'Manrope'; src: url('/fonts/Manrope-Var.woff2') format('woff2-variations');
  font-weight: 200 800; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Inter'; src: url('/fonts/Inter-Var.woff2') format('woff2-variations');
  font-weight: 100 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Alethia Pro'; src: url('/fonts/AlethiaPro-Regular.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Felidae'; src: url('/fonts/Felidae-Regular.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'TT Firs Neue';
  src: url('/fonts/TTFirsNeue-Regular.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'TT Firs Neue';
  src: url('/fonts/TTFirsNeue-Medium.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'TT Firs Neue';
  src: url('/fonts/TTFirsNeue-Bold.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}

:root {
  --font: 'TT Firs Neue', Helvetica, Arial, sans-serif;
  --font-display: var(--font);        /* заголовки; переключается парой */
  --display-tracking: -1px;

  --surface: #ffffff;
  --surface-muted: #f0f0f0;
  --surface-raised: #ffffff;         /* поверхность, приподнятая над muted:
                                        день календаря, значок в полосе,
                                        раскрытый вопрос. Звался четырьмя
                                        компонентами и не был объявлен —
                                        подложка молча падала в прозрачную */
  --surface-ink: #17205a;            /* кобальт — выбор Тимура из четырёх кандидатов,
                                        закрыт 21.08. ORACAL 641 065M / RAL 5013.
                                        Белый текст на нём — 13,9:1 */
  --ink-glow: #2a3684;               /* синее свечение в градиенте тёмных поверхностей */
  --text: #1e1e1e;
  --text-inverse: #ffffff;
  --text-muted: #666b71;
  --text-on-ink: #c9ced4;
  --accent: #0096cf;
  --accent-deep: #007bab;
  --accent-wash: #e6f4fb;
  --highlight: #f9dd66;
  --accent-warm: #7a5c00;            /* единственный тёплый в системе: тип события
                                        AI Demo Day и текст статуса «лист ожидания».
                                        6,25:1 на белом — годится и как цвет текста */
  --border: rgba(30, 30, 30, 0.12);
  --border-on-ink: rgba(255, 255, 255, 0.16);

  --r-control: 6px;
  --r-pill: 12px;
  --r-card: 20px;

  --s-xs: 8px;
  --s-sm: 16px;
  --s-md: 24px;
  --s-lg: 40px;
  --s-xl: 80px;

  --container: 1280px;
  --gutter: 24px;
  --bento-row: 320px;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}


/* Кандидаты в тёмную поверхность (FEST #151b28, Navy #131936, Peony #1b2f52,
   кобальт #17205a) сравнивались на v9-v12 переключателем `?ink=`. 21.08 выбран
   кобальт, переключатель снят, значение стоит в базовом токене выше.
   История сравнения жива в v12. */

/* ═══════════════════════════════════════════════════════════
   База
   ═══════════════════════════════════════════════════════════ */

*, *::before, *::after { box-sizing: border-box; }

html { scrollbar-color: var(--accent) var(--surface-muted); }

body {
  margin: 0;
  background: var(--surface);
  color: var(--text);
  font-family: var(--font);
  font-size: 1rem;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection { background: var(--accent); color: var(--text-inverse); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--r-control); }

img { max-width: 100%; display: block; }
a { color: inherit; }

.wrap {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--s-lg);
}
@media (max-width: 767px) { .wrap { padding: 0 var(--s-md); } }

/* ═══════════════════════════════════════════════════════════
   Типографика. Иерархия — кеглем и воздухом, вес держим 400–500.
   ═══════════════════════════════════════════════════════════ */

h1, h2, h3, h4 { margin: 0; font-weight: 400; text-wrap: balance; font-family: var(--font-display); }

.display {
  font-family: var(--font-display);
  font-size: clamp(2rem, 4.4vw, 3rem);
  line-height: 1.06;
  letter-spacing: var(--display-tracking);
}
.headline {
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  line-height: 1.1;
  letter-spacing: -0.4px;
}
.title { font-size: 1.25rem; font-weight: 500; line-height: 1.2; }
.label {
  font-size: 0.875rem;
  line-height: 1.2;
  letter-spacing: -0.14px;
  color: var(--text-muted);
}

p { margin: 0; max-width: 68ch; }
.muted { color: var(--text-muted); }

/* Висящий заголовок: стоит в воздухе, не внутри контейнера.
   Над ним больше воздуха, чем под ним. */
.section-head {
  margin: var(--s-xl) 0 var(--s-lg);
  display: grid;
  gap: var(--s-sm);
  max-width: 62ch;
}
@media (max-width: 767px) { .section-head { margin: 56px 0 var(--s-md); } }

/* ═══════════════════════════════════════════════════════════
   Сетка и плитка-конструктор.
   Плитка НЕ имеет типа: плитка = след × слот картинки × действие.
   Плитки с одинаковым следом свободно подменяют друг друга.
   Канон — DESIGN.md, раздел «Плитка-конструктор».
   ═══════════════════════════════════════════════════════════ */

.bento {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--gutter);
  grid-auto-rows: var(--bento-row);
}

/* ── Ось 1: след. Список закрыт, новый добавляется правкой DESIGN.md ── */
.t-s  { grid-column: span 3; }                   /* 3×1  282×320  */
.t-m  { grid-column: span 4; }                   /* 4×1  384×320  */
.t-t  { grid-column: span 4; grid-row: span 2; } /* 4×2  384×664  */
.t-l  { grid-column: span 6; }                   /* 6×1  588×320  */
.t-w  { grid-column: span 8; }                   /* 8×1  792×320  */
.t-f  { grid-column: span 12; }                  /* 12×1 1200×320 */
.t-f2 { grid-column: span 12; grid-row: span 2; }/* 12×2 1200×664 */

/* Перекладка задаётся СЛЕДОМ, а не содержимым — поэтому подмена безопасна. */
@media (max-width: 1023px) {
  .bento { grid-template-columns: repeat(8, 1fr); }
  .t-s, .t-m, .t-t { grid-column: span 4; }
  .t-l, .t-w, .t-f, .t-f2 { grid-column: span 8; }
}
@media (max-width: 767px) {
  :root { --gutter: 16px; }
  .bento { grid-template-columns: repeat(4, 1fr); grid-auto-rows: auto; }
  .t-s, .t-m, .t-t, .t-l, .t-w, .t-f, .t-f2 { grid-column: span 4; grid-row: auto; }
  .tile { min-height: 180px; }
}

/* ── Базовая плитка. Различаем тоном подложки, не рамками. Теней нет. ── */
.tile {
  position: relative;
  background: var(--surface-muted);
  border-radius: var(--r-card);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-width: 0;
}
.tile__body {
  padding: var(--s-md);
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--s-xs);
  min-height: 0;
}
.tile__foot { margin-top: auto; padding-top: var(--s-sm); }

/* ── Тон подложки: три ступени. Акцентная заливка — исключение,
      не более одной акцентной плитки на экран. ── */
/* Тона объявлены с двойной специфичностью намеренно: иначе `color: inherit`
   у оси «действие» перебивает их и заголовок пропадает на тёмной плитке.
   Оси должны быть независимы — комбинация link+ink обязана работать. */
.tile.tile--ink { background: var(--surface-ink); color: var(--text-inverse); }

/* Блок площадки: ряд выше обычного — под фотографию, а не под текст.
   Плитки те же, след тот же, меняется только высота ряда секции. */
#itpark .bento { grid-auto-rows: 360px; }
#itpark .tile__media { width: 46%; }
#itpark .tile__body  { width: 54%; justify-content: center; }
@media (max-width: 767px) {
  #itpark .bento { grid-auto-rows: auto; }
  #itpark .tile__media, #itpark .tile__body { width: 100%; }
}
.tile--ink .muted, .tile--ink .label { color: var(--text-on-ink); }
.tile.tile--accent { background: var(--accent); color: var(--text-inverse); }
/* Кнопка на акцентной заливке: белая плашка, текст фирменным синим. */
.btn--on-accent { background: var(--surface); color: var(--accent-deep); border-color: var(--surface); }
.btn--on-accent:hover { background: rgba(255, 255, 255, 0.88); }

/* Врезка — полоса, а не плитка в полный ряд: заголовок, строка и кнопка стоят
   в одну линию, как в образце Практикума, и не разъезжаются пустотой по 320px. */
#raspisanie .bento { grid-auto-rows: 200px; }
#raspisanie .tile__body { flex-direction: row; align-items: center; gap: var(--s-lg); }
#raspisanie .tile__body h2 { flex: 0 0 auto; max-width: 20ch; }
#raspisanie .tile__body p { flex: 1 1 auto; margin: 0; }
#raspisanie .tile__foot { margin: 0; padding: 0; flex: 0 0 auto; }
@media (max-width: 900px) {
  #raspisanie .bento { grid-auto-rows: auto; }
  #raspisanie .tile__body { flex-direction: column; align-items: flex-start; gap: var(--s-sm); }
  #raspisanie .tile__foot { padding-top: var(--s-sm); }
}
.tile--accent .muted,
.tile--accent .label { color: rgba(255, 255, 255, 0.86); }
.tile--wash { background: var(--accent-wash); }

/* ── Ось 2: слот картинки. Картинка прилегает к краю без отступа
      и обрезается по контейнеру — трёхслойного отступа Практикума нет. ── */
.tile__media { flex: none; overflow: hidden; }
.tile__media img { width: 100%; height: 100%; object-fit: cover; }
/* <picture> — обёртка без своей геометрии: высоту слота меряет .tile__media,
   а img height:100% считается от ближайшего блока-родителя. Без этих строк
   картинка в <picture> ложится в натуральную высоту и рвёт слот. Тот же приём
   стоит на сценах первого экрана (.heroD__scene picture). */
.tile__media picture { display: block; width: 100%; height: 100%; }

.tile--top    .tile__media { height: 55%; order: -1; }
.tile--bottom .tile__media { height: 45%; order: 2; }

.tile--side { flex-direction: row; }
/* Сторона картинки — параметр слота, а не новый слот. Чередование даёт шахматку. */
.tile--side-rev { flex-direction: row-reverse; }
.tile--side .tile__media { width: 40%; height: auto; align-self: stretch; }
.tile--side .tile__body  { width: 60%; justify-content: center; }
/* Единственное разрешённое изменение внутренней компоновки на брейкпоинте. */
@media (max-width: 767px) {
  .tile--side, .tile--side-rev { flex-direction: column; }
  .tile--side .tile__media { width: 100%; height: 200px; }
  .tile--side .tile__body  { width: 100%; }
}

/* corner — свободный объект уходит за обрез угла. Дорогой слот, точечно. */
/* Объект в углу меряется по ВЫСОТЕ плитки, а не по её ширине: иначе на низком
   следе (f 12×1, всего 320px) вертикальный объект раздувается по ширине и в кадр
   попадают одни ноги. Ширина — auto, пропорция объекта не трогается. */
.tile--corner .tile__media {
  position: absolute;
  right: 3%;
  bottom: -14%;
  height: 128%;
  width: auto;
  pointer-events: none;
}
.tile--corner .tile__media img { height: 100%; width: auto; object-fit: contain; }
/* Набросок в углу: спокойнее объекта — не вылезает за обрез, живёт в углу
   по диагонали от заголовка, как в референсе Тимура. */
.tile--corner-sm .tile__media { right: 5%; bottom: 4%; height: 42%; opacity: 0.9; }
.tile--corner-sm.tile--ink .tile__media { filter: invert(1) brightness(1.9); opacity: 0.7; }
/* Набросок мельче объекта и живёт под текстом, а не сбоку от него, поэтому
   колонку текста ужимать не надо — иначе строки рвутся в лапшу. */
.tile--corner-sm .tile__body { max-width: 100%; }
@media (max-width: 767px) { .tile--corner-sm .tile__media { height: 34%; } }
.tile--corner .tile__body { position: relative; z-index: 1; max-width: 62%; }
/* На узком экране объект уменьшается и уходит за правый край: он декоративный,
   и наезжать на текст ему нельзя. Ниже 480px прячем совсем — там места нет,
   а терять строку текста ради картинки не стоит. */
@media (max-width: 767px) {
  .tile--corner .tile__media { height: 66%; bottom: 0; right: -10%; }
  .tile--corner .tile__body { max-width: 70%; }
}
@media (max-width: 480px) {
  .tile--corner .tile__media { display: none; }
  .tile--corner .tile__body { max-width: 100%; }
}

/* full — картинка на весь контейнер, текст поверх. Затемнение обязательно:
   контраст считаем на фактическом фоне, а не на идеальном. */
.tile--full .tile__media {
  position: absolute;
  inset: 0;
  height: 100%;
}
.tile--full::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(20,22,24,0.74) 0%, rgba(20,22,24,0.36) 62%, rgba(20,22,24,0.52) 100%);
}
.tile--full .tile__body { position: relative; z-index: 1; color: var(--text-inverse); }
.tile--full .muted { color: rgba(255, 255, 255, 0.86); }

/* ── Ось 3: действие ── */
.tile--link { text-decoration: none; color: inherit; transition: transform 0.2s var(--ease); }
.tile--link:hover { transform: translateY(-2px); }
.tile--link .tile__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-sm);
}
.tile--link .tile__foot::after {
  content: "→";
  color: var(--accent);
  font-size: 1.25rem;
  line-height: 1;
  transition: transform 0.2s var(--ease);
}
.tile--link:hover .tile__foot::after { transform: translateX(4px); }
.tile--ink.tile--link .tile__foot::after,
.tile--full.tile--link .tile__foot::after { color: var(--highlight); }

.after-bento { margin-top: var(--s-md); }
/* ═══════════════════════════════════════════════════════════
   Меню. Полупрозрачное, при скролле — плашка со стеклом.
   Непрозрачность после первого экрана: контраст не должен
   зависеть от того, какая секция проезжает под плашкой.
   ═══════════════════════════════════════════════════════════ */

/* Меню — парящая стеклянная капсула, а не полоса во всю ширину.
   Геометрия снята с practicum.yandex.kz: .navbar — position:fixed,
   top:6px, ограниченная ширина, blur(10px), rgba(255,255,255,0.8),
   белая рамка 1px, свой радиус. Мы держим ту же форму, но берём
   sticky вместо fixed (поток документа не ломается) и добавляем
   три вещи, которых у референса нет, а у эппловского стекла есть:
   saturate подложки, блик по верхней кромке и мягкая тень. */

.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  padding: 10px 0;
  pointer-events: none;
}
.nav > .wrap { pointer-events: none; }
.nav__inner {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: var(--s-md);
  height: 56px;
  padding: 0 8px 0 20px;
  border-radius: var(--r-card);

  background: rgba(255, 255, 255, 0.70);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.72);

  /* Блик по верхней кромке + мягкая тень: стекло имеет толщину,
     плоская система это единственное место, где тень разрешена. */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.85),
    0 1px 1px rgba(16, 24, 32, 0.04),
    0 8px 24px rgba(16, 24, 32, 0.08);

  transition: background 0.28s var(--ease), box-shadow 0.28s var(--ease);
}
/* При скролле капсула чуть плотнее и тень глубже — она «оторвалась» от страницы. */
.nav[data-stuck="true"] .nav__inner {
  background: rgba(255, 255, 255, 0.82);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    0 1px 1px rgba(16, 24, 32, 0.05),
    0 12px 32px rgba(16, 24, 32, 0.13);
}
/* Без backdrop-filter стекло превращается в честную непрозрачную плашку. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .nav__inner { background: rgba(255, 255, 255, 0.97); }
}
.nav__logo { height: 26px; width: auto; flex: none; }
.nav__links { display: flex; gap: 2px; margin-left: auto; align-items: center; }
.nav__links a {
  text-decoration: none;
  white-space: nowrap;
  font-size: 1rem;
  color: var(--text);
  padding: 7px 12px;
  border-radius: var(--r-control);
  transition: color 0.15s var(--ease), background 0.15s var(--ease);
}
.nav__links a:hover { background: rgba(255, 255, 255, 0.92); }
@media (max-width: 1023px) { .nav__links { display: none; } }
@media (max-width: 767px) {
  .nav__inner { height: 60px; gap: var(--s-sm); }
  .nav__inner > a:last-child { margin-left: auto !important; }
}
@media (max-width: 400px) { .nav__inner > a:last-child { font-size: 0.875rem; padding: 8px 10px; } }

/* ═══════════════════════════════════════════════════════════
   Кнопки
   ═══════════════════════════════════════════════════════════ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-xs);
  padding: 12px 20px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  font: inherit;
  font-size: 1rem;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s var(--ease), color 0.15s var(--ease), border-color 0.15s var(--ease);
}
.btn--primary { background: var(--accent); color: var(--text-inverse); }
.btn--primary:hover { background: var(--accent-deep); }
.btn--ghost { background: transparent; color: var(--text); border-color: var(--border); }
.btn--ghost:hover { border-color: var(--text); }
.btn--on-ink { background: var(--surface); color: var(--text); }
.btn--on-ink:hover { background: var(--surface-muted); }
.btn--sm { padding: 8px 14px; font-size: 1rem; border-radius: var(--r-control); }

.cta-row { display: flex; flex-wrap: wrap; gap: var(--s-sm); max-width: 100%; }

/* На узком экране длинный ярлык кнопки переносится, а не распирает контейнер. */
@media (max-width: 767px) {
  .btn { white-space: normal; text-align: center; max-width: 100%; }
  .cta-row { width: 100%; }
  .cta-row .btn { flex: 1 1 100%; }
}

/* ═══════════════════════════════════════════════════════════
   Герой
   ═══════════════════════════════════════════════════════════ */

.hero { padding: var(--s-xl) 0 var(--s-lg); }
/* Полноэкранный первый экран своего отступа не имеет: он уезжает под стеклянную
   капсулу отрицательным margin, а padding от .hero возвращал бы его обратно —
   ровно это и оставляло белую полосу над кадром (правка 2 Тимура). */
.hero--full { padding: 0; }
@media (max-width: 767px) { .hero { padding: var(--s-lg) 0 var(--s-md); } }

.hero__head { display: grid; gap: var(--s-md); margin-bottom: var(--s-lg); }
.hero__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-xs) var(--s-md);
  align-items: center;
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--r-pill);
  background: var(--surface-muted);
  font-size: 0.875rem;
  letter-spacing: -0.14px;
}
.chip--accent { background: var(--accent-wash); color: var(--accent-deep); }

/* Одна авторская сцена: плитки первого экрана проявляются каскадом
   из уже видимого состояния. Дальше по странице движения нет. */
.hero .tile {
  animation: rise 0.62s var(--ease) both;
}
.hero .tile:nth-child(1) { animation-delay: 0.02s; }
.hero .tile:nth-child(2) { animation-delay: 0.09s; }
.hero .tile:nth-child(3) { animation-delay: 0.16s; }
.hero .tile:nth-child(4) { animation-delay: 0.23s; }

@keyframes rise {
  from { transform: translateY(14px); opacity: 0.55; filter: blur(3px); }
  to   { transform: none; opacity: 1; filter: none; }
}
@media (prefers-reduced-motion: reduce) {
  .hero .tile { animation: none; }
  * { transition-duration: 0.01ms !important; }
}

/* ═══════════════════════════════════════════════════════════
   Кейс: цифра «часы → минуты» — измеряемый результат, а не иконка
   ═══════════════════════════════════════════════════════════ */

.swap {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 1.25rem;
  letter-spacing: -0.4px;
}
.swap__from { color: var(--text-muted); text-decoration: line-through; text-decoration-thickness: 1px; }
.swap__to { color: var(--accent); font-weight: 500; }
.tile--ink .swap__to { color: var(--highlight); }
.arrow { color: var(--text-muted); }

/* ═══════════════════════════════════════════════════════════
   Сравнение форматов
   ═══════════════════════════════════════════════════════════ */

.spec { display: grid; gap: 10px; margin: 0; }
.spec > div {
  display: grid;
  grid-template-columns: 116px 1fr;
  gap: var(--s-sm);
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}
.tile--ink .spec > div { border-bottom-color: var(--border-on-ink); }
.spec dt { color: var(--text-muted); font-size: 1rem; }
.tile--ink .spec dt { color: var(--text-on-ink); }
.spec dd { margin: 0; }
@media (max-width: 480px) { .spec > div { grid-template-columns: 1fr; gap: 2px; } }

.price {
  font-size: 1.75rem;
  letter-spacing: -0.4px;
  font-variant-numeric: tabular-nums;
}

/* ═══════════════════════════════════════════════════════════
   FAQ
   ═══════════════════════════════════════════════════════════ */

/* Границы первого поколения (простой список) сняты: карточки во втором
   поколении рисуют собственную рамку со скруглением, а сквозная линия
   торчала по бокам первой карточки. */
.faq { display: grid; gap: 0; }
.faq summary {
  cursor: pointer;
  padding: var(--s-md) 0;
  font-size: 1.125rem;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s-md);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "";
  flex: none;
  width: 11px; height: 11px;
  border-right: 1.5px solid var(--text-muted);
  border-bottom: 1.5px solid var(--text-muted);
  transform: rotate(45deg) translate(-3px, -3px);
  transition: transform 0.2s var(--ease);
}
.faq details[open] summary::after { transform: rotate(-135deg) translate(-3px, -3px); }
.faq p { padding: 0 0 var(--s-md); color: var(--text-muted); }

/* ═══════════════════════════════════════════════════════════
   Финал и подвал
   ═══════════════════════════════════════════════════════════ */

.closer {
  margin: var(--s-xl) 0 0;
  background: var(--surface-ink);
  color: var(--text-inverse);
  border-radius: var(--r-card);
  padding: var(--s-xl) var(--s-lg);
  display: grid;
  gap: var(--s-md);
  justify-items: start;
}
@media (max-width: 767px) { .closer { padding: var(--s-lg) var(--s-md); } }
.closer .muted { color: var(--text-on-ink); }
.closer > * { max-width: 100%; }

.foot {
  padding: var(--s-xl) 0 var(--s-lg);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-lg);
}
@media (max-width: 767px) { .foot { grid-template-columns: 1fr; gap: var(--s-md); } }
.foot h4 { font-size: 0.875rem; color: var(--text-muted); margin-bottom: var(--s-xs); }
.foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.foot a { text-decoration: none; }
.foot a:hover { color: var(--accent-deep); }
.foot__legal {
  border-top: 1px solid var(--border);
  padding: var(--s-md) 0 var(--s-xl);
  color: var(--text-muted);
  font-size: 0.875rem;
}

/* ═══════════════════════════════════════════════════════════
   Секция и висящий заголовок. Заголовок стоит в воздухе,
   вне контейнеров — скролл по заголовкам читается как текст.
   ═══════════════════════════════════════════════════════════ */

.block { padding-top: var(--s-xl); }
@media (max-width: 767px) { .block { padding-top: var(--s-lg); } }

.block__head {
  display: grid;
  gap: var(--s-sm);
  margin-bottom: var(--s-lg);
  max-width: 900px;
}

.lead { font-size: 1.125rem; line-height: 1.3; margin: 0; max-width: 62ch; }
p { margin: 0; }
.muted { color: var(--text-muted); }

/* ═══════════════════════════════════════════════════════════
   Форма. Не плитка: она выше любого следа из закрытого списка,
   а новый след по месту канон запрещает.
   ═══════════════════════════════════════════════════════════ */

.form {
  display: grid;
  grid-template-columns: 1fr 1.15fr;
  gap: var(--s-lg);
  align-items: start;
  justify-items: stretch;
}
@media (max-width: 900px) { .form { grid-template-columns: 1fr; } }

.form__text { display: grid; gap: var(--s-md); }

.form__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-sm);
}
@media (max-width: 520px) { .form__grid { grid-template-columns: 1fr; } }

.field {
  font: inherit;
  font-size: 1rem;
  color: var(--text-inverse);
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid var(--border-on-ink);
  border-radius: var(--r-control);
  padding: 12px 14px;
  width: 100%;
  resize: vertical;
}
.field::placeholder { color: var(--text-on-ink); }
.field:focus { outline: 2px solid var(--accent); outline-offset: 2px; }
.field--wide { grid-column: 1 / -1; }

.form__submit {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-md);
}
.consent {
  display: flex;
  gap: var(--s-xs);
  align-items: flex-start;
  font-size: 0.875rem;
  color: var(--text-on-ink);
  max-width: 34ch;
  cursor: pointer;
}
.consent input { margin-top: 3px; flex: none; }

/* Пары гарнитур. Правка 7: Manrope или Inter в тексте, антиква в заголовках.
   TT Firs Neue оставлена точкой отсчёта — это то, что стоит на боевом. */
html[data-type="firs"] {
  --font: 'TT Firs Neue', Helvetica, Arial, sans-serif;
  --font-display: var(--font); --display-tracking: -1px;
}
html[data-type="manrope"] {
  --font: 'Manrope', Helvetica, Arial, sans-serif;
  --font-display: var(--font); --display-tracking: -1.2px;
}
html[data-type="inter"] {
  --font: 'Inter', Helvetica, Arial, sans-serif;
  --font-display: var(--font); --display-tracking: -1.2px;
}
html[data-type="manrope-alethia"] {
  --font: 'Manrope', Helvetica, Arial, sans-serif;
  --font-display: 'Alethia Pro', Georgia, serif; --display-tracking: -0.5px;
}
html[data-type="manrope-felidae"] {
  --font: 'Manrope', Helvetica, Arial, sans-serif;
  --font-display: 'Felidae', Georgia, serif; --display-tracking: 0;
}
html[data-type="inter-alethia"] {
  --font: 'Inter', Helvetica, Arial, sans-serif;
  --font-display: 'Alethia Pro', Georgia, serif; --display-tracking: -0.5px;
}
html[data-type="inter-felidae"] {
  --font: 'Inter', Helvetica, Arial, sans-serif;
  --font-display: 'Felidae', Georgia, serif; --display-tracking: 0;
}
/* Антиква в крупном кегле держит строку плотнее — компенсируем интерлиньяж. */
html[data-type$="-felidae"] .display { line-height: 1.0; }
html[data-type$="-alethia"] .display { line-height: 1.04; }

/* ═══════════════════════════════════════════════════════════
   Меню. Правки Тимура 1-5.
   ═══════════════════════════════════════════════════════════ */

/* Правка 1: элементы меню стоят на границах вёрстки. Капсула шире контента
   ровно на свой внутренний отступ — тогда логотип слева и кнопка справа
   попадают на ту же вертикаль, что заголовок и плитки под ними. */
/* dual-ok: то же меню — правки Тимура 1-5 надстраивают базовое правило секции «Меню» */
.nav__inner { position: relative; padding: 0 var(--nav-pad); margin: 0 calc(-1 * var(--nav-pad)); }
:root { --nav-pad: 14px; }

/* Правка 3: навигация по центру экрана, а не в остатке между лого и кнопками. */
/* dual-ok: то же меню — по правкам Тимура 1-5 ссылки переезжают в центр */
.nav__links { position: absolute; left: 50%; transform: translateX(-50%); margin-left: 0; }

/* Правка 4: «Компаниям» — отдельный продукт, отбит воздухом от основного списка. */
.nav__sep { display: block; width: var(--s-lg); flex: none; }

/* Правка 4: «Контакты» переехали из ссылок в кнопки — справа их теперь две. */
.nav__cta { display: flex; align-items: center; gap: var(--s-xs); margin-left: auto; }
@media (max-width: 767px) { .nav__cta .btn--ghost { display: none; } }

/* ═══════════════════════════════════════════════════════════
   Первый экран — четыре композиции (правка 8).
   Показывается одна, выбор живёт в URL: ?hero=a|b|c|d
   ═══════════════════════════════════════════════════════════ */

/* Состояние живёт на <html>, поэтому прячем именно секции: голый [data-hero]
   поймал бы и сам корень документа — страница исчезла бы целиком. */
section[data-hero] { display: none; }
html[data-hero="a"] section[data-hero="a"],
html[data-hero="b"] section[data-hero="b"],
html[data-hero="c"] section[data-hero="c"],
html[data-hero="d"] section[data-hero="d"] { display: block; }

.hero__lead { font-size: 1.125rem; color: var(--text-muted); }

/* ── A. Два самостоятельных контейнера: текст и картинка ── */
.heroA { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gutter); align-items: stretch; }
.heroA__text {
  background: var(--surface-muted); border-radius: var(--r-card);
  padding: var(--s-xl) var(--s-lg); display: flex; flex-direction: column;
  justify-content: center; gap: var(--s-md); min-height: 60vh;
}
.heroA__media { border-radius: var(--r-card); overflow: hidden; min-height: 60vh; }
.heroA__media img { width: 100%; height: 100%; object-fit: cover; }
@media (max-width: 767px) {
  .heroA { grid-template-columns: 1fr; }
  .heroA__text { padding: var(--s-lg) var(--s-md); min-height: 0; }
  .heroA__media { min-height: 320px; }
}

/* ── B. Центральная ось: заголовок, лид, кнопки и образ на одной вертикали ── */
.heroB { text-align: center; display: grid; justify-items: center; gap: var(--s-md); }
.heroB p { margin-inline: auto; }
.heroB .cta-row { justify-content: center; }
.heroB__media {
  margin-top: var(--s-md); width: min(560px, 100%); border-radius: var(--r-card);
  overflow: hidden; max-height: 46vh;
}
.heroB__media img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 46%; }

/* ── C. Красивое фоновое изображение внутри контейнера ── */
.heroC { position: relative; border-radius: var(--r-card); overflow: hidden; min-height: 72vh; display: flex; }
.heroC picture, .heroC img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.heroC::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(21,27,40,0.10) 0%, rgba(21,27,40,0.30) 45%, rgba(21,27,40,0.86) 100%);
}
.heroC__body {
  position: relative; z-index: 1; margin-top: auto; padding: var(--s-lg);
  display: grid; gap: var(--s-md); color: var(--text-inverse); max-width: 46rem;
}
.heroC__body .hero__lead { color: rgba(255,255,255,0.88); }
@media (max-width: 767px) { .heroC { min-height: 78vh; } .heroC__body { padding: var(--s-md); } }

/* ── D. Атмосферная сцена на весь экран: композиция в центре, воздух по бокам ──
   Фон-градиент замерен по левой кромке самого кадра, поэтому шва между
   картинкой и «воздухом» не видно. */
.heroD {
  position: relative; min-height: 100svh; display: flex; flex-direction: column;
  background: linear-gradient(180deg,
    #2D4347 0%, #3B4D50 12%, #4A5A5B 26%, #5A6461 40%, #747368 52%,
    #948069 62%, #B98459 70%, #BF885B 78%, #50463C 86%, #151C1E 100%);
  color: var(--text-inverse); overflow: hidden;
}
/* Сцена уходит под стеклянную капсулу: первый экран занимает экран целиком,
   меню лежит поверх кадра, как на референсе AETHERA. */
html[data-hero="d"] main > section[data-hero="d"] { margin-top: calc(-56px - 20px); }
.heroD__scene { position: absolute; inset: 0; display: flex; justify-content: center; }
/* Сцена выбирается на странице; в бою остаётся одна и лишние <picture> удаляются.
   Активной обёртке нужны свои размеры: <picture> — flex-элемент внутри
   .heroD__scene, и без width/height он сжимается по содержимому. Тогда
   `width: 100%` у картинки считается от самой картинки, и при любом
   соотношении окна, кроме ровно 16:9, по бокам остаются белые поля. */
.heroD__scene picture { display: none; }
.heroD__scene picture[data-scene] { width: 100%; height: 100%; }
/* Портретный кадр уже не центрируется flex-контейнером — обёртка теперь во всю
   ширину, поэтому центрируется сама картинка. */
.heroD__scene img { margin-inline: auto; }
html[data-scene="tower"] .heroD__scene picture[data-scene="tower"],
html[data-scene="d1"]    .heroD__scene picture[data-scene="d1"],
html[data-scene="d2"]    .heroD__scene picture[data-scene="d2"],
html[data-scene="d3"]    .heroD__scene picture[data-scene="d3"],
html[data-scene="wide"]  .heroD__scene picture[data-scene="wide"] { display: block; }
/* Кадры под 16:9 закрывают экран целиком: ни маски, ни размытия краёв.
   Маска остаётся только у портретного кадра «маяка» — он уже с воздухом. */
html[data-scene="d1"] .heroD, html[data-scene="d2"] .heroD,
html[data-scene="d3"] .heroD, html[data-scene="wide"] .heroD { background: #2b3a3f; }
html[data-scene="d1"] .heroD__scene img,
html[data-scene="d2"] .heroD__scene img,
html[data-scene="d3"] .heroD__scene img,
html[data-scene="wide"] .heroD__scene img {
  width: 100%; height: 100%; object-fit: cover;
  -webkit-mask-image: none; mask-image: none;
}
/* Купол башни — смысловой центр кадра, и заголовок не должен его накрывать.
   На полноэкранных кадрах текст поднимается в верхнюю треть: блок кончается
   там, где начинается шар. */
html[data-scene="d1"] .heroD__body, html[data-scene="d2"] .heroD__body,
html[data-scene="d3"] .heroD__body, html[data-scene="wide"] .heroD__body {
  padding-top: 5vh; max-width: 54rem;
}
@media (max-width: 767px) {
  html[data-scene="d1"] .heroD__body, html[data-scene="d2"] .heroD__body,
  html[data-scene="d3"] .heroD__body, html[data-scene="wide"] .heroD__body { padding-top: 12vh; }
}
/* Вуаль сверху: текст первого экрана читается поверх светлой части неба. */
.heroD::before {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, rgba(18,26,38,0.52) 0%, rgba(18,26,38,0.18) 34%, rgba(18,26,38,0) 56%);
}
.heroD__scene img {
  height: 100%; width: auto; max-width: none; object-fit: cover;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 16%, #000 84%, transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 16%, #000 84%, transparent 100%);
}
.heroD__body {
  position: relative; z-index: 2; padding-top: 18vh; display: grid; gap: var(--s-md);
  justify-items: center; text-align: center; max-width: 44rem; margin-inline: auto;
  text-shadow: 0 1px 24px rgba(10,16,26,0.45);
}
.heroD__body .hero__lead { color: rgba(255,255,255,0.9); }
.heroD .cta-row { justify-content: center; }
@media (max-width: 767px) {
  .heroD__scene img { width: 100%; height: 100%; -webkit-mask-image: none; mask-image: none; }
  .heroD__body { padding-top: 14vh; }
}

/* ═══════════════════════════════════════════════════════════
   Служебная панель сравнения. В бою удаляется одним блоком.
   ═══════════════════════════════════════════════════════════ */
.devbar {
  position: fixed; z-index: 90; left: 50%; bottom: 16px; transform: translateX(-50%);
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  padding: 8px 10px; border-radius: var(--r-card); max-width: calc(100vw - 24px);
  background: rgba(255,255,255,0.82); backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(255,255,255,0.72);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.85), 0 12px 32px rgba(16,24,32,0.16);
  font-size: 0.8125rem; color: var(--text);
}
.devbar b { font-weight: 500; padding: 0 4px 0 6px; color: var(--text-muted); }
.devbar button {
  font: inherit; cursor: pointer; padding: 6px 10px; border-radius: var(--r-control);
  border: 1px solid var(--border); background: transparent; color: var(--text);
}
.devbar button:hover { background: rgba(255,255,255,0.9); }
.devbar button[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #fff; }
.devbar__x { margin-left: 4px; opacity: 0.6; }
.devbar__toggle { display: none; }
@media (max-width: 767px) {
  .devbar { max-width: none; left: auto; right: 12px; transform: none; }
  .devbar__toggle { display: block; }
  .devbar:not([data-open="true"]) > *:not(.devbar__toggle) { display: none; }
  .devbar[data-open="true"] { left: 12px; max-height: 70vh; overflow: auto; }
}
@media print { .devbar { display: none; } }



/* ═══════════════════════════════════════════════════════════
   Компоненты подстраниц (v13)
   ═══════════════════════════════════════════════════════════ */

/* Первый экран внутренней страницы: не на весь экран — половина, чтобы
   содержимое начиналось сразу. Кадр тот же, что и на главной. */
.subhero {
  position: relative; overflow: hidden; color: var(--text-inverse);
  background: var(--surface-ink);
  margin-top: calc(-56px - 20px); padding: calc(56px + 20px + var(--s-xl)) 0 var(--s-xl);
}
.subhero__scene { position: absolute; inset: 0; }
.subhero__scene img { width: 100%; height: 100%; object-fit: cover; }
.subhero::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(16,22,34,0.78) 0%, rgba(16,22,34,0.55) 55%, rgba(16,22,34,0.72) 100%);
}
.subhero__body { position: relative; z-index: 1; display: grid; gap: var(--s-md); max-width: 46rem; }
.subhero .lead { color: rgba(255,255,255,0.9); }
.subhero .eyebrow { color: rgba(255,255,255,0.72); }
.subhero .cta-row { margin-top: var(--s-xs); }
.subhero__facts {
  position: relative; z-index: 1; display: flex; flex-wrap: wrap; gap: var(--s-md);
  margin-top: var(--s-lg); color: rgba(255,255,255,0.86); font-size: 0.9375rem;
}
.subhero__facts b { font-weight: 500; color: var(--text-inverse); }

/* ── Календарь расписания ──
   Раскладка с созвона: на десктопе слева описание выбранной даты, справа сам
   календарь — та же пара контейнеров, что и в первом экране A. На телефоне
   календарь уезжает наверх, описание и кнопка — под ним. */
/* Колонки равные, а не 5fr/7fr: календарь был на 196 px шире карточки события
   и на 192 px выше — пара читалась как «таблица и приписка». Растяжка (stretch)
   доводит карточку до высоты календаря, поэтому это две ровные плиты. */
.cal-layout { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gutter); align-items: stretch; }
/* min-width: auto у грид-элементов раздувает колонку по самому длинному слову —
   на телефоне из-за этого страница уезжала вбок. */
.cal-layout > * { min-width: 0; }
.cal-panel .title { overflow-wrap: anywhere; }
@media (max-width: 900px) { .cal-layout { grid-template-columns: 1fr; } .cal-layout__panel { order: 2; } }

.cal { background: var(--surface-muted); border-radius: var(--r-card); padding: var(--s-md); }
.cal__head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-sm); margin-bottom: var(--s-md); }
.cal__title { font-size: 1.125rem; text-transform: capitalize; }
.cal__nav { display: flex; gap: 6px; }
.cal__nav button {
  font: inherit; cursor: pointer; width: 36px; height: 36px; line-height: 1;
  border-radius: var(--r-control); border: 1px solid var(--border);
  background: var(--surface-raised); color: var(--text);
}
.cal__nav button:hover { border-color: var(--accent); color: var(--accent); }
.cal__nav button[disabled] { opacity: 0.4; cursor: default; }
.cal__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.cal__dow { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); text-align: center; padding-bottom: 4px; }
.cal__cell {
  font: inherit; text-align: left; cursor: default; position: relative;
  min-height: 64px; padding: 8px 5px; border-radius: var(--r-control);
  border: 1px solid transparent; background: var(--surface-raised); color: var(--text-muted);
}
.cal__cell--out { background: transparent; color: rgba(30,30,30,0.28); }
.cal__cell--past { opacity: 0.5; }
.cal__num { font-size: 0.9375rem; }
.cal__cell--event { cursor: pointer; color: var(--text); border-color: var(--border); }
.cal__cell--event:hover { border-color: var(--accent); }
.cal__cell--event .cal__num { font-weight: 500; }
/* Клетка сузилась с 86 до 72 px: кегль на пункт меньше и без разрядки, иначе
   подпись вылезает на соседний день — «Компаниям» не помещалась и при 86 px. */
.cal__tag { display: block; margin-top: 4px; font-size: 0.625rem; line-height: 1.2; text-transform: uppercase; letter-spacing: 0; }
.cal__cell[aria-pressed="true"] { background: var(--surface-ink); border-color: var(--surface-ink); color: var(--text-inverse); }
.cal__cell[aria-pressed="true"] .cal__tag { color: rgba(255,255,255,0.8); }
/* Тип события — цветом кромки, а не заливкой: заливка спорит с выбранным днём. */
/* ── Цвета типов событий ──
   Отдельный набор, а не служебные токены палитры. Раньше тип брал цвет прямо
   у --accent / --accent-deep / --surface-ink / --text-muted, и «лекция» с
   «буткемпом» разошлись всего на ΔE76 = 11,3 — в квадратике легенды 10×10 это
   один и тот же синий. Поменять --accent-deep было нельзя: на нём заливка
   кнопок. Отсюда свои токены — один источник и для кромки клетки, и для
   легенды, и место, где различимость можно проверить гейтом.

   Порог: попарно ΔE76 ≥ 25 и контраст к белой клетке ≥ 3:1 (норма для
   нетекстовых элементов). Текстом эти цвета не печатаются — см. ниже. */
:root {
  --ev-lecture:  #0096cf;   /* = --accent */
  --ev-practice: #17205a;   /* = --surface-ink */
  --ev-bootcamp: #127a63;   /* приглушённый teal: мин. ΔE 34,2, на белом 5,26:1 */
  --ev-demoday:  #7a5c00;   /* = --accent-warm */
  --ev-corp:     #666b71;   /* = --text-muted */
  --ev-fest:     #9c2a6b;   /* фестивальная маджента: 7,1:1 на белом,
                              ближайший сосед по цвету — кобальт практики, ΔE 47,9 */
}

.cal__cell--lecture   { --ev: var(--ev-lecture); }
.cal__cell--practice  { --ev: var(--ev-practice); }
.cal__cell--bootcamp  { --ev: var(--ev-bootcamp); }
.cal__cell--demoday   { --ev: var(--ev-demoday); }
.cal__cell--corp      { --ev: var(--ev-corp); }
.cal__cell--fest      { --ev: var(--ev-fest); }
.cal__cell--event     { box-shadow: inset 3px 0 0 var(--ev); }

/* Подпись типа держится, пока её держит клетка; дальше — точка, расшифровка
   остаётся в легенде. Порог считается по ширине САМОГО календаря (@container),
   а не окна: узкая клетка получается и на телефоне, и на ноутбуке 1100, где
   те же две колонки. Клетке под слово нужно ≥64 px, это календарь от 540 px. */
.cal__grid > * { min-width: 0; }
.cal { container-type: inline-size; }
@container (max-width: 540px) {
  .cal__cell { text-align: center; }
  .cal__tag { display: none; }
  .cal__cell--event::after {
    content: ""; display: block; width: 7px; height: 7px; border-radius: 50%;
    margin: 4px auto 0; background: var(--ev);
  }
  /* На выбранном дне подложка тёмная: точка типа на ней тонет (у «практики»
     цвет почти совпадает с заливкой). Выбранный день и так подписан в панели. */
  .cal__cell[aria-pressed="true"]::after { background: var(--text-inverse); }
  .cal__cell--event { box-shadow: none; }
  .cal__cell[aria-pressed="true"] { color: var(--text-inverse); }
}
@media (max-width: 600px) {
  .cal { padding: var(--s-sm); }
  .cal__cell { min-height: 46px; padding: 6px 4px; }
}

.cal__legend { display: flex; flex-wrap: wrap; gap: var(--s-sm); margin-top: var(--s-md); font-size: 0.8125rem; color: var(--text-muted); }
.cal__legend i { display: inline-block; width: 12px; height: 12px; border-radius: 3px; margin-right: 6px; vertical-align: -2px; }
.cal__legend .lecture { background: var(--ev-lecture); }
.cal__legend .practice { background: var(--ev-practice); }
.cal__legend .bootcamp { background: var(--ev-bootcamp); }
.cal__legend .demoday { background: var(--ev-demoday); }
.cal__legend .corp { background: var(--ev-corp); }
.cal__legend .fest { background: var(--ev-fest); }

/* Панель выбранной даты — обычная плитка, только собранная скриптом. */
.cal-panel { background: var(--surface-muted); border-radius: var(--r-card); padding: var(--s-lg); display: grid; gap: var(--s-sm); align-content: start; }
.cal-panel__date { font-size: 0.875rem; color: var(--accent); text-transform: uppercase; letter-spacing: 0.04em; }
.cal-panel__meta { display: grid; gap: 4px; color: var(--text-muted); font-size: 0.9375rem; }
.cal-panel__status { justify-self: start; padding: 2px 10px; border-radius: var(--r-pill); font-size: 0.8125rem; background: var(--accent-wash); color: var(--accent-deep); }
.cal-panel__status--waitlist { background: #fdf3d4; color: var(--accent-warm); }
.cal-panel__status--done { background: rgba(30,30,30,0.06); color: var(--text-muted); }

/* Раздел, на котором вы сейчас: в одностраничнике этого не требовалось. */
.nav__links a[aria-current="page"] { color: var(--accent); }

/* Кнопка-призрак на тёмном: в v10 она задавалась инлайном прямо в разметке
   первого экрана — на подстраницах нужен нормальный класс. */
.btn--on-dark { color: var(--text-inverse); border-color: rgba(255,255,255,0.5); }
.btn--on-dark:hover { background: rgba(255,255,255,0.14); border-color: rgba(255,255,255,0.7); }

/* Надзаголовок блока: «01 / Почему сейчас» — нумерация с боевого сайта,
   она держит длинную страницу и помогает договариваться о правках. */
.eyebrow {
  display: block; font-size: 0.8125rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-muted); margin-bottom: var(--s-xs);
}
.eyebrow b { font-weight: 500; color: var(--accent); }

/* Шаги: та же плитка, номер живёт в надзаголовке, а не в отдельном круге. */
.step__num { font-size: 2.5rem; line-height: 1; color: var(--accent); font-weight: 300; }

/* Тариф: плитка с ценой. Цена — не заголовок, поэтому набирается отдельно. */
/* dual-ok: то же поле цены, что в «Сравнении форматов» — свойства дополняют друг друга, font-size совпадает */
.price { font-size: 1.75rem; line-height: 1.1; margin: var(--s-xs) 0 0; }
.price small { display: block; font-size: 0.875rem; color: var(--text-muted); margin-top: 4px; }
.tile--ink .price small { color: var(--text-on-ink); }
.tile__list { margin: var(--s-sm) 0 0; padding: 0; list-style: none; display: grid; gap: 6px; }
.tile__list li { position: relative; padding-left: 20px; color: var(--text-muted); font-size: 0.9375rem; }
.tile__list li::before {
  content: ""; position: absolute; left: 0; top: 8px; width: 10px; height: 2px;
  background: var(--accent);
}
.tile--ink .tile__list li { color: var(--text-on-ink); }
.tile--ink .tile__list li::before { background: var(--highlight); }
.tile__badge {
  display: inline-block; justify-self: start; align-self: flex-start;
  padding: 2px 10px; border-radius: var(--r-pill);
  background: var(--accent); color: var(--text-inverse); font-size: 0.8125rem; margin-bottom: var(--s-xs);
}

/* Частые вопросы: раскрывающийся список, без скриптов. */
/* dual-ok: второе поколение FAQ поверх первого из секции «FAQ»; нынешний вид собран из обоих блоков — разбор отдельной задачей */
.faq { display: grid; gap: var(--s-xs); }
.faq details {
  border: 1px solid var(--border); border-radius: var(--r-card);
  background: var(--surface-muted); padding: var(--s-md) var(--s-md);
}
.faq details[open] { background: var(--surface-raised); box-shadow: var(--shadow-card, 0 8px 24px rgba(16,24,32,0.06)); }
.faq summary {
  cursor: pointer; list-style: none; font-size: 1.0625rem; display: flex; gap: var(--s-sm);
  align-items: baseline; justify-content: space-between;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--accent); font-size: 1.25rem; line-height: 1; }
.faq details[open] summary::after { content: "−"; }
.faq p { margin-top: var(--s-sm); color: var(--text-muted); }

/* Строка сравнения тарифов практики: три колонки, на телефоне — карточки. */
.compare { width: 100%; border-collapse: collapse; font-size: 0.9375rem; }
.compare th, .compare td { text-align: left; padding: var(--s-sm) var(--s-md); border-bottom: 1px solid var(--border); vertical-align: top; }
.compare thead th { font-weight: 500; font-size: 1.0625rem; }
.compare tbody th { font-weight: 400; color: var(--text-muted); }
.compare td.yes { color: var(--accent); }
.compare tr:last-child td, .compare tr:last-child th { border-bottom: 0; }
.compare__wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--r-card); }

/* ── Первый экран «Лекций» и «Контактов» в двух компоновках ──
   Правка Тимура 20.08: одна компоновка — сплит, где сначала идёт картинка и
   только потом карточка с текстом; вторая — тот же кадр во всю ширину, а текст
   прижат к левому краю вёрстки, чтобы не спорить с картинкой. Разметка одна на
   обе: компоновка выбирается через data-lay на <html>, поэтому кадр и текст
   не дублируются в HTML и не расходятся при правке. */
.lekhero { position: relative; overflow: hidden; }
.lekhero__pic img { display: block; width: 100%; height: 100%; object-fit: cover; }
.lekhero__body { display: grid; gap: var(--s-md); }
.lekhero__facts {
  display: flex; flex-wrap: wrap; gap: var(--s-md);
  margin-top: var(--s-sm); font-size: 0.9375rem;
}
.lekhero__facts b { font-weight: 500; }

/* Сплит: две колонки, картинка первой. */
html[data-lay="split"] .lekhero { padding: var(--s-xl) 0; }
html[data-lay="split"] .lekhero__grid {
  display: grid; grid-template-columns: 6fr 6fr; gap: var(--gutter); align-items: stretch;
}
html[data-lay="split"] .lekhero__grid > * { min-width: 0; }
html[data-lay="split"] .lekhero__pic {
  border-radius: var(--r-card); overflow: hidden; min-height: 26rem;
}
html[data-lay="split"] .lekhero__body {
  background: var(--surface-muted); border-radius: var(--r-card);
  padding: var(--s-xl) var(--s-lg); align-content: center;
}
html[data-lay="split"] .lekhero__facts { color: var(--text-muted); }
html[data-lay="split"] .lekhero__facts b { color: var(--text); }
html[data-lay="split"] .lekhero .btn--on-dark { color: var(--text); border-color: var(--border); }
html[data-lay="split"] .lekhero .btn--on-dark:hover { border-color: var(--accent); color: var(--accent); }

/* Полноэкранный кадр: подложка тёмная, текст по левому краю вёрстки. */
html[data-lay="full"] .lekhero {
  color: var(--text-inverse); background: var(--surface-ink);
  margin-top: calc(-56px - 20px);
  padding: calc(56px + 20px + var(--s-xl)) 0 var(--s-xl);
}
html[data-lay="full"] .lekhero .lekhero__pic { position: absolute; inset: 0; }
html[data-lay="full"] .lekhero::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(16,22,34,0.86) 0%, rgba(16,22,34,0.72) 42%, rgba(16,22,34,0.38) 100%);
}
html[data-lay="full"] .lekhero .lekhero__body { position: relative; z-index: 1; }
html[data-lay="full"] .lekhero .lekhero__body { max-width: 44rem; }
html[data-lay="full"] .lekhero .lead { color: rgba(255,255,255,0.9); }
html[data-lay="full"] .lekhero .eyebrow { color: rgba(255,255,255,0.72); }
html[data-lay="full"] .lekhero .lekhero__facts { color: rgba(255,255,255,0.86); }
html[data-lay="full"] .lekhero .lekhero__facts b { color: var(--text-inverse); }

@media (max-width: 900px) {
  html[data-lay="split"] .lekhero__grid { grid-template-columns: 1fr; }
  html[data-lay="split"] .lekhero__pic { min-height: 16rem; }
  html[data-lay="full"] .lekhero::after {
    background: linear-gradient(180deg, rgba(16,22,34,0.82) 0%, rgba(16,22,34,0.6) 55%, rgba(16,22,34,0.78) 100%);
  }
}

/* Ряд технологий: не логотипы, а имена — логотипы чужих брендов на сайт не
   кладём без разрешения правообладателей, а список меняется каждый месяц. */
/* Плашка-вставка сразу под первым экраном: пара коротких обещаний со значками.
   Образец с доски (x83267) — светлая полоса во всю ширину контейнера. */
.stripe {
  display: flex; flex-wrap: wrap; gap: var(--s-lg);
  background: var(--surface-muted); border-radius: var(--r-card);
  padding: var(--s-md) var(--s-lg); margin-top: var(--s-lg);
}
.stripe__item { display: flex; align-items: center; gap: var(--s-sm); font-size: 1rem; }
.stripe__icon {
  flex: none; width: 38px; height: 38px; border-radius: 12px;
  display: grid; place-items: center; background: var(--surface-raised); color: var(--accent);
}
.stripe__icon svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.6; }

/* Строка «дата · место · условия» у блока конкретной лекции. */
.eventline { color: var(--text-muted); font-size: 1.0625rem; margin-top: var(--s-xs); }
.eventline b { color: var(--text); font-weight: 500; }

.techs { display: flex; flex-wrap: wrap; gap: var(--s-sm); margin-bottom: var(--s-md); }
.techs .chip { font-size: 1rem; }

/* Карта на «Контактах»: живой виджет Яндекса во всю ширину контейнера. */
.mapframe {
  border-radius: var(--r-card); overflow: hidden; border: 1px solid var(--border);
  background: var(--surface-muted);
}
.mapframe iframe { display: block; width: 100%; height: 440px; border: 0; }
@media (max-width: 767px) { .mapframe iframe { height: 320px; } }

/* Карточка контактов: строки «подпись → значение» крупным набором. */
.contacts { display: grid; gap: var(--s-md); }
.contacts__row { display: grid; gap: 2px; }
.contacts__row .label { color: var(--text-muted); font-size: 0.8125rem; text-transform: uppercase; letter-spacing: 0.04em; }
.contacts__row a { font-size: 1.25rem; }

@media (max-width: 767px) {
  .compare { min-width: 640px; }
}




/* ── Градиент акцентной плитки ──
   Единственное, что взято из разбора Mark OS (21.08): мешь с их разворота,
   пересчитанный в нашу гамму. Роли цветов у нас свои — синий по-прежнему
   означает «сюда можно нажать», — но плоская заливка на широкой плитке
   выглядела дёшево, а мешь даёт ей глубину и не спорит с кнопками.
   Светлая лазурь в правом верхнем углу, насыщенная бирюза по левой кромке,
   бледная засветка в середине и затемнённый фирменный внизу слева. */
.tile.tile--accent {
  background:
    radial-gradient(70% 120% at 98% -10%, rgba(150, 222, 245, 0.85) 0%, rgba(150, 222, 245, 0) 58%),
    radial-gradient(58% 130% at 4% 14%, #1592c4 0%, rgba(21, 146, 196, 0) 66%),
    radial-gradient(64% 150% at 8% 108%, #062f47 0%, rgba(6, 47, 71, 0) 72%),
    linear-gradient(196deg, #0d8fc4 0%, #0a76a4 48%, #064a68 100%);
  color: var(--text-inverse);
}

/* Первый экран заходит под меню (правка 2), поэтому композиция сдвигается
   на высоту капсулы: 56 px плюс 10 px отступа сверху и снизу. */
html[data-scene="wide"] .heroD__body { padding-top: calc(76px + 4vh); }
@media (max-width: 767px) {
  html[data-scene="wide"] .heroD__body { padding-top: calc(76px + 8vh); }
  /* На телефоне заголовок и лид занимают две трети экрана и неминуемо ложатся
     на башню: вуаль сверху становится плотнее и тянется ниже. Замер белого
     текста на самом светлом месте кадра — 7,1:1. */
  .heroD::before {
    background: linear-gradient(180deg, rgba(18, 26, 38, 0.74) 0%, rgba(18, 26, 38, 0.52) 46%,
      rgba(18, 26, 38, 0.16) 72%, rgba(18, 26, 38, 0) 100%);
  }
}

/* ── Корпоративный баннер: текст и кнопка одним блоком ──
   Правка Тимура 22.08 «текст с кнопкой объединить — сейчас они разлетелись».
   `.tile__foot` по умолчанию прижат к нижней кромке (`margin-top: auto`), и на
   плитке следа f это разносило кнопку и текст на пол-экрана. Здесь блок
   собирается по вертикальному центру, кнопка идёт сразу за абзацем —
   как на референсе Практикума, приложенном к правке. */
#korp .tile__body { justify-content: center; max-width: 56%; }
/* Объект-звездолёт лежит по горизонтали, поэтому правило слота corner
   (высота 128 % и выход за нижнюю кромку) ему не подходит: корабль надо
   вписать по высоте и увести вправо за обрез. */
#korp .tile__media { right: -3%; bottom: 6%; height: 88%; }
#korp .tile__media img { height: 100%; width: auto; }
@media (max-width: 767px) { #korp .tile__media { height: 46%; bottom: 2%; right: -6%; } }
#korp .tile__foot { margin-top: 0; }
#korp .title { font-size: clamp(1.375rem, 2.2vw, 1.75rem); }
#korp .lead { font-size: 1.125rem; color: var(--text-inverse); margin-bottom: 2px; }
@media (max-width: 767px) { #korp .tile__body { max-width: 100%; } }

/* ── Витрина ближайших дат ──
   Плитка следа f, но внутри не «текст + кнопка», а лента карточек: правка
   Тимура 22.08 требует держать расписание перед глазами на каждой странице.
   Карточки — стекло поверх градиента; на телефоне лента скроллится вбок,
   потому что три карточки в столбик занимают весь экран. */
.showcase { display: flex; flex-direction: column; gap: var(--s-md); }
.showcase__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-md); }
/* Шапка лежит на самой светлой части меша — мягкая тень вместо обводки. */
.showcase__head .title { text-shadow: 0 1px 12px rgba(3, 40, 60, 0.55); }
/* Ссылка стоит в самом светлом углу меша: на голом градиенте мелкий белый
   текст давал 2,55:1 (замер). Своя тёмная подложка возвращает 8,4:1 и заодно
   делает кликабельную зону честной. */
.showcase__all {
  color: var(--text-inverse); text-decoration: none; font-size: 0.9375rem; white-space: nowrap;
  background: rgba(4, 44, 66, 0.52); border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 999px; padding: 7px 14px;
  transition: background 0.18s var(--ease);
}
.showcase__all:hover { background: rgba(4, 44, 66, 0.68); }
.showcase__list { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-sm); }
/* Стекло на карточках — тёмное, а не белое. Белое поверх светлой части
   градиента давало 1,9–2,9:1 у белого текста (замер по скриншоту), то есть
   ниже порога; тёмная подложка держит 7,5:1 в любой точке плитки.
   Правило то же, что и в стеклянном меню: контраст закрывается замером
   по реальному фону, а не на глаз. */
.scard {
  display: flex; flex-direction: column; gap: 6px; min-height: 148px;
  padding: var(--s-sm) var(--s-md); border-radius: var(--r-pill);
  background: rgba(4, 44, 66, 0.52);
  border: 1px solid rgba(255, 255, 255, 0.22);
  color: var(--text-inverse); text-decoration: none;
  transition: background 0.18s var(--ease), transform 0.18s var(--ease);
}
.scard:hover { background: rgba(4, 44, 66, 0.66); transform: translateY(-2px); }
.scard__date { font-size: 1.25rem; font-weight: 600; line-height: 1.15; }
.scard__type { font-size: 0.8125rem; text-transform: uppercase; letter-spacing: 0.04em; color: rgba(255, 255, 255, 0.88); }
.scard__title { font-size: 0.9375rem; color: #fff; }
.scard__cta { margin-top: auto; font-size: 0.9375rem; font-weight: 600; }
@media (max-width: 900px) {
  .showcase__list { grid-auto-flow: column; grid-auto-columns: minmax(232px, 1fr); grid-template-columns: none; overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: 4px; }
  .scard { scroll-snap-align: start; }
}

/* ── Платёжная информация в подвале ──
   Требование правки: «текст берём с боевого, вёрстку улучшаем». На боевом это
   сплошная простыня мелким кеглем; здесь — линейка платёжных систем, три
   коротких абзаца с выделенными подписями и общая ширина в меру строки. */
.pay { border-top: 1px solid var(--border); padding-top: var(--s-md); margin-top: var(--s-md); display: grid; gap: 8px; }
.pay__row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 4px; }
.pay__label { font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); }
.pay__badge { font-size: 0.6875rem; letter-spacing: 0.04em; color: var(--text-muted);
  border: 1px solid var(--border); border-radius: 6px; padding: 5px 11px; background: #fff; }
.pay p { font-size: 0.8125rem; line-height: 1.7; color: var(--text-muted); margin: 0; max-width: 74ch; }
.pay p b { color: var(--text); font-weight: 600; }
/* dual-ok: тот же подвал — v13 кладёт раскладку поверх рамки и отступов из «Финала и подвала» */
.foot__legal { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--s-sm); }
.foot__social a { color: var(--text-muted); }
.foot__social a:hover { color: var(--accent-deep); }

/* Блок ролей держит свой ряд: на общих 320 px плитка следа t вырастала до
   664 px при 520 px контента, и под текстом оставалась пустая полоса —
   правка Тимура 22.08 «убрать лишний воздух в карточке под текстом». */
#roles .bento { --bento-row: 268px; }

/* Кнопка «Подробнее» у лекционного зала стоит сразу под текстом, а не
   у нижней кромки плитки: то же правило, что и в корпоративном баннере. */
#itpark .tile__foot { margin-top: var(--s-sm); padding-top: 0; }

/* Витрина — плитка следа f, но без .tile__body, поэтому внутренние отступы
   ставятся ей самой. Высота — по содержимому: три карточки в ряд не влезают
   в один ряд сетки. */
.tile.showcase { padding: var(--s-md); height: auto; }
#raspisanie .bento, #raspisanie { --bento-row: auto; }

/* Панель выбора кадра — временная, слева внизу: та же роль, что была
   у панели палитры, поэтому и место то же. */
.devbar.picbar { left: 16px; right: auto; transform: none; }
@media (max-width: 767px) { .devbar.picbar { left: 12px; right: auto; } }


/* ═══════════════════════════════════════════════════════════
   Компоненты v15 — документ Тимура от 24.08
   ═══════════════════════════════════════════════════════════ */

/* ── Поп-ап заявки ──
   Форма одна на весь сайт: «Записаться» больше не уводит человека на другую
   страницу, а открывает её поверх того места, где он читал. */
.modal[hidden] { display: none; }
.modal {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center; padding: var(--s-md);
}
.modal__backdrop {
  position: absolute; inset: 0;
  background: rgba(16, 22, 34, 0.55);
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
.modal__card {
  position: relative; z-index: 1; width: min(30rem, 100%);
  background: var(--surface); border-radius: var(--r-card);
  padding: var(--s-lg) var(--s-md) var(--s-md);
  display: grid; gap: var(--s-xs);
  max-height: 92vh; overflow-y: auto;
  box-shadow: 0 24px 64px rgba(16, 24, 32, 0.28);
}
.modal__close {
  position: absolute; top: var(--s-sm); right: var(--s-sm);
  width: 2rem; height: 2rem; border: 0; border-radius: 50%;
  background: var(--surface-muted); color: var(--text-muted);
  font-size: 1.375rem; line-height: 1; cursor: pointer;
}
.modal__close:hover { background: var(--border); color: var(--text); }
.modal__grid { display: grid; gap: var(--s-sm); margin-top: var(--s-sm); }
.modal__grid .btn { justify-self: stretch; text-align: center; }
/* .field собрано под тёмную форму-финалку: белый текст на полупрозрачной
   подложке. В белом поп-апе это давало белое по белому — переопределяем. */
.modal .field {
  color: var(--text);
  background: var(--surface);
  border-color: var(--border);
}
.modal .field::placeholder { color: var(--text-muted); }
.modal .field[readonly] { background: var(--surface-muted); }
.modal .consent { color: var(--text-muted); }
/* Ошибка формы: платёж не создался, поле не заполнено. Живёт в потоке грид-формы,
   чтобы кнопка не прыгала под курсором при появлении текста. */
.modal__error {
  color: var(--danger, #b3261e); font-size: 0.875rem; line-height: 1.35;
  background: rgba(179, 38, 30, 0.08); border-radius: var(--r-control); padding: 8px 10px;
}
.modal__error[hidden] { display: none; }
/* Та же строка в утвердительном виде: заявка принята. Отдельный узел здесь
   лишний — два узла разъезжаются по видимости и умеют показать оба разом. */
.modal__error--ok { color: var(--text); background: rgba(0, 150, 207, 0.12); }

/* Ответ формы на странице. Все четыре формы стоят на кобальтовой подложке,
   поэтому текст белый: тёмно-красный по тёмно-синему нечитаем. */
.form__note {
  grid-column: 1 / -1;
  font-size: 0.875rem; line-height: 1.35;
  border-radius: var(--r-control); padding: 8px 10px;
  color: #fff; background: rgba(179, 38, 30, 0.55);
}
.form__note[hidden] { display: none; }
.form__note--ok { background: rgba(0, 150, 207, 0.55); }
.modal .consent a { color: var(--accent); }

/* ── Тёмная секция-панель ──
   «Собираем блок по аналогии один-в-один» из документа: блок целиком ложится
   на кобальтовую подложку, карточки внутри становятся полупрозрачными. */
.block--ink {
  background: var(--surface-ink);
  color: var(--text-inverse);
  border-radius: var(--r-card);
  padding: var(--s-xl) var(--s-lg) var(--s-lg);
  margin-top: var(--s-xl);
  overflow: hidden;
}
@media (max-width: 767px) { .block--ink { padding: var(--s-lg) var(--s-md) var(--s-md); } }
.block--ink .headline,
.block--ink .title,
.block--ink .muted b { color: var(--text-inverse); }
.block--ink .lead,
.block--ink .muted { color: rgba(255, 255, 255, 0.78); }
.block--ink .eyebrow { color: rgba(255, 255, 255, 0.6); }
.block--ink .soft { color: rgba(255, 255, 255, 0.6); }
.block--ink .tile {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--border-on-ink);
}
.block--ink .arrow {
  color: var(--accent); font-size: 1.125rem; line-height: 1;
  margin: var(--s-xs) 0;
}

/* ── Таблица программы практики ── */
/* ── Программа практики ──
   Была таблица в рамке: на узких ширинах рамка сдавливала текст, а колонка
   «материалы» уходила в горизонтальную прокрутку. Стала лента шагов —
   время слева, шаг и результат справа, разделители-волосинки вместо рамки. */
.prog { list-style: none; margin: 0; padding: 0; }
.prog__row {
  display: grid;
  grid-template-columns: 5.5rem minmax(0, 1fr);
  gap: var(--s-md);
  padding: var(--s-md) 0;
  border-top: 1px solid var(--border);
}
.prog__row:first-child { border-top: 0; padding-top: 0; }
.prog__time {
  color: var(--accent-text);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.2px;
}
.prog__title { font-size: 1.0625rem; line-height: 1.3; margin: 0 0 6px; }
.prog__text { color: var(--text-muted); margin: 0; max-width: 62ch; }
.prog__out { margin: var(--s-xs) 0 0; font-size: 0.9375rem; }
.prog__out b { color: var(--accent-text); font-weight: 500; }
.prog__facts {
  display: flex; flex-wrap: wrap; gap: var(--s-xs) var(--s-md);
  margin-bottom: var(--s-md); color: var(--text-muted); font-size: 0.9375rem;
}
.prog__facts b { color: var(--text); font-weight: 500; }
.prog__day2 { margin-top: var(--s-md); }
.prog__list {
  list-style: none; margin: var(--s-sm) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-sm) var(--s-md);
}
.prog__list li { display: grid; gap: 2px; }
.prog__list b { font-weight: 500; }
.prog__list span { color: var(--text-on-ink); font-size: 0.9375rem; }
@media (max-width: 767px) {
  .prog__row { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .prog__list { grid-template-columns: minmax(0, 1fr); }
}

.program { width: 100%; border-collapse: collapse; font-size: 0.9375rem; }
.program th {
  text-align: left; padding: 0 var(--s-md) var(--s-sm) 0;
  color: var(--text-muted); font-weight: 400; font-size: 0.8125rem;
  text-transform: uppercase; letter-spacing: 0.04em;
  border-bottom: 1px solid var(--border);
}
.program td {
  padding: var(--s-md) var(--s-md) var(--s-md) 0;
  border-bottom: 1px solid var(--border); vertical-align: top;
}
.program tr:last-child td { border-bottom: 0; }
.program__num { color: var(--accent); width: 3rem; font-size: 1.125rem; }
.program__note { display: block; color: var(--text-muted); margin-top: 4px; }
.program__mats { white-space: nowrap; }
.program__mats .chip { margin: 0 var(--s-xs) var(--s-xs) 0; }
@media (max-width: 767px) { .program { min-width: 34rem; } }

/* ── «Оплатит работодатель» ── */
.compare__buy th { border-bottom: 0; }
.compare__buy td { border-bottom: 0; padding-top: var(--s-sm); }

/* Баннер работодателя: подстрочник прижат к заголовку, кнопка отодвинута от текста. */
.employer .tile__body { display: grid; align-content: center; gap: var(--s-xs); }
.employer .steps4 { margin-top: var(--s-sm); }
.employer .cta-row { margin-top: var(--s-md); }
.employer .tile__media { background: var(--surface-muted); }
.employer .tile__media img { object-fit: contain; padding: var(--s-md); }
.steps4 {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-xs) var(--s-md); counter-reset: s4; list-style: none;
  margin: var(--s-xs) 0 0; padding: 0;
}
.steps4 li {
  counter-increment: s4; display: flex; gap: var(--s-xs); align-items: baseline;
  color: var(--text-muted); font-size: 0.9375rem;
}
.steps4 li::before {
  content: counter(s4); flex: none;
  width: 1.375rem; height: 1.375rem; border-radius: 50%;
  background: var(--surface-muted); color: var(--text-muted);
  font-size: 0.75rem; display: inline-grid; place-items: center;
}
@media (max-width: 767px) { .steps4 { grid-template-columns: 1fr; } }

/* ── Ряд по содержимому ──
   Фиксированная высота ряда хороша, пока карточка — это плитка с картинкой.
   Там, где карточка живёт текстом, она либо режет хвост (третья карточка
   «Было → Стало» теряла последнюю строку), либо оставляет провал под текстом —
   ровно то, на что Тимур указал на главной. bento--auto отдаёт высоту
   содержимому: строка грида выравнивает карточки по самой высокой. */
.bento--auto { --bento-row: auto; }
.bento--auto .tile--top .tile__media { height: auto; }
.bento--auto .tile--top .tile__media img { height: auto; }
.bento--auto .tile__body { padding-bottom: var(--s-md); }

/* ── Первый экран подстраницы: текст по левому краю контента ──
   .subhero__body несёт и .wrap: собственный max-width: 46rem перебивал
   контейнер, а margin: 0 auto центрировал узкую колонку — первый экран уезжал
   вправо примерно на 270 px против всего остального содержимого страницы. */
.subhero__body { max-width: var(--container); }
.subhero__body > .eyebrow,
.subhero__body > .display,
.subhero__body > .lead { max-width: 46rem; }

/* ── Вёрстку причесать: скругления у витрины и значок в вопросах ── */
/* dual-ok: та же витрина из v13 — v15 добавляет ей скругление */
.showcase { border-radius: var(--r-card); }
.faq details { transition: background 0.2s var(--ease); }
.faq summary { padding: 2px 0; }
/* Значок собирался из двух поколений правил сразу: старая CSS-галочка
   (border + rotate) и новый «+» рисовались в одном псевдоэлементе и
   накладывались друг на друга. Сбрасываем геометрию галочки. */
.faq summary::after {
  width: auto; height: auto; border: 0; transform: none;
  font-size: 1.375rem; line-height: 1; color: var(--accent);
}
.faq details[open] summary::after { transform: none; }

/* ── Объект, вписанный в плитку ── */
/* Вариант слота corner для случаев, когда важен силуэт целиком: у локатора
   срезанная тарелка читается как ошибка кропа, а не как приём. Объект держит
   поля плитки и никуда не уходит за обрез. */
.tile--object .tile__media {
  position: absolute; right: var(--s-lg); top: var(--s-md); bottom: var(--s-md);
  width: 32%; pointer-events: none;
}
.tile--object .tile__media img {
  width: 100%; height: 100%; object-fit: contain; object-position: center;
}
.tile--object .tile__body { position: relative; z-index: 1; max-width: 62%; }
@media (max-width: 767px) {
  .tile--object .tile__media { width: 38%; right: var(--s-md); }
  .tile--object .tile__body { max-width: 66%; }
}
@media (max-width: 480px) {
  .tile--object .tile__media { display: none; }
  .tile--object .tile__body { max-width: 100%; }
}

/* ── Вуаль первого экрана на телефоне ── */
/* На телефоне текст занимает почти всю высоту первого экрана, и под кнопки
   попадает светлый купол башни: белый текст давал 2,33:1 на самом светлом
   участке (замер 24.08) при 7,98:1 по медиане. Тянем ту же вуаль, что уже
   держит контраст в верхней части кадра, до низа текстового блока — красить
   саму кнопку не нужно, её вид документом не менялся. */
@media (max-width: 767px) {
  .heroD::before {
    background: linear-gradient(180deg,
      rgba(18, 26, 38, 0.56) 0%, rgba(18, 26, 38, 0.34) 38%,
      rgba(18, 26, 38, 0.32) 72%, rgba(18, 26, 38, 0) 90%);
  }
}

/* ── Финальный призыв с картинкой ── */
/* Тот же приём, что у слота corner: объект уходит за обрез правого края,
   текст держит свою колонку. На узком экране объект прячется — терять строку
   текста ради декора не стоит. */
.closer--pic { position: relative; overflow: hidden; }
/* Объект вписан целиком и держит поля блока: у «маршрута» смысл в форме —
   два шага вверх, — и срезанный край её ломает. Текст держит свою колонку. */
.closer__media {
  position: absolute; right: var(--s-lg); top: 50%; transform: translateY(-50%);
  height: 74%; width: auto; pointer-events: none;
}
.closer__media img { height: 100%; width: auto; object-fit: contain; }
.closer--pic > *:not(.closer__media) { position: relative; z-index: 1; max-width: 58%; }
@media (max-width: 900px) {
  .closer__media { height: 56%; right: var(--s-md); }
  .closer--pic > *:not(.closer__media) { max-width: 70%; }
}
@media (max-width: 560px) {
  .closer__media { display: none; }
  .closer--pic > *:not(.closer__media) { max-width: 100%; }
}

/* ── Отзывы ── */
/* Портрет участника во всю высоту плитки и крупная цитата рядом (вариант B,
   выбор Лёши 24.08). Слот side уже умеет чередовать сторону — зеркалим через
   один. Портрет 4:5 растянул бы плитку под 600 px, поэтому кадрируем по её
   высоте, а точку фокуса задаём каждому свою: лица стоят в кадре по-разному. */
.rev-side { max-height: 400px; overflow: hidden; }
.rev-side .tile__body { display: flex; flex-direction: column; justify-content: center; }
.rev-side .tile__media img { width: 100%; height: 100%; object-fit: cover; }
.rev-side--dmitriy .tile__media img { object-position: 54% 50%; }
.rev-side--margarita .tile__media img { object-position: 52% 30%; }
.rev-side--vlad .tile__media img { object-position: 62% 46%; }
@media (max-width: 767px) { .rev-side { max-height: none; } }
.rev-big { font-family: var(--font-display); font-size: 1.375rem; line-height: 1.45;
           max-width: 34em; }
@media (max-width: 900px) { .rev-big { font-size: 1.125rem; } }


/* ═══════════════════════════════════════════════════════════
   v19 — прогон QA и мобильная адаптация (24.08)
   Каждая правка держится на замере из temp/v19-defects.md.
   ═══════════════════════════════════════════════════════════ */

/* ── Мобильное меню ──
   Кнопка и панель создаются скриптом из ссылок шапки; здесь только вид. */
.nav__burger {
  display: none; margin-left: var(--s-xs);
  width: 44px; height: 44px; flex: none;
  align-items: center; justify-content: center;
  flex-direction: column; gap: 5px;
  background: transparent; border: 0; border-radius: var(--r-control);
  cursor: pointer; padding: 0;
}
.nav__burger span {
  display: block; width: 20px; height: 2px; border-radius: 2px;
  background: var(--text); transition: transform 0.18s var(--ease), opacity 0.18s var(--ease);
}
.nav[data-menu="open"] .nav__burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav[data-menu="open"] .nav__burger span:nth-child(2) { opacity: 0; }
.nav[data-menu="open"] .nav__burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Подложка: панель висит над первым экраном с фотографией, без затемнения
   список сливается с кадром. */
.nav[data-menu="open"]::before {
  content: ""; position: fixed; inset: 0; z-index: -1;
  background: rgba(16, 22, 34, 0.45);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  pointer-events: auto;
}
.nav__panel {
  pointer-events: auto;
  position: fixed; inset: 76px var(--s-md) auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: 0 24px 60px rgba(9, 14, 40, 0.18);
  padding: var(--s-xs);
  max-height: calc(100dvh - 96px);
  overflow-y: auto;
}
.nav__panel-links { display: grid; }
.nav__panel-links a {
  display: block; text-decoration: none; color: var(--text);
  font-size: 1.0625rem; padding: 14px var(--s-md);
  border-radius: var(--r-control);
}
.nav__panel-links a:hover { background: var(--surface-muted); }
.nav__panel-links a[aria-current="page"] { color: var(--accent-deep); }
/* Разделитель «Компаниям» в панели не нужен — в столбце он читается как пропуск. */
.nav__panel-links .nav__sep { display: none; }

@media (max-width: 1023px) {
  .nav__burger { display: flex; }
  /* Кнопка «Расписание» остаётся в шапке: это главное действие страницы. */
  .nav__cta { margin-left: auto; }
}
@media (min-width: 1024px) { .nav__panel { display: none; } }

/* ── Плитки: текст перестаёт резаться нижней кромкой ──
   Замер v18: «Предпринимателям» на 320 и 1024 теряли последнее слово —
   высоту плитки диктовала сетка, а картинка съедала 55% в процентах.
   На узких экранах картинка получает высоту в пикселях, тело — остаток. */
@media (max-width: 1100px) {
  /* Ряд сетки перестаёт быть потолком: высота задана как минимум, дальше растёт
     под содержимое. Иначе на 1024 плитка ролей теряла последнее слово абзаца,
     а блоки площадки и отзывов резали текст нижней кромкой. */
  #roles .bento { --bento-row: auto; }
  .bento:not(.bento--auto) { grid-auto-rows: minmax(var(--bento-row), auto); }
  /* Блок площадки и врезка расписания задают ряд не переменной, а свойством —
     их потолок снимаем тем же приёмом отдельно. */
  #itpark .bento { grid-auto-rows: minmax(360px, auto); }
  #raspisanie .bento { grid-auto-rows: minmax(200px, auto); }
  .tile--top .tile__media, .tile--bottom .tile__media { height: 240px; flex: none; }
  .tile--top .tile__media img, .tile--bottom .tile__media img { height: 100%; }
  /* overflow:hidden у плитки не снимаем: на нём держится слот corner —
     объект по канону уходит за обрез угла, без обрезки он раздвигает страницу. */
}
@media (max-width: 767px) {
  .tile--top .tile__media, .tile--bottom .tile__media { height: 200px; }
}

/* ── Плитка со слотом side на планшете ──
   На 1024 текст сжимался в колонку по два-три слова: 60% от 384 px — это
   230 px под абзац. Ниже 1100 px картинка уходит вниз, текст получает всю ширину. */
@media (max-width: 1100px) {
  .tile--side, .tile--side-rev { flex-direction: column; }
  .tile--side .tile__body, .tile--side-rev .tile__body { flex: 1 1 auto; }
  .tile--side .tile__media, .tile--side-rev .tile__media { width: 100%; height: 220px; align-self: auto; }
  .tile--side .tile__body, .tile--side-rev .tile__body { width: 100%; }
}

/* ── Слот corner на планшете ──
   Тело плитки держит 62% ширины, чтобы не налезать на объект. На 1024 колонка
   сетки узкая, и 62% превращались в 143 px — абзац набирался по два слова
   в строке. В этом диапазоне текст получает всю ширину, а объект опускается
   к нижней кромке, как это уже сделано для телефона. */
@media (min-width: 768px) and (max-width: 1100px) {
  /* 72%, а не вся ширина: объект остаётся справа и не оказывается под
     подписью со стрелкой — текст поверх рисунка читается как ошибка. */
  .tile--corner .tile__body { max-width: 72%; }
  .tile--corner .tile__media { height: 52%; bottom: 0; right: -10%; }
}

/* ── Врезка расписания: лента читается как лента ──
   Карточки обрывались ровно по внутреннему полю плитки и выглядели обрезанными.
   Теперь лента уходит под правый край, а карточка занимает 78% ширины —
   следующая всегда выглядывает. */
@media (max-width: 767px) {
  .tile.showcase { padding-right: 0; }
  .showcase__head { padding-right: var(--s-md); }
  .showcase__list {
    grid-auto-columns: 78%;   /* minmax(0,78%) даёт трекам ужаться и втиснуть три карточки */
    padding-right: var(--s-md);
    scroll-padding-inline-start: 0;
    scrollbar-width: none;
  }
  .showcase__list::-webkit-scrollbar { display: none; }
}

/* ── Таблица программы практики на телефоне ──
   Была горизонтальная прокрутка с обрезанными чипами материалов.
   Строка становится карточкой: номер слева, шаг и материалы в колонку. */
@media (max-width: 767px) {
  .program { min-width: 0; font-size: 1rem; }
  /* Шапка таблицы на телефоне не нужна: строка развёрнута в карточку,
     подписи столбцов ушли в разметку карточки. */
  .program thead { display: none; }
  .program tbody, .program tr, .program td { display: block; }
  .program tr {
    display: grid; grid-template-columns: 2.25rem 1fr;
    column-gap: var(--s-xs); align-items: start;
    padding: var(--s-md) 0; border-bottom: 1px solid var(--border);
  }
  .program tr:last-child { border-bottom: 0; }
  .program td { padding: 0; border-bottom: 0; }
  .program__num { grid-column: 1; grid-row: span 2; font-size: 1rem; padding-top: 2px; }
  .program td:not(.program__num) { grid-column: 2; }
  .program__mats { white-space: normal; margin-top: var(--s-xs); }
  .program__mats .chip { margin: 0 6px 6px 0; }
}

/* ── Сравнение форматов на телефоне ──
   Три колонки в 390 px не живут. Строка разворачивается в карточку:
   признак заголовком, под ним три значения с подписью формата (data-col). */
@media (max-width: 767px) {
  .compare__wrap { border: 0; border-radius: 0; overflow: visible; }
  .compare, .compare tbody, .compare tr, .compare th, .compare td { display: block; }
  /* Таблица, переведённая в блок, сохраняет минимальную ширину своей табличной
     раскладки и раздвигает страницу — снимаем её явно. */
  .compare { min-width: 0; max-width: 100%; width: 100%; }
  .compare thead { display: none; }
  .compare tr {
    border: 1px solid var(--border); border-radius: var(--r-card);
    padding: var(--s-md); margin-bottom: var(--s-sm);
  }
  .compare tbody th {
    padding: 0 0 var(--s-xs); border: 0;
    color: var(--text); font-size: 1.0625rem;
  }
  .compare td {
    display: flex; justify-content: space-between; gap: var(--s-md);
    padding: 8px 0; border-bottom: 1px solid var(--border);
    text-align: right;
  }
  .compare tr td:last-child { border-bottom: 0; }
  .compare td::before {
    content: attr(data-col); text-align: left;
    color: var(--text-muted); font-size: 0.9375rem;
  }
  /* Бейдж «Рекомендуем» живёт в шапке таблицы — на телефоне шапки нет. */
  .compare td[data-col*="2 дня"]::before { content: "2 дня · рекомендуем"; }
}

/* ── Цели для пальца ──
   Замер: ссылки подвала 20 px, чекбокс согласия 13×13, стрелки календаря 36×36. */
@media (max-width: 1023px) {
  .foot ul { gap: 0; }
  .foot ul a { display: block; padding: 9px 0; }
  .foot__legal a { padding: 4px 0; display: inline-block; }
  .foot__social a { display: inline-block; padding: 6px 4px; }
  .cal__nav button, .cal button.cal__arrow { min-width: 44px; min-height: 44px; }
}
.consent input[type="checkbox"], .form input[type="checkbox"], .modal input[type="checkbox"] {
  width: 20px; height: 20px; flex: none; accent-color: var(--accent);
}

/* ── Заливка действия: белый текст держит норму ──
   Решение Лёши 24.08 после прогона: белый на фирменном #0096cf давал 3,35:1
   при норме 4,5. Меняем не сам токен --accent (он ещё и цвет-код «лекции»
   в календаре, и акцент на кобальте, где 4,5 как раз держится), а ЗАЛИВКУ
   тех мест, где поверх лежит белый текст: 4,75:1 на --accent-deep.
   Наведение уходит на тон глубже, иначе отклик кнопки пропадает. */
:root { --accent-deeper: #00658c; }   /* 6,48:1 с белым */
/* dual-ok: та же кнопка, что в секции «Кнопки» — QA 24.08 увёл основной фон на тёмный акцент */
.btn--primary { background: var(--accent-deep); }
.btn--primary:hover { background: var(--accent-deeper); }
/* dual-ok: та же плашка из v13 — QA 24.08 перекрасил фон */
.tile__badge { background: var(--accent-deep); }
::selection { background: var(--accent-deep); }

/* ── Контраст ──
   Голубой как ЦВЕТ ТЕКСТА давал 3,35:1 на белом и не дотягивал до нормы на
   серой подложке даже в варианте --accent-deep (4,17). Заливки кнопок не
   трогаем — это фирменный цвет; для текста заводим отдельный тон.
   Замеры: 5,45 на белом · 4,78 на --surface-muted · 4,85 на --accent-wash. */
:root { --accent-text: #00719e; }
.cal-panel__date, .cal-panel__status, .cal__legend b, .eyebrow b, .program__num,
.prose a, .lead a, .muted a, .foot__legal a, p a:not(.btn),
.nav__links a[aria-current="page"] { color: var(--accent-text); }

/* Тёмные поверхности системы: кобальт под текстом переворачивает требования —
   серый надзаголовок давал 2,81, а тёмный акцент 3,18. Здесь работают
   светлые тона: --text-on-ink 9,54 и фирменный --accent ровно 4,5. */
.tile--ink .eyebrow, .block--ink .eyebrow, .closer .eyebrow, .subhero .eyebrow,
.heroD .eyebrow, html[data-lay="full"] .lekhero .eyebrow,
.tile--ink .label, .block--ink .label, .closer .label, .subhero .label, .heroD .label {
  color: var(--text-on-ink);
}
.tile--ink .eyebrow b, .block--ink .eyebrow b, .closer .eyebrow b, .subhero .eyebrow b,
.heroD .eyebrow b, html[data-lay="full"] .lekhero .eyebrow b {
  color: var(--accent);
}


/* ═══════════════════════════════════════════════════════════
   Правки 25.08 — тарифная карточка «Инструментов», заглушка
   раздела и корпоративный вариант поп-апа
   ═══════════════════════════════════════════════════════════ */

/* Карточка тарифа из документа: две строки-позиции (подписка и сервер),
   сумма — на кнопке. Не новый след и не новый слот: меняется только
   содержимое тела плитки.

   ⛔ 01.09.2026: имя `.plan` занято дважды — здесь это список позиций внутри
   плитки, ниже (тарифы «Практики», 31.08) — сама карточка. Второе описание
   идёт позже и приносило сюда фон, радиус и padding: на тёмной плитке
   подписки белый текст ложился на светло-серую подложку (1,14:1), а лишние
   48 px высоты выталкивали кнопку за нижнюю кромку плитки t-m (320 px,
   overflow: hidden). Развели по контексту: список — только внутри .tile,
   карточка — только внутри .plans. */
.tile .plan { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-sm); }
.tile .plan li {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-sm);
  padding-bottom: var(--s-sm); border-bottom: 1px solid var(--border);
}
.tile .plan li:last-child { border-bottom: 0; padding-bottom: 0; }
.tile--ink .plan li { border-color: var(--border-on-ink); }
.plan__what { display: grid; gap: 2px; min-width: 0; }
.plan__what small { font-size: 0.875rem; color: var(--text-muted); }
.tile--ink .plan__what small { color: var(--text-on-ink); }
.plan__sum {
  font-size: 1.25rem; white-space: nowrap; font-variant-numeric: tabular-nums;
}

/* Заглушка раздела: кадр во весь экран, текст и форма поверх него.
   Затемнение уводится влево — правая треть кадра несёт сюжет. */
.subhero--splash { min-height: 100svh; display: grid; align-items: center; }
.subhero--splash::after {
  background: linear-gradient(100deg, rgba(16,22,34,0.88) 0%, rgba(16,22,34,0.66) 46%,
              rgba(16,22,34,0.34) 100%);
}
@media (max-width: 767px) {
  .subhero--splash::after {
    background: linear-gradient(180deg, rgba(16,22,34,0.82) 0%, rgba(16,22,34,0.72) 100%);
  }
}
.splash__form { display: grid; gap: var(--s-sm); max-width: 34rem; margin-top: var(--s-sm); }
.splash__form .consent { max-width: 28ch; }
/* Подпись формы стоит на кадре, а не на светлой подложке: --text-muted здесь
   даёт серое по тёмному. Тот же перевод на --text-on-ink, что у .closer. */
.subhero .muted { color: var(--text-on-ink); }
/* На телефоне кадр режется по центру и сюжет уходит за кромку: сундук стоит
   в правой трети — сдвигаем точку фокуса к нему. */
/* Сдвиг кроп-точки уехал в переменную --crop (блок v35 ниже): одно значение
   на картинку и на маски искр, порознь они бы разъехались. */

/* ── Читаемость первого экрана на телефоне (правка Тимура 26.08) ──

   Механизм, а не вкусовщина. Оверлей первого экрана — градиент
   0.78 → 0.55 (на 55%) → 0.72. На широком экране текст стоит в левой трети,
   а сюжет кадра — в правой, и провал 0.55 приходится мимо текста. На телефоне
   кадр портретный, сюжет уходит в центр, а текстовый блок занимает всю высоту —
   и провал ложится ровно под подзаголовок. У «Инструментов» и «Практики»
   светлый купол башни оказывается прямо под белой строкой, у «Расписания»
   в нижнюю треть приходит светлеющий горизонт, где стоят факты.

   Глухо затемнить кадр — самый простой ответ и неправильный: Тимур уже просил
   «сделать картинку сочнее» (30.07), плита вместо фотографии — шаг назад.
   Поэтому две меры вместе: убрать провал в середине (перепад 0.86 → 0.80,
   без светлой полосы) и снять с кадра мелкую деталь размытием. Размытие
   убивает именно то, что мешает читать, — контурную мелочь конструкции и
   толпу, — и сохраняет цвет и настроение. scale(1.06) прячет кромку размытия,
   saturate возвращает насыщенность, которую съедает blur.

   Числа выбраны замером, а не на глаз. Кадр снят БЕЗ текста (`.subhero__body`
   спрятан), в полосе, где стоит подзаголовок, считались контраст белого к
   самой светлой точке подложки и разброс яркости:

     Практика      было 5,91:1 · σ 0,0174 → стало 8,33:1 · σ 0,0101
     Инструменты   было 6,11:1 · σ 0,0144 → стало 8,35:1 · σ 0,0088
     Расписание    было 7,40:1 · σ 0,0173 → стало 10,75:1 · σ 0,0082

   Видно, в чём была причина: СРЕДНИЙ контраст и раньше был 11–12:1, то есть
   формально всё проходило. Мешала не средняя яркость, а светлое пятно купола
   и пестрота — текст стоял на движущемся фоне. Поэтому лечится размытием,
   а не затемнением. Глухой вариант (0,86/0,80 + blur 3px) даёт 12–13:1 при
   σ 0,004, но кадр превращается в плиту — отвергнут. */
@media (max-width: 767px) {
  /* v24: кадры нарисованы под текст — сюжет в нижней четверти, верх пустой
     и тёмный. Душить их нечем, поэтому скрим втрое легче прежнего, а излом
     на 55% высоты приходится туда, где у кадров начинается сюжет. Размытие
     снято: размывать нечего, а LCP от фильтра дешевле не становится. */
  .subhero::after {
    background: linear-gradient(180deg, rgba(16,22,34,0.42) 0%,
                rgba(16,22,34,0.34) 55%, rgba(16,22,34,0.90) 100%);
  }
}

/* ── Мобильные правки после обхода по 13 разрешениям (25.08) ──

   1. Якорь внутри страницы приводил заголовок ПОД шапку: меню липкое и на
      телефоне занимает 80 px, а `#tarify` ставит цель ровно в ноль. На десктопе
      сходилось случайно (76 против 80), на 390 заголовок «Два тарифа…» уезжал
      под капсулу. Отступ прокрутки задаётся один раз для всех якорей сайта. */
html { scroll-padding-top: 96px; }

/*  2. Финал «Лекций» на 320 px вылезал за свой же padding на 10 px. Причина не
      в переносе, а в auto-минимуме грид-элемента: колонка .closer растягивалась
      по самому длинному слову заголовка («действительно»). Тот же приём, что уже
      стоит у .tile и .cal-layout, — снять min-width, а перенос дослать словом. */
.closer > * { min-width: 0; }
/* dual-ok: общая добавка ко всем трём заголовочным стилям — длинное слово не должно рвать плитку */
.display, .headline, .title { overflow-wrap: break-word; }

/*  3. Логотип в шапке — ссылка на главную высотой 26 px: по канону тач-цели
      мало. Высота ссылки поднята до 44 px, вид капсулы не меняется. */
.nav__inner > a[aria-label] { display: inline-flex; align-items: center; min-height: 44px; }

/* Порядок полей корпоративного варианта: ФИО, Компания, почта, телефон. */
.modal[data-variant="korp"] #modalName { order: 1; }
.modal[data-variant="korp"] #modalCompany { order: 2; }
.modal[data-variant="korp"] #modalEmail { order: 3; }
.modal[data-variant="korp"] #modalPhone { order: 4; }
.modal[data-variant="korp"] #modalSlot { order: 5; }
.modal[data-variant="korp"] #modalSubmit { order: 6; }
/* Оплата: порядок полей как в платёжной форме на боевом — ФИО, почта, телефон. */
.modal[data-variant="checkout"] #modalName { order: 1; }
.modal[data-variant="checkout"] #modalEmail { order: 2; }
.modal[data-variant="checkout"] #modalPhone { order: 3; }
.modal[data-variant="checkout"] #modalError { order: 4; }
.modal[data-variant="checkout"] #modalSubmit { order: 5; }
.modal[data-variant="korp"] .consent { order: 7; }


/* ═══════════════════════════════════════════════════════════
   Cookie-баннер (152-ФЗ). Разметку вставляет site.js — иначе блок
   пришлось бы держать в восьми страницах, и они разъехались бы.
   ═══════════════════════════════════════════════════════════ */

/* [hidden] отдельным правилом обязателен: display: flex ниже перебил бы
   браузерный дефолт атрибута, и баннер показывался бы всегда. */
.cookie[hidden] { display: none; }

.cookie {
  position: fixed;
  z-index: 55;                 /* выше навигации (50), ниже поп-апа (60) */
  left: var(--s-sm); right: var(--s-sm); bottom: var(--s-sm);
  max-width: 34rem; margin: 0 auto;
  display: flex; align-items: center; gap: var(--s-md);
  padding: 14px var(--s-md);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: 0 12px 32px rgba(16, 24, 32, 0.16);
  font-size: 0.875rem; line-height: 1.5; color: var(--text-muted);
}

.cookie__text { flex: 1; }
.cookie__text a { color: var(--accent); text-decoration: underline; }
.cookie .btn { flex: none; }

/* Кнопка рядом с текстом перестаёт помещаться раньше, чем ломается остальная
   раскладка, — своя кромка, не общий брейкпоинт сетки. */
@media (max-width: 560px) {
  .cookie {
    flex-direction: column; align-items: stretch;
    text-align: center; gap: var(--s-sm);
  }
  /* .btn--sm даёт 42 px — на два пикселя мельче тач-цели. На десктопе кнопку
     не трогаем: там она попадается мышью, и высота держит ряд с текстом. */
  .cookie .btn { min-height: 44px; }
}

/* ═══════════════════════════════════════════════════════════
   Плитка «Работает из России напрямую»: импульс по нарисованному лучу
   Свет на растре статичен и остаётся статичным — SVG-слой лишь один раз
   прогоняет по нему сегмент. Стартует не по load, а по появлению плитки
   в кадре (site.js): блок лежит ниже трёх экранов, анимация по загрузке
   отработала бы в невидимой зоне.
   ═══════════════════════════════════════════════════════════ */
.tile__media--beam { position: relative; }
.beam {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
/* Кроп переключается тем же порогом, что и <source> у картинки: слой света
   обязан жить в той же системе координат, что и кадр под ним. */
.beam--wide { display: none; }
@media (max-width: 1100px) {
  .beam--sq { display: none; }
  .beam--wide { display: block; }
}

.beam__line {
  fill: none;
  stroke: #fff3de;
  stroke-width: 9;
  stroke-linecap: round;
  /* pathLength=1000 на самих путях приводит оба кропа к одной шкале: длины
     линий разные (550 и 578 пользовательских единиц), а раскладка штриха
     считается так, будто в каждом ровно 1000. Поэтому keyframes — общий,
     без var() в значениях: подставленную переменную Chromium не интерполирует,
     и офсет прыгает из начала в конец вместо того, чтобы ехать. */
  stroke-dasharray: 175 3000;
  stroke-dashoffset: 175;
  opacity: 0;
  /* Два ореола: узкий добавляет импульсу плотности, широкий — тепла вокруг.
     Одним слоем сегмент на светлой стене читается как царапина, а не как свет. */
  filter: drop-shadow(0 0 4px rgba(255, 214, 150, 0.95))
          drop-shadow(0 0 14px rgba(245, 166, 60, 0.75));
}
.beam__spark { opacity: 0; }

.tile__media--beam.is-lit .beam__line {
  animation: beam-run 1.05s cubic-bezier(0.3, 0.45, 0.35, 1) 0.25s 1 both;
}
.tile__media--beam.is-lit .beam__spark--src {
  animation: beam-flash 0.7s ease-out 1 both;
}
.tile__media--beam.is-lit .beam__spark--dst {
  animation: beam-flash 0.55s ease-out 1.2s 1 both;
}

@keyframes beam-run {
  0%   { opacity: 0; stroke-dashoffset: 175; }
  14%  { opacity: 1; }
  86%  { opacity: 1; }
  100% { opacity: 0; stroke-dashoffset: -1000; }
}
@keyframes beam-flash {
  0%   { opacity: 0; }
  35%  { opacity: 1; }
  100% { opacity: 0; }
}

/* Просили меньше движения — показываем кадр как есть. Луч на картинке уже
   нарисован, так что смысл плитки не теряется. */
@media (prefers-reduced-motion: reduce) {
  .tile__media--beam.is-lit .beam__line,
  .tile__media--beam.is-lit .beam__spark { animation: none; }
}

/* ═══════════════════════════════════════════════════════════
   Ещё три акцента света тем же приёмом, что луч на Инструментах.
   Общее правило набора: подсвечиваем только уже нарисованный свет,
   один раз при появлении, не больше одного акцента в поле зрения.
   ═══════════════════════════════════════════════════════════ */

/* Хост объявляется разметкой (data-beam), а не классом конкретной плитки:
   акцентов теперь четыре в трёх разных обвязках.
   ⚠️ Контекст позиционирования задаём ТОЛЬКО там, где своего нет. Голый
   [data-beam] с position: relative весит как класс, стоит ниже в файле и
   перебивает чужое правило: так уже уронили первый экран (.heroD__scene
   { position: absolute } → сцена выпала в поток, заголовок уехал под кадр)
   и следом плитку локатора (.tile--object .tile__media — та же специфичность
   (0,2,0), медиа встала в поток и схлопнула текст блока с 320 до 48 px).
   ⭐ «Только если position: static» в CSS выразить нельзя, поэтому родное
   значение возвращаем ЯВНО — это переживёт и новые модификаторы плиток. */
.tile__media[data-beam] { position: relative; }
.tile--object .tile__media[data-beam] { position: absolute; }

/* Портретный кадр первого экрана — свой файл и свой кроп, порог тот же,
   что у <source> картинки. */
.beam--port { display: none; }
@media (max-width: 767px) {
  .heroD__scene .beam--sq { display: none; }
  .beam--port { display: block; }
}

/* Купол башни: длинный вдох-выдох, амплитуда намеренно низкая. Это первый
   экран — акцент должен задавать тон, а не показывать фокус. */
@keyframes beam-slow {
  0%   { opacity: 0; }
  45%  { opacity: 0.55; }
  100% { opacity: 0; }
}
[data-beam].is-lit .beam__spark--slow {
  animation: beam-slow 2.6s cubic-bezier(0.4, 0, 0.3, 1) 0.35s 1 both;
}

/* Огонёк локатора: два коротких мигания — станция вышла в эфир. Пауза между
   ними длиннее самих вспышек, иначе читается как мерцание неисправности. */
@keyframes beam-blink {
  0%, 8%    { opacity: 0; }
  16%       { opacity: 1; }
  30%       { opacity: 0; }
  46%       { opacity: 1; }
  62%, 100% { opacity: 0; }
}
[data-beam].is-lit .beam__spark--blink {
  animation: beam-blink 2.2s linear 0.3s 1 both;
}

/* Шлейф робота наливается светом от робота вперёд: точка отсчёта — левый край
   эллипса, то есть сам робот. Бегущий сегмент здесь пробовали и убрали —
   на конусе света он читался как белая «таблетка», а не как свет. */
.beam__spark--flare { transform-box: fill-box; transform-origin: 0% 50%; }
@keyframes beam-flare {
  0%   { opacity: 0;    transform: scaleX(0.42); }
  32%  { opacity: 0.9;  transform: scaleX(0.78); }
  70%  { opacity: 0.55; transform: scaleX(1); }
  100% { opacity: 0;    transform: scaleX(1); }
}
[data-beam].is-lit .beam__spark--flare {
  animation: beam-flare 1.6s cubic-bezier(0.3, 0.5, 0.35, 1) 0.2s 1 both;
}

@media (prefers-reduced-motion: reduce) {
  [data-beam].is-lit .beam__spark,
  [data-beam].is-lit .beam__line { animation: none; }
}

/* ═══════════════════════════════════════════════════════════
   v33: две лампочки.
   ═══════════════════════════════════════════════════════════ */

/* Огонёк робота: три коротких мигания. Пауза длиннее вспышки — так читается
   работающая машина, а не аварийный маячок. */
@keyframes beam-pulse {
  0%, 6%     { opacity: 0; }
  12%        { opacity: 1; }
  24%        { opacity: 0.06; }
  32%        { opacity: 1; }
  44%        { opacity: 0.06; }
  52%        { opacity: 1; }
  68%, 100%  { opacity: 0; }
}
[data-beam].is-lit .beam__spark--pulse {
  animation: beam-pulse 2.4s linear 0.3s 1 both;
}

/* Терминал: оранжевый моргает один раз — карта приложена. */
@keyframes pay-ping {
  0%   { opacity: 0; }
  22%  { opacity: 1; }
  70%  { opacity: 0.25; }
  100% { opacity: 0; }
}
/* …и уступает зелёному, который ОСТАЁТСЯ: платёж прошёл, состояние конечное.
   `both` держит последний кадр — гасить его нечем и незачем. */
@keyframes pay-ok {
  0%   { opacity: 0; transform: scale(0.55); }
  60%  { opacity: 1; transform: scale(1.12); }
  100% { opacity: 1; transform: scale(1); }
}
[data-beam].is-lit .beam__spark--ping {
  animation: pay-ping 0.75s ease-out 0.2s 1 both;
}
[data-beam].is-lit .beam__spark--ok {
  transform-box: fill-box; transform-origin: 50% 50%;
  animation: pay-ok 0.6s cubic-bezier(0.34, 1.4, 0.5, 1) 0.85s 1 both;
}

/* ⭐ Луч в соседней плитке ждёт, пока отработает карта: две плитки одного ряда
   читаются как цепочка «оплатил → доступ открылся», а не как два независимых
   мигания. Задержки = базовые из v31 плюс 1.55 с. Развести обратно — убрать
   этот блок, keyframes общие и не тронуты. */
.tile__media--beam.is-lit .beam__spark--src { animation-delay: 1.55s; }
.tile__media--beam.is-lit .beam__line       { animation-delay: 1.80s; }
.tile__media--beam.is-lit .beam__spark--dst { animation-delay: 2.75s; }

@media (prefers-reduced-motion: reduce) {
  [data-beam].is-lit .beam__spark { animation: none; }
}


/* ═══════════════════════════════════════════════════════════
   v34 — правки адаптивов по сплошному аудиту 29.08.2026
   Гейт: temp/audit-responsive.py (8 страниц × 17 ширин × 5 состояний).
   ═══════════════════════════════════════════════════════════ */

/* ── A. Ряд сетки на телефоне считается по содержимому ──
   Замысел был объявлен ещё в блоке ≤767 (`grid-auto-rows: auto`), но правка
   v18 стоит НИЖЕ и на всём диапазоне ≤1100 возвращает ряду роль пола:
   `minmax(var(--bento-row), auto)`. На телефоне это значит «не меньше 320 px»
   даже там, где текста на 190. Ниже 480 px рисунок в углу скрывается совсем
   (`display: none`) — и под текстом оставалось до 156 px голой подложки.
   Замер v33, главная: «Лекции» 156, «Инструменты» 156, «Сокровищница» 132,
   «Практика» 108; те же дыры на «Расписании» и «Инструментах» в шагах 1-2-3.

   Лечим не отменой правки v18 (она нужна на планшете, где плитка иначе режет
   текст нижней кромкой), а явным словом для телефона — последним в каскаде. */
@media (max-width: 767px) {
  .bento:not(.bento--auto),
  #itpark .bento,
  #raspisanie .bento { grid-auto-rows: auto; }
  /* Плитка-кадр живёт картинкой, а не текстом: у неё свой пол, иначе
     подложка сжимается до полосы и сюжет пропадает. */
  .tile--full { min-height: 280px; }
}

/* ── B. Плитка-цитата ──
   `.tile__foot` прижимает подпись к нижней кромке — верно для карточки со
   ссылкой, неверно для высказывания: между цитатой и именем зияло 162 px
   (замер 1440). Слова и подпись — одно целое, поэтому пара центрируется
   в плитке, а не разъезжается по углам. */
.tile--quote .tile__body { justify-content: center; }
.tile--quote .tile__foot { margin-top: var(--s-sm); }

/* ── C. Цели для пальца ──
   Продолжение блока «Цели для пальца» от v26 — там подняли подвал, чекбокс
   и стрелки календаря. Замер v33 нашёл ещё пять мест ниже нормы 44 px:
   «Всё расписание» 164×39, вопрос FAQ 542×31, телефон в контактах 512×30,
   крестик поп-апа 32×32 и клетка календаря 39×50. */
@media (max-width: 767px) {
  .showcase__all { padding: 11px 16px; }
  /* Вертикаль остаётся прежней: у details забираем ровно столько, сколько
     отдаём summary, — иначе карточка вопроса подрастает на 20 px. */
  .faq details { padding: var(--s-sm) var(--s-md); }
  .faq summary { padding: 10px 0; }
  .contacts__row a { display: inline-flex; align-items: center; min-height: 44px; }
  .modal__close { width: 44px; height: 44px; }
}
/* Семь колонок в 390 px: клетка выходила 39 px. Недостающее забираем у полей
   календаря и промежутков — сетка остаётся семиколоночной.
   Расчёт: (390 − 48 поля страницы − 16 поля календаря − 18 промежутков) / 7 = 44. */
@media (max-width: 400px) {
  .cal { padding: var(--s-sm) 8px; }
  .cal__grid { gap: 3px; }
}

/* ── D. Мелкий кегль ──
   Значки оплаты в подвале набирались 11 px, подпись типа события в календаре —
   10 px. Подпись не ужимаем дальше, а раньше переключаем клетку на точку:
   самому длинному слову («Компаниям») при 12 px нужно ≈73 px вместе с полями,
   это календарь от 660 px, а не от 540. Ниже порога тип события показывает
   точка, расшифровка остаётся в легенде — механизм прежний, сдвинут порог. */
.pay__label, .pay__badge { font-size: 0.75rem; }
.cal__tag { font-size: 0.75rem; }
@container (max-width: 660px) {
  .cal__cell { text-align: center; }
  .cal__tag { display: none; }
  .cal__cell--event::after {
    content: ""; display: block; width: 7px; height: 7px; border-radius: 50%;
    margin: 4px auto 0; background: var(--ev);
  }
  .cal__cell[aria-pressed="true"]::after { background: var(--text-inverse); }
  .cal__cell--event { box-shadow: none; }
  .cal__cell[aria-pressed="true"] { color: var(--text-inverse); }
}

/* ── E. Шапка витрины расписания на телефоне ──
   Заголовок и ссылка стояли в одну строку через `space-between`: на 390 px
   заголовок ломался на две строки и вплотную подходил к плашке «Всё
   расписание». Ставим в столбик — строка заголовка получает всю ширину. */
@media (max-width: 767px) {
  .showcase__head { flex-direction: column; align-items: flex-start; gap: var(--s-sm); }
}


/* ═══════════════════════════════════════════════════════════
   v35 — искры «Сокровищницы». Выбор Лёши по демо /sok-glow.
   ═══════════════════════════════════════════════════════════ */

/* Правило набора прежнее: подсвечиваем только то, что на картинке УЖЕ
   нарисовано как свет. Маска вырезана из самого кадра — вспышка садится
   на светящуюся карточку и обрезается её силуэтом.

   ⚠️ Место искры задаёт МАСКА, а не проценты слоя: первый экран здесь
   `100svh`, и проценты слоя увели бы точку с предмета. `mask-size: cover`
   повторяет `object-fit: cover` картинки, `--crop` — её `object-position`. */
.subhero--splash { --crop: 50%; }
/* ⛔ Медиа-запрос обязан стоять ПОСЛЕ дефолта: при равной специфичности
   выигрывает последнее правило. Первый заход оставил `--crop: 74%` выше
   по файлу — дефолт 50% его перебил, и на телефоне сундук ушёл за кромку. */
@media (max-width: 767px) { .subhero--splash { --crop: 74%; } }
.subhero--splash .subhero__scene img { object-position: var(--crop) center; }

.sok-spark {
  /* z-index поднимает вспышку НАД затемнением первого экрана: `.subhero::after`
     идёт в потоке позже сцены и без этого гасит её. Текст остаётся выше —
     у `.subhero__body` тот же z-index, но он ниже по разметке. */
  position: absolute; inset: 0; pointer-events: none; z-index: 1;
  background: #ffeccb;
  mix-blend-mode: screen;
  opacity: 0;
  -webkit-mask-size: cover;              mask-size: cover;
  -webkit-mask-position: var(--crop) center; mask-position: var(--crop) center;
  -webkit-mask-repeat: no-repeat;        mask-repeat: no-repeat;
}
.sok-spark--1 { -webkit-mask-image: url('/images/sok-spark-1.webp'); mask-image: url('/images/sok-spark-1.webp'); }
.sok-spark--2 { -webkit-mask-image: url('/images/sok-spark-2.webp'); mask-image: url('/images/sok-spark-2.webp'); }
.sok-spark--3 { -webkit-mask-image: url('/images/sok-spark-3.webp'); mask-image: url('/images/sok-spark-3.webp'); }
.sok-spark--4 { -webkit-mask-image: url('/images/sok-spark-4.webp'); mask-image: url('/images/sok-spark-4.webp'); }

/* Вспышки идут снизу вверх — как будто содержимое поднимается из сундука. */
.subhero__scene.is-lit .sok-spark    { animation: sok-spark 1.6s ease-in-out both; }
.subhero__scene.is-lit .sok-spark--2 { animation-delay: 0.34s; }
.subhero__scene.is-lit .sok-spark--3 { animation-delay: 0.68s; }
.subhero__scene.is-lit .sok-spark--4 { animation-delay: 1.0s; }
@keyframes sok-spark {
  0%, 100% { opacity: 0; }
  42%      { opacity: 0.72; }
}
/* На телефоне кадр обрезан так, что карточки стоят прямо под текстом формы,
   и вспышка в полную силу съедала читаемость: замер по худшей точке подложки
   под самой строкой давал 2,91 → 2,50. Половинная яркость возвращает строку
   к исходному значению — вклад искр в читаемость нулевой.
   ⚠️ Отдельный набор кадров, а не var() внутри @keyframes: переменные там
   Chromium не интерполирует (грабля v31, [[reference_svg_light_layer_over_raster]]). */
@keyframes sok-spark--soft {
  0%, 100% { opacity: 0; }
  42%      { opacity: 0.34; }
}
@media (max-width: 767px) {
  .subhero__scene.is-lit .sok-spark { animation-name: sok-spark--soft; }
}
/* Страховка вторым рубежом: скрипт при reduce-motion класс не вешает вовсе. */
@media (prefers-reduced-motion: reduce) {
  .sok-spark { animation: none !important; opacity: 0 !important; }
}


/* ═══════════════════════════════════════════════════════════
   Тарифы «Практики» — карточки-предложения. 31.08.2026, выбор Лёши
   по двум демо на стенде (вариант A).

   Зачем менялось: тарифы были таблицей сравнения, а на ≤767 она
   разворачивается ПО СТРОКАМ — семь карточек-признаков, цена отдельно,
   кнопки отдельно, 1952 px до кнопки. Одно предложение приходилось
   склеивать в голове из семи кусков. Правило теперь простое:
   одно предложение — одна карточка.
   ═══════════════════════════════════════════════════════════ */

.plans {
  display: grid; gap: var(--s-md);
  grid-template-columns: repeat(3, 1fr); align-items: stretch;
}
.plans .plan {
  display: flex; flex-direction: column; gap: var(--s-sm);
  background: var(--surface-muted); border-radius: var(--r-card);
  padding: var(--s-md);
}
/* Рекомендуемый формат — на кобальте: белый на нём 13,9:1, это уже
   проверенная поверхность системы, а не новый цвет. */
.plans .plan--rec { background: var(--surface-ink); color: var(--text-inverse); }

.plan__top { display: flex; align-items: center; gap: var(--s-xs); flex-wrap: wrap; }
.plan__name { margin: 0; font-size: 1.25rem; font-weight: 500; }
.plan__badge {
  background: var(--highlight); color: #1e1e1e;
  border-radius: var(--r-pill); padding: 2px 10px;
  font-size: 0.8125rem; white-space: nowrap;
}
/* Цена набирается системным компонентом `.price` (основная гарнитура,
   табличные цифры). ⛔ Первый заход дал ей var(--font-display) — на этой паре
   это Alethia Pro, антиква для заголовков: цена сразу выпала из ряда всех
   остальных цифр сайта. Здесь только отбивка и вес. */
.plan__price { margin: 0; line-height: 1.1; font-weight: 500; }
.plan__when { margin: 0; color: var(--text-muted); }
.plan--rec .plan__when { color: var(--text-on-ink); }

.plan__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.plan__list li {
  display: grid; grid-template-columns: 18px 1fr; gap: var(--s-xs);
  align-items: start; line-height: 1.35;
}
/* Разделитель между пунктами раньше приходил из `.plan li` списка позиций —
   после разведения имён карточка держит его сама. Вид тот же, что на бою. */
.plan__list li { padding-bottom: var(--s-sm); border-bottom: 1px solid var(--border); }
.plan__list li:last-child { border-bottom: 0; padding-bottom: 0; }
.plan__list li::before { content: "✓"; color: var(--accent-deep); font-weight: 500; }
.plan--rec .plan__list li::before { color: var(--highlight); }
.plan__list li.no { color: var(--text-muted); }
.plan__list li.no::before { content: "—"; color: var(--text-muted); }
.plan--rec .plan__list li.no { color: var(--text-on-ink); }

/* Кнопка прижата к низу карточки: в ряду разной высоты они встают в одну линию. */
.plan__buy { margin-top: auto; width: 100%; }

.plans__compare { margin-top: var(--s-lg); }
.plans__compare-title {
  margin: 0 0 var(--s-sm); font-size: 1.0625rem; font-weight: 500;
  color: var(--text-muted);
}

/* ── Телефон ───────────────────────────────────────────────────────
   Таблица построчно здесь скрыта совсем: ровно она и рвала предложение
   на семь кусков. Всё, что в ней было, уже стоит внутри карточек. */
@media (max-width: 767px) {
  .plans { grid-template-columns: 1fr; }
  .plans__compare { display: none; }
  /* Рекомендуемое — первым: на телефоне порядок и есть подсказка. */
  .plans .plan--rec { order: -1; }
}
