/* Hallmark · genre: modern-minimal · macrostructure: Ledger/Schedule (ведомость чертежа)
 * design-system: DESIGN-SITE.md · токены: tokens.css · первый экран: hero.css (не трогаем)
 * enrichment: Tier C generated stills, ч/б + цветная техника · signature: выноска с числом
 * pre-emit critique: P5 H5 E5 S5 R4 V5
 *
 * Главная ниже первого экрана. Ритм секций намеренно РАЗНЫЙ, чтобы страница
 * не читалась одним шаблоном:
 *   услуги      — ведомость строками, цена на правом поле, как в счёте
 *   техника     — витрина неравных плиток: широкая, высокая, широкая + плотный список
 *   цены        — HTML-таблица, пять строк
 *   правила     — штамп: сетка ячеек, ни одного изображения
 *   вопросы     — две колонки, вопрос слева, ответ справа
 *   новости     — три колонки без картинок, моно-даты
 *   партнёрам   — широкая полоса: текст + список групп документов
 *   контакты    — СВЕТЛЫЙ ОСТРОВ, единственный на странице разрыв тёмного поля
 *   подвал      — плотная сетка ссылок и реквизитов
 */

:root {
  /* Продолжение короткой шкалы из tokens.css: большие прыжки, а не десяток
     близких размеров. 16 (база) → 24 → 28 → 48. */
  --text-h2:     clamp(1.75rem, 2.1vw + 1rem, 3rem);
  --text-h3:     clamp(1.125rem, 0.5vw + 1rem, 1.5rem);
  --text-price:  clamp(1.25rem, 0.9vw + 0.95rem, 1.75rem);
  --text-num-xl: clamp(1.625rem, 2.4vw + 0.9rem, 2.5rem);
  --text-sm:     0.875rem;                 /* 14 — подписи в плотных блоках */

  /* ─── Вертикальный ритм: три ступени, а не одна константа ──────────────────
     Было: --sec-pad 58.5px у всех девяти секций и разрыв 117px на каждом стыке —
     ровная гребёнка, в которой ни один переход не читается как новая глава.
     Стало: разрыв — свойство СТЫКА, а не секции. Каждая секция берёт сверху
     половину своего верхнего стыка, снизу — половину нижнего, поэтому суммы
     складываются в ровно три ступени: 80 / 176 / 280px на 1440.
       S 40  — секция продолжает мысль предыдущей (цены после техники);
       M 88  — соседняя тема внутри той же главы;
       L 140 — смена главы, разрыв обязан кричать.
     Единица clamp — vw, а не vh: ритм должен спорить с шириной колонки, а не
     с высотой окна. На vh страница на ноутбуке и на мониторе дышала по-разному
     при одинаковой длине строки. */
  --step-s: clamp(24px, 2.8vw, 40px);
  --step-m: clamp(44px, 6.2vw, 88px);
  --step-l: clamp(64px, 9.8vw, 140px);
  --sec-pad: var(--step-m);                /* дефолт стыка, если вес не задан */

  /* Ширина «листа» — текстовых блоков со строками и колонками. Секция может
     быть во всю страницу (полоса кадра, витрина техники, штамп), а ведомость,
     вопросы и таблица цен ограничены: без ограничения на 1920 между текстом
     и ценовым полем оставалось около 700px пустоты, потому что колонка тянется,
     а её содержимое упирается в 62ch. Замер на рендере 1920, до правки. */
  --sheet: 1320px;

  /* Продолжение шкалы слоёв из tokens.css (--z-frame … --z-nav: 4).
     Именованный слой, а не «z-index: 60»: произвольные числа — прямой путь
     к тому, что через месяц два элемента подерутся за верх. */
  --z-tray: 5;
}

/* ───────────────────────── Обвязка секции ─────────────────────────────────
   Полосы контента живут в одной коробке 1720 с полями --gutter, как первый
   экран. Полнокадровые полосы выходят за поля отрицательным отступом ровно
   на величину поля — переполнения по горизонтали при этом не возникает. */
.sec {
  /* width:100% обязателен: main — колоночный флекс, а `margin-inline:auto`
     у флекс-элемента отменяет растягивание, и секция садится по содержимому.
     Замерено на рендере 1440: «Цены» ужимались до 899px и уезжали в центр,
     «Правила» до 827px, «Вопросы» до 1205px — при соседних секциях на 1440.
     Метрике переполнения здесь верить нельзя, дефект видно только глазами. */
  width: 100%;
  max-width: 1720px;
  margin-inline: auto;
  padding: var(--pt, var(--sec-pad)) var(--gutter) var(--pb, var(--sec-pad));
  border-top: var(--hair) solid var(--edge);
}
.sec:first-of-type { border-top: 0; }

/* Вес стыка проставляется в разметке: --t-* сверху, --b-* снизу. Раскладка
   по главной: hero→calc S · calc→services M · services→fleet M · fleet→prices S
   · prices→why S · why→faq L · faq→news S · news→partners S · partners→contacts M.
   Единственный L — граница коммерческой части и справочной: до него страница
   продаёт, после него отвечает на вопросы. */
.sec--t-s { --pt: var(--step-s); }
.sec--t-m { --pt: var(--step-m); }
.sec--t-l { --pt: var(--step-l); }
.sec--b-s { --pb: var(--step-s); }
.sec--b-m { --pb: var(--step-m); }
.sec--b-l { --pb: var(--step-l); }

/* Стык hero→calc целиком лежит на верхнем поле калькулятора: у первого экрана
   padding-bottom НЕ трогаем. Проверено на рендере 1440 — от лишних 40px внизу
   коробка кадра подрастает, и нижняя выноска «Экипаж · входит в ставку»
   заезжает под штамп. Поэтому отдельная величина: целая малая ступень
   (80px на 1440, 48px на 375) — ровно то же число, что и сумма двух половин. */
.sec--t-s1 { --pt: clamp(48px, 5.6vw, 80px); }

/* Голова секции. Хайрлайн + моно-подпись на нём — как выноска на чертеже:
   подпись всегда сидит на линии, а не висит сама по себе. */
