:root {
  --bg: #f6f3ee;
  --ink: #1c1a17;
  --ink-soft: #5c574e;
  --line: rgba(28, 26, 23, 0.14);
  --accent: #b5502e;
  --card: #ffffff;
  --mono: ui-monospace, "SF Mono", "IBM Plex Mono", Menlo, Consolas, "Courier New", monospace;
  --grid: rgba(28, 26, 23, 0.05);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background:
    repeating-linear-gradient(0deg, var(--grid) 0, var(--grid) 1px, transparent 1px, transparent 48px),
    repeating-linear-gradient(90deg, var(--grid) 0, var(--grid) 1px, transparent 1px, transparent 48px),
    var(--bg);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  line-height: 1.5;
}

code {
  font-family: var(--mono);
  background: rgba(28, 26, 23, 0.06);
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 0.9em;
}

header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 22px 6vw;
  border-bottom: 1px solid var(--line);
}

.brand {
  font-weight: 800;
  font-size: 18px;
  letter-spacing: -0.01em;
}
.brand-tag {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  color: var(--ink-soft);
  margin-top: 2px;
}

.header-right {
  display: flex;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
}

nav { display: flex; gap: 28px; }
nav a {
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
nav a:hover { color: var(--ink); }

/* Переключатель языка. 🔴 Первая версия сливалась с меню: тот же шрифт,
   тот же цвет, тот же ряд — Антон 08.10: «не видно переключателя, если
   не искать». Теперь это кнопка с рамкой и собственным фоном, отделённая
   от навигации зазором: читается как управляющий элемент, а не как ещё
   один пункт меню.
   Флаги сознательно НЕ используем: у португальского их два (Бразилия
   и Португалия, и бразильцу чужой флаг неприятен), у английского тоже,
   а флаг вообще обозначает страну, а не язык. */
.lang-switch {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  margin-left: 22px;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--card, #fff);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  line-height: 1;
}
.lang-switch .lang-current,
.lang-switch a {
  padding: 5px 10px;
  border-radius: 999px;
  text-decoration: none;
  transition: background 0.15s, color 0.15s;
}
.lang-switch .lang-current {
  color: #fff;
  background: var(--accent);
  font-weight: 700;
}
.lang-switch a { color: var(--ink-soft); }
.lang-switch a:hover { color: var(--ink); background: rgba(0, 0, 0, 0.06); }
/* Разделитель в кнопочном виде не нужен — его роль играет сама заливка. */
.lang-switch .lang-sep { display: none; }

section { padding: 8vw 6vw; }

.eyebrow {
  color: var(--accent);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  margin: 0 0 16px;
}

.hero {
  padding-top: 10vw;
  padding-bottom: 8vw;
  max-width: 780px;
}
.hero h1 {
  font-size: clamp(34px, 5.6vw, 58px);
  line-height: 1.08;
  margin: 0 0 24px;
  letter-spacing: -0.02em;
}
.hero h1 .accent { color: var(--accent); }
.hero .lede {
  color: var(--ink-soft);
  font-size: 17px;
  max-width: 560px;
  margin: 0 0 32px;
}

.spec-strip {
  display: flex;
  gap: 22px;
  flex-wrap: wrap;
  margin: 0 0 28px;
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: 0.03em;
  color: var(--ink-soft);
  text-transform: uppercase;
}
.spec-strip b { color: var(--ink); font-weight: 700; }

.btn {
  display: inline-block;
  padding: 14px 26px;
  border-radius: 999px;
  background: var(--ink);
  color: var(--bg);
  font-weight: 700;
  font-size: 14px;
  text-decoration: none;
}
.btn:hover { background: var(--accent); }

/* Две кнопки на первом экране (09.10.2026): первая зовёт к действию,
   вторая ведёт к доказательствам. Раньше ссылка была одна — «посмотри,
   как это собрано», то есть единственный путь вёл в описание процесса,
   а не к заказу. */
.hero-cta { display: flex; gap: 12px; flex-wrap: wrap; }
.btn-ghost {
  background: transparent;
  color: var(--ink);
  box-shadow: inset 0 0 0 1.5px var(--ink);
}
.btn-ghost:hover { background: var(--ink); color: var(--bg); }

/* Технические метрики переехали с первого экрана в блок доказательств:
   там они подтверждают качество, а не продают вместо обещания. */
.proof .spec-strip { margin: 26px 0 0; }

.line {
  padding: 0 6vw 6vw;
  overflow-x: auto;
}
.line-track {
  display: flex;
  align-items: flex-start;
  min-width: 560px;
  max-width: 820px;
  position: relative;
}
.line-track::before {
  content: "";
  position: absolute;
  top: 5px;
  left: 5px;
  right: 5px;
  height: 1px;
  background: var(--line);
}
.line-node {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  position: relative;
}
.line-node:first-child { align-items: flex-start; }
.line-node:last-child { align-items: flex-end; }
.line-dot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--bg);
  border: 1.5px solid var(--ink-soft);
}
.line-node-end .line-dot { border-color: var(--accent); background: var(--accent); }
.line-label {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-soft);
  white-space: nowrap;
}
.line-node-end .line-label { color: var(--ink); font-weight: 600; }

