/* ═══════════════════════════════════════════════════════════════════════════
   ЗАГЛУШКА ГЛАВНОЙ · ГЕРОЙ «ПОЛОТНО» — ПОРТ, А НЕ АВТОРСКИЙ КОД.

   Источник: the-essence-storefront, ветка feat/ch03-mirrors,
   web/src/components/book/chapters/ch01hero.css (сам — порт выверенного
   стенда ЛЕНДИНГ-ФИНАЛ/ГЕРОЙ-ПОЛОТНО-v22: итерации v18→v22, две слепые
   рецензии, десятки замеров в headless Chrome).

   ⛔ НЕ ПРАВИТЬ ЗДЕСЬ ТО, ЧТО ПРАВИТСЯ В ИСТОЧНИКЕ. Файл — производная;
   расхождение означает, что следующий порт молча затрёт правку. Комментарии
   оригинала сохранены ЦЕЛИКОМ: в них цена каждого решения и замеры.

   ⚠️ СНЯТО ПО СЕЛЕКТОРАМ, А НЕ ПО НОМЕРАМ СТРОК — и это не педантизм.
   Первый заход резал диапазонами строк по заголовкам разделов, и вместе с
   «видео в углу» уехала вся типографика заголовка, лида и цепочки, лежавшая
   в том же диапазоне: кегль h1 упал с 70 px до 32, полоса развалилась.
   Поймано на рендере, а не в уме.

   Снято: .vid* (кружок с видео — в источнике помечен как плейсхолдер с
   ПОСТОРОННИМ человеком и «не для публикации») и .qv* (попап книги по клику:
   на заглушке кликам вести некуда). Всё остальное — дословно, включая .lift
   и всю адаптивную систему: телефон, короткий телефон, планшет, короткий
   ноутбучный кадр, prefers-reduced-motion.

   ⚠️ Цвета зашиты числами — это ПОРТ, переписывать их на токены значило бы
   расходиться с источником. Файл лежит в app/assets/stylesheets, поэтому
   детектор 202 (сырые hex в app/views) его не считает.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ⚠️ МЁРТВЫЕ ПРАВИЛА ОТ ВЫРЕЗАННЫХ КУСКОВ — ЗДЕСЬ, И ЭТО ОСОЗНАННО.
   Порт снял видеокружок, попап книги (.qv) и кнопки покупки, но их стили
   остались: 24 класса в селекторах, которых нет на странице ни в разметке,
   ни в том, что ставит скрипт, — примерно 55 строк из 2382 (2,3%).
   Замерено сверкой селекторов файла со списком классов ЖИВОЙ страницы.

   Почему не вырезано. Я попробовал — самодельный удалятель принял текст
   комментариев за селекторы и обрезал два объяснения в середине файла
   (поймано diff'ом, откачено). Резать двухтысячестрочный порт вручную
   написанным разборщиком дороже, чем стоит выигрыш: вред здесь — вес и
   ложный след для следующего читателя, а не поведение страницы.

   Что сделано вместо: число закреплено храповиком в
   spec/views/marketing/placeholder_guards_spec.rb — вырасти оно не может.
   Появится новый мёртвый класс — страж назовёт его поимённо.
   Мёртвые: act__go/next/row/up · bk--light · btn · ghost · grp__i ·
   lnk/lnk__t/lnk__w · org · qv__fig/in/no/note/q/t/x · vid__cap/disc/play/v · w3 */

.bp-hero{
  /* ⚠️ ДОБАВЛЕНО ПРИ ПОРТЕ: в витрине эти токены объявлены глобально в её
     tokens.css, у нас такой ветки нет. Без них порт молча сереет —
     rgb(var(--…-rgb) / .x) не вычисляется, и правило отбрасывается целиком.
     Значения сняты с живого next.the-essence.ai. */
  --color-bg-deep:#0A0805; --color-bg-deep-rgb:10 8 5;
  --color-accent-rgb:232 184 152; --color-accent-strong-rgb:240 201 174;
  --color-fg-rgb:244 239 231; --color-paper-rgb:251 248 243;
  --ease-entrance:cubic-bezier(.16,1,.3,1);
  --ease-standard:cubic-bezier(.2,0,0,1);
}

/* ═══════════════════════════════════════════════════════════════════════════
   АКТ 01 · ОБЛОЖКА · ГЕРОЙ «ПОЛОТНО» (Ch01Hero). ТЁМНЫЙ ОСТРОВ.

   Порт выверенного стенда ЛЕНДИНГ-ФИНАЛ/ГЕРОЙ-ПОЛОТНО-v22.html (итерации
   v18→v22, слепые рецензии 5,5 → 6,3, десятки замеров в headless Chrome).
   Той же дорогой раньше пришла Глава VIII (ch10.css) — стенд правится в
   «Сути Души», сюда приезжает готовым.

   ЧТО ВНУТРИ: полотно из 21 обложки (три яруса, разные скорости), заголовок
   со сменным словом, карточка запроса читателя в углу, три такта метода,
   нижняя полоса «цена · гарантия · кнопка», две аннотации-раскрытия — смета
   «300 000» и состав команды — и попап книги по клику на обложку.

   ⚠️ ВСЁ SELF-SCOPED ПОД .bp-hero. Страница /next светлая (light-first), и
   любое правило, оставшееся глобальным, покрасило бы соседние главы. При
   порте :root уехал в .bp-hero, body-правила потеряли margin/height/overflow
   (на стенде они держали единственный экран без прокрутки — здесь убили бы
   страницу), а @keyframes переименованы в hero-*: имена анимаций глобальны,
   и «run» с «breath» почти наверняка есть у соседей.

   ⛔ НЕ ПРАВИТЬ ЗДЕСЬ ТО, ЧТО МОЖНО ПОПРАВИТЬ В СТЕНДЕ. Файл — производная;
   расхождение с ЛЕНДИНГ-ФИНАЛ/ГЕРОЙ-ПОЛОТНО-v22.html означает, что следующий
   порт молча затрёт правку. Исключение — три правила выше, помеченные
   «⚠️ порт»: они существуют только потому, что герой встал в длинную страницу.
   ═══════════════════════════════════════════════════════════════════════════ */


.bp-hero{
  --acc:#E8B898; --acc2:#F0C9AE; --acc-on:#0F0D08;
  --fg:#F4EFE7; --body:#E8E2D8; --mut:#B5AB9D; --sub:#9C9287;
  /* .34 давали 1.7:1 — нечитаемо и мимо любого порога. */
  --faint:rgba(251,248,243,.58); --brd:#4A4135; --line:rgba(251,248,243,.09);
  --sans:"Manrope",-apple-system,system-ui,sans-serif;
  --ital:"Lora","Times New Roman",Georgia,serif;
  --mono:"JetBrains Mono","SF Mono",ui-monospace,monospace;
  --tnum:"tnum" 1,"lnum" 1;
  --e-enter:var(--ease-entrance); --e-std:var(--ease-standard);
  /* ПЕРСПЕКТИВА ЗАДАЁТСЯ РАЗМЕРОМ, А НЕ transform:scale — scale не меняет
     раскладку, ряд визуально ужимается и оставляет за собой пустую полосу.
     У каждого ряда своя ШИРИНА ОБЛОЖКИ, и раскладка честно следует за планом.
     --fsum — сумма долей всех планов, её выставляет скрипт (см. PLANES).
     База обратно пропорциональна ей: сколько бы планов ни было, их стопка
     занимает ту же высоту кадра. 61vh подобрано так, что при трёх планах
     (сумма 2.72) выходит 22.4vh и стопка чуть выходит за край, продолжаясь за
     рамкой. Верхний предел 420, а не 290: на 2560×1440 стопка упиралась в
     потолок и не доставала до краёв кадра — сверху и снизу оставались чёрные
     поля по 73 px. Замерено. */
  --fsum:2.72;
  /* --cwb-px выставляет скрипт по ВИДИМОЙ высоте полотна (см. applyStack);
     clamp остаётся страховкой на случай, если скрипт ещё не отработал. */
  --cwb-px:calc(61vh / var(--fsum));
  --cwb:clamp(118px,var(--cwb-px),420px);
  --cw:var(--cwb);
  --gap:clamp(10px,1.5vh,20px);
  --pad:clamp(20px,4vw,72px);
  /* --colw снят вместе с колонной: текст больше не стоит в левой половине,
     ширме нечего под неё подгонять (см. .veil). */
}
.bp-hero *{box-sizing:border-box}

/* ⚠️ position:relative + isolation НА КОРНЕ СЕКЦИИ — вместо того, что на
   стенде держал <body>. Внутри героя лежат fixed-панели аннотаций и
   absolute-слои полотна; без своей системы координат и своего контекста
   наложения они считались бы от страницы и всплывали над соседними главами. */
.bp-hero{position:relative;isolation:isolate;
  background:var(--color-bg-deep);color:var(--body);font-family:var(--sans);
  -webkit-font-smoothing:antialiased;}
.bp-hero :focus-visible{outline:2px solid var(--acc);outline-offset:3px}

/* isolation — чтобы подсветка смешивалась строго внутри сцены и не уходила
   блендиться с корнем документа. */
.bp-hero .scene{position:relative;height:100dvh;overflow:hidden;background:var(--color-bg-deep);
  isolation:isolate}

/* ═══ ПОЛОТНО ════════════════════════════════════════════════════════════ */
.bp-hero .web{position:absolute;inset:0;display:flex;flex-direction:column;
  justify-content:center;gap:var(--gap);z-index:1;pointer-events:none;
  padding-bottom:var(--web-pad,0px);
  /* Наклон приподнимает правый край на полширины × tg(угла), и внизу справа
     открывается тёмный клин. Угол держим небольшим, а вылет за кадр — с
     запасом, чтобы стопка этот клин перекрывала. */
  transform:rotate(-2.2deg) scale(1.12);
  /* ⚠️ ЦЕНТР МАСШТАБИРОВАНИЯ — СЕРЕДИНА ВИДИМОЙ ЧАСТИ, А НЕ КАДРА.
     Полотно занимает весь кадр, но стопка центрируется в его верхней части
     (padding-bottom поднимает её над полосой). При origin 50% 50% увеличение
     считалось от середины ЭКРАНА и утаскивало стопку вниз: на 1920×1080 низ
     последнего ряда уходил на 837 при кромке полосы 724, то есть третий ряд
     снова прятался под текст — ровно та беда, ради которой всё и затевалось.
     Здесь origin следует за той же величиной, что и отступ. */
  transform-origin:50% calc((100% - var(--web-pad,0px)) / 2);will-change:transform;
  opacity:0;animation:hero-webIn 1.5s var(--e-enter) .05s forwards}
@keyframes hero-webIn{to{opacity:1}}
/* Ряд — это план. Размер + яркость + скорость: три согласованных признака
   глубины вместо одного. Размытия нет намеренно — оно топит обложки, а именно
   они здесь товар.
   ⚠️ ЯРКОСТЬ ПЛАНА — НИ В КОЕМ СЛУЧАЕ НЕ ФИЛЬТРОМ НА РЯДЕ. Ряд это родитель
   едущей дорожки в несколько тысяч пикселей, и filter родителя браузер обязан
   пересчитывать по всей её площади на каждом кадре (замерено: 65 мс на кадр).
   План гасит полупрозрачная плашка — см. --dim у .bk::after. */
.bp-hero .row{display:flex;flex:none;overflow:visible}
/* align-items:flex-start — иначе вертикальный сдвиг карточки (см. --off)
   съедался бы stretch-ем и строй остался бы линейкой. */
.bp-hero .track{display:flex;align-items:flex-start;gap:var(--gap);padding-right:var(--gap);
  flex:none;animation:hero-run var(--dur,120s) linear infinite;will-change:transform}
.bp-hero .row--back .track{animation-direction:reverse}
@keyframes hero-run{from{transform:translate3d(0,0,0)}to{transform:translate3d(-50%,0,0)}}
/* Лента замирает и когда всматриваются в обложку, и когда открыта карточка. */
.bp-hero .scene[data-hold="1"] .track{animation-play-state:paused}
/* Вкладка в фоне — время для сцены не идёт. Разбор в блоке «ВКЛАДКА УШЛА В
   ФОН» в скрипте: без этого лента на возврате перескакивает вперёд на всё
   время отсутствия. Подсветка замирает по той же причине — её дыхание
   отыграло бы накопленные циклы одним махом. */
.bp-hero .scene[data-away="1"] .track,
.bp-hero .scene[data-away="1"] .glow{animation-play-state:paused}

/* --off — вертикальный сдвиг карточки. Через top у relative-элемента, а не
   через margin: смещение не трогает раскладку, высота ряда не пляшет. */
/* ⚠️ НИ ФИЛЬТРА, НИ РАЗМЫТОЙ ТЕНИ НА КАРТОЧКЕ — ЭТО ПЛАТА ЗА ПЛАВНОСТЬ.
   filter:brightness() на каждой из шести десятков карточек заставляет браузер
   заводить под каждую отдельную поверхность; box-shadow с радиусом 26 px по
   всем карточкам — лишняя закраска на каждом тайле едущей дорожки. Отсюда и
   рывки. Яркость плана даёт плашка (--dim в ::after): чёрный с альфой a даёт
   ровно то же, что brightness(1−a), но композитору не стоит ничего. Тень
   остаётся только у наведённой карточки — она одна. */
.bp-hero .bk{position:relative;top:var(--off,0px);flex:none;width:var(--cw);aspect-ratio:707/1000;
  border-radius:2px;overflow:hidden;background:var(--color-bg);padding:0;border:none;
  cursor:pointer;pointer-events:auto;
  box-shadow:inset 0 0 0 .5px rgba(255,255,255,.07);
  /* Карточка сама больше не растёт: подъём вынесен в .lift, поэтому здесь
     переходу нечего вести. Лишний transition на полусотне едущих плиток —
     это лишняя работа композитора на каждом кадре. */
  transition:none}
.bp-hero .bk img{width:100%;height:100%;object-fit:cover;display:block}
/* Лак. Блик по верхней кромке — то, чем печатная обложка отличается от
   картинки обложки: у неё есть поверхность. Обычным альфа-градиентом, без
   mix-blend-mode: смешивание пришлось бы пересчитывать на каждой карточке. */
.bp-hero .bk::before{content:"";position:absolute;inset:0;z-index:5;pointer-events:none;
  background:linear-gradient(146deg,rgb(var(--color-paper-rgb) / .13) 0%,
    rgb(var(--color-paper-rgb) / .035) 11%,transparent 27%)}
.bp-hero .bk--light{--dim:.7}
/* ЗАТЕНЕНИЕ ПЛАНА + виньетка сверху — одним псевдоэлементом, двумя слоями
   фона. --dim задаётся рядом и равен 1 минус яркость плана. */
.bp-hero .bk::after{content:"";position:absolute;inset:0;pointer-events:none;z-index:2;
  background:
    radial-gradient(ellipse 132% 92% at 50% 0%,transparent 44%,rgb(var(--color-bg-deep-rgb) / .24)),
    linear-gradient(rgba(10,8,5,var(--dim,0)),rgba(10,8,5,var(--dim,0)));
  transition:opacity .5s var(--e-std)}
.bp-hero .bk__no{position:absolute;left:7%;top:4.5%;z-index:4;font-family:var(--mono);
  font-size:clamp(7px,calc(var(--cw) * .055),9.5px);letter-spacing:.14em;
  color:rgb(var(--color-paper-rgb) / .55);font-feature-settings:var(--tnum)}
/* Затирка нижней строки обложки (там настоящее имя читателя). Была
   backdrop-filter:blur — это сто с лишним элементов, каждый заставляет браузер
   пересобирать подложку на движущейся ленте. Плотный градиент скрывает строку
   так же, а стоит ноль. */
/* 🔴 30% И БЫСТРОЕ НАРАСТАНИЕ — ОБА ЧИСЛА ПОДБИРАЛИСЬ ЗАМЕРОМ, НЕ ТРОГАЙТЕ
   ПООДИНОЧКЕ. Имя читателя набрано на 82% высоты обложки. Полоса в 16%
   начинала глушить только с 84% — то есть проходила ПОД именем. Расширение до
   24% не помогло: имя попадало в участок градиента плотностью .55 и читалось
   насквозь. Работает лишь сочетание: полоса 30% (от 70% высоты обложки) и
   нарастание, выходящее на плотное к 38% полосы, то есть к 81% обложки.
   ⚠️ ЗАТИРКА ЖИВЁТ В ТРЁХ МЕСТАХ: .bk__mask (лента), .lift::after (поднятая
   копия) и .qv__fig::after (карточка). Разъедутся — имя проступит там, где
   про него забыли, а рядом стоит обещание «личные данные скрыты». */
.bp-hero .bk__mask{position:absolute;left:0;right:0;bottom:0;height:30%;z-index:3;
  background:linear-gradient(180deg,rgb(var(--color-bg-deep-rgb) / 0) 0%,rgb(var(--color-bg-deep-rgb) / .42) 12%,
    rgb(var(--color-bg-deep-rgb) / .86) 26%,rgb(var(--color-bg-deep-rgb) / .97) 38%,var(--color-bg-deep) 48%)}
/* ═══ ОБЛОЖКА ПОД КУРСОРОМ ═══════════════════════════════════════════════
   🔴 ГЛАВНАЯ ПРИЧИНА, ПО КОТОРОЙ ЭТО НЕ РАБОТАЛО ТРИ ПОДХОДА ПОДРЯД.
   Карточке ставили z-index 9 и ждали, что она выйдет на передний план. Она не
   выходила и выйти не могла: у .web есть transform, а transform создаёт
   контекст наложения — все z-index карточек считаются ВНУТРИ полотна, и целиком
   оно остаётся на своём слое 1, под ширмой, зерном, подложкой полосы и текстом.
   Юрий это и увидел: увеличенная обложка лезла под плашки и не вылезала даже
   из нижней полосы.
   Поднимать z-index у самого .web нельзя — тогда наверх выедут ВСЕ обложки и
   лягут на текст.

   РЕШЕНИЕ: ПОДЪЁМНИК. Наведённая обложка не увеличивается на месте — её копия
   выносится отдельным слоем поверх всей сцены (.lift, position:fixed) и растёт
   уже там. Оригинал на это время гасится, дыру в стене полностью перекрывает
   выросшая копия. Лента под курсором и так стоит, поэтому копия никуда не
   плывёт.
   Побочная выгода, ради которой стоило: копия рисуется БЕЗ наклона полотна —
   книга будто выпрямляется в руке, когда её берут с полки.

   ⚠️ РАЗМЕР КОПИИ СЧИТАЕТСЯ НЕ ПО getBoundingClientRect. Карточка лежит в
   повёрнутом полотне, и rect отдаёт axis-aligned коробку — она шире и выше
   настоящей примерно на 5%, копия вышла бы раздутой и с чужими пропорциями.
   Берём собственные offsetWidth/offsetHeight и умножаем на реальный масштаб
   полотна, вынутый из его матрицы (см. liftOn). */
.bp-hero .bk:hover,
.bp-hero .bk:focus-visible{z-index:9}
.bp-hero .bk[data-lift="1"]{opacity:0;transition:opacity .18s linear}
.bp-hero .bk:hover::after,
.bp-hero .bk:focus-visible::after{opacity:0}

/* Подъёмник. Один элемент на всю страницу, поверх всего (z-index 30 — выше
   ширмы, зерна, полосы и текста, ниже модальной карточки книги). */
/* ⚠️ В ПЕРЕХОДЕ ТОЛЬКО opacity И transform. БОЛЬШЕ НИЧЕГО.
   Первая версия анимировала ещё box-shadow, outline-offset и координаты с
   размерами. Каждое из этих свойств заставляет браузер перерисовывать элемент
   на каждом кадре, а тень тут с размытием в 120 px — то есть пересчитывать
   приходилось площадь много больше самой обложки. Отсюда и «подлагивает, нет
   плавности»: не тяжёлая графика, а анимация некомпозитных свойств.
   Тень и рамка теперь заданы статично — они появляются вместе с элементом
   через его общую прозрачность и не пересчитываются ни разу. Координаты едут
   через translate3d внутри того же transform, что и рост: и переезд с обложки
   на обложку, и раскрытие идут одним композитным свойством. */
.bp-hero .lift{position:fixed;left:0;top:0;z-index:30;pointer-events:none;border-radius:2px;
  background:var(--color-bg);overflow:hidden;
  outline:1px solid rgb(var(--color-accent-rgb) / .5);outline-offset:9px;
  box-shadow:0 44px 96px rgba(0,0,0,.84),
             0 0 120px rgb(var(--color-accent-rgb) / .22),
             0 0 30px rgb(var(--color-accent-rgb) / .12);
  opacity:0;transform-origin:50% 50%;will-change:transform,opacity;
  transition:opacity .28s var(--e-std),transform .52s var(--e-enter)}
.bp-hero .lift img{display:block;width:100%;height:100%;object-fit:cover}
/* Лак и затирка имени — те же, что на карточке: копия обязана быть неотличима
   от оригинала, иначе подмена читается. */
.bp-hero .lift::before{content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background:linear-gradient(146deg,rgb(var(--color-paper-rgb) / .13) 0%,
    rgb(var(--color-paper-rgb) / .035) 11%,transparent 27%)}
.bp-hero .lift::after{content:"";position:absolute;left:0;right:0;bottom:0;height:30%;z-index:3;
  background:linear-gradient(180deg,rgb(var(--color-bg-deep-rgb) / 0) 0%,rgb(var(--color-bg-deep-rgb) / .42) 12%,
    rgb(var(--color-bg-deep-rgb) / .86) 26%,rgb(var(--color-bg-deep-rgb) / .97) 38%,var(--color-bg-deep) 48%)}
.bp-hero .lift__no{position:absolute;left:7%;top:4.5%;z-index:4;font-family:var(--mono);
  font-size:11px;letter-spacing:.2em;
  color:var(--acc2);font-feature-settings:var(--tnum)}

/* Затемнение поля. Один элемент, одна прозрачность, ноль работы на кадр. */
.bp-hero .web__dim{position:absolute;inset:-20%;z-index:5;pointer-events:none;
  background:var(--color-bg-deep);opacity:0;transition:opacity .5s var(--e-std)}
.bp-hero .scene[data-hold="1"] .web__dim{opacity:.32}

/* ═══ СВЕТ ════════════════════════════════════════════════════════════════
   Тёплый ключевой свет на полотне: без него ряды освещены равномерно и
   читаются обоями. Пятно медленно дышит — сцена живёт сама по себе;
   анимируется одна opacity на одном композитном слое.
   ⚠️ mix-blend-mode:screen СНЯТ. Он заставлял композитор вычитывать подложку
   под всей правой третью кадра на КАЖДОМ кадре, а под ним едут три дорожки.
   Это была одна из трёх причин рывков. Обычная альфа даёт тот же тёплый воздух
   и стоит ноль. */
.bp-hero .glow{position:absolute;inset:0 0 0 34%;pointer-events:none;z-index:2;
  background:
    radial-gradient(ellipse 68% 42% at 54% 38%,rgb(var(--color-accent-strong-rgb) / .115) 0%,
      rgb(var(--color-accent-strong-rgb) / .045) 42%,transparent 72%),
    radial-gradient(ellipse 50% 32% at 82% 86%,rgba(184,164,214,.07) 0%,transparent 70%);
  animation:hero-breath 19s ease-in-out infinite}
@keyframes hero-breath{0%,100%{opacity:.72}50%{opacity:1}}