.sec__head { max-width: 60ch; }
.sec__kicker {
  margin: 0 0 var(--space-sm);
  display: flex; align-items: center; gap: var(--space-sm);
  font-family: var(--font-mono); font-size: var(--text-mono-label);
  letter-spacing: .04em; text-transform: uppercase; color: var(--label);
}
.sec__kicker::before {
  content: ""; width: 26px; height: var(--hair); background: var(--chrome-dim); flex: none;
}
.sec__title {
  margin: 0;
  font-family: var(--font-display);
  font-variation-settings: "SHRP" var(--shrp);
  font-weight: 700; font-size: var(--text-h2);
  line-height: 1.02; letter-spacing: -.03em; color: var(--text);
  text-wrap: balance;
  /* последняя возможность переноса внутри слова: на 320 длинное
     составное слово иначе вылезает за экран */
  overflow-wrap: anywhere; min-width: 0;
}
.sec__lead {
  margin: var(--space-md) 0 0;
  max-width: 56ch; color: var(--text-2); font-size: var(--text-lead); line-height: 1.5;
}
.sec__act {
  margin-top: var(--space-xl);
  display: flex; flex-wrap: wrap; gap: var(--space-sm);
}

/* Служебная сноска под блоком: мелко, но не мельче 12px. */
.note {
  margin: var(--space-md) 0 0;
  font-family: var(--font-mono); font-size: var(--text-mono-label); line-height: 1.6;
  color: var(--label); max-width: 72ch;
}

/* ═════════════════════════ 1. УСЛУГИ ══════════════════════════════════════ */

/* Полнокадровая полоса. Коробка кадра задана aspect-ratio и растянута
   min-width/min-height — ручной cover. В отличие от object-fit коробка
   остаётся коробкой снимка, поэтому процент внутри неё — это точка
   на машине, и выноска указывает туда, куда должна, при любой ширине. */
.band {
  position: relative;
  margin: var(--space-2xl) calc(var(--gutter) * -1) 0;
  height: clamp(220px, 34vw, 460px);
  display: grid; place-items: center;
  overflow: clip;
  background: var(--surface);
}
.band__stage {
  position: relative;
  aspect-ratio: 1600 / 681;
  width: auto; height: auto; min-width: 100%; min-height: 100%;
}
.band__img { display: block; width: 100%; height: 100%; }
/* Низ полосы уходит в графит — стык кадра и ведомости не читается швом. */
.band::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top, var(--graphite) 0%,
              color-mix(in oklch, var(--graphite) 40%, transparent) 9%, transparent 22%);
}
/* SIGNATURE. Наследует .mark из hero.css: точка → выносная линия → полка →
   моноширинная подпись с числом. Ниже 768 подпись уводится левее: на узком
   экране кадр кадрируется сильнее и точка уезжает к правому краю. */
.mark--svc { --x: 54%; --y: 40%; --len: clamp(34px, 6vw, 72px); z-index: var(--z-content); }
@media (max-width: 767px) { .mark--svc { --x: 46%; --y: 33%; --len: 28px; } }
/* На 320 подпись вылезала за правый край кадра и обрезалась: коробка снимка
   там шире экрана на 126px, а «БОЙ БЕТОНА И КИРПИЧА» моноширинным в одну
   строку занимает больше 200px. Ужимаем ПОДПИСЬ, а не двигаем точку: точка
   обязана остаться на машине, иначе выноска перестаёт быть выноской.
   9.5rem = 152px; при точке на 142px от левого края экрана правый край полки
   встаёт на 294 при экране 320 — запас 26px. Ключ переносится на две строки,
   это нормальная выносная надпись. */
@media (max-width: 479px) {
  .mark--svc { max-width: 9.5rem; }
  .mark--svc .mark__body { padding: var(--space-2xs) var(--space-xs) var(--space-xs); }
  .mark--svc .mark__key { line-height: 1.25; }
  .mark--svc .mark__val { font-size: var(--text-mono-label); }
}

/* ── Ведомость услуг. Строки, а не карточки: ни рамок, ни теней —
      разделяет хайрлайн, как графы в таблице чертежа. ─────────────────────── */
.ledger { list-style: none; margin: 0; padding: 0; max-width: var(--sheet); }
.ledger__row {
  display: grid;
  grid-template-columns: minmax(0, 236px) minmax(0, 1fr) max-content;
  align-items: start;
  gap: var(--space-lg) clamp(var(--space-md), 2.4vw, var(--space-2xl));
  padding: var(--space-lg) 0;
  border-top: var(--hair) solid var(--edge);
}
.ledger__row:first-child { border-top: 0; padding-top: var(--space-xl); }
/* Строка без кадра держит ту же графу: колонка названий не должна прыгать
   от строки к строке — в ведомости это первое, что читается как небрежность.
   Раньше графа при этом оставалась ПУСТОЙ (задумка «графа эскиза без эскиза»),
   и владелец прочитал это как недоделку: «где-то картинки есть, а где-то нет,
   и даже заглушек нет». Решение владельца перевешивает задумку — рисуем ту же
   честную заглушку, что в каталоге техники и на страницах категорий,
   но в пропорции ведомости 3:2, а не 1.6:1. */
.ledger__shot .noshot { aspect-ratio: 3 / 2; padding: var(--space-sm); }
.ledger__shot .noshot__mark { left: var(--space-sm); top: var(--space-sm); width: 16px; height: 16px; }
/* Пояснения «Снимаем машину на объекте…» в ведомости нет и в разметке:
   в графе 236px оно переносится на пять строк и вылезает за поле, а прятать
   его через display:none — держать в HTML текст, которого никто не увидит.
   Ключа «КАДР ГОТОВИМ» здесь хватает: ставка стоит в той же строке справа,
   и человеку сразу видно, что отсутствие кадра на цену не влияет. */

.ledger__shot { margin: 0; grid-column: 1; }
.ledger__shot img {
  display: block; width: 100%; height: auto; aspect-ratio: 3 / 2;
  object-fit: cover; background: var(--surface);
}
.ledger__body { grid-column: 2; min-width: 0; }

.ledger__name {
  margin: 0;
  font-family: var(--font-display);
  font-variation-settings: "SHRP" var(--shrp);
  font-weight: 600; font-size: var(--text-h3);
  line-height: 1.12; letter-spacing: -.02em; color: var(--text);
  overflow-wrap: anywhere; min-width: 0;
}
.ledger__text {
  margin: var(--space-xs) 0 0;
  color: var(--text-2); line-height: 1.55; max-width: 62ch;
}

/* Правое поле — цена. Выравнивание по правому краю и tabular-nums:
   колонка цифр стоит в столбик, как в счёте. */
.ledger__price { grid-column: 3; text-align: right; min-width: 0; }
.ledger__rate {
  display: block; white-space: nowrap;
  font-family: var(--font-mono); font-weight: 600; font-size: var(--text-price);
  line-height: 1.15; letter-spacing: -.03em;
  color: var(--chrome); font-variant-numeric: tabular-nums;
}
.ledger__rate + .ledger__rate { margin-top: var(--space-2xs); }
.ledger__unit {
  font-size: var(--text-mono-label); font-weight: 400; color: var(--text-2);
  letter-spacing: 0;
}
.ledger__for {
  display: block; margin-top: var(--space-3xs);
  font-family: var(--font-mono); font-size: var(--text-mono-label);
  text-transform: uppercase; letter-spacing: .04em; color: var(--label);
  white-space: nowrap;
}

