/* ===== Шрифты =====
   Серифный — Spectral, теперь он же стоит и в макете (раньше там была
   Cambria, и кегли приходилось подгонять по ширине — больше не нужно).
   Cambria и Georgia — запасные. Наборный — Graphik LC Web. */
@font-face {
  font-family: 'Spectral';
  src: url('fonts/Spectral-Light.ttf') format('truetype');
  font-weight: 300;
  font-display: swap;
}
@font-face {
  font-family: 'Spectral';
  src: url('fonts/Spectral-Regular.ttf') format('truetype');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Spectral';
  src: url('fonts/Spectral-Medium.ttf') format('truetype');
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: 'Spectral';
  src: url('fonts/Spectral-SemiBold.ttf') format('truetype');
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: 'Spectral';
  src: url('fonts/Spectral-Bold.ttf') format('truetype');
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: 'Graphik';
  src: url('fonts/Graphik-Regular.ttf') format('truetype');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Graphik';
  src: url('fonts/Graphik-Medium.ttf') format('truetype');
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: 'Graphik';
  src: url('fonts/Graphik-Semibold.ttf') format('truetype');
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: 'Graphik';
  src: url('fonts/Graphik-Bold.ttf') format('truetype');
  font-weight: 700;
  font-display: swap;
}

/* ===== База ===== */
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body {
  /* Фон вокруг полотна. Был почти чёрным, потом светло-серым (#EBEBEB),
     сейчас снова чёрный — по просьбе автора. Белое полотно на нём и держится.
     Меняешь — проверь подвал: он лежит прямо на этом фоне, и цвет текста
     в нём подобран под него. */
  background: #000;
  color: #000;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  overflow-x: clip;
}
/* Резиновый холст. Вёрстка сделана в натуральную величину макета
   (полотно 1050), а на экран её кладёт zoom. Потолок — 1200/1050 ≈ 1.1429:
   при широком окне белое полотно занимает ровно 1200px. Внутри ничего не
   пересчитываем — всё масштабируется целиком, поэтому и не разъезжается.
   При сужении окна зум падает, тёмные поля по краям съедаются, полотно
   остаётся по центру. Точное значение выставляет скрипт в конце страницы. */
#page {
  position: relative;
  width: 1050px;
  margin: 0 auto;
  min-height: 7155px;
  padding-top: 24px;
  zoom: var(--zoom, 1.1429);
}
/* Картинки на странице все до одной декоративные: ни одна не кликается
   и не тянется. Без `pointer-events: none` браузеры вешают над ними свои
   панели — Яндекс-браузер показывает управление картинкой прямо поверх
   вёрстки. Заодно снимаем перетаскивание и выделение. */
img {
  display: block;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
}

/* Белое полотно 1050px: всё, что вылезает за него, кадрируется */
.sheet {
  position: relative;
  width: 1050px;
  height: 7048px;
  margin: 0;
  background: #fff;
  border-radius: 4px;
  /* Не режем: облако реплик нарочно вылезает за полотно вверх и по бокам,
     на серый фон. Горизонтальной полосы прокрутки от этого не будет —
     её снимает `overflow-x: clip` на `body`. На мобильном обрез остаётся:
     там полотно во всю ширину экрана, и резать нечему. */
  overflow: visible;
}
.sheet > section { position: absolute; }

/* Spectral по умолчанию ставит минускульные (разновысокие) цифры,
   а в макете цифры маюскульные — включаем их везде, где серифом набраны числа */
.badge-old, .badge-now, .buy-old, .buy-now {
  font-variant-numeric: lining-nums;
  font-feature-settings: 'lnum' 1;
}

/* ===== Типографика макета ===== */
.h1 {
  font: 300 124px/96.72px 'Spectral', Cambria, Georgia, serif;
  letter-spacing: -4.96px;
}
/* H2 — Regular, не Medium: в макете его начертание сменили. Заодно он уехал
   из ряда 500 таблицы кернинга в ряд 400, поэтому пары «Пр», «Чт», «ну», «ут»
   продублированы и там — иначе правка молча отключилась бы. */
.h2 {
  font: 400 72px/62.64px 'Spectral', Cambria, Georgia, serif;
  letter-spacing: -1.44px;
}
/* H3 в макете набран наборным, не серифом */
.h3 {
  font: 600 28px/1 'Graphik', sans-serif;
}
/* Ссылки. Подчёркивание в макете тонкое — 2,5% кегля (`decoration-[2.5%]`),
   это и есть 0.025em. Сплошное: skip-ink выключен, иначе линия рвётся
   о хвосты «р», «у» и собачку в «@tuptoppppp».
   Приглушена до 60% только сама линия, текст всегда чёрный: поэтому тут
   `text-decoration-color` с альфой, а не `opacity` — та красит элемент целиком,
   вместе с буквами. Под курсором линия доходит до цвета текста. */
.u {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 0.025em;
  text-decoration-skip-ink: none;
  text-underline-offset: 0.26em;
  text-decoration-color: rgba(0, 0, 0, 0.6);
  transition: color 0.15s ease, text-decoration-color 0.15s ease;
}
/* Под курсором — тот же красный, что у перечёркнутых ценников. Линия идёт
   за текстом через currentColor, поэтому краснеет вместе с ним. */