/* ═══ ШИРМА · ЕДИНСТВЕННОЕ МЕСТО, ГДЕ ГАСИТСЯ ПОЛОТНО ════════════════════
   Весь текст, лежащий на едущих обложках, читается благодаря ЭТОМУ слою и
   собственной тени глифов. Локальных подложек ни у одного элемента нет —
   почему, разобрано над .cap.

   ТРИ ПРАВИЛА, БЕЗ КОТОРЫХ ЭТОТ СЛОЙ СНОВА СТАНЕТ ПЯТНОМ

   1. КАЖДОЕ ЗАТЕМНЕНИЕ ПРИКРЕПЛЕНО К КРОМКЕ КАДРА. Центр эллипса стоит
      строго на 0%, 100% или на краю по вертикали — никогда внутри. Тогда самая
      плотная его часть совпадает с краем экрана, где темнота естественна, а
      наружу от неё ничего нет. Граница появляется ровно в тот момент, когда
      центр уезжает внутрь кадра.
   2. СПАД ИДЁТ ПО КРИВОЙ, А НЕ В ТРИ СТУПЕНИ. Линейная альфа на площади в
      пол-экрана видна полосами: глаз ловит излом производной, даже когда не
      ловит сам переход. Одиннадцать стопов ниже приближают ease-out: плотность
      держится у центра и быстро тает к 70–80%, дальше почти невидима.
      ⛔ НЕ СОКРАЩАЙТЕ КОЛИЧЕСТВО СТОПОВ «для чистоты кода» — они и есть
      причина, по которой слой не читается объектом.
   3. ЭЛЛИПСЫ РАЗМЕЧЕНЫ ПО ФАКТИЧЕСКИМ КОРОБКАМ НАБОРА, а не на глаз.
      Левый: от кромки до конца самой длинной строки лида (46ch ≈ 31vw) с
      запасом; по вертикали от колонтитула до низа лида.
      Правый: карточка стоит на 71–96% ширины и 38–52% высоты (замерено на
      1512×800 и 1920×1080) — отсюда центр 46% и радиус 26%.
      Если двинете лид или карточку — перемерьте и поправьте здесь, иначе
      набор снова окажется на светлой обложке.

   ⚠️ МЕЖДУ ЛЕВЫМ И ПРАВЫМ ЗАТЕМНЕНИЕМ НАМЕРЕННО ОСТАВЛЕН СВЕТЛЫЙ КОРИДОР.
   Обложки — товар, и середина кадра обязана идти в полную силу. Если поднять
   любой из радиусов так, что коридор схлопнется, полотно превратится в фон,
   и весь смысл экрана пропадёт.

   ⚠️ ЗЕРНО (.grain) — ЧАСТЬ ЭТОГО РЕШЕНИЯ, А НЕ УКРАШЕНИЕ. Градиенты такого
   размаха на 8-битной панели идут ступенями; зерно их разбивает. Снимете
   зерно — вернётся полосатость. */
.bp-hero .veil{position:absolute;inset:0;pointer-events:none;z-index:3;
  background:
    /* ── ВЕРХ СЛЕВА: ЗАГОЛОВОК. Центр на левой кромке, вертикаль прижата
         к верху.
         ⚠️ РАДИУС ОБРЕЗАН ПО ФАКТИЧЕСКОЙ КОРОБКЕ НАБОРА, А НЕ «С ЗАПАСОМ».
         Было 44vw × 46% от 16% — эллипс дотягивался до 62% высоты и до
         середины кадра, гася обложки там, где текста нет вовсе: под лидом
         оставалась мёртвая тёмная четверть, и Юрий это увидел.
         Заголовок занимает по вертикали 8–33%, по горизонтали до 35vw.
         Эллипс 32vw × 28% от 13% накрывает 0–41% — ровно набор и полосу
         спада под ним, ни пикселем ниже. */
    radial-gradient(ellipse clamp(340px,32vw,700px) 28% at 0% 13%,
      rgb(var(--color-bg-deep-rgb) / .56) 0%,   rgb(var(--color-bg-deep-rgb) / .55) 10%,  rgb(var(--color-bg-deep-rgb) / .525) 20%,
      rgb(var(--color-bg-deep-rgb) / .49) 30%,  rgb(var(--color-bg-deep-rgb) / .44) 40%,  rgb(var(--color-bg-deep-rgb) / .38) 50%,
      rgb(var(--color-bg-deep-rgb) / .31) 60%,  rgb(var(--color-bg-deep-rgb) / .225) 70%, rgb(var(--color-bg-deep-rgb) / .135) 80%,
      rgb(var(--color-bg-deep-rgb) / .06) 90%,  transparent 100%),
    /* ── ВДОЛЬ СТРОКИ ЛИДА: широкое и низкое, тоже от левой кромки.
         Набор имеет форму буквы «Г» — заголовок высокий и узкий, лид низкий
         и широкий, — и одним эллипсом такая фигура не покрывается.
         ⚠️ ВЫСОТА УРЕЗАНА С 19% ДО 13%. Лид — одна строка; всё, что ниже неё,
         затемнялось впустую. Полоса 29–55% по вертикали покрывает строку и
         короткий спад, дальше полотно идёт в полную силу.
         Шва между двумя затемнениями не возникает: сумма плавных полей
         плавная, оба прикреплены к одной кромке. Пик ниже (.80 против .88),
         чтобы в зоне наложения не вышло глухого пятна. */
    radial-gradient(ellipse clamp(460px,48vw,1020px) 13% at 0% 42%,
      rgb(var(--color-bg-deep-rgb) / .52) 0%,   rgb(var(--color-bg-deep-rgb) / .51) 10%,  rgb(var(--color-bg-deep-rgb) / .485) 20%,
      rgb(var(--color-bg-deep-rgb) / .45) 30%,  rgb(var(--color-bg-deep-rgb) / .405) 40%, rgb(var(--color-bg-deep-rgb) / .35) 50%,
      rgb(var(--color-bg-deep-rgb) / .28) 60%,  rgb(var(--color-bg-deep-rgb) / .205) 70%, rgb(var(--color-bg-deep-rgb) / .12) 80%,
      rgb(var(--color-bg-deep-rgb) / .055) 90%, transparent 100%),
    /* ── СПРАВА ПО СЕРЕДИНЕ: карточка с запросом читателя. Центр на правой
         кромке (100%). */
    radial-gradient(ellipse clamp(330px,31vw,600px) 27% at 100% 46%,
      rgb(var(--color-bg-deep-rgb) / .66) 0%,   rgb(var(--color-bg-deep-rgb) / .65) 10%,  rgb(var(--color-bg-deep-rgb) / .625) 20%,
      rgb(var(--color-bg-deep-rgb) / .58) 30%,  rgb(var(--color-bg-deep-rgb) / .525) 40%, rgb(var(--color-bg-deep-rgb) / .45) 50%,
      rgb(var(--color-bg-deep-rgb) / .365) 60%, rgb(var(--color-bg-deep-rgb) / .265) 70%, rgb(var(--color-bg-deep-rgb) / .155) 80%,
      rgb(var(--color-bg-deep-rgb) / .07) 90%,  transparent 100%),
    /* ── КОЛОНТИТУЛ: марка слева, девиз справа. Прижат к верхней кромке. */
    linear-gradient(180deg,
      rgb(var(--color-bg-deep-rgb) / .60) 0%,  rgb(var(--color-bg-deep-rgb) / .52) 3%,  rgb(var(--color-bg-deep-rgb) / .40) 6%,
      rgb(var(--color-bg-deep-rgb) / .26) 10%, rgb(var(--color-bg-deep-rgb) / .13) 14%, rgb(var(--color-bg-deep-rgb) / .04) 18%,
      transparent 22%),
    /* ── НИЗ: лёгкий притин, чтобы полотно не обрывалось по кромке кадра.
         Основную работу под полосой делает её собственная подложка (.deck). */
    linear-gradient(180deg,
      transparent 0%,  transparent 60%, rgb(var(--color-bg-deep-rgb) / .05) 70%,
      rgb(var(--color-bg-deep-rgb) / .13) 80%, rgb(var(--color-bg-deep-rgb) / .22) 90%, rgb(var(--color-bg-deep-rgb) / .32) 100%),
    /* ── ВИНЬЕТКА: собирает кадр, гасит углы. */
    radial-gradient(ellipse 92% 86% at 50% 46%,
      transparent 58%, rgb(var(--color-bg-deep-rgb) / .09) 78%, rgb(var(--color-bg-deep-rgb) / .22) 100%)}

/* ЗЕРНО. Тёмные градиенты такого размаха на 8-битной панели идут полосами;
   зерно их разбивает и заодно даёт полотну фактуру печати — уместно там, где
   товар книга. Статичный слой, ни одного пересчёта на кадр. */
.bp-hero .grain{position:absolute;inset:0;pointer-events:none;z-index:6;opacity:.055;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.86' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.62'/%3E%3C/svg%3E");
  background-size:160px 160px}

/* ═══ УГОЛ: ПОДСКАЗКА И КАРТОЧКА КНИГИ ═══════════════════════════════════
   ⛔ ПОДПИСЬ НЕ ХОДИТ ЗА ОБЛОЖКОЙ. Пробовал ставить её под саму карточку —
   казалось, что этикетка под экспонатом честнее. На деле у нижнего ряда она
   падала прямо в текст полосы и ложилась на третью колонку (Юрий это и
   увидел), а у крайних обложек прижималась к краю кадра. Место у неё одно —
   правый нижний угол над полосой, тот самый, что Юрий отдал воздуху ещё в
   v18: там пусто по построению, и туда же смотрит глаз после полотна.

   ПОЯВЛЕНИЕ ПОСТРОЧНОЕ. Три строки выезжают из-под маски со сдвигом в 70 мс —
   номер, название, запрос. Это дороже простого проявления и стоит ровно
   столько же: три композитных transform на трёх элементах.

   ═══ v22: КАРТОЧКА ПЕРЕСТАЛА ЖДАТЬ КУРСОРА ═══════════════════════════════
   🔴 ГЛАВНАЯ СМЫСЛОВАЯ ПРАВКА ЭКРАНА, И ОНА ЗДЕСЬ, А НЕ В ЗАГОЛОВКЕ.
   Поле `q` у каждой книги — настоящий запрос читателя его словами. Это лучший
   текст на всём проекте, и в v21 его видел только тот, кто догадался навести
   мышь на едущую обложку; на телефоне (.cap{display:none}) его не видел
   никто. Экран из-за этого читался как каталог чужих книг: «Аня»,
   «Владимир», «Твой год» — красиво и ни о чём. Стоило запросу выйти на свет,
   и полотно стало галереей случаев: каждая книга родилась из чьего-то
   вопроса, и в чужом вопросе покупатель узнаёт свой.
   Поэтому карточка теперь листает витрину САМА (см. autoNext в скрипте), а
   наведение её перебивает. Разметка та же, добавлено одно состояние.

   ⚠️ ЧТО ИМЕННО ПОМЕНЯЛОСЬ В ПРАВИЛАХ НИЖЕ, ЧТОБЫ ЭТО СТАЛО ВОЗМОЖНО:
   · .card больше не position:absolute поверх подсказки. Раньше они делили
     одно место и подменяли друг друга (.cap__hint гасла по data-cap="1"), —
     логика «или подсказка, или карточка». Теперь карточка стоит всегда, а
     подсказка ПОД ней объясняет, что это за текст и что будет по клику.
   · data-cap из переключателя «видно / не видно» стал переключателем
     «на месте / уезжает»: смена книги гасит его на 300 мс, и три строки
     уезжают и приезжают той же анимацией, что писалась под наведение.
     Ничего нового на кадр это не стоит — те же три transform раз в пять
     секунд. */
.bp-hero .cap{position:relative;grid-row:2;grid-column:1;align-self:end;justify-self:end;z-index:7;
  /* ⚠️ 38ch, А НЕ 44. На широком кадре длинная цитата дотягивалась левым
     краем до зоны, где затемнение уже почти сошло на нет, и сквозь начало
     строки проступало название подъехавшей обложки. Расширять затемнение
     нельзя — оно съело бы светлый коридор в середине кадра, ради которого
     всё и построено; поэтому сужается карточка. Переносу вторая строка не
     мешает: высота под неё зарезервирована (см. .card__q). */
  width:min(38ch,34vw);text-align:right;pointer-events:none;
  display:grid;gap:10px;
  margin-bottom:clamp(30px,5vh,64px)}
/* ⚠️ ЭТО НЕ ПЛАШКА ПОД КАРТОЧКОЙ, И РАЗНИЦА ПРИНЦИПИАЛЬНА.
   Правило экрана: тип на полотне несёт собственный контраст тенью, а не
   ширмой, потому что каждый процент ширмы гасит товар. Тень карточку и
   держит — но у одной строки она не справляется: «Экземпляр № 001» набран
   9.5 px акцентным #E8B898, и когда под него подъезжает бирюзовая «Тёплые
   руки», строка тонет не по яркости, а по ЦВЕТУ — тень против этого бессильна
   (замерено на 1512: номер и название обложки сливались в одно пятно).
   Поэтому здесь не прямоугольник под текстом, а радиальный градиент из
   правого нижнего угла кадра — визуальное продолжение подложки полосы
   (.deck::before), которая приходит снизу. Он не имеет собственного контура,
   гаснет к 75% радиуса и на полотне читается как та же тень кадра, а не как
   подложка под надписью.
   ⛔ НЕ ЗАМЕНЯТЬ НА ROUNDED-ПРЯМОУГОЛЬНИК: любая различимая форма превратит
   витрину в интерфейсную панель, а весь смысл угла — что там книги, а не UI.
   Стоит ноль на кадре: статический градиент, ничего не анимируется. */
/* ⛔ ЛОКАЛЬНЫХ ПЯТЕН ПОД ТЕКСТОМ БОЛЬШЕ НЕТ — И НЕ ЗАВОДИТЕ ИХ СНОВА.
   Я дважды пытался подпереть набор собственной подложкой: сперва радиальной,
   потом линейной с маской. Оба раза выходило пятно с различимой кромкой, и оба
   раза Юрий это видел («смотри как неопрятно», «отвратительно»).
   Причина не в подборе стопов, а в геометрии: у подложки есть КОРОБКА, и её
   край всегда где-то проходит. Спрятать его можно, только доведя градиент до
   нуля на всех четырёх кромках, — а тогда под самим текстом плотности уже не
   остаётся. Это тупик по построению, а не неудачная настройка.
   ✅ РАБОТАЕТ ТОЛЬКО ОДНО: затемнение, ПРИКРЕПЛЁННОЕ К КРОМКЕ КАДРА. У него
   нет видимой границы, потому что там, где оно плотнее всего, — край экрана,
   где глаз и ожидает темноту. Всю эту работу делает .veil, см. ниже. */
/* 🔴 УГОЛ ГАСНЕТ И ЗАЖИГАЕТСЯ ЦЕЛИКОМ — ЭТО ИСПРАВЛЕНИЕ, А НЕ УКРАШЕНИЕ.
   Прозрачность стояла на .card, а подсказка под ней жила своей жизнью. В
   момент смены книги (240 мс каждые 5 с) три строки карточки исчезали, а
   служебная строка «ЗАПРОС ЧИТАТЕЛЯ · КЛИК — ИСТОРИЯ КНИГИ» оставалась висеть
   одна над пустотой в добрую сотню пикселей. Выглядело поломкой вёрстки.
   Независимый рецензент поймал это в двух случайных кадрах из шести — то есть
   посетитель это увидит, а не теоретически может увидеть.
   Теперь состояние одно на весь угол: карточка и подсказка — один предмет,
   гаснут и возвращаются вместе. Подложка (::before) гаснет с ними же, иначе в
   паузе на полотне оставалось бы тёмное пятно без содержимого. */
/* .14s, а не .2s: вместе с паузой в 165 мс угол пустует около 300 мс из
   каждых 5 секунд — 6% времени вместо прежних 11%. Рецензент ловил пустой
   кадр случайным скриншотом; теперь окно вдвое ýже. */
.bp-hero .cap{transition:opacity .14s var(--e-std)}
.bp-hero .scene[data-cap="0"] .cap{opacity:0}
/* 🔴 НА ТАЧ-УСТРОЙСТВАХ КАРТОЧКА НЕ ГАСНЕТ ВООБЩЕ.
   На десктопе она висит поверх полотна: пока текст сменяется, под ней всё
   равно едут обложки, и провала не видно. На телефоне она лежит В ПОТОКЕ, и
   те же 150 мс прозрачности оставляют посреди первого экрана чёрный прямо-
   угольник в треть высоты — рецензент поймал его случайным кадром, и поймает
   каждый, кто смотрит дольше пяти секунд.
   Здесь смена мгновенная: текст подменяется без перехода. Потери нет —
   построчная выездка задумывалась под наведение курсором, которого на
   телефоне не существует. */
@media (hover:none){
  .bp-hero .cap{transition:none}
  .bp-hero .scene[data-cap="0"] .cap{opacity:1}
  .bp-hero .card__l > *{transition:none}
  .bp-hero .scene[data-cap="0"] .card__l > *{transform:none}
}
/* 9.5 → 11 px. Слепой рецензент: «интерактив, в который вложены пятнадцать
   обложек и модальные окна, на телефоне просто не обнаруживается». Строка
   служебная, но она единственная объясняет, что за текст висит над ней и что
   будет по клику; невидимая подсказка не служебная, а бесполезная.
   Трекинг ослаблен с .2em до .16em: на выросшем кегле прежний разряд начинал
   рассыпать слово. */
.bp-hero .cap__hint{margin:0;white-space:nowrap;font-family:var(--mono);font-size:11px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--mut);opacity:.92}

.bp-hero .card{width:100%;display:grid;justify-items:end;gap:6px}
/* Каждая строка едет из-под собственной маски: overflow скрывает её до входа,
   а не прозрачность — от этого движение читается как проявка, а не как
   включение лампы. */
.bp-hero .card__l{display:block;overflow:hidden}
.bp-hero .card__l > *{display:block;transform:translateY(115%);
  transition:transform .62s var(--e-enter)}
.bp-hero .scene[data-cap="1"] .card__l > *{transform:none}
.bp-hero .scene[data-cap="1"] .card__l:nth-child(1) > *{transition-delay:.02s}
.bp-hero .scene[data-cap="1"] .card__l:nth-child(2) > *{transition-delay:.09s}
.bp-hero .scene[data-cap="1"] .card__l:nth-child(3) > *{transition-delay:.16s}
/* opacity .85 снята: строка и так самая мелкая на полотне, приглушать её
   означало отдавать её первой же светлой обложке. */
.bp-hero .card__no{font-family:var(--mono);font-size:9.5px;letter-spacing:.26em;
  color:var(--acc);font-feature-settings:var(--tnum)}
.bp-hero .card__t{font-family:var(--ital);font-style:italic;color:var(--fg);line-height:1.12;
  font-size:clamp(1.2rem,1.45vw,1.7rem);letter-spacing:-.01em}
/* 🔴 ЗАПРОС ЧИТАТЕЛЯ ПОДНЯТ В ВЕСЕ — САМАЯ ВАЖНАЯ СТРОКА ЭКРАНА ПОСЛЕ ЛИДА.
   Было: .82–.98rem цветом --mut, то есть приглушённая подпись под названием.
   И оба рецензента, независимо друг от друга, сказали одно: единственное
   место, где покупатель узнаёт СЕБЯ, — это чужой вопрос, и он набран самым
   мелким кеглем на экране, в самом дальнем углу. Красивая витрина при этом
   объясняет ЧТО продаётся и не объясняет ЗАЧЕМ.
   Стало .95–1.18rem цветом --body: строка сравнялась по весу с корпусом
   полосы и стала читаться раньше названия книги, что и правильно — название
   принадлежит продавцу, вопрос принадлежит человеку.
   ⚠️ Больше 1.18rem поднимать нельзя: карточка начнёт спорить с заголовком. */
/* 🔴 ВЫСОТА ЗАРЕЗЕРВИРОВАНА ПОД ДВЕ СТРОКИ — ЭТО ИСПРАВЛЕНИЕ СДВИГА МАКЕТА.
   Запросы читателей разной длины: «жду знака, хотя всё уже случилось» встаёт в
   одну строку, «десять вопросов, которые ты не задаёшь вслух» — в две. Карточка
   меняла высоту на 21 px каждые пять секунд, и на телефоне, где она лежит в
   потоке, вместе с ней ездило всё ниже: КНОПКА ПОКУПКИ ПРЫГАЛА С 666 НА 687 px
   ПОД БОЛЬШИМ ПАЛЬЦЕМ. Замерено на 390×844 девяноста пробами; высота документа
   скакала 1465 ↔ 1486.
   Промах по кнопке в точке конверсии — самая дорогая мелочь, какая бывает, и
   выглядит она недоделанностью, а не живостью.
   min-height в 2.8em — ровно две строки при line-height 1.4. На десктопе
   карточка стоит в гриде с выключкой по низу и ничего не двигала, но правило
   общее: так одинаково на всех ширинах и не сломается от новой книги с длинным
   запросом.
   ⛔ НЕ МЕНЯЙТЕ line-height, НЕ ПЕРЕСЧИТАВ min-height: они связаны. */
.bp-hero .card__q{color:var(--body);line-height:1.4;font-size:clamp(.95rem,1.05vw,1.18rem);
  min-height:2.8em;text-wrap:pretty}
/* Волосяная черта под карточкой — та же, что держит линейку под заголовком:
   на полотне тексту нужна опора, иначе он висит. Растёт вместе с появлением. */
.bp-hero .card__rule{height:1px;background:var(--acc);opacity:.34;width:0;justify-self:end;
  transition:width .7s var(--e-enter) .1s}
.bp-hero .scene[data-cap="1"] .card__rule{width:100%}
/* ⚠️ ТЕНЬ ЗДЕСЬ СИЛЬНЕЕ, ЧЕМ У ЗАГОЛОВКА, И ЭТО НЕ ПЕРЕСТРАХОВКА.
   Пока карточка появлялась только под курсором, она лежала на ЗАМЕРШЕЙ и
   притушенной сцене: при hold="1" .web__dim гасит полотно на 32%, и трёх
   слоёв тени хватало с запасом. Теперь карточка стоит всегда — то есть на
   полном, непритушенном полотне, и под неё раз в несколько секунд подъезжает
   любая обложка, включая бирюзовую «Тёплые руки» и кремовую «Всё уже взошло».
   Замерено на 1512: на светлой обложке «Экземпляр № 001» и название тонули.
   Четвёртый слой в 52 px — мягкое тёмное гало, которое не читается плашкой
   (плашку тут ставить нельзя: обложки — товар, см. правило над h1). */
.bp-hero .cap__hint,
.bp-hero .card__no,
.bp-hero .card__t,
.bp-hero .card__q{
  text-shadow:0 1px 10px rgb(var(--color-bg-deep-rgb) / .95),0 0 24px rgb(var(--color-bg-deep-rgb) / .92),
              0 0 52px rgb(var(--color-bg-deep-rgb) / .9),0 0 3px rgb(var(--color-bg-deep-rgb) / .95)}

/* ═══ СЦЕНА В ТРИ ЯРУСА ══════════════════════════════════════════════════
   ПОЛНАЯ ПЕРЕСБОРКА РАЗМЕЩЕНИЯ (правка Юрия 18.08: «переделай ВСЁ с нуля»).

   ЧТО БЫЛО НЕ ТАК. Весь текст стоял колонной в левой половине кадра: три
   абзаца подряд одинакового веса, заголовок всего вдвое крупнее корпуса,
   врезка — тёмным прямоугольником посреди них. Получался документ, положенный
   на красивый фон. Плюс колонна в 54vw держала меру на голодном пайке и
   заставляла тушить половину полотна ширмой.

   ЧТО СТАЛО. Кадр разложен на три яруса во всю ширину:
   I  · КОЛОНТИТУЛ — марка слева, девиз справа, прижаты к верхней кромке.
   II · ЗАГОЛОВОК — доминанта. Освободившееся место позволило поднять кегль
        вдвое (было ~49 px на 14", стало ~95): теперь между заголовком и
        корпусом пять с половиной крат, а не два с половиной. Ровно это и
        отличает кадр от документа.
   III· ПОЛОСА — весь корпус ушёл вниз и лёг тремя колонками во всю ширину
        кадра. Колонка получилась ~420 px вместо прежних 240 — мера выросла до
        ~50 знаков, и это при том, что текст занимает вдвое меньше высоты, чем
        когда стоял в столбик.
   Полотно от этого выиграло больше всех: верхние две трети кадра теперь его
   целиком, гасить приходится только низ. */