/* Первая строка — флагман. Крупнее по типографике, кадр у неё — полоса выше. */
.ledger__row--lead { padding-top: var(--space-xl); }
.ledger__row--lead .ledger__name { font-size: clamp(1.375rem, 1.4vw + 1rem, 2rem); }
.ledger__row--lead .ledger__text { font-size: var(--text-lead); }

/* ═════════════════════════ 2. ТЕХНИКА ═════════════════════════════════════
   Плитки намеренно РАЗНОГО веса: широкая, высокая на два ряда, широкая.
   Одинаковых плиток с иконкой и строкой текста здесь нет — в каждой
   реальная ставка из прайса. */
/* Зазор между плитками — не волосок, по тому же замечанию заказчика 03.09.2026,
   что и в каталоге: кадры стыковались краями и читались одной лентой. Хайрлайн
   больше не может быть фоном контейнера — на зазоре в 24px он стал бы широкой
   светлой полосой между плитками. Поэтому кромку рисует обводка КАЖДОЙ плитки,
   ровно как в .units каталога и в .rules штампа: outline не занимает места,
   а пустой хвост ряда остаётся графитом. */
.fleet {
  margin-top: var(--space-2xl);
  display: grid;
  grid-template-columns: minmax(0, 1.62fr) minmax(0, 1fr);
  gap: var(--space-lg);
}
.unit {
  position: relative; margin: 0; min-width: 0;
  background: var(--graphite);
  display: flex; flex-direction: column;
}
/* Обводка — только плиткам витрины, и селектор с потомком тут обязателен.
   Класс .unit носят ещё и три карточки сценариев расчёта на главной, а они
   САМИ являются ссылками. Кольцо фокуса в проекте описано через
   :where(a, button, [tabindex]):focus-visible — у :where() специфичность
   нулевая, поэтому простое .unit { outline } перебивало кольцо и с клавиатуры
   оставалась серая кромка 1.28:1 вместо янтарного кольца. Здесь .unit —
   это figure, ссылок в нём нет, конфликта нет. */
.fleet > .unit { outline: var(--hair) solid var(--edge); }
/* Высокая плитка занимает два ряда, поэтому её высоту задаёт не свой
   контент, а сумма двух соседних плиток слева. Раньше окно кадра забирало
   весь этот остаток через `flex: 1` — то есть ФОРМА кадрового окна
   получалась из объёма ЧУЖОГО текста и менялась при каждой правке
   соседей. 27.08.2026 кадр автовышки сняли вертикальным ровно под
   тогдашние 0,72 (то же число в tools/build_media.py), 28.08 в соседних
   плитках прибавилось по строке про высоты и смену — окно стало 0,44,
   и object-fit: cover срезал 38% ширины: кабина машины ушла за левый край,
   а нижнюю треть занял пустой асфальт. Заказчик 31.08: «Съехало фото».
   Теперь пропорция окна названа числом и равна пропорции самого кадра —
   съехать от чужого текста она больше не может.

   ⚠ Остаток высоты (на 1440 это 433 px — замер) отдан НИЗУ, а не зазору
   между кадром и подписью. Прежний space-between сажал подпись на нижний
   край, вровень с подписью соседней плитки, и между фотографией и её
   собственным названием зияло пустое поле в треть плитки: подпись читалась
   как ничья. Решение владельца 01.09.2026 — подпись идёт сразу под кадром,
   пустота уходит под текст. Плата за это принята осознанно: подписи высокой
   и соседней плитки больше не стоят на одной линии. */
.unit--tall { grid-row: span 2; justify-content: flex-start; }
.unit__shot { position: relative; overflow: clip; background: var(--surface); }
.unit__shot img { display: block; width: 100%; height: 100%; object-fit: cover; }
.unit--wide .unit__shot { aspect-ratio: 16 / 9; }
.unit--tall .unit__shot { flex: 0 1 auto; aspect-ratio: 760 / 1056; min-height: 260px; }
.unit--tall .unit__shot img { position: absolute; inset: 0; }

.unit__body {
  padding: var(--space-md) var(--space-lg) var(--space-lg);
  display: grid; gap: var(--space-xs);
  border-top: var(--hair) solid var(--edge);
}
.unit__name {
  margin: 0;
  font-family: var(--font-display);
  font-variation-settings: "SHRP" var(--shrp);
  font-weight: 600; font-size: var(--text-h3); line-height: 1.1;
  letter-spacing: -.02em; color: var(--text);
  overflow-wrap: anywhere; min-width: 0;
}
/* Полка со ставкой — тихая производная от выноски: та же полка и та же
   моноширинная подпись, но без выносной линии. Полный приём живёт
   на первом экране и на полосе сноса, здесь он не должен спорить. */