/* -1 · The read — wide block above the ladder, deliberately outside the
   step grid (task 182: the work behind step 0 is the most valuable part
   of the line and was invisible before this). Video is a generated
   animation, not footage — scripts/step_minus_one.py. */
.read-block {
  border-top: 1px solid var(--line);
  padding-top: 6vw;
  padding-bottom: 3vw;
}
.read-video {
  width: 100%;
  max-width: 980px;
  margin: 0 auto;
  aspect-ratio: 16 / 9;
  background: #000;
  border-radius: 8px;
  overflow: hidden;
}
.read-video video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  background: #000;
}
.read-lnum {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 700;
  color: var(--accent);
  text-align: center;
  margin: 22px 0 8px;
}
.read-caption {
  max-width: 640px;
  margin: 0 auto;
  text-align: center;
  color: var(--ink-soft);
  font-size: 15px;
  line-height: 1.5;
}

.jobs { border-top: 1px solid var(--line); }
.jobs h2, .proof h2 {
  font-size: clamp(26px, 3.6vw, 38px);
  margin: 0 0 44px;
  letter-spacing: -0.01em;
}

.job-card {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: 40px;
  align-items: center;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 32px;
  margin-bottom: 32px;
}
.job-card.reverse { grid-template-columns: 0.9fr 1.1fr; }
.job-card.reverse .job-text { order: 2; }
.job-card.reverse .job-video { order: 1; }

.job-tag {
  font-size: 15px;
  font-style: italic;
  color: var(--ink-soft);
  margin: 0 0 10px;
}
.job-text h3 { margin: 0 0 12px; font-size: 21px; letter-spacing: -0.01em; }
.job-text p { margin: 0 0 12px; color: var(--ink-soft); font-size: 15px; }
.job-meta {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-soft);
  opacity: 0.8;
}

.callout {
  background: var(--bg);
  border-left: 3px solid var(--accent);
  padding: 10px 14px;
  font-size: 13.5px;
  color: var(--ink);
}

.job-video {
  aspect-ratio: 9 / 16;
  max-height: 440px;
  background: #000;
  border-radius: 6px;
  overflow: hidden;
}
.job-video video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  background: #000;
}
.job-video-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--line);
  background: transparent;
}
.job-video-empty p {
  color: var(--ink-soft);
  font-size: 13px;
  font-style: italic;
  margin: 0;
}

.ladder-intro {
  color: var(--ink-soft);
  font-size: 15px;
  max-width: 640px;
  margin: 0 0 36px;
}

/* Задание ladder-geometry-and-layout (25.09.2026) put every step in one
   nowrap row with horizontal scroll — "буквально конвейер, который листаешь
   вбок". Владелец посмотрел выкаченную версию и отклонил ровно это:
   «прокрутка этапов вручную, тяжело, лучше уж статично» (задание
   ladder-static-and-content, 25.09.2026). Scroll is gone. All 8 steps sit
   in two static rows.

   🔴 Задание ladder-content-and-grid (25.09.2026) заменило раскладку строки
   ЕЩЁ РАЗ — прошлая версия держала карточки одной ВЫСОТОЙ (var(--ladder-h))
   и давала ширину по аспекту, из-за чего колонки получались разной ширины
   (portrait-карточка ~101px, landscape ~430px) — на широком экране текст под
   узкими карточками рвался по 3-4 слова в строку («A fixed crop clips him
   when he moves — that reads as a mistake, not a style» в колонку шириной
   с палец), владелец увидел это на скриншоте: «вёрстка на веб-версии всё
   ещё беда». Починка меняет, ЧТО фиксировано: теперь фиксирована ШИРИНА
   колонки (равная у всех 8 шагов, `grid-template-columns: repeat(4, 1fr)`),
   а видео вписывается в неё своей пропорцией — горизонтальные ролики выходят
   низкими, вертикальные высокими, ровно как попросил владелец. */
