/* 144 AGENCY — каркас страницы и фирменный слой.
   Ссылку на сайт открывают из переписки, чаще с телефона: страница обходится
   без сервера, без сборщика и без внешних запросов. Все пути относительные.

   Страница светлая: молочная основа, белые карточки, почти чёрный текст
   и два акцента — кислотный лайм заливками и электрик-синий на всём, что
   нажимается. Гайд HUMAN с тремя серыми остался референсом, решение
   заказчика. Прописной узкий дисплей на заголовках, наборный гротеск
   в тексте, графика из монтажной программы (REC, таймкод, скобки) и
   много пустого пространства — от первой версии. Тёмными остались только
   корпуса телефонов: это «кино» внутри светлой страницы. Подложка
   лайтбокса не тёмная, а в цвете открытого ролика.

   Порядок файла: шрифты → переменные → база → рукодельный слой →
   фоновая подложка → иконки → шапка → телефон → первый экран → блоки →
   цифры → логотипы → кейсы → веер → лайтбокс → контакты → подвал →
   плашка связи → видоискатель и цвет от наведения. */

/* ── шрифты ─────────────────────────────────────────────────────────────
   Сабсеты собирает build_fonts.py: латиница, кириллица и отдельный
   файл на ₽ и тире. Переменные woff2, поэтому диапазон font-weight. */
@font-face {
  font-family: "Montserrat";
  src: url("assets/fonts/montserrat-lat.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Montserrat";
  src: url("assets/fonts/montserrat-cyr.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Montserrat";
  src: url("assets/fonts/montserrat-extra.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+20BD, U+2013, U+2014, U+00A0, U+00D7;
}
@font-face {
  font-family: "Oswald";
  src: url("assets/fonts/oswald-lat.woff2") format("woff2-variations");
  font-weight: 200 700;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Oswald";
  src: url("assets/fonts/oswald-cyr.woff2") format("woff2-variations");
  font-weight: 200 700;
  font-display: swap;
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Oswald";
  src: url("assets/fonts/oswald-extra.woff2") format("woff2-variations");
  font-weight: 200 700;
  font-display: swap;
  unicode-range: U+20BD;
}

/* ── переменные ───────────────────────────────────────────────────────
   Вся палитра страницы лежит здесь, семью значениями. Ниже по файлу
   цветов больше нет: только эти переменные и прозрачности от них.

   Лайм — заливка и никогда не текст: на лайме текст всегда --ink.
   Синий — только то, что можно нажать: ссылка, кнопка, обводка фокуса. */
:root {
  --base: #f4f4f0;  /* молочный: фон страницы */
  --card: #ffffff;  /* белый: карточки и подложки под знаки */
  --ink: #111214;   /* почти чёрный: заголовки и основной текст */
  --mut: #5a5c60;   /* второй текст: подписи, сноски, источники */
  --lime: #c8ff2e;  /* акцент 1: наклейки, плашки, маркер */
  --blue: #1b4dff;  /* акцент 2: ссылки, кнопки, активное, фокус */
  --cine: #111214;  /* кино: рамки телефонов и подложка лайтбокса */

  /* Оранжевый знака. Единственное место на странице, где он живёт, —
     цифры внутри плавающего круга: это родной цвет логотипа из
     brand/logo/144-agency-src.png. В кнопки, наклейки, ссылки и
     акценты он не идёт: палитра страницы — семь значений выше, знак
     имеет право на свой цвет, страница нет. */
  --sign-ink: #f43d04;

  --line: rgba(17, 18, 20, 0.16);
  --line-soft: rgba(17, 18, 20, 0.08);
  /* слабая заливка под полосами и дорожками */
  --wash: rgba(17, 18, 20, 0.06);
  /* пара полос «было → стало». Молочная полоса на молочном фоне пропадает,
     поэтому «было» — бледная тень текста, «стало» — лайм. Лайм светлее
     фона страницы и краями сливается с ним, отсюда кант.
     Имя не --was: длины полос приходят из разметки переменными --was и --now */
  --dim: rgba(17, 18, 20, 0.22);
  --lime-edge: rgba(17, 18, 20, 0.5);

  --display: "Oswald", "Arial Narrow", "Helvetica Neue", sans-serif;
  --text: "Montserrat", "Helvetica Neue", Arial, sans-serif;

  --max: 1240px;
  --pad: clamp(18px, 5vw, 56px);
  /* поперечник плавающего знака вверху: от него считается верхний
     отступ первого экрана и остановка прокрутки к разделу */
  --sign-h: 56px;
  /* высота капсулы внизу экрана: от неё считается нижний отступ страницы,
     чтобы подвал не уезжал под стекло */
  --cap-h: 60px;
}

/* ── база ───────────────────────────────────────────────────────────── */
* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  /* Сверху столько, сколько занимает плавающий знак с отступом: иначе
     прыжок по ссылке капсулы подводит заголовок раздела ровно под круг. */
  scroll-padding-top: calc(var(--sign-h) + 28px);
  /* Снизу столько же, сколько занимает капсула. Без этого таб на телефон
     веера или на ссылку подвала подводит узел ровно под её стекло:
     браузер считает, что показал его, а человек фокуса не видит. */
  scroll-padding-bottom: calc(var(--cap-h) + 26px + env(safe-area-inset-bottom));
  -webkit-text-size-adjust: 100%;
}

/* Зерно лежит фоном страницы, а не слоем поверх: под текстом оно не
   трогает контраст, а молочная плоскость перестаёт быть идеально ровной.
   Плитка 256×256, 6 КБ, повтор на таком зерне глазом не читается. */
body {
  margin: 0;
  /* место под капсулу-меню: без этого отступа последний блок и подвал
     уезжают под стекло. Считается от высоты капсулы, не набивается
     на глаз, поэтому меняется вместе с ней в узких ширинах */
  padding-bottom: calc(var(--cap-h) + 34px + env(safe-area-inset-bottom));
  background: var(--base) url("assets/gen/grain.webp") repeat top left;
  color: var(--ink);
  font-family: var(--text);
  font-size: clamp(15px, 1.05vw, 17px);
  font-weight: 400;
  line-height: 1.7;
  letter-spacing: 0.01em;
  -webkit-font-smoothing: antialiased;
}

/* вес плотнее, чем в тёмной версии: на молочном фоне тонкий Oswald
   выглядит слабым, а тот же вес на графите читался как крупный */
h1, h2, h3 {
  margin: 0;
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 0.94;
}

p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

a {
  color: inherit;
  text-decoration: none;
}

/* обводка фокуса синяя: молочная на молочном фоне не видна */
:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 3px;
}
/* поверх «кино» синему нужен молочный ореол: на почти чёрном он один
   вытягивает всего 3:1 и на постере ролика теряется */
.box :focus-visible,
.fan__open:focus-visible {
  box-shadow: 0 0 0 5px rgba(244, 244, 240, 0.85);
}

/* Фоновые пятна свешиваются за края секций: обрезаем их по странице,
   иначе на узком экране появляется горизонтальная прокрутка. clip
   не создаёт прокручиваемый бокс, hidden — фолбэк для старых Safari.
   Липкая шапка и капсула-меню лежат вне main, их это не касается. */
main {
  overflow: hidden;
  overflow: clip;
}

.wrap {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--pad);
}

.skip {
  position: absolute;
  left: 8px;
  top: -80px;
  z-index: 40;
  padding: 12px 18px;
  background: var(--blue);
  color: var(--card);
}
.skip:focus { top: 8px; }

/* мелкая сухая подпись: таймкод, номер блока, подпись к части блока */
.kick, .idx, .lbl {
  font-family: var(--text);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--mut);
}

.kick {
  display: flex;
  align-items: center;
  gap: 14px;
}

.rec {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--ink);
}
.rec::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--mut);
}

.lead {
  max-width: 46ch;
  color: var(--mut);
  font-size: 1.05rem;
  line-height: 1.75;
}

/* ── название в подвале ─────────────────────────────────────────────
   «144» цифрами крупно, «agency» мелким строчным рядом, набором. Вверху
   страницы стоит не это, а обведённый знак в круге (.sign): в подвале
   название читается как подпись, а в круге нужен сам логотип. */
.mark {
  display: inline-flex;
  align-items: baseline;
  gap: 0.42em;
  font-family: var(--display);
  line-height: 1;
}
.mark__num {
  font-size: 30px;
  font-weight: 700;
  letter-spacing: 0.01em;
}
/* «agency» мельче цифр, но не тоньше 500 и не бледнее второго текста:
   в тёмной версии тонкое светлое начертание рядом с «144» пропадало */
.mark__word {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.28em;
  color: var(--mut);
}
.mark--foot .mark__num { font-size: 72px; }
.mark--foot .mark__word { font-size: 14px; }

/* ── рукодельный слой ───────────────────────────────────────────────
   Три примитива, которыми пользуются все блоки. Только CSS, без картинок.
   Угол каждого меняется переменной --tilt, чтобы наклоны не совпадали. */

/* 1. Наклейка: лаймовая плашка под небольшим углом. Лайм здесь работает
      заливкой, а текст на нём всегда почти чёрный — 14:1. */
.sticker {
  --tilt: -2.4deg;
  display: inline-block;
  padding: 0.42em 0.8em 0.36em;
  background: var(--lime);
  color: var(--ink);
  font-family: var(--display);
  font-size: 15px;
  font-weight: 700;
  line-height: 1.15;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border-radius: 2px;
  transform: rotate(var(--tilt));
  box-shadow: 0 6px 16px rgba(17, 18, 20, 0.14);
}
/* обратный вариант: белая плашка там, где лайма в блоке уже хватает */
.sticker--ink {
  background: var(--card);
  color: var(--ink);
  box-shadow: 0 6px 14px rgba(17, 18, 20, 0.1);
  outline: 1px solid var(--line);
}

/* 2. Полоска скотча: полупрозрачная матовая лента с рваными краями. */
.tape {
  --tilt: -2.2deg;
  display: inline-block;
  width: var(--tape-w, 196px);
  height: var(--tape-h, 26px);
  background:
    repeating-linear-gradient(112deg, rgba(17, 18, 20, 0.05) 0 3px, rgba(17, 18, 20, 0) 3px 10px),
    linear-gradient(180deg, rgba(17, 18, 20, 0.14), rgba(17, 18, 20, 0.07) 50%, rgba(17, 18, 20, 0.11));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.7),
    inset 0 -1px 0 rgba(17, 18, 20, 0.1);
  transform: rotate(var(--tilt));
  /* рваные короткие края: лента отрывалась руками, а не резалась */
  clip-path: polygon(1% 7%, 99% 0%, 97% 44%, 100% 93%, 3% 100%, 0% 48%);
}
/* скотч поверх соседнего содержимого */
.tape--pin {
  position: absolute;
  top: var(--tape-top, -14px);
  left: var(--tape-left, -22px);
  z-index: 2;
  pointer-events: none;
}

/* 3. Маркерное подчёркивание: два неровных прохода лаймового маркера.
      Рисуется фоном, поэтому текст остаётся почти чёрным — 14:1 на лайме.
      Полоса толще, чем в тёмной версии: лайм светлее фона страницы, и
      тонкий штрих на молочном просто не виден. */
.marker {
  --mk: 0.4em;  /* толщина в долях кегля: у крупных заголовков полоса тоньше */
  --mk-y: 94%;  /* высота прохода: полоса задевает низ букв, как маркер */
  padding-inline: 0.1em;
  margin-inline: -0.1em;
  background-image:
    linear-gradient(97deg, rgba(200, 255, 46, 0) 0 2%, rgba(200, 255, 46, 1) 5% 95%, rgba(200, 255, 46, 0.4) 100%),
    linear-gradient(93deg, rgba(200, 255, 46, 0) 0 6%, rgba(200, 255, 46, 0.6) 10% 88%, rgba(200, 255, 46, 0) 100%);
  background-repeat: no-repeat, no-repeat;
  background-size: 100% var(--mk), 92% calc(var(--mk) * 0.3);
  background-position: 0 var(--mk-y), 4% 100%;
}
h1 .marker,
h2 .marker { --mk: 0.28em; --mk-y: 88%; }
/* у h3 полоса проходит выше: такой заголовок занимает две-три строки, а на
   88 % маркер уезжает под них и читается как перечёркивание нижней строки */
h3 .marker { --mk: 0.28em; --mk-y: 80%; }

/* ── фоновая подложка ───────────────────────────────────────────────
   Пятна, плоскости и зерно лежат в site/assets/gen, собирает их
   tools/gen_assets.py. Форма приходит из генерации, цвет — только палитра:
   каждый файл это один цвет и мягкий канал прозрачности, поэтому пятно
   ложится на молочный фон без прямоугольной границы и весит копейки.

   Подложка работает под текстом и под медиа, спорить с ними ей нельзя:
   прозрачность в файлах уже занижена, здесь её только гасим на узких
   экранах, где текста на единицу площади больше. */
.glow {
  position: absolute;
  z-index: -1;
  /* картинку нельзя ни нажать, ни утащить мышью: это фон, не изображение */
  pointer-events: none;
}

/* Первый экран обходится без файла: там цвет приносит сам ролик, и
   лаймовое пятно под заголовком с ним спорило — два пятна на одном
   экране, оба лаймовые. Заодно заголовок перестал читаться сквозь
   зелёный склон. Пятно первого экрана — .first__phone::before ниже. */

/* Веер: плоскость лежит под дугой, телефоны стоят на ней. Координаты
   считаются от .fan__deck, а не от секции: плоскость и дуга — один узел,
   поэтому плоскость не уезжает под заголовок на другой ширине.

   Растянута по всей высоте узла (inset + object-fit по умолчанию): для
   размытой абстрактной плоскости растяжение незаметно, зато мягкие края
   файла остаются мягкими и подложка не обрывается прямой линией. */
.glow--fan {
  inset: 0 -8%;
  width: auto;
  height: 100%;
}

/* цена: то же лаймовое пятно, что на первом экране, другим краем */
.glow--price {
  right: -22%;
  bottom: -4%;
  width: min(700px, 92%);
  height: auto;
  transform: scaleX(-1);
}

/* команда: синяя плоскость по низу блока */
.glow--team {
  right: -10%;
  bottom: -6%;
  width: 108%;
  height: auto;
}

@media (max-width: 700px) {
  .glow { opacity: 0.7; }
}
/* «уменьшить движение» подложку не трогает: она статична. А вот людям,
   которым мешает лишний цвет под текстом, помогает контрастный режим */
@media (prefers-contrast: more) {
  .glow { display: none; }
}

/* ── иконки ─────────────────────────────────────────────────────────
   Один набор, нарисованный руками: сетка 24×24, обводка 1,6 и никакой
   заливки. Спрайт лежит в начале страницы, иконки вставляются <use>.
   Цвет всегда currentColor, поэтому иконка перекрашивается там, где
   стоит: синей в интерактиве, почти чёрной в тексте. */
.sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.ico {
  width: 24px;
  height: 24px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ── плавающий знак ─────────────────────────────────────────────────
   Полосы шапки нет: наверху едет круг со знаком и держится там всю
   прокрутку, до самого низа. Разметка — в начале index.html.

   Подложка и стекло взяты у капсулы: два элемента поверх страницы
   должны быть из одного материала, иначе круг читается наклейкой.
   Стекло здесь не украшение — знак стоит и на молочном фоне, и поверх
   кадра ролика в веере.

   Прячется классом is-locked вместе с капсулой, правило — в разделе
   «поверх страницы что-то открыто». */
.sign {
  position: fixed;
  top: calc(14px + env(safe-area-inset-top));
  left: var(--pad);
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--sign-h);
  height: var(--sign-h);
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  /* фолбэк там, где размытия нет: плотная белая заливка */
  background: rgba(255, 255, 255, 0.94);
  box-shadow: 0 10px 30px rgba(17, 18, 20, 0.1);
  transition: opacity 0.2s ease, visibility 0.2s ease, box-shadow 0.2s ease;
}