.unit__rate {
  margin: 0; display: flex; align-items: baseline; gap: var(--space-xs);
  padding-top: var(--space-xs);
  border-top: 2px solid var(--chrome);
  width: max-content; max-width: 100%;
}
.unit__num {
  font-family: var(--font-mono); font-weight: 600; font-size: var(--text-price);
  line-height: 1.1; letter-spacing: -.03em;
  color: var(--chrome); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.unit__per { font-family: var(--font-mono); font-size: var(--text-mono-label); color: var(--text-2); }
.unit__meta {
  margin: 0; font-family: var(--font-mono); font-size: var(--text-mono-label);
  line-height: 1.6; color: var(--label);
}
.unit__meta b { color: var(--text-2); font-weight: 400; }

/* Витрина обязана быть входом в каталог, а не тупиком: название ведёт
   на карточку машины или на свою строку прайса, под ставкой — строка выхода.
   Раньше отсюда не вело ни одной ссылки, и полный прайс на 21 позицию
   с главной был недостижим вообще. */
/* Область нажатия набирается вертикальными полями, а не ростом шрифта:
   замер на 375 давал 199×24 при норме 44. Отрицательное поле гасит прирост,
   чтобы заголовок плитки не отъехал от ставки. */
.unit__name a {
  display: inline-block;
  padding-block: 12px; margin-block: -12px;
  color: inherit; text-decoration: none;
  border-bottom: var(--hair) solid var(--edge-strong);
}
.unit__link {
  margin: 0; font-family: var(--font-mono); font-size: var(--text-mono-label);
  line-height: 1.5;
}
.unit__link a {
  display: inline-flex; align-items: center; min-height: 44px;
  color: var(--text-2); text-decoration: underline;
  text-underline-offset: 3px; text-decoration-color: var(--edge-strong);
}
.unit__link a::after { content: " →"; color: var(--chrome-dim); white-space: pre; }
@media (hover: hover) and (pointer: fine) {
  .unit__name a:hover { color: var(--green-signal); border-bottom-color: var(--green-signal); }
  .unit__link a:hover { color: var(--green-signal); text-decoration-color: var(--green-signal); }
}

/* Плотный список остального парка — приборная упаковка внутри воздушной сетки. */
.fleet__rest {
  grid-column: 1 / -1;
  background: var(--graphite);
  outline: var(--hair) solid var(--edge);
  padding: var(--space-lg) var(--space-lg) var(--space-md);
}
.fleet__rest h3 {
  margin: 0 0 var(--space-md);
  font-family: var(--font-mono); font-size: var(--text-mono-label);
  letter-spacing: .04em; text-transform: uppercase; color: var(--label); font-weight: 400;
}
.rest {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0 clamp(var(--space-lg), 3vw, var(--space-3xl));
}
/* Строка списка — ссылка на свою позицию прайса. Раскладка перенесена
   с li на a целиком: кликается вся строка, а не одно название. */
.rest li { border-bottom: var(--hair) solid var(--edge); }
.rest li a {
  display: flex; align-items: baseline; gap: var(--space-sm);
  min-height: 44px; padding: var(--space-xs) 0;
  text-decoration: none; color: inherit;
  transition: color var(--dur-short) var(--ease-out);
}
/* Расшифровка обозначения рядом с названием: «10/7» снабженец читает с ходу,
   обычный заказчик — нет, а спросить ему некого. */
.rest__hint {
  display: block;
  font-family: var(--font-mono); font-size: var(--text-mono-label);
  color: var(--label);
}
@media (hover: hover) and (pointer: fine) {
  .rest li a:hover { color: var(--green-signal); }
  .rest li a:hover .rest__name { color: inherit; }
  .rest li a:hover .rest__rate { color: inherit; }
}
/* Отточие между названием и ставкой — приём прайс-листа, а не веб-карточки. */
.rest__dots {
  flex: 1; min-width: var(--space-md); align-self: center;
  border-bottom: var(--hair) dotted var(--edge-strong);
  translate: 0 -2px;
}
.rest__name { color: var(--text-2); min-width: 0; }
.rest__rate {
  font-family: var(--font-mono); font-weight: 600; color: var(--chrome);
  font-variant-numeric: tabular-nums; white-space: nowrap; font-size: var(--text-sm);
}

/* ═════════════════════════ 3. ЦЕНЫ НА ВЫВОЗ ═══════════════════════════════ */
.tariff-wrap { margin-top: var(--space-xl); max-width: var(--sheet); overflow-x: auto; }
.tariff {
  width: 100%; border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}
.tariff caption {
  caption-side: bottom; text-align: left;
  padding-top: var(--space-md);
  font-family: var(--font-mono); font-size: var(--text-mono-label); line-height: 1.6;
  color: var(--label);
}
.tariff th, .tariff td {
  text-align: left; padding: var(--space-sm) var(--space-md);
  border-bottom: var(--hair) solid var(--edge); vertical-align: baseline;
}
.tariff thead th {
  font-family: var(--font-mono); font-size: var(--text-mono-label); font-weight: 400;
  letter-spacing: .04em; text-transform: uppercase; color: var(--label);
  border-bottom-color: var(--edge-strong);
}
.tariff tbody th {
  font-weight: 600; color: var(--text); padding-left: 0; white-space: nowrap;
}
.tariff__what { color: var(--text-2); }
.tariff__price {
  text-align: right; white-space: nowrap; padding-right: 0;
  font-family: var(--font-mono); font-weight: 600; color: var(--chrome);
}
.tariff__price span { font-size: var(--text-mono-label); font-weight: 400; color: var(--text-2); }

/* ═════════════════════════ 4. ПРАВИЛА (штамп) ═════════════════════════════
   Ни одного изображения: только цифры и подписи. Ячейки сидят по содержимому,
   как графы основной надписи чертежа. */
.rules {
  margin-top: var(--space-xl);
  display: grid; grid-template-columns: repeat(auto-fit, minmax(228px, 1fr));
  gap: var(--hair);
}
/* Хайрлайн рисует ОБВОДКА каждой ячейки, а не фон контейнера, просвечивающий
   в зазорах. Причина замерена на 768: там сетка ложится 3+2, и шестая ячейка
   пустая — фон контейнера показывал на её месте светлый прямоугольник.
   Обводка не влияет на раскладку и у пустого места её просто нет. */
.rules__cell {
  outline: var(--hair) solid var(--edge);
  background: var(--graphite);
  padding: var(--space-md) var(--space-lg) var(--space-lg);
  display: grid; gap: var(--space-2xs); align-content: start;
}
.rules__key {
  font-family: var(--font-mono); font-size: var(--text-mono-label);
  letter-spacing: .05em; text-transform: uppercase; color: var(--label);
}
.rules__val {
  font-family: var(--font-display);
  font-variation-settings: "SHRP" var(--shrp);
  font-weight: 600; font-size: clamp(1.25rem, 1.2vw + .85rem, 1.75rem);
  line-height: 1.05; letter-spacing: -.03em; color: var(--text);
  font-variant-numeric: tabular-nums; overflow-wrap: anywhere; min-width: 0;
  /* Под значение резервируются две строки: у «НДС 22%» пояснение переносится,
     у «28» нет, и без резерва подписи в соседних графах вставали на разной
     высоте — в штампе это первое, что читается как небрежность.
     em-версия стоит фолбэком для браузера без единицы lh. */
  min-height: 2.2em;
  min-height: 2lh;
}
.rules__val small { font-family: var(--font-body); font-weight: 400; font-size: var(--text-sm); color: var(--text-2); letter-spacing: 0; }
.rules__note { margin: var(--space-2xs) 0 0; color: var(--text-2); font-size: var(--text-sm); line-height: 1.5; }

/* ═════════════════════════ 5. ВОПРОСЫ И ОТВЕТЫ ════════════════════════════
   Две колонки: вопрос слева, ответ справа. Текст виден целиком и лежит
   в HTML — краулеры нейросетей JS не исполняют, а прятать ответ в аккордеон
   значит отдать им пустую страницу. */
.faq { margin-top: var(--space-xl); max-width: var(--sheet); }
.faq__item {
  display: grid; grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
  gap: var(--space-md) clamp(var(--space-lg), 4vw, var(--space-3xl));
  padding: var(--space-lg) 0;
  border-top: var(--hair) solid var(--edge);
}
.faq__item:first-child { border-top: 0; padding-top: var(--space-md); }
.faq__q {
  margin: 0;
  font-family: var(--font-display);
  font-variation-settings: "SHRP" var(--shrp);
  font-weight: 600; font-size: var(--text-h3); line-height: 1.15;
  letter-spacing: -.02em; color: var(--text); text-wrap: balance;
  overflow-wrap: anywhere; min-width: 0;
}
.faq__a { margin: 0; color: var(--text-2); line-height: 1.6; max-width: 68ch; }
.faq__a b { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }

/* ═════════════════════════ 6. НОВОСТИ ═════════════════════════════════════ */
.news {
  list-style: none; margin: var(--space-xl) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--hair);
  background: var(--edge); border-top: var(--hair) solid var(--edge);
}
.news__item {
  background: var(--graphite);
  padding: var(--space-md) var(--space-lg) var(--space-lg) 0;
  display: grid; gap: var(--space-xs); align-content: start;
}
.news__item + .news__item { padding-left: var(--space-lg); }
.news__meta {
  display: flex; flex-wrap: wrap; gap: var(--space-sm);
  font-family: var(--font-mono); font-size: var(--text-mono-label);
  letter-spacing: .04em; text-transform: uppercase; color: var(--label);
}
/* Без разделителя «ТЕМА В РАБОТЕ» и рубрика читались одной строкой:
   зазора в 12px моноширинному шрифту не хватает, чтобы их развести. */