/* ⚠️ КОЛОНКА ОБЯЗАНА БЫТЬ minmax(0,1fr), А НЕ ПОДРАЗУМЕВАЕМОЙ auto.
   Неявная колонка грида сайзится по содержимому — и вся сцена сжималась до
   1117 px при кадре в 1512: полоса не доходила до правого края, кнопка
   останавливалась за 275 px до него, и правый нижний угол выглядел пустым
   (Юрий это и увидел). Колонки текста при этом теряли пятую часть меры. */
.bp-hero .stage{position:absolute;inset:0;z-index:8;display:grid;
  grid-template-columns:minmax(0,1fr);
  grid-template-rows:auto 1fr auto;
  /* Ни один ярус не должен заводить неявных дорожек — см. grid-column у .cap */
  padding:clamp(18px,2.8vh,34px) var(--pad) clamp(20px,3vh,36px);
  pointer-events:none}
/* ⚠️ КУРСОР РАЗРЕШЁН АДРЕСНО, А НЕ «ВСЕМ ДЕТЯМ СЦЕНЫ».
   Здесь стояло `.stage > * {pointer-events:auto}` плюс отдельное правило,
   гасившее заголовок и колонтитул. Оно не работало — и это чистая
   специфичность: `.stage > *` весит один класс (0,1,0), а `h1` — один тег
   (0,0,1), и тег проигрывает. Так же молча проигрывало и `pointer-events:none`
   у подсказки в углу.
   Итог замером: 47% площади полотна курсор не брал вовсе. Перехватывали
   заголовок, окно ролика, его колонка, слово внутри и карточка в углу —
   человек вёл мышью по обложкам, а книги не отзывались. Ровно на это Юрий и
   указал («много мест если навести — не наводится, особенно верхний ряд»).
   Теперь сцена не ловит курсор целиком, а право получает единственный, кому
   оно нужно, — нижняя полоса с кнопкой и ссылкой. Заголовок больше не
   выделяется мышью: на первом экране это никому не нужно, а живое полотно —
   нужно. */
.bp-hero .deck{pointer-events:auto}

/* ⚠️ ВЕСЬ ТИП, ЛЕЖАЩИЙ НА ПОЛОТНЕ, НЕСЁТ СОБСТВЕННЫЙ КОНТРАСТ.
   Это принципиальнее, чем кажется. Читаемость заголовка и колонтитула нельзя
   обеспечивать затемнением полотна: обложки — товар, и каждый процент ширмы
   гасит именно его. Мы дважды прошли этот маятник — сначала эллипс не
   дотягивался до конца строки и тире тонуло в обложке, потом растянулся до
   78vw и выжег левую треть кадра. Тень по тексту снимает вопрос вовсе: она
   работает на любом фоне, ничего не гасит, статична и стоит ноль на кадре.
   Ширме после этого остаётся лишь мягкая подложка под самый плотный набор. */
.bp-hero h1,
.bp-hero .brand,
.bp-hero .vid__cap,
.bp-hero .lede{text-shadow:
  0 1px 14px rgb(var(--color-bg-deep-rgb) / .92),
  0 0 34px rgb(var(--color-bg-deep-rgb) / .8),
  0 0 4px rgb(var(--color-bg-deep-rgb) / .75)}

/* ═══ ЛЕСТНИЦА ПОЯВЛЕНИЯ ══════════════════════════════════════════════════
   🔴 ЗАДЕРЖКИ УКОРОЧЕНЫ ВДВОЕ (было .16 / .28 / .42 / .5 с). Слепой замер
   рецензента: на кадре t≈0.3 с нижняя половина экрана — три колонки, гарантия,
   цена, кнопка — практически невидима, и первое, что встречает человека, это
   стена обложек без единого читаемого предложения о сделке. Полсекунды на
   экране, где живут пять, — это десятая часть всего внимания, потраченная на
   красивый вход.
   Лестница сохранена (колонтитул → заголовок → лид → полоса), но сжата так,
   что к 0.35 с читается уже всё. Порядок важнее длительности: он ведёт взгляд,
   а не развлекает. */
/* ЯРУС I — колонтитул. Так набирают колонтитул книги: слева марка, справа
   девиз (строка Юрия от 17.08 21:08). Ноль лишней высоты. */
.bp-hero .top{grid-row:1;display:flex;align-items:center;justify-content:space-between;gap:24px;
  opacity:0;animation:hero-riseIn .7s var(--e-enter) .06s forwards}
.bp-hero .brand{display:flex;align-items:center;gap:10px;margin:0;
  font-family:var(--mono);font-size:clamp(9px,.62vw,10.5px);letter-spacing:.32em;
  text-transform:uppercase;color:var(--sub);white-space:nowrap}
.bp-hero .brand i{width:15px;height:15px;flex:none;border-radius:50%;border:1px solid var(--acc);
  position:relative}
.bp-hero .brand i::after{content:"";position:absolute;inset:4.5px;border-radius:50%;background:var(--acc)}
/* ═══ ВИДЕО В УГЛУ ══════════════════════════════════════════════════════
   ⚠️ ДИАМЕТР 76–96 px — ЭТО НЕ ВКУСОВЩИНА, А ПОРОГ УЗНАВАНИЯ ЛИЦА. Мельче
   60 px лицо перестаёт читаться лицом и превращается в значок: доверия такой
   кружок не добавляет, а место занимает. Крупнее сотни начинает спорить с
   заголовком, который обязан оставаться единственной доминантой.
   ⚠️ ПОДПИСЬ СЛЕВА, А НЕ ПОД КРУЖКОМ. Под ним она уехала бы на полотно и
   потребовала собственного затемнения; слева она попадает в тот же градиент
   колонтитула, что и марка, и ничего не стоит.
   ⚠️ pointer-events:auto ОБЯЗАТЕЛЕН: сцена курсор не ловит (см. разбор над
   .deck), иначе кружок будет виден и не нажат. */

.bp-hero .vid__cap{font-family:var(--mono);font-size:clamp(9px,.62vw,10.5px);
  letter-spacing:.18em;text-transform:uppercase;color:var(--mut);
  text-align:right;line-height:1.65;white-space:nowrap;
  transition:color .3s var(--e-std)}
.bp-hero .vid__disc{position:relative;flex:none;
  /* Диаметр поднят с 76–96 до 92–118: на прежнем лицо считывалось, но
     приходилось всматриваться, а кружок должен звать, а не проверять зрение. */
  width:clamp(92px,7.4vw,118px);aspect-ratio:1;border-radius:50%;overflow:hidden;
  /* ПЛЕЙСХОЛДЕР ПОСТЕРА. Тёплое пятно уходит в тень книзу — так же, как
     освещены обложки, чтобы кружок читался частью этого мира, а не вставкой
     из другого. Заменяется на <img> без единой правки остальных правил. */
  background:
    radial-gradient(circle at 42% 34%,rgb(var(--color-accent-strong-rgb) / .30) 0%,
      rgb(var(--color-accent-strong-rgb) / .10) 42%,transparent 70%),
    linear-gradient(160deg,var(--color-border) 0%,var(--color-bg-elevated) 62%,var(--color-bg) 100%);
  box-shadow:0 0 0 1px rgb(var(--color-accent-rgb) / .34),0 14px 34px rgba(0,0,0,.5);
  transition:box-shadow .35s var(--e-std),transform .35s var(--e-enter)}
/* Знак воспроизведения — треугольник на границах, без картинки и шрифта. */
.bp-hero .vid__play{position:absolute;top:50%;left:calc(50% + 2px);
  width:0;height:0;transform:translate(-50%,-50%);
  border-top:9px solid transparent;border-bottom:9px solid transparent;
  border-left:15px solid var(--acc);
  transition:border-left-color .3s var(--e-std)}



/* Кадр берётся по ширине, а голова сидит в верхней трети вертикального
   ролика — поэтому окно смещено вверх, иначе в круг попадает торс. */
.bp-hero .vid__v{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:50% 10%;display:block}
/* Знак воспроизведения лежит поверх кадра и должен читаться на любом:
   собственная тень вместо плашки — плашка закрыла бы лицо. */
.bp-hero .vid__play{filter:drop-shadow(0 2px 6px rgba(0,0,0,.75))}

/* ЯРУС II — заголовок. Прижат к верхней трети, а не по центру: под ним должен
   остаться воздух, иначе доминанта превращается в шапку.

   ⚠️ v22: МЕСТО В СЕТКЕ ДЕРЖИТ .lead, А НЕ h1. В ярус въехал лид, и два
   элемента в одной ячейке грида легли бы друг на друга: у .cap та же
   grid-row:2, и она уже занимает низ ячейки (align-self:end). Обёртка решает
   это без единой новой дорожки — h1 и лид едут вместе как один предмет.
   Если будете возвращать grid-row на h1 — не забудьте снять его с .lead,
   иначе заголовок встанет в неявную дорожку и полоса уедет за кадр. */
@keyframes hero-riseIn{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}
/* ⛔ НИКАКОГО max-width НА .lead — ЭТО ЛОВУШКА, В КОТОРУЮ Я УЖЕ ПОПАЛ.
   Стояло max-width:min(100%,52ch), и выглядело безобидно. Но `ch` считается от
   ШРИФТА САМОГО ЭЛЕМЕНТА, а .lead — обычный <div> с кеглем тела в 16 px.
   52ch превращались в 508 px, и в эти 508 px зажимался ЗАГОЛОВОК в 90 px: на
   1920 «Создаём книги —» ломалось на «Создаём / книги —», хотя свободного
   места справа оставалось больше тысячи пикселей. В v21 такого не было —
   там max-width стоял на самом h1, где 38ch считаются от 90 px и в реальную
   ширину никогда не упираются.
   Меру держат дети, каждый в своём кегле: h1 — 38ch от заголовочного,
   .lede — 46ch от своего. Обёртке ширину ограничивать нечем и незачем. */
.bp-hero .lead{grid-row:2;grid-column:1;align-self:start;margin:clamp(20px,5vh,64px) 0 0}
.bp-hero h1{margin:0;max-width:min(100%,38ch);
  font-weight:250;color:var(--fg);letter-spacing:-.038em;line-height:.98;
  text-wrap:balance;
  /* Ножка «Создаём книги —» вдвое короче прежней «Создаём персональные
     книги —», и потолок кегля поднят следом: доминанта не должна теряться
     оттого, что текста в ней стало меньше. */
  font-size:clamp(2rem,.5rem + 4.3vw,min(6rem,12.2vh));
  opacity:0;animation:hero-riseIn .8s var(--e-enter) .12s forwards}

/* ЛИД — сделка одной строкой. Смысл разобран в шапке файла; здесь только
   почему он набран ИМЕННО так.
   ⚠️ КЕГЛЬ ДЕРЖИМ НА 19–22 px, НЕ БОЛЬШЕ. Соблазн поднять его велик — строка
   несёт главное сообщение экрана. Но между заголовком (до 96 px) и корпусом
   полосы (~17 px) сейчас пять с половиной крат, и это то, чем кадр отличается
   от документа. Лид крупнее 22 px становится вторым заголовком, разница
   схлопывается до двух крат, и экран снова читается страницей.
   ⚠️ И НЕ УЖЕ 40ch: строка обязана лечь в ОДНУ, максимум в две строки. На
   трёх она перестаёт быть репликой и становится абзацем, а абзац на этом
   месте спорит с полосой внизу — там уже есть три.
   Верхний отступ отрицательный по той же причине, что у .roll: под окном
   ролика остаётся 0.235em пустоты от маски, и без подтяга лид отваливается
   от заголовка на видимую пропасть. */
.bp-hero .lede{position:relative;margin:clamp(14px,1.9vh,24px) 0 0;color:var(--body);
  font-weight:300;
  max-width:min(100%,46ch);line-height:1.38;text-wrap:pretty;
  font-size:clamp(1rem,.86rem + .5vw,1.34rem);
  opacity:0;animation:hero-riseIn .8s var(--e-enter) .2s forwards}
/* 🔴 ЛИДУ НУЖНА СОБСТВЕННАЯ ОПОРА, И ТЕНИ ЗДЕСЬ НЕ ХВАТАЕТ.
   Тень спасает белый набор на тёмном, но лид лежит на едущей ленте, и под него
   раз в несколько секунд подъезжает ЗОЛОТОЕ название обложки — того же роста,
   почти на той же базовой линии и близкого тона. Слепой рецензент прочитал
   получившееся как «мы отвечаем на негоОксана» и «на него Владимир»: главная
   строка экрана ломалась ровно там, где человек должен понять сделку.
   Тень такое не лечит в принципе — она гасит фон ВОКРУГ глифа, а мешает здесь
   не фон, а чужой текст той же яркости.
   Слой узкий и вытянут вдоль строки, гаснет к правому краю: обложки под ним
   темнеют ровно на ширину набора и остаются видны — ширмой это не становится
   (см. правило над h1). Тот же приём, что у карточки в углу, и по той же
   причине; радиус так же не превышает 100%, иначе появится видимый край. */
/* Подложки у лида нет: см. запрет над .cap и разбор в .veil. */
/* Опора под сделкой — тем же акцентом, что <b> в полосе: «целой книгой» и
   есть то, ради чего строка написана. */
.bp-hero .lede b{color:var(--fg);font-weight:600}

/* ЦЕПОЧКА. На десктопе скрыта — там путь разложен тактами полосы.
   Стрелка рисуется псевдоэлементом между звеньями, а не символом в разметке:
   так последнее звено не тащит за собой висячую стрелку при переносе. */
.bp-hero .chain{display:none;margin:clamp(10px,1.6vh,16px) 0 0;
  font-family:var(--mono);font-size:12px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--sub)}
.bp-hero .chain span + span::before{content:"→";margin:0 .7em;color:var(--acc);opacity:.75}

/* ═══ РОЛИК ПОЛУЧАТЕЛЯ ════════════════════════════════════════════════════
   ⚠️ ШАГ РАВЕН ВЫСОТЕ ОКНА — и это единственная величина, других здесь нет.
   Ошибка, которую ловили дважды: шаг делали по высоте СТРОКИ (1.2em, потом
   1.44em), а окно — того же размера. Тогда соседнее слово стоит ink-в-ink к
   границе окна, и его хвосты («р», «у», «б») торчат в срезе: под заголовком
   висела чёрточка, а в момент смены — обрубки букв.
   ПОЧЕМУ 1.78em, А НЕ 2.08em. Сосед уходит за край окна на (шаг − 1.31)/2, где
   1.31em — содержательная коробка Lora italic. Формально хватило бы и 1.44em,
   но метрика шрифта не учитывает выносные курсива: хвост «р» вылезает ещё
   примерно на 0.12em, на этом 1.44em и посыпался. 1.78em даёт зазор 0.235em —
   вдвое больше выноса. 2.08em, поставленные сгоряча, были перестраховкой, и
   весь лишний воздух осел между строками заголовка: Юрий увидел пропасть.
   --rpad .22em, а не .3em: при шаге 1.78em низ окна отстоит от хвоста «р»
   всего на 15.6 px, и растушёвка в 18.7 px подтирала выносные у пяти слов из
   девяти на 2–3 px. Замерено по actualBoundingBoxDescent.

   ⚠️ ЭТОТ БЛОК ОДНАЖДЫ БЫЛ УДАЛЁН ЦЕЛИКОМ вместе со старой колонной при
   пересборке композиции — и заголовок мгновенно превратился в столбик из
   шести слипшихся строк («о васо вашем ребёнкео вашей паре…»), потому что без
   .roll__win пропадает и окно, и обрезка. Если правите разметку заголовка —
   проверяйте, что эти пять правил на месте. */
/* margin-top −.38em, а не −.24em: на кегле 79 px шаг окна в 1.78em даёт 141 px,
   и при прежнем подтяге между «Пишем книгу —» и получателем открывалась
   пропасть — та самая, на которую Юрий указывал ещё в v18. Подтяг съедает её,
   не трогая ни шаг окна, ни маску, то есть выносные курсива по-прежнему целы. */
.bp-hero .roll{display:block;margin-top:-.38em;--rstep:1.78em;--rpad:.22em}
/* 🔴 МАСКА СНЯТА — ОНА И БЫЛА ПРИЧИНОЙ РАЗЪЕХАВШЕГОСЯ ЗАГОЛОВКА.
   Здесь сходились три вещи: overflow:hidden, mask-image и transition:transform
   на дочерней колонке. Маска на слое, который непрерывно анимируется, — тот
   самый composited-опасный приём, от которого этот файл предостерегает в
   разборе над .bk: браузер заводит под маску отдельную поверхность и в
   какой-то момент перестаёт её перерисовывать. Тогда обрезка отваливается, и
   соседние слова ролика проступают поверх заголовка полупрозрачными
   призраками — Юрий поймал это на боевом файле.
   ⚠️ ОБРЕЗКУ ДЕЛАЕТ contain:paint, А НЕ ТОЛЬКО overflow. contain — это
   гарантия на уровне спецификации: ни один потомок не имеет права рисовать
   за коробкой, что бы ни решил композитор. Стоит дешевле маски и не заводит
   лишних поверхностей.
   ⚠️ ЧТО ПОТЕРЯЛИ. Маска растушёвывала верх и низ окна на 0.22em, пряча
   выносные курсива в срезе. Их прячет и шаг: при 1.78em под ink-ом остаётся
   0.235em пустоты — больше, чем вылет хвоста «р» (≈0.12em). То есть чернила
   до кромки не доходят и без растушёвки; ради этого запаса шаг и подбирался
   (см. разбор выше).
   ⛔ НЕ ВОЗВРАЩАЙТЕ mask-image СЮДА. Если понадобится смягчить кромку —
   делайте это неподвижным слоем поверх, а не маской на движущемся. */
.bp-hero .roll__win{display:block;position:relative;overflow:hidden;contain:paint;
  height:var(--rstep);min-width:var(--rw-max,0px)}
.bp-hero .roll__col{display:block;position:absolute;left:0;top:0;width:max-content;
  transition:transform .95s var(--e-enter)}
.bp-hero .roll__it{display:block;width:max-content;height:var(--rstep);line-height:var(--rstep);
  white-space:nowrap;font-family:var(--ital);font-style:italic;color:var(--acc);
  letter-spacing:-.018em}
/* Линейка идёт по низу окна. При шаге 1.78em под ink-ом слова остаётся 0.235em
   пустоты, поэтому подтягивать её можно не больше чем на 0.06em — иначе она
   сядет на хвост «р» в «партнёре». */
.bp-hero .roll__rule{display:block;height:1px;background:var(--acc);opacity:.34;
  width:var(--rw,10ch);margin-top:-.06em;transition:width .95s var(--e-enter)}/* ═══ ЯРУС III · ПОЛОСА ══════════════════════════════════════════════════
   Три такта в три колонки во всю ширину кадра. Это НЕ те три столбца, что были
   в v20: там колонка была 240 px и держала 24 знака в строке — газетная врезка,
   из-за которой кегль упирался в потолок. Здесь колонка ~420 px и мера ~50
   знаков, потому что полоса идёт во всю ширину, а не в 54vw.
   Колонки равной длины по построению: в каждом такте 27–31 слово.
   Волосяная линейка сверху — граница между кадром и полосой; она же не даёт
   тексту «висеть» на полотне. */
/* ⚠️ ПОДЛОЖКА ПРИНАДЛЕЖИТ САМОЙ ПОЛОСЕ, А НЕ ШИРМЕ. Это была главная ошибка
   всей нижней части: затемнение задавалось процентами высоты кадра, а полоса
   стоит там, где кончился её собственный текст. На 727 px они совпадали, на
   1100 — расходились, и сквозь колонки просвечивали корешки «Всё уже взошло»
   и номера обложек. Юрий это и увидел.
   Теперь полоса несёт затемнение сама: отрицательные поля выводят фон под
   самые края кадра, а 88 px разгона сверху дают мягкий вход без шва. Где бы
   полоса ни оказалась, текст всегда лежит на плотном — по построению, а не по
   совпадению. Ширме остаётся только заголовок, и полотно открылось ещё выше. */
.bp-hero .deck{position:relative;grid-row:3;align-self:end;
  opacity:0;animation:hero-riseIn .8s var(--e-enter) .26s forwards}
/* ⚠️ ПОДЛОЖКА МЕРЯЕТСЯ ОТ ОКНА, А НЕ ОТ СЕТКИ. Первый заход делал её фоном
   самой полосы с отрицательными полями — и справа она не доставала до края:
   замерено 1238 px вместо 1512, потому что ширина колонки грида считается по
   содержимому, а не по контейнеру. Из-за этого сквозь правую треть полосы
   по-прежнему просвечивали обложки, хотя текст слева уже лежал на плотном.
   Отдельный слой в 100vw с выключкой по центру не зависит от сетки вовсе и
   доедет до края при любой раскладке.
   92 px разгона сверху дают мягкий вход без шва: к верхней кромке полосы
   плотность уже .92, а над ней полотно открыто. */
.bp-hero .deck::before{content:"";position:absolute;z-index:-1;pointer-events:none;
  left:50%;transform:translateX(-50%);width:100vw;
  /* ⚠️ РАЗГОН 92 px БЫЛ КОРОТОК. Обложка высотой 300–400 px попадала в него
     серединой: низ уже в глухом чёрном, верх ещё в полную силу — карточка
     выглядела обрезанной ножом, и стык полосы читался полосой. 170 px — это
     примерно половина ближней обложки, на такой длине переход перестаёт быть
     виден вовсе. Плотность к верхней кромке полосы прежняя, .93. */
  top:-170px;bottom:calc(-1 * clamp(24px,3.4vh,42px));
  background:linear-gradient(180deg,
    rgb(var(--color-bg-deep-rgb) / 0) 0%,
    rgb(var(--color-bg-deep-rgb) / .14) 9%,
    rgb(var(--color-bg-deep-rgb) / .46) 18%,
    rgb(var(--color-bg-deep-rgb) / .8) 25%,
    rgb(var(--color-bg-deep-rgb) / .93) 31%,
    rgb(var(--color-bg-deep-rgb) / .99) 40%,
    var(--color-bg-deep) 50%)}
/* Зазор вынесен в переменную: им и только им разводятся колонки — см.
   разбор снятых вертикальных линеек ниже. */
.bp-hero .beats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  --bgap:clamp(20px,3vw,58px);gap:var(--bgap);margin:0;padding:0;list-style:none;
  border-top:.5px solid rgb(var(--color-paper-rgb) / .14);padding-top:clamp(12px,1.8vh,20px)}
/* 🔴 ВЕРТИКАЛЬНЫЕ ЛИНЕЙКИ МЕЖДУ КОЛОНКАМИ СНЯТЫ (правка Юрия 20.08:
   «лишние полоски разграничивающие колонки текста появились, ужасно
   выглядит»). Довод в их пользу был газетный: вертикаль сообщает объём до
   чтения и снижает порог «начать читать». На этой полосе он не сработал —
   у каждой колонки уже есть свой знак сверху, и линейка оказалась третьим
   разделителем подряд после знака и зазора: полоса читалась таблицей.
   ⛔ НЕ ВОЗВРАЩАТЬ. Если колонки снова покажутся слипшимися, лечить нужно
   зазором --bgap, а не новой графикой. */
.bp-hero .bt{position:relative}
/* ЗНАК КОЛОНКИ. Рисован волосяной линией в 0.9 px — той же, что печать и
   рамки обложек: на первом экране не должно быть двух разных графических
   языков. Знак не украшение: он даёт глазу точку входа в колонку, которой
   раньше не было вовсе — три абзаца читались как три простыни (правка Юрия
   18.08). */