.ladder-strip {
  display: flex;
  flex-direction: column;
  gap: 32px;
}
/* `.ladder-row` — грид на 6 равных колонок (задание ladder-row-posters,
   02.10.2026; до этого было 5, ещё раньше 3, ещё раньше комментарий здесь
   называл 4 — все устарели, см. заметку про замер ниже). `.ladder-step`
   переведён в `display: contents`: его дети (видео + 4 строки подписи)
   становятся ПРЯМЫМИ элементами этого грида, каждый в своём grid-row — так
   у ВСЕХ 8 шагов видео стоит в ряду 1, номер шага в ряду 2, заголовок
   в ряду 3, первая строка подписи в ряду 4, вторая (`why`) в ряду 5. Высота
   каждого ряда — по самому высокому элементу этого ряда среди колонок: для
   ряда 1 это portrait-видео (высокое), поэтому landscape-видео в том же
   ряду 1 короче и `align-self: end` прижимает его к общему нижнему краю —
   тем самым низ ЛЮБОГО видео в строке лежит на одной линии, и подписи
   (ряды 2-5) у всех карточек стартуют с одного y — то самое требование
   владельца «выровняй превью по нижнему краю, чтобы подписи начинались на
   одной линии». */
/* Задание vitrina-positioning (29.09.2026): владелец увидел живой сайт —
   «видосы какие-то огромные». Замер подтвердил: при 3 колонках и реальной
   ширине `.ladder-row` 1232px (не оценка "на глаз", а `bounding_box()` из
   Playwright) колонка выходила 394.7px, портретное видео — 701.6px высотой,
   почти во весь экран. 5 колонок держала высоту у цели ~400px владельца, но
   шесть портретных шагов (2-7) на 5 колонках не делятся ровно — 5 шагов
   (2-6) шли в первой строке, шаг 7 оставался один во второй, с большим
   пустым хвостом грида справа (3 из 5 колонок, одна карточка внутри них) —
   «сбой вёрстки», замечание владельца 02.10. 🔴 Задание ladder-row-posters
   (02.10.2026) объединило оба ряда в один и перешло на 6 колонок: при той
   же ширине `.ladder-row` 1232px (`bounding_box()` из Playwright, см.
   docs/RESULT-ladder-row-posters.md) — (1232 - 5*24) / 6 ≈ 187px ширины
   колонки -> 187 * 16/9 ≈ 333px высоты видео. Меньше, чем было у 5 колонок
   (404px), но по шапке 187px читается без прищура, и все шесть шагов стоят
   в ОДНОМ ряду, как и просил владелец. */
.ladder-row {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-template-rows: auto auto auto auto auto;
  column-gap: 24px;
  row-gap: 0;
}
/* Задание ladder-fake-shots (27.09.2026): шаги 0-1 (нативно 16:9, вдвое ниже
   любого 9:16-соседа) больше не сидят в одном гриде с портретными шагами —
   раньше `align-self: end` прижимал их видео к нижнему краю строки, чья
   высоту диктовал portrait-сосед, и наверху оставалась пустая дыра (именно
   на это владелец указал: «плохо на странице расположены»). Теперь это
   отдельный верхний блок на 2 колонки, обе landscape — переход 16:9 -> 9:16
   происходит между блоками, а не внутри одной строки грида. */
.ladder-top-row { grid-template-columns: repeat(2, 1fr); }
.ladder-step { display: contents; }
.ladder-step > .ladder-video { grid-row: 1; align-self: end; }
.ladder-step > .lnum { grid-row: 2; }
.ladder-step > h4 { grid-row: 3; }
.ladder-step > p:not(.lnum):not(.why) { grid-row: 4; }
.ladder-step > p.why { grid-row: 5; }
/* Row-to-row connector: a short vertical drop + node under the end of row 1,
   standing in for "the line keeps going into the next row" without trying
   to draw a literal diagonal from step 3 to step 4. */