@supports ((backdrop-filter: blur(20px)) or (-webkit-backdrop-filter: blur(20px))) {
  .sign {
    background: rgba(255, 255, 255, 0.72);
    -webkit-backdrop-filter: blur(20px);
    backdrop-filter: blur(20px);
  }
}

/* Единственное место, где на странице появляется оранжевый. Заливка
   стоит на самом контуре, а не наследуется: у .ico по умолчанию
   fill: none и stroke — знак остался бы пустым. */
.sign__ico {
  width: auto;
  height: 52%;
  fill: var(--sign-ink);
}

@media (hover: hover) {
  .sign:hover { box-shadow: 0 12px 30px rgba(17, 18, 20, 0.22); }
}

/* ── телефон ────────────────────────────────────────────────────────
   Корпус собран вектором: рисунок кладёт phone.js одним svg внутрь
   .phone__body, градиенты лежат на странице один раз в .phone__ink.
   Здесь — только размеры, порядок слоёв и заливки этого рисунка.

   Размер и наклон задаются переменными --phone-w и --phone-tilt:
   тот же класс идёт в веер, в разбор кейса и в лайтбокс.

       <div class="fan__item" style="--phone-w: 220px; --phone-tilt: 8deg">

   Все внутренние размеры считаются от --phone-w, поэтому телефон
   остаётся собой на любой ширине. Кант --phone-frame и скругление
   --phone-radius — те же доли, из которых сложена сетка рисунка
   (1000 единиц ширины, кант 32, скругление 135).

   container-type: телефон сам себе контейнер, и мелкие детали гаснут
   по его собственной ширине, а не по ширине окна. Один корпус на все
   места страницы — значит и упрощаться он должен сам. */
.phone {
  --phone-w: 280px;
  --phone-tilt: -5deg;
  --phone-radius: calc(var(--phone-w) * 0.135);
  --phone-frame: calc(var(--phone-w) * 0.032);

  width: var(--phone-w);
  margin: 0;
  flex: none;
  container-type: inline-size;
}

.phone__body {
  position: relative;
  padding: var(--phone-frame);
  border-radius: var(--phone-radius);
  /* корпус остаётся «кино», почти чёрный: заливка держится и до того,
     как встанет рисунок. Тень мягче, чем в тёмной версии: на молочном
     фоне плотная тень читается как грязь */
  background: var(--cine);
  box-shadow:
    0 24px 44px rgba(17, 18, 20, 0.18),
    0 4px 12px rgba(17, 18, 20, 0.12),
    0 1px 2px rgba(17, 18, 20, 0.24);
  transform: rotate(var(--phone-tilt));
}

/* Рисунок корпуса: кант, фаска, внутренний рант и кнопки. Лежит под
   экраном, поэтому середина рисунка не видна — её закрывает кадр.
   Отрицательный inset ровно на те 12 единиц из 1000, которые viewBox
   держит про запас: кнопки торчат за силуэт корпуса. */
.phone__shell {
  position: absolute;
  inset: calc(var(--phone-w) * -0.012);
  pointer-events: none;
}
.shell__base { fill: var(--cine); }
.shell__rail { fill: url(#ph-rail); }
.shell__edge { fill: url(#ph-edge); }
.shell__side { fill: url(#ph-side); }
.shell__lip { fill: url(#ph-lip); }
.shell__key { fill: url(#ph-key); }
.shell__key--far { fill: url(#ph-key-far); }

/* Блик стекла. Направление света считается от наклона: телефон повёрнут
   на --phone-tilt, и градиент поворачивается на столько же в обратную
   сторону — свет остаётся на месте, а корпус под ним крутится. В веере
   наклон даёт сам веер, и он пишет свой угол в --phone-lean: без этого
   десять телефонов светились бы одинаково и сразу выдали бы рисунок. */
.phone__body::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: inherit;
  background:
    linear-gradient(
      calc(112deg - var(--phone-lean, var(--phone-tilt))),
      rgba(255, 255, 255, 0) 27%,
      rgba(255, 255, 255, 0.09) 38%,
      rgba(255, 255, 255, 0.02) 45%,
      rgba(255, 255, 255, 0) 56%
    ),
    linear-gradient(
      calc(150deg - var(--phone-lean, var(--phone-tilt))),
      rgba(255, 255, 255, 0.11) 0%,
      rgba(255, 255, 255, 0.02) 12%,
      rgba(255, 255, 255, 0) 24%
    );
  pointer-events: none;
}
@media (prefers-contrast: more) {
  .phone__body::before { display: none; }
}

/* Градиенты корпуса: сама коробка ничего не показывает, из неё берут
   краску все телефоны страницы. */
.phone__ink {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.phone__screen {
  position: relative;
  aspect-ratio: 9 / 16;
  overflow: hidden;
  /* скругление стекла соосно корпусу: внешнее минус кант, как в рисунке */
  border-radius: calc(var(--phone-radius) - var(--phone-frame));
  background: var(--cine);
  /* тёмная линия стыка: стекло стоит глубже светлого ранта */
  box-shadow: 0 0 0 1px rgba(17, 18, 20, 0.6);
}
/* Подсветка изнутри — отдельным слоем: внутренняя тень на самом экране
   не видна, кадр ложится поверх неё. */
.phone__screen::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.09);
  pointer-events: none;
}

.phone__video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: var(--cine);
}

/* Вырез камеры островком: пилюля глубже стекла, справа объектив с
   отсветом, слева датчик. Форма и место — от ширины телефона, поэтому
   островок не разъезжается ни в веере, ни в лайтбоксе. */
.phone__cam {
  position: absolute;
  top: calc(var(--phone-w) * 0.028);
  left: 50%;
  width: calc(var(--phone-w) * 0.28);
  height: calc(var(--phone-w) * 0.077);
  transform: translateX(-50%);
  border-radius: 99px;
  background: var(--cine);
  box-shadow:
    inset 0 0 0 1px rgba(17, 18, 20, 0.9),
    0 0 0 1px rgba(255, 255, 255, 0.05);
}
.phone__cam::before {
  content: "";
  position: absolute;
  top: 50%;
  right: 12%;
  width: calc(var(--phone-w) * 0.031);
  height: calc(var(--phone-w) * 0.031);
  transform: translateY(-50%);
  border-radius: 50%;
  background: radial-gradient(
    circle at 34% 28%,
    rgba(255, 255, 255, 0.2) 0%,
    rgba(255, 255, 255, 0.05) 42%,
    rgba(17, 18, 20, 0.9) 100%
  );
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
}
.phone__cam::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 16%;
  width: calc(var(--phone-w) * 0.014);
  height: calc(var(--phone-w) * 0.014);
  transform: translateY(-50%);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.06);
}

/* Мелкий телефон: детали уходят сами. На 200 пикселях ширины датчик
   в островке и бесшумный режим на канте занимают меньше пикселя —
   вместо детали получается рябь. Считается по ширине самого телефона:
   в веере он мелкий на любом окне. */
@container (max-width: 200px) {
  .phone__cam::after { display: none; }
  .shell__key--mute { display: none; }
}

/* Наклейка с числом просмотров: наклеена на верхний торец корпуса,
   почти целиком выше кадра. Внутри кадра ей места нет: у роликов
   титры вжаты в само видео, а снизу стоит родной счётчик просмотров —
   наклейка садилась то на титры, то на ту же цифру второй раз.
   Верхний торец свободен на любом постере: там системная полоса. */
.phone__views {
  --tilt: 3.4deg;
  position: absolute;
  top: calc(var(--phone-w) * -0.04);
  left: calc(var(--phone-w) * 0.04);
  z-index: 2;
  font-size: clamp(12px, calc(var(--phone-w) * 0.058), 17px);
}

/* кнопка воспроизведения: видна, когда движение просят убавить
   или когда браузер не дал запустить ролик сам */
.phone__play {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: none;
  place-items: center;
  border: 0;
  padding: 0;
  background: rgba(17, 18, 20, 0.34);
  color: var(--base);
  cursor: pointer;
}
.phone__play > span {
  width: calc(var(--phone-w) * 0.2);
  height: calc(var(--phone-w) * 0.2);
  border: 1px solid var(--base);
  border-radius: 50%;
  background: rgba(17, 18, 20, 0.6);
}
.phone__play > span::after {
  content: "";
  display: block;
  width: 0;
  height: 0;
  margin: 36% 0 0 40%;
  border-left: calc(var(--phone-w) * 0.058) solid var(--base);
  border-top: calc(var(--phone-w) * 0.036) solid transparent;
  border-bottom: calc(var(--phone-w) * 0.036) solid transparent;
}
.phone.is-manual:not(.is-poster) .phone__play { display: grid; }

/* сухая подпись под корпусом: кто клиент и какая отрасль */
.phone__cap {
  margin-top: calc(var(--phone-w) * 0.075);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--mut);
}
.phone__cap b {
  font-weight: 600;
  color: var(--ink);
}

/* ── первый экран ───────────────────────────────────────────────────── */
.first {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  /* Сверху — полоса под плавающий знак: полосы шапки нет, и без этого
     отступа круг сел бы прямо на строку «rec [ 9:16 · 25.00 fps ]».
     Дальше по странице знак едет поверх, как ему и положено, но первый
     экран человек видит нетронутым. */
  padding-top: calc(var(--sign-h) + clamp(32px, 6vh, 72px));
  padding-bottom: clamp(32px, 6vh, 72px);
}
.first__in {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "kick  phone"
    "title phone"
    "lead  phone"
    "acts  phone";
  column-gap: clamp(28px, 5vw, 80px);
  row-gap: clamp(14px, 2.6vh, 30px);
  align-items: start;
  justify-items: start;
}
.first .kick { grid-area: kick; }
.first__title { grid-area: title; }
.first__lead { grid-area: lead; }
.first__contacts { grid-area: acts; }

.first__phone {
  position: relative;
  /* своя область наложения: пятно уходит за телефон, но не под страницу */
  z-index: 0;
  grid-area: phone;
  align-self: center;
  justify-self: end;
}

/* Пятно в цвете кадра. Цвет приносит ролик: app.js считает его из
   постера и кладёт в --reel-tint на этом узле. Переменной нет —
   в дело идёт лайм, и первый экран выглядит ровно так же, только
   нейтрально. Форма мягкая и размытая: пятно, а не подсветка рамки. */
.first__phone::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -40% -60%;
  background: radial-gradient(
    56% 48% at 50% 50%,
    var(--reel-tint, var(--lime)) 0%,
    transparent 100%
  );
  opacity: 0.9;
  filter: blur(34px);
  pointer-events: none;
}
@media (prefers-contrast: more) {
  .first__phone::before { display: none; }
}
/* телефон встаёт в кадр целиком: ширина ограничена и высотой экрана тоже */
.first__phone .phone {
  --phone-w: clamp(200px, min(24vw, 33vh), 320px);
  --phone-tilt: -6deg;
}

/* Кегль считается от самой длинной заданной строки: колонка первого
   экрана должна вмещать её без своих переносов, иначе заданных строк
   становится больше трёх. Колонка на широком экране не растёт, а
   сужается — телефон добирает свои последние 23 пикселя раньше, чем
   она, — поэтому предел стоит на кегле, а не на ширине.

   82 — это тот кегль, что был на сайте до двух понижений: заголовок
   стал короче (самая длинная строка «у тех, кого видят»), и колонка
   снова его вмещает. Запас по ширине: 82 против 89 доступных на 1600
   и шире.

   Нижняя граница не тронута: на узких ширинах кегль держит не колонка,
   а высота окна. По ширине на 390 влезает 41 пиксель, но три строки
   крупнее 36 уводят кнопку связи под капсулу, поэтому там осталось 32.
   Расти заголовок начинает с 600 пикселей ширины. */
.first__title {
  font-size: clamp(32px, 5.4vw, 82px);
  line-height: 0.94;
  /* заголовок ломает сетку: свешивается на оптический отступ влево */
  margin-left: -0.05em;
}

.first__lead { max-width: 42ch; }

.first__contacts {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 8px;
}

/* кнопки синие: синий на странице означает «это нажимается» */
.btn {
  display: inline-block;
  padding: 14px 22px;
  background: var(--blue);
  color: var(--card);
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
}
.btn:hover { background: var(--ink); }

/* Узкий экран: телефон встаёт сразу под заголовок, чтобы играющий ролик
   был виден раньше текста, а не в конце первого экрана.

   Здесь же первый экран собирается плотнее. Внизу стоит капсула-меню, и
   всё, что должно прочитаться, обязано уместиться над ней: хук, телефон,
   абзац и обе кнопки связи. Поэтому телефон считается и от высоты окна
   тоже, а промежутки между строками сжимаются. Кегли и цвета не трогаем. */
@media (max-width: 900px) {
  .first {
    /* Полоса под плавающий знак остаётся и в столбик. Без неё круг садится
       ровно на строку «rec [ 9:16 · 25.00 fps ]»: в столбик она идёт первой
       и стоит по тому же левому краю, что знак. Прятать знак при прокрутке
       вниз нечего — на нетронутом первом экране он уже мешает. */
    padding-top: calc(var(--sign-h) + clamp(8px, 1.6vh, 18px));
    /* полоса под капсулой: содержимое до неё не доходит */
    padding-bottom: calc(var(--cap-h) + 26px + env(safe-area-inset-bottom));
  }
  .first__in {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "kick"
      "title"
      "phone"
      "lead"
      "acts";
    row-gap: clamp(10px, 1.6vh, 22px);
  }
  .first__phone {
    justify-self: center;
    /* небольшой отступ сверху: телефон стоит прямо под заголовком, и
       наклейка на его торце иначе садится на маркер последней строки */
    margin: 6px 0 0;
  }
  /* В столбик заголовок стоит прямо над телефоном, и пятно достаёт до
     него. Гасим: под текстом цвет должен быть заметен, но не спорить */
  .first__phone::before {
    inset: -22% -44%;
    opacity: 0.62;
  }
  .first__phone .phone {
    --phone-w: clamp(160px, min(38vw, 21vh), 240px);
  }
  /* подпись под телефоном в одну строку: две съедают высоту, которой
     на первом экране и так впритык. Ширина телефона ей не указ */
  .first__phone .phone__cap {
    position: relative;
    left: 50%;
    width: max-content;
    max-width: 92vw;
    transform: translateX(-50%);
    flex-wrap: nowrap;
    gap: 8px;
  }
}

/* Самые узкие: абзац идёт в один интервал плотнее, кнопки садятся в один
   ряд. Переносить кнопки не запрещаем: на совсем узких экранах они всё
   равно встанут в два ряда, и это лучше горизонтальной прокрутки. */
@media (max-width: 560px) {
  .first__lead {
    font-size: 1rem;
    line-height: 1.6;
  }
  .first__contacts {
    gap: 10px;
    margin-top: 0;
  }
  .first__contacts .btn {
    padding: 15px 14px;
    font-size: 11px;
    letter-spacing: 0.08em;
  }
}

/* Экраны 360 и уже. Здесь кегли ниже, чем на 390: заголовок в свои
   32 пикселя не встаёт заданными строками, кнопки уходят в два ряда,
   и первый экран перестаёт помещаться над капсулой. Обрезанный экран
   хуже мелкого шрифта. */
@media (max-width: 380px) {
  .first__title { font-size: 29px; }
  .first__lead { font-size: 0.94rem; }
  .first__phone .phone { --phone-w: clamp(140px, min(38vw, 21vh), 240px); }
  .first__contacts .btn { padding: 14px 10px; letter-spacing: 0.06em; }
}

/* ── пустые блоки ───────────────────────────────────────────────────
   Каркас под содержание: номер блока слева, заголовок справа.
   Тикеты 02–09 наполняют .block__body, не трогая разметку вокруг. */
.block {
  position: relative;
  border-top: 1px solid var(--line-soft);
  padding-block: clamp(56px, 10vh, 120px);
}
.block__in {
  display: grid;
  grid-template-columns: minmax(0, 88px) minmax(0, 1fr);
  gap: clamp(16px, 3vw, 40px);
  align-items: start;
}
.block__body { position: relative; }
.idx { padding-top: 0.7em; }

.block__title {
  font-size: clamp(32px, 6.4vw, 74px);
  margin-left: -0.03em;
}

/* скотч у заголовка блока: только он, а не всякая лента внутри кейсов.
   Панели разборов уезжают в окно, и селектор по id их больше не достаёт */
#cases .block__body > .tape {
  --tape-top: -28px;
  --tape-left: -34px;
  --tilt: -3.4deg;
}

/* ── цифры клиентов ─────────────────────────────────────────────────
   Четыре плашки в сетке, а не четыре строки отчёта: главная цифра
   занимает четверть площади блока, три остальные складываются вокруг.
   Скептик сначала видит масштаб, потом разбирается, из чего он сложился.

   У каждой плашки свой тон: лайм под главной цифрой, почти чёрная под
   второй, белые под двумя мелкими. Тон задаётся четырьмя переменными
   (--tone и цвета на нём), поэтому цифра, подпись и источник красятся
   один раз на плашку, а не по отдельности в каждом правиле.

   Источник цифры стоит внизу плашки мельче подписи и вторым цветом:
   цифра без источника выглядит выдумкой, а источник в один вес с цифрой
   спорит с ней за внимание. */
.nums__lead {
  margin-top: clamp(18px, 2.4vw, 26px);
  max-width: 50ch;
}

.nums {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(10px, 1.2vw, 16px);
  margin-top: clamp(30px, 5vw, 58px);
}
/* главная цифра — квадрат на две колонки и две строки, вторая цифра
   лежит над двумя мелкими. Места плашкам не назначаем: при таких
   размахах сетка раскладывает их сама и в том же порядке */
.num--big { grid-column: span 2; grid-row: span 2; }
.num--wide { grid-column: span 2; }

.num {
  --tone: var(--card);
  --tone-ink: var(--ink);
  --tone-mut: var(--mut);
  --tone-line: var(--line-soft);

  display: flex;
  flex-direction: column;
  padding: clamp(18px, 1.8vw, 26px);
  border-radius: 18px;
  background: var(--tone);
  color: var(--tone-ink);
  box-shadow: 0 1px 2px rgba(17, 18, 20, 0.06), 0 10px 26px rgba(17, 18, 20, 0.06);
}
/* белая плашка на молочном держится кантом: одной тени мало, край теряется */
.num:not(.num--lime):not(.num--ink) { outline: 1px solid var(--line-soft); }

.num--lime {
  --tone: var(--lime);
  /* на лайме текст всегда почти чёрный: серый --mut даёт на нём мутное
     пятно. Источник уводим прозрачностью того же чернильного цвета —
     62 % на лайме это 5:1, читается и с цифрой не спорит */
  --tone-mut: rgba(17, 18, 20, 0.62);
  --tone-line: rgba(17, 18, 20, 0.2);
}
.num--ink {
  --tone: var(--ink);
  --tone-ink: var(--card);
  /* белый в 68 % на почти чёрном — 8:1: источник читается, но не спорит */
  --tone-mut: rgba(255, 255, 255, 0.68);
  --tone-line: rgba(255, 255, 255, 0.18);
}

.num__val {
  font-family: var(--display);
  font-size: clamp(30px, 3vw, 44px);
  font-weight: 700;
  line-height: 0.92;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
}
/* Главная цифра сидит в середине плашки, а не под верхним краем: плашка
   вдвое выше остальных, и свободное место флексбокс делит между двумя
   автоотступами поровну — над цифрой и над источником. */
.num--big .num__val {
  margin-top: auto;
  /* верхний предел упирается в ширину плашки: на 72 «800 000 000+» встаёт
     в одну строку, на 78 переносится и читается как две разные цифры.
     Проверяет tools/shot_numbers.py — он считает строки каждой цифры */
  font-size: clamp(34px, 5.2vw, 72px);
}

.num__what {
  margin-top: 12px;
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.2em;
}
.num--big .num__what { font-size: 12px; }

/* источник прижат к низу плашки: у плашек одного ряда высота общая,
   и сноски встают на одну линию, как в приложении */
.num__src {
  max-width: 34ch;
  margin-top: auto;
  padding-top: 14px;
  color: var(--tone-mut);
  font-size: 12px;
  line-height: 1.5;
}
/* линия над источником — короткая насечка, а не разделитель таблицы */
.num__src::before {
  content: "";
  display: block;
  width: 26px;
  margin-bottom: 12px;
  border-top: 1px solid var(--tone-line);
}

/* ── логотипы клиентов ──────────────────────────────────────────────
   Высота у каждого знака своя: широкий и жирный FIT SERVICE при общей
   высоте перекрикивает всех, а круглый знак Чистой линии пропадает.
   Множитель --k уменьшает весь ряд на узких экранах одной правкой.

   Высоты пересчитаны для светлого фона. Мерялись не на глаз: замер
   tools/shot_numbers.py считает по снимку, сколько чернил знак ставит
   на молочное поле, и высоты подобраны так, чтобы чернил у всех было
   примерно поровну. На тёмном фоне тот же ряд стоял иначе: там знаки
   были светлыми на графите, и вес читался по площади свечения, а не
   по площади чернил. Отсюда правки: тонкий MEGACAMPUS подрос, жирный
   FIT SERVICE и плотный kari убавлены.

   Чистая линия — исключение из счёта чернил: круглая многоцветная
   эмблема держит взгляд сверх своих чернил, поэтому знак остался
   на прежней высоте, а не подрос до расчётной. */
.logos {
  --k: 1;
  position: relative;
  margin-top: clamp(44px, 7vw, 88px);
  padding-top: clamp(26px, 4vw, 40px);
  border-top: 1px solid var(--line-soft);
}
/* скотч приклеен поперёк линии, которая отделяет ряд логотипов */
#numbers .logos .tape {
  --tape-top: -11px;
  --tape-left: auto;
  --tape-w: 148px;
  --tape-h: 22px;
  --tilt: 2.8deg;
  right: -12px;
}

.logos__kick { --tilt: -1.9deg; }

.logos__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(22px, 3.6vw, 54px);
  margin-top: clamp(22px, 3vw, 34px);
}
.logos__i img {
  display: block;
  width: auto;
  height: calc(var(--h, 34px) * var(--k));
}
.logos__i--mega { --h: 60px; }
.logos__i--chl  { --h: 54px; }
.logos__i--yak  { --h: 25px; }
.logos__i--kari { --h: 30px; }
.logos__i--fit  { --h: 14px; }

.logos__note {
  max-width: 56ch;
  margin-top: clamp(22px, 3vw, 32px);
  color: var(--mut);
  font-size: 13px;
  line-height: 1.65;
}

/* планшет: в четыре колонки плашка мельче цифры, которая на ней стоит.
   Главная забирает всю ширину, вторая тоже, две мелкие делят ряд. */
@media (max-width: 900px) {
  .nums { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .num--big { grid-row: span 1; }
}

@media (max-width: 760px) {
  .logos { --k: 0.8; }
  #numbers .logos .tape { right: -6px; }
}

/* телефон: цифра в девять знаков не встаёт в половину экрана без переноса */
@media (max-width: 470px) {
  .nums { grid-template-columns: minmax(0, 1fr); }
  .num--big,
  .num--wide { grid-column: span 1; }
}

/* ── кейсы ──────────────────────────────────────────────────────────
   На странице от кейсов остался ряд кнопок: логотип клиента и одна
   строка результата. Сам разбор открывается поверх страницы, окном
   ниже в этом файле (.deep).

   Панель разбора идёт одинаковым порядком: ролик кейса → логотип
   с отраслью → заголовок с результатом → чем клиент считал результат
   и что сделали → метрики → кадры со съёмок. Порядок один на все три,
   поэтому читатель ищет свою цифру в одном и том же месте.

   Заголовок кейса набран мельче заголовка блока: результат клиента
   не должен спорить с названием раздела. */
.cases__lead {
  margin-top: clamp(18px, 2.4vw, 26px);
  max-width: 52ch;
}

/* Кнопка клиента: белая карточка с логотипом и результатом одной
   строкой. Синим здесь только строка «разбор» со стрелкой — на
   странице синий означает «это нажимается». */
.picks {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(258px, 100%), 1fr));
  gap: clamp(12px, 1.6vw, 20px);
  margin-top: clamp(28px, 4vw, 46px);
}

.pick {
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: clamp(16px, 2vw, 24px);
  width: 100%;
  height: 100%;
  padding: clamp(18px, 2.2vw, 26px);
  border: 1px solid var(--line-soft);
  background: var(--card);
  color: var(--ink);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.18s, box-shadow 0.18s, transform 0.18s;
}
@media (hover: hover) {
  .pick:hover {
    border-color: var(--blue);
    box-shadow: 0 14px 30px rgba(17, 18, 20, 0.12);
    transform: translateY(-2px);
  }
}

.pick__logo { --k: 0.9; align-self: start; }
/* карточка сама белая: подложка под многоцветным знаком тут стала бы
   рамкой вокруг него, как это уже было в ряду логотипов на молочном */
.pick__logo.case__logo--chl {
  padding: 0;
  background: none;
  outline: 0;
}

.pick__line {
  font-family: var(--display);
  font-size: clamp(19px, 1.6vw, 25px);
  font-weight: 700;
  line-height: 1.14;
  text-transform: uppercase;
  letter-spacing: 0.01em;
}
.pick__line .marker { white-space: nowrap; }

.pick__go {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--blue);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.2em;
}
.pick__go .ico { width: 18px; height: 18px; }