/* ⚠️ ВЫКЛЮЧКА ЗНАКА ПО ЛЕВОМУ КРАЮ НАБОРА, А НЕ ПО КОРОБКЕ SVG. У всех трёх
   рисунков внутри квадрата 40×40 оставались разные поля — 3.2, 5.1 и 7.2 —
   и на кадре знаки висели правее первой буквы абзаца, каждый на свою величину.
   viewBox у каждого обрезан по фактическим границам рисунка, поэтому теперь
   они выключены по одной оси с текстом и одного оптического размера. */
/* ⛔ РИМСКИХ ЦИФР У ТАКТОВ НЕТ И БЫТЬ НЕ ДОЛЖНО. Я завёл их, чтобы колонки
   читались тремя шагами, а не тремя абзацами, — и это была ошибка: знак уже
   делает ровно эту работу, он и есть маркер такта. Две маркировки подряд не
   усиливают друг друга, а спорят, и цифра читается служебным мусором.
   Правило на будущее: если у элемента уже есть визуальный маркер, второй не
   добавляет ясности — он добавляет шум. */
.bp-hero .bt__i{display:block;width:clamp(32px,2.7vw,42px);height:auto;color:var(--acc);
  margin:0 0 clamp(10px,1.5vh,15px)}
/* ⛔ РАЗРЕЗАТЬ ТАКТ НАДВОЕ — ХУЖЕ, ЧЕМ ОСТАВИТЬ ПРОСТЫНЁЙ. Я разбил каждый
   такт по смысловой цезуре и набрал части разным тоном: думал, так появится
   вход в абзац. На деле один такт превратился в два обрывка — вторая часть
   с приглушённым тоном стала читаться сноской, хотя в третьей колонке там
   как раз самое важное («тон, цвета, обложка — всё персонально»). И низ
   колонок разъехался: 3+3, 3+3, 4+2 строки при общей высоте, выровненной по
   верху.
   ✅ ЧИТАЕМОСТЬ УЗКОЙ КОЛОНКИ ДАЁТ НЕ РАЗРЕЗ, А ВОЗДУХ МЕЖДУ СТРОК. При мере
   в 42 знака межстрочный 1.5 держит текст плотной серой массой; 1.62 её
   разжимает, не трогая ни высоту блока целиком, ни порядок чтения.
   ⛔ НЕ ВОЗВРАЩАЙТЕ РАЗБИВКУ НА ДВА <p> И ДВА ТОНА. */
.bp-hero .bt__t{margin:0;color:var(--body);font-weight:300;line-height:1.62;
  font-size:clamp(.88rem,.74rem + .36vw,1.08rem);
  /* text-wrap:pretty убирает висячее слово в конце абзаца — «ваш вопрос»
     оставалось одно на последней строке третьей колонки. Браузер сам
     перебалансирует последние строки; там, где свойство не поддержано,
     раскладка просто остаётся прежней. */
  text-wrap:pretty}
/* ДВА УРОВНЯ АКЦЕНТА, А НЕ ОДИН. <b> — смысловая опора, белым полужирным;
   <u> — числа и меры, акцентным цветом и чуть крупнее.
   ⚠️ НА КОЛОНКУ РОВНО ОДНА ОПОРА И ДВЕ МЕРЫ, НЕ БОЛЬШЕ. В первом заходе я
   выделил почти половину текста — и выделенным перестало быть хоть что-то:
   ровно та ошибка, от которой предостерегает правило ниже. Если добавляете
   акцент — снимите другой. */
/* ⚠️ КОРОТКАЯ ОПОРА НЕ ЛОМАЕТСЯ ПЕРЕНОСОМ. «— всё / персонально» через
   строку читается двумя обрывками, а не акцентом: жирное начертание тянет
   взгляд, и разрыв в этом месте бьёт сильнее, чем в обычном тексте.
   Класс вешается ТОЧЕЧНО и только на короткие фразы: длинную опору
   («одну из самых подробных систем в мире») запретить переносить нельзя —
   она распёрла бы колонку и вылезла за меру. */
.bp-hero .bt__t b{color:var(--fg);font-weight:600}
.bp-hero .bt__t b.nb{white-space:nowrap}
/* 🔴 ЧИСЛА — ЭТО КРЮЧКИ, ПО КОТОРЫМ ПОЛОСУ ЧИТАЮТ, НЕ ЧИТАЯ.
   Человек, давший экрану десять секунд, не читает три абзаца подряд — он
   скользит по ним и цепляется за то, что выделяется. Если зацепиться не за
   что, он не начинает читать вовсе. «2500 лет», «200 страниц А4», «30 000»,
   «8–10 дней», «около 100» — сами по себе рассказывают историю: древнее
   знание, огромный расчёт, доступная цена, короткий срок, толстая книга.
   Поэтому кегль поднят с 1.06 до 1.16em, а насыщенность — с 500 до 600:
   меры должны читаться на полшага раньше окружающего текста.
   ⚠️ ВЫШЕ 1.2em НЕ ПОДНИМАТЬ — числа начнут спорить с опорой <b> и разорвут
   строку по вертикали: при межстрочном 1.62 более крупный глиф вылезет за
   интерлиньяж и строки запляшут. */
.bp-hero .bt__t u{text-decoration:none;color:var(--acc);font-weight:600;font-size:1.16em;
  letter-spacing:-.006em;white-space:nowrap}
/* ⛔ МЕТОК НАД КОЛОНКАМИ БОЛЬШЕ НЕТ (правка Юрия 18.08). Вынос «2500 ЛЕТ» и
   «9 ДНЕЙ» в моно-сноски казался находкой — шкала времени читалась отдельно от
   текста. На деле вышло наоборот: числа, выдернутые из фразы, потеряли смысл
   («9 дней» — чего именно?), а «2500 лет», сильнейшие слова на экране, ушли в
   служебный кегль и перестали считываться вовсе. Числа вернулись внутрь фраз
   и набраны там полужирным.
   Поворот теперь отмечен только линейкой над колонкой и цветом текста —
   без плашки, которая читалась как выделение мышкой, и без метки. */
.bp-hero .bt--pivot::before{content:"";position:absolute;left:0;right:0;
  top:calc(-1 * clamp(12px,1.8vh,20px) - 1px);height:1.5px;background:var(--acc)}
/* ⛔ СПЛОШНАЯ ПОДСВЕТКА СРЕДНЕЙ КОЛОНКИ СНЯТА. Она красила такт целиком в
   --fg, и вместе с новой двухступенчатой плотностью средний столбец потерял
   бы внутреннюю иерархию — стал бы единственной ровной стеной из трёх.
   Поворот по-прежнему отмечен акцентной линейкой над колонкой; этого хватает,
   а читаемость важнее подсветки. */

/* СТРОКА ДЕЙСТВИЯ. Гарантия слева, кнопка справа — на одной оси, в один рост.
   Текст гарантии — ДОСЛОВНО утверждённый Юрием, без единого добавленного
   слова: «Мы уверены, вы удивитесь точности. Если нет — вернём ВСЮ СУММУ
   деньгами». Всё, что я дописывал раньше (про карту, баллы и нотариуса),
   снято — правка 18.08 «не пиши лишнего». Нотариус остался там, где ему и
   место: на самой печати, по кругу. */
/* ⚠️ СЕТКА, А НЕ flex-wrap. На широком кадре гарантия с печатью занимала
   почти всю строку, ссылка с кнопкой не помещались и переносились под неё —
   кнопка уезжала к левому краю, а правый нижний угол оставался пустым (правка
   Юрия 18.08). Две колонки «1fr auto» держат кнопку у правого края при любой
   ширине и любой длине текста гарантии. */
/* ═══ НИЖНЯЯ ПОЛОСА — ОДНА СЕТКА НА ЧЕТЫРЕ ТЕКСТА ════════════════════════
   🔴 ДВЕ ПОПЫТКИ ДО ЭТОЙ БЫЛИ НЕВЕРНЫ, И ОБЕ ПОУЧИТЕЛЬНЫ.
   1. Полоса из двух колонок, каждая складывает свою пару строк. Высоты
      колонок разные (печать 82 px против кнопки 52 px), нижние строки
      расходились на 12–16 px — Юрий 20.08: «всё на разных уровнях».
   2. Служебные строки вынесены в отдельный ряд грида. Уровень сошёлся, но
      строка гарантии оторвалась от цены на добрых три десятка пикселей:
      связанные вещи перестали читаться парой — «выровнял, но не красиво же,
      в тупую сделал».
   ⚠️ ВЕРНО — НЕ ВЫРАВНИВАТЬ КОЛОНКИ, А ПОЛОЖИТЬ ВСЕ ЧЕТЫРЕ ТЕКСТА В ОДНУ
   СЕТКУ. Верхний ряд несёт главное (цена · ссылка · кнопка), нижний —
   служебное (гарантия · состав страницы). Уровни совпадают потому, что это
   один ряд грида, а не потому, что кто-то подобрал отступ; а пары остаются
   рядом, потому что ряды разделяет обычный row-gap в 5–8 px.
   ⚠️ ОБЁРТКИ РАСТВОРЕНЫ ЧЕРЕЗ display:contents. Они остаются в разметке ради
   семантики (печать с гарантией — один смысловой блок), но раскладку
   целиком задаёт .act: иначе высота обёртки снова начнёт диктовать уровни.
   ⚠️ ПЕЧАТЬ ЗАНИМАЕТ ОБА РЯДА И ЦЕНТРИРУЕТСЯ. Так она держит левый край
   полосы целиком, а не висит рядом с одной из строк, и — главное — её
   высота больше не решает, где окажется строка гарантии. */
.bp-hero .act{display:grid;
  grid-template-columns:auto minmax(0,1fr) auto auto;
  grid-template-areas:
    "seal price more btn"
    "seal note  note next";
  align-items:center;
  column-gap:clamp(10px,1vw,16px);row-gap:clamp(3px,.45vh,6px);
  margin-top:clamp(14px,2.2vh,26px);padding-top:clamp(13px,2vh,22px);
  border-top:.5px solid rgb(var(--color-paper-rgb) / .09)}
.bp-hero .guar,
.bp-hero .guar__b,
.bp-hero .act__go,
.bp-hero .act__row{display:contents}
/* ⚠️ ЗАЗОРЫ РАЗНЫЕ, А column-gap В ГРИДЕ ОДИН. «О методе» и «Изучить
   историю» — две кнопки подряд, и между ними просвет должен быть меньше,
   чем между печатью и текстом или между оффером и кнопками: рядом стоящие
   органы управления читаются группой только вплотную. Поэтому общий зазор
   задан по самому тесному месту, а там, где нужно шире, добавлено полем
   у самого элемента. Отрицательных margin здесь нет намеренно — они ломают
   расчёт колонок при смене кегля. */
.bp-hero .seal{grid-area:seal;align-self:center;margin-right:clamp(4px,.9vw,14px)}
.bp-hero .guar__t{grid-area:price}
.bp-hero .act__fine{grid-area:note;justify-self:start}
.bp-hero .ghost{grid-area:more;margin-left:clamp(8px,1.4vw,26px)}
.bp-hero .btn{grid-area:btn}
/* Подпись прижата вправо — под правый край кнопки; стрелка в конце строки
   уходит вверх и упирается в кнопку. */
.bp-hero .act__next{grid-area:next;justify-self:end}
/* ⚠️ ВЫСОТУ СТРОКИ ЗАДАЁТ ПЕЧАТЬ, И ЭТО ЕДИНСТВЕННАЯ ПРИЧИНА, ПО КОТОРОЙ ЦЕНА
   ПОМЕСТИЛАСЬ БЕСПЛАТНО. Печать — 82 px на ноутбучном кадре, текст гарантии
   занимает под ней от силы 44. Пустые 38 px справа от печати и есть место под
   строку цены: полоса не растёт ни на пиксель. Отдельной строкой под кнопкой
   цена добавляла 24 px, и на 1512×727 низ полосы уезжал за кадр — кнопка
   оказывалась подрезана снизу (замерено: 740 при кромке 727).
   Если будете менять размер печати — проверьте эту строку: она держится на
   том, что печать выше текста. */
/* ⚠️ nowrap ОБЯЗАТЕЛЕН. На 390 px строка переносилась ровно перед стрелкой, и
   «→» оставалась висеть одна на отдельной строке под подчёркиванием — читалось
   как мусор в вёрстке. Ссылка коротка (18 знаков), в любую мобильную ширину
   встаёт целиком; переносится строка цены перед ней. */
.bp-hero .guar__more{font-family:var(--mono);font-size:inherit;letter-spacing:.16em;
  text-transform:uppercase;color:var(--sub);text-decoration:none;
  white-space:nowrap;
  border-bottom:1px solid rgb(var(--color-paper-rgb) / .2);padding-bottom:1px;
  transition:color .3s var(--e-std),border-color .3s var(--e-std)}
.bp-hero .guar__more:hover{color:var(--acc);border-bottom-color:var(--acc)}
/* ⚠️ РАЗДЕЛИТЕЛЬ ВЕШАЕТСЯ НА ЦЕНУ, А НЕ НА ССЫЛКУ. Псевдоэлемент внутри <a>
   входит в его строчную коробку — точка досталась бы и подчёркиванию, и
   области клика. Здесь он снаружи. */
/* Разделитель снят вместе со строкой о носителе: в .act__fine остался один
   элемент, точке не между чем стоять. */
/* Печать — не картинка из стока, а SVG в той же волосяной графике. Текст по
   кругу идёт на textPath; вращение очень медленное (46 с на оборот): хватает,
   чтобы взгляд её нашёл, и мало, чтобы спорить с полотном. Анимируется ОДИН
   элемент одним transform. */
/* Печать была мельче собственной подписи и читалась значком. Здесь она —
   вещественное доказательство обещания, и по весу должна спорить с кнопкой
   на другом краю строки. */
.bp-hero .seal{width:clamp(66px,5.4vw,92px);height:auto}
.bp-hero .seal__ring{fill:none;stroke:var(--acc)}
/* 8.2 → 9.2 px и полная непрозрачность: кольцевая надпись перестала быть
   орнаментом. Больше не влезает — окружность фиксированной длины. */
.bp-hero .seal__arc{font-family:var(--mono);font-size:9.2px;letter-spacing:.1em;
  fill:var(--acc);opacity:1}
/* Разворот на 8° — чтобы начало надписи стояло не строго внизу, а читалось
   сразу; это статичный поворот, а не анимация. */
.bp-hero .seal__g{transform-box:view-box;transform-origin:50% 50%;transform:rotate(-8deg)}
.bp-hero .seal__big{font-family:var(--mono);font-size:25px;fill:var(--acc);font-weight:500;
  letter-spacing:-.03em}
.bp-hero .seal__sub{font-family:var(--mono);font-size:6.6px;letter-spacing:.2em;
  fill:var(--acc);opacity:.7}
/* ⚠️ МЕРА 46 ЗНАКОВ РЕЗАЛА ФРАЗУ ПОПОЛАМ. Обещание в 71 знак ломалось на
   «…вернём / всю сумму деньгами» даже там, где до кнопки оставалось семьсот
   пикселей пустоты. Гарантия — единственная строка, которую нельзя ронять
   переносом посреди сказуемого. 74 знака дают ей уложиться в строку на любом
   кадре шире 1400 и спокойно перенестись по смыслу на узких. */
/* ⚠️ ОФФЕР — САМАЯ ГРОМКАЯ ФРАЗА ПОЛОСЫ, И НАБОР ОБЯЗАН ЭТО ПОКАЗЫВАТЬ.
   Он стоял тем же кеглем, что окружающий текст, и терялся между печатью и
   кнопкой (правка Юрия 20.08: «оффер выделим сильный»). Поднят кегль и
   уплотнён межстрочный — фраза читается одним куском, а не двумя строками.
   ⚠️ ЛИНИЯ ПОД НИМ — НЕ ДЕКОР, А ОСНОВАНИЕ. Она заканчивает оффер и держит
   под собой служебную строку: без неё между ними зияла пустота в три
   десятка пикселей («не было так много пустоты между строк»). Затухание
   слева направо повторяет ход чтения и не режет полосу пополам, как это
   сделала бы ровная черта во всю ширину. */
.bp-hero .guar__t{margin:0;color:var(--fg);line-height:1.3;max-width:74ch;text-wrap:pretty;
  font-size:clamp(1rem,.84rem + .46vw,1.28rem);font-weight:300;
  position:relative;padding-bottom:clamp(8px,.9vh,12px)}
/* ⚠️ ПЛОТНОСТЬ ЛИНИИ ПОДНЯТА ДВАЖДЫ. На .5 в начале и .13 к середине она
   угадывалась, но не работала: «полоска есть конечно, но чуть видна» —
   а её задача не украшать, а заполнять промежуток между оффером и строкой
   гарантии. Теперь старт .82, плато до 34% и мягкий сход к нулю: линия
   читается как основание фразы и при этом не режет полосу пополам. */
.bp-hero .guar__t::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1.5px;
  border-radius:1px;
  background:linear-gradient(90deg,rgb(var(--color-accent-rgb) / .82),
    rgb(var(--color-accent-rgb) / .66) 34%,rgb(var(--color-accent-rgb) / .22) 68%,rgb(var(--color-accent-rgb) / 0) 96%)}
.bp-hero .guar__t b{color:var(--acc);font-weight:600}
/* Цена — тем же ростом, что и фраза вокруг неё, но плотнее и белым: она
   опознаётся как число, не крича. tnum обязателен, иначе цифры пляшут. */
.bp-hero .guar__t .price{color:var(--fg);font-weight:600;letter-spacing:-.01em;
  font-feature-settings:var(--tnum);white-space:nowrap}

/* Кнопка — единственный по-настоящему яркий предмет кадра. */
.bp-hero .btn{display:inline-flex;align-items:center;gap:10px;text-decoration:none;flex:none;
  padding:clamp(13px,1.6vh,17px) clamp(22px,2vw,34px);border-radius:2px;
  background:var(--acc);color:var(--acc-on);font-weight:700;letter-spacing:.005em;
  font-size:clamp(.94rem,.88rem + .16vw,1.06rem);
  box-shadow:0 1px 0 rgba(255,255,255,.22) inset;
  transition:background .3s var(--e-std),transform .3s var(--e-enter),
             box-shadow .3s var(--e-std)}
.bp-hero .btn svg{width:15px;height:15px;flex:none}
.bp-hero .btn:hover{background:var(--acc2);transform:translateY(-2px);
  box-shadow:0 1px 0 rgba(255,255,255,.3) inset,0 14px 34px rgb(var(--color-accent-rgb) / .26)}
/* ⚠️ ВТОРИЧНАЯ КНОПКА, А НЕ ПОДЧЁРКНУТАЯ СТРОКА. «Подробнее о методе»
   набиралось тем же кеглем и тем же светлым тоном, что оффер слева, и
   сливалось с ним в одну строку — Юрий 22.08: «сливается со строчкой
   30 000 за книгу», непонятно, что по ней можно ткнуть. Рамка отделяет
   ссылку от текста и называет её предметом, по которому нажимают;
   акцентный тон и стрелка договаривают направление. Заодно текст сокращён
   до «О методе» — в рамке длинная формулировка не нужна.
   ⚠️ РАМКА ВОЛОСЯНАЯ, ФОН ПОЧТИ ПРОЗРАЧНЫЙ. Полноценная вторая кнопка
   рядом с главной отобрала бы у неё внимание: на экране должен остаться
   один по-настоящему яркий предмет. */
.bp-hero .ghost{position:relative;display:inline-flex;align-items:center;gap:9px;
  text-decoration:none;overflow:hidden;perspective:340px;
  color:var(--acc);font-size:clamp(.84rem,.8rem + .12vw,.94rem);
  padding:clamp(9px,1vh,13px) clamp(15px,1.3vw,20px);border-radius:3px;
  border:1px solid rgb(var(--color-accent-rgb) / .34);white-space:nowrap;
  transition:border-color .35s var(--e-std),color .35s var(--e-std),
    box-shadow .35s var(--e-std)}
.bp-hero .ghost::before{content:"";position:absolute;inset:0;z-index:0;
  transform-origin:left center;
  background:linear-gradient(90deg,rgb(var(--color-accent-rgb) / .14),rgb(var(--color-accent-rgb) / .03));
  transition:transform .5s var(--e-enter)}
.bp-hero .ghost > *{position:relative;z-index:1}
.bp-hero .ghost svg{width:14px;height:14px;flex:none;
  transition:transform .35s var(--e-std)}
.bp-hero .ghost:hover,.bp-hero .ghost:focus-visible{color:var(--acc2);
  border-color:rgb(var(--color-accent-rgb) / .66);outline:none;
  box-shadow:inset 14px 0 24px -16px rgb(var(--color-accent-strong-rgb) / .55)}
.bp-hero .ghost:hover::before,.bp-hero .ghost:focus-visible::before{
  transform:rotateY(-62deg)}
.bp-hero .ghost:hover svg{transform:translateX(3px)}
/* ⚠️ ПОДПИСЬ ПОД КНОПКОЙ НЕ УДЛИНЯЕТ ПОЛОСУ. Высоту строки действия задаёт
   печать (84 px на коротком кадре), а столбец с кнопкой набирает 49 + 8 + 17 =
   74 — то есть подпись въезжает в тот же запас, в котором уже стоит цена
   слева. Проверено замером: полоса осталась 89 px. Если будете добавлять сюда
   вторую строку — сначала померьте, а не на глаз. */
/* 10–11.5 → 11.5–12.5 px и цвет с --faint на --sub: строка отвечает на «что
   будет, если я нажму» — вопрос, который задают ровно перед кликом, и читать
   её должно быть легче, чем разглядывать. */
/* ⚠️ ПОДПИСЬ ПОД КНОПКОЙ — ПО ЕЁ ГАБАРИТУ, БЕЗ ГРАФИКИ.
   🔴 УГОЛКОВУЮ ВЫНОСКУ «└» Я ПРОБОВАЛ — И ЭТО БЫЛА ОШИБКА. Замысел был
   провести линию от кнопки к первому слову подписи; на экране вышла
   чёрточка, зацепившаяся за левый край и повисшая сбоку от строки, —
   Юрий 20.08: «стало ужасно прям». Графическая связь тут лишняя.
   Работает габарит: подпись переносится ровно по ширине кнопки и
   центрируется. Строка под кнопкой и по её краям читается как подпись под
   изображением — чья она, вопроса нет.
   🔴 grid-template-columns:min-content ЗДЕСЬ НЕ ГОДИТСЯ, ХОТЯ И ПРОСИТСЯ.
   Минимум у кнопки — не она сама: внутри неё flex-строка, которая умеет
   переноситься, и min-content оказывается длиной самого длинного СЛОВА.
   Кнопка схлопывалась с 305 до 159 px (замерено на 1512).
   ⚠️ ПОЭТОМУ ШИРИНУ КОЛОНКИ ЗАДАЁТ ТОЛЬКО КНОПКА: width:0 обнуляет вклад
   подписи в расчёт ширины, а min-width:100% растягивает её по уже
   посчитанной колонке. Ни одного зашитого числа — кегль кнопки плавает от
   1280 до 1920, и любая константа разъехалась бы. */
/* ⚠️ НАБОР ТОТ ЖЕ, ЧТО У «НОТАРИАЛЬНАЯ ГАРАНТИЯ ВОЗВРАТА» (правка Юрия
   20.08). Две служебные строки по краям полосы обязаны быть одним голосом:
   моно, капитель, разрядка .16em. Разный набор читался как разный статус —
   будто одна строка важнее другой.
   ⚠️ СТРЕЛКА ВЕДЁТ ВВЕРХ-ВЛЕВО, НА КНОПКУ, И СТОИТ В САМОМ ПРАВОМ КРАЮ.
   Это замена снятой уголковой выноске: линия идёт от конца строки вверх и
   упирается в кнопку — принадлежность подписи видна без слов. Прижата
   вправо намеренно: слева строка начинается с текста, и стрелка там спорила
   бы с первым словом. */