.news__meta span + span::before { content: "· "; color: var(--chrome-dim); }
.news__stub { color: var(--chrome-dim); }
.news__title {
  margin: 0;
  font-family: var(--font-display);
  font-variation-settings: "SHRP" var(--shrp);
  font-weight: 600; font-size: 1.0625rem; line-height: 1.2;
  letter-spacing: -.02em; color: var(--text-2);
  overflow-wrap: anywhere; min-width: 0;
}
/* Заголовок новости — самостоятельный переход, а не слово внутри абзаца.
   Замер до правки: цвет доставался браузеру (#0000EE), 2.01:1 на графите
   при норме AA 4.5:1. Берём тот же приём, что у остальных названий-ссылок
   сайта: цвет текста, подчёркивание хромом, зелёный сигнал на наведении. */
.news__title a {
  color: inherit;
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--chrome-dim);
}
@media (hover: hover) and (pointer: fine) {
  .news__title a:hover { color: var(--green-signal); text-decoration-color: var(--green-signal); }
}

/* ═════════════════════════ 7. ПАРТНЁРАМ ═══════════════════════════════════ */
.partners {
  margin-top: var(--space-xl); max-width: var(--sheet);
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 22rem);
  gap: clamp(var(--space-lg), 4vw, var(--space-3xl));
  align-items: start;
}
.partners__text p { margin: 0 0 var(--space-md); color: var(--text-2); line-height: 1.6; max-width: 58ch; }
/* Заголовок и первый абзац шли вплотную: у .sec__title margin 0, у абзаца
   верхнего поля не было, и выносные элементы букв почти касались строки. */
.partners__text .sec__title + p { margin-top: var(--space-md); }
.docs { list-style: none; margin: 0; padding: 0; border-top: var(--hair) solid var(--edge-strong); }
.docs li {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-md);
  padding: var(--space-sm) 0; border-bottom: var(--hair) solid var(--edge);
  font-family: var(--font-mono); font-size: var(--text-sm); color: var(--text-2);
}
.docs b { color: var(--chrome); font-weight: 600; letter-spacing: .04em; }
.docs span { color: var(--label); font-size: var(--text-mono-label); text-align: right; }

/* ═════════════════════════ 8. КОНТАКТЫ · СВЕТЛЫЙ ОСТРОВ ═══════════════════
   Единственный светлый блок страницы и единственное место, где решается
   заявка. Тёмный экран на улице работает зеркалом — светлый остров ровно
   там, где человек читает номер и жмёт кнопку (DESIGN-SITE.md). */
.island {
  width: 100%;                 /* та же причина, что у .sec: body — колоночный флекс */
  max-width: 1720px; margin-inline: auto;
  padding: var(--pt, var(--sec-pad)) var(--gutter) var(--pb, var(--sec-pad));
  background: var(--light-surface); color: var(--light-text);
}
.island__grid {
  max-width: var(--sheet);
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 24rem);
  gap: clamp(var(--space-lg), 4vw, var(--space-3xl));
  align-items: start;
}
.island .sec__kicker { color: color-mix(in oklch, var(--light-text) 72%, transparent); }
.island .sec__kicker::before { background: color-mix(in oklch, var(--light-text) 45%, transparent); }
.island .sec__title { color: var(--light-text); }

.island__tel {
  /* Область нажатия 44px набирается min-height. Подчёркивание рисует сам
     текст, а не бордюр: бордюр уезжал на 8px от базовой линии и читался
     жирной чертой под номером, а не подчёркиванием. */
  display: inline-flex; align-items: center; min-height: 44px;
  margin: var(--space-lg) 0 0 calc(var(--space-2xs) * -1);
  padding-inline: var(--space-2xs);
  font-family: var(--font-mono); font-weight: 600; font-size: var(--text-num-xl);
  line-height: 1.1; letter-spacing: -.04em;
  color: var(--light-text); font-variant-numeric: tabular-nums;
  text-decoration: underline; text-decoration-color: var(--green-brand);
  text-decoration-thickness: 2px; text-underline-offset: 3px;
}
.island__rows { list-style: none; margin: var(--space-lg) 0 0; padding: 0; }
.island__rows li {
  display: grid; grid-template-columns: minmax(0, 8.5rem) minmax(0, 1fr);
  gap: var(--space-md);
  padding: var(--space-sm) 0; border-top: var(--hair) solid var(--light-edge);
  line-height: 1.5;
}
.island__k {
  font-family: var(--font-mono); font-size: var(--text-mono-label);
  letter-spacing: .04em; text-transform: uppercase;
  color: color-mix(in oklch, var(--light-text) 68%, transparent);
}
.island__v { min-width: 0; overflow-wrap: anywhere; }
/* Отрицательные поля компенсируют padding: строка не раздувается, а высота
   области нажатия растёт с 20 до 44px — замер показал 145×20, для пальца мало. */
.island__v a {
  display: inline-flex; align-items: center; min-height: 44px;
  padding-inline: var(--space-2xs); margin: -12px calc(var(--space-2xs) * -1);
  color: var(--light-text); text-decoration: underline; text-underline-offset: 3px;
}