/* Панель разбора: слева ролик кейса, справа результат, цифры и кадры.
   Отдельной обёртки вокруг правой колонки нет — во вторую колонку
   встают все дети панели, кроме телефона, а телефон занимает первую
   целиком и стоит на месте, пока читают цифры.

   Панели живут в разметке блока #cases, а site/cases.js переносит их
   в окно. Без скрипта они остаются на странице, и эта же раскладка
   работает там: телефон слева, разбор справа. */
.cases { margin-top: clamp(36px, 5vw, 60px); }

.case {
  display: grid;
  grid-template-columns: minmax(0, clamp(190px, 21vw, 276px)) minmax(0, 1fr);
  column-gap: clamp(22px, 3vw, 52px);
  align-items: start;
}
/* без этой строки .case перебивает служебное [hidden] и в окне видны
   все три кейса разом */
.case[hidden] { display: none; }
.case > * { grid-column: 2; }

/* Телефон занимает первую колонку целиком и стоит на месте, пока читают
   цифры. Спан задан числом с запасом, а не до линии -1: явной сетки
   строк здесь нет, и -1 указала бы на первую же линию — телефон встал
   бы в одну строку с логотипом и растянул её на свою высоту. */
.case__film {
  position: sticky;
  /* не в упор: наклейка с просмотрами свешивается за верхний торец
     корпуса, и на нуле её срезало бы краем окна */
  top: 12px;
  grid-column: 1;
  grid-row: 1 / span 20;
}
/* клиент и отрасль стоят рядом логотипом и наклейкой, второй раз
   подписывать их под телефоном незачем */
.case__film .phone__cap { display: none; }
/* пятно в цвете кадра, как на первом экране: цвет приносит сам ролик
   (--reel-tint от app.js), не посчитался — остаётся лайм */
.case__phone {
  position: relative;
  z-index: 0;
}
.case__phone::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -30% -44%;
  background: radial-gradient(
    56% 48% at 50% 50%,
    var(--reel-tint, var(--lime)) 0%,
    transparent 100%
  );
  opacity: 0.8;
  filter: blur(30px);
  pointer-events: none;
}
@media (prefers-contrast: more) {
  .case__phone::before { display: none; }
}
.case__phone .phone {
  --phone-w: clamp(176px, 19vw, 260px);
  --phone-tilt: -3deg;
}

.case + .case {
  margin-top: clamp(46px, 7vw, 96px);
  padding-top: clamp(38px, 5.5vw, 68px);
  border-top: 1px solid var(--line-soft);
}

/* имя клиента — это логотип; рядом наклейка с отраслью */
.case__who {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(14px, 2.4vw, 30px);
}
/* высоты подобраны по тому же соотношению весов, что в ряду логотипов
   выше: узкий знак Якитории при общей высоте пропадает рядом с двумя
   крупными. Множитель --k уменьшает все три на узких экранах */
.case__logo { --k: 1; display: inline-flex; }
.case__logo img {
  display: block;
  width: auto;
  height: calc(var(--h, 40px) * var(--k));
}
.case__logo--mega { --h: 60px; }
.case__logo--yak  { --h: 28px; }
/* многоцветный знак ставим на белую подложку, как в ряду выше */
.case__logo--chl {
  --h: 60px;
  padding: calc(9px * var(--k)) calc(12px * var(--k));
  background: var(--card);
  outline: 1px solid var(--line-soft);
}

.case__ind { --tilt: -2.2deg; }

/* строки чуть свободнее, чем у заголовка блока: в две-три строки
   набор в упор слипается, и маркеру под словом не остаётся места */
.case__title {
  margin-top: clamp(18px, 2.6vw, 30px);
  max-width: 26ch;
  font-size: clamp(25px, 3.3vw, 42px);
  line-height: 1.06;
  margin-left: -0.02em;
}
/* маркер рисуется фоном на всей строчной области сразу: если размеченные
   слова разъезжаются по двум строкам, полоса встаёт поперёк текста и читается
   как перечёркивание. Поэтому подчёркнутое маркером не переносим */
#cases .block__title .marker,
#process .block__title .marker,
#price .block__title .marker,
.case__title .marker { white-space: nowrap; }

.case__sub {
  margin-top: 14px;
  color: var(--mut);
  font-size: 14px;
}

.case__cols {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(20px, 3.4vw, 54px);
  margin-top: clamp(26px, 3.4vw, 42px);
}
.case__text {
  max-width: 44ch;
  margin-top: 12px;
  line-height: 1.65;
}

/* ── метрики кейса ──────────────────────────────────────────────────
   Проценты сами по себе ничего не говорят: «−45%» без второй величины
   читается как обещание. Поэтому под каждой цифрой стоят две полосы —
   «было» бледной тенью и «стало» лаймом. Логика прежняя: тусклая полоса
   это то, с чем сравнили, яркая — результат. Молочная полоса из тёмной
   версии на молочном фоне пропала бы совсем.

   Длины задаёт разметка: --was и --now считаются от большей величины,
   поэтому у роста длиннее «стало», а у экономии — «было». */
.case__mets { margin-top: clamp(30px, 4vw, 46px); }

.mets {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(22px, 3vw, 44px);
  margin-top: clamp(16px, 2vw, 22px);
}
.met {
  flex: 1 1 200px;
  max-width: 320px;
}

.met__what {
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--mut);
}
.met__val {
  margin-top: 8px;
  font-family: var(--display);
  font-size: clamp(30px, 3.2vw, 44px);
  font-weight: 700;
  line-height: 0.95;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
}