.bp-hero .act__next{margin:0;white-space:nowrap;
  display:flex;align-items:center;gap:10px;
  font-family:var(--mono);font-size:clamp(11px,.72vw,12px);
  letter-spacing:.16em;text-transform:uppercase;line-height:1.45;
  color:var(--sub)}
/* ⚠️ ЛИНИЯ ИДЁТ ОТ КНОПКИ ВНИЗ И ПОВОРАЧИВАЕТ ВЛЕВО, В ТЕКСТ.
   Направление я дважды взял неверно. Сначала остриё смотрело вверх-влево —
   в пустоту слева от кнопки; потом вверх-вправо — в саму кнопку, будто
   подпись указывает на неё. Верно наоборот: выноска идёт ОТ названного
   (кнопка) К пояснению (строка), поэтому вертикаль начинается под кнопкой,
   а остриё указывает влево на слова — Юрий 20.08: «должна идти сверху
   вниз, отзеркалить, типа <---|». */
.bp-hero .act__up{flex:none;width:28px;height:17px;color:rgb(var(--color-accent-rgb) / .62)}
/* ЦЕНА. Две конечные суммы, а не «+5 000»: доплату, которую надо вычислять,
   голова читает как спрятанную. Кегль служебный намеренно — цена здесь якорь
   для гарантии, а не аргумент; аргумент стоит на кнопке рядом.
   ⚠️ tnum обязателен: без табличных цифр «15 000» и «20 000» в одной строке
   встают разной ширины и строка выглядит набранной вручную.
   ⚠️ ПЕРЕНОС РАЗРЕШЁН. Соблазн поставить nowrap («цена не должна ломаться»)
   ловится на 1080–1280: левая колонка там ýже строки, и неразрывная строка
   распирала бы грид, утаскивая кнопку за край. Ломаться строке негде —
   пробелы внутри сумм неразрывные. */
/* 🔴 БЫЛО 10–11.5 px ЦВЕТОМ --faint (.58 белого) — И ЭТО БЫЛА ОШИБКА
   ПРИОРИТЕТА, А НЕ ВКУСА. Слепой рецензент сформулировал точно: главное число
   сделки набрано мельче служебных подписей. Логика «цена — якорь, а не
   аргумент» верна для иерархии, но не для кегля: якорь, который не видно, не
   держит. Часть аудитории просто не заметила бы цену, дошла до формы и
   отвалилась там — с испорченным впечатлением, что сумму от неё прятали.
   Стало 12.5–14 px цветом --mut. Моноширинный и tnum остаются: две суммы в
   одной строке обязаны стоять в колонку по цифрам.
   ⚠️ Крупнее делать нельзя — начнёт спорить с самой гарантией над собой,
   а её обещание дороже суммы. */
.bp-hero .act__fine{margin:0;font-family:var(--mono);font-size:clamp(12.5px,.82vw,14px);
  letter-spacing:.06em;line-height:1.55;color:var(--mut);
  font-feature-settings:var(--tnum)}

/* ═══ АННОТАЦИЯ ПОД ЧИСЛОМ «300 000» ═════════════════════════════════════
   ⚠️ ПУНКТИРНОЕ ПОДЧЁРКИВАНИЕ — ЕДИНСТВЕННЫЙ ЗНАК, КОТОРЫЙ ЧИТАЕТСЯ БЕЗ
   ОБЪЯСНЕНИЙ. Сплошное обещает переход на другую страницу, вопросительный знак
   в кружке удешевляет полосу, иконка «i» на премиальном экране выглядит
   интерфейсом службы поддержки. Пунктир говорит ровно то, что нужно: здесь
   есть пояснение, и оно раскроется на месте.
   ⚠️ ЭТО <button>, А НЕ <span> С ОБРАБОТЧИКОМ. Иначе до сметы не добраться с
   клавиатуры — а клавиатурой пользуется как раз тот дотошный человек, ради
   которого смета и заводится. */
/* ⚠️ ТОТ ЖЕ КЕГЕЛЬ, ЧТО У СОСЕДНЕГО ЧИСЛА. Кнопка наследовала font целиком,
   то есть 1em и вес 300, — а «30 000» рядом набрано правилом .bt__t u в
   1.16em и весе 600. Сравнение двух цен разваливалось: «300 000» выглядело
   мельче «30 000», хотя оно на порядок больше. Числа, которые сравнивают,
   обязаны быть ОДНОГО размера — иначе глаз сравнивает кегли, а не суммы.
   ⚠️ ЦВЕТ РАЗНЫЙ, И ЭТО НАМЕРЕННО. Равный кегль сравнивает, приглушённый
   тон расставляет роли: «30 000» — живая цена акцентом, «300 000» —
   отвергнутая альтернатива телесным тоном. Красить обе акцентом нельзя,
   иначе фраза «а не 300 000» перестаёт читаться как отказ. */
/* 🔴 nowrap НА КНОПКЕ БЫЛ ОШИБКОЙ, И ОНА ОБОШЛАСЬ В ДВЕ СТРОКИ ТЕКСТА.
   Он ставился ради числа: «300 000» рвать нельзя. Но неразрывным
   становился весь якорь вместе со знаком, то есть кусок в 120–140 px,
   который строка обязана уместить целиком, — и вторая колонка распухала
   на две строки против соседних (замерено: 8 против 6 на 1280, 6 против 4
   на 2048). Число защищает .ann__n, а разрывать между словами внутри
   абзаца — нормально. Знак при этом не отрывается: между ним и текстом
   нет пробела, значит нет и точки переноса. */
.bp-hero .ann{font:inherit;font-size:1.16em;font-weight:600;letter-spacing:-.006em;
  color:var(--mut);background:none;border:0;padding:0;
  cursor:help;white-space:normal;
  transition:color .25s var(--e-std)}
/* ⚠️ ПУНКТИР ЖИВЁТ НА ЧИСЛЕ, А НЕ НА КНОПКЕ. Граница у кнопки тянулась бы и
   под знаком сноски, перечёркивая кружок; вложенный span оставляет линию
   ровно под цифрами. Толщина 1.5 px и прижим к базовой линии — потому что
   тонкий пунктир в 30 px под строкой на экране попросту не виден. */
.bp-hero .ann__n{border-bottom:1.5px dashed rgb(var(--color-accent-rgb) / .62);padding-bottom:1px;
  white-space:nowrap;transition:border-color .25s var(--e-std)}
/* ⚠️ СПЛОШНАЯ ЛИНИЯ — ПЕРЕХОД, ПУНКТИР — РАСКРЫТИЕ НА МЕСТЕ. Два разных
   обещания в одном абзаце обязаны выглядеть по-разному, иначе человек не
   знает, уедет он с экрана или получит пояснение здесь. «Одна из самых
   подробных систем в мире» — заявление, которое одной всплывающей карточкой
   не доказать: под него отведён отдельный экран, и ссылка ведёт туда
   (решение Юрия 22.08: «правильнее сделать якорь на экран»). */
.bp-hero .lnk{color:var(--fg);font-weight:600;text-decoration:none;white-space:normal;
  transition:color .25s var(--e-std)}
/* ⚠️ ЛИНИЯ НА ТЕКСТЕ, А НЕ НА ССЫЛКЕ — иначе она прошла бы и под знаком,
   перечеркнув кружок. Та же причина, что у .ann__n. */
.bp-hero .lnk__t{border-bottom:1.5px solid rgb(var(--color-accent-rgb) / .7);padding-bottom:1px;
  transition:border-color .25s var(--e-std)}
/* ⚠️ ЗНАК ОБЯЗАТЕЛЕН, ОДНОГО ПОДЧЁРКИВАНИЯ МАЛО. С линией фраза читалась
   просто выделенной — Юрий 22.08: «не видно, что можно навести». Кружок
   рядом с числом уже означает «здесь есть пояснение»; тот же кружок со
   стрелкой наружу означает «здесь есть отдельный экран». Два знака одной
   формы, разного содержания — человек различает их с первого раза и
   больше не путает раскрытие с переходом.
   ⚠️ СТРЕЛКА — ФОНОВАЯ КАРТИНКА, А НЕ ГЛИФ «↗». Символ есть не во всех
   моношрифтах, и там, где его нет, вместо знака встал бы пустой квадрат.
   ⚠️ ЗНАК ВИСИТ НА ПОСЛЕДНЕМ СЛОВЕ, А НЕ НА ВСЕЙ ССЫЛКЕ. Фраза в колонке
   переносится, и знак, приделанный к ссылке целиком, уезжал на следующую
   строку один — «в мире» вверху, кружок внизу перед запятой. Обёртка
   .lnk__w держит слово и знак неразрывной парой; подчёркивание при этом
   осталось на .lnk__t, то есть только под буквами. */
.bp-hero .lnk__w{white-space:nowrap}
.bp-hero .lnk__w::after{content:"";display:inline-block;width:.94em;height:.94em;
  margin-left:.25em;vertical-align:-.02em;border-radius:50%;
  border:1px solid rgb(var(--color-accent-rgb) / .45);
  background:rgb(var(--color-accent-rgb) / .1)
    url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M3.1 6.9 6.9 3.1M4.1 3.1h2.8v2.8' fill='none' stroke='%23E8B898' stroke-width='1.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")
    center/56% no-repeat;
  transition:border-color .25s var(--e-std),background-color .25s var(--e-std)}
.bp-hero .lnk:hover{color:var(--acc2)}
/* ⚠️ ФОКУС С КЛАВИАТУРЫ НЕЛЬЗЯ ОБОЗНАЧАТЬ ОДНИМ ЦВЕТОМ. Здесь стояло
   `:focus-visible{color:…;outline:none}` — то же, что при наведении. Мышью так
   можно (курсор сам показывает, где ты), с клавиатуры — нет: единственный
   признак «я тут» это смена оттенка, а при дальтонизме и её нет. Из 237
   фокусируемых элементов /next это оказался единственный без кольца. */
.bp-hero .lnk:focus-visible{color:var(--acc2);
  outline:2px solid rgb(var(--color-accent-rgb) / .85);outline-offset:3px;border-radius:2px}
.bp-hero .lnk:hover .lnk__t,
.bp-hero .lnk:focus-visible .lnk__t{border-bottom-color:var(--acc2)}
.bp-hero .lnk:hover .lnk__w::after,
.bp-hero .lnk:focus-visible .lnk__w::after{
  border-color:var(--acc2);background-color:rgb(var(--color-accent-rgb) / .24)}
/* ⚠️ ЯКОРЬ АННОТАЦИИ — ОДНО СЛОВО, А НЕ ФРАЗА. Кнопке задан nowrap (число
   рвать нельзя), поэтому длинный якорь становится неразрывным куском: пара
   «нашим специалистам» вместе со знаком давала 232 px, которые строка
   обязана уместить целиком, и вторая колонка распухала на две строки
   против соседних — ровно тот баланс, который выравнивали. Одно слово
   держит и смысл, и ширину.
   ⚠️ ЗНАК СНОСКИ, А НЕ ИКОНКА ИНТЕРФЕЙСА. Серый кружок «?» с иконкой
   поддержки удешевил бы полосу; надстрочный акцентный знак — приём книжный,
   и на экране про книги он читается как «здесь есть примечание». Именно он
   делает аннотацию заметной: пунктир один работает только для того, кто уже
   знает, что искать (правка Юрия 20.08: «не видно, что можно навести»).
   ⚠️ ПСЕВДОЭЛЕМЕНТ НЕ ЧИТАЕТСЯ ВСЛУХ, ПОТОМУ ЧТО У КНОПКИ ЕСТЬ aria-label.
   Без него скринридер произнёс бы «300 000 вопросительный знак». */
/* 🔴 ЗНАК ПРОБОВАЛИ ВЫНЕСТИ ИЗ ПОТОКА — И ЭТО ПРИШЛОСЬ ОТКАТИТЬ.
   Замысел был честный: кнопка — inline-block, то есть неразрывный атом, и
   знак внутри неё этот атом удлиняет; position:absolute убирал его вклад в
   перенос, и вторая колонка сходилась с соседними (6/6/6 на 1280, 4/4/4 на
   2048 вместо 8/6 и 6/4). Но выпавший из потока знак некуда деть: вровень
   с буквами он накрывает следующее слово, поднятый над строкой — лезет в
   строку выше, а у ссылки «в мире» он и вовсе закрыл запятую. Две лишние
   строки текста дешевле, чем кружок поверх букв.
   ⛔ НЕ ВОЗВРАЩАТЬ absolute. Если колонки снова разъедутся — причина в
   длине среднего такта (проверено отключением знаков: без них 1600 и 1920
   всё равно дают 7 и 6 строк против 5 и 4), и лечить надо текст. */
.bp-hero .ann::after{content:"?";display:inline-flex;align-items:center;
  justify-content:center;width:1.5em;height:1.5em;margin-left:.26em;
  vertical-align:.44em;font-family:var(--mono);font-size:.5em;font-weight:600;
  line-height:1;color:var(--acc);background:rgb(var(--color-accent-rgb) / .10);
  border:1px solid rgb(var(--color-accent-rgb) / .45);border-radius:50%;
  transition:background .25s var(--e-std),border-color .25s var(--e-std),
    color .25s var(--e-std)}
.bp-hero .ann:hover,
.bp-hero .ann:focus-visible,
.bp-hero .ann[aria-expanded="true"]{color:var(--acc2)}
/* Та же причина, что у .lnk выше: `outline:none` оставлял клавиатуре только
   смену оттенка, а «300 000» и «специалистам» — кнопки, открывающие панель. */
.bp-hero .ann:focus-visible{outline:2px solid rgb(var(--color-accent-rgb) / .85);
  outline-offset:3px;border-radius:2px}
.bp-hero .ann:hover .ann__n,
.bp-hero .ann:focus-visible .ann__n,
.bp-hero .ann[aria-expanded="true"] .ann__n{border-bottom-color:var(--acc2)}
.bp-hero .ann:hover::after,
.bp-hero .ann:focus-visible::after,
.bp-hero .ann[aria-expanded="true"]::after{
  background:var(--acc2);border-color:var(--acc2);color:var(--color-bg)}

/* ⚠️ ПАНЕЛЬ, А НЕ МОДАЛЬНОЕ ОКНО. Модалка гасит экран и требует закрытия —
   это разговор, который человек не начинал. Смета должна открыться рядом с
   числом, дать себя прочитать и исчезнуть, когда взгляд ушёл: её работа —
   снять сомнение, а не перехватить управление.
   ⚠️ position:fixed И КООРДИНАТЫ ОТ СКРИПТА. Панель выше своей строки и шире
   колонки; лежи она в потоке полосы — распёрла бы такт и утащила кнопку за
   сгиб. Фиксированное положение выносит её из раскладки совсем. */
/* ⚠️ max-height С ПРОКРУТКОЙ — ЖЁСТКАЯ ГАРАНТИЯ, А НЕ ПОДСТРАХОВКА.
   Одиннадцать работ, четыре метки групп, крупный итог, шкала и сноска
   упираются в ноутбучный кадр 727 px почти вплотную. Кегли ниже подобраны
   так, что панель укладывается, но любая добавленная строка вернёт проблему. Ограничение по высоте оставляет
   расчёт читаемым при любом составе: не влезло — прокручивается внутри. */
/* ⚠️ 640, А НЕ 470. На узкой панели первая колонка получала 170 px, и почти
   каждая работа ломалась на две строки — смета из расчёта превращалась в
   лохматый список. Лишняя ширина выпрямляет все одиннадцать строк и при
   этом делает панель НИЖЕ: переносов нет — высоты меньше. */
.bp-hero .ann__panel{position:fixed;z-index:40;width:min(640px,92vw);
  max-height:calc(100dvh - 28px);overflow-y:auto;
  padding:clamp(15px,1.3vw,20px) clamp(18px,1.6vw,26px) clamp(12px,1.1vw,16px);
  /* Свечение сверху — та же оптика, что у сцены: свет падает на смету
     сверху, а не заливает её равномерно, как интерфейсную плашку. */
  background:radial-gradient(125% 58% at 50% 0%,rgb(var(--color-accent-rgb) / .06),
      transparent 68%),var(--color-bg);
  border:1px solid rgb(var(--color-accent-rgb) / .19);border-radius:4px;
  box-shadow:0 30px 80px rgba(0,0,0,.78);
  opacity:0;transform:translateY(6px);pointer-events:none;
  transition:opacity .22s var(--e-std),transform .28s var(--e-enter)}
.bp-hero .ann__panel[data-on="1"]{opacity:1;transform:none;pointer-events:auto}
/* Световой шов по верхней кромке: панель «зажигается» сверху, а не просто
   появляется прямоугольником. Одна линия — весь эффект. */
.bp-hero .ann__panel::before{content:"";position:absolute;top:0;left:0;right:0;height:1px;
  background:linear-gradient(90deg,transparent,rgb(var(--color-accent-rgb) / .6) 28%,
    rgb(var(--color-accent-rgb) / .6) 72%,transparent)}
/* Надзаголовок называет жанр документа до того, как начнётся чтение:
   человек понимает, что перед ним смета, за долю секунды. */
.bp-hero .ann__k{margin:0 0 6px;font-family:var(--mono);font-size:9px;
  letter-spacing:.3em;text-transform:uppercase;color:var(--acc);opacity:.72}
.bp-hero .ann__t{margin:0 0 5px;font-family:var(--ital);font-style:italic;color:var(--fg);
  font-size:clamp(1.06rem,1.14vw,1.24rem);line-height:1.2;letter-spacing:-.012em}
.bp-hero .ann__sub{margin:0 0 clamp(9px,.85vw,12px);font-family:var(--mono);
  font-size:9.5px;letter-spacing:.05em;line-height:1.55;color:var(--sub);
  font-feature-settings:var(--tnum)}
/* Крестик нужен только там, где нет курсора: мышью панель закрывается уходом. */
.bp-hero .ann__x{position:absolute;top:10px;right:10px;display:none;
  width:34px;height:34px;border-radius:50%;cursor:pointer;
  border:1px solid rgb(var(--color-fg-rgb) / .2);background:rgb(var(--color-bg-deep-rgb) / .6);
  color:var(--fg);font-size:15px;line-height:1}

/* ⚠️ ЧИСЛА МОНОШИРИННЫМ И С ТАБЛИЧНЫМИ ЦИФРАМИ. Смета убеждает не текстом, а
   тем, что колонка сумм стоит колонкой: цифры одной ширины выстраиваются в
   столбик, и глаз читает их как расчёт. Пропорциональные цифры разъезжаются,
   и та же таблица выглядит записанной от руки. */
/* ⚠️ КЕГЕЛЬ ТАБЛИЦЫ — ФИКСИРОВАННЫЙ, НЕ vw. Панель шириной 640 px одинакова
   на всех кадрах, а кегль на vw рос вместе с экраном: на 1920 текст был
   крупнее, чем на 1280, и в той же коробке ломался на две строки. Ширина
   постоянна — кегль обязан быть постоянным, иначе перенос зависит от
   размера окна, к которому таблица не имеет отношения. */
.bp-hero .ann__tbl{width:100%;border-collapse:collapse;
  font-size:12.5px;line-height:1.28}
.bp-hero .ann__tbl th{font-family:var(--mono);font-weight:400;font-size:9.5px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--sub);
  text-align:right;padding:0 0 7px;border-bottom:1px solid rgb(var(--color-paper-rgb) / .13)}
.bp-hero .ann__tbl th:first-child{text-align:left}
/* ⚠️ БЕЗ ЭТОГО ЗАЗОРА ЧИСЛА СЛИПАЮТСЯ. Ячейкам задан nowrap, ширину они
   берут по содержимому — и «67 000 знаков» упиралось прямо в «1 200/1000»,
   читаясь одним нечитаемым числом. Отступ идёт слева у каждой колонки,
   кроме первой: справа его съела бы выключка по правому краю. */
.bp-hero .ann__tbl th+th,
.bp-hero .ann__tbl td+td{padding-left:16px}
/* ⚠️ ЧИСЛОВЫМ ЯЧЕЙКАМ — nowrap. Без него «1 200/1000» переносится на две
   строки, а «345 000 ₽» роняет знак рубля вниз: расчёт мгновенно перестаёт
   читаться как расчёт. Переносить разрешено только первой колонке — там
   проза, и перенос ей естественен. */
.bp-hero .ann__tbl td{padding:3.6px 0;color:var(--body);text-align:right;
  white-space:nowrap;
  font-family:var(--mono);font-feature-settings:var(--tnum);
  border-bottom:1px solid rgb(var(--color-paper-rgb) / .055)}
.bp-hero .ann__tbl td:first-child{text-align:left;font-family:var(--sans);
  white-space:normal;color:var(--mut);padding-right:12px}
.bp-hero .ann__tbl td:nth-child(2){color:var(--sub)}
.bp-hero .ann__tbl td span{color:var(--sub);font-size:.86em}
/* ⚠️ ГРУППЫ — ГЛАВНОЕ ЛЕКАРСТВО ОТ «ПРОСТЫНИ». Одиннадцать равнозначных
   строк подряд глаз не структурирует: он видит список и отказывается его
   читать. Четыре смысловых блока с подытогом дают опоры — можно прочитать
   только заголовки («замысел, текст, иллюстрации, книга») и уже понять, из
   чего собрана цена. А подытог рядом с меткой отвечает на вопрос «сколько
   стоит рисовать» без сложения в уме.
   ⚠️ ЗНАК ПЕРЕД МЕТКОЙ, А НЕ ПЛАШКА И НЕ ФОН. Заливка строки читалась бы
   как выделение мышью и утяжелила бы панель. Сначала стояла чёрточка — она
   держала воздух, но не говорила ничего; знак делает ту же работу и вдобавок
   называет раздел до чтения слова (правка Юрия 20.08: «не хватает иконок»).
   ⚠️ РИСОВАНЫ ВОЛОСЯНОЙ ЛИНИЕЙ, КАК ЗНАКИ КОЛОНОК И ПЕЧАТЬ. На экране не
   должно быть двух графических языков: залитые иконки внесли бы второй. */
.bp-hero .ann__tbl tr.grp td{padding:11px 0 4px;border-bottom:0;
  font-family:var(--mono);font-size:9px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--acc);opacity:.85}
.bp-hero .ann__tbl tbody:first-of-type tr.grp:first-child td{padding-top:6px}
.bp-hero .grp__i{width:13px;height:13px;fill:none;stroke:currentColor;stroke-width:1.1;
  stroke-linecap:round;stroke-linejoin:round;vertical-align:-2.5px;
  margin-right:9px;opacity:.9}
.bp-hero .ann__tbl tr.grp td:last-child{letter-spacing:.04em;font-size:11px;
  color:var(--mut);opacity:1}
/* Подсветка строки под курсором: смета становится «живой» и позволяет
   вести пальцем по расчёту, не теряя строку. */
.bp-hero .ann__tbl tbody tr:not(.grp):hover td{background:rgb(var(--color-accent-rgb) / .055)}
.bp-hero .ann__tbl tbody tr:not(.grp):hover td:first-child{color:var(--fg)}
/* Границу под последней работой снимаем: черту рисует блок вывода, две
   линии подряд читались бы как ошибка вёрстки. */
.bp-hero .ann__tbl tbody tr:last-child td{border-bottom:0}
/* ⚠️ ВЫВОД ЛИПНЕТ К НИЗУ ПАНЕЛИ НА ЛЮБОМ УСТРОЙСТВЕ, НЕ ТОЛЬКО НА ТАЧЕ.
   На ноутбучном кадре 1280×720 смета рядом с числом не помещается, панель
   ужимается до трёхсот пикселей с прокруткой — и «306 000 против 30 000»
   уезжало под прокрутку ровно там, где кадр меньше всего. Замерено.
   Там, где панель влезает целиком, sticky ведёт себя как обычный блок и
   ничего не меняет; поля низа отданы ему, иначе он прилипнет к границе
   содержимого и под ним будет просвечивать таблица. */