.ladder-row-link {
  width: 10px;
  height: 32px;
  margin: -16px 0 -16px 4px;
  position: relative;
}
.ladder-row-link::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--accent);
  opacity: 0.6;
}
.ladder-row-link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -1px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--bg);
}
.ladder-video {
  width: 100%;
  background: #000;
  border-radius: 8px;
  overflow: hidden;
  position: relative;
}
.ladder-step.landscape .ladder-video { aspect-ratio: 16 / 9; }
.ladder-step.portrait .ladder-video { aspect-ratio: 9 / 16; }
.ladder-video video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  background: #000;
}
.ladder-step .lnum {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--accent);
  font-weight: 700;
  margin: 12px 0 2px;
}
.ladder-step h4 { margin: 0 0 6px; font-size: 15px; letter-spacing: -0.005em; }
.ladder-step p:not(.lnum) { margin: 0; color: var(--ink-soft); font-size: 12.5px; line-height: 1.45; }
/* Second line per step: what the layer above is doing for the person
   watching, not what it technically is (that's the first <p>). Set apart
   with a thin accent rule so it doesn't read as more of the same sentence. */
.ladder-step p.why {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--line);
  font-style: italic;
  color: var(--ink);
  opacity: 0.82;
}

.ladder .callout { margin-top: 8px; max-width: 720px; }

.attribution {
  margin-top: 18px;
  max-width: 720px;
  font-size: 11.5px;
  color: var(--ink-soft);
  opacity: 0.75;
}
.attribution a { color: inherit; }

/* Линия-коннектор между шагами внутри ряда, версия 3 (задание
   ladder-content-and-grid, 25.09.2026). Версии 1-2 висели на
   `.ladder-step::after/::before` по центру ФИКСИРОВАННОЙ высоты карточки
   (`var(--ladder-h)/2`) — этой высоты больше нет (шаг 4 стал `display:
   contents`, псевдоэлементы на нём не рендерятся ни в одном браузере), а
   середина видео теперь у каждой карточки в ряду РАЗНАЯ (portrait высокое,
   landscape низкое). Новый якорь — САМ `.ladder-video`, `bottom: 0`: так как
   `align-self: end` кладёт низ любого видео в ряду на одну линию (см. выше),
   `bottom: 0` относительно `.ladder-video` — это одна и та же линия у всех
   4 карточек ряда без вычислений. Последняя карточка ряда — маркер
   `.ladder-step--row-end` в разметке (не CSS-селектор по позиции: `display:
   contents` рвёт `:last-child`/`:nth-child` относительно грида ряда, они
   продолжают считаться от родителя `.ladder-step`, а не от `.ladder-row`). */
.ladder-step:not(.ladder-step--row-end) > .ladder-video::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 100%;
  width: 24px;
  height: 2px;
  background: var(--accent);
  opacity: 0.6;
  pointer-events: none;
}
.ladder-step:not(.ladder-step--row-end) > .ladder-video::before {
  content: "";
  position: absolute;
  bottom: -4px;
  left: calc(100% + 11px);
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--bg);
  pointer-events: none;
  z-index: 1;
}

.proof { border-top: 1px solid var(--line); }
.proof-copy {
  color: var(--ink-soft);
  font-size: 16px;
  max-width: 660px;
  margin: 0 0 40px;
}
.proof-note {
  color: var(--ink-soft);
  font-size: 13px;
  opacity: 0.75;
  max-width: 660px;
  margin: 24px 0 0;
}

.method-row {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 28px;
  max-width: 900px;
}
.method-block {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 26px 28px;
  background: var(--card);
  position: relative;
}
.method-index {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--accent);
  letter-spacing: 0.08em;
}
.method-block h3 { margin: 6px 0 16px; font-size: 19px; letter-spacing: -0.01em; }
.method-spec { margin: 0; }
.method-spec dt {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-soft);
  opacity: 0.75;
  margin: 14px 0 4px;
}
.method-spec dt:first-child { margin-top: 0; }
.method-spec dd {
  margin: 0;
  font-size: 14px;
  color: var(--ink-soft);
}
.method-spec dd b { color: var(--ink); font-family: var(--mono); font-weight: 700; }