.met__cmp {
  display: grid;
  gap: 12px;
  margin-top: 16px;
}
.met__pair { display: grid; gap: 6px; }
/* полоса лежит в дорожке во всю ширину: без дорожки короткая полоса
   висит в пустоте и сравнивать её не с чем */
.met__bar {
  display: block;
  height: 11px;
  background: var(--wash);
}
.met__bar::before {
  content: "";
  display: block;
  height: 100%;
}
.met__pair--was .met__bar::before {
  width: var(--was, 100%);
  background: var(--dim);
}
/* лайм светлее фона страницы: без канта конец полосы теряется в молочном */
.met__pair--now .met__bar::before {
  width: var(--now, 100%);
  background: var(--lime);
  box-shadow: inset 0 0 0 1px var(--lime-edge);
}
.met__lab {
  font-size: 11.5px;
  line-height: 1.35;
  letter-spacing: 0.02em;
  color: var(--mut);
}
.met__lab b { font-weight: 700; }
.met__pair--now .met__lab { color: var(--ink); }

/* ── сколько набрали ────────────────────────────────────────────────
   Абсолютные цифры кейса набраны мельче блока итогов и по-другому:
   единица стоит в одну строку со значением, а под ней сноска. Иначе
   кейс выглядит как повтор блока «Проверьте каждую цифру». */
.tally__kick { margin-top: clamp(28px, 3.6vw, 40px); }

.tally {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(166px, 100%), 1fr));
  gap: clamp(18px, 2.4vw, 30px);
  margin-top: clamp(14px, 1.8vw, 20px);
}
.tally__i {
  padding-top: 13px;
  border-top: 1px solid var(--line-soft);
}
.tally__val {
  font-family: var(--display);
  font-size: clamp(23px, 2.2vw, 30px);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
}
/* единица стоит отдельной строкой: в узкой колонке она всё равно уходит
   на вторую строку, а строки рвутся у каждой цифры по-своему */
.tally__val span {
  display: block;
  margin-top: 7px;
  font-family: var(--text);
  font-size: 10.5px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--mut);
}
.tally__src {
  margin-top: 9px;
  color: var(--mut);
  font-size: 12.5px;
  line-height: 1.5;
}

/* ── кадры со съёмок ────────────────────────────────────────────────
   Кадры лежат полосой, как фотографии, разложенные на столе: у каждого
   своя высота задана, а ширина берётся из его собственных пропорций —
   поэтому ни один кадр не растянут и ни одно лицо не обрезано. Полоса
   переносится по строкам, на телефоне встаёт по два в ряд. */
.case__shots { margin-top: clamp(30px, 4vw, 46px); }

/* Предел высоты — 284, а не 352: разбор кейса лежит в окне шириной 1180,
   и колонка под кадрами там не растёт вместе с экраном. От 24vw кадры на
   1920 выходили такими, что четвёртый уезжал на вторую строку один,
   оставляя дыру справа. На 284 все четыре встают в один ряд от 900 и
   выше, и остаётся запас на классическую полосу прокрутки: в окне она
   забирает у колонки ещё пятнадцать пикселей, а на маке её не видно. */
.shots {
  --shot-h: clamp(228px, 24vw, 284px);
  position: relative;
  margin-top: clamp(16px, 2vw, 22px);
}
.shots__row {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(8px, 1.1vw, 15px);
}

.shot { --tilt: -1deg; flex: none; }
/* кадры тёмные, фон страницы молочный: без канта и мягкой тени фотография
   выглядит дырой в странице, а плотная тень из тёмной версии — грязью */
.shot img {
  display: block;
  width: auto;
  height: var(--shot-h);
  border-radius: 3px;
  transform: rotate(var(--tilt));
  box-shadow:
    0 0 0 1px rgba(17, 18, 20, 0.1),
    0 12px 26px rgba(17, 18, 20, 0.14);
}
/* углы разные: одинаковый наклон читается как сетка, а не как стопка */
.shot:nth-child(1) { --tilt: -1.1deg; }
.shot:nth-child(2) { --tilt: 0.8deg; }
.shot:nth-child(3) { --tilt: -0.5deg; }
.shot:nth-child(4) { --tilt: 1.2deg; }

/* скотч приклеен к углу первого кадра. Углы разведены по клиенту,
   а не по порядку в блоке: в окне разбора панель всегда одна */
.shots .tape {
  --tape-w: 116px;
  --tape-h: 20px;
  --tape-top: -11px;
  --tape-left: -13px;
  --tilt: -3.8deg;
}
[data-pane="chl"] .shots .tape { --tilt: 3deg; --tape-left: -7px; }
[data-pane="yak"] .shots .tape { --tilt: -2.2deg; --tape-left: -16px; }

.shots__note {
  max-width: 62ch;
  margin-top: clamp(16px, 2.2vw, 22px);
  color: var(--mut);
  font-size: 12.5px;
  line-height: 1.6;
}

/* планшет: две колонки текста в кейсе становятся слишком узкими */
@media (max-width: 900px) {
  .case__cols { grid-template-columns: minmax(0, 1fr); }
  .case__text { max-width: 52ch; }
}

/* телефон рядом с текстом не оставляет ему ширины: до 700 разбор встаёт
   одним столбцом — ролик, дальше цифры и кадры, — и весь этот столбец
   прокручивается внутри окна */
@media (max-width: 700px) {
  .case {
    grid-template-columns: minmax(0, 1fr);
    row-gap: clamp(18px, 3vw, 28px);
  }
  .case > *,
  .case__film { grid-column: 1; }
  .case__film {
    position: static;
    grid-row: auto;
    justify-self: start;
  }
}

@media (max-width: 760px) {
  .case__logo { --k: 0.82; }
}

/* ── как работаем: полоса из семи шагов ─────────────────────────────
   Аккордеон из четырёх раскрывающихся полос заказчик забраковал за
   сложность. Вместо него линия с семью узлами: номер, иконка в кружке
   и название стоят у каждого шага всегда, поэтому порядок читается
   без единого нажатия. Подробности — таб-лист с одной панелью.

   Линию рисуют сами шаги: у каждого два псевдоэлемента, левая и правая
   половина отрезка на высоте кружка. Отдельной линии под узлами нет —
   на переносе строки она торчала бы в пустоту. Пройденные отрезки
   и левая половина текущего синие: видно, где стоишь и сколько дальше.
   Кружку нужен свой слой (position + z-index), иначе линия из
   псевдоэлемента ляжет поверх него.

   Сроки стоят скобками над полосой: у семи шагов дней нет, известно
   только «первые четыре — до 10 дней», «съёмка 2–3 дня», «монтаж до
   двух недель». Скобка тянется по колонкам из --from и --to. Отдельной
   мини-шкалы месяца больше нет: скобки — это она и есть.

   Панели лежат стопкой в одной ячейке: высоту держит самая длинная,
   и переключение шага не двигает то, что ниже. Закрытая прячется
   видимостью, а не display. Без скрипта у панелей 2–7 остаётся hidden
   из разметки: виден первый шаг. Скрипт (site/plan.js) снимает hidden
   и дальше переключает классом. */
/* воздуха вокруг блока меньше, чем у соседей: свёрнутым он обязан
   помещаться в один экран, и первое, что для этого ужимают, — поля */
.block--plan { padding-block: clamp(34px, 4vh, 62px); }

.plan__lead {
  margin-top: clamp(12px, 1.5vw, 16px);
  max-width: 74ch;
  font-size: 1rem;
  line-height: 1.6;
}

.rail { margin-top: clamp(14px, 1.8vw, 22px); }

.rail__top {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 24px;
  margin-bottom: clamp(8px, 1vw, 12px);
}
.rail__cycle {
  font-family: var(--display);
  font-size: clamp(14px, 1.2vw, 17px);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.rail__cycle .lbl { margin-right: 8px; }
.rail__leg {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--mut);
  font-size: 12px;
}
.rail__key {
  width: 13px;
  height: 13px;
  flex: none;
  border-radius: 50%;
  background: var(--lime);
  box-shadow: inset 0 0 0 1px var(--lime-edge);
}

/* скобки сроков и сама полоса стоят на одной сетке в семь колонок,
   поэтому скобка над первыми четырьмя шагами кончается ровно над
   четвёртым */
.rail__terms,
.rail__track {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
}
.rail__term {
  grid-column: var(--from) / var(--to);
  position: relative;
  padding-bottom: 9px;
  font-family: var(--display);
  font-size: clamp(10.5px, 0.85vw, 12px);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: center;
  color: var(--mut);
}
/* П-образная скоба под подписью, открытая вниз, к своим шагам */
.rail__term::after {
  content: "";
  position: absolute;
  left: 6px;
  right: 6px;
  bottom: 0;
  height: 5px;
  border: 1px solid var(--line);
  border-bottom: 0;
}
/* строка сроков вместо скобок — только на телефоне */
.rail__terms-line { display: none; }

.rail__step {
  --dot: clamp(34px, 3vw, 42px);
  --no-h: 15px;
  position: relative;
  display: grid;
  justify-items: center;
  padding: 6px 3px 2px;
  background: none;
  border: 0;
  border-radius: 4px;
  color: inherit;
  font: inherit;
  text-align: center;
  cursor: pointer;
}
/* линия между узлами: левая и правая половина отрезка у каждого шага.
   Крайние половины у первого и последнего шага не рисуются — линия
   начинается и кончается в кружке, а не в воздухе */
.rail__step::before,
.rail__step::after {
  content: "";
  position: absolute;
  top: calc(6px + var(--no-h) + 5px + var(--dot) / 2 - 1px);
  height: 2px;
  background: var(--line);
}
.rail__step::before { left: 0; right: 50%; }
.rail__step::after { left: 50%; right: 0; }
.rail__step:first-child::before,
.rail__step:last-child::after { display: none; }

.rail__no {
  height: var(--no-h);
  font-family: var(--display);
  font-size: 11px;
  font-weight: 600;
  line-height: var(--no-h);
  letter-spacing: 0.14em;
  color: var(--mut);
  transition: color 0.2s ease;
}
.rail__dot {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: var(--dot);
  height: var(--dot);
  margin-top: 5px;
  border-radius: 50%;
  background: var(--card);
  box-shadow: inset 0 0 0 2px var(--line);
  transition: background-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease;
}
.rail__ico {
  width: 21px;
  height: 21px;
  color: var(--mut);
  transition: color 0.2s ease;
}
.rail__name {
  margin-top: 8px;
  font-family: var(--display);
  font-size: clamp(12.5px, 1.05vw, 15px);
  font-weight: 500;
  line-height: 1.15;
  color: var(--mut);
  transition: color 0.2s ease;
}

/* пройденные шаги: синий контур кружка и синий отрезок за ним */
.rail__step.is-done .rail__dot { box-shadow: inset 0 0 0 2px var(--blue); }
.rail__step.is-done .rail__ico { color: var(--blue); }
.rail__step.is-done .rail__no,
.rail__step.is-done .rail__name { color: var(--ink); }
.rail__step.is-done::before,
.rail__step.is-done::after,
.rail__step.is-on::before { background: var(--blue); }

/* съёмка — единственные дни заказчика, поэтому её кружок лаймовый */
.rail__step[data-mine] .rail__dot { background: var(--lime); }

/* выбранный шаг: залитый кружок с ореолом. Название только перекрашивается —
   от смены насыщенности строка меняла бы ширину и полоса дёргалась */
.rail__step.is-on .rail__dot {
  background: var(--blue);
  box-shadow: inset 0 0 0 2px var(--blue), 0 0 0 4px rgba(27, 77, 255, 0.14);
  transform: scale(1.06);
}
.rail__step.is-on .rail__ico { color: var(--card); }
.rail__step.is-on .rail__no,
.rail__step.is-on .rail__name { color: var(--ink); }
.rail__step[data-mine].is-on .rail__dot {
  box-shadow: inset 0 0 0 2px var(--blue), 0 0 0 4px var(--lime);
}

/* наведение показывает панель шага, но выбор не меняет: кружок
   подрастает, а синим остаётся выбранный */
.rail__step.is-peek .rail__dot { transform: scale(1.06); }
@media (hover: hover) {
  .rail__step:hover .rail__ico,
  .rail__step:hover .rail__name { color: var(--ink); }
  .rail__step:hover .rail__dot { box-shadow: inset 0 0 0 2px var(--blue); }
  .rail__step.is-on:hover .rail__dot {
    box-shadow: inset 0 0 0 2px var(--blue), 0 0 0 4px rgba(27, 77, 255, 0.14);
  }
}

/* уголок над панелью стоит под выбранным шагом: --sel ставит скрипт,
   и уголок переезжает по полосе вместе с выбором */
.rail__panes {
  position: relative;
  display: grid;
  margin-top: clamp(13px, 1.5vw, 18px);
  padding-top: 8px;
}
.rail__panes::before {
  content: "";
  position: absolute;
  top: 0;
  left: calc((var(--sel, 1) - 0.5) / 7 * 100%);
  width: 16px;
  height: 8px;
  margin-left: -8px;
  background: var(--card);
  clip-path: polygon(50% 0, 100% 100%, 0 100%);
}
/* общее правило «убавить движение» гасит переходы у элементов, но
   не у псевдоэлементов: звёздочка их не берёт. Поэтому уголок под полосой
   и заливка отрезков ездят только там, где движение разрешили */
@media (prefers-reduced-motion: no-preference) {
  .rail__panes::before { transition: left 0.28s cubic-bezier(0.4, 0, 0.2, 1); }
  .rail__step::before,
  .rail__step::after { transition: background-color 0.25s ease; }
}

.rail__pane {
  grid-area: 1 / 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 300px);
  gap: clamp(12px, 2vw, 32px);
  padding: clamp(13px, 1.3vw, 18px) clamp(12px, 1.2vw, 17px);
  background: var(--card);
  border-radius: 5px;
  box-shadow: 0 0 0 1px var(--line-soft);
  visibility: hidden;
}
.rail__pane.is-on { visibility: visible; }
/* display: grid выше перебивает служебное hidden, и без этой строки
   страница без скрипта показывала бы все семь панелей стопкой */
.rail__pane[hidden] { display: none; }

.rail__text {
  max-width: 62ch;
  font-size: 15px;
  line-height: 1.55;
}
/* «от вас» отбито линией: по этой строке читатель считает своё время */
.rail__you {
  padding-left: 13px;
  border-left: 1px solid var(--line);
  font-size: 13px;
  line-height: 1.55;
}
.rail__you .lbl {
  display: block;
  margin-bottom: 5px;
}

/* ── сколько отдаёте и что забираете ────────────────────────────────
   Две колонки внизу блока. Слева время заказчика — единственная лаймовая
   плоскость в блоке: он освобождает 2–3 дня один раз в месяц, а не по
   дню каждую неделю. Справа то, что он получает. Стояли друг под другом
   и занимали два экрана, хотя мысль у них одна. */
.plan__foot {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(16px, 2.2vw, 30px);
  margin-top: clamp(18px, 2.2vw, 26px);
}

.mine {
  position: relative;
  padding: clamp(17px, 1.7vw, 21px) clamp(15px, 1.6vw, 20px) clamp(15px, 1.6vw, 19px);
  background: var(--lime);
  border-radius: 5px;
}
/* наклейка приклеена к верхнему краю плашки и наполовину свешивается
   с него: внутри блока лайм на лайме, а строка не съедала бы ряд */
.mine__kick {
  --tilt: -2.1deg;
  position: absolute;
  top: -11px;
  left: clamp(14px, 1.6vw, 20px);
  font-size: 12.5px;
}