.bp-hero .ann__panel{display:flex;flex-direction:column;padding-bottom:0}
/* 🔴 АТРИБУТ `hidden` БЫЛ ПОБЕЖДЁН СТРОКОЙ ВЫШЕ, И ЭТО ЛОМАЛО ДОСТУПНОСТЬ.
   `[hidden]` даёт `display:none` из СТИЛЕЙ БРАУЗЕРА, а любое авторское правило
   `display` его перебивает. Замерено на чистой загрузке, без единого касания:
   `panel.hidden` → true, при этом `getComputedStyle(...).display` → «flex»,
   `visibility` → «visible», `checkVisibility()` → true. Скрывала панель одна
   лишь `opacity:0` — то есть она была ПРОЗРАЧНОЙ, а не скрытой. Отсюда две
   беды сразу:
     • три крестика «✕» закрытых панелей стояли в порядке обхода — человек
       с клавиатуры трижды проваливался в невидимую кнопку;
     • диктор читал содержимое всех трёх панелей при загрузке, включая
       таблицу сметы в 16 строк, — то есть 306 000 ₽ звучали раньше, чем
       человек дошёл до цены.
   Лечение не костылём `!important`, а возвратом атрибуту его работы: пока
   `hidden` стоит, панели нет ни в раскладке, ни в дереве доступности.
   Порядок в скрипте это выдерживает: `open()` снимает `hidden` ДО замера
   `place()`, а `shut()` возвращает его через 260 мс, после затухания. */
.bp-hero .ann__panel[hidden]{display:none}
.bp-hero .ann__out{position:sticky;bottom:0;z-index:1;background:var(--color-bg);
  padding-bottom:clamp(12px,1.1vw,16px)}
/* ⚠️ СРЕЗ ПОД ЗАКРЕПЛЁННЫМ ИТОГОМ НУЖНО ГАСИТЬ ГРАДИЕНТОМ, А НЕ ТЕНЬЮ.
   Стояло box-shadow:0 -16px 20px -10px — на живой странице (ноутбук, кадр 727)
   строка «Обложка» обрывалась под итогом ровно пополам, и это читалось как
   вёрстка поехала, а не как «список продолжается». Тень такой длины гасит
   от силы четверть строки. Градиент на всю её высоту уводит текст в фон
   панели, и обрыв перестаёт быть событием. */
.bp-hero .ann__out::before{content:"";position:absolute;left:0;right:0;bottom:100%;
  height:clamp(20px,2vh,30px);pointer-events:none;
  background:linear-gradient(to top,var(--color-bg),transparent)}

/* ═══ ВЫВОД: ДВА СТОЛБИКА ВМЕСТО ПРОЦЕНТА ════════════════════════════════
   🔴 ПРОЦЕНТ БЫЛ ОШИБКОЙ. Стояло «это меньше 9% сметы» рядом с одной
   полоской: доля посчитана верно, но покупатель книги не переводит проценты
   в выгоду на лету — Юрий 20.08: «тоже не поймут ЦА, как сейчас им НЕ
   ПОНЯТНО». Одна полоска вдобавок не с чем сравнить: длина сама по себе
   ничего не значит.
   ⚠️ ПОЭТОМУ ПОЛОС ДВЕ, ОДНА ПОД ДРУГОЙ, И ВЫВОД — КРАТНОСТЬЮ. Верхняя во
   всю ширину и есть смета; нижняя — наша цена, и она видно короче. «В 10 раз
   дешевле» понимает кто угодно без арифметики. Проценты убраны совсем.
   ⚠️ ШИРИНА НИЖНЕЙ СЧИТАЕТСЯ ОТ РЕАЛЬНЫХ ЧИСЕЛ: 30 000 / 306 000 = 9.8%.
   Нарисуете «на глаз» — получите ту самую натяжку, ради опровержения
   которой вся смета и заводилась. */
.bp-hero .ann__out{margin-top:11px;padding-top:12px;
  border-top:1px solid rgb(var(--color-accent-rgb) / .26)}
.bp-hero .ann__cmp{display:grid;grid-template-columns:auto minmax(0,1fr) auto;
  align-items:center;column-gap:14px;row-gap:10px}
.bp-hero .ann__cmpL{font-family:var(--mono);font-size:9.5px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--sub);white-space:nowrap}
.bp-hero .ann__cmpL--us{color:var(--acc)}
.bp-hero .ann__cmpB{position:relative;height:10px;border-radius:5px;
  background:rgb(var(--color-paper-rgb) / .07);overflow:hidden}
.bp-hero .ann__cmpB i{position:absolute;top:0;bottom:0;left:0;border-radius:5px;width:0;
  background:linear-gradient(90deg,rgb(var(--color-paper-rgb) / .30),rgb(var(--color-paper-rgb) / .16));
  transition:width .9s cubic-bezier(.22,.61,.36,1) .18s}
/* ⚠️ НАША ПОЛОСА СВЕТИТСЯ, ЧУЖАЯ — НЕТ. Разный тон здесь несёт смысл, а не
   украшает: серая полоса — чужой счёт, тёплая — наш. Без этой разницы две
   полосы читаются как две части одной шкалы. */
.bp-hero .ann__cmpB i.us{background:linear-gradient(90deg,var(--acc),var(--acc2));
  box-shadow:0 0 16px rgb(var(--color-accent-rgb) / .5);transition-delay:.42s}
.bp-hero .ann__panel[data-on="1"] .ann__cmpB i{width:var(--fill)}
.bp-hero .ann__outV,
.bp-hero .ann__usV{font-family:var(--mono);font-feature-settings:var(--tnum);
  line-height:1;letter-spacing:-.02em;white-space:nowrap;text-align:right}
.bp-hero .ann__outV{color:var(--mut);font-weight:500;font-size:clamp(1rem,1.1vw,1.16rem)}
.bp-hero .ann__usV{color:var(--acc2);font-weight:600;font-size:clamp(1.24rem,1.4vw,1.5rem)}
.bp-hero .ann__cmpN{margin:clamp(9px,.9vw,12px) 0 0;text-align:center;
  font-size:clamp(12px,.85vw,13.5px);line-height:1.4;color:var(--mut)}
.bp-hero .ann__cmpN b{color:var(--acc2);font-weight:600}
/* ═══ ПАНЕЛЬ «КТО ДЕЛАЕТ КНИГУ» ══════════════════════════════════════════
   Та же коробка, что у сметы, — намеренно: две аннотации на одном экране
   обязаны выглядеть одним приёмом, иначе вторая читается как чужой блок.
   Уже сметы, потому что здесь список из четырёх строк, а не расчёт. */
.bp-hero .ann__panel--team{width:min(470px,92vw)}
.bp-hero .team{margin:0;padding:0;list-style:none;
  display:grid;gap:clamp(10px,1vw,14px)}
.bp-hero .team li{display:grid;grid-template-columns:auto minmax(0,1fr);
  column-gap:12px;align-items:start;
  font-size:clamp(12.5px,.85vw,13.5px);line-height:1.42;color:var(--mut)}
.bp-hero .team b{color:var(--fg);font-weight:600}
/* Знаки те же, что у групп сметы: волосяная линия, один графический язык. */
.bp-hero .team__i{width:14px;height:14px;margin-top:2px;fill:none;stroke:var(--acc);
  stroke-width:1.1;stroke-linecap:round;stroke-linejoin:round;opacity:.85}
/* ⚠️ БЛОК ПРО ИИ ОТДЕЛЁН РАМКОЙ, А НЕ ПРОСТО ОТСТУПОМ. Он отвечает на
   возражение, а не продолжает перечисление: слитый со списком, он читался
   бы пятым участником команды — ровно тем, чего человек и опасается. */
.bp-hero .team__ai{margin-top:clamp(12px,1.2vw,16px);
  padding:clamp(10px,1vw,14px) clamp(11px,1.1vw,15px);
  border:1px solid rgb(var(--color-accent-rgb) / .2);border-radius:3px;
  background:rgb(var(--color-accent-rgb) / .045)}
.bp-hero .team__aiT{margin:0 0 5px;font-family:var(--mono);font-size:9px;
  letter-spacing:.24em;text-transform:uppercase;color:var(--acc);opacity:.8}
.bp-hero .team__aiB{margin:0;font-size:clamp(12px,.82vw,13px);line-height:1.5;
  color:var(--mut)}
.bp-hero .team__aiB b{color:var(--fg);font-weight:600}
.bp-hero .ann__panel--team .ann__cmpN{margin-top:clamp(11px,1.1vw,15px);
  padding-top:clamp(9px,.9vw,12px);
  border-top:1px solid rgb(var(--color-paper-rgb) / .09)}
.bp-hero .ann__note{margin:clamp(9px,.85vw,12px) 0 0;font-size:10.5px;line-height:1.5;
  color:var(--sub);border-top:1px solid rgb(var(--color-paper-rgb) / .09);
  padding-top:clamp(8px,.8vw,10px)}
.bp-hero .ann__note b{color:var(--mut);font-weight:400}

/* На тач-устройствах панель — нижний лист во всю ширину: у числа в тексте
   попросту нет места, чтобы что-то рядом с ним раскрыть. */
@media (hover:none){
  /* ⚠️ ПАЛЬЦУ НУЖНА ЦЕЛЬ ВЫШЕ СТРОКИ. Число в тексте даёт 31 px по высоте —
     мало для тапа. padding у строчного элемента расширяет область попадания,
     НЕ трогая раскладку: высота строки считается по интерлиньяжу, а не по
     полям. Больше 4 px не ставить — перехватит тапы у соседней строки. */
  .bp-hero .ann{cursor:pointer;border-bottom-style:dashed;padding:4px 0}
  .bp-hero .ann__panel{left:0!important;right:0;bottom:0;top:auto!important;
    width:100%;max-height:82dvh;overflow-y:auto;border-radius:14px 14px 0 0;
    border-left:0;border-right:0;border-bottom:0;
    padding-bottom:calc(18px + env(safe-area-inset-bottom,0px));
    transform:translateY(14px);
    /* ⚠️ ЗАТЕМНЕНИЕ ФОНА ДЕЛАЕТ ТЕНЬ, А НЕ ОТДЕЛЬНАЯ ПОДЛОЖКА. Лист во всю
       ширину без затемнения читается приклеенным к странице, и неясно, что
       он поверх. Разгон тени на 100vmax гасит всё вокруг одним свойством —
       без лишнего элемента, который пришлось бы показывать и прятать в такт
       с панелью. Тап мимо ловит глобальный pointerdown, подложке не нужно
       быть кликабельной. */
    box-shadow:0 -18px 50px rgba(0,0,0,.55),0 0 0 100vmax rgb(var(--color-bg-deep-rgb) / .62);
    /* Докрутил лист до конца — страница за ним не должна поехать следом. */
    overscroll-behavior:contain;
    /* Поля низа отданы липкому выводу — иначе sticky прилипнет к границе
       содержимого, а не к краю листа, и под ним будет просвечивать смета. */
    padding-bottom:0}
  .bp-hero .ann__out{padding-bottom:calc(15px + env(safe-area-inset-bottom,0px))}
  .bp-hero .ann__x{display:block}
}

/* ⚠️ ПЛАНШЕТ — НЕ БОЛЬШОЙ ТЕЛЕФОН. Нижний лист заведён потому, что на
   телефоне рядом с числом физически нет места. На iPad место есть: лист во
   всю ширину растягивал смету на 1194 px, колонки расползались, и таблица
   переставала читаться как расчёт. Здесь панель — карточка той же ширины,
   что на десктопе, прижатая к низу и отцентрованная.
   ⚠️ ЦЕНТРИРУЕТ margin-inline:auto ПРИ ЗАДАННЫХ left/right. Базовое тач-
   правило ставит left:0 !important, перебить его без второго !important
   нельзя — а при распорке left/right и явной ширине автоматические поля
   делят остаток поровну. Тот же результат без войны важностей. */
@media (hover:none) and (min-width:700px){
  .bp-hero .ann__panel{width:min(640px,92vw);margin-inline:auto;
    bottom:max(22px,env(safe-area-inset-bottom,0px));
    max-height:min(78dvh,760px);border-radius:6px;
    border:1px solid rgb(var(--color-accent-rgb) / .19)}
  .bp-hero .ann__out{border-radius:0 0 6px 6px}
}

/* ⚠️ НА ТЕЛЕФОНЕ ТАБЛИЦА ПЕРЕСТАЁТ БЫТЬ ТАБЛИЦЕЙ. Четыре колонки с nowrap
   требуют ≈430 px; в лист шириной 390 они не влезают, и «Сумма» уезжала за
   правый край — обрезанной оказывалась ровно та колонка, ради которой смета
   и открыта. Горизонтальная прокрутка внутри листа не спасение: человек её
   не заметит и прочитает обрезанные числа как настоящие.
   Поэтому строка складывается в стопку: работа, под ней множитель
   «10 ч × 2 500» подстрочником, сумма — справа по центру блока. Расчёт
   остаётся проверяемым, а ширины хватает с запасом.
   Порог по ШИРИНЕ, а не по hover: планшету с тачем четыре колонки влезают,
   и ломать их там незачем. */
@media (max-width:520px){
  .bp-hero .ann__panel .ann__tbl{font-size:13px;line-height:1.32}
  .bp-hero .ann__panel .ann__tbl thead{display:none}
  .bp-hero .ann__panel .ann__tbl tbody tr{display:grid;
    grid-template-columns:max-content max-content 1fr max-content;
    column-gap:8px;row-gap:1px;padding:9px 0;
    border-bottom:1px solid rgb(var(--color-paper-rgb) / .055)}
  .bp-hero .ann__panel .ann__tbl tbody td{padding:0;border:0}
  .bp-hero .ann__panel .ann__tbl tbody td:first-child{grid-column:1/4;grid-row:1;
    white-space:normal;color:var(--body);padding-right:0}
  .bp-hero .ann__panel .ann__tbl tbody td:nth-child(2){grid-column:1;grid-row:2;
    text-align:left;font-size:.88em}
  .bp-hero .ann__panel .ann__tbl tbody td:nth-child(3){grid-column:2;grid-row:2;
    text-align:left;font-size:.88em;color:var(--sub)}
  .bp-hero .ann__panel .ann__tbl tbody td:nth-child(3)::before{content:'× '}
  .bp-hero .ann__panel .ann__tbl tbody td:nth-child(4){grid-column:4;grid-row:1/3;
    align-self:center;padding-left:10px;color:var(--fg)}
  /* Фиксированные работы: множителя нет, подстрочник не нужен. */
  .bp-hero .ann__panel .ann__tbl tbody tr.flat td:nth-child(2),
.bp-hero .ann__panel .ann__tbl tbody tr.flat td:nth-child(3){display:none}
  .bp-hero .ann__panel .ann__tbl tbody tr.flat td:nth-child(4){grid-row:1}
  /* Метка группы — не стопка, а строка «название … подытог». */
  .bp-hero .ann__panel .ann__tbl tbody tr.grp{display:flex;justify-content:space-between;
    align-items:baseline;gap:12px;padding:15px 0 5px;border-bottom:0}
  .bp-hero .ann__panel .ann__tbl tbody tr.grp td{padding:0}
  .bp-hero .ann__panel .ann__tbl tfoot tr{display:flex;justify-content:space-between;
    align-items:center;gap:12px;padding-top:13px}
  .bp-hero .ann__panel .ann__tbl tfoot td{padding:0;border:0}
  /* ⚠️ НА ТЕЛЕФОНЕ СРАВНЕНИЕ РАСКЛАДЫВАЕТСЯ В ДВЕ СТРОКИ НА ПОЛОСУ.
     В три колонки метка и сумма съедали 267 px из 358, полосе оставалось
     девяносто — и «в десять раз короче» переставало быть видно, потому что
     обе полосы упирались в один огрызок. Название и сумма встают строкой,
     полоса идёт под ними во всю ширину: сравнение длин снова работает. */
  .bp-hero .ann__panel .ann__cmp{grid-template-columns:1fr auto;column-gap:12px;row-gap:5px}
  .bp-hero .ann__panel .ann__cmpB{grid-column:1/3;height:11px;margin-bottom:5px}
}


/* ═══ КАРТОЧКА КНИГИ ══════════════════════════════════════════════════════
   Юрий 17.08 18:32: «ткнув на обложку будет открываться разбор кейса книги».
   Полный разбор — отдельная страница и отдельная работа (правка 18:35:
   «сначала герой, потом то, что открывается по клику»). Здесь стоит честный
   первый шаг: обложка крупно, название, запрос читателя и выход. Главное — в
   v20 обложки были <button>, которые НИЧЕГО не делали: наведение обещало
   действие, клик молчал, и десятки холостых кнопок стояли в tab-порядке.
   Нативный <dialog> взят ради ловушки фокуса и Esc без единой строки кода. */


.bp-hero .qv__in{position:relative;display:grid;
  grid-template-columns:minmax(0,.8fr) minmax(0,1fr);
  gap:clamp(20px,3vw,44px);align-items:center;
  background:var(--color-bg);border:1px solid rgb(var(--color-accent-rgb) / .18);border-radius:3px;
  padding:clamp(20px,3vw,40px)}
/* 🔴 ЗАТИРКА ИМЕНИ ОБЯЗАТЕЛЬНА И ЗДЕСЬ — В ЛЕНТЕ ОНА БЫЛА, В КАРТОЧКЕ НЕТ.
   Это была не косметика, а утечка. Нижняя строка обложек несёт настоящее имя
   читателя; в полотне её закрывает .bk__mask, а в открытой карточке обложка
   показывалась целиком — и прямо над примечанием «личные данные на обложке
   скрыты» читалось «Константин Снигирёв». То есть экран одновременно давал
   обещание и нарушал его в одном кадре, а заодно публиковал имя человека без
   его ведома.
   Плашка повторяет .bk__mask один в один: те же проценты, те же стопы. Если
   будете править одну — правьте обе, иначе они разъедутся и дыра вернётся.
   ⚠️ РЕШАЕТ ЗАДАЧУ ТОЛЬКО ДО ПЕРЕРЕНДЕРА PDF. Настоящее решение — обезличенные
   исходники обложек; плашка держит оборону, пока их нет. */
.bp-hero .qv__fig{margin:0;border-radius:2px;overflow:hidden;position:relative;
  box-shadow:0 30px 70px rgba(0,0,0,.7)}
.bp-hero .qv__fig::after{content:"";position:absolute;left:0;right:0;bottom:0;height:30%;
  pointer-events:none;
  background:linear-gradient(180deg,rgb(var(--color-bg-deep-rgb) / 0) 0%,rgb(var(--color-bg-deep-rgb) / .42) 12%,
    rgb(var(--color-bg-deep-rgb) / .86) 26%,rgb(var(--color-bg-deep-rgb) / .97) 38%,var(--color-bg-deep) 48%)}
.bp-hero .qv__fig img{display:block;width:100%;height:auto}
.bp-hero .qv__no{font-family:var(--mono);font-size:10.5px;letter-spacing:.24em;
  color:var(--sub);margin:0 0 12px;font-feature-settings:var(--tnum)}
.bp-hero .qv__t{margin:0 0 12px;font-family:var(--ital);font-style:italic;color:var(--fg);
  font-size:clamp(1.5rem,2.4vw,2.1rem);line-height:1.12;letter-spacing:-.01em}
.bp-hero .qv__q{margin:0 0 20px;color:var(--mut);line-height:1.55;
  font-size:clamp(.95rem,1.05vw,1.08rem)}
.bp-hero .qv__note{margin:0 0 22px;font-family:var(--mono);font-size:10.5px;
  letter-spacing:.06em;line-height:1.7;color:var(--sub)}
.bp-hero .qv__x{position:absolute;top:12px;right:12px;z-index:3;width:38px;height:38px;
  border:1px solid rgb(var(--color-fg-rgb) / .2);background:rgb(var(--color-bg-deep-rgb) / .6);border-radius:50%;
  color:var(--fg);font-size:17px;line-height:1;cursor:pointer;
  transition:border-color .3s,background .3s}
.bp-hero .qv__x:hover{border-color:var(--acc);background:rgb(var(--color-bg-deep-rgb) / .85)}