.author {
  border-top: 1px solid var(--line);
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 40px;
  align-items: start;
}
.author-photo-slot {
  aspect-ratio: 3 / 4;
  border: 1px solid var(--line);
  border-radius: 6px;
  overflow: hidden;
}
.author-photo-slot img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.author-text h2 { margin: 0 0 16px; font-size: clamp(26px, 3.2vw, 32px); letter-spacing: -0.01em; }
.author-text p { margin: 0 0 14px; color: var(--ink-soft); font-size: 15.5px; max-width: 620px; }

.closing {
  border-top: 1px solid var(--line);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 28px;
  max-width: 900px;
}
.closing-block {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 26px 28px;
  background: var(--card);
}
.closing-block h3 { margin: 6px 0 12px; font-size: 20px; letter-spacing: -0.01em; }
.closing-block p { margin: 0 0 16px; color: var(--ink-soft); font-size: 14.5px; }
.closing-offer { border-color: var(--accent); }
.closing-note {
  grid-column: 1 / -1;
  margin: 4px 0 0;
  font-size: 13px;
  color: var(--ink-soft);
  opacity: 0.85;
}

footer {
  padding: 26px 6vw;
  border-top: 1px solid var(--line);
  font-size: 12.5px;
  color: var(--ink-soft);
}

@media (max-width: 760px) {
  .job-card, .job-card.reverse {
    grid-template-columns: 1fr;
  }
  .job-card.reverse .job-text,
  .job-card.reverse .job-video,
  .job-card .job-text,
  .job-card .job-video {
    order: initial;
  }
  .job-video { max-height: 70vh; }
  .method-row { grid-template-columns: 1fr; }
  .author { grid-template-columns: 1fr; }
  .author-photo-slot { max-width: 200px; }
  .closing { grid-template-columns: 1fr; }
  .line-track { min-width: 480px; }
  header { flex-direction: column; align-items: flex-start; gap: 12px; }
  nav { gap: 18px; flex-wrap: wrap; }
  /* Below 760px the row-height match above still leaves the landscape steps
     narrower than the screen is wide but shorter than a thumb wants to
     read — single column, full-width previews for every step instead,
     landscape and portrait alike. Landscape is now ~2.39:1 (real source
     aspect, see .ladder-step.landscape above) so at full container width
     it's already short (~145px tall) and needs no extra cap. Portrait at
     the same full width would be 343 * 16/9 ≈ 610px of video alone — on a
     ~390px-wide phone that's most of the screen for ONE step, which is
     the "have to scroll forever, can't compare neighbours" complaint from
     the owner. Capped at 195px wide (≈347px video + ~185px caption incl.
     the why-line ≈ 530-570px total step height, measured with Playwright)
     so the step with its caption fits inside a ~667px viewport (iPhone SE,
     the smallest common reference) with room left over for the next
     step's edge. */
  .ladder-strip {
    flex-direction: column;
    align-items: stretch;
    overflow-x: visible;
    padding-bottom: 0;
    position: relative;
    padding-left: 24px;
  }
  /* Desktop (ladder-content-and-grid, 25.09.2026) lays every step out as a
     4-column grid with `.ladder-row`/`.ladder-step` both flattened via
     `display: contents`. A single mobile column needs the opposite — real
     boxes that simply stack top to bottom — so both are reset to normal
     flow here: `.ladder-row` becomes invisible (its 4 `.ladder-step`
     children join `.ladder-strip`'s flex column directly, same as if there
     were no row wrapper at all) and `.ladder-step` goes back to being a
     rendered block so its own width/connector rules below apply. */
  .ladder-row { display: contents; }
  .ladder-step { display: block; }
  .ladder-video { height: auto; width: 100%; }
  .ladder-step.landscape {
    width: 100%;
    max-width: 420px;
    --video-h: 144px;
  }
  .ladder-step.portrait {
    width: 100%;
    max-width: 195px;
    margin: 0 auto;
    --video-h: 347px;
  }
  /* Desktop connector (straight segment + node in the row gap) doesn't
     apply to a single column — there IS no gap to the side, steps stack
     top-to-bottom. Владелец прямо попросил на мобильной НЕ сегменты
     между карточками («скачут коряво»), а ОДНА непрерывная линия вдоль
     левого края — реализовано как один `::before` на самой `.ladder-strip`
     (не на каждом шаге), с `top:0;bottom:0`, поэтому она физически не
     может разорваться независимо от того, сколько текста в каждом шаге
     (высота карточек из-за разной длины подписи не фиксирована — линия
     не должна на это опираться). Узлы — отдельный `::before` на каждом
     `.ladder-step`, выровнены по x с линией (см. расчёт смещения ниже),
     по y — на вертикальном центре СВОЕГО видео (var(--video-h)/2), тот же
     принцип, что у прямого коннектора на десктопе. */
  .ladder-strip::before {
    content: "";
    position: absolute;
    left: 8px;
    top: 0;
    bottom: 0;
    width: 2px;
    background: var(--accent);
    opacity: 0.55;
  }
  /* Desktop's node used `.ladder-step:not(:last-child)::before`
     (specificity 0,2,1) — kill it here with the identical selector (same
     specificity, later in the cascade wins) rather than fight it with a
     less specific replacement that would silently lose. The new mobile
     node below is deliberately `.ladder-strip .ladder-step::after` (an
     extra ancestor to reach the same 0,2,1 specificity) on a DIFFERENT
     pseudo-element (::after, not ::before) so it can't collide with the
     rule it's not meant to touch, and it applies to EVERY step including
     the last one (desktop's version skips the last step on purpose — a
     row-gap connector has nothing to connect to after the final card —
     but a left-edge rail with one node per step needs a node on all 8). */
  .ladder-step:not(.ladder-step--row-end) > .ladder-video::before { content: none; }
  .ladder-step:not(.ladder-step--row-end) > .ladder-video::after { content: none; }
  .ladder-strip .ladder-step::after {
    content: "";
    position: absolute;
    left: -20px;
    top: calc(var(--video-h) / 2 - 5px);
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 0 3px var(--bg);
  }
}