.mine__rows {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr));
  gap: clamp(12px, 1.8vw, 26px);
}
.mine__val {
  font-family: var(--display);
  font-size: clamp(27px, 2.6vw, 36px);
  font-weight: 700;
  line-height: 0.95;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
}
/* на лайме второй серый текст даёт 4,3:1 — подписи набраны почти чёрным
   и приглушены прозрачностью, а не цветом из палитры */
.mine__what {
  max-width: 32ch;
  margin-top: 8px;
  font-size: 12.5px;
  line-height: 1.5;
  opacity: 0.78;
}
.mine__text {
  margin-top: clamp(13px, 1.6vw, 18px);
  font-size: 13px;
  line-height: 1.55;
  opacity: 0.86;
}

#process .tally__kick { margin-top: 0; }
/* три колонки держатся до последнего: во второй ряд «что получаете»
   уезжает только на телефоне, где строка всё равно одна */
#process .tally {
  grid-template-columns: repeat(auto-fit, minmax(min(118px, 100%), 1fr));
  gap: clamp(11px, 1.4vw, 18px);
}
#process .tally__val { font-size: clamp(19px, 1.7vw, 23px); }
#process .tally__val span { margin-top: 5px; }
#process .tally__src { font-size: 12px; }

.plan__why {
  margin-top: clamp(14px, 1.8vw, 20px);
  padding-top: clamp(11px, 1.3vw, 15px);
  border-top: 1px solid var(--line-soft);
  color: var(--mut);
  font-size: 12.5px;
  line-height: 1.5;
}

/* планшет: в панели шага «от вас» и текст рядом не встают, а внизу
   блока двум колонкам не хватает ширины на три плашки «что получаете» */
@media (max-width: 900px) {
  .rail__pane { grid-template-columns: minmax(0, 1fr); }
  .rail__you { max-width: 52ch; }
  .plan__foot { grid-template-columns: minmax(0, 1fr); }
}

/* ── полоса в две строки ────────────────────────────────────────────
   До 700 px семь колонок дают по 80 px на шаг, и «Сдача материала»
   в них не встаёт. Полоса переносится на две строки, 4 и 3, — это
   по-прежнему полоса с линией и узлами, а не семь карточек столбиком.
   Отрезок после четвёртого шага и перед пятым не рисуется: строка
   кончается в кружке, следующая с кружка начинается.

   Скобки сроков на две строки не переносятся — вместо них строка
   текста под полосой. Уголок над панелью тоже уходит: он считает
   позицию по семи колонкам одной строки. */
@media (max-width: 700px) {
  .rail__terms { display: none; }
  .rail__terms-line {
    display: block;
    margin-top: clamp(12px, 2.4vw, 16px);
    color: var(--mut);
    font-size: 12.5px;
    line-height: 1.5;
  }
  .rail__track {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    row-gap: clamp(12px, 2.6vw, 18px);
  }
  .rail__step:nth-child(4)::after,
  .rail__step:nth-child(5)::before { display: none; }
  .rail__panes {
    padding-top: 0;
    margin-top: clamp(11px, 2.4vw, 15px);
  }
  .rail__panes::before { display: none; }
}

/* телефон: кружок мельче, название в две строки — иначе четыре шага
   в ряд по 85 px не сходятся */
@media (max-width: 470px) {
  .rail__step {
    --dot: 32px;
    padding-inline: 1px;
  }
  .rail__ico { width: 19px; height: 19px; }
  .rail__name { font-size: 11.5px; }
  .rail__cycle { font-size: 14px; }
}

/* ── цена: лестница из трёх ступеней ────────────────────────────────
   Три ступени, и каждая следующая включает предыдущую. Тремя равными
   колонками их ставить нельзя: равные колонки предлагают выбрать одну
   из трёх, а здесь третья содержит две первые. Поэтому ступени идут
   полосами сверху вниз и растут в двух величинах сразу.

   Ширина. Первая ступень занимает две трети блока, вторая четыре
   пятых, третья всю ширину. Левый край у всех трёх общий, правый
   уходит вправо на каждой следующей — три полосы складываются
   в лестницу, и по ней видно, что третья ступень накрывает две первые.

   Вес. Первая стоит на бумаге страницы обводкой в один пиксель, вторая
   белой карточкой, третья — белым ценником с тенью и скотчем. Поэтому
   лестница читается лестницей и на телефоне, где ширина у всех трёх
   одна: разница остаётся в материале и в кегле цены.

   Ниже — оплата половинами, состав работ и гарантия; все три лежат
   внутри третьей ступени. Под лестницей сноска про разброс, за ней
   границы и оговорка про оферту. */
.price__lead {
  margin-top: clamp(18px, 2.4vw, 26px);
  max-width: 56ch;
}

.stair {
  display: grid;
  gap: clamp(14px, 1.8vw, 22px);
  margin-top: clamp(30px, 4.6vw, 56px);
}

.step {
  position: relative;
  border-radius: 6px;
}
.step .lbl { display: block; }

/* первая ступень: обводки в один пиксель хватает, чтобы она читалась
   ступенью, и не хватает, чтобы спорить с третьей */
.step--one {
  --cols: 3;
  width: 66%;
  padding: clamp(16px, 2vw, 22px) clamp(16px, 2.2vw, 26px) clamp(18px, 2.2vw, 24px);
  box-shadow: inset 0 0 0 1px var(--line);
}
/* вторая: белая карточка без тени — материал появился, вес ещё нет */
.step--two {
  --cols: 2;
  width: 83%;
  padding: clamp(18px, 2.2vw, 26px) clamp(18px, 2.4vw, 30px) clamp(20px, 2.4vw, 28px);
  background: var(--card);
  box-shadow: 0 0 0 1px var(--line-soft), 0 1px 2px rgba(17, 18, 20, 0.05);
}
/* третья: тот же ценник, что стоял в блоке до лестницы. Белая карточка
   на молочном держится кантом: одной тени мало, край теряется */
.step--three {
  --cols: 4;
  width: 100%;
  background: var(--card);
  box-shadow:
    0 0 0 1px var(--line-soft),
    0 1px 2px rgba(17, 18, 20, 0.05),
    0 14px 34px rgba(17, 18, 20, 0.06);
}
/* скотч приклеен к верхнему краю третьей ступени в том месте, где
   кончается вторая: лента держит верхнюю ступень на нижней, а не
   просто висит на углу */
#price .step--three .tape {
  --tape-w: 150px;
  --tape-h: 22px;
  --tape-top: -12px;
  --tape-left: 78%;
  --tilt: 2.4deg;
}

/* название и цена стоят в одну строку по разным краям ступени: цена
   тем самым садится на правый край, а он у каждой ступени свой */
.step__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 10px clamp(16px, 2.4vw, 30px);
}
/* подпись и название держатся вместе одним куском: иначе на переносе
   строки цена вклинивается между «ступень 2» и её названием */
.step__title { min-width: 0; }
.step__name {
  margin-top: 7px;
  font-size: clamp(19px, 2.2vw, 27px);
}
.step--three .step__name { font-size: clamp(22px, 2.8vw, 36px); }

.step__price {
  font-family: var(--display);
  font-weight: 700;
  line-height: 0.92;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
  /* сумма из двух групп цифр рвётся по пробелу и теряет разряды */
  white-space: nowrap;
  font-size: clamp(26px, 3vw, 38px);
}
.step--two .step__price { font-size: clamp(30px, 3.5vw, 46px); }
/* цена третьей ступени свешивается влево на толщину штриха, как
   заголовки и главная цифра в блоке цифр. Переносить строку ей можно —
   «от» и «в месяц» на узкой колонке уходят вниз, — но само число
   переносу не отдаётся: по пробелу оно рвётся и теряет разряды */
.step__price--big {
  margin-top: clamp(12px, 1.6vw, 18px);
  margin-left: -0.035em;
  font-size: clamp(40px, 5.4vw, 76px);
  white-space: normal;
}
.step__sum { white-space: nowrap; }
/* «от» и «в месяц» набраны подписью, а не цифрой: они уточняют число,
   а не спорят с ним за кегль */
.step__ot,
.step__per {
  font-family: var(--text);
  font-size: 12px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--mut);
  white-space: nowrap;
}
.step__price--big .step__ot,
.step__price--big .step__per { font-size: 13px; }
.step__per { margin-left: 0.1em; }

.step__note {
  max-width: 30ch;
  margin-top: clamp(12px, 1.6vw, 16px);
  color: var(--mut);
  font-size: 13px;
  line-height: 1.55;
}

/* состав ступени: строки одного веса под линией сверху, как в прежнем
   списке работ. У ступени нет главного пункта */
.step__has {
  display: grid;
  /* колонок ровно столько, сколько строк в этой ступени, и меняются они
     по ширине руками. auto-fit тут не годится: у ступеней разная ширина
     и разное число строк, и он то и дело оставлял последнюю строку
     одну во втором ряду с пустым местом рядом */
  grid-template-columns: repeat(var(--cols, 1), minmax(0, 1fr));
  gap: clamp(12px, 1.6vw, 18px) clamp(16px, 2.2vw, 28px);
  margin-top: clamp(14px, 1.8vw, 20px);
}
.step__it {
  max-width: 44ch;
  padding-top: 11px;
  border-top: 1px solid var(--line-soft);
  color: var(--mut);
  font-size: 13.5px;
  line-height: 1.55;
}
/* первой строкой состава стоит предыдущая ступень целиком: плюс перед
   ней и почти чёрный набор вместо серого. Читается как сложение —
   ступень ниже плюс то, что перечислено дальше в строке */
.step__it--in {
  color: var(--ink);
  font-family: var(--display);
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  line-height: 1.25;
  border-top-color: var(--line);
}
.step__it--in::before {
  content: "+";
  margin-right: 0.45em;
}

/* Ценник третьей ступени: слева сумма за месяц, справа отрывной ярлык.
   Линия отрыва — пунктир во всю высоту верхней части, поперёк него
   наклейка «делим на 30». Оба числа остаются в одной строке до самого
   телефона: порознь они снова начинают спорить друг с другом. */
.step__top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.66fr);
  border-bottom: 1px solid var(--line-soft);
}
.step__main { padding: clamp(20px, 2.6vw, 34px) clamp(18px, 2.4vw, 32px); }

/* ярлык: пунктир слева идёт от края до края верхней части, потому что
   колонки сетки растягиваются на всю её высоту. Слева отступ шире
   остальных — в него ложится половина наклейки на пунктире */
.step__tag {
  position: relative;
  padding:
    clamp(20px, 2.6vw, 34px) clamp(18px, 2.4vw, 32px)
    clamp(20px, 2.6vw, 34px) clamp(62px, 5.6vw, 86px);
  border-left: 2px dashed var(--line);
}
/* дырка под шнурок: пробита у самой линии отрыва, как на настоящей бирке.
   По ней ярлык и читается как ярлык, а не как вторая половина таблицы */
.step__hole {
  position: absolute;
  top: clamp(20px, 2.6vw, 34px);
  left: clamp(26px, 2.6vw, 36px);
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--base);
  box-shadow: inset 0 1px 2px rgba(17, 18, 20, 0.18), 0 0 0 1px var(--line-soft);
}
.step__each {
  margin-top: clamp(10px, 1.4vw, 16px);
  font-family: var(--display);
  font-size: clamp(28px, 3.2vw, 44px);
  font-weight: 700;
  line-height: 0.9;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* наклейка сидит верхом на пунктире: половина на цене, половина на ярлыке */
.step__split {
  --tilt: -3.2deg;
  position: absolute;
  top: 50%;
  left: 0;
  z-index: 1;
  transform: translate(-50%, -50%) rotate(var(--tilt));
  font-size: 13px;
  white-space: nowrap;
}

.step__body { padding: 0 clamp(18px, 2.4vw, 32px) clamp(22px, 2.8vw, 34px); }

/* сноска про разброс: она объясняет «от» у всех трёх цен, поэтому
   стоит под лестницей, а не внутри одной ступени */
.stair__spread {
  max-width: 62ch;
  margin-top: clamp(18px, 2.4vw, 26px);
  color: var(--mut);
  font-size: 13.5px;
  line-height: 1.65;
}

/* ── как платите ────────────────────────────────────────────────────
   Полоса ровно пополам: два платежа видно раньше, чем прочитаны цифры.
   Цвета те же, что на шкале месяца, — тусклым идёт наша работа, лаймом
   отбит платёж после съёмок.

   Полоса лежит внутри третьей ступени: остаток платят после съёмок,
   а снимаем мы только здесь. Отдельным блоком под лестницей она
   повисла бы непонятно к какой цене. */
.pay { margin-top: clamp(28px, 4vw, 44px); }

.pay__split {
  display: flex;
  gap: 3px;
  height: 14px;
  /* полосу держим в ширине текста: растянутая на всю страницу, она читается
     как шкала месяца из блока выше, хотя показывает всего два платежа */
  max-width: 680px;
  margin-top: clamp(13px, 1.7vw, 17px);
}
.pay__part { flex: 1; }
.pay__part--one { background: var(--dim); }
.pay__part--two {
  background: var(--lime);
  box-shadow: inset 0 0 0 1px var(--lime-edge);
}

.pay__legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 30px;
  margin-top: 13px;
  color: var(--mut);
  font-size: 13px;
}
.pay__leg {
  display: inline-flex;
  align-items: center;
  gap: 9px;
}
.pay__leg b {
  color: var(--ink);
  font-family: var(--display);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0.03em;
}
.pay__key {
  width: 22px;
  height: 10px;
  flex: none;
}
.pay__key--one { background: var(--dim); }
.pay__key--two {
  background: var(--lime);
  box-shadow: inset 0 0 0 1px var(--lime-edge);
}

/* ── границы ────────────────────────────────────────────────────────
   За что не берёмся — отдельная полоса под лестницей: отказы касаются
   всех трёх ступеней. Набраны тем же кеглем и цветом, что остальной
   текст, без крестиков, минусов и извинений: это условия работы.
   Оговорка про оферту идёт под ними. */
.deal {
  position: relative;
  margin-top: clamp(40px, 6vw, 76px);
  padding-top: clamp(28px, 4vw, 40px);
  border-top: 1px solid var(--line);
}

/* плашка гарантии: та же лаймовая заливка, что у «вашего времени»
   в блоке «как работаем», и наклейка приклеена к верхнему краю.
   Наклейка белая: лайм в плашке уже есть, лайм на лайме не читается.
   Плашка лежит внутри третьей ступени, и по месту видно, к чему она:
   на стратегии и сценариях просмотры обещать нечем */
.vow-plate {
  position: relative;
  margin-top: clamp(24px, 3vw, 32px);
  padding: clamp(22px, 2.6vw, 30px) clamp(18px, 2.2vw, 28px) clamp(18px, 2.2vw, 24px);
  background: var(--lime);
  border-radius: 6px;
}
.deal__kick {
  --tilt: -2.3deg;
  position: absolute;
  top: -11px;
  left: clamp(16px, 2vw, 24px);
  font-size: 12.5px;
}
.deal__lbl { display: block; }

.vow {
  max-width: 22ch;
  font-family: var(--display);
  font-size: clamp(24px, 3vw, 38px);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1.06;
}
/* на лайме второй серый текст мутнеет: строку набираем тем же почти
   чёрным и отделяем от обещания линией, а не цветом */
.vow__else {
  margin-top: clamp(14px, 1.8vw, 18px);
  padding-top: clamp(13px, 1.6vw, 17px);
  border-top: 1px solid rgba(17, 18, 20, 0.2);
  font-size: 15.5px;
  line-height: 1.55;
}
.deal__text {
  max-width: 40ch;
  margin-top: clamp(18px, 2.4vw, 24px);
  color: var(--mut);
  font-size: 13px;
  line-height: 1.65;
}