/* ═══════════════════════════════════════════════════════════════════════════
   🔴🔴 ТЕЛЕФОН · ГЛАВНОЕ ПРАВИЛО ЭТОГО БЛОКА
   КНОПКА ПОКУПКИ ОБЯЗАНА БЫТЬ ВЫШЕ СГИБА НА 390×734. Не «желательно» — обязана.
   Трафик идёт из соцсети, то есть с телефона; человек, готовый нажать на пятой
   секунде, должен иметь по чему нажать без скролла.
   Замер v22 до этой правки (независимый рецензент, вслепую): кнопка начиналась
   на y=855 при экране 844, а в реальном Safari с адресной строкой (390×734)
   первый экран обрывался на середине строки цены — не было видно ни кнопки, ни
   цены целиком, ни одного такта метода. На 360×640 экран заканчивался словами
   «Не узнаете себя — вернём всю».
   ⚠️ ПОРЯДОК ОБЯЗАН БЫТЬ ТАКИМ: лента → марка → заголовок → лид → запрос
   читателя → ЦЕНА → КНОПКА → «подробнее» → гарантия с печатью → метод.
   Гарантия ушла ПОД кнопку намеренно: она снимает страх у того, кто уже
   решается, а решается человек, увидев цену и кнопку. Метод — в самый низ: он
   нужен сомневающемуся, а сомневающийся скроллит.
   ⚠️ ПРИ ЛЮБОЙ ПРАВКЕ ЭТОГО БЛОКА ПЕРЕМЕРЬТЕ 390×734 И 360×640, а не только
   390×844: 844 — это высота устройства, а не вьюпорта, и она врёт в плюс на
   110 пикселей. Именно на этой разнице поломка и жила незамеченной.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width:1079px){
  /* Высота ленты — одна величина на три слоя (.web/.glow/.veil), иначе при
     правке разъезжаются подложка и градиент. Была min(40vh,320px): на 734
     это 294 px, то есть 40% первого экрана под витрину, которая уже сказала
     всё, что могла, за первые 150. Стало 26vh с потолком 240. */
  /* Обложка обязана влезать в ленту целиком: cw × 1000/707 ≤ ribbon − 12.
     При 14vh ширина на 734 = 103 × 1.18 = 121 px, высота 172 < 191. */
  /* ⚠️ 24vh, А НЕ 26: строка-цепочка под лидом стоит 30 px, и на 390×734 их
     не хватало — кнопка уходила за кромку на восемь пикселей (замерено).
     Забираем недостающее у ленты: она к этому моменту уже сказала всё, что
     могла, а кнопка не сказала ничего.
     ⚠️ ОБЛОЖКА ОБЯЗАНА ОСТАТЬСЯ ЦЕЛОЙ, И СЧИТАТЬ НАДО ВМЕСТЕ СО СДВИГОМ.
     Карточки в ряду намеренно расставлены по вертикали (--off, до 8.8% своей
     ширины), чтобы строй не был линейкой. При 14vh самая сдвинутая обложка
     выходила за ленту на шесть пикселей — замер показал две целых из трёх.
     13.2vh даёт высоту 185 плюс сдвиг 11 против 203 ленты: целые все. */
  /* 12.4vh, а не 13.2: на 390×734 самая сдвинутая карточка выходила за ленту
     (замер: три целых из четырёх). Высота обложки со сдвигом обязана быть
     меньше ленты — считайте вместе с --off, до 8.8% ширины. */
  /* ⚠️ ЛЕНТА НА ТЕЛЕФОНЕ УРЕЗАНА С 24% ЭКРАНА ДО 16%. Четверть первого
     кадра занимала полоса обрезанных обложек без единого слова — это
     отмечали все рецензенты подряд. Витрина нужна, но доказывать ею
     двадцать четыре процента экрана нечем: обложки там всё равно срезаны
     кромкой и читаются фрагментом. Освободившееся место уходит вниз, к
     методу, который до правки начинался на 824 px при кадре 734. */
  .bp-hero{--cwb:clamp(76px,12.4vh,108px);--ribbon:clamp(108px,15.5vh,158px)}
  
  .bp-hero .scene{display:flex;flex-direction:column;height:auto;min-height:100dvh;
    isolation:auto}
  /* transform на полосе снят намеренно: overflow:hidden режет СОДЕРЖИМОЕ, а
     потом обрезанное ещё раз масштабируется и поворачивается — полоса вылезала
     за свою коробку примерно на сорок пикселей. Наклон здесь не стоит поломки,
     вместо него берём кегль обложек. */
  /* 🔴 v22, ПОЧИНЕНО — САМАЯ ДОРОГАЯ ПОЛОМКА ФАЙЛА, И ОНА БЫЛА НЕВИДИМА В
     КОДЕ. padding-bottom:var(--web-pad) — десктопное устройство: оно
     поднимает стопку обложек над нижней полосой. Величину считает скрипт как
     innerHeight − canvasH, а canvasH = innerHeight − высота полосы − 60. На
     телефоне полоса лежит в потоке и её высота под тысячу пикселей, поэтому
     canvasH упирался в собственный пол (200), и --web-pad выходил 644 px.
     Дальше box-sizing:border-box: коробка не может быть ниже своих полей, и
     .web высотой 320 разворачивался в 644, из которых 644 — пустые. На экране
     это выглядело так: узкая полоска обложек сверху, под ней пустой чёрный
     экран в пол-айфона, и только потом колонтитул с заголовком.
     Замерено на 390×844: колонтитул начинался на 665 вместо 354.
     ⚠️ ПОЭТОМУ ЗДЕСЬ ЯВНЫЙ padding-bottom:0 — на телефоне полотну не над чем
     подниматься, полоса не лежит поверх него. Правило обязано стоять ПОСЛЕ
     базового .web (оно и стоит: медиазапрос ниже по файлу). */
  .bp-hero .web{position:relative;inset:auto;flex:none;height:var(--ribbon);
    padding-bottom:0;
    overflow:hidden;justify-content:center;transform:none}
  .bp-hero .glow{inset:0 0 auto 0;height:var(--ribbon)}
  /* Спуск к тексту начинается только с 58%: при трёх планах в полосу входит
     три ряда, и при раннем спуске целый ряд обложек уходил под плашку в
     половину плотности — на 390×844 он читался чёрными прямоугольниками. */
  .bp-hero .veil{inset:0 0 auto 0;height:var(--ribbon);
    background:linear-gradient(180deg,rgb(var(--color-bg-deep-rgb) / .66) 0%,rgb(var(--color-bg-deep-rgb) / .06) 15%,
      rgb(var(--color-bg-deep-rgb) / .06) 58%,rgb(var(--color-bg-deep-rgb) / .34) 78%,rgb(var(--color-bg-deep-rgb) / .84) 92%,var(--color-bg-deep) 100%)}
  /* ⚠️ absolute, А НЕ fixed. На стенде экран был один и зерно во весь вьюпорт
     ложилось ровно; на длинной странице /next fixed-слой накрыл бы все главы
     ниже, и светлые развороты получили бы чужую шершавость. */
  .bp-hero .grain{position:absolute}
  /* 🔴 v22: КАРТОЧКА НА ТЕЛЕФОНЕ ВКЛЮЧЕНА. В v21 стояло .cap{display:none} с
     объяснением «подпись под курсором на тач-экране смысла не имеет» — верным
     ровно наполовину. Курсора действительно нет, но запрос читателя перестал
     быть подписью к курсору: он листается сам. Пряча .cap, мы прятали от
     мобильного покупателя ЕДИНСТВЕННОЕ место, где сказано, что за каждой
     книгой стоит живой вопрос живого человека, — и телефон видел ленту
     красивых чужих обложек без объяснения, зачем она тут.
     Заодно уходит вторая беда: на тач-экране ничто не намекало, что обложку
     можно ткнуть. Теперь об этом написано в подсказке (см. .cap__hint —
     текст на мобильной ширине свой, см. ниже).
     Место в потоке она получает правильное по порядку в разметке: сразу под
     лентой обложек, перед полосой. */
  .bp-hero .cap{width:auto;text-align:left;justify-self:stretch;
    margin:clamp(9px,1.4vh,15px) 0 0}
  /* Подложка нужна только там, где карточка лежит НА обложках. На телефоне
     она стоит под лентой, на собственном фоне, и градиент был бы тёмным по
     тёмному — работы ноль, слой лишний. */
  .bp-hero .cap::before{display:none}
  /* Одной строкой в 38 знаков подсказка на 390 px не встаёт — переносим. */
  .bp-hero .cap__hint{white-space:normal}
  /* Текст подсказки на тач-устройствах подменяет скрипт — см. HINT_TOUCH.
     Здесь только перенос: на 390 px строка в одну не встаёт. */
  .bp-hero .card{justify-items:start}
  .bp-hero .card__rule{justify-self:start;max-width:120px}
  /* Сцена перестаёт быть тремя ярусами поверх кадра и становится обычным
     потоком под полосой обложек. */
  /* ⚠️ ВЕСЬ ВОЗДУХ НИЖЕ УРЕЗАН РАДИ ОДНОЙ ЦЕЛИ — ДОВЕСТИ КНОПКУ ДО СГИБА.
     Каждое из этих clamp'ов раньше было щедрее на 8–14 px; в сумме они и
     съедали те 120 px, которых не хватало на 390×734. Отступы на телефоне —
     не эстетика, а бюджет: их тратят там, где взгляд действительно
     переключает регистр (лента → текст, предложение → метод), и экономят
     между строками одного смыслового блока. */
  .bp-hero .stage{position:relative;inset:auto;display:block;
    padding:clamp(12px,1.8vh,20px) var(--pad) clamp(30px,5vh,52px)}
  .bp-hero .top{flex-direction:column;align-items:flex-start;gap:7px}
  /* Кружок на телефоне мельче и без подписи: ширины на два предмета в строке
     нет, а подпись рядом с маркой читалась бы вторым заголовком. Диаметр
     держим не ниже 58 px — порога, на котором лицо ещё лицо. */
  /* ⛔ ПОДПИСЬ У КРУЖКА БОЛЬШЕ НЕ ПРЯЧЕТСЯ. Я убрал её, потому что рядом с
     маркой не хватало ширины, — и получил на телефоне лицо незнакомого
     человека со значком воспроизведения без единого слова о том, что это и
     зачем. Самый человечный элемент экрана превращался в непонятный аватар
     ровно там, куда приходит вся реклама из соцсетей.
     Ширины в строку действительно нет, поэтому подпись встаёт ПОД кружок:
     столбиком у правого края, где под ним пусто до самого заголовка. */
  /* Отступ держит обёртка — иначе он сложится с её собственным и заголовок
     отъедет от колонтитула вдвое дальше положенного. */
  .bp-hero .lead{margin:clamp(10px,1.7vh,18px) 0 0;max-width:none}
  .bp-hero h1{margin:0;max-width:none;
    font-size:clamp(2.05rem,1.15rem + 4vw,3.1rem)}
  .bp-hero .lede{font-size:1.06rem;max-width:none;margin-top:9px}
  .bp-hero .chain{display:block}
  .bp-hero .deck{margin-top:clamp(11px,1.8vh,18px)}
  /* На узком экране страница прокручивается, и 100vw шире полосы прокрутки —
     появился бы горизонтальный скролл. Здесь полоса и так лежит в потоке,
     поэтому подложка не нужна вовсе: под ней просто фон страницы. */
  .bp-hero .deck::before{display:none}
  /* Три колонки по 42 знака превратились бы в три по 14. */
  /* ⛔ ВЕРТИКАЛЬНЫЕ ЛИНЕЙКИ НА ТЕЛЕФОНЕ ОТКЛЮЧЕНЫ. Колонки здесь идут
     стопкой, и линейка «между колонками» нарисовалась бы слева от второго и
     третьего блока — то есть посреди пустоты, без всякого смысла. Разделять
     их по вертикали не нужно вовсе: сверху вниз порядок и так очевиден. */
  .bp-hero .beats{grid-template-columns:1fr;gap:clamp(17px,2.6vh,24px)}
  .bp-hero .bt--pivot::before{display:none}
  .bp-hero .bt--pivot{border-left:2px solid var(--acc);padding-left:14px;margin-left:-16px}
  .bp-hero .bt__t{font-size:1rem}
  /* 🔴 v22, ПОЧИНЕНО: здесь стояло .act{flex-direction:column} — у элемента с
     display:grid. Грид это свойство игнорирует, поэтому на 390 px гарантия и
     кнопки так и стояли в двух колонках «1fr auto»: печать с текстом жалась в
     первую, кнопка во всю ширину — во вторую. Выглядело сломанным, и было.
     Лечится тем, чем и задавалось, — дорожками грида.
     И блок действия поднят НАД тактами (order). На телефоне полоса читается
     сверху вниз, и в v21 путь до кнопки шёл через три абзаца метода: человек,
     который уже согласен, должен был проскроллить объяснение, которое ему не
     нужно. Теперь порядок «предложение → цена → действие → и только потом
     почему это работает». Тем, кому нужно объяснение, оно на месте. */
  .bp-hero .deck{display:flex;flex-direction:column}
  .bp-hero .act{grid-template-columns:1fr;align-items:stretch;gap:10px;
    order:-1;margin-top:0;padding-top:0;border-top:none}
  /* Линейка над тактами уже есть у .beats — второй границы здесь не нужно,
     иначе две волосяные линии встают в трёх пикселях друг от друга. */
  .bp-hero .beats{margin-top:clamp(13px,2.1vh,22px)}

  /* ═══ ПЕРЕСБОРКА СТРОКИ ДЕЙСТВИЯ ПОД ТЕЛЕФОН ═══════════════════════════
     На десктопе порядок «гарантия слева, кнопка справа» правильный: глаз
     идёт слева направо и заканчивает на действии. На телефоне порядок
     становится вертикальным, и тот же DOM выдаёт «печать → гарантия → цена →
     подробнее → кнопка», то есть кнопка последняя. Ниже сгиба.
     ⚠️ ЛЕЧИТСЯ display:contents, А НЕ ПЕРЕСТАНОВКОЙ РАЗМЕТКИ. Разметка одна
     на все ширины; чтобы цена и кнопка встали рядом, обёртки .guar и .guar__b
     на телефоне РАСТВОРЯЮТСЯ — их дети становятся прямыми детьми грида .act
     и получают собственный order. Ни одного лишнего узла, ни одной копии.
     ⚠️ display:contents убирает коробку, но не стили детей: печать поэтому
     позиционируется отдельно (justify-self), а не потоком flex-родителя,
     которого больше нет. */
  /* Сетка вместо порядка: явные области читаются однозначно и не ломаются от
     добавления узла. Две колонки нужны только последнему ряду — печать и
     обещание стоят рядом, как на десктопе. */
  /* ⚠️ ПОРЯДОК: ПРЕДЛОЖЕНИЕ → ДЕЙСТВИЕ → СЛУЖЕБНОЕ.
     Цена переехала внутрь фразы гарантии, значит первой строкой блока идёт
     теперь она: «15 000 ₽ за книгу. Не узнаете себя — вернём всю сумму
     деньгами». Это и есть предложение целиком, и оно обязано стоять НАД
     кнопкой — человек сначала узнаёт условие, потом жмёт. Служебная строка
     (носитель и ссылка на документ) уходит под кнопку: она ничего не решает.
     ⛔ НЕ ВОЗВРАЩАЙТЕ СЛУЖЕБНУЮ СТРОКУ НАВЕРХ. В прошлой сборке наверху стояла
     она, а предложение с ценой оказывалось последним — и на 390×734, 375×667
     и 360×640 уезжало за сгиб целиком. Замерено. */
  /* ⚠️ ТУТ ТОЛЬКО ДРУГИЕ ОБЛАСТИ — СЕТКА ТА ЖЕ. Раскладка полосы задана
     областями в .act, поэтому телефон переставляет блоки одной таблицей
     areas и ничем больше: ни display, ни порядок в разметке не трогаются.
     Порядок здесь свой: кнопка идёт первой, под ней её подпись, ниже
     «Подробнее о методе» и гарантия — палец добирается до действия сразу,
     а пояснения читает по пути вниз. */
  .bp-hero .act{grid-template-columns:auto minmax(0,1fr);
    grid-template-areas:
      "seal  price"
      "btn   btn"
      "next  next"
      "more  more"
      "note  note";
    row-gap:10px}
  .bp-hero .act__fine{justify-self:stretch;text-align:center;line-height:1.65}
  .bp-hero .act__fine > a{display:inline-block;margin-top:5px}
  .bp-hero .act__next{justify-self:stretch;justify-content:center;
    width:auto;white-space:normal;gap:8px}
  .bp-hero .seal{align-self:center;width:clamp(46px,13vw,56px);margin-right:12px}
  .bp-hero .guar__t{align-self:center;font-size:1rem;max-width:none}
  .bp-hero .btn{width:100%;justify-content:center}
  /* Ссылка стала кнопкой с рамкой — подчёркивание ей больше не нужно,
     а по ширине она равняется на главную кнопку над собой. */
  .bp-hero .ghost{justify-content:center;width:100%;margin-left:0}
}
/* ═══ КОРОТКИЙ ТЕЛЕФОН (SE, старые Android, 360×640) ═════════════════════════
   Замер после основной мобильной пересборки: на 390×734 кнопка вошла целиком
   (660..707 при кромке 734), а на 360×640 её нижние 34 px всё ещё срезало.
   Разница набегает из трёх мест: лента (168), строка цены, которая на 360 px
   переносится в три строки вместо двух, и межстрочный воздух.
   ⚠️ КНОПКУ РЕЖЕТ ХУЖЕ, ЧЕМ ЕСЛИ БЫ ЕЁ НЕ БЫЛО ВИДНО ВОВСЕ: наполовину
   видимая кнопка читается как «страница сломалась», а не как «пролистни».
   Поэтому порог именно 680 px — с запасом над 640, чтобы поймать и панель
   браузера, и «безопасные зоны» вырезов. */
/* ═══ ПЛАНШЕТ И УЗКИЙ НОУТБУК (700–1079) ════════════════════════════════
   ⚠️ ЗДЕСЬ РАБОТАЕТ МОБИЛЬНАЯ ВЁРСТКА, А ШИРИНА — ДЕСКТОПНАЯ. На 1024 текст
   вставал строкой в 940 px: сорок с лишним слов до переноса, читать такое
   невозможно, глаз теряет начало следующей строки. Три колонки сюда тоже не
   влезают — при 340 px на колонку каждый такт разворачивается строк на
   десять и полоса перестаёт помещаться в кадр.
   Поэтому колонка одна, но с человеческой мерой: 46rem ≈ 70–75 знаков —
   верхняя граница читаемого. Пустое поле справа не «недоделка», а поле;
   оно и должно быть на планшете. */
@media (min-width:700px) and (max-width:1079px){
  .bp-hero .lead,
.bp-hero .cap,
.bp-hero .deck{max-width:46rem}
}
@media (max-width:1079px) and (max-height:680px){
  /* Лента на коротких экранах урезана вслед за общей: 22% от 640 — это
     141 px витрины против четырёх строк текста, которые в них не влезают. */
  .bp-hero{--cwb:clamp(66px,11vh,92px);--ribbon:clamp(96px,15vh,132px)}
  /* 8 вместо 10: на 360×640 кнопка заканчивалась в пяти пикселях от кромки —
     запас, который съест любой шрифт, приехавший чуть иначе. */
  .bp-hero .act{gap:8px}
  /* Вертикальные зазоры доужаты, чтобы край первого такта попадал в кадр:
     на самых коротких экранах человек должен видеть, что ниже есть текст,
     иначе первый экран читается как вся страница. */
  .bp-hero .lead{margin-top:clamp(7px,1.2vh,13px)}
  .bp-hero .deck{margin-top:clamp(8px,1.2vh,13px)}
  .bp-hero .beats{margin-top:clamp(9px,1.4vh,15px)}
  .bp-hero .cap{margin-top:clamp(6px,1vh,11px)}
  /* ⚠️ СЛУЖЕБНЫЕ СТРОКИ ВОЗВРАЩАЮТСЯ К ПРЕЖНЕМУ КЕГЛЮ ТОЛЬКО ЗДЕСЬ.
     Подсказку и строку «что дальше» подняли (9.5→11 и 10→11.5) по замечанию
     о нечитаемой служебной типографике — и это правильно везде, кроме самых
     коротких экранов: рост на две строки увёл кнопку под сгиб на 360×640
     (замерено: 606…653 при кромке 640). Здесь читаемость служебной строки
     уступает главному — видимой кнопке. */
  .bp-hero .cap__hint{font-size:10px;letter-spacing:.14em}
  .bp-hero .act__next{font-size:11px}
  /* ⚠️ ЦЕПОЧКА НА КОРОТКИХ ЭКРАНАХ СНЯТА. Она стоит 28 px вместе с отступом,
     а на 360×640 до кромки остаётся четыре. Между «человек видит путь» и
     «человек видит кнопку» на самом тесном экране выбор однозначен: путь
     он прочитает, пролистнув, кнопку — только если она есть. */
  .bp-hero .chain{display:none}
  .bp-hero .act__fine{line-height:1.45}
  .bp-hero .lede{margin-top:9px;font-size:1.02rem}
  .bp-hero .cap{margin-top:11px;gap:8px}
  .bp-hero .lead{margin-top:12px}
}
/* ═══ КОРОТКИЙ НОУТБУЧНЫЙ КАДР ═══════════════════════════════════════════
   🔴 1512×727 — САМЫЙ ХОДОВОЙ КАДР И САМЫЙ ТЕСНЫЙ. Высота видимой области у
   14" MacBook с открытой панелью браузера именно такая, и в неё обязаны
   уложиться четыре предмета: колонтитул, заголовок в две строки, воздух под
   ним и полоса в три колонки с гарантией и кнопкой. Замер v22 без этого блока:
   низ полосы 740 при кромке кадра 727 — кнопку срезало.
   ⚠️ ЛЕЧИМ ВОЗДУХОМ, А НЕ КЕГЛЕМ. Соблазн ужать шрифты велик и ошибочен:
   лид на 15 px перестаёт читаться репутационно («мелкий шрифт под обещанием»),
   а корпус полосы уже стоит на нижней границе меры. Отступы же на коротком
   кадре просто не нужны в том объёме, в каком они хороши на 1080. */
@media (min-width:1080px) and (max-height:820px){
  /* ⚠️ ПОСЛЕ ОТСТУПОВ УРЕЗАЕТСЯ ЗАГОЛОВОК, И ТОЛЬКО ОН. Замер после правки
     отступов: между лидом и волосяной линейкой полосы осталось 6 px — лид
     садился на полосу верхом. Взять недостающие 26 px больше неоткуда:
     корпус полосы стоит на нижней границе меры, шаг ролика трогать нельзя
     (см. РОЛИК: 1.78em — это выносные курсива, а не воздух).
     Заголовок теряет 73 → 65 px, то есть падает с 4.3 к корпусу до 3.8 —
     доминантой быть не перестаёт, а лид получает свои 32 px воздуха.
     ⚠️ ВЕРХНЯЯ ГРАНИЦА clamp ЗДЕСЬ НИ ПРИ ЧЁМ: на 1512 предпочтительное
     значение (4.3vw) и так ниже потолка 12.2vh, потолок не связывает. Резать
     надо СРЕДНИЙ член — что и сделано. */
  .bp-hero h1{font-size:clamp(2rem,.4rem + 3.9vw,min(6rem,12.2vh))}
  .bp-hero .lead{margin-top:clamp(12px,2.4vh,26px)}
  .bp-hero .lede{margin-top:clamp(10px,1.4vh,16px)}
  .bp-hero .beats{padding-top:clamp(9px,1.2vh,14px)}
  .bp-hero .act{margin-top:clamp(10px,1.4vh,16px);padding-top:clamp(9px,1.3vh,14px)}
  /* Печать задаёт высоту всей строки действия, поэтому на коротком кадре она
     уменьшается — но НЕ СИЛЬНО. Первый заход резал её до 74 px, и текст по
     кругу («ВОЗВРАТ ВСЕЙ СУММЫ · ЗАВЕРЕНО У НОТАРИУСА») слипался в кашу:
     печать переставала быть вещественным доказательством и становилась
     значком, то есть теряла ровно то, ради чего нарисована. 84 px — граница,
     на которой кольцевая надпись ещё читается; замер после правки отступов
     показал, что этот размер в кадр укладывается (низ полосы 717 при
     кромке 727). */
  .bp-hero .seal{width:clamp(70px,5.2vw,84px)}
}
@media (prefers-reduced-motion:reduce){
  .bp-hero .track,
.bp-hero .glow{animation:none}
  .bp-hero .web{opacity:1;animation:none}
  .bp-hero .top,
.bp-hero h1,
.bp-hero .deck{opacity:1;animation:none}
  .bp-hero .card__l > *,
.bp-hero .card__rule{transition:none}
  .bp-hero .roll__col,
.bp-hero .roll__rule{transition:none}
  /* Смета: панель появляется без выезда, полосы — сразу нужной длины.
     ⚠️ ШИРИНУ ЗДЕСЬ НАДО ЗАДАТЬ ЯВНО. Одного transition:none мало: старт у
     полос — width:0, и без этой строки человек с отключённой анимацией
     увидел бы две пустые дорожки вместо главного довода панели. */
  .bp-hero .ann__panel{transition:opacity .18s linear;transform:none}
  .bp-hero .ann__cmpB i{transition:none;width:var(--fill)}
}

/* ═══ ТРИ ПРАВИЛА, КОТОРЫХ НЕТ В СТЕНДЕ ═══════════════════════════════════
   Они существуют ровно потому, что герой встал в длинную страницу с общей
   шапкой. При следующем порте их надо перенести — в стенде их не будет.

   1. КОЛОНТИТУЛ ГЕРОЯ СНЯТ. На стенде «⊙ СУТЬ · THE ESSENCE» было
      единственным знаком бренда на экране. На /next ровно над ним стоит
      настоящая шапка витрины с тем же логотипом: два логотипа в шестидесяти
      пикселях друг от друга читаются как ошибка сборки. Разметка оставлена —
      стенд и порт должны совпадать узел в узел.
   2. ВЕРХНИЙ ОТСТУП СЦЕНЫ. Шапка витрины — position:fixed поверх страницы
      (z-index 1020), и первый ярус героя уезжал под неё. Отступ считается от
      --header-h, той же переменной, которой пользуются соседние главы;
      запасные 71px — её значение по умолчанию.
   3. ЯКОРЬ СЕКЦИИ. Переход по ссылке на первый акт должен оставлять шапке её
      высоту, иначе заголовок оказывается под ней. Как в ch10.css.
   ⚠️ БЛОК СТОИТ В КОНЦЕ ФАЙЛА, И ЭТО НЕ ВКУСОВЩИНА. Те же селекторы —
   .bp-hero .top, .bp-hero .stage, .bp-hero .vid — объявлены выше в порте
   стенда. Специфичность одинаковая, значит выигрывает последний: из начала
   файла эти четыре строки не делали ничего (проверено замером — колонтитул
   остался на месте).
   ═══════════════════════════════════════════════════════════════════════════ */
.bp-hero{scroll-margin-top:var(--header-h,71px)}
.bp-hero .top{display:none}
/* ⚠️ ОТСТУП ПОД ШАПКУ — ТОЛЬКО В ШИРОКОЙ РАСКЛАДКЕ. Там .stage лежит
   absolute поверх полотна, и первый ярус действительно уезжает под шапку.
   На телефоне полотно вынесено отдельной полосой сверху, шапка ложится на
   него — а сцена начинается ниже; тот же отступ добавлял ей полторы сотни
   пикселей пустоты между лентой и заголовком (замерено на 390×844). */
@media (min-width:1080px){
  .bp-hero .stage{padding-top:calc(var(--header-h,71px) + clamp(16px,2.4vh,30px))}
}