/* Полноэкранный режим растягивал вертикальное видео по горизонтали
   (задание ladder-geometry-and-layout, 25.09.2026): `.job-video video` и
   `.ladder-video video` держат `object-fit: cover` для нормального
   вписывания В КАРТОЧКУ (тот же аспект, что у самого видео, крадиться
   почти нечему) — но в `:fullscreen` пропорция контейнера становится
   пропорцией ЭКРАНА (почти всегда шире, чем 9:16), и `cover` на этой
   новой пропорции либо обрезает, либо (в зависимости от браузера)
   съезжает к растяжению без сохранения соотношения сторон — ровно то,
   что видел владелец. Правило ниже переопределяет именно на
   `:fullscreen`/`::-webkit-full-screen` (Safari) — `object-fit: contain`,
   чтобы видео вписывалось целиком (чёрные поля по бокам вместо обрезки
   или растяжения), независимо от того, шире экран или уже самого видео. */
.job-video video:fullscreen,
.ladder-video video:fullscreen,
.job-video video:-webkit-full-screen,
.ladder-video video:-webkit-full-screen {
  object-fit: contain;
  width: 100%;
  height: 100%;
  background: #000;
}

.legal { max-width: 680px; }
.legal h1 {
  font-size: clamp(28px, 4.2vw, 38px);
  line-height: 1.15;
  margin: 0 0 22px;
  letter-spacing: -0.02em;
}
.legal-block { margin: 0 0 20px; max-width: 640px; }
.legal-block h3 { margin: 0 0 10px; font-size: 17px; letter-spacing: -0.01em; }
.legal-block p { margin: 0 0 10px; color: var(--ink-soft); font-size: 15px; }
.legal-block p:last-child { margin-bottom: 0; }
.legal-block a { color: var(--accent); }

footer { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
footer a { color: var(--ink-soft); }

.brand-accent { opacity: .62; font-weight: 400; }

/* Пока фотографии нет, блок об авторе идёт одной колонкой: иначе текст
   жмётся в правую часть, а слева зияет пустая треть. Убрать вместе
   с возвратом фото. */
.author--no-photo { grid-template-columns: 1fr; }