/* два отказа встают в ряд, пока каждому хватает на строку в 46 знаков:
   столбиком они уводят оговорку про оферту под капсулу-меню */
.limits {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: clamp(18px, 2.6vw, 40px);
  margin-top: clamp(18px, 2.4vw, 26px);
}
.limit {
  padding-top: 13px;
  border-top: 1px solid var(--line-soft);
}
.limit__name {
  font-family: var(--display);
  font-size: clamp(17px, 1.8vw, 22px);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  line-height: 1.1;
}
.limit__why {
  max-width: 46ch;
  margin-top: 9px;
  color: var(--mut);
  font-size: 13.5px;
  line-height: 1.6;
}

/* оговорка: мельче 13 px и бледнее серого из палитры не делаем —
   её читают с телефона, и прятать её незачем */
.fine {
  max-width: 64ch;
  margin-top: clamp(28px, 3.6vw, 40px);
  padding-top: clamp(18px, 2.4vw, 24px);
  border-top: 1px solid var(--line-soft);
  color: var(--mut);
  font-size: 13px;
  line-height: 1.65;
}

/* Ноутбук. На 1200 px первой ступени достаётся 590 px, и три колонки
   состава дают 180 px на строку — состав встаёт столбиком. Третья
   ступень укладывает свои четыре строки двумя рядами по два: это ровный
   квадрат, а не ряд из четырёх колонок по 190 px */
@media (max-width: 1200px) {
  .step--one { --cols: 1; }
  .step--three { --cols: 2; }
}

/* Уступ по ширине убавляем в два приёма, чтобы он не прыгал на 170 px
   в одной точке: 1100 и 900. Ниже 900 первая ступень отступает от края
   третьей на 10 %, вторая на 5 % — на 390 это 35 и 18 пикселей. Правый
   край всё ещё виден лестницей, а строки уже не жмутся; дальше лестницу
   держат вес карточки и кегль цены */
@media (max-width: 1100px) {
  .step--one { width: 76%; }
  .step--two { width: 88%; }
}
@media (max-width: 900px) {
  .step--one { width: 90%; }
  .step--two { width: 95%; }
}

/* планшет в портрете и телефон: состав идёт столбиком у всех трёх.
   В двух колонках по 250 px строка «30 готовых роликов: MP4, до 4K…»
   разваливается на пять строк по три слова */
@media (max-width: 700px) {
  .step--two { --cols: 1; }
  .step--three { --cols: 1; }
}

/* телефон: ярлык отрывается снизу, а не сбоку. Пунктир переезжает на
   верхний край ярлыка, наклейка остаётся на нём же — и продолжает
   читаться как деление, а не как подпись к первому числу */
@media (max-width: 760px) {
  .step__top { grid-template-columns: minmax(0, 1fr); }
  .step__tag {
    border-left: 0;
    border-top: 2px dashed var(--line);
    padding-top: clamp(30px, 7vw, 38px);
    padding-left: clamp(18px, 2.4vw, 32px);
  }
  .step__split {
    top: 0;
    left: clamp(18px, 2.4vw, 32px);
    transform: translateY(-50%) rotate(var(--tilt));
  }
  /* дырка уходит на другой край: наклейка держит левый угол отрыва,
     дырка — правый, и вдвоём они читаются как корешок билета */
  .step__hole {
    top: clamp(16px, 4vw, 22px);
    left: auto;
    right: clamp(18px, 2.4vw, 32px);
  }
}

/* узкий телефон: название и цена в одну строку не встают — цена уходит
   под название. Прижимать её к правому краю там нечем, левый край
   у обеих один */
@media (max-width: 480px) {
  .step__head {
    display: block;
  }
  .step__price {
    margin-top: clamp(10px, 3vw, 14px);
  }
}

/* ── веер ───────────────────────────────────────────────────────────
   Телефоны раскрыты дугой, как карты в руке: каждый следующий отходит
   в сторону, поворачивается, съезжает вниз и становится мельче.
   Раскладку считает fan.js, но все её величины заданы здесь — поэтому
   на узком экране веер перестраивается одной медиазапросной правкой,
   а скрипт остаётся прежним.

   Веер обрезан по краям (overflow: hidden), поэтому горизонтальной
   прокрутки страницы он не создаёт ни на одной ширине. */

.fan__intro {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(18px, 4vw, 56px);
  margin-top: clamp(18px, 3vw, 32px);
  align-items: start;
}
.fan__intro .lead { max-width: 38ch; }

.pitch__kick {
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--mut);
}

/* список отраслей — адресация «это про меня?», а не подписи к телефонам */
.inds {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 14px;
}
.inds li {
  padding: 7px 13px 5px;
  /* белая заливка: плашки стоят над цветной плоскостью веера, и на
     прозрачных сквозь буквы просвечивал лайм */
  background: var(--card);
  border: 1px solid var(--line);
  font-family: var(--display);
  font-size: clamp(14px, 1.3vw, 17px);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  line-height: 1.15;
}

.pitch__text {
  max-width: 42ch;
  margin-top: 20px;
  color: var(--mut);
}
.pitch__more {
  margin-top: 14px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.16em;
}
.pitch__more a {
  color: var(--blue);
  border-bottom: 1px solid rgba(27, 77, 255, 0.35);
  padding-bottom: 3px;
}
.pitch__more a:hover { border-bottom-color: var(--blue); }

/* Подложка под дугой. Без неё телефоны висели в пустоте молочного листа.
   Два слоя: лаймовая полка градиентом и поверх неё сгенерированная
   плоскость (site/assets/gen/plane-fan.webp). Плоскость даёт разводы
   и неровный край, полка — ровное покрытие: сама плоскость собрана
   с уклоном влево, и правая половина дуги на ней не стояла ни на чём.

   Цвет здесь лайм, а не от ролика: пятно в цвете кадра пришлось бы
   ставить за дугу, а дуга его целиком закрывает — на экране от него
   не остаётся ничего. Цвет ролика работает там, где его видно:
   на первом экране и на подложке лайтбокса.

   Своя область наложения (z-index: 0): подложка уходит под телефоны,
   но не под страницу. */
.fan__deck {
  position: relative;
  z-index: 0;
  margin-top: clamp(28px, 5vw, 56px);
  padding-bottom: clamp(10px, 2vw, 26px);
}
.fan__deck::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(84% 46% at 50% 76%, var(--lime) 0%, transparent 74%);
  opacity: 0.62;
  pointer-events: none;
}
@media (prefers-contrast: more) {
  .fan__deck::before { display: none; }
}

.fan {
  --fan-w: clamp(146px, 14.5vw, 214px); /* ширина одного телефона */
  --fan-gap: 0.86;     /* шаг вбок в долях ширины телефона */
  --fan-angle: 6.5;    /* градусов поворота на каждый шаг */
  --fan-drop: 7;       /* пикселей вниз по дуге, растёт квадратично */
  --fan-shrink: 0.075; /* насколько мельче каждый следующий телефон */
  --fan-far: 3.4;      /* дальше этого шага телефон уже не виден */

  position: relative;
  /* высота полосы: телефон, падение по дуге и две наклейки подписи под
     корпусом. Свободные пиксели сверху — под наклейку с просмотрами,
     которая свешивается за торец и на наведении едет вверх вместе
     с телефоном. Не хватит — веер обрежет и то, и другое */
  height: calc(var(--fan-w) * 2.16 + 130px);
  overflow: hidden;
  touch-action: pan-y; /* вертикальную прокрутку страницы не перехватываем */
  cursor: grab;
  /* края растворяются: телефон уходит из кадра, а не обрубается */
  -webkit-mask-image: linear-gradient(90deg, transparent, var(--ink) 7%, var(--ink) 93%, transparent);
  mask-image: linear-gradient(90deg, transparent, var(--ink) 7%, var(--ink) 93%, transparent);
}
.fan.is-drag { cursor: grabbing; }

.fan__item {
  position: absolute;
  top: 40px;
  left: 50%;
  width: var(--fan-w);
  margin-left: calc(var(--fan-w) / -2);
  z-index: var(--z, 1);
  transform-origin: 50% 92%;
  transition: transform 0.45s cubic-bezier(0.22, 0.75, 0.28, 1), opacity 0.3s ease;
}
/* пока телефон тащат мышью, он идёт за курсором без задержки;
   первая раскладка тоже без переезда — телефоны не разлетаются из центра */
.fan.is-drag .fan__item,
.fan:not(.is-set) .fan__item { transition: none; }

/* наведение выдвигает телефон вперёд. Место в дуге задаёт трансформ на
   .fan__item, а подъём — отдельный трансформ на самом телефоне: две
   независимые величины не мешают друг другу */
.fan__item:hover,
.fan__item:focus-within { z-index: 300; }
/* подъём небольшой: телефон едет вверх вместе с наклейкой, которая уже
   свешивается за торец корпуса, и на большом подъёме веер её обрезал */
.fan__item:hover .phone,
.fan__item:focus-within .phone { transform: translateY(-14px) scale(1.045); }

.fan__item .phone {
  --phone-w: var(--fan-w);
  --phone-tilt: 0deg; /* наклон даёт сам веер */
  transition: transform 0.35s cubic-bezier(0.22, 0.75, 0.28, 1);
}
/* Подписи наклейками, а не мелким серым текстом: клиент на плашке
   покрупнее, отрасль на плашке помельче, обе под небольшим углом.
   Значения повторяют .sticker: сам класс сюда не поставить, разметку
   телефона собирает шаблон в phone.js, один на весь сайт.
   Подписи стоят в столбик и по центру — у соседних телефонов они
   почти вплотную и в строку слипаются в одну. */
.fan__item .phone__cap {
  flex-direction: column;
  align-items: center;
  gap: 6px;
  text-align: center;
  transition: opacity 0.4s ease;
}
.fan__item .phone__cap b,
.fan__item .phone__cap span {
  max-width: 100%;
  padding: 0.4em 0.72em 0.32em;
  border-radius: 2px;
  font-family: var(--display);
  color: var(--ink);
  letter-spacing: 0.06em;
  box-shadow: 0 5px 14px rgba(17, 18, 20, 0.12);
}
.fan__item .phone__cap b {
  background: var(--lime);
  font-size: clamp(11px, calc(var(--fan-w) * 0.062), 14px);
  font-weight: 700;
  transform: rotate(-2.4deg);
}
.fan__item .phone__cap span {
  background: var(--card);
  outline: 1px solid var(--line-soft);
  font-size: clamp(9px, calc(var(--fan-w) * 0.05), 11px);
  font-weight: 600;
  transform: rotate(1.6deg);
}
/* Соседи отступают в глубину: поверх кадра ложится молочная дымка.
   Гасить их прозрачностью нельзя — сквозь корпус начинает светить
   плоскость, и телефон становится грязно-зелёным пятном вместо
   тёмного экрана, который просто стоит в стороне. */
.fan__item .phone__screen::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--base);
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
}
.fan__item:not(.is-active) .phone__screen::after { opacity: 0.34; }
.fan__item:not(.is-active):hover .phone__screen::after { opacity: 0.12; }
/* тень соседа мягче: одинаковая тень делает мелкий телефон тяжелее
   крупного центрального */
.fan__item .phone__body { transition: box-shadow 0.4s ease; }
.fan__item:not(.is-active) .phone__body {
  box-shadow:
    0 12px 24px rgba(17, 18, 20, 0.14),
    0 1px 2px rgba(17, 18, 20, 0.2);
}
/* у соседей подпись тише: наклейка белая, а не лаймовая, и вся пара
   чуть прозрачнее — иначе девять лаймовых плашек читаются как грядка */
.fan__item:not(.is-active) .phone__cap { opacity: 0.86; }
.fan__item:not(.is-active) .phone__cap b {
  background: var(--card);
  outline: 1px solid var(--line-soft);
}
/* у соседей на наклейке остаётся одна цифра: девять раз «просмотров»
   подряд превращают веер в стену текста */
.fan__item:not(.is-active) .phone__views-w { display: none; }
/* наклейка не переносится: телефон в дуге узкий, и «2,6 млн просмотров»
   вставало в две строки, залезая на соседний телефон. Свесить её за
   торец корпуса правильнее — наклейку так и клеят */
.fan__item .phone__views { white-space: nowrap; }

/* кнопкой служит весь телефон: своя кнопка воспроизведения тут не нужна,
   звук всё равно включается в лайтбоксе */
.fan__item .phone__play { display: none; }

.fan__open {
  position: absolute;
  inset: 0;
  z-index: 3;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.fan.is-drag .fan__open { cursor: grabbing; }
.fan__open:focus-visible { outline: 2px solid var(--blue); outline-offset: -4px; }

.fan__note {
  max-width: 62ch;
  margin-top: clamp(20px, 3vw, 34px);
  color: var(--mut);
  font-size: 13px;
  line-height: 1.65;
}

@media (max-width: 900px) {
  .fan__intro { grid-template-columns: minmax(0, 1fr); }
  .fan__intro .lead { max-width: 46ch; }
}

/* на телефоне веер крупнее и уже: центральный ролик занимает экран,
   соседи выглядывают краями и подсказывают, что можно листать */
@media (max-width: 760px) {
  .fan {
    --fan-w: clamp(150px, 46vw, 220px);
    --fan-gap: 0.94;
    --fan-angle: 7;
    --fan-far: 2.4;
    height: calc(var(--fan-w) * 2.16 + 122px);
  }
  .fan__item { top: 38px; }
}

/* ── лайтбокс ───────────────────────────────────────────────────────
   Один на страницу. Внутри — тот же компонент телефона, только крупнее
   и со звуком; клиент, отрасль и просмотры стоят рядом.

   Подложка окрашивается в цвет открытого ролика: --box-tint кладёт
   fan.js через Phone.tint, тем же холстом, что считает цвет для первого
   экрана. Тёмным в окне остаётся один корпус телефона — «кино» внутри
   цветного окна.

   Подписи при этом стоят не прямо на подложке, а на молочной карточке.
   Тон ролика — средней светлоты, и текстом по нему не попасть ни в одну
   сторону: молочный на нём даёт 2:1, почти чёрный на самом тёмном из
   десяти кадров — 4,1:1, тоже ниже 4,5:1. На карточке любая подпись
   даёт 16:1, а подложка остаётся полноцветной. */
.box {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: clamp(12px, 3vw, 40px);
  color: var(--ink);
}
/* без этой строки .box перебивает служебное [hidden] и лайтбокс виден всегда */
.box[hidden] { display: none; }

/* цвет ролика плюс высветление к середине и притенение по низу: ровная
   заливка во весь экран читается как ошибка вёрстки, а не как подложка */
.box__back {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(76% 62% at 50% 40%, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0) 70%),
    radial-gradient(120% 96% at 50% 104%, rgba(17, 18, 20, 0.26), rgba(17, 18, 20, 0) 62%),
    var(--box-tint, var(--lime));
}

.box__in {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 290px);
  align-items: center;
  gap: clamp(20px, 4vw, 60px);
  max-width: 100%;
}

.box__stage .phone {
  --phone-w: min(74vw, 430px, calc((100svh - 96px) / 1.95));
  --phone-tilt: 0deg;
}
/* подписи стоят в колонке рядом, на самом телефоне их не дублируем */
.box .phone__cap,
.box .phone__views { display: none; }

/* карточка с подписями: молочная плашка на цветной подложке */
.box__meta {
  padding: clamp(18px, 2.2vw, 26px) clamp(18px, 2.4vw, 28px) clamp(20px, 2.4vw, 28px);
  background: var(--card);
  box-shadow: 0 22px 48px rgba(17, 18, 20, 0.2);
}