/* ═══════════════════════════════════════════════════════════════════════════
   НАШИ ДОБАВЛЕНИЯ К ПОРТУ — всё с префиксом pl-, чтобы при следующем порте
   было видно с одного взгляда, что тут не из источника.

   Их два, и оба существуют потому, что у нас ОДИН экран, а у источника —
   длинная страница: метка «сайт в разработке» (её на лендинге нет вовсе) и
   юридический колофон (на лендинге он в подвале, до которого тут не дойти).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ⚠️ ВОЗВРАЩАЕМ КОЛОНТИТУЛ. В источнике он скрыт (.top{display:none}) — там
   марка уже стоит в шапке сайта, и второй раз она была бы дублем. У нас шапки
   нет вовсе: заглушка — одна секция, и без этого правила страница осталась бы
   без имени бренда и без метки «сайт в разработке». По той же причине снят и
   отступ .stage под несуществующую шапку: он давал 87 px пустоты сверху. */
/* Страница — одна секция во весь экран, и своего reset у неё нет: Tailwind
   сюда не грузится (см. layouts/placeholder). Дефолтный margin:8px у body
   делал страницу выше вьюпорта ровно на 16 px — замерено, а не предположено. */
body{margin:0}

.bp-hero .top{display:flex;align-items:baseline;justify-content:space-between}
@media (min-width:1080px){
  .bp-hero .stage{padding-top:clamp(18px,2.8vh,34px)}
}

.bp-hero .pl-status{margin:0;display:inline-flex;align-items:center;gap:8px;
  font-family:var(--mono);font-size:clamp(9px,.62vw,11px);letter-spacing:.18em;
  text-transform:uppercase;color:var(--acc);white-space:nowrap}
.bp-hero .pl-dot{width:5px;height:5px;border-radius:999px;background:var(--acc);
  animation:pl-pulse 2.6s ease-in-out infinite}
@keyframes pl-pulse{0%,100%{opacity:.35}50%{opacity:1}}

/* ═══ ЮРИДИЧЕСКИЙ БЛОК — В ПРАВОЙ ТРЕТИ ПОЛОСЫ ГАРАНТИИ ═══════════════════
   Сетка .act пришла с лендинга под торговлю: "seal price more btn" /
   "seal note note next". Кнопки мы сняли, и три правых слота остались
   нулевой ширины — замерено «auto minmax(0,1fr) 0px 0px», то есть справа
   от строки гарантии пустовало 333 px. Колофон при этом шёл ОТДЕЛЬНОЙ
   строкой ниже: лишние 48 px высоты и второй горизонтальный шов сразу под
   первым — два тонких правила в 11 px друг от друга читаются как сбой
   вёрстки, а не как структура.
   Теперь колонок три, и правая — юридическая. Полоса стала на 48 px ниже,
   а эти 48 px забирает полотно: fitStack() ужимает стопку по месту, значит
   обложки видно больше. Выключка вправо ставит колофон под правый край
   третьей полосы содержания — footer наследует ритм колонок над собой. */
/* ═══ БАННЕР СООБЩЕНИЯ (flash) ════════════════════════════════════════════
   🔴 КЛАССА `.placeholder-flash` НЕ СУЩЕСТВОВАЛО НИ В ОДНОМ ЛИСТЕ СТИЛЕЙ.
   Замерено на живой странице: правил, упоминающих класс, — 0; вычисленные
   стили — прозрачный фон, нулевые отступы, `position:static`. То есть
   сообщение приезжало голой белой строкой поверх стены обложек: на светлой
   обложке его не прочитать. А это единственный способ, которым человек
   узнаёт, ПОЧЕМУ его увело сюда, — лэйаут заводил баннер ровно ради случая
   «увели с оплаты без единого слова».
   Второй урон был тише и хуже: строка в потоке сдвигала героя и ломала
   обещание «один экран» — переполнение 0 → 22 px, страница начинала
   прокручиваться. Поэтому баннер НАЛОЖЕН (fixed), а не втиснут в поток:
   сообщение видно, экран остаётся один.
   Собственная тёмная плашка, а не токен темы: страница прибита к тёмной, и
   баннер обязан читаться на любой обложке, какая окажется под ним. */
.bp-hero ~ .placeholder-flash,
.placeholder-flash{position:fixed;z-index:40;
  left:50%;transform:translateX(-50%);
  top:max(12px,env(safe-area-inset-top,0px));
  width:min(calc(100vw - 24px),640px);box-sizing:border-box;
  margin:0;padding:11px 16px;
  border-radius:3px;
  border:.5px solid rgb(232 184 152 / .34);
  background:rgb(15 13 8 / .96);
  color:#F4EFE7;
  font-family:"Manrope","Inter",system-ui,sans-serif;
  font-size:clamp(12.5px,.9vw,14px);line-height:1.45;text-align:center;
  text-wrap:pretty;
  box-shadow:0 10px 34px rgb(0 0 0 / .5)}
@media (prefers-reduced-motion:no-preference){
  .placeholder-flash{animation:pl-flash-in .5s cubic-bezier(.16,1,.3,1) both}
}
@keyframes pl-flash-in{from{opacity:0;transform:translate(-50%,-8px)}
  to{opacity:1;transform:translate(-50%,0)}}

/* Колофон по умолчанию (телефон) — строка в самом низу полосы, со своим швом.
   На десктопе шов снимается: там его несёт обёртка .band на всю ширину. */
.bp-hero .pl-colophon{margin-top:clamp(8px,1.4vh,16px);
  padding-top:clamp(7px,1.2vh,12px);
  border-top:.5px solid rgb(var(--color-paper-rgb) / .09)}

/* По умолчанию (телефон) обёртка РАСТВОРЕНА: .act и колофон становятся
   прямыми детьми .deck, и каждый слушается своего order. Это единственный
   способ сохранить порядок источника — цена выше объяснения (.act{order:-1}),
   а право в самом низу. Колофон, лежавший ВНУТРИ .act, уезжал наверх вместе
   с ней и вставал перед строкой сути (поймано на рендере 390×844). */
.bp-hero .band{display:contents}
/* ⚠️ НА ДЕСКТОПЕ ССЫЛКИ — СЕТКА 3×2, А НЕ ПЕРЕНОС ПО МЕСТУ (правило выше).
   Гибкий ряд с wrap раскладывал шесть ссылок разной длины как придётся:
   замерено 2+2+2 в три строки с рваным правым краем — под выключенным вправо
   текстом реквизитов это читалось неряшливо. Колоночный порядок кладёт первые
   три документа в левый столбец, вторые три — в правый, то есть в том порядке,
   в каком их читают, и оба столбца получают ровный правый край.
   На телефоне ширины на два столбца нет — там обычный текучий ряд. */
.bp-hero .pl-legal{display:flex;flex-wrap:wrap;gap:4px 20px}
.bp-hero .pl-legal a{font-family:var(--mono);
  font-size:clamp(8.5px,.58vw,10px);letter-spacing:.15em;text-transform:uppercase;
  white-space:nowrap;color:var(--sub);text-decoration:none;
  border-bottom:.5px solid rgb(var(--color-paper-rgb) / .16);padding-bottom:1px;
  transition:color .2s var(--e-std),border-color .2s var(--e-std)}
.bp-hero .pl-legal a:hover,
.bp-hero .pl-legal a:focus-visible{color:var(--fg);border-bottom-color:var(--acc)}
/* ⚠️ РЕКВИЗИТЫ РАЗБИТЫ НА ДВЕ СТРОКИ ЯВНО, А НЕ ПЕРЕНОСОМ. Свободный перенос
   в узкой колонке отрывал «The Essence» на третью строку одну — классический
   висячий хвост, и правый край блока получал ступеньку в две трети пустоты.
   Две осмысленные строки (кто мы · чем зарегистрированы / оговорки · копирайт)
   ложатся почти вровень и держат прямоугольник. */
.bp-hero .pl-imprint{margin:clamp(6px,1vh,10px) 0 0;font-family:var(--mono);
  font-size:clamp(8px,.55vw,9.5px);line-height:1.7;letter-spacing:.07em;
  color:var(--faint);text-wrap:pretty}
.bp-hero .pl-imprint span + span::before{content:" · "}

/* Правая треть — только там, где она есть. Ниже 1080 колонок не существует:
   полоса и так в одну, и весь этот блок был бы вредом. */
@media (min-width:1080px){
  .bp-hero .band{display:grid;grid-template-columns:minmax(0,1fr) auto;
    align-items:center;column-gap:clamp(24px,3vw,56px);
    /* Шов переехал с .act на обёртку: иначе линия шла бы только над левой
       частью и обрывалась там, где начинается право. */
    margin-top:clamp(14px,2.2vh,26px);padding-top:clamp(13px,2vh,22px);
    border-top:.5px solid rgb(var(--color-paper-rgb) / .09)}
  .bp-hero .act{margin-top:0;padding-top:0;border-top:none}
  .bp-hero .pl-colophon{justify-self:end;text-align:right;
    margin-top:0;padding-top:0;border-top:none}
  .bp-hero .pl-legal{display:grid;grid-auto-flow:column;
    grid-template-rows:repeat(3,auto);
    justify-items:end;justify-content:end;
    gap:clamp(3px,.5vh,5px) clamp(16px,1.8vw,28px)}
  /* Разделитель нужен только когда строки текут в одну (телефон).
     Разбитые явно, они получали ведущее « · » во второй строке. */
  .bp-hero .pl-imprint span{display:block}
  .bp-hero .pl-imprint span + span::before{content:none}
}

/* Телефон: колофон ужимается сильнее всего — он служебный, а место на
   первом экране принадлежит цене и гарантии. */
@media (max-width:1079px){
  .bp-hero .pl-legal{gap:3px 12px}
  .bp-hero .pl-status{font-size:8.5px;letter-spacing:.12em;gap:6px}
  .bp-hero .pl-colophon{margin-top:8px;padding-top:7px}
  .bp-hero .pl-legal{gap:3px 12px}
  .bp-hero .pl-legal a{font-size:8px;letter-spacing:.1em}
  .bp-hero .pl-imprint{margin-top:5px;font-size:7.5px;line-height:1.55;letter-spacing:.04em}
}

/* Плотная строка вместо трёх полос — только на телефоне (см. разметку). */
.bp-hero .pl-gist{display:none}
@media (max-width:1079px){
  .bp-hero .beats{display:none}
  .bp-hero .pl-gist{display:block;margin:clamp(10px,1.6vh,16px) 0 0;
    color:var(--body);font-weight:300;line-height:1.6;
    font-size:clamp(13px,3.5vw,15px)}
  .bp-hero .pl-gist u{text-decoration:none;color:var(--acc);font-weight:600;
    font-size:1.08em}
  /* Колонтитул на телефоне в одну строку: два коротких блока по краям
     помещаются, а столбиком они отнимали 20 px у полосы. */
  .bp-hero .top{flex-direction:row;align-items:center;gap:12px}
}

/* Последние 47 px до одного экрана (замер на 390×844). Режем воздух и
   служебные кегли, не трогая ни заголовок по смыслу, ни цену, ни гарантию. */
@media (max-width:1079px){
  .bp-hero .lead{margin-top:clamp(6px,1vh,12px)}
  .bp-hero h1{font-size:clamp(1.95rem,1rem + 4vw,2.9rem)}
  .bp-hero .lede{margin-top:7px;font-size:1rem}
  .bp-hero .chain{margin-top:8px}
  .bp-hero .cap{margin-top:clamp(8px,1.3vh,14px)}
  .bp-hero .cap__hint{margin-top:5px;font-size:8.5px}
  .bp-hero .card__rule{margin-top:7px}
  .bp-hero .pl-gist{margin-top:clamp(8px,1.2vh,12px);line-height:1.52}
  .bp-hero .pl-colophon{margin-top:7px;padding-top:6px}
  .bp-hero .pl-imprint{margin-top:4px}
}

/* Ещё 24 px: лента отдаёт их первой — к этому моменту она уже сказала всё,
   что могла, а цена и гарантия не сказали ничего (логика источника). */
@media (max-width:1079px){
  .bp-hero{--ribbon:clamp(96px,13vh,140px)}
  .bp-hero .stage{padding-bottom:clamp(12px,2vh,22px)}
}

/* ═══ КОРОТКИЙ ТЕЛЕФОН (375×667 и родня) ══════════════════════════════════
   Замер до правки: перелив 91 px. У источника здесь страница прокручивается,
   у нас — нет, поэтому режем дальше. Порядок жертв тот же, что и везде: сперва
   лента, потом воздух, потом служебные кегли. Цена, гарантия, все три сноски
   и юридический ряд остаются нетронутыми. */
@media (max-width:1079px) and (max-height:700px){
  .bp-hero{--ribbon:clamp(66px,9.6vh,100px)}
  .bp-hero .stage{padding-top:8px;padding-bottom:8px}
  .bp-hero h1{font-size:clamp(1.7rem,.9rem + 3.6vw,2.4rem)}
  .bp-hero .lead{margin-top:6px}
  .bp-hero .lede{margin-top:5px;font-size:.94rem}
  .bp-hero .chain{margin-top:6px}
  .bp-hero .cap{margin-top:8px}
  .bp-hero .card__q{font-size:.92rem}
  .bp-hero .cap__hint{display:none}      /* подсказка про обложки — не первой нужды */
  .bp-hero .card__rule{margin-top:5px}
  .bp-hero .pl-gist{margin-top:8px;font-size:12.5px;line-height:1.45}
  .bp-hero .act{margin-top:9px;padding-top:8px}
  .bp-hero .pl-colophon{margin-top:6px;padding-top:5px}
  .bp-hero .pl-legal{gap:2px 10px}
  .bp-hero .pl-legal a{font-size:7.5px}
  .bp-hero .pl-imprint{margin-top:3px;font-size:7px;line-height:1.5}
}

/* ═══ ОЧЕНЬ НИЗКИЙ И ОЧЕНЬ УЗКИЙ ЭКРАН ════════════════════════════════════
   Ярус ниже существующего `max-height:700px`: тот доводил до одного экрана
   375×667, но не справлялся с 360×640 и 320×568 — замерено переполнение
   **25 px** и **127 px** соответственно. Полотно к этому моменту уже сжато
   до предела (66 px, `fitStack()` больше не отдаёт), значит резать надо не
   его, а самое атмосферное. Уходит карточка запроса: она не несёт ни цены,
   ни гарантии, ни документа — ровно та часть, которой можно пожертвовать,
   чтобы человек увидел остальное без прокрутки. Тем же рассуждением
   источник снимает `.cap__hint` на 700 px. */
@media (max-width:1079px) and (max-height:660px){
  .bp-hero .stage{padding-top:6px;padding-bottom:6px}
  .bp-hero .cap{display:none}
  .bp-hero .lead{margin-top:4px}
  .bp-hero .lede{margin-top:4px}
  .bp-hero .pl-gist{margin-top:6px}
  .bp-hero .act{margin-top:7px;padding-top:7px}
  .bp-hero .pl-colophon{margin-top:4px;padding-top:4px}
  .bp-hero .pl-imprint{margin-top:2px}
}
/* Очень узкий экран (320 px и уже). Две строки набраны `white-space:nowrap`
   и на такой ширине вылезали за кадр: «САЙТ В РАЗРАБОТКЕ» и «НОТАРИАЛЬНАЯ
   ГАРАНТИЯ ВОЗВРАТА →». Замерено: оба правым краем за вьюпортом.
   Переносить их нельзя (у ссылки стрелка оставалась бы одна на строке —
   разбор над `.guar__more`), поэтому ужимается кегль и трекинг. */
@media (max-width:340px){
  .bp-hero .pl-status{font-size:7.5px;letter-spacing:.08em;gap:5px}
  .bp-hero .guar__more{font-size:9px;letter-spacing:.08em}
  .bp-hero .brand{font-size:8px;letter-spacing:.1em}
}

/* ═══ ПЕЧАТЬ ═══════════════════════════════════════════════════════════════
   🔴 БЕЗ ЭТОГО БЛОКА СТРАНИЦА ПЕЧАТАЛАСЬ ПОЧТИ ПУСТЫМ ЛИСТОМ. Ни один из
   четырёх листов, которые подключает заглушка, не имел ни одного правила
   `@media print`, а страница тёмная: браузер фоны при печати не рисует, но
   цвет текста берёт как есть. Посчитано на бумаге (белый лист):
     основной текст #F4EFE7 — 1,14:1 · акцент #E8B898 — 1,79:1
     приглушённый #B5AB9D — 2,26:1 · тусклый #948A80 — 3,38:1
   То есть человек, нажавший «Печать» или «Сохранить как PDF», получал белый
   лист с еле различимыми разводами. А печатают тут ровно то, что стоит
   печатать: цену, нотариальную гарантию и реквизиты ИП.

   Решение — не «сделать красиво на бумаге», а «донести суть»: снимаем всё
   движущееся и декоративное (стена обложек, свечение, ширма, зерно, подъём
   обложки, карточка запроса — они бессмысленны в статике и съедают тонер),
   возвращаем светлую палитру и печатаем то, ради чего лист и заводят. */
@media print{
  /* ⚠️ `.stage` ОБЯЗАН СТАТЬ СТАТИЧНЫМ, И ЭТО НЕ МЕЛОЧЬ. На экране он
     `position:absolute` внутри `.scene`, а `.scene` держит высоту вьюпортом.
     Убрав высоту, но оставив абсолютность, я получил ровно то, от чего лечил:
     `.scene` схлопнулась в 0, набор вывалился из потока, тёмный текст лёг на
     тёмный холст — ЧЁРНЫЙ ЛИСТ вместо белого. Поймано рендером пробы, а не
     чтением: замерено `scene h=0`, `stage position:absolute`, при этом
     `lead h=209`, `deck h=619`. Белый фон ставится и на лист (`html`,`body`),
     иначе холст остаётся тем, каким его назначил `color-scheme:dark`. */
  @page{margin:14mm 14mm 12mm}
  html,body{background:#fff}
  /* ⚠️ ПАЛИТРА ПЕРЕОПРЕДЕЛЯЕТСЯ ТОКЕНАМИ, А НЕ ПЕРЕЧНЕМ СЕЛЕКТОРОВ. Первая
     попытка красила `.guar__t b`, `.price`, `h1 em` поимённо — и пропустила
     всё остальное: на пробе «о вашем ребёнке», «целой книгой», «2500 лет»,
     «200 страниц А4», «30 000» остались бледно-персиковыми на белом. Порт
     красит через `--acc`, `--fg`, `--mut` и т.д.; значит и на бумаге менять
     надо их — тогда ни один акцент не проскочит мимо. */
  .bp-hero{
    --fg:#151310; --body:#242019; --mut:#4A443C; --sub:#5C554B;
    --faint:#6B6459; --acc:#8A5326; --acc2:#7A4A22; --acc-on:#fff;
    --brd:#C9C2B6; --line:rgba(21,19,16,.16);
    --color-fg-rgb:21 19 16; --color-paper-rgb:21 19 16;
    --color-accent-rgb:138 83 38; --color-accent-strong-rgb:122 74 34;
    --color-bg:#fff; --color-bg-deep:#fff; --color-bg-deep-rgb:255 255 255;
    background:#fff;color:#151310}
  .bp-hero .scene{height:auto;min-height:0;overflow:visible;background:#fff}
  .bp-hero .stage{position:static;display:block;padding:0;min-height:0;
    background:#fff;color:#151310}

  /* Декорация и движение с бумаги уходят целиком. */
  .bp-hero .web,.bp-hero .glow,.bp-hero .veil,.bp-hero .grain,
  .bp-hero .lift,.bp-hero .cap,.bp-hero .web__dim,
  .bp-hero .ann__panel,.bp-hero .pl-status{display:none}

  /* Тени экранного набора на бумаге превращаются в грязь. */
  .bp-hero *{text-shadow:none!important;box-shadow:none!important}

  /* Печать — это документ: заголовок сверху, дальше содержание, внизу
     гарантия и реквизиты. Порядок задаёт поток, сетку распускаем. */
  .bp-hero .top{display:flex;margin-bottom:14pt}
  .bp-hero .lead{margin-bottom:12pt}
  .bp-hero .deck{display:block;margin:0}
  .bp-hero .beats{display:block}
  .bp-hero .bt{margin:0 0 10pt;page-break-inside:avoid}
  .bp-hero .pl-gist{display:none}
  .bp-hero .band{display:block;border-top:.5pt solid #C9C2B6;padding-top:10pt;
    margin-top:14pt;page-break-inside:avoid}
  .bp-hero .act{display:flex;align-items:center;gap:12pt;
    border:none;margin:0;padding:0}
  .bp-hero .pl-colophon{text-align:left;margin:10pt 0 0;border:none;padding:0}
  /* Выключка влево принудительно: правая треть — экранная затея, а на листе
     блок идёт обычным текстом. Десктопный медиаблок (min-width:1080px) на
     бумаге шириной ~816 px и не сработал бы, но полагаться на это нельзя:
     лист бывает и альбомным. */
  .bp-hero .pl-legal{display:flex!important;flex-wrap:wrap;gap:4pt 14pt;
    justify-content:flex-start!important;text-align:left}
  /* ⚠️ РАЗМЕРЫ НА БУМАГЕ ЗАДАЮТСЯ ЗАНОВО. Экранные `clamp(8px,.55vw,9.5px)`
     на листе дают около 6 пунктов — ниже порога читаемости для печати. А
     печатают эту страницу ровно ради нижней части: реквизитов ИП и списка
     документов. Замерено на пробе: реквизиты 8 px, ссылки 8,5 px. */
  .bp-hero .pl-legal a{border-bottom:none;font-size:8pt;letter-spacing:.08em}
  /* Адрес документа рядом с его названием: на бумаге ссылка не кликается.
     Строчными — прописной URL в каптелях нечитаем. */
  .bp-hero .pl-legal a::after{content:" " attr(href);color:#6B6459;
    text-transform:lowercase;letter-spacing:0}
  .bp-hero .pl-imprint{font-size:8pt;line-height:1.5;letter-spacing:.02em}
  .bp-hero .guar__t{font-size:12pt}
  .bp-hero .act__fine{font-size:8.5pt}
  .bp-hero .brand{font-size:8pt}
  .bp-hero h1{font-size:26pt;line-height:1.1}
  .bp-hero .lede{font-size:11pt}
  .bp-hero .bt__t{font-size:10pt;line-height:1.45}

  /* Печать — единственное место, где обводка кольца обязана быть тёмной:
     иначе от гарантии остаётся пустой кружок. */
  /* Печать — единственное место, где обводка кольца обязана быть тёмной:
     иначе от гарантии остаётся пустой кружок. `!important` здесь честен —
     цвета печати обязаны победить экранные значения `stroke`/`fill`. */
  .bp-hero .seal{width:74pt;flex:none}
  .bp-hero .seal__ring{stroke:#7A4A22!important}
  .bp-hero .seal__arc,.bp-hero .seal__big,.bp-hero .seal__sub{fill:#7A4A22!important}

  /* ⚠️ ГАСЯ АНИМАЦИИ, ОБЯЗАТЕЛЬНО ВЕРНУТЬ `opacity`. Набор въезжает на экран
     анимацией `hero-riseIn`, у которой стартовая `opacity:0`. Сняв анимацию и
     не вернув непрозрачность, я получил БЕЛЫЙ ПУСТОЙ ЛИСТ: замерено на пробе —
     `.top`, `h1`, `.lede`, `.deck` все с `opacity:0` при `animation:none`,
     высота у них при этом честная (163, 29, 619 px). Ровно эту ловушку
     обходит и блок `prefers-reduced-motion` в источнике, где рядом с
     `animation:none` всегда стоит `opacity:1`. Декоративные слои не всплывут:
     они сняты `display:none` выше, а он сильнее любой непрозрачности. */
  .bp-hero *{animation:none!important;transition:none!important;opacity:1!important}
}