.island__act { display: grid; gap: var(--space-sm); }
.island__act .btn { width: 100%; }
.island .btn--ghost { color: var(--light-text); border-color: color-mix(in oklch, var(--light-text) 42%, transparent); }
.island__small {
  margin: var(--space-sm) 0 0;
  font-family: var(--font-mono); font-size: var(--text-mono-label); line-height: 1.6;
  color: color-mix(in oklch, var(--light-text) 74%, transparent);
}
@media (hover: hover) and (pointer: fine) {
  .island .btn--ghost:hover { border-color: var(--light-text); background: color-mix(in oklch, var(--light-text) 6%, transparent); }
  .island__tel:hover { text-decoration-color: var(--green-hi); }
}

/* ═════════════════════════ 9. ПОДВАЛ ══════════════════════════════════════
   Ровно тот же подвал, что на /ceny/ и на карточке машины. Раньше здесь была
   своя раскладка со своими же реквизитами — и они разошлись с внутренними
   страницами («ИСПОЛНИТЕЛЬ» против «КОМПАНИЯ», капс в названии, другая
   запись адреса). Разные подвалы на одном сайте — это не разнообразие,
   а расхождение в реквизитах, которое владелец замечает первым.

   Правила скопированы из pages.css сознательно: сборки у превью пока нет,
   а подключать pages.css к главной нельзя — там свои .rules и .island,
   которые перекрыли бы блоки главной. */
.sheet {
  width: 100%; max-width: 1720px; margin-inline: auto;
  padding-inline: var(--gutter);
}
.foot { border-top: var(--hair) solid var(--edge); background: var(--surface); margin-top: auto; }
/* Графы соразмерны содержимому, а не равны механически: первая держит
   название и описание, последние две — списки ссылок. Раньше все четыре были
   по 1fr, и графа «Разделы» с 14 пунктами тянулась на 706px при соседях
   в 100–180px — подвал читался как один столбец справа и пустое поле слева. */
.foot__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, .85fr);
  gap: 0;
}
.foot__cell { padding: var(--space-lg); border-left: var(--hair) solid var(--edge); min-width: 0; }
.foot__cell:first-child { border-left: 0; padding-left: 0; }
.foot__cell:last-child { padding-right: 0; }
.foot__key {
  display: block; margin-bottom: var(--space-xs);
  font-family: var(--font-mono); font-size: var(--text-mono-label);
  letter-spacing: .05em; text-transform: uppercase; color: var(--label);
}
.foot__val { margin: 0; color: var(--text-2); line-height: 1.6; }
.foot__val strong { color: var(--text); font-weight: 600; }
.foot__links { list-style: none; margin: 0; padding: 0; }
/* Замер: строки-ссылки стояли встык (зазор 0 при норме 8px) — на телефоне
   промах уводил в соседний раздел. 8px разводит области нажатия и заодно
   даёт списку воздух, которого раньше не было. */
.foot__links li + li { margin-top: 8px; }
/* Замер до правки: телефон 131×38 и почта 145×38 при норме 44 — для пальца
   мало, а это единственный способ связаться из подвала. Ссылки разделов —
   во всю ширину графы: строка целиком кликабельна, а не одно слово (было 43px
   ширины у «Цены»). */
.foot__links a, .foot__val a {
  display: inline-flex; align-items: center; min-height: 44px;
  padding-block: 6px;
  color: var(--text-2); text-decoration: none;
}
.foot__links a { display: flex; }
.foot__val a { text-decoration: underline; text-underline-offset: 3px; }
@media (hover: hover) and (pointer: fine) {
  .foot__links a:hover, .foot__val a:hover { color: var(--green-signal); }
}
.foot__val--addr { margin-top: var(--space-sm); }
.foot__legal {
  border-top: var(--hair) solid var(--edge);
  padding-block: var(--space-md);
  font-family: var(--font-mono); font-size: var(--text-mono-label); line-height: 1.7; color: var(--label);
}
.foot__note { margin: 0; }
/* Документы и служебные страницы — сноска под основной надписью, не раздел
   сайта. Разделитель рисуется точкой между пунктами, а не символом в тексте:
   скринридер читает список из четырёх ссылок, а не одну строку с точками. */
.foot__docs {
  list-style: none; margin: var(--space-xs) 0 0; padding: 0;
  display: flex; flex-wrap: wrap; column-gap: var(--space-md);
}
.foot__docs li { display: flex; align-items: center; }
/* Разделитель ставится ПОСЛЕ пункта, а не перед следующим: при переносе строки
   точка остаётся в хвосте предыдущей строки, а не висит маркером в начале новой
   (замер на 768: со скобкой ::before вторая строка начиналась с «·»). */
.foot__docs li:not(:last-child)::after {
  content: "·"; margin-left: var(--space-md); color: var(--label);
}
/* На узком экране пункты встают столбцом — разделитель там лишний. */
@media (max-width: 559px) {
  .foot__docs { flex-direction: column; }
  .foot__docs li:not(:last-child)::after { content: none; }
}
/* Правовая строка: три самостоятельных перехода, а не слова в предложении.
   Замер до правки: цвет браузерный (#0000EE), 1.84:1 на графите при норме 4.5,
   область нажатия по высоте строки вместо 44px. Правило повторяет tpl.css —
   главная собрана вручную и tpl.css не подключает. */
.foot__legal a {
  display: inline-flex; align-items: center; min-height: 44px;
  color: var(--text-2);
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--chrome-dim);
}
@media (hover: hover) and (pointer: fine) {
  .foot__legal a:hover { color: var(--green-signal); text-decoration-color: var(--green-signal); }
}
@media (max-width: 1023px) {
  .foot__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .foot__cell { padding: var(--space-md); }
  .foot__cell:nth-child(odd) { border-left: 0; padding-left: 0; }
  .foot__cell:nth-child(even) { padding-right: 0; }
  .foot__cell:nth-child(n+3) { border-top: var(--hair) solid var(--edge); }
}
@media (max-width: 559px) {
  .foot__grid { grid-template-columns: minmax(0, 1fr); }
  .foot__cell { border-left: 0; padding-inline: 0; border-top: var(--hair) solid var(--edge); }
  .foot__cell:first-child { border-top: 0; }
}

/* Телефон внутри моно-сноски. Отрицательные поля компенсируют padding:
   строка не раздувается, а область нажатия вырастает до 30px. */
.note__tel {
  /* Область нажатия набирается min-height, а не произвольным отступом:
     44px — норма, замер до правки давал 31px. Отрицательное поле гасит
     прирост строки, чтобы сноска не раздувалась. */
  display: inline-flex; align-items: center; min-height: 44px;
  padding-inline: var(--space-2xs); margin: -12px calc(var(--space-2xs) * -1);
  color: var(--amber); text-decoration: underline; text-underline-offset: 3px;
  white-space: nowrap;
}