.u:hover { color: #bd0600; text-decoration-color: currentColor; }

/* ===== Кнопки ===== */
/* Кнопка из кита: высота задана явно (56), отбивки внутри асимметричные —
   16 сверху и 18 снизу, текст центрируется флексом. */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  height: 56px;
  padding: 16px 24px 18px;
  border-radius: 8px;
  font: 600 20px/normal 'Graphik', sans-serif;
  text-decoration: none;
  white-space: nowrap;
}
.btn-light { background: #fff; color: #000; }
.btn-light:hover { background: #ececec; }
.btn-dark { background: #000; color: #fff; }
.btn-dark:hover { background: #2b2b2b; }
/* Кнопки на лид-карточках в макете стали жёлтыми (#FEDD2D) с чёрным текстом */
.btn-yellow { background: #fedd2d; color: #000; }
.btn-yellow:hover { background: #f2cf12; }

/* ===== Хиро ===== */
.hero { top: -40px; left: 0; width: 1050px; height: 1039px; }
.hero .h1 { position: absolute; left: 32px; top: 399px; }
.hero-sub {
  position: absolute;
  left: 32px; top: 621px;
  width: 570px;
  /* Интерлиньяж 135% автор просила отдельно, а теперь он стоит и в макете:
     32,4 = 24 × 1,35, две строки дают 64,8. */
  font: 400 24px/32.4px 'Graphik', sans-serif;
}

/* Реплики из чатов.
   Плашка — ровно 280×138,5, и рисуется она одной картинкой: контур целиком
   это один путь из кита. Раньше контур собирался из border плюс треугольник
   на ::after, и в месте стыка рамка рвалась. Форм в ките две:
   `spch bbl 1` (узел 1558:3633) — хвостик снизу слева, скругление 9,9,
   `spch bbl 2` (1558:3642) — хвостик снизу справа, скругление 8,3.
   Вторая вешается классом .bbl-2, монетку бросает JS.
   Размер фиксированный, потому что картинка не тянется. */
.bubbles { position: absolute; left: 0; top: 0; width: 1050px; height: 404px; }
.bbl {
  position: absolute;
  width: 280px; height: 138.5px;
  color: #000;
  background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='280.6' height='139.285' viewBox='0 0 280.6 139.285' fill='none'%3E%3Cpath d='M0.3 8.3C0.3 5.49974 0.3 4.09961 0.844967 3.03005C1.32433 2.08924 2.08924 1.32433 3.03005 0.844967C4.09961 0.3 5.49974 0.3 8.3 0.3H272.3C275.1 0.3 276.5 0.3 277.57 0.844967C278.511 1.32433 279.276 2.08924 279.755 3.03005C280.3 4.09961 280.3 5.49974 280.3 8.3V113.3C280.3 116.1 280.3 117.5 279.755 118.57C279.276 119.511 278.511 120.276 277.57 120.755C276.5 121.3 275.1 121.3 272.3 121.3H244.8V138.8L209.8 121.3H8.29999C5.49974 121.3 4.09961 121.3 3.03005 120.755C2.08924 120.276 1.32433 119.511 0.844967 118.57C0.3 117.5 0.3 116.1 0.3 113.3V8.3Z' fill='white' stroke='black' stroke-width='0.6'/%3E%3C/svg%3E") no-repeat -0.3px -0.3px;
  background-size: 280.6px 139.285px;
  opacity: 0;
  transform: rotate(var(--rot, 0deg)) scale(0.6);
  transition: opacity 0.3s ease, transform 0.45s cubic-bezier(0.34, 1.4, 0.64, 1);
}
.bbl-2 {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='280.6' height='139.285' viewBox='0 0 280.6 139.285' fill='none'%3E%3Cpath d='M0.3 8.3C0.3 5.49974 0.3 4.09961 0.844967 3.03005C1.32433 2.08924 2.08924 1.32433 3.03005 0.844967C4.09961 0.3 5.49974 0.3 8.3 0.3H272.3C275.1 0.3 276.5 0.3 277.57 0.844967C278.511 1.32433 279.276 2.08924 279.755 3.03005C280.3 4.09961 280.3 5.49974 280.3 8.3V113.3C280.3 116.1 280.3 117.5 279.755 118.57C279.276 119.511 278.511 120.276 277.57 120.755C276.5 121.3 275.1 121.3 272.3 121.3H244.8V138.8L209.8 121.3H8.29999C5.49974 121.3 4.09961 121.3 3.03005 120.755C2.08924 120.276 1.32433 119.511 0.844967 118.57C0.3 117.5 0.3 116.1 0.3 113.3V8.3Z' fill='white' stroke='black' stroke-width='0.6'/%3E%3C/svg%3E");
}
.bbl.in { opacity: 1; transform: rotate(var(--rot, 0deg)) scale(1); }
/* плашку можно взять мышью и переложить */
/* `touch-action: none` — чтобы плашку можно было тянуть пальцем: без него
   браузер забирает жест себе под прокрутку, и pointermove до нас не доходит.
   Стоит только на самой плашке, поэтому страница по-прежнему листается
   с промежутков между ними и со всего, что ниже облака. */
.bbl { cursor: grab; user-select: none; touch-action: none; }
.bbl.held { cursor: grabbing; }
/* события ловит сама плашка, а не текст с иконкой внутри — иначе браузер
   норовит начать своё перетаскивание картинки */
.bbl * { pointer-events: none; }
.bbl p {
  position: absolute;
  left: 17.81px; top: 16px;
  width: 248px; height: 72px;
  overflow: hidden;
  font: 400 15px/1.25 'Graphik', sans-serif;
  letter-spacing: -0.15px;
}
.bbl-foot {
  position: absolute;
  left: 17.81px; top: 88px;
  width: 248px;
  display: flex; align-items: center; justify-content: space-between;
}
/* Иконка в ките залитая, без кружка; габарит 24 по высоте, а по ширине
   чуть больше — картинка свисает влево на полпикселя.

   В самих файлах вьюбокс расширен на 1 с каждой стороны: у всех трёх иконок
   контур доходил ровно до края, и на рендере их срезало (у огня — заметно,
   вертикальным сколом справа). Отрицательные поля возвращают эту единицу
   обратно, поэтому рисунок стоит там же и того же размера, что и раньше:
   габарит 26, из него 24 — сама иконка. */
.bbl-foot img { height: 26px; width: auto; margin: -1px 0 -1px -1.4px; }
.bbl-foot time { font: 400 13px/1.25 'Graphik', sans-serif; }
@media (prefers-reduced-motion: reduce) {
  .bbl { transition: none; }
}

/* ===== Лид-карточка в хиро =====
   Плашка 308×292 с текстурной подложкой (узел 1958:792). Зубцы сверху и снизу
   зашиты в саму картинку; в PNG они прозрачные, но полотно под карточкой белое,
   поэтому держим JPEG с белой подложкой — он вчетверо легче.
   Координаты внутри хиро равны макетным: сама секция уже сдвинута на −40,
   поэтому второй раз вычитать не надо. */
/* z-index обязателен: вступление стоит на той же высоте, и его прозрачный бокс
   во всю колонку лежит поверх плашки — без подъёма кнопка не нажимается. */
.badge { position: absolute; z-index: 2; left: 710px; top: 747px; width: 308px; height: 292px; }

/* ===== Текстура с параллаксом =====
   Внутри обеих плашек фон едет при скролле. Для этого текстура выгружена
   удлинённой (узлы 1964:820 и 1966:867: 308×530 и 986×654 против 308×292
   и 986×406) и двигается трансформом — запас по высоте и есть ход
   параллакса: 238 и 248.

   Зубцы по краям раньше были зашиты в саму картинку; теперь картинка
   прямоугольная и ездит, поэтому контур задан **маской** — это альфа той же
   векторной выгрузки, что рисовала зубцы, белым по прозрачному. Маска
   тянется на весь контейнер (`100% 100%`), так что зубцы не плывут.

   **Обрезает тоже маска, а не `overflow: hidden`.** Вне своей картинки маска
   пуста, то есть всё, что вылезло за бокс, и так не рисуется. А `overflow:
   hidden` делает контейнер скролл-контейнером — и тогда `animation-timeline:
   view()` считает путь текстуры **внутри него**, а не по странице,
   и параллакс не запускается вовсе.

   Трансформ по умолчанию ставит текстуру серединой хода: так плашка выглядит
   верно и до того, как отработает анимация, и при `prefers-reduced-motion`. */
.badge-bg, .buy-bg {
  position: absolute;
  left: 0; top: 0;
}
.badge-bg > i, .buy-bg > i {
  display: block;
  position: absolute;
  left: 0; top: 0;
  width: 100%;
  background: no-repeat 0 0 / 100% 100%;
  will-change: transform;
}

/* Ход считает сам браузер по таймлайну прокрутки: `view()` — это путь элемента
   через экран, от «показался снизу» до «ушёл за верх», ровно то окно, которое
   раньше считал скрипт. Разница в том, что такая анимация живёт в компоновщике
   и идёт кадр в кадр с прокруткой. Скрипт двигал трансформ из главного потока,
   и фон то отставал, то догонял; глушить рывки коротким `transition` оказалось
   ещё хуже — параллакс поехал следом за страницей с заметной задержкой.

   `ease-in-out` тут — кривая по таймлайну, а не по времени: у краёв производная
   нулевая, поэтому текстура не трогается рывком и так же мягко встаёт, а вся
   скорость приходится на середину прохода.

   Скрипт «ПАРАЛЛАКС ТЕКСТУР» остаётся для браузеров без таймлайнов (Firefox):
   он сам проверяет поддержку и в Chromium не вмешивается. */
@keyframes plate-parallax {
  from { transform: translate3d(0, var(--par-from), 0); }
  to   { transform: translate3d(0, 0, 0); }
}
@supports (animation-timeline: view()) {
  .badge-bg > i, .buy-bg > i {
    animation-name: plate-parallax;
    animation-timing-function: ease-in-out;
    animation-fill-mode: both;
    animation-timeline: view();
    animation-range: cover 0% cover 100%;
  }
}
@media (prefers-reduced-motion: reduce) {
  .badge-bg > i, .buy-bg > i { animation-name: none; }
}
.badge-bg {
  width: 308px; height: 292px;
  -webkit-mask: url('assets/plate-badge-mask.png') 0 0 / 100% 100% no-repeat;
          mask: url('assets/plate-badge-mask.png') 0 0 / 100% 100% no-repeat;
}
.badge-bg > i {
  height: 530px;
  --par-from: -238px;
  background-image: url('assets/plate-badge.jpg');
  transform: translate3d(0, -119px, 0);
}
/* Текст выключен влево по колонке 268 с отбивкой 20 от края карточки. */
.badge-head {
  position: absolute;
  left: 20px; top: 29px;
  width: 268px;
  color: #fff;
}
/* Первая строка наборная, остальные — сериф: так в макете. Обе на одном
   интерлиньяже 1,15, поэтому строки идут сплошным блоком. */
.badge-lead { font: 600 18px/20.7px 'Graphik', sans-serif; letter-spacing: 0.02em; }
.badge-note { font: 600 18px/20.7px 'Spectral', Cambria, Georgia, serif; }
.badge-old, .badge-now {
  position: absolute;
  left: 20px;
  color: #fff;
}
/* Приглушена только цена: перечёркивание рисуется поверх и остаётся жёлтым,
   поэтому тут альфа в цвете, а не `opacity` — та красит и псевдоэлемент. */
/* Перечёркивание — настоящая линия текста, а не псевдоэлемент на фиксированных
   координатах. Так браузер сам ставит её по метрикам шрифта и по ширине цифр:
   линия всегда идёт серединой цены и кончается ровно на последней цифре.
   Раньше это был `::after` с `top: 10px` и шириной 57 — пока рисовался Spectral,
   он попадал в середину, но стоило шрифту не загрузиться и подставиться Cambria
   (у неё цифры сидят ниже), как линия уезжала к верхушкам цифр.
   Толщина — ровно 1px на обеих плашках: по макету выходило 1 и 1,6 (там это
   0,05 кегля), но автор попросила одинаковую линию. */
.badge-old {
  top: 130px; width: max-content;
  font: 500 20px/21.6px 'Spectral', Cambria, Georgia, serif;
  color: rgba(255, 255, 255, 0.5);
  text-decoration: line-through;
  text-decoration-color: #fedd2d;
  text-decoration-thickness: 1px;
}
/* У Фигмы бокс крупной цены обрезан по прописной (`text-box-trim`), то есть
   154 — это верх краски. В CSS бокс полный, поэтому вычитаем расстояние
   от верха строки до прописной: (1 − 1,522)/2 + 1,059 − 0,66 = 0,138 em,
   при кегле 60 это 8,28. */
.badge-now {
  top: 145.7px; width: 223px;
  font: 400 60px/1 'Spectral', Cambria, Georgia, serif;
}
/* Пробел перед рублём в макете уже, чем даёт обычный: там он набран спаном
   другого начертания, и один к одному в CSS не переводится. Подтягиваем
   по рендеру — замер по колонкам краски даёт 6px при кегле 60 и 9px при 98. */
.badge-now .rub { font-size: 40px; letter-spacing: -0.8px; margin-left: -7px; }
.badge .btn { position: absolute; left: 20px; top: 214px; width: 268px; }

/* ===== Вступление с буквицей =====
   После редизайна это просто текст на белом: чёрной карточки, красного уголка
   и скрепки больше нет. Буквица вылезает за колонку влево на 17 — так в макете
   (узел 2001:733 стоит на x = −17 внутри колонки 986).

   **Буквица стоит на базовой линии первой строки**, а не по верху блока:
   автор выровняла её так в макете. Координата не подбиралась, а посчитана
   из метрик — базовая линия внутри строчного бокса лежит на
   `(интерлиньяж − (восходящая + нисходящая) × кегль) / 2 + восходящая × кегль`:
   у буквицы это 85,31 (Spectral 124/96,72), у первой строки 21,36
   (Graphik 20/27) от её верха на 86,15, то есть базовая на 107,51.
   Разница и даёт 22,2 — в Фигме у этого блока ровно 22. */
.intro { top: 707px; left: 32px; width: 986px; height: 291px; }
.intro-cap {
  position: absolute;
  left: -7px; top: 21.2px;
  font: 300 124px/96.72px 'Spectral', Cambria, Georgia, serif;
  letter-spacing: -4.96px;
}
/* Первая строка обтекает буквицу, остальные идут от левого края колонки.
   Шаг между ними ровно одна строка (27), поэтому абзац читается слитно. */
.intro-first {
  position: absolute;
  left: 79px; top: 86.15px;
  width: 487px;
  font: 500 20px/1.35 'Graphik', sans-serif;
}
.intro-rest {
  position: absolute;
  left: 0; top: 113px;
  width: 620px;
  font: 500 20px/1.35 'Graphik', sans-serif;
}
.intro-rest p + p { margin-top: 8px; }

/* ===== Программа ===== */
.program { top: 1088px; left: 32px; width: 986px; height: 1856px; }
/* Заголовок сдвинут на 5 влево: так автор выровняла его `П` по левому краю
   колонки — у серифа своя боковая полуапрошь, и без поправки заголовок
   казался отодвинутым от разделителя под ним (узел 2319:15658, x = −5). */
.program .h2 { margin: 0 0 40px -5px; }
.sprint { position: absolute; left: 0; width: 986px; }
.sprint:nth-of-type(1) { top: 103px; }
.sprint:nth-of-type(2) { top: 780px; }
.sprint:nth-of-type(3) { top: 1546px; }
.sprint .h3 {
  margin-top: 12px;
  padding-bottom: 32px;
  border-top: 0;
}
/* Разделитель во всю колонку 986 (раньше был 980) и волосяной: в макете это
   обводка 0,6, а не линия в пиксель. Хром рисует её как один ряд с альфой. */
.sprint::before {
  content: '';
  display: block;
  width: 986px; height: 0.6px;
  background: #000;
}
/* Третья колонка в каждом спринте — фотография, поэтому колонки разводит
   `space-between` по всей ширине 986, а не фиксированный зазор: у текстовых
   колонок он выходит 25, у картинки свой остаток. Отбивки слева больше нет —
   в `2087:1890` колонки стоят на 0, 337 и 674. */
.sprint-cols {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}
.sprint-col { width: 312px; display: flex; flex-direction: column; gap: 20px; }
/* В третьем спринте текстовые колонки сгруппированы и стоят в 20 друг от друга */
.sprint-pair { display: flex; gap: 20px; }
.sprint-pic { width: 312px; }
.sprint-pic-1 { height: 559px; }
.sprint-pic-2 { height: 615px; }
.sprint-pic-3 { height: 238px; }
.grp { display: flex; flex-direction: column; gap: 5px; }
/* .grp p бьёт .grp-t по специфичности (0,1,1 против 0,1,0), поэтому заголовок
   группы задаём селектором из двух классов — иначе он теряет Semibold и
   выглядит так же, как пункты внутри. Опорный класс тут .sprint-col, а не .grp:
   последний заголовок в третьем спринте («Итоги проекта и обратная связь»)
   в макете лежит прямо в колонке, без группы, и под .grp .grp-t не попадал —
   оставался браузерным сериф-дефолтом, потому что font-family на body не задан. */
/* Пункты 16, заголовки групп 19 — кегли в программе автор уже меняла
   дважды, сверяйся с макетом. Интерлиньяж у обоих 1.2. */
.grp p { font: 400 16px/1.2 'Graphik', sans-serif; }
.sprint-col .grp-t { font: 600 19px/1.2 'Graphik', sans-serif; }
/* То, что ещё не вышло — во всех спринтах одинаково, 40%. В макете у третьего
   спринта осталось 50, но автор попросила свести к одному значению. */
.later { opacity: 0.4; }

/* Бирки «Скоро» и «Бесплатно»: красный контур 0,6 со скруглением 4.
   Отбивки внутри асимметричные — 1 сверху и 3 снизу, как в макете.

   Бирка у заголовка спринта стоит рядом с ним и выравнивается по низу
   (ряд в макете с `items-end`), а бирка у заголовка группы — инлайновая:
   заголовок её обтекает и переносится на вторую строку. Поэтому у второй
   `vertical-align` и отбивка справа, а не флексовый зазор. */
.tag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 26px;
  padding: 1px 8px 3px;
  border: 0.6px solid #bd0600;
  border-radius: 4px;
  font: 400 16px/1.35 'Graphik', sans-serif;
  color: #bd0600;
  white-space: nowrap;
}
.sprint .h3 { display: flex; align-items: flex-end; gap: 8px; }
/* «Бесплатно» в макете зелёная, «Скоро» — красная */
.tag-free { border-color: #39a300; color: #39a300; }
/* Бирка в строке заголовка задаёт высоту этой строки: 26 своих плюс
   поля. Отрицательная отбивка −1 как раз даёт макетные 44,5 на двух
   строках (без неё 46,7) — замерено по живому заголовку. */
.sprint-col .grp-t .tag { margin: -1px 0 -1px 5px; vertical-align: middle; }

/* ===== Что внутри ===== */
.inside { top: 3034px; left: 32px; width: 986px; height: 878px; }
.inside .h2 { margin-bottom: 24px; }
.inside-lead {
  width: 574px;
  font: 500 20px/1.35 'Graphik', sans-serif;
}
/* Скриншот урока: в макете у него скругление 12 и волосяная рамка
   rgba(34,34,34,.15). Рамка в Фигме внутренняя, поэтому тут `border-box` —
   иначе картинка станет 988 и уедет от правого края колонки.

   Скриншотов четыре (узлы в секции `2609:18346`), и они лежат стопкой
   в `.inside-shots`: по скроллу видно тот, чей интервал сейчас идёт.
   Переключает их скрипт «СКРИНШОТЫ В «ЧТО ВНУТРИ»».

   Смена мгновенная: перехода по `opacity` тут был 0,35s, автор попросила
   убрать. Раз анимации нет, не нужна и ветка на `prefers-reduced-motion`. */
.inside-shots {
  position: absolute;
  left: 0; top: 208px;
  width: 986px; height: 670px;
}
.inside-shot {
  position: absolute;
  left: 0; top: 0;
  width: 100%; height: 100%;
  box-sizing: border-box;
  border: 1px solid rgba(34, 34, 34, 0.15);
  border-radius: 12px;
  opacity: 0;
}
.inside-shot.is-on { opacity: 1; }
/* Значок Степика: повёрнутый скруглённый квадрат, фон вокруг прозрачный.
   В Фигме это картинка в повёрнутой маске, и экспорт её обрезки приходит
   битым — поэтому фон выбит заливкой от краёв (белая «S» внутри осталась).
   Габарит 220,4 — это сторона 156 со скруглением 55,5, повёрнутая на 47,73°
   (156 × (cos 47,73° + sin 47,73°)); значок автор увеличила вместе
   со сменой скриншота. */
.inside-doodle {
  position: absolute;
  left: 725.61px; top: 87.75px;
  width: 220.37px; height: 220.37px;
}
/* ===== Для практики понадобятся =====
   После редизайна чёрной полосы с уголками тут нет — просто две колонки
   текста на белом, 456 и 477 в колонке 986, зазор 53.
   Стиль «soft&availability» из макета: Graphik Regular 32, интерлиньяж 1.02.
   Строки в Фигме разложены по 33px с зазором 5, поэтому тут шаг 38. */
.practice { top: 3972px; left: 32px; width: 986px; height: 147px; }
.inside-notes {
  position: absolute;
    /* Фигма стопит строки боксами по 32,64 с зазором 5,36, а у нас шаг задан
     интерлиньяжем 38 — браузер делит этот зазор пополам и опускает весь блок
     на 2,68. Возвращаем его обратно, иначе все четыре строки ниже макета. */
  left: 0; top: -2.68px;
  display: flex; gap: 53px;
  font: 400 32px/38px 'Graphik', sans-serif;
  letter-spacing: -0.32px;
}
.inside-note:first-child { width: 456px; }
.inside-note:last-child { width: 477px; }
/* В макете верх иконки совпадает с верхом строки (ряд с items-start),
   а строка — это кегль × 1.02. Отсюда и сдвиг: базовая линия Graphik лежит
   на 28,9px ниже верха такой строки, иконка 32px → её низ на 3,1px ниже
   базовой линии. Подбирать на глаз не нужно, всё считается из метрик шрифта:
   восходящая 0.981 em, сумма восходящей и нисходящей 1.176 em. */
.app {
  display: inline-block;
  width: 32px; height: 32px;
  vertical-align: -3.1px;
  /* Подложка со скруглением впечатана в сами картинки — автор прислала их
     отдельным узлом (1772:531), с прозрачными углами. Ни фона, ни радиуса
     в CSS не нужно. */
  /* зазоры из автолейаута: 6 до иконки, 3 после */
  margin: 0 3px 0 6px;
}
/* Бесконечность нарисована чёрным контуром — на белом она и нужна чёрной */
.inf {
  display: inline-block;
  width: 49px; height: 33px;
  vertical-align: -4.1px;
  margin-right: 3px;
}

/* ===== Авторы ===== */
.authors { top: 4209px; left: 32px; width: 986px; height: 527px; }
.authors .h2 { margin-bottom: 40px; }
.authors-row { display: flex; gap: 44px; }
.author { width: 292px; }
.author-wide { width: 312px; }
.author-pic { position: relative; width: 292px; height: 288px; }
.author-pic > img {
  width: 288px; height: 288px;
  margin-left: 1px;
  border-radius: 50%;
  object-fit: cover;
}
/* От низа кружка до подписи 28: подпись в макете стоит на 419 от верха
   секции, кружок на 103, высота кружка 288. */
/* Подпись — стиль «Desktop/text light», то есть Regular, а не Medium:
   у нас тут долго стояло 500, и на мобильном это гасилось переопределением.
   Теперь вес один на оба экрана, как в макете (узел 2087:2066). */
.author p {
  margin-top: 28px;
  width: 300px;
  font: 400 20px/1.35 'Graphik', sans-serif;
}
/* Полужирное имя — Semibold, а у него свои вертикальные метрики: нижний
   выносной элемент уходит ниже, чем у наборного веса, и первая строка
   подписи становится на 2px выше остальных. Интерлиньяж 1 прижимает
   инлайновый бокс имени внутрь строки, которую задаёт сам абзац. */
.author p b { font-weight: 600; line-height: 1; }

/* Кружок с видео */
.video-circle {
  position: absolute;
  left: 1px; top: 0;
  width: 288px; height: 288px;
  cursor: pointer;
}
.video-circle video {
  /* video по умолчанию инлайновый, и под ним остаётся место под базовую
     линию — кружок становится на 4px выше видео. */
  display: block;
  width: 100%; height: 100%;
  border-radius: 50%;
  object-fit: cover;
}
/* Таймбар по киту: бледная окружность целиком, поверх неё яркая дуга
   пройденного и белый узелок на её конце. Радиус 134,62 — это 9,38 внутрь
   от края кружка, как в ките. */
.video-circle .ring {
  position: absolute; inset: 0;
  width: 288px; height: 288px;
  pointer-events: none;
  overflow: visible;
}
.video-circle .ring circle {
  fill: none;
  stroke: #fff;
  stroke-width: 2;
}
.video-circle .ring .ring-bg { opacity: 0.41; }
.video-circle .ring .ring-bar {
  stroke-linecap: round;
  stroke-dasharray: 100 100;
  stroke-dashoffset: 100;
  transform: rotate(-90deg);
  transform-origin: 144px 144px;
  transition: stroke-dashoffset 0.28s linear;
}
/* Узелок едет по окружности поворотом вокруг центра: 0° — двенадцать часов.
   Прозрачная обводка 16px — это зона захвата: сам узелок 12px, в такой
   курсором ещё попадёшь, а пальцем уже нет. pointer-events: all нужен
   потому, что обводка прозрачная, иначе события по ней не ловятся. */
.video-circle .ring .ring-knob {
  fill: #fff;
  stroke: transparent;
  stroke-width: 16;
  pointer-events: all;
  touch-action: none;
  cursor: grab;
  transform: rotate(var(--p, 0deg));
  transform-origin: 144px 144px;
  transition: transform 0.28s linear, opacity 0.2s ease;
  filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.5));
}
/* Где есть курсор — узелок показываем только при наведении на кружок
   и пока его тащат. На тач-экранах наведения нет, там он виден всегда. */
@media (hover: hover) {
  .video-circle .ring .ring-knob { opacity: 0; }
  .video-circle:hover .ring .ring-knob,
  .video-circle.scrubbing .ring .ring-knob { opacity: 1; }
}
/* на перемотке плавность только мешает — узелок должен идти за курсором */
.video-circle.scrubbing .ring .ring-bar,
.video-circle.scrubbing .ring .ring-knob { transition: opacity 0.2s ease; }
.video-circle.scrubbing .ring .ring-knob { cursor: grabbing; }
.video-circle .icon-play {
  position: absolute;
  left: 114px; top: 114px;
  width: 60px; height: 60px;
  pointer-events: none;
  visibility: hidden;
}
/* Треугольник виден не только на паузе, но и пока ролик идёт без звука:
   кружок запускается сам и молча, и это единственный знак, что его можно
   нажать и посмотреть со звуком. */
.video-circle.paused .icon-play,
.video-circle.silent .icon-play { visibility: visible; }

/* ===== Телеграм-канал ===== */
/* Карточка целиком — одна картинка из макета: в ней и рамка с зубцами,
   и телефон. Раньше рамка рисовалась CSS'ом, а фото накладывалось отдельно,
   и после правок макета фото перестало совпадать с рамкой. Прозрачность
   не нужна, потому что полотно под карточкой белое. У мобильного своя
   картинка — она уже, выше и телефон в ней стоит иначе; выбирает `<picture>`. */
.tg { top: 4826px; left: 32px; width: 986px; height: 440px; background: #fff; }
/* обёртка picture ничего не рисует, но инлайновый бокс добавил бы строку —
   делаем её блочной, а картинка внутри всё равно позиционирована */
.tg picture { display: block; }
.tg-card { position: absolute; left: 0; top: 0; width: 986px; height: 440px; }
/* Regular, не Bold: автор облегчила заголовок вслед за надзаголовком
   «Курс» в финальной плашке. Трекинг макетный, −1.2. */
.tg-title {
  position: absolute;
  left: 32px; top: 46px;
  width: 526px;
  font: 400 60px/1 'Spectral', Cambria, Georgia, serif;
  letter-spacing: -1.2px;
}
.tg-text {
  position: absolute;
  left: 32px; top: 190px;
  width: 526px;
  font: 500 20px/1.35 'Graphik', sans-serif;
}
.tg .btn { position: absolute; left: 32px; top: 324px; }

/* ===== Вопросы ===== */
.faq { top: 5356px; left: 32px; width: 986px; height: 640px; }
.faq .h2 { margin-bottom: 40px; }
.faq-item { margin-bottom: 32px; }
.faq-item .h3 { margin-bottom: 8px; }
.faq-item p {
  width: 640px;
  font: 400 20px/1.35 'Graphik', sans-serif;
}
/* В макете у каждого ответа своя ширина — от неё зависит, где рвётся строка.
   Высоты блоков (54 / 81 / 108 / 54) из этого и складываются. */
.faq-item:nth-of-type(1) p { width: 538px; }
.faq-item:nth-of-type(2) p { width: 518px; }
.faq-item:nth-of-type(3) p { width: 500px; }
.faq-item:nth-of-type(4) p { width: 396px; }

/* ===== Финальный блок: плашка с ценой =====
   Конверта, письма, печати и образцов печати больше нет — после редизайна это
   текстурная плашка 986×406 (узел 1850:2981) с зубцами по верху и низу,
   зашитыми в саму картинку, и жёлтой кнопкой. Под ней таймлайн.
   `top` секции — это верх плашки: бокс `1850:2979` в Фигме стоит на 18 ниже,
   потому что внутри него плашка сдвинута на −18. */
.buy { top: 6086px; left: 32px; width: 986px; height: 560px; }
.buy-card { position: relative; width: 986px; height: 406px; color: #fff; }
.buy-bg {
  width: 986px; height: 406px;
  -webkit-mask: url('assets/plate-buy-mask.png') 0 0 / 100% 100% no-repeat;
          mask: url('assets/plate-buy-mask.png') 0 0 / 100% 100% no-repeat;
}
.buy-bg > i {
  height: 654px;
  --par-from: -248px;
  background-image: url('assets/plate-buy.jpg');
  transform: translate3d(0, -124px, 0);
}
.buy-kicker, .buy-title, .buy-text, .buy-head, .buy-old, .buy-now { position: absolute; }
.buy-kicker {
  left: 53px; top: 52px;
  /* Regular и без трекинга — по просьбе автора: в макете тут Medium −0.52,
     но на рендере начертание спорило с заголовком под ним. */
  font: 400 26px/25.22px 'Spectral', Cambria, Georgia, serif;
}
.buy-title {
  left: 53px; top: 91px;
  width: 510px;
  font: 400 88px/72.16px 'Spectral', Cambria, Georgia, serif;
  letter-spacing: -1.76px;
}
.buy-text {
  left: 53px; top: 259px;
  width: 460px;
  font: 400 24px/1.15 'Graphik', sans-serif;
}
/* Правая колонка: подзаголовок, цена, кнопка — все от 637 */
.buy-head { left: 637px; top: 54px; width: 265px; }
.buy-lead { font: 600 16px/19.2px 'Graphik', sans-serif; letter-spacing: 0.01em; }
.buy-note { font: 600 16px/19.2px 'Spectral', Cambria, Georgia, serif; }
/* Как и в лид-карточке: приглушён только текст цены, линия поверх остаётся
   жёлтой, поэтому альфа в цвете, а не `opacity`. */
/* Перечёркивание тут устроено так же, как в лид-карточке: линия текста,
   а не псевдоэлемент, и той же толщины — 1px. */
.buy-old {
  left: 637px; top: 137px;
  width: max-content;
  font: 400 32px/1 'Spectral', Cambria, Georgia, serif;
  color: rgba(255, 255, 255, 0.5);
  text-decoration: line-through;
  text-decoration-color: #fedd2d;
  text-decoration-thickness: 1px;
}
/* Бокс крупной цены в Фигме обрезан по прописной: 161 от верха плашки —
   это верх краски, а не верх строки. Вычитаем 0,138 em (при 98 это 13,52). */
.buy-now {
  left: 637px; top: 165.5px;
  width: 280px;
  font: 400 98px/1 'Spectral', Cambria, Georgia, serif;
}
.buy-now .rub { font-size: 64px; letter-spacing: -1.28px; margin-left: -12px; }
.buy-card .btn { position: absolute; left: 637px; top: 262px; width: 265px; }

/* Таймлайн */
.when { position: absolute; left: 0; top: 446px; width: 986px; height: 114px; }
/* Линия со стрелкой и засечками — одной картинкой из макета (Footer Line).
   Засечки там торчат по 10px вверх и вниз от линии, поэтому картинка
   начинается на 20,4 выше верха блока. */
.when-line {
  position: absolute;
  left: 0; top: -2.45px;
  width: 988px; height: 27px;
  background: url('assets/timeline-line.svg') no-repeat;
}
.when-col { position: absolute; top: 35px; width: 230px; }
.when-col:nth-of-type(2) { left: 0; }
.when-col:nth-of-type(3) { left: 254px; }
.when-col:nth-of-type(4) { left: 508px; }
.when-col:nth-of-type(5) { left: 762px; }
.when-date { font: 400 16px/1.2 'Graphik', sans-serif; }
.when-what { margin-top: 3px; font: 700 18px/1.35 'Graphik', sans-serif; }
.when-date + .when-what { margin-top: 6px; }

/* ===== Если пока не определились ===== */
.undecided { top: 6736px; left: 32px; width: 986px; height: 204px; }
.undecided .h2 { margin-bottom: 24px; }
.undecided p {
  width: 571px;
  font: 500 20px/1.35 'Graphik', sans-serif;
}

/* ===== Подвал ===== */
/* Подвал лежит на фоне под полотном, и до него от полотна 32px.
   Координата тут **от верха `#page`**, а у полотна своя система — оно стоит
   в потоке за `padding-top: 24`. Значит `top` подвала = 24 + высота полотна
   + 32, и забыть эти 24 легко: один раз так и вышло, зазор стал 8 вместо 32. */
.site-footer {
  position: absolute;
  left: 0; top: 7104px;
  width: 1050px;
  display: flex; align-items: center; justify-content: space-between;
  font: 400 15px/1.25 'Graphik', sans-serif;
  /* Белый, как в макете: там подвал побелел вместе с фоном, который стал
     чёрным. До этого он был чёрным на светлом, и у нас стоял серый —
     компромисс, который теперь не нужен. */
  color: #fff;
}
.foot-left { display: flex; gap: 20px; align-items: center; }
/* Единственная ссылка в подвале — политика конфиденциальности. Раньше тут
   стояли неактивные «Оферта» и «Оплата и возврат»; в макете их больше нет.
   Оформление то же, что у ссылок в тексте, только линия белая на чёрном. */
.foot-link {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 0.025em;
  text-decoration-skip-ink: none;
  /* Отбивка тут своя, 0.3em вместо 0.26: белая линия на чёрном зрительно
     липнет к буквам сильнее, чем чёрная на белом, и при 15px её надо
     отодвинуть. Приглушена, как и у ссылок в тексте, только линия — сам
     текст остаётся белым: `opacity` на всём блоке гасила бы и буквы, и линия
     от этого выходила заметно жирнее, чем везде. */
  text-underline-offset: 0.3em;
  text-decoration-color: rgba(255, 255, 255, 0.6);
  transition: text-decoration-color 0.15s ease;
}
/* Красный ховер остальных ссылок на чёрном не читается, поэтому тут линия
   просто доходит до цвета текста. */
.foot-link:hover { text-decoration-color: currentColor; }

/* ===== Страница «Политика конфиденциальности» (макет 2319:15970) =====
   Тут, в отличие от главной, всё в потоке: страница — это один столбец
   текста, и её высота зависит от того, как лягут строки. Поэтому и полотно,
   и подвал высоту не фиксируют, а считаются сами; от макета берутся только
   отбивки. Поправки −40, как на главной, здесь нет — автор собрала фрейм
   заново, и координаты в нём свои. */
/* Под подвалом те же 32 фона, что на главной; там их держит min-height,
   а тут высоту задаёт контент — значит, отбивкой. */
#page.privacy { min-height: 0; padding-bottom: 32px; }
/* Колонка контента 986 задана отбивками полотна: 32 по бокам, 42 сверху
   до заголовка и 104 снизу — последнее из макета (полотно 3330, низ
   контента 3226). */
.privacy .sheet {
  height: auto;
  padding: 42px 32px 102px;
}
/* Заголовок рвётся на две строки, как в макете: ширины колонки хватило бы
   и на одну, а бокс там 126 — ровно два интерлиньяжа.
   **Трекинг тут против макета.** В Фигме у этого заголовка он нулевой —
   сверено по краске, «конфиденциальности» в рендере макета 712 пикселей,
   а с трекингом выходит 688, ровно 17 просветов по 1,44. Но автор попросила
   его подобрать, и заголовок встал в общий ряд: те же −2%, что у H2
   на главной. Задано в em, а не в пикселях, чтобы работало и на мобильном,
   где кегль тут свой (32). */
.pp-title { width: 986px; letter-spacing: -0.02em; }
/* Волосяная линия, как разделитель спринта в программе. Отбивка сверху —
   это 351 (линия) минус низ заголовка 167,28 (42 + два раза 62,64). */
.pp-rule {
  width: 986px; height: 0.6px;
  margin-top: 183.72px;
  background: #000;
}
/* Колонка текста 760, между разделами 48, внутри раздела 16 */
.pp-body {
  width: 760px;
  margin-top: 63.4px;
  display: flex; flex-direction: column; gap: 48px;
}
.pp-sec { display: flex; flex-direction: column; gap: 16px; }
/* Вводная фраза и список — один блок: по совету Бюро (bureau.ru/soviet/20220608)
   вводное предложение прижимается к первому пункту, чтобы было видно их связь.
   В макете это отдельные фреймы (2356:4141, 4140, 4143) с зазором 6. Список,
   который идёт сразу за заголовком раздела (третий раздел), в такой блок
   не завёрнут — там обычные 16. */
.pp-lead { display: flex; flex-direction: column; gap: 6px; }
.pp-sec p { font: 400 20px/1.35 'Graphik', sans-serif; }
/* Ссылка на отказ от Метрики — длинный адрес одним словом. На десктопе он
   в колонку 760 помещается, на мобильном нет, поэтому разрешаем ему рваться
   в любом месте: иначе он вылезет за колонку и полотно его срежет. */
.pp-sec a { overflow-wrap: anywhere; }
/* Список отмечен втяжкой, без маркеров: тире из макета убрано, пункты просто
   отодвинуты на 14 с обеих сторон (в Фигме это `px-[14px]` у блока списка).
   Между пунктами 6. По совету Бюро расстояние между пунктами должно быть
   больше межстрочного в сплошном тексте и чуть меньше, чем между абзацами:
   на десктопе от строки к строке 27, между пунктами 33, между абзацами 43;
   на мобильном 21,6 / 27,6 / 37,6. */
.pp-list {
  display: flex; flex-direction: column; gap: 6px;
  padding: 0 14px;
}
.pp-back {
  display: inline-block;
  margin-top: 60px;
  font: 500 20px/1.35 'Graphik', sans-serif;
}
/* Подвал тут в потоке: высоту полотна заранее не знаем, а зазор до него
   тот же, что на главной, — 32. */
.privacy .site-footer {
  position: static;
  margin-top: 32px;
}

/* ============================================================
   МОБИЛЬНАЯ РАСКЛАДКА (макет 375px)
   Жёсткий холст 1440 остаётся десктопу; на телефоне отдаём
   обычный поток в одну колонку. Переключение — скриптом в <head>,
   который меняет meta viewport по ширине экрана.
   ============================================================ */
@media (max-width: 759px) {
  /* Мобильная вёрстка тоже в натуральную величину макета (колонка 343
     в холсте 375), на экран её кладёт тот же zoom, что и десктоп. Потолок
     1.2: до 450px ширины макет масштабируется один в один, дальше масштаб
     стоит, а холст становится шире — раскладка тут поточная и лишнюю
     ширину разбирает сама. Значения считает скрипт «АВТОСКЕЙЛ ХОЛСТА»,
     в CSS лежат дефолты на случай отключённого JS. */
  #page {
    zoom: var(--zoom, 1);
    width: var(--page-w, 100%);
    min-height: 0;
    padding-top: 16px;
  }
  .sheet {
    width: 100%;
    height: auto;
    margin: 0;
    overflow: hidden;
    /* от низа контента до подвала 130: 102 тут и 28 в отбивке подвала */
    padding-bottom: 102px;
  }
  .sheet > section,
  .sheet > .hero {
    position: static;
    width: auto;
    height: auto;
    margin: 0 16px;
    z-index: auto;
  }

  /* Сбрасываем десктопные координаты у того, что на мобильном идёт в поток.
     Плашки (лид-карточка и финальная) и таймлайн внутри себя остались
     абсолютными — в макете они так и свёрстаны, только уже. */
  .intro-first, .intro-rest,
  .inside-shots,
  .tg-title, .tg-text, .tg .btn,
  .when, .sprint, .video-circle, .bubbles, .site-footer {
    left: auto; top: auto; right: auto; bottom: auto;
  }

  /* перенос строки, который нужен только широкому экрану */
  .wide-only { display: none; }

  /* Типографика мобильного макета (2078:1371).
     H3 тут наборный, как и на десктопе, но крупнее: Graphik Semibold 24. */
  .h1 { font: 400 60px/51px 'Spectral', Cambria, Georgia, serif; letter-spacing: -1.8px; }
  .h2 { font: 400 42px/38.64px 'Spectral', Cambria, Georgia, serif; letter-spacing: -0.84px; }
  .h3 { font: 600 24px/1.05 'Graphik', sans-serif; }

  /* ===== Хиро ===== */
  .hero { margin: 0 !important; }
  /* Высота облака плюс отступ дают 284 — ровно столько от верха полотна
     до заголовка в макете. Сами плашки лежат абсолютно и за эту высоту
     не выходят: нижняя граница AREA подобрана с запасом на наклон. */
  .bubbles {
    position: relative;
    width: 100%; height: 284px;
    /* Автор попросила поднять на мобильном весь контент на 10, кроме самого
       облака. Поэтому не трогаем ни высоту контейнера (от неё считается
       область, куда падают плашки), ни отбивку страницы сверху, а забираем
       10 отрицательным полем: облако остаётся на месте, всё под ним едет
       вверх. От верха полотна до заголовка теперь 274, а не 284. */
    margin-bottom: -10px;
  }
  .hero .h1 { position: static; margin: 0 16px; }
  .hero-sub {
    position: static;
    width: auto; max-width: 278px;
    margin: 16px 16px 0;
    font-size: 18px;
    line-height: 1.25;
  }
  /* Лид-плашка в поток, во всю колонку; внутри координаты макетные —
     те же, что на десктопе, только кнопка во всю ширину карточки.
     Зубцы из картинки тут не попадают в край, поэтому их рисуют
     псевдоэлементы ниже, а текстура растягивается по карточке. */
  .badge {
    position: relative;
    left: auto; top: auto;
    width: auto; height: 292px;
    margin: 40px 16px 0;
    background: #2b241c url('assets/plate-badge.jpg') 50% 50% / cover;
  }
  .badge::before, .badge::after {
    content: '';
    position: absolute;
    left: 0; right: 0;
    height: 5px;
    background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='5'%3E%3Cpath d='M0 0L5 4.4L10 0Z' fill='%23fff'/%3E%3C/svg%3E") repeat-x;
  }
  .badge::before { top: 0; }
  .badge::after { bottom: 0; transform: scaleY(-1); }
  .badge-bg { display: none; }
  /* Трекинг у цен тут свой: на десктопе автор его сняла, а в мобильном
     макете (`2078:1757`, `2078:1755`) он остался — −1.8 и −0.2. Ширину
     линии не задаём: она идёт по тексту, а с трекингом он чуть уже. */
  /* Трекинг у цен тут снят — в обновлённой лид-плашке (2396:1989) его нет,
     как и на десктопе. У финальной плашки в макете он пока остался. */
  .badge-old { letter-spacing: 0; }
  /* в макете крупная цена тут на 154 от верха карточки (бокс обрезан
     по прописной), минус те же 0,138 em при кегле 60 */
  .badge-now { top: 145.7px; letter-spacing: 0; }
  /* при трекинге −1.8 пробел перед рублём уже, чем на десктопе без трекинга */
  .badge .btn { width: calc(100% - 40px); }

  /* ===== Вступление ===== */
  /* Буквица поднятая, как на десктопе: стоит на базовой линии первой
     строки. В макете (Cambria) она при этом лежит на нуле — у Spectral
     базовая внутри бокса выше на 3,5, отсюда и сдвиг. */
  /* `.sheet > section { position: static }` бьёт просто `.intro`
     по специфичности, поэтому position возвращаем тем же селектором —
     иначе буквица позиционируется от полотна и улетает под облако реплик. */
  .sheet > .intro {
    position: relative;
    left: auto; top: auto;
    width: auto; height: auto;
    margin-top: 80px !important;
    padding-top: 29px;
    /* отступ первой строки под буквицу; у абзаца ниже он снят */
    text-indent: 39px;
  }
  .intro-cap {
    position: absolute;
    /* 6, а не прежние 4: буквица стоит на базовой линии первой строки,
       а строка подросла с 16/23,2 до 18/26,1 — базовая уехала вниз
       на 2,2. Считается как и на десктопе, по метрикам. */
    left: -3px; top: 6px;
    text-indent: 0;
    font: 400 60px/51px 'Spectral', Cambria, Georgia, serif;
    letter-spacing: -1.8px;
  }
  .intro-first,
  .intro-rest {
    position: static;
    width: auto;
    font-size: 18px;
    line-height: 1.45;
  }
  /* первый абзац — один поток, чтобы строка рвалась по месту, а не по вёрстке
     десктопа: первая строка обтекает буквицу, остальные идут от края колонки */
  .intro-first, .intro-rest, .intro-rest p:first-child { display: inline; }
  .intro-rest p:last-child { display: block; margin-top: 11px; text-indent: 0; }

  /* ===== Программа ===== */
  .program { margin-top: 80px !important; }
  /* на мобильном заголовок стоит по краю колонки, сдвиг −5 не нужен */
  .program .h2 { margin: 0 0 40px; }
  .sprint { position: static; width: auto; margin-bottom: 60px; }
  .sprint:last-child { margin-bottom: 0; }
  .sprint::before { width: 100%; }
  .sprint-cols, .sprint-pair { flex-direction: column; gap: 20px; padding-left: 0; }
  .sprint-col { width: auto; }
  /* Фотография тянется во всю колонку, пропорции держит aspect-ratio;
     до неё в макете 40, то есть 20 от флексового зазора плюс 20 тут.
     Кадр на мобильном свой — шире и ниже десктопного (343×508, 594 и 260),
     поэтому тут `object-fit: cover`: файл один, а лишнее по высоте
     обрезается. */
  .sprint-pic { width: 100%; height: auto; margin-top: 20px; object-fit: cover; }
  .sprint-pic-1 { aspect-ratio: 343 / 508; }
  .sprint-pic-2 { aspect-ratio: 343 / 594; }
  .sprint-pic-3 { aspect-ratio: 343 / 260; }
  /* В мобильном макете у программы свой кегль: и заголовки групп, и пункты
     набраны 18/1.25 — на десктопе это 19/1.2 и 16/1.2. Селекторы повторяют
     базовые: `.grp p` — это (0,1,1), простой `.grp-t` ему проигрывает,
     поэтому заголовок берём теми же двумя классами. */
  .sprint-col .grp-t { font-size: 18px; line-height: 1.25; }
  .grp p { font-size: 18px; line-height: 1.25; }

  /* ===== Что внутри ===== */
  .inside { margin-top: 80px !important; }
  .inside .h2 { margin-bottom: 20px; }
  .inside-lead { width: auto; font-size: 18px; line-height: 1.45; }
  /* Стопка скриншотов идёт в поток, высоту ей держит пропорция — сами
     картинки внутри остались абсолютными, иначе они сложились бы столбиком. */
  .inside-shots {
    position: relative;
    width: 100%; height: auto;
    aspect-ratio: 986 / 670;
    margin-top: 40px;
  }
  /* Значок Степика висит на скриншоте, а не на секции, поэтому считаем
     его от низа: скриншот 233 высотой, значок торчит над ним на 37,5
     и заходит на него на 39. Так он не поедет, если текст над скриншотом
     переберёт лишнюю строку. Размер и место сняты с мобильного макета
     по краске — автор ставила значок там отдельно, пропорция
     с десктопом не сходится. */
  .inside-doodle {
    position: absolute;
    left: auto; right: 23px; top: auto; bottom: 194.6px;
    width: 76.6px; height: 76.6px;
  }
  /* Этим секциям нужен position для абсолютных детей (значок Степика,
     карточка телеграма).
     Базовое `.sheet > section { position: static }` выше по специфичности,
     чем просто `.inside`, поэтому возвращаем через тот же `.sheet >`. */
  .sheet > .inside,
  .sheet > .tg { position: relative; left: auto; top: auto; }
  /* ===== Для практики понадобятся =====
     От «Что внутри» тут 60, а не 80: в макете это один блок. */
  .practice { width: auto; height: auto; margin-top: 60px !important; }
  .inside-notes {
    position: relative;
    top: -2.28px;
    flex-direction: column; gap: 32px;
    margin-top: 0;
    font-size: 22px;
    line-height: 27px;
    letter-spacing: -0.22px;
  }
  .inside-note:first-child,
  .inside-note:last-child { width: auto; }
  .app { width: 22px; height: 22px; vertical-align: -2.1px; margin: 0 2px 0 4px; }
  .inf { width: 34px; height: 22px; vertical-align: -2.1px; }

  /* ===== Авторы =====
     Кружки идут во всю ширину колонки — так в макете. */
  .authors { margin-top: 80px !important; }
  .authors-row { flex-direction: column; gap: 44px; }
  .author, .author-wide { width: auto; }
  .author-pic { width: 100%; height: auto; aspect-ratio: 1; }
  .author-pic > img { width: 100%; height: 100%; margin: 0; }
  .author p { width: auto; margin-top: 20px; }
  /* height: 100% от родителя с height: auto в части браузеров (Safari)
     схлопывается в ноль, и кружок пропадает. Задаём высоту пропорцией. */
  .video-circle {
    position: relative;
    left: 0;
    width: 100%;
    height: auto; aspect-ratio: 1;
  }
  .video-circle .ring { width: 100%; height: 100%; }
  .video-circle .icon-play {
    left: 50%; top: 50%; right: auto; bottom: auto;
    /* треугольник из кита в той же пропорции к кружку, что на десктопе */
    width: 71px; height: 71px;
    transform: translate(-50%, -50%);
  }

  /* ===== Телеграм =====
     У мобильного своя карточка-картинка (узел 2001:4361, 343×619): рамка
     с зубцами и телефон в ней уже есть, рисовать их CSS'ом не нужно.
     Высоту секции держит `aspect-ratio` — картинка лежит абсолютно
     и в поток не считается. */
  .tg {
    position: relative;
    margin-top: 80px !important;
    padding: 33px 16px 0;
    aspect-ratio: 343 / 620;
  }
  .tg-card { width: 100%; height: auto; }
  /* текст и кнопка в потоке, а картинка позиционирована — без `relative`
     они оказались бы под ней */
  .tg-title, .tg-text, .tg .btn { position: relative; width: auto; }
  .tg-title { font-weight: 600; font-size: 36px; letter-spacing: -0.72px; }
  .tg-text { margin-top: 16px; max-width: 311px; font-size: 18px; line-height: 1.45; }
  .tg .btn { display: flex; height: 52px; margin-top: 30px; }

  /* ===== Вопросы ===== */
  .faq { margin-top: 80px !important; }
  .faq .h2 { margin-bottom: 32px; }
  .faq-item { margin-bottom: 36px; }
  .faq-item:last-of-type { margin-bottom: 0; }
  .faq-item .h3 { margin-bottom: 16px; }
  .faq-item p,
  .faq-item:nth-of-type(1) p, .faq-item:nth-of-type(2) p,
  .faq-item:nth-of-type(3) p, .faq-item:nth-of-type(4) p { width: auto; }

  /* ===== Финальный блок =====
     Плашка во всю колонку, 583 высотой; внутри — макетные координаты
     от её верхнего края, выключка влево от 20, как в лид-карточке.
     Зубцы рисуют псевдоэлементы, текстура растянута по карточке. */
  .buy { margin-top: 80px !important; }
  .buy-card {
    position: relative;
    width: auto; height: 583px;
    margin: 0;
    background: #2b241c url('assets/plate-buy.jpg') 50% 50% / cover;
  }
  .buy-bg { display: none; }
  .buy-card::before, .buy-card::after {
    content: '';
    position: absolute;
    left: 0; right: 0;
    height: 5px;
    background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='5'%3E%3Cpath d='M0 0L5 4.4L10 0Z' fill='%23fff'/%3E%3C/svg%3E") repeat-x;
  }
  .buy-card::before { top: 0; }
  .buy-card::after { bottom: 0; transform: scaleY(-1); }
  .buy-kicker {
    left: 20px; top: 40px;
    font-size: 20px; line-height: 19.4px;
    font-weight: 500; letter-spacing: -0.4px;
  }
  .buy-title {
    left: 20px; top: 69px;
    width: 295px;
    font-size: 52px; line-height: 44.2px;
    letter-spacing: -1.04px;
  }
  .buy-text {
    left: 20px; top: 173px;
    width: 303px;
    font-size: 20px; line-height: 1.35;
  }
  .buy-head { left: 20px; top: 275px; width: 268px; }
  .buy-lead, .buy-note { font-size: 18px; line-height: 20.7px; }
  .buy-old {
    left: 20px; top: 363px;
    font-weight: 500; font-size: 20px; line-height: 21.6px;
    letter-spacing: -0.2px;
  }
  /* 387 в макете — верх краски (бокс обрезан по прописной), минус 0,138 em */
  .buy-now {
    left: 20px; top: 378.7px;
    width: 303px;
    font-size: 60px;
    letter-spacing: -1.8px;
  }
  .buy-now .rub { font-size: 40px; letter-spacing: -0.8px; margin-left: -6px; }
  .buy-card .btn { left: 20px; top: 447px; width: calc(100% - 40px); }

  /* Таймлайн листается вбок, как в макете */
  .when {
    position: static;
    width: auto; height: auto;
    margin-top: 40px;
    overflow-x: auto;
  }
  /* На десктопе линия висит на 20,45 выше блока — внутри прокручиваемой
     полосы её бы срезало сверху, поэтому тут она начинается от нуля,
     а колонки опускаются на те же 37,45. */
  .when-inner { position: relative; width: 986px; height: 120px; }
  .when-line { top: 0; }
  .when-col { top: 37px; }

  /* ===== Если пока не определились ===== */
  .undecided { margin-top: 80px !important; }
  .undecided p { width: auto; max-width: 299px; font-size: 18px; line-height: 1.45; }

  /* ===== Подвал ===== */
  .site-footer {
    position: static;
    width: auto;
    margin: 0;
    padding: 28px 16px 40px;
    display: block;
    font-size: 15px;
  }
  .foot-left { flex-direction: column; align-items: flex-start; gap: 16px; }
  .site-footer > p { margin-top: 32px; max-width: 253px; }

  /* ===== Политика конфиденциальности (мобильный макет 2354:3695) =====
     Макет неполный: в нём есть заголовок, разделы 1, 2 и 8 и подвал.
     Чего в нём нет — разделителя под заголовком, ссылки «Вернуться
     на главную» и разделов 3–7, — доделано по его же правилам.
     Кегли тут свои, не те, что в мобильной типографике главной:
     заголовок Spectral 34/0.95, подзаголовки Graphik Semibold 22/1.15,
     текст Graphik Regular 16/1.35. */
  /* Фон под подвалом тут не нужен: на мобильном страницу закрывает
     собственная отбивка подвала, как и на главной. */
  #page.privacy { padding-bottom: 0; }
  /* Заголовок в макете стоит на 48 от верха страницы, полотно — на 16,
     значит внутри полотна это 32. */
  .privacy .sheet { padding: 32px 16px 102px; }
  .pp-title {
    width: auto;
    font: 400 34px/32.3px 'Spectral', Cambria, Georgia, serif;
    /* Трекинг тот же, что на десктопе, −2%: в макете он нулевой, но автор
       просила заголовок подобрать, и доля должна быть одна на обоих экранах.
       Повторять приходится потому, что мобильное правило `.h2` стоит в файле
       выше, а специфичность у них одинаковая — иначе заголовок забрал бы
       оттуда −0.84px, при кегле 34 это −2,5%. */
    letter-spacing: -0.02em;
  }
  /* Разделителя в мобильном макете нет: заголовок и текст разведены
     отбивкой 60, и между ними пусто. */
  .pp-rule { display: none; }
  .pp-body { width: auto; margin-top: 60px; gap: 48px; }
  .pp-sec .h3 { font: 600 22px/1.15 'Graphik', sans-serif; }
  .pp-sec p { font: 400 16px/1.35 'Graphik', sans-serif; }
  /* Втяжка та же, 14: мобильный фрейм под эту правку не обновлён, тире там
     ещё стоит, но делать на телефоне иначе нет причин. Прежний маркер съедал
     19 (колонка 15 плюс зазор 4), так что строка от втяжки даже не короче. */
  .pp-back { margin-top: 48px; font-size: 16px; }
  /* Подвал на мобильном и так статический, отбивку ему даёт своя. */
  .privacy .site-footer { margin-top: 0; }
}