.box__client {
  font-family: var(--display);
  font-size: clamp(26px, 3.4vw, 42px);
  font-weight: 700;
  text-transform: uppercase;
  line-height: 1;
}
.box__ind {
  margin-top: 10px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--mut);
}
.box__title {
  margin-top: 18px;
  font-size: 15px;
  line-height: 1.6;
}
.box__views {
  --tilt: -2.6deg;
  margin-top: 22px;
}
.box__hint {
  margin-top: 26px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--mut);
}

/* кнопки тёмные: подложка теперь светлая, и молочный кружок на ней
   пропадал вместе с обводкой */
.box__nav,
.box__close {
  position: fixed;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  padding: 0;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--base);
  cursor: pointer;
}
.box__nav:hover,
.box__close:hover {
  background: var(--blue);
  border-color: var(--blue);
  color: var(--card);
}
.box__nav { top: 50%; margin-top: -23px; }
.box__nav--prev { left: clamp(8px, 2vw, 28px); }
.box__nav--next { right: clamp(8px, 2vw, 28px); }
.box__close { top: clamp(8px, 2vw, 28px); right: clamp(8px, 2vw, 28px); }

/* стрелки и крестик нарисованы рамкой: картинок в интерфейсе нет */
.box__nav::before {
  content: "";
  width: 11px;
  height: 11px;
  border-left: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
}
.box__nav--prev::before { transform: translateX(2px) rotate(45deg); }
.box__nav--next::before { transform: translateX(-2px) rotate(-135deg); }
.box__close::before,
.box__close::after {
  content: "";
  position: absolute;
  width: 17px;
  height: 1.5px;
  background: currentColor;
}
.box__close::before { transform: rotate(45deg); }
.box__close::after { transform: rotate(-45deg); }

/* ── разбор кейса ───────────────────────────────────────────────────
   Окно поверх страницы: на странице от кейсов остался ряд кнопок, а
   весь разбор лежит здесь. Устройство то же, что у лайтбокса роликов
   выше: подложка на весь экран, окно по центру, is-locked на body.

   Прокручивается не окно, а полоса панелей внутри него: кружки
   клиентов, стрелки и крестик остаются на месте, до какой бы цифры
   ни дочитали. Поэтому окно — сетка из двух строк, верхняя по
   содержимому, нижняя во весь остаток, и прокрутка живёт в нижней.
   overscroll-behavior не отдаёт прокрутку странице, когда панель
   кончилась.

   Подложка здесь ровная почти чёрная, без цвета ролика: цвет в этом
   окне приносит пятно за телефоном, а страница за подложкой должна
   уйти совсем — под ней остаётся читаемый текст, а не один кадр. */
.deep {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: clamp(6px, 2vw, 34px);
  color: var(--ink);
}
/* без этой строки .deep перебивает служебное [hidden] и окно видно всегда */
.deep[hidden] { display: none; }

.deep__back {
  position: absolute;
  inset: 0;
  background: rgba(17, 18, 20, 0.66);
}

.deep__win {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  width: min(1180px, 100%);
  max-height: calc(100svh - clamp(12px, 4vw, 68px));
  overflow: hidden;
  background: var(--base);
  box-shadow: 0 30px 70px rgba(17, 18, 20, 0.38);
}

.deep__top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(8px, 1.6vw, 20px);
  padding: clamp(9px, 1.4vw, 15px) clamp(10px, 2vw, 24px);
  border-bottom: 1px solid var(--line-soft);
  background: var(--card);
}

.deep__switch {
  display: flex;
  align-items: flex-start;
  gap: clamp(4px, 1vw, 12px);
  margin-right: auto;
}

/* Кружки-аватарки: переключение клиента, как сториз. Имя клиента стоит
   под кружком текстом, а не в подписи к картинке: читалка называет
   клиента, и по нему же попадают пальцем. */
.dots {
  display: flex;
  align-items: flex-start;
  gap: clamp(4px, 0.9vw, 14px);
}

/* место под именем шире самого кружка: «Мегакампус» одним словом не
   рвётся, и на узком кружке имена налезали друг на друга */
.dot {
  display: grid;
  justify-items: center;
  gap: 6px;
  width: clamp(68px, 6.6vw, 86px);
  padding: 0;
  border: 0;
  background: none;
  color: var(--mut);
  font-family: inherit;
  cursor: pointer;
}
.dot__pic {
  display: grid;
  place-items: center;
  width: clamp(42px, 4.4vw, 56px);
  height: clamp(42px, 4.4vw, 56px);
  border-radius: 50%;
  background: var(--base);
  box-shadow: inset 0 0 0 1px var(--line);
}
/* знаки разной ширины: узкий вписывается по высоте, широкий по ширине,
   поэтому у обоих сторон свой предел, а пропорции остаются родные */
.dot__pic img {
  width: auto;
  height: auto;
  max-width: 62%;
  max-height: 44%;
}
.dot__name {
  font-size: 10px;
  font-weight: 500;
  line-height: 1.25;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.dot.is-here .dot__pic {
  background: var(--card);
  box-shadow: inset 0 0 0 2px var(--blue);
}
.dot.is-here .dot__name {
  color: var(--ink);
  font-weight: 600;
}

/* стрелки и крестик — иконки из набора в начале index.html */
.deep__nav,
.deep__close {
  display: grid;
  place-items: center;
  flex: none;
  width: clamp(34px, 3.4vw, 42px);
  height: clamp(34px, 3.4vw, 42px);
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--card);
  color: var(--ink);
  cursor: pointer;
}
.deep__nav { margin-top: clamp(2px, 0.6vw, 8px); }
.deep__nav .ico,
.deep__close .ico { width: 20px; height: 20px; }
@media (hover: hover) {
  .deep__nav:hover,
  .deep__close:hover {
    background: var(--blue);
    border-color: var(--blue);
    color: var(--card);
  }
}

.deep__hint {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--mut);
}

.deep__panes {
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: clamp(16px, 2.6vw, 34px) clamp(12px, 2.4vw, 34px) clamp(26px, 4vw, 46px);
}
/* панель в окне всегда одна: отбивка между кейсами со страницы здесь
   давала бы пустую полосу сверху у второго и третьего клиента */
.deep .case + .case {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

/* до 860 строку про Esc убираем: она адресована клавиатуре, а места
   в один ряд с кружками на этой ширине уже нет */
@media (max-width: 860px) {
  .deep__hint { display: none; }
}

/* на 390 три кружка, две стрелки и крестик стоят в один ряд только
   при мелком имени: кегль ниже, разрядка плотнее */
@media (max-width: 560px) {
  .dot { gap: 5px; }
  .dot__name {
    font-size: 9px;
    letter-spacing: 0.02em;
  }
}

/* ── общий признак «поверх страницы что-то открыто» ─────────────────
   Класс is-locked на body ставят лайтбокс (site/fan.js) и разбор кейса
   (site/cases.js). Он делает две вещи: останавливает прокрутку страницы
   и убирает всё, что висит поверх неё, — капсулу-меню внизу и знак
   вверху. Больше ничего для этого делать не нужно. */
body.is-locked { overflow: hidden; }
body.is-locked .cap,
body.is-locked .sign {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

@media (max-width: 860px) {
  .box__in {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    gap: 16px;
    text-align: center;
  }
  .box__stage .phone {
    --phone-w: min(68vw, 300px, calc((100svh - 230px) / 1.95));
  }
  .box__meta { max-width: 32ch; }
  .box__views { margin-top: 16px; }
  .box__hint { display: none; }
  .box__nav,
  .box__close { width: 38px; height: 38px; }
}

/* ── команда ────────────────────────────────────────────────────────
   Сцена вместо списка: пятеро стоят в одной плоскости и перекрывают
   друг друга, как группа на обложке. Первый вариант — пять карточек
   в рамках — заказчик отклонил, поэтому рамок здесь нет ни одной:
   фигуры лежат на молочном фоне вырезанными по контуру.

   Каждая фигура — отдельный файл с прозрачным фоном. Рост у всех общий
   (--h), а ширину фигура берёт от своей картинки; остальное держат
   проценты: --l ставит левый край, --b приподнимает над общей линией
   пояса, --z решает, кто перед кем. Поэтому фотографию живого человека
   достаточно прогнать через tools/cut_crew.py и положить под тем же
   именем — она встанет в тот же слот, и вёрстка не изменится.

   Свет приходит с трёх сторон: мышь на фигуре, фокус с клавиатуры
   внутри неё и нажатие (класс is-on ставит crew.js). Выбранный выходит
   вперёд и обводится лаймом, остальные притухают, сверху появляется
   подпись. Подписи лежат отдельным слоем над сценой и не ловят мышь,
   иначе они перекрывали бы головы соседей.

   Ниже сцены — кадры со съёмок. Они лежат ровным рядом и пропорции
   у них родные (4:5), поэтому ни один не обрезан: наклон даёт
   рукодельный слой, а не кроп. */
.team__lead {
  margin-top: clamp(18px, 2.4vw, 26px);
  max-width: 52ch;
}

.crew { margin-top: clamp(22px, 3vw, 34px); }

/* На узких экранах сцена шире окна и едет вбок: пять фигур в ряд на
   390 превратились бы в марки. Прокрутка сохраняет главное — это
   по-прежнему один кадр, а не столбик карточек. */
.crew__scroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
}

/* Пропорция сцены задаёт не размер фигур — их держит ширина, — а высоту
   пустой полосы над головами. В этой полосе стоит подсказка, а на
   выбранной фигуре появляется подпись, и подпись не должна налезать
   на головы: shot_team.py печатает запас полосы на каждой ширине.

   Полоса стала ниже вместе с перерисовкой: у прежних фигур руки были
   опущены, и слой выходил вытянутым по вертикали, а теперь у каждого в
   руках предмет и локти в стороны — тот же рост занимает больше ширины.
   При прежней пропорции пятеро сидели узкой лентой у нижнего края под
   пустым полем в две своих высоты.

   Вырезки из фотографий обрезаны вплотную по человеку и в ширину они
   уже рисунков: при прежней пропорции сцены пятеро вставали в строчку
   с просветами. Чтобы группа стояла плотно, фигуры выросли на пятую
   часть, и полоса над головами держится прежней по пикселям только на
   более высокой сцене. */
.crew__plane {
  position: relative;
  width: 100%;
  aspect-ratio: 1.8 / 1;
}

/* Лаймовое пятно за группой: держит воздух над головами и делает из
   пяти вырезок один плакат. Мягкое, без края — прямоугольник тут
   читался бы той самой рамкой. */
.crew__plane::before {
  content: "";
  position: absolute;
  inset: 4% 2% 0;
  z-index: 0;
  background: radial-gradient(62% 64% at 50% 64%, var(--lime), transparent 72%);
  opacity: 0.26;
  pointer-events: none;
}

/* Рост общий на всех: файлы приходят одной высоты, поэтому слой меряется
   по высоте, а ширину берёт от картинки. Так подстановка человека — это
   правда один файл: у присланной фотографии свой разворот плеч, при
   ширине в процентах она встала бы ниже соседей и пришлось бы лезть в
   стили. */
.crew__figs {
  position: absolute;
  inset: 0;
  --h: 60.3%;
}

.fig {
  position: absolute;
  bottom: var(--b);
  left: var(--l);
  z-index: var(--z);
  height: var(--h);
  transform-origin: 50% 100%;
  transition: transform 0.3s ease, opacity 0.3s ease;
}

.fig__ph {
  display: block;
  height: 100%;
  width: auto;
  transition: filter 0.3s ease;
}

/* Нажатие ловит прозрачная кнопка-плашка по торсу, а не весь бокс
   картинки: боксы соседей налезают друг на друга, и по целому боксу
   передняя фигура забирала бы мышь у видимой части задней. */
.fig__hit {
  position: absolute;
  top: 0;
  right: 17%;
  bottom: 0;
  left: 17%;
  padding: 0;
  border: 0;
  background: none;
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
}
.fig__hit:focus-visible { outline-offset: 4px; }

/* Кто где стоит и кто перед кем. Ширину каждый берёт от своего файла,
   поэтому здесь только левый край, подъём над линией пояса и порядок
   по глубине. Соседи заходят друг на друга на 9–10% сцены — это треть
   фигуры: группа стоит плотно, но никто не закрыт наполовину. Заход
   разный у каждой пары, иначе пятеро выстраиваются по линейке. Автор
   идей уходит на 2% за левый край: кадр обрезает крайнего, как в
   группе, снятой одним планом. Порядок слева направо повторяет порядок
   работы: идея, сценарий, съёмка, монтаж, а порядок по глубине сводит
   группу клином — середина впереди, крайние позади. */
.fig--avtor {
  --l: -2%;
  --b: 6%;
  --z: 1;
}
.fig--scenarist {
  --l: 16.9%;
  --b: 3.5%;
  --z: 3;
}
.fig--rezhisser {
  --l: 32.7%;
  --b: 0%;
  --z: 5;
}
.fig--operator {
  --l: 50.8%;
  --b: 2%;
  --z: 4;
}
.fig--montazher {
  --l: 73.5%;
  --b: 5%;
  --z: 2;
}

/* Выбрали одного — он выходит вперёд, остальные притухают. Горит всегда
   ровно один: наведение работает, только пока никого не выбрали фокусом
   или нажатием. Иначе нажали на телефоне по одному, сцена подъехала,
   курсор оказался над другим — и на экране две подписи разом.

   Свет и тень идут через drop-shadow, а не через рамку или подложку:
   этот фильтр считает форму по прозрачности картинки, поэтому лайм
   обходит человека по контуру. Маской по тому же файлу вышло бы
   чище, но страницу открывают и с диска, а по file:// браузер маску
   не грузит и фигура пропадает целиком.

   Лайм широкий и мягкий: узкий и плотный давал неоновую обводку,
   фигура читалась наклейкой, а не человеком под светом. */
.fig:is(:focus-within, .is-on),
.crew__figs:not(:has(.fig:is(:focus-within, .is-on))) .fig:hover {
  z-index: 9;
  transform: translateY(-2%) scale(1.03);
}
.fig:is(:focus-within, .is-on) .fig__ph,
.crew__figs:not(:has(.fig:is(:focus-within, .is-on))) .fig:hover .fig__ph {
  filter:
    drop-shadow(0 16px 22px rgba(17, 18, 20, 0.2))
    drop-shadow(0 0 20px rgba(200, 255, 46, 0.85));
}

/* притухают все, кроме горящего, и очерёдность здесь та же */
.crew__figs:has(.fig:is(:focus-within, .is-on)) .fig:not(:focus-within, .is-on),
.crew__figs:not(:has(.fig:is(:focus-within, .is-on))):has(.fig:hover)
  .fig:not(:hover) {
  opacity: 0.42;
}

/* Подписи. Стоят по верху сцены, каждая над своей фигурой: под ногами
   места нет, кадр обрезан по пояс. Крайние прижаты к краям сцены,
   остальные встают по центру своей фигуры. */
.crew__tags {
  position: absolute;
  inset: 0;
  z-index: 10;
  pointer-events: none;
}

.tag {
  position: absolute;
  top: 0;
  width: min(240px, 32%);
  padding-left: 12px;
  border-left: 3px solid var(--lime);
  transform: translateX(-50%);
  translate: 0 -8px;
  opacity: 0;
  transition: opacity 0.26s ease, translate 0.26s ease;
}
/* каждая подпись стоит над серединой своей фигуры; крайние прижаты
   к краям сцены, иначе вылезли бы за кадр */
.tag--avtor {
  left: 0;
  transform: none;
}
.tag--scenarist { left: 28.2%; }
.tag--rezhisser { left: 46.6%; }
.tag--operator { left: 69.2%; }
.tag--montazher {
  right: 0;
  left: auto;
  transform: none;
}

.tag__role {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--display);
  font-size: clamp(17px, 1.5vw, 21px);
  font-weight: 500;
  letter-spacing: 0.04em;
  line-height: 1.1;
  text-transform: uppercase;
}
.tag__role .ico {
  width: 19px;
  height: 19px;
}