/* ───────── Строка статуса у нижнего края ────────────────────────────────
   Появляется на нажатие якоря, которого в превью ещё нет. Не модальное
   окно-перехват (они на этом проекте запрещены): не блокирует страницу,
   закрывается крестом и Esc, уходит сама через 9 секунд. */
.tray {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-tray);
  display: flex; align-items: center; gap: var(--space-md);
  /* Нижний отступ считается через max(): на айфоне с вырезом системная
     полоса жеста накрыла бы крест закрытия, и палец попадал бы в систему,
     а не в кнопку. В эмуляторе это НЕ проверяется — Chrome DevTools отдаёт
     env(safe-area-inset-*) нулём на любом выбранном устройстве, поэтому
     max() стоит как безопасное значение по умолчанию.
     Боковые поля — тоже через max(): в ландшафтной ориентации вырез
     съедает край экрана. */
  padding:
    var(--space-sm)
    max(var(--gutter), env(safe-area-inset-right))
    max(var(--space-sm), env(safe-area-inset-bottom))
    max(var(--gutter), env(safe-area-inset-left));
  background: var(--surface);
  border-top: var(--hair) solid var(--edge-strong);
}
.tray[hidden] { display: none; }
.tray__msg {
  margin: 0; flex: 1; min-width: 0;
  font-family: var(--font-mono); font-size: var(--text-mono-label); line-height: 1.6;
  color: var(--text-2);
}
/* На узком экране плашка вместе с липкой шапкой откусывала 26% вьюпорта
   (замер на 375). Текст сокращён, а здесь ужаты поля и интерлиньяж:
   сообщение временное, оно не имеет права занимать четверть экрана. */
@media (max-width: 559px) {
  .tray { padding-top: var(--space-xs); gap: var(--space-xs); }
  .tray__msg { line-height: 1.45; }
}
.tray__msg::before { content: "→ "; color: var(--green-signal); }
.tray__tel {
  display: inline-flex; align-items: center; min-height: 44px;
  padding-inline: var(--space-2xs); margin: -12px calc(var(--space-2xs) * -1);
  color: var(--amber); text-decoration: underline; text-underline-offset: 3px;
  white-space: nowrap;
}
.tray__x {
  flex: none; width: 44px; height: 44px;
  display: grid; place-items: center;
  background: none; border: var(--hair) solid var(--edge-strong); border-radius: var(--radius-btn);
  color: var(--text-2); cursor: pointer;
  transition: color var(--dur-short) var(--ease-out), border-color var(--dur-short) var(--ease-out);
}
.tray__x svg { width: 14px; height: 14px; }
.tray__x:active { transform: scale(0.94); }
.tray__x:disabled { opacity: .55; cursor: not-allowed; }
@media (hover: hover) and (pointer: fine) {
  .tray__x:hover { color: var(--text); border-color: var(--chrome); }
}
@media (prefers-reduced-motion: no-preference) {
  .tray:not([hidden]) { animation: tray-in var(--dur-short) var(--ease-out) both; }
  @keyframes tray-in { from { transform: translateY(100%); } to { transform: none; } }
}

/* ═════════════════════════ Движение ═══════════════════════════════════════
   Приёмов по-прежнему два: блок проявляется, входя в кадр, и хайрлайн над
   секцией прочерчивается слева направо.

   ⚠️ 11.08.2026 — АВАРИЯ И ЕЁ ПРИЧИНА. Раньше оба приёма висели на нативном
   scroll-driven CSS (`animation-timeline: view()`) под гейтом
   `@supports (animation-timeline: view())`. В WebKit 26.5 (движок Safari)
   @supports отвечает ДА, свойства применяются, а таймлайн фактически не
   продвигается — и из-за `animation-fill-mode: both` все блоки навсегда
   остаются в кадре `from { opacity: 0 }`. Замер на живом сайте: 30 блоков
   .reveal из 30 с opacity < 0.5, страница для заказчика — пустой графит.
   Вывод, из которого сделана эта правка: @supports отвечает за поддержку
   СИНТАКСИСА, а не за то, что анимация поедет. Значит видимость контента
   не имеет права висеть ни на @supports, ни на анимации вообще.

   Как сделано сейчас: проявление ломает на два независимых слоя.
   1) Базовое состояние ВСЕГДА видимое. Ни opacity:0, ни scaleX(0) не стоят
      ни в одном правиле, которое действует само по себе.
   2) Прятать разрешено только внутри `.has-reveal` — класс ставит скрипт
      в head и только после того, как убедился, что IntersectionObserver есть.
      Скрипт же снимает класс по сторожу, если наблюдатель не поехал.
      Нет JS, старый браузер, сломанный наблюдатель, reduce-motion — контент
      виден, потому что прятать его некому.
   3) Само движение — обычный transition по классу `.is-in`. Он либо есть,
      либо нет: промежуточных 0.75 у высоких блоков (та самая правка утром
      про .fleet) больше не бывает в принципе, высота блока ни на что
      не влияет. Прерываемость и старт от текущего значения — бесплатно,
      это свойство transition, а не анимации по таймлайну. */
@media (prefers-reduced-motion: no-preference) {
  .has-reveal .reveal {
    transition: opacity 520ms var(--ease-out), transform 520ms var(--ease-out);
  }
  .has-reveal .reveal:not(.is-in) { opacity: 0; transform: translateY(18px); }
  /* Клавиатура не ждёт перехода. Замер обходом Tab (119 остановок, Chromium):
     в 4 случаях фокус приезжал в блок, который в этот момент ещё проявлялся,
     и человек полсекунды смотрел на 0.26 непрозрачности. Наблюдатель такой
     блок всё равно откроет, но фокусу показываем сразу и без анимации. */
  .has-reveal .reveal:focus-within { opacity: 1; transform: none; transition: none; }

  /* Хайрлайн секции рисуется отдельным слоем: сам border остаётся на месте,
     поверх него проезжает хромовая линия. Слой существует только когда
     проявление вообще включено — иначе секцию делит обычный border. */
  .has-reveal .sec { position: relative; }
  .has-reveal .sec::before {
    content: ""; position: absolute; left: 0; right: 0; top: calc(var(--hair) * -1);
    height: var(--hair); background: var(--chrome-dim);
    transform-origin: left center; transform: scaleX(0);
    transition: transform 700ms var(--ease-out);
  }
  .has-reveal .sec.is-in::before { transform: scaleX(1); }
  .has-reveal .sec:first-of-type::before { display: none; }

  /* Выноска на полосе сноса. В hero.css её части анимируются по времени
     с задержками — для первого экрана верно, но здесь полоса лежит на
     втором-третьем экране: к моменту, когда человек доскроллит, разметка
     давно нарисовалась за кадром, и главный момент приёма пропадает.
     Поэтому до входа в кадр анимации у неё нет вовсе (значит выноска
     ВИДНА — это и есть безопасное состояние), а в момент входа те же кадры
     проигрываются по времени: точка → линия → полка с числом.
     Имена кадров (prick / leader-v / ink) объявлены в hero.css. */
  .has-reveal .mark--svc .mark__dot,
  .has-reveal .mark--svc .mark__line,
  .has-reveal .mark--svc .mark__tick,
  .has-reveal .mark--svc .mark__body { animation: none; }

  .has-reveal .is-in .mark--svc .mark__dot {
    animation: prick var(--dur-short) var(--ease-out) both; animation-delay: 80ms;
  }
  .has-reveal .is-in .mark--svc .mark__line {
    animation: leader-v var(--dur-med) var(--ease-out) both; animation-delay: 200ms;
  }
  .has-reveal .is-in .mark--svc .mark__tick,
  .has-reveal .is-in .mark--svc .mark__body {
    animation: ink var(--dur-med) var(--ease-out) both; animation-delay: 360ms;
  }
}

/* ═════════════════════════ Адаптив ════════════════════════════════════════ */

/* 1200 и ниже — витрина техники теряет второй столбец у высокой плитки */
@media (max-width: 1199px) {
  .fleet { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); }
  .rest { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Планшет */
@media (max-width: 959px) {
  .ledger__row {
    grid-template-columns: minmax(0, 200px) minmax(0, 1fr);
    gap: var(--space-md) var(--space-lg);
  }
  .ledger__body { grid-column: 2; }
  /* цена уходит под текст, но остаётся на правом поле — колонка цифр
     не рассыпается */
  .ledger__price { grid-column: 2; text-align: left; }
  .ledger__for { white-space: normal; }

  .faq__item { grid-template-columns: minmax(0, 1fr); gap: var(--space-sm); }
  .partners { grid-template-columns: minmax(0, 1fr); }
  .island__grid { grid-template-columns: minmax(0, 1fr); }
  .island__act { max-width: 24rem; }
  .news { grid-template-columns: minmax(0, 1fr); }
  .news__item { padding: var(--space-md) 0 var(--space-lg); }
  .news__item + .news__item { padding-left: 0; }
}

/* Телефон */
@media (max-width: 767px) {
  .fleet { grid-template-columns: minmax(0, 1fr); }
  .unit--tall { grid-row: auto; }
  .unit--tall .unit__shot { aspect-ratio: 4 / 3; min-height: 0; flex: none; }
  .unit--tall .unit__shot img { position: static; }
  .rest { grid-template-columns: minmax(0, 1fr); }

  .band { margin-top: var(--space-xl); height: clamp(190px, 52vw, 280px); }

  .ledger__row {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-sm);
    padding: var(--space-lg) 0;
  }
  .ledger__shot, .ledger__body, .ledger__price { grid-column: 1; }
  .ledger__shot { order: -1; }
  /* На телефоне ведомость — одна колонка, и графа кадра растягивается
     на всю ширину. Заглушка здесь остаётся выключенной осознанно: три
     штрихованных поля 390×260 подряд забирают почти три экрана и кричат
     «у нас нет фотографий» громче, чем их отсутствие. Смысл заглушки —
     держать сетку, а в одну колонку держать нечего: строка без кадра
     просто начинается с названия, и ничего не выглядит сломанным. */
  .ledger__row--noshot .ledger__shot { display: none; }
  .ledger__price { text-align: left; }
  .ledger__rate + .ledger__rate { margin-top: var(--space-3xs); }

  .tariff th, .tariff td { padding: var(--space-sm) var(--space-xs); }
  .tariff__what { display: none; }        /* на телефоне остаются материал и цена */
  .rules__cell { padding: var(--space-md) var(--space-md) var(--space-lg); }
}

/* Зазор между двумя числами, которые обязаны совпадать, но живут в разных
   файлах. Витрина техники разворачивается в одну колонку до 767, а <picture>
   на главной переключается с горизонтального кадра fleet-lift-s на
   вертикальный fleet-lift уже с 700 (`media="(min-width: 700px)"`,
   site/index.html — рукописная страница, генератор её не собирает).
   В зазоре 700–767 вертикальный кадр 0,72 попадал в горизонтальное окно 4/3
   и срезался на 46% по высоте: от машины оставалась полоса без колёс
   и без люльки. Раскладку здесь не трогаем — колонка одна, как и была,
   меняется только форма окна под тот кадр, который сюда реально приезжает.
   Двигаете 700 в index.html — подвиньте и здесь. */
@media (min-width: 700px) and (max-width: 767px) {
  .unit--tall .unit__shot { aspect-ratio: 760 / 1056; }
}

@media (max-width: 559px) {
  .island__rows li { grid-template-columns: minmax(0, 1fr); gap: var(--space-3xs); }
  /* расшифровка обозначения уезжает на свою строку — иначе на 320
     «борт 10 т / стрела 7 т» не помещается рядом с названием */
  .rest__hint { display: block; }
  /* Отточие имеет смысл, пока название и цена стоят в одну строку. На 320
     название занимает три строки, и остаток пунктира висит в воздухе
     огрызком — там он не приём прайс-листа, а мусор. */
  .rest__dots { display: none; }
  .rest li a { justify-content: space-between; gap: var(--space-md); }
}

/* ═════════════════ Страница без JavaScript ════════════════════════════════
   ⚠️ ИСТОРИЧЕСКАЯ СПРАВКА, действующего механизма здесь больше НЕТ.
   Пока reveal висел на нативном `animation-timeline: view()`, страница без JS
   прятала 26 блоков из 27, и это лечили двумя страховками: `@media
   (scripting: none)` и класс `.no-js`. 11.08.2026 механизм переписан: прятать
   вообще нечему, если нет класса `has-reveal` (см. раздел «Движение» выше),
   а этот класс ставит только сторож /js/reveal.js. Нет скрипта — нет класса —
   страница целиком видима сама собой, страховать нечего.

   Блоки удалены сознательно, а не забыты: правило, которое ничего не
   страхует, читается следующим как действующая защита, и следующая правка
   опирается на неё. Ровно так «фолбэк на @media (scripting: none)» создал
   иллюзию страховки от мёртвого таймлайна — а он страховал только «нет JS».
   Если сюда снова захочется что-то дописать, сначала ответьте: этот механизм
   умеет ПОКАЗАТЬ обратно в тот же момент, когда прячет? */