.tag__when {
  margin-top: 6px;
  color: var(--mut);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.14em;
  line-height: 1.4;
  text-transform: uppercase;
}

/* имя приходит от заказчика и встаёт под ролью. Пока имён нет, все
   пять строк лежат подряд в .crew__names с hidden, а crew.js
   расставляет их по подписям */
.tag__name {
  margin-top: 7px;
  font-size: 14px;
  letter-spacing: 0.02em;
}

.tag__what {
  margin-top: 8px;
  color: var(--mut);
  font-size: 12.5px;
  line-height: 1.5;
}

/* Подпись загорается вместе со своей фигурой, и очерёдность та же:
   наведение работает, пока никого не выбрали фокусом или нажатием. */
.crew__plane:has(.fig--avtor:is(:focus-within, .is-on)) .tag--avtor,
.crew__plane:has(.fig--scenarist:is(:focus-within, .is-on)) .tag--scenarist,
.crew__plane:has(.fig--rezhisser:is(:focus-within, .is-on)) .tag--rezhisser,
.crew__plane:has(.fig--operator:is(:focus-within, .is-on)) .tag--operator,
.crew__plane:has(.fig--montazher:is(:focus-within, .is-on)) .tag--montazher,
.crew__plane:not(:has(.fig:is(:focus-within, .is-on))):has(.fig--avtor:hover) .tag--avtor,
.crew__plane:not(:has(.fig:is(:focus-within, .is-on))):has(.fig--scenarist:hover) .tag--scenarist,
.crew__plane:not(:has(.fig:is(:focus-within, .is-on))):has(.fig--rezhisser:hover) .tag--rezhisser,
.crew__plane:not(:has(.fig:is(:focus-within, .is-on))):has(.fig--operator:hover) .tag--operator,
.crew__plane:not(:has(.fig:is(:focus-within, .is-on))):has(.fig--montazher:hover) .tag--montazher {
  opacity: 1;
  translate: 0 0;
}

/* Подсказка стоит перед сценой: без неё сцена выглядит просто
   картинкой, и никто не догадается по ней возить мышью. Внутрь сцены
   её класть нельзя — на телефоне она уехала бы вбок вместе с кадром. */
.crew__hint {
  margin-bottom: clamp(8px, 1vw, 12px);
  color: var(--mut);
  font-size: 12.5px;
  line-height: 1.5;
}

/* Подсказку про прокрутку показываем только там, где сцена правда шире
   окна. Ширина порога зависит и от полей страницы, поэтому решает не
   медиазапрос, а измерение: класс is-wide ставит crew.js. */
.crew__drag {
  display: none;
  margin-top: clamp(10px, 1.4vw, 16px);
  color: var(--mut);
  font-size: 12.5px;
  line-height: 1.5;
}
.crew.is-wide .crew__drag { display: block; }

.team__why {
  max-width: 62ch;
  margin-top: clamp(30px, 4vw, 46px);
  padding-top: clamp(18px, 2.4vw, 24px);
  border-top: 1px solid var(--line);
  color: var(--mut);
  font-size: 13px;
  line-height: 1.65;
}

/* Ноутбук и телефон: сцена перестаёт помещаться в окно целиком. Она
   не ломается на карточки, а становится шире окна и едет вбок — кадр
   остаётся кадром, просто человек проходит по нему взглядом.

   Ширина не в процентах, а порогом в пикселях: от процента сцена на
   640 раздувалась до 900 px высоты, а на 390 в окно попадала одна
   фигура. С порогом высота держится около 460 px на всех узких
   ширинах, на 390 в окне двое, на 768 — почти четверо. */
@media (max-width: 1000px) {
  .crew__plane {
    width: max(100%, 790px);
    /* полоса над головами та же по пикселям, что на широком экране,
       но сцена уже — значит доля полосы должна вырасти */
    aspect-ratio: 1.72 / 1;
  }
  /* сцена стала выше при той же ширине, а рост фигур считается от её
     высоты — доля уменьшается, чтобы пятеро остались того же размера */
  .crew__figs { --h: 57.7%; }
  .tag { width: min(220px, 26%); }
}

/* ── контакты ───────────────────────────────────────────────────────── */
.block--contacts .lead { margin-top: 18px; }

.cards {
  display: grid;
  /* min() держит колонку внутри экрана: без неё на узких ширинах
     появляется горизонтальная прокрутка */
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: 18px;
  margin-top: 30px;
  max-width: 760px;
}
.card {
  padding: 22px;
  background: var(--card);
  border: 1px solid var(--line-soft);
}
.card:hover { border-color: var(--line); }

.card__who {
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--mut);
}
/* оба контакта — ссылки, поэтому оба синие */
.card__tg {
  display: block;
  margin-top: 12px;
  color: var(--blue);
  font-family: var(--display);
  font-size: clamp(22px, 2.6vw, 30px);
  font-weight: 600;
  letter-spacing: 0.01em;
}
.card__tg:hover { text-decoration: underline; text-underline-offset: 5px; }
.card__tel {
  display: block;
  margin-top: 4px;
  color: var(--blue);
  font-size: 15px;
  letter-spacing: 0.04em;
}
.card__tel:hover { text-decoration: underline; text-underline-offset: 4px; }

/* ── подвал ─────────────────────────────────────────────────────────── */
.foot {
  border-top: 1px solid var(--line);
  padding-block: clamp(40px, 7vh, 80px);
}
.foot__in {
  display: grid;
  gap: 26px;
}
.foot__contacts {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 26px;
  font-size: 14px;
  letter-spacing: 0.04em;
}
.foot__contacts a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--blue);
}
.foot__contacts .ico { width: 16px; height: 16px; }
.foot__contacts a:hover { text-decoration: underline; text-underline-offset: 4px; }
.foot__note {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--mut);
}

/* ── капсула-меню ───────────────────────────────────────────────────
   Навигация страницы и связь: едет внизу экрана до самого низа, на всех
   ширинах. Разметка — в конце index.html, подсветка и полоска — app.js.

   Капсула должна читаться частью страницы, а не приклеенным виджетом,
   поэтому здесь нет ни градиентов, ни двух цветов в обводке, ни
   подпрыгивания: матовое стекло, тонкая граница и мягкая тень.

   Пузыри связи стоят отдельными кружками рядом с капсулой, а не внутри:
   их видно с любого места страницы и по ним удобно попадать пальцем. */
.cap {
  position: fixed;
  left: 50%;
  bottom: calc(14px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 10px;
  transition: opacity 0.2s ease, visibility 0.2s ease;
}

.cap__pill {
  position: relative;
  display: flex;
  align-items: stretch;
  gap: 2px;
  height: var(--cap-h);
  padding: 0 6px;
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  /* фолбэк там, где размытия нет: плотная белая заливка, иначе текст
     страницы просвечивал бы сквозь иконки */
  background: rgba(255, 255, 255, 0.94);
  box-shadow: 0 10px 30px rgba(17, 18, 20, 0.1);
}

@supports ((backdrop-filter: blur(20px)) or (-webkit-backdrop-filter: blur(20px))) {
  .cap__pill {
    background: rgba(255, 255, 255, 0.72);
    -webkit-backdrop-filter: blur(20px);
    backdrop-filter: blur(20px);
  }
}

/* Ссылка без подписи — 44 пикселя в ширину на всю высоту капсулы: меньше
   палец не берёт. Активная расширяется под подпись, остальные остаются
   как были, поэтому высота капсулы не меняется никогда, а ширина —
   только на переходе между разделами. */
.cap__link {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-width: 44px;
  /* снизу больше, чем сверху: иконка с подписью встают выше полоски
     прогресса, иначе подпись садится на неё */
  padding: 0 4px 5px;
  border-radius: 999px;
  color: var(--mut);
}
.cap__link .ico { width: 22px; height: 22px; }

.cap__word {
  font-size: 8px;
  font-weight: 600;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  white-space: nowrap;
}
/* подпись есть у всех пяти ссылок, но видна только у активной: имя для
   читалки нужно каждой, а пять подписей разом раздувают капсулу */
.cap__link:not(.is-here) .cap__word {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

.cap__link.is-here {
  padding: 0 10px 5px;
  color: var(--blue);
}
@media (hover: hover) {
  .cap__link:hover { color: var(--ink); }
  .cap__link.is-here:hover { color: var(--blue); }
}

/* полоска прогресса по нижнему краю капсулы: сколько страницы пройдено.
   Ширину ставит app.js через --progress, от 0 до 1 */
.cap__track {
  position: absolute;
  left: 18px;
  right: 18px;
  bottom: 5px;
  height: 2px;
  border-radius: 2px;
  background: var(--line-soft);
}
.cap__fill {
  display: block;
  height: 100%;
  border-radius: 2px;
  background: var(--blue);
  transform: scaleX(var(--progress, 0));
  transform-origin: left center;
}

/* пузырь связи: один, телеграм. Кнопок с номером на странице нет —
   номер остался строкой в контактах и в подвале */
.cap__calls {
  display: flex;
  gap: 8px;
}
.cap__ball {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 999px;
  box-shadow: 0 8px 22px rgba(17, 18, 20, 0.16);
}
.cap__ball .ico { width: 21px; height: 21px; }
.cap__ball--tg {
  background: var(--blue);
  color: var(--card);
}
@media (hover: hover) {
  .cap__ball:hover { box-shadow: 0 10px 26px rgba(17, 18, 20, 0.26); }
}

/* ── узкие экраны ───────────────────────────────────────────────────
   Кнопка шапки, сетка блоков и наклейка кейсов. Капсула отсюда и ниже. */
@media (max-width: 760px) {
  .block__in {
    grid-template-columns: 1fr;
    gap: 10px;
  }
  .idx { padding-top: 0; }

  #cases .block__body > .tape {
    --tape-top: -22px;
    --tape-left: -6px;
  }
}

/* До 560 капсула тянется почти во всю ширину с отступом 12 по краям.
   env(safe-area-inset-bottom) держит её выше системной полосы айфона. */
@media (max-width: 560px) {
  :root { --cap-h: 56px; --sign-h: 48px; }

  /* Знак встаёт по тому же краю, что и капсула внизу: на узком экране
     два круга по разным отступам читаются как два разных виджета. */
  .sign {
    top: calc(12px + env(safe-area-inset-top));
    left: 12px;
  }

  .cap {
    left: 12px;
    right: 12px;
    bottom: calc(12px + env(safe-area-inset-bottom));
    transform: none;
    gap: 8px;
  }
  .cap__pill {
    flex: 1;
    min-width: 0;
    padding: 0 4px;
  }
  /* Свободную ширину забирают сами ссылки, а не промежутки между ними:
     на 390 иконка с зазорами по бокам даёт цель в 26 пикселей, пальцем
     в такую не попасть. Активная ссылка идёт по размеру подписи. */
  .cap__link {
    flex: 1 1 0;
    min-width: 0;
    padding: 0 0 5px;
  }
  .cap__link.is-here {
    flex: 0 0 auto;
    padding: 0 6px 5px;
  }
  .cap__word { font-size: 7px; letter-spacing: 0.02em; }
  .cap__ball { width: 44px; height: 44px; }
  .cap__calls { gap: 6px; }
  .cap__track { left: 14px; right: 14px; }
}

@media (max-width: 420px) {
  .mark--foot .mark__num { font-size: 56px; }
  .cards { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition-duration: 0.001s !important; animation-duration: 0.001s !important; }
}

/* ── видоискатель и цвет от наведения ───────────────────────────────
   Два приёма поверх собранной страницы, оба глобальные.

   КУРСОР. Над медиа стрелка меняется на рамку видоискателя с лаймовой
   точкой посередине. Точка стоит ровно в горячей точке курсора, поэтому
   целиться она не мешает: попадаешь туда, где она стоит.

   Рамка нарисована прямо в строке — data:image/svg+xml, 48×48. Ни
   картинки, ни своего элемента, ни слежки за мышью на каждом кадре:
   курсор рисует система, прокрутку это не трогает вообще. Обводка
   тёмная, под ней белый ореол — иначе рамка пропадает то на кадре
   ролика, то на молочном фоне.

   Зона узкая: телефоны, фотографии и кнопки кейсов. Над текстом,
   ссылками, капсулой и обычными кнопками курсор обычный — иначе он
   мешает читать и попадать. Сцена команды тоже осталась со своим
   курсором: у фигур уже есть свой отклик по наведению, и рамка поверх
   спорила бы с ним. Веер держит свои grab и grabbing, пока телефоны
   тащат: это отдельная работа мыши, и подменять её нечем.

   ЦВЕТ. Фотографии лежат чёрно-белыми и наливаются цветом под курсором.
   Кадры внутри телефонов сюда не попадают ни одним селектором: ролики
   всегда цветные, они и есть товар. Знаки клиентов тоже: одноцветный
   знак от обесцвечивания только портится.

   Оба приёма живут внутри (hover: hover) and (pointer: fine) — на
   телефоне и планшете курсора нет, а фотографии сразу цветные, и
   серыми они там не остаются. У курсора в том же запросе стоит
   prefers-reduced-motion: no-preference: попросили убавить движение —
   курсор обычный. */
:root {
  /* %23 — это «#»: внутри url решётка начинает якорь, и цвет обрывается.
     Значения из палитры: обводка --ink, ореол под ней белый, точка
     --lime. Других цветов в рамке нет.
     24 24 — горячая точка, середина рамки. */
  --aim: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='48' height='48' viewBox='0 0 48 48'%3E%3Cpath d='M7 16V7h9 M32 7h9v9 M41 32v9h-9 M16 41H7v-9' fill='none' stroke='%23ffffff' stroke-opacity='.92' stroke-width='4.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M7 16V7h9 M32 7h9v9 M41 32v9h-9 M16 41H7v-9' fill='none' stroke='%23111214' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3Ccircle cx='24' cy='24' r='4' fill='%23ffffff' fill-opacity='.92'/%3E%3Ccircle cx='24' cy='24' r='2.6' fill='%23c8ff2e' stroke='%23111214' stroke-width='1'/%3E%3C/svg%3E") 24 24;
}

@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  /* медиа, которое нажимают: телефон в веере, кнопки кейсов, кнопка
     воспроизведения. Запасной курсор — палец: если браузер не возьмёт
     svg, нажимаемое остаётся нажимаемым на вид */
  .fan__open,
  .pick,
  .phone__play { cursor: var(--aim), pointer; }

  /* медиа, которое просто лежит: корпус телефона на первом экране,
     в разборе и в лайтбоксе, и кадры со съёмок внутри разбора */
  .phone__body,
  .shot img { cursor: var(--aim), default; }
}

@media (hover: hover) and (pointer: fine) {
  /* Контраст чуть поднят: без цвета кадры со съёмок садятся в середину
     шкалы и становятся серой кашей. Мигать при прокрутке тут нечему —
     обесцвечивание стоит в стилях и ничего не ждёт от скрипта. */
  .shot img {
    filter: grayscale(1) contrast(1.04);
    transition: filter 0.35s ease;
  }

  .shot:hover img,
  .shot:focus-within img { filter: none; }
}
