/*
 * f7c_design :: бренд-пакет Forbion (клиентский бренд, НЕ визуальный язык системы).
 * Источник: share/guideline.pdf (брендбук Forbion, 25 стр., взят из share 2026-07-09).
 * Подключается ПОСЛЕ tokens/tokens.css. Переопределяет ТОЛЬКО значения
 * темизируемых токенов по docs/THEMING.md — базовые токены остаются нейтральными.
 * Производный артефакт: источник истины — brand.json (раздел tokens),
 * правки только синхронно с ним.
 *
 * Контрасты проверены (WCAG): primary #70B62C / on-primary #1D1D1B = 6.77;
 * hover #63A427 = 5.52; active #5B9624 = 4.69; link #3F7314 на белом = 5.72 (сведён к AA на всех фонах 15.08).
 * Фирменный зелёный НЕ проходит с белым текстом (2.5) — поэтому on-primary чёрный.
 */
:root {
  /* Акцентные цвета: фирменный зелёный PANTONE P 154-8 C */
  --ds-color-primary: #70b62c;
  --ds-color-primary-hover: #63a427;
  --ds-color-primary-active: #5b9624;
  --ds-color-on-primary: #1d1d1b;
  --ds-color-accent: #478016; /* тёмно-зелёный: бейджи/выделения на светлом */
  /* 🔴 ЦВЕТ ССЫЛКИ СВЕДЁН К AA НА ВСЕХ ФОНАХ (решение владельца 15.08 через integrator-c2).
   * Повод — находка ячейки S: 3.86 в подвале письма. Пересчитал на всех парах и подтвердил:
   *   было #478016: body 4.81 ✓ · panel 4.25 🔴 · footer 3.86 🔴
   *   стало #3F7314: body 5.72 ✓ · panel 5.05 ✓ · footer 4.59 ✓
   * ⚠ Мой промах, из-за которого это дожило до сегодня: пары «фон+текст» я задал для КАЖДОЙ
   * поверхности, а ссылку померил ОДИН раз — на body. У ссылки столько же фонов, сколько у текста.
   * ⚠ `--ds-color-accent` НЕ трогаю: это другой токен и другая роль (бейджи, кикер). Он остаётся
   * #478016, и с этой правки два зелёных в бренде РАЗОШЛИСЬ — названо вслух, не побочный эффект. */
  --ds-text-link: #3F7314;
  /* 🔴 ДВА ЗЕЛЁНЫХ БРЕНДА РАЗОШЛИСЬ НАМЕРЕННО (15.08, принято integrator-c2 как решение).
   * ссылка `--ds-text-link` #3F7314 — сведена к AA на всех светлых фонах (5.42 / 5.05 / 4.59);
   * акцент `--ds-color-accent` #478016 — ДРУГАЯ РОЛЬ: кикер, бейджи, выделения.
   * ⚠ НЕ СВОДИТЬ К ОДНОМУ. Совпадали они по истории, а не по смыслу; сведение вернёт ссылке
   * контраст 4.25 на raised и 3.86 на sunken — то есть отменит правку, не назвав её. */

  /* Поверхности: фирменный серый PANTONE P 126-9 C / чёрный PANTONE Black C.
   * 🔴 14.08: страница НЕ чисто белая, а зеленоватая #F7FAF3 — как в каноне (виза владельца,
   * строка A12 сверки живого с макетом). Это ЕДИНСТВЕННОЕ место правки: ядро не трогаем,
   * у izibuh и остальных страница остаётся белой — они за наше решение платить не должны.
   * ⚠ Контраст пересчитан на новом фоне, а не предположен: ни один токен НЕ упал ниже порога
   * из-за этой правки. Ближе всех к границе стала ссылка бренда #478016 — 4.81 → 4.56 при
   * пороге 4.5, то есть запас 0.06. Дальше темнить фон нельзя без правки ссылки. */
  --ds-surface-page: #f7faf3;
  /* 🔴 ПОВЕРХНОСТИ — ПО ЗАМЕРУ КАНОНА, А НЕ ПО ОДНОМУ ПРАВИЛУ (15.08, решение integrator-c2).
   * ⚠ И ПОПРАВКА К МОЕМУ ЖЕ ДОВОДУ: я написал «брендбучных серых в макете нет вовсе» — НЕВЕРНО.
   *   Замер по площади: #FFFFFF 23 узла (основная площадь) · #F7FAF3 страница ·
   *   #EDF6E3 6 узлов (выделение) · #ECF2F2 **5 узлов — полоса вкладок калькулятора и
   *   невыбранные ступени цены**. То есть #ECF2F2 в каноне ЕСТЬ, но роль у него другая:
   *   не поверхность секции, а поверхность НЕАКТИВНОГО КОНТРОЛА.
   * ⇒ секции сводим к белому НОВЫМ токеном `--ds-surface-section`, а `--ds-surface-raised`
   *   остаётся #ECF2F2 — теперь уже как канон-подтверждённая поверхность контролов. */
  --ds-surface-section: #ffffff;
  /* Поверхность выделения канона: 6+ носителей, чернила #1D1D1B, контраст 14.4 */
  --ds-surface-highlight: #edf6e3;
  /* Зазор внутренней сетки героя — канон: 44px (6 вхождений в макете). */
  --ds-hero-grid-gap: 44px;
  --ds-fw-price: 900;   /* канон: 26 узлов веса 900 — цена, крупные числа, словомарк */
  /* Волна-кайма белой секции: канон даёт высоту 32 и заливку ЦВЕТОМ СТРАНИЦЫ
   * (замер 15.08: 8 волн, по две у #calc, #srv, #inc, #form — все на белых секциях). */
  /* Значок карточки круглый — канон даёт 50 % у всех ролей (замер 15.08) */
  /* Плавающий чип первого экрана — замер канона: стекло 72 %, blur 12, рамка #E2E8E4, 12px/700 */
  --ds-chip-bg: rgba(255, 255, 255, 0.72);
  --ds-chip-blur: blur(12px);
  --ds-chip-border: #e2e8e4;
  --ds-chip-size: 12px;
  /* Пункт сравнения — канон: 16/600 (замер 15.08) */
  /* Калькулятор по канону (замер @1366): колонки 669/418 = 1.60; панель итога — БЕЛАЯ
   * карточка rgba(255,255,255,.72), а не сплошная градиентная плита. */
  --ds-calc-cols: 1.6fr 1fr;
  /* Ряд ступеней цены — канон: nowrap, пять равных долей по 121 из 630 (замер 15.08) */
  --ds-segment-wrap: nowrap;
  --ds-segment-item-flex: 1 1 0;
  --ds-calc-panel-bg: rgba(255, 255, 255, 0.72);
  --ds-calc-panel-ink: var(--ds-text-primary);
  /* Приглушённый текст панели — вторичный текст ТЕМЫ (канон `--sub`: #6B726C светлая,
     #B3B9AC тёмная), а не чернила на зелёном: у панели зелёной подложки нет. */
  --ds-calc-panel-ink-muted: var(--ds-text-secondary);
  --ds-compare-item-size: 16px;
  --ds-compare-item-weight: 600;
  --ds-card-icon-radius: 50%;
  /* 🔴 ЗНАЧОК КАРТОЧКИ У КАНОНА СТУПЕНЧАТЫЙ, А НЕ ОДНО ЧИСЛО (замер 16.08, восемь ширин
     `#srv .pcard .ic`): 43.5 · 43.6 · 43.8 · 43.6 | 57.9 · 57.6 · 58 · 57.8 — ступень ровно
     на 1100, там же меняются поля (8/12 → 10/14). У нас стояло фиксированное 58: на широком
     совпадало, на узком давало +15 к значку и +66 к плитке (значок стоял в потоке до v0.266.0).
     ⚠ Ставлю 44, а не 43.7: разброс 43.5…43.8 — это доли пикселя от округления, и совпадать
     с ними числом значило бы принять шум за величину. Различие ниже порога смысла объявляю
     решением, а не прячу.
     📌 И вот теперь канонный порог 1100 воспроизведён ТЕМ, ЧЕМ он на самом деле управляет:
     размером и полями значка. Обтекание безусловно (v0.266.0). */
  --ds-card-promo-icon-size: 44px;
  /* 🔴 СТУПЕНЬ: канон `.lad .lic` СТУПЕНЧАТ НА 1100 — 46/глиф 22 ниже, 104/глиф 48 РОВНО С 1100 (прицельно: @1099 46, @1100 103.5). Выше порога значок стоит
     на 103.5…104 — разброс 0.4 px это ПОДПИКСЕЛЬ доли 29.5 % от плитки, а не величина;
     беру 104, как на опорной 1366.
     🔴 И ГЛАВНОЕ, ЧТО ЭТО МЕНЯЕТ В МОЁМ ЖЕ ВЧЕРАШНЕМ ВЫВОДЕ: прежние 104 в ядре НЕ БЫЛИ
     ложной пометкой. Они были ПОЛОВИНОЙ ПРАВДЫ — верной выше 1100 и неверной ниже. Я объявил
     их «утверждением о каноне, которое никто не проверял», а проверять надо было не пометку,
     а ШИРИНУ. Моя правка заменила одну половину другой.
     ⚠ В `v0.282.0` я поставил 46 БЕЗУСЛОВНО, потому что мерил канон на 390 — и напечатал
     в проверке строку «канон: значок 46 глиф 22» РУКАМИ, смешав замер узкого с высотами
     широкого. То есть нарушил собственное правило, выведенное за час до того: **любое число,
     снятое на одной ширине, есть гипотеза о всех остальных**. Правило было записано, названо
     вслух и не применено к следующей же правке.
     📌 И порог здесь НЕ 901, как у пяти других величин, а 1100 — оба есть в перечне канона.
     «Раз у всех 901, то и тут 901» было бы той же ошибкой в другую сторону. */
  --ds-card-ladder-icon-size: 46px;
  --ds-card-ladder-glyph: 22px;
  --ds-card-icon-inline-margin: 0 0 8px 12px;
  /* Подвал: канон `.cols` — равные колонки, число следует из ширины (`auto-fit`, минимум 220),
   * зазор 28. Замер рендером: 1440 → 4×251 · 1040 → 4×226 · 1000 → 3×297 · 900 → 3×264. */
  --ds-footer-cols: repeat(auto-fit, minmax(220px, 1fr));
  --ds-footer-gap: 28px;
  /* Замер канона @390 (`.ftr` + `.ftr > .wrap`, слоями, offset-единицами):
     подвал 46/0/30 · wrap 0/26 · колонки gap 28 · строка копирайта mar-top 28 + pad-top 16, снизу 0.
     ⚠ У нас было 48/16/32 + нижняя строка 16/16 — то есть НАШИ поля БОЛЬШЕ канонных.
     Правка делает подвал НИЖЕ и разрыв высоты страницы ФОРМАЛЬНО ХУЖЕ (−145 → ~−177):
     недостача подвала — не поля, а СОСТАВ (у канона 20 ссылок в четырёх колонках, у нас 9).
     Смешивать эти два движения нельзя: высота страницы — сальдо, а не предмет.
     🔴 И ЧИСЛА ЛЕГЛИ НЕ ТУДА, КУДА ИХ КЛАЛ КАНОН. У канона строка копирайта ВНУТРИ `wrap`,
     у нас `__bottom` — СОСЕД `__inner`. Поэтому канонное «30 снизу подвала» на нашем дереве
     означает нижнее поле НИЖНЕЙ СТРОКИ, а не нижнее поле колонок; там, где у канона 30 стоит
     под копирайтом, у меня в первой редакции оно встало НАД ним. Между колонками и строкой
     у канона 28 (её `margin-top`). Переношу по МЕСТУ в дереве, не по совпадению числа. */
  --ds-footer-pad: 46px 26px 28px;
  --ds-footer-bottom-pad: 16px 26px 30px;

  /* Поверхность «плита» — канонный `--silk`: блик сверху слева поверх мягкого перехода.
   * Та же поверхность у карточек тарифов, промо-плиток и плит секции заявки. */
  --ds-surface-silk:
    radial-gradient(130% 90% at 18% 0%, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0) 55%),
    linear-gradient(165deg, #FFFFFF 0%, #FDFEFB 55%, #F3F7EE 100%);
  --ds-shadow-silk:
    inset 0 1.5px 0 rgba(255, 255, 255, 0.85), inset 0 -1.5px 0 rgba(29, 29, 27, 0.05),
    inset 0 22px 40px -26px rgba(255, 255, 255, 0.6), 0 6px 14px rgba(29, 29, 27, 0.07),
    0 34px 72px -26px rgba(29, 29, 27, 0.3);
  --ds-radius-plate: 20px;
  /* Поле комментария: канон держит 66px при двух строках, подсказка помещается внутри. */
  --ds-textarea-min-h: 66px;
  /* 🔴 16.08, СВЕРКА ПОМЕТОК: 13 БЫЛО ПРАВДОЙ О ДРУГОМ УЗЛЕ. Замер живого: `--ds-field-size`
     накрывает ровно три контрола, все в ФОРМЕ ЗАЯВКИ; в калькуляторе таких узлов нет вовсе.
     Канон формы (`input.fld`, обе стороны прогоном): кегль 14.5 · поля 13/15 · border-box ·
     высота 45 как следствие. Опции калькулятора (`.copt > span` = 13) сходятся ОТДЕЛЬНЫМ
     токеном `--ds-field-label-size` — он и остаётся 13. */
  --ds-field-size: 14.5px;
  --ds-field-pad: 13px 15px;
  --ds-field-lh: normal;   /* канон: строка опции `line-height: normal`, не 24px */

  /* ── ТАБЛИЦА ТАРИФОВ `#t`: числа канона для c-tpl (16.08, наряд integrator-c2) ──────────
   * 🔴 ДЕРЖАТЕЛЬ ЗДЕСЬ НЕ Я, И ЭТО ЗАМЕР, А НЕ ОТКАЗ. Живое: таблица — `table.ttab`, целиком
   * шаблонная, DS-компонента в ней нет; `.rmark` и поля ячеек авторятся в `tpl.css`, кегль
   * и интерлиньяж просто НАСЛЕДУЮТСЯ от базовой типографики. Писать правила на чужие классы
   * из ядра нельзя, поэтому моя часть — числа канона токенами.
   * Замер обеих сторон @1366 (мой прогон, не пересказ):
   *     канон  th 21 / lh normal / поля 11 · small 11 (высота 13) · rmark 9.5 (высота 11)
   *     наше   th 16 / lh 24px   / поля 12 · small НЕТ            · rmark 12  (высота 18)
   * ⚠ ДВЕ ЕДИНИЦЫ РАЗЪЕХАЛИСЬ В ПЕРЕДАННЫХ ЧИСЛАХ: «rmark 18 против 9.5» сравнивает НАШУ
   * ВЫСОТУ с КАНОННЫМ КЕГЛЕМ (кегли 12 против 9.5, высоты 18 против 11), а «small 13» —
   * это высота канонного узла, кегль у него 11. Правка по этим парам промахнулась бы. */
  --ds-ttab-price-size: 21px;
  --ds-ttab-price-lh: normal;
  --ds-ttab-unit-size: 11px;
  --ds-ttab-rmark-size: 9.5px;
  --ds-ttab-cell-pad: 11px;
  /* Подпись опции у канона того же кегля, что и значение — 13, не 14. */
  --ds-field-label-size: 13px;
  /* Сноска согласия в форме заявки — канон 12 (узел `.pd`), не 13: роль юридическая. */
  /* 🔴 ЗНАЧЕНИЯ БЛОКА СРАВНЕНИЯ ВЕРНУЛИСЬ 17.08 — УСЛОВИЕ ВОЗВРАТА НАСТУПИЛО.
     История: правка верна и выпущена в `v0.297.0`, снята откатом вперёд в `v0.299.0` (16.08)
     по единственной причине — `#honest` был тогда КОРОЧЕ канона (−171 @390), и верная правка
     увела бы ещё на −121, то есть читалась бы на живом как «стало хуже».
     🔴 УСЛОВИЕ ПЕРЕВЕРНУЛОСЬ: после панели доверия и карточек секция стала ДЛИННЕЕ канона
     (+196 @901, +122 @390). Возврат теперь двигает К канону, а не от него.
     ЗАМЕР ВОЗВРАТА (offsetHeight · reduce · канон 1c против живого ts · автор c-design · 17.08):
         @390  секция 1683 → 1562 при канонных 1561   (Δ +122 → +1)
         @901  секция 1042 →  972 при канонных  846   (Δ +196 → +126)
         @1366 секция  841 →  791 при канонных  722   (Δ +119 → +69)
     ⚠ Остаток внутри колонки сравнения (+137 @901) — ОТДЕЛЬНЫЙ предмет, разбирается дальше;
     эта запись закрывает только зазор и интерлиньяж.
     📌 И урок самой записи: ответ лежал в моём же файле с готовым условием возврата.
     Условие, записанное рядом с отменённой правкой, — единственное, что отличает
     «отложено» от «забыто». */
  --ds-compare-lh: normal;
  --ds-compare-gap: 18px;
  /* Числа канона той же секции (источник `:645` `.cc{padding:26px}`; рендер списка @901
     даёт промежуток 11 при наших 12). Мелочь по величине, но это канон, а не округление. */
  --ds-compare-col-pad: 26px;
  --ds-compare-list-gap: 11px;
  /* ── ПАНЕЛЬ ДОВЕРИЯ: числа канона `.trustblock` (c-design, 17.08, замер прогоном) ──────
   * 🔴 ЧИСЛО КОЛОНОК ВЗЯТО СВИПОМ, А НЕ ГЛАЗОМ. 380…1400 через 20: ступени 1→2→3→4 стоят
   * на контейнере 428→448, 648→668, 888→908. Три независимые ступени дают
   * min ∈ (208.5 … 210.7] — в это окно попадает ровно одно круглое число. Одна ширина дала
   * бы «минимум где-то от 190 до 250», то есть гипотезу, выданную за замер.
   * ⚠ Ступень по КОНТЕЙНЕРУ, не по окну: панель живёт внутри секции, и медиазапрос по окну
   * промахнулся бы всюду, где контейнер уже своего порога.
   * ⚠ Маркер пункта — ТА ЖЕ формула, что у подложки значка карточки (замер обоих узлов:
   * `circle at 32% 26%`, 58 %, 100 % с теми же поверхностями). Поэтому здесь ССЫЛКА на
   * готовый токен, а не копия: копия разъехалась бы при первой правке одной из сторон. */
  /* ── «ПЛИТА» — ОБЩАЯ ПОВЕРХНОСТЬ КАНОНА (c-design, 17.08) ─────────────────────────────
   * 🔴 ЭТО НЕ ОБОБЩЕНИЕ «ПО ВКУСУ», А ТОЖДЕСТВО, ДОКАЗАННОЕ ЗАМЕРОМ. Панель доверия и
   * карточка преимущества слайда 3 (`.wcard` у канона) дают ПОБАЙТНО одинаковые
   * `background-image` и `box-shadow` — сверено сравнением computed-строк на одной странице,
   * а не глазами: `панельФон: true · панельТень: true`. Различается только радиус (22 против 26).
   * ⇒ значение объявляется ОДИН раз и читается обоими. Копия разъехалась бы при первой правке
   * одной из сторон, и разъехалась бы МОЛЧА — обе стороны остались бы «как записано». */
  --ds-surface-plate:
    radial-gradient(130% 90% at 18% 0%, rgba(255, 255, 255, .95), rgba(255, 255, 255, 0) 55%),
    linear-gradient(165deg, #FFFFFF 0%, #FDFEFB 55%, #F3F7EE 100%);
  --ds-shadow-plate:
    inset 0 1.5px 0 rgba(255, 255, 255, .85),
    inset 0 -1.5px 0 rgba(29, 29, 27, .05),
    inset 0 22px 40px -26px rgba(255, 255, 255, .6),
    0 6px 14px rgba(29, 29, 27, .07),
    0 34px 72px -26px rgba(29, 29, 27, .3);

  /* ── ОКНО (вход · регистрация). Плита, а не «карточка с тенью»: окно перехватывает внимание
   * целиком, и та же поверхность, что у панели доверия, держит его в одной идиоме с сайтом —
   * человек не должен чувствовать, что попал в чужой интерфейс на самом ответственном шаге.
   * ⚠ Завеса ТЕМНЕЕ обычной (.52 против ходовых .42): за окном лежит светлая страница с
   * зелёными акцентами, и на .42 она продолжает спорить с формой за взгляд — проверено глазом,
   * не выведено из числа. */
  /* Крупная кнопка — числа канона. Замер по секциям: у канона `topSlider` и `srv` несут
     ОДНО значение (14px · 12/22), поэтому одного брендового хватает на оба наших места.
     Было 18px · 16/32 — из-за чего кнопка героя при 390 переносилась в ДВЕ строки (70px
     против канонных 40). ⚠ Калькулятор сюда не входит: его кнопка уже переопределена
     в 13px/11-20 и совпадает с канонной. */
  --ds-btn-lg-font: 14px;
  --ds-btn-lg-pad: 12px 22px;

  --ds-dialog-bg: var(--ds-surface-plate);
  --ds-dialog-shadow: var(--ds-shadow-plate);
  --ds-dialog-veil-bg: rgba(29, 29, 27, .52);
  --ds-dialog-max: 420px;
  --ds-dialog-pad: 26px 26px 24px;

  --ds-trust-radius: 22px;
  --ds-trust-pad: 18px 20px;
  --ds-trust-mar-top: 20px;
  --ds-trust-bg: var(--ds-surface-plate);
  /* Пять слоёв, три из них внутренние: блик сверху, тень снизу, мягкая подсветка внутрь,
     ближняя тень и дальняя. Плоская подложка здесь читалась бы как выключенная панель. */
  --ds-trust-shadow: var(--ds-shadow-plate);
  --ds-trust-title-size: 13px;
  --ds-trust-title-weight: 800;
  /* 🔴 РАЗРЯДКА ОТНОСИТЕЛЬНАЯ, А НЕ ПИКСЕЛЬНАЯ. Я снял её рендером как `.52px` — верное
     ЗНАЧЕНИЕ при кегле 13, но у канона в источнике стоит `.04em`, и это разные вещи:
     пиксель не поедет за кеглем, `em` поедет. Рендер дал число, источник — правило. */
  --ds-trust-title-tracking: .04em;
  --ds-trust-title-transform: uppercase;
  --ds-trust-title-lh: normal;   /* канон 15 при кегле 13 */
  --ds-trust-title-gap: 12px;
  --ds-trust-cols: repeat(auto-fit, minmax(210px, 1fr));
  --ds-trust-gap: 12px 18px;
  --ds-trust-item-gap: 2px;
  --ds-trust-marker-room: 22px;
  --ds-trust-marker-size: 12px;
  --ds-trust-marker-top: 5px;
  --ds-trust-marker-bg: var(--ds-card-icon-bg);

  /* Мелкая юр-строка и список с маркером — числа канона (`#calc .offer-note`, `#calc .srvinc`). */
  /* отступы канонной юр-строки: замер `.offer-note.rev` — 14 сверху, 9.5 снизу.
     Без них правка кегля перелетает через ноль: мы становимся на 7.5 КОРОЧЕ канона. */
  --ds-legal-note-mar: 14px 0 9.5px;
  --ds-legal-note-size: 9.5px;
  --ds-legal-note-lh: 1.45;
  --ds-legal-note-max: 480px;
  --ds-marked-list-gap: 8px;
  --ds-marked-list-room: 22px;
  --ds-marked-list-mark: 13px;
  --ds-marked-list-mark-top: 5px;
  --ds-marked-list-mark-bg: var(--ds-card-icon-bg);
  --ds-marked-list-mark-inner: inset 0 1px 0 rgba(255, 255, 255, .5);
  --ds-trust-marker-inner: inset 0 1px 0 rgba(255, 255, 255, .5);
  --ds-trust-name-size: 14.5px;
  --ds-trust-name-weight: 800;
  --ds-trust-name-lh: 1.35;
  --ds-trust-source-size: 12px;
  --ds-trust-source-lh: 1.45;
  --ds-trust-note-size: 11.5px;
  --ds-trust-note-lh: 1.5;
  --ds-trust-note-gap: 14px;

  /* ── ЛИД СЕКЦИИ: числа канона (замер ВСЕХ восьми узлов `.ksub`, 16.08) ────────────────
   * Пары «узел канона ⇄ наша секция» названы явно, потому что имена сторон не совпадают:
   *     #t → #t 15.5 · #srv → #srv 15.5 · #hub → #navi 15.5 · #form → #form 15.5
   *     #calc → #calc 14.5 · cmp-sec → #honest 16 · #topSlider ×2 → герой 13 @390 / 14 @1366
   * ⇒ общее у канона нашлось НЕ В ЗНАЧЕНИИ, А В ОТНОШЕНИИ: интерлиньяж 1.6 у всех восьми.
   * Базовый кегль 15.5 покрывает ЧЕТЫРЕ пары из шести; две исключения (#calc 14.5,
   * #honest 16) требуют ролевого класса от `c-tpl` — у этих секций его сегодня нет,
   * есть только модификатор полей. Механизм тот же, что у `--ds-calc-title-gap`.
   * ⚠ ЧИТАТЕЛЬ — ПРАВИЛО `c-tpl` (`tpl.css {.tpl-section-lead}`), сейчас оно берёт мою шкалу
   * (`--ds-fs-lg` 18 / `--ds-lh-loose` 1.7). До того как он переключится на эти токены,
   * рендер не двигается — намеренно. */
  --ds-section-lead-size: 15.5px;
  /* Две роли, где канон отступает от базовых 15.5 (замер всех восьми `.ksub`):
     секция сравнения 16 · калькулятор 14.5. Признак включения роли у `c-tpl` —
     ЛЮБОЙ её токен, поэтому классы появятся от самого объявления. */
  --ds-honest-lead-size: 16px;
  --ds-calc-lead-size: 14.5px;
  --ds-section-lead-lh: 1.6;
  --ds-consent-size: 12px;

  /* 🔴 CTA КАЛЬКУЛЯТОРА — БРЕНДОВЫЙ СЛОЙ, ПОТОМУ ЧТО ПРАВИЛО У ПОТРЕБИТЕЛЯ ОДНО НА ДВА БРЕНДА.
     Канон: зелёная пилюля во всю ширину блока. Сейчас `c-tpl` красит её
     `background: var(--ds-color-on-primary)` — токеном ЧЕРНИЛ; у forbion это #1D1D1B (тёмная),
     у izibuh — белая, и белая там ПРИНЯТЫЙ вид. Поэтому не «поставьте `.ds-btn--gradient`»
     (я так и ответил сначала и был неполон: модификатор брендопараметричен, а КЛАСС ставится
     одним правилом на оба бренда — сменив класс, мы сменили бы вид izibuh), а токен с фолбэком
     на прежнее: izibuh не объявляет и остаётся при своём по построению.
     ⚠ Чернила обязаны ехать вместе с заливкой: сейчас надпись зелёная на тёмном; на зелёном
     градиенте она станет зелёным по зелёному. `on-primary` — ровно тот цвет, под который
     в ядре записано требование «все стопы `--ds-gradient-brand` дают с ним ≥4.5». */
  --ds-calc-cta-bg: var(--ds-gradient-brand);
  --ds-calc-cta-ink: var(--ds-color-on-primary);

  /* Ритм секции «что входит» — канон `#inc` (замер 15.08, 1366): заголовок→сетка 18,
     сетка→полоса 34. Сумма почти наша (52 против 56), а РАСПРЕДЕЛЕНИЕ обратное: канон
     прижимает сетку к заголовку и даёт воздух перед полосой. Ни 18, ни 34 не ступени
     шкалы (4·8·12·16·24·32) — потому и токены, а не литералы у потребителя.
     Имена держат секцию, потому что и числа держат секцию: это канон одной полосы,
     а не роль ядра. Потребитель — `c-tpl`, фолбэки на прежние 32/24. */
  --ds-inc-gap-before-grid: 18px;
  --ds-inc-gap-before-strip: 34px;

  /* Плитка «что входит»: канон `#inc .iti` — зазор значок↔текст 12, заголовок↔описание 3. */
  --ds-card-icon-gap: 12px;
  --ds-card-lead-row-gap: 3px;
  /* Опция-строка калькулятора — числа канона (`#calc .copts .copt`, 1366). */
  --ds-field-row-gap: 14px;
  --ds-field-row-pad: 9px 12px;
  --ds-field-row-radius: 16px;
  /* 🔴 БЫЛ ЛИТЕРАЛ #FFFFFF БЕЗ ТЁМНОЙ ПАРЫ — та же протечка, что у плиты сегодня утром.
     Замер тёмной темы: семь узлов `.ds-field--row` оставались БЕЛЫМИ на тёмной странице
     (у канона таких узлов ноль). Источник канона: `.copt{background:var(--card)}` — у него это
     ТОКЕН ТЕМЫ, #FFFFFF светлая / #27271F тёмная, а не константа.
     ⇒ читаем роль `--ds-surface-card`; литерал требует пары, композиция из ролей — нет. */
  --ds-field-row-bg: var(--ds-surface-card);
  /* Ритм шагов калькулятора канон несёт полями ЭЛЕМЕНТОВ (15 · 10 · 7 · 0), а не зазором
   * контейнера — поэтому контейнерный зазор обнуляется, иначе он прибавляется ко всем парам. */
  /* Канон `#calc .cl`: между табами и первым шагом 6 — единственная пара с зазором. */
  --ds-calc-gap-after-tabs: 6px;
  /* Канон `#calc .cr`: карточка → блок итога 10 (обе ширины). */
  --ds-calc-panel-gap: 10px;
  /* Канон `#calc .cr`: поля панели 16 (на 390 — 12, ниже в медиаблоке). */
  --ds-calc-panel-pad: 16px;
  /* Поля формы — канон `#calc .cl`: 14px 20px от **901** (ниже — 18px 20px, в медиаблоке).
     🔴 ПОРОГ В ТЕКСТЕ БЫЛ «1024» — БИСЕКЦИЯ 16.08 ДАЁТ 900/901 (@900 = 18px, @901 = 14px),
     и это тот же рубеж, что у полей секции и кикера. Значение и медиаблок были ВЕРНЫ всё
     это время; протухла ПОМЕТКА. 1024 в перечне медиазапросов канона отсутствует вовсе —
     это была ширина моего замера, принятая за границу (тот же промах, что с «768» у полей
     секции). ⚠ Пометка — такой же носитель, как значение, и протухает ОТДЕЛЬНО от него.
     🔴 НАЙДЕНО ВТОРЫМ ПРОХОДОМ по своим же числам на второй ширине: из четырнадцати предметов
     разошлись четыре, три из них я уже воспроизвёл ступенями, и остался ЭТОТ — единственный
     новый. Прежде я записал «поля формы 18/20 против наших 24 — отдельный предмет» и мерил
     их ТОЛЬКО на 390: там 18, а выше 901 канон даёт 14, то есть моё «отдельное число»
     само было половиной ступени. */
  --ds-calc-form-pad: 14px 20px;
  /* Блок итога, числа канона (замер обеих сторон @901, 16.08, по наряду integrator-c2):
     подпись h14 кегль 12 lh normal · сумма h37 кегль 32 lh normal, единица 13 ·
     строка расчёта li кегль 11 lh 16.5 · пилюли span 10.5 · кнопка 13 */
  /* Пара зазоров блока итога (канон: у дисклеймера отступа нет — его самого нет; кнопка
     несёт margin-top 18; блок держит поле снизу 6). Ставятся ВМЕСТЕ: 18 без снятых 16 дало бы 34. */
  /* 🔴 ПИЛЮЛИ ПАНЕЛИ: ДВА ЗНАЧЕНИЯ, И ПОРОЗНЬ КАЖДОЕ ДЕЛАЕТ ХУЖЕ (замер 16.08).
     Канон `#calc .csat span`: h=20 = `line-height: normal` (12 при кегле 10.5) + поля 4/4.
     У нас h=16 = `lh: 15.75` + поля 0/0, то есть мы НИЖЕ канона на 6.
     · один `lh: normal`  → 12 (хуже на 8)
     · одни поля 4/4      → 24 (перелёт на 4)
     ⇒ едут ТОЛЬКО ВМЕСТЕ.
     🔴 И ВЕРТИКАЛЬНОЕ ПОЛЕ Я ПОСТАВИТЬ НЕ МОГУ ВОВСЕ: `tpl.css` объявляет
     `.tpl-calc__pill { padding: 0 var(--ds-space-2) }` — ноль стоит ЯВНО, в шорткате, —
     а его файл грузится ПОСЛЕ бренда. При равной специфичности решает порядок, и моё
     правило проигрывает. Проверено прогоном: поля остались 0/0.
     ⇒ оба значения отданы ТОКЕНАМИ, читатель один и он у `c-tpl`. Рендер не двигается,
     пока читатель не появится, — и это здесь не осторожность, а единственная форма:
     половина правки видимо ухудшает. */
  /* Зазор ряда пилюль: канон 6, у нас 8 (замер `#calc .csat` обеих сторон @901).
     🔴 Найден АРИФМЕТИКОЙ, а не глазом: после приезда пары «поля + интерлиньяж» ряд стал 48
     против канонных 46, и пилюля тут ни при чём — обе стороны переносят пилюли в ДВА ряда,
     канон 2×20 + 6 = 46, мы 2×20 + 8 = 48. Пара сработала ровно (20 = 20), остаток — зазор. */
  --ds-calc-pill-gap: 6px;
  --ds-calc-pill-pad-y: 4px;
  --ds-calc-pill-lh: normal;
  --ds-calc-note-gap-after: 0;
  --ds-calc-sum-gap-before-cta: 18px;
  --ds-calc-sum-pad-bottom: 6px;
  --ds-calc-caption-lh: normal;
  --ds-calc-total-size: 32px;
  --ds-calc-total-unit-size: 13px;
  --ds-calc-line-size: 11px;
  --ds-calc-line-lh: 1.5;
  --ds-calc-includes-lh: normal;   /* канон: `ul` карточки тарифа держит normal, не 24px */
  --ds-calc-includes-gap: 5px;   /* 4 (зазор) + 5 = канонные 9 */
  /* Ритм блока итога — замер канона `#calc .cr > div:last-child`: 0 · 10 · 8 · 18.
     ⚠ Четвёртый (пилюли→кнопка 18) НЕ объявляю: у нас между ними стоит наш дисклеймер,
     и «перед кнопкой» у сторон означает разные пары. Назову, когда пары сойдутся. */
  --ds-calc-sum-gap-after-caption: 0;
  --ds-calc-sum-gap-after-total: 10px;
  --ds-calc-sum-gap-after-line: 8px;
  --ds-calc-form-gap: 0;

  /* 🔴 РИТМ ШАГОВ — ЧЕТЫРЕ ТОКЕНА ПО ОТНОШЕНИЯМ, а не одно число и не литералы.
   * Замер канона (`#calc .cl`, block-поток; расстояния несут поля ЭЛЕМЕНТОВ, зазора у
   * контейнера нет вовсе — потому `--ds-calc-form-gap` и обнулён):
   *     подпись шага → контрол                15
   *     контрол      → подпись следующего     10
   *     подпись шага → сетка опций             7
   *     сетка опций  → строка «Оплата за год»   0
   * ⚠ Ни одно из четырёх НЕ ступень шкалы (4·8·12·16·24·32) — значит литералы в чужом файле
   * стали бы четырьмя величинами без автора, ровно тем, что мы весь день чинили.
   * ⚠ И одним числом ритм не выражается по построению: значения РАЗНЫЕ и убывают.
   * Именованы ОТНОШЕНИЯМИ, а не порядковыми номерами: номер сместится при вставке шага,
   * отношение — нет. Потребитель — шаблон. */
  --ds-calc-gap-after-step-label: 15px;
  --ds-calc-gap-after-control: 10px;
  --ds-calc-gap-before-options: 7px;
  --ds-calc-gap-after-options: 0;

  /* Контролы опции калькулятора — числа канона (замер `#calc .copts`, 1366):
   * степпер целиком 32 (кнопка 26 + поля 2×3) · переключатель 26.
   * ⚠ И структурная деталь, которая объясняет остаток лучше любого кегля: у канона опция —
   * СТРОКА (`display:flex`, подпись слева, контрол справа, поля 9/12), у нас колонка.
   * Поэтому мы выше даже при НУЛЕВЫХ полях: сжимать надо контрол и раскладку, а не отступ. */
  /* 🔴 ПОПРАВКА К СЕБЕ (15.08, вечер): здесь стояли 26 и 3 — они были ВЫВЕДЕНЫ из высоты
   * контейнера (32 = 26 + 2×3), а не измерены. Прямой замер узлов канона:
   *     кнопка 32×32 · контейнер `.stp` БЕЗ полей · `<output>` 16 высотой, 36 шириной
   * То есть высоту держит кнопка, а полей нет вовсе. `c-tpl` применил мои числа точно
   * (кнопка ровно 26, поля ровно 3) — и получил 42, потому что третий узел, поле ввода,
   * в моём разложении не фигурировал вовсе.
   * ⚠ Класс мой же и сегодня повторённый: **величина, выведенная из суммы, не есть замер
   * слагаемого** — у суммы 32 было минимум два разложения, и я взял неверное, не проверив. */
  --ds-stepper-btn: 32px;
  --ds-stepper-btn-font: 17px;   /* канон `#calc .stp button`: 17px/17px */
  --ds-stepper-pad: 0;
  /* Поле ввода не должно быть выше кнопки: у канона это `<output>` 16 без полей. */
  --ds-stepper-input-pad-y: 0;

  /* 🔴 ЗАЗОРЫ СЕТКИ ОПЦИЙ КАЛЬКУЛЯТОРА — ТОКЕНЫ НАЗНАЧЕНИЯ, оба (запрос `c-tpl`, 15.08).
   * Ось вывел он сам из моей же таблицы высот, и вывод проверяем с любой стороны:
   *     опции 63 · 63 · 77 · 77 · 92 · 92 → две колонки, ТРИ ряда: 63 + 77 + 92 = 232
   *     колонка 244 · 244 − 232 = 12 = ДВА междурядья по 6  ⇒ row 6, column 12
   * ⚠ 12 СОВПАДАЕТ со ступенью шкалы (`--ds-space-3`), и всё равно объявлен назначением:
   * иначе следующая правка шкалы тихо поедет в калькулятор. **Совпадение значений не есть
   * совпадение ролей** — тот же довод, по которому `c-tpl` отказался писать 6 как
   * `calc(--ds-space-3 / 2)`: это утверждало бы, что канонная шестёрка есть «половина
   * двенадцати», а такого замера нет ни у него, ни у меня.
   * Потребитель — шаблон; внутреннего читателя в ядре нет, объявлены контрактом. */
  --ds-calc-option-row-gap: 6px;
  --ds-calc-option-col-gap: 12px;
}

/* ── ПОЛЯ, ЗАЗОР И ИНТЕРЛИНЬЯЖ КАРТОЧКИ ПО РОЛЯМ (c-design, 15.08) ──────────────
 * Замер канона на 1366: промо-плитка (`#srv`, `#inc`) поля 15/16 · зазор 8 · подпись 12/17.4;
 * карточка хаба поля 20/22 · зазор 7. У нас на всех ролях было 24 · 12 · 12/18.
 * 🔴 ЭТО ОТМЕНЯЕТ ГИПОТЕЗУ, КОТОРАЯ УЖЕ УШЛА ПО ЦЕПОЧКЕ: `c-tpl` разложил высоту опытами
 * и вывел «у канона МЕНЬШЕ кегль подписи», интегратор передал это `c-copy` как предмет.
 * Замер: **кегль ОДИН И ТОТ ЖЕ, 12px у обоих**; подпись канона — 72 знака в ТРИ строки
 * (52 = 3 × 17.4), а не 82 в две, как считала гипотеза. Настоящий остаток — поля и интерлиньяж:
 *     поля   30 против 48 = 18 px
 *     строки 52 против 54 =  2 px
 *     итого 20 — ровно то, что осталось у `c-tpl` после снятия значка (144 − 124).
 * Значок свои 18 отдаёт модификатором `--icon-inline`, он уже есть. */
.ds-card--promo { --ds-card-pad: 15px 16px; --ds-card-gap: 8px; --ds-card-text-lh: 1.45; }
/* 🔴 16.08, сверка пометок (куст `card.css`): пометка №11 говорит `pad 16px 18px; gap 12`,
   а объявлено было 15/16 и 8 — то есть пометка и значение под ней РАЗОШЛИСЬ, и разошлись
   молча. Перемер обеих сторон (@390 и @1366): канон `.iti` — `flex`, `pad 16 18`, `gap 12`.
   ⚠ Свожу ТОЛЬКО КОРОБКУ. Раскладку не трогаю: у канона плитка `flex` с ДВУМЯ детьми,
   у нас `grid` с ТРЕМЯ — это состав, держатель `c-tpl`.
   🔴 И ЗАЗОР Я СНАЧАЛА ПОСТАВИЛ 12 ПО СОВПАДЕНИЮ СЛОВА, А НЕ ВЕЛИЧИНЫ, И ОТКАТИЛ. Канонные
   `gap: 12` во flex с двумя детьми — это расстояние ЗНАЧОК↔ТЕКСТ, а у нас его несёт
   `column-gap` (`--ds-card-icon-gap`), и он **уже равен 12**. Наши `row-gap: 3` — промежуток
   к ТРЕТЬЕМУ ребёнку, которого у канона нет вовсе: канонного соответствия у него не
   существует. Правка была бы «объявлено и не действует»: замер показал зазор `3px 12px`
   и ДО, и ПОСЛЕ — значение перекрыто `--ds-card-lead-row-gap`. */
.ds-card--inc   { --ds-card-pad: 16px 18px; --ds-card-gap: 8px; --ds-card-text-lh: 1.45; }
/* Плотность карточек хаба числами канона (замер пары узлов @1366):
   у канона ОБЕ роли — поля 20/20, зазор 7, значок 52. У нас обычная сходилась,
   а КРУПНАЯ шла на 24/24, зазоре 12 и значке 48 ⇒ была выше канонной на 6
   ПРИ ВДВОЕ МЕНЬШЕМ ТЕКСТЕ. Поля у канона 20 по вертикали; горизонталь оставляю 22:
   её я не мерил, а ставить не мерянное — тот же промах, что с полями блока сравнения. */
/* 🔴 РЕЗЕРВ ПОД ИЛЛЮСТРАЦИЮ: У КАЖДОЙ РОЛИ СВОЯ КАРТИНКА, И ОДНО ЧИСЛО НА ДВЕ РОЛИ БЫЛО
   МОИМ ПРОМАХОМ (16.08, поймал integrator-c2). История предмета: я поставил канонные 78/186 →
   `c-ops` показал, что 78 на НАШЕЙ иллюстрации дают заезд → предмет отдан `c-tpl` → он снял
   СВОЁ правило и поднял пин на мой тег → а мой резерв к тому часу уже был откачен. Резерва не
   осталось ни у кого. Возвращая его (v0.332.0), я вывел ОДНО число «от нашей картинки» и
   раскатал его на ОБЕ роли — **обычной карточке это срезало резерв 112 → 94, а её я не мерил
   вовсе.** Мой же класс: верная единица, неверная ОБЛАСТЬ.
   🔴 ЗАМЕР ОБЕИХ СТОРОН ПО РОЛЯМ (`svg` внутри карточки, не подложка):
       ширина картинки   канон @390 / @1366     наша @390 / @1366
         обычная              87 / 103              103 / 103
         КРУПНАЯ              87 / 168              103 / 168
       резерв канона        112 (постоянно)       78 → 186 (ступень 901)
   ⇒ у канона резерв следует ЗА КАРТИНКОЙ роли: обычная 103 → 112 (+9), КРУПНАЯ 87 → 78 (−9),
   168 → 186 (+18). Наша обычная картинка 103 на ОБЕИХ ширинах ⇒ канонные **112 постоянно**
   подходят нам по МЕХАНИЗМУ, а не по совпадению. КРУПНАЯ с 901 — картинка та же (168), значит
   и число канонное: **186**, а не мои выведенные 184.
   ⚠ ЕДИНСТВЕННОЕ ЧИСЛО, ГДЕ КАНОННОЕ НЕ ГОДИТСЯ, — КРУПНАЯ НИЖЕ 901: наша картинка там
   **103 против канонных 87**, шире на 16, и канонные 78 положили бы текст на неё заездом 19.
   Держу выведенное **94** (103 − 9, то же отношение канона) — и остаток ширины текста ровно
   эти 16 и объясняет.
   📌 ПРОВЕРКА МЕХАНИЗМОМ, А НЕ ГЛАЗОМ: ширина текста расходится с каноном ровно на разницу
   ШИРИН КАРТОЧКИ (@1366 карточка +3/+5 → текст 197/307 при канонных 194/302; @390 карточка
   +24 → текст 202 при 179). Совпадение остатка с чужой величиной = число сидит на месте. */
.ds-card--hub    { --ds-card-pad: 20px 22px; --ds-card-gap: 7px; --ds-card-text-pad-right: 112px; }
/* 🔴 РЕЗЕРВ КРУПНОЙ КАРТОЧКИ — СТУПЕНЧАТЫЙ, И Я ПОСТАВИЛ ЕГО КОНСТАНТОЙ (найдено `c-ops`
   ДО выкладки, 16.08). Канон по восемнадцати ширинам: **78 ниже 901 и 186 с 901**; у обычной
   карточки 112 ПОСТОЯННО. Я снял 186 на @1366 и объявил без условия — на @390 это дало бы
   содержимое 128 против канонных 216, то есть перебор 108, и карточка распухла бы строками
   ровно там, где сегодня она КОРОЧЕ канона.
   ⚠ И ступень тут НЕ ТА, что у сетки: сетка ломается на 761 (коробка 664 → 304), резерв — на
   901. **Две ступени на одной величине, и пороги у них РАЗНЫЕ** — взяв 761, промахнулись бы
   на всём диапазоне 761…900.
   📌 Мой же класс, третий раз за сутки: величина, снятая на ОДНОЙ ширине, поставлена
   константой. В тот же день это уже случилось у соседа на `#hero`. */
.ds-card--hub-lg { --ds-card-pad: 20px 22px; --ds-card-gap: 7px; --ds-card-icon-size: 52px;
                   --ds-card-text-pad-right: 94px; }
@media (min-width: 901px) {
  /* 186 — число КАНОНА, не выведенное: с 901 наша картинка 168 = канонной 168, значит
     переносится сам резерв, а не отношение. Мои 184 были арифметикой без механизма. */
  .ds-card--hub-lg { --ds-card-text-pad-right: 186px; }
}

/* 🔴 РЕЗЕРВ ПОД ИЛЛЮСТРАЦИЮ СНЯТ ОТКАТОМ ВПЕРЁД (16.08, решение integrator-c2).
   Предмет оказался сделан ДВАЖДЫ: мой `--ds-card-text-pad-right` (78/186 + медиазапрос)
   и `TEMPLATE v0.230.0` — `calc(var(--tpl-illu-w) + var(--ds-space-4))`. Оба кладут
   `padding-right` на ОДИН И ТОТ ЖЕ абзац; приехав вместе, они сузили бы колонку ВДВОЕ.
   ⚖ ВЫБРАНА ЕГО РЕАЛИЗАЦИЯ, И ДОВОД НЕ ПРО СТАРШИНСТВО ТЕГА, А ПРО УСТРОЙСТВО:
   у него резерв ВЫЧИСЛЕН из ширины самой иллюстрации и того же отступа, которым она
   отодвинута — **резерв и смещение читают ОДНО значение, а не два похожих**. ⇒ он следует
   за иллюстрацией и медиазапрос ему НЕ НУЖЕН ВОВСЕ.
   ⚠ А мои 78/186 — это то самое «величина, снятая на одной ширине»: `c-ops` поймал у канона
   ступень (78 на 360…900, 186 с 901), я её воспроизвёл — но **воспроизведённая ступень
   остаётся двумя числами, которые надо стеречь**, а вычисленный резерв не ломается вовсе.
   📌 Урок мне: я чинил ЧИСЛО там, где предмет закрывался УСТРОЙСТВОМ. Медиазапрос был бы
   лечением симптома — и выглядел бы при этом добросовестной работой.
   ⚠ Читатель `--ds-card-text-pad-right` в ядре ОСТАЁТСЯ (умолчание 0): роль объявлена и
   никому не мешает; вернуть значение = вернуть строку, а не искать, что было отменено. */
/* Подвал карточки: у канона поля нет вовсе — там ссылка, а не кнопка. */
.ds-card--hub,
.ds-card--hub-lg { --ds-card-footer-pad-top: 0; }

/* продолжение брендового :root — величины, не относящиеся к ролям карточек */
:root {

  /* 🔴 ССЫЛКА «ПЕРЕЙТИ» В КАРТОЧКЕ ХАБА — ОБЪЯВЛЯЮ Я (решение integrator-c2, 16.08).
   * Правило раздела: `--ds-*` — пространство ядра и бренда, `--tpl-*` — шаблона; читатель
   * у `c-tpl` (`.tpl-card__go`), значение у бренда — ровно как с `--ds-card-text-pad-right`.
   * ЗАМЕР КАНОНА СВОЙ, не пересказ: три узла `span.hgo` @1366, все три одинаковы —
   * `display:flex`, gap **7**, кегль **13**, вес **800**, `line-height: normal`,
   * цвет `rgb(62,112,19)` = **#3E7013**, коробка 307×15.
   * ⚠ ЦВЕТ НЕ РАВЕН АКЦЕНТУ forbion (`--ds-color-accent` #478016) — и это не описка канона,
   * а отдельная роль: ссылка тише бейджа. Псевдоним на акцент дал бы «похоже», но увёл бы
   * величину за чужим токеном.
   * 📌 `normal` тут ЗАМЕРЕННОЕ, а не нейтральное: наследуемые 1.5 дали бы строку 21 при
   * канонных 15 — «нейтральное умолчание = прежний рендер» здесь неприменимо, прежнего
   * рендера у роли нет вовсе.
   * ⚠ У `c-tpl` в рабочем дереве те же пять лежат умолчанием на `html` (0,0,1) — специально
   * ниже бренда по СПЕЦИФИЧНОСТИ, чтобы это объявление выигрывало при любом порядке
   * подключения. Двойного автора здесь нет: у него умолчание шаблона, у меня значение бренда. */
  --ds-card-go-size: 13px;
  --ds-card-go-weight: 800;
  --ds-card-go-color: #3E7013;
  --ds-card-go-gap: 7px;
  --ds-card-go-lh: normal;

  /* ── ПОЛЯ ЦЕНЫ В ПЛИТКЕ — числа канона, забраны из шаблона в бренд (17.08, запрос `c-tpl`) ──
   * Их `TEMPLATE v0.236.0` объявляет `margin: var(--ds-card-price-mt, 10px) 0 var(--ds-card-price-mb, 2px)`
   * — имена и фолбэки сверены по ИХ тегу, а не по письму. Фолбэк у них = замер канона, то есть
   * бренд-число временно жило в слое шаблона; при втором бренде оно обязано было бы уехать.
   * Кладу значение сюда — рендер не меняется (10/2 = 10/2), меняется ДЕРЖАТЕЛЬ.
   * 🔴 И строка реестра `docs/TOKENS-EXTERNAL.md` заводится ОДНОВРЕМЕННО с этим объявлением,
   * а не раньше: у `--ds-card-go-*` строка простояла четыре тега при НЕ объявленном ни одном
   * значении — реестр снимал гейт 17, обещая, что предмет закрыт другим способом, и обещание
   * было пустым. Реестр без объявления — не запись, а глушитель проверки. */
  --ds-card-price-mt: 10px;
  --ds-card-price-mb: 2px;

  /* 🔴 ЗАЗОР СЕТКИ ХАБА — ТОКЕН НАЗНАЧЕНИЯ, а не выбор из шкалы (запрос `c-tpl`, 15.08).
   * Замер канона: `.hub{display:grid;grid-template-columns:repeat(6,1fr);gap:14px}` — шесть
   * колонок, крупная карточка занимает три, обычная две. Отсюда 537 = 3×169.66 + 2×14
   * и 353 = 2×169.66 + 14 при контейнере 1088.
   * ⚠ **14 не ступень нашей шкалы** (у нас 12 и 16), и подгонять его к ступени нельзя:
   * ступень изменит ШИРИНЫ карточек, а они канонные. Проверено арифметикой на числах `c-tpl`:
   * его сетка та же шестиколоночная, при зазоре 24 даёт ровно 532/347 — то есть расходится
   * ТОЛЬКО зазор, механизм совпадает.
   * Потребитель — шаблон; внутреннего читателя в ядре у токена нет, поэтому он объявлен
   * контрактом в `docs/TOKENS-EXTERNAL.md`. */
  --ds-hub-grid-gap: 14px;

  /* Вертикальные поля секций по ролям — замер канона 1366 (партия 9):
   * 24 калькулятор · 32 сравнение · 62 «что входит»/сервер · 96 форма · 50 обычная (умолчание).
   * ⚠ 50 в умолчание НЕ ставлю: у нас общее 64, и сдвиг всех секций разом — отдельный предмет
   * с ре-визой, а не попутная правка. Роли ставит потребитель классом. */
  /* ⚠ ТОЛЬКО ДЕСКТОП: ниже 901 канон даёт калькулятору НЕ 24, а 50/58 — см. медиазапрос ниже.
   * Замер по ряду ширин: 1024 и 940 → 24 · 900 · 760 · 560 · 390 → 50/58. Порог 901. */
  /* Роль «обычная секция» — канон 50 (ре-виза строки 102, виза integrator-c2 15.08).
     Носители: t · ladder · navi · faq · trust — пять секций без ролевого модификатора. */
  --ds-section-pad-normal: 50px;   /* ⚠ ступень: ниже 768 канон даёт 48 — см. медиаблок ниже */

  /* 🔴 ЗАЗОР ПОД ЗАГОЛОВКОМ: у канона это ОДНО правило, а не пять чисел (замер 16.08, 1366,
     все десять секций). У канонного `h2` **margin-bottom: 0 ВЕЗДЕ**; весь зазор приносит
     СОСЕД снизу своим `margin-top`: подводка 8 (topSlider · t · srv · hub · form), 4 (calc),
     10 (сравнение); сетка 34 (ladder · inc) и 22 (faq) — с ними наблюдаемый зазор выходит
     18 · 18 · 6 из-за схлопывания через обёртку.
     ⚠ «t = 9» — ШУМ строчного бокса при том же соседском 8, а не шестое значение: разница
     в один пиксель между 8 и 9 не переживает смены кегля. Отличать шум от величины — то же,
     что 43.5…43.8 у значка.
     ⇒ У НАС МЕХАНИЗМ ЗЕРКАЛЬНЫЙ: зазор держит заголовок, а не сосед. Числа он воспроизводит
     те же, поэтому механизм не меняю (смена потребовала бы объявить поля у десяти чужих
     узлов сразу). Умолчание ставлю 8 — самое частое ЭФФЕКТИВНОЕ значение канона;
     секционные исключения (calc 4 · faq 6 · сравнение 10 · ladder 18 · inc 18) объявляет
     потребитель ролью, как `c-tpl` уже сделал для `#inc`. */
  --ds-section-title-gap: 8px;

  /* Секционные исключения канона к зазору под заголовком (замер 16.08, все десять секций:
     у канонного `h2` `margin-bottom: 0` ВЕЗДЕ, зазор приносит сосед — подводка 8, в калькуляторе
     4, в сравнении 10; сетка 34/22 через схлопывание даёт 18·18·6).
     Носители завёл `c-tpl` (`TEMPLATE v0.208.0`) и провёл через ту же ручку
     `--ds-section-title-gap`, что стоит у `#inc`.
     ⚠ Его гейт печатает класс роли ТОЛЬКО при объявленном токене — значит эти две строки
     не просто задают числа, а ВКЛЮЧАЮТ носители. У соседей без объявления класс не появляется
     вовсе, и разметка у них остаётся байт-в-байт. */
  --ds-calc-title-gap: 4px;
  /* Номеров вопросов у канона нет вовсе — гасим у себя, компонент и соседи не двигаются. */
  /* Ответ FAQ: канон 24.8 при кегле 15.5 = отношение 1.6 (у нас было 1.5); поле снизу 17. */
  --ds-faq-a-lh: 1.6;
  --ds-faq-a-pad-bottom: 17px;
  --ds-faq-num-display: none;
  /* Номера погашены ⇒ резерв под них снимается ТЕМ ЖЕ ходом: канон даёт 20/20. */
  --ds-faq-item-pad-left: 20px;
  --ds-faq-item-pad-right: 20px;
  --ds-faq-q-lh: normal;   /* канон: вопрос держит normal, не 24 */
  --ds-faq-title-gap: 6px;
  --ds-section-pad-tight: 24px;
  --ds-section-pad-compact: 32px;
  --ds-section-pad-wide: 62px;
  --ds-section-pad-final: 96px;

  /* 🔴 РЯД ПЛИТ СЕКЦИИ ЗАЯВКИ — ДВА ЧИСЛА, А НЕ ОДНО (запрос `c-tpl` и integrator-c2, 15.08).
   * Оба вывели зазор арифметикой: «(1088 − X)/2 = 495 ⇒ X = 98». **98 в каноне нет.**
   * Правило целиком: `.fin-grid{display:grid;grid-template-columns:1fr 1fr;gap:30px;
   * max-width:1020px;margin:34px auto 0}` — то есть ряд УЖЕ контейнера (1020 из 1088),
   * а зазор **30**. Замер рендером: плиты 495 ‖ 495, зазор по коробкам 30, родитель 1020.
   * ⚠ Класс ошибки общий у обоих: **в уравнении было ДВА неизвестных — ширина ряда и зазор, —
   * а решали как одно.** Приняли ширину ряда равной контейнеру, и весь остаток свалился в зазор.
   * Потребитель — шаблон; внутреннего читателя в ядре нет, оба объявлены контрактом. */
  --ds-cta-row-max: 1020px;
  --ds-cta-row-gap: 30px;

  /* Плита секции заявки и её перечень — числа канона (замер `.gifts` и `.gifts ul li`, 1366):
   * поля 26/28 · пункт 15.5/22.475 (это ровно 1.45, тот же интерлиньяж, что у подписи карточки).
   * ⚠ Пункты канона НЕРАВНЫ: 45 · 45 · 45 · 65 — последний переносится. Средняя высота пункта
   * врёт в обе стороны, поэтому в разборе высоты её брать нельзя. */
  --ds-plate-pad: 26px 28px;
  --ds-plate-item-size: 15.5px;
  --ds-plate-item-lh: 1.45;
  /* Подложка выделенной карточки — канон `.hcard.hi`: блик сверху слева плюс переход
   * «поверхность выделения → поверхность контрола». Роли взяты нашими токенами, поэтому
   * подложка едет за темой; литералов канона здесь нет. */
  --ds-card-highlight-bg:
    radial-gradient(120% 90% at 25% 0%, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0) 60%),
    linear-gradient(165deg, var(--ds-surface-highlight), var(--ds-surface-raised));
  /* Подложка значка карточки — канон `.lic`: радиальный градиент от блика к выделению
   * и дальше к поверхности контрола, плюс внутренняя светлая кромка. Величины ролей взяты
   * нашими токенами, а не литералами канона, чтобы подложка ехала за темой. */
  --ds-card-icon-hi: rgba(255, 255, 255, 0.95);
  --ds-card-icon-bg: radial-gradient(circle at 32% 26%, var(--ds-card-icon-hi),
                     var(--ds-surface-highlight) 58%, var(--ds-surface-raised) 100%);
  --ds-card-icon-inner: inset 0 1.5px 0 rgba(255, 255, 255, 0.45);
  /* Знак раскрытия FAQ — канон: круг 43, глиф цветом акцента, вопрос 17/700 (замер 15.08).
   * Форму круга даём кольцом-тенью, чтобы не трогать маску шеврона в ядре. */
  --ds-faq-toggle-size: 24px;
  --ds-faq-toggle-radius: 50%;
  --ds-faq-toggle-ring: 0 0 0 10px rgba(112, 182, 44, 0.10);
  /* 🔴 ФОРМА ВОЛНЫ: ФАЗА БЫЛА ПЕРЕВЁРНУТА — гребень против впадины (16.08).
     Нашлось РАСТРОМ, а не сравнением путей: снял силуэт обеих сторон по колонкам и получил
         канон [19 23 23 21 17 14 13 15 19 20 …]  ·  наше [18 14 14 17 20 23 24 21 18 17 …]
     суммы пар ПОСТОЯННЫ (~37) ⇒ наша волна — зеркало канонной, а не «сдвиг на 3 px»,
     как я предположил, сравнивая нормализованные пути. **Сравнение путей дало неверный
     диагноз при верных числах: у сторон разные система координат, сторона замыкания и флип,
     и в этой арифметике легко получить правдоподобный, но ложный ответ. Растр — прямой замер.**
     ⇒ путь ПЕРЕСЧИТАН в нашу систему (та же коробка 70, замыкание вниз), фаза перевёрнута
     (y' = 70 − y), канонный путь «как есть» НЕ вставлялся.
     Проверка верхней позиции растром: |стало − канон| ≤ 2 px по всем четырнадцати колонкам.
     ⚠ НИЖНЯЯ ПОЗИЦИЯ РАСТРОМ НЕ ПРОВЕРЕНА: у канона под секцией полоса не двухцветная,
     замер невалиден — это НЕ «сошлось», а «не измерено». Ждёт визуального вердикта. */
  --ds-divider-shape: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 70" preserveAspectRatio="none"><path d="M0,35 C240,0 480,70 720,42 C960,14 1200,56 1440,28 L1440,70 L0,70 Z"/></svg>');
  /* Полосы-подложка: форма канона (`svg.bars`, два многоугольника 100×100).
     ⚠ Здесь ПЕРЕНОС ФОРМЫ БЕЗОПАСЕН, в отличие от волны: у многоугольников нет ни замыкания
     пути, ни флипа — переносится сам контур, а не его дополнение. Волну я пересчитывал
     именно потому, что там инвертировали три вещи разом. */
  /* Умолчание роли = экземпляр ГЕРОЯ (он же был единственным, когда роль заводилась). */
  --ds-bars-top: -40px;
  --ds-bars-right: -60px;
  --ds-bars-shape: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="none"><polygon points="0,58 0,82 100,35 100,11"/><polygon points="0,28 0,52 100,5 100,-19"/></svg>');
  --ds-bars-color: var(--ds-color-primary);
  --ds-divider-height: 32px;
  --ds-divider-color: var(--ds-surface-page);
  /* Выделение носителя — подъём к белому (канон: карточка `.lad.hi` = rgba(255,255,255,.72),
   * её бейдж без подложки; строка `tr.hi` = ячейки зелёные, чипы внутри белые). */
  --ds-surface-picked: rgba(255, 255, 255, 0.72);
  --ds-surface-picked-chip: #ffffff;
  /* 🔴 ЛИНИЯ. Нашёл НЕ на кадре, а зондом, когда проверял тёмную пару: у канона `--ln` в светлой
   * #E2E8E4, а у нас на светлой стояла ядровая #d9dde5 — синеватая, как и весь ядровый набор.
   * Значение канона в бренде уже жило, но только под одним потребителем (`--ds-chip-border`),
   * то есть верное число было в файле и НЕ РАБОТАЛО на остальные носители линии.
   * Пишу вслух, что это замер зондом, а не строка партии 5: на кадре разницу #d9dde5/#E2E8E4
   * не видно, и подавать её как «увидел глазами» было бы неправдой. */
  --ds-border-default: #E2E8E4;
  /* 🔴 Заголовок героя ТЕЧЁТ, как в каноне: `clamp(28px, 3vw, 36px)` — замер по восьми ширинам
   * совпал с формулой канона до сотых (28 @901 · 30.72 @1024 · 36 @1200+).
   * Ниже 768 у канона фиксированные 34px — берём их же. */
  --ds-hero-title-size: 34px;
  --ds-hero-title-weight: 800;    /* канон: заголовок героя 800, у нас было 700 */
  --ds-hero-title-leading: 1.08;  /* канон 36.72/34 и 38.88/36 — оба дают 1.08 */
  --ds-hero-lead-size: 14px;      /* от 761; ниже — 13 (в медиаблоке) */
  --ds-hero-lead-leading: 1.6;    /* от 761; ниже — 1.4 */
  --ds-hero-lead-weight: 500;
  --ds-hero-title-size-md: clamp(28px, 3vw, 36px);
  --ds-hero-title-size-sm: 34px;
  /* Тире перед кикером и крупная стрелка карусели — приёмы канона (замер 15.08):
   * `::before` 22×2 цветом primary · стрелка круг 60×60, глиф 24px (у нас было 46 и мельче). */
  --ds-eyebrow-dash: 22px;
  --ds-carousel-arrow-size: 60px;
  /* 🔴 27 БЫЛО ОШИБКОЙ, И ОШИБКА В ЕДИНИЦЕ: я померил у канона ЛИНЕЙНУЮ КОРОБКУ текстового
     глифа (8×27 при кегле 24), а `c-ops` померил ИНОК — 5.75×9.38. Наш инок при 27 вышел
     9.50×16.25, то есть В 1.7 РАЗА КРУПНЕЕ канонного: правка увела ДАЛЬШЕ, чем было.
     ⚠ Класс мой же и сегодняшний: величина названа верно, ЕДИНИЦА взята другая.
     19 подобрано так, чтобы инок нашего штрихового глифа сошёлся с канонным. */
  --ds-carousel-arrow-glyph: 19px;
  /* 🔴 ЧЕРНИЛА СТРЕЛКИ — В СВЕТЛОМ СЛОЕ. Первая редакция правила ТЁМНЫЙ блок: строка нашлась
     грепом, и я не посмотрел, в каком она блоке. Поймал ГЕЙТ ПАРЫ ТЕМ: «бренд возвращает
     #1D1D1B, а ядро светлое даёт var(--ds-color-primary)». ⇒ у значения есть не только
     носитель и область, но и СЛОЙ ТЕМЫ, и греп его не показывает. */
  --ds-carousel-arrow-ink: #1D1D1B;
  /* Активная ступень калькулятора — приём канона: не заливка, а поверхность выделения
   * с обычными чернилами и рамкой 1px primary (замер: button.on, #EDF6E3 + 1px #70B62C). */
  /* ── ТАБЫ КАЛЬКУЛЯТОРА: числа канона `.ctabs`/`.ctab` (источник :546–:561) ──────────────
   * Роль табов ядро держало и раньше — активное состояние читается и по `aria-selected`.
   * Здесь только ЗНАЧЕНИЯ вида; `role="tablist"` ставит разметка, ядро ролями не владеет. */
  /* ── ТУМБЛЕР: числа канона `.sw` (источник :1015–:1029 — ДЕЙСТВУЮЩИЕ правила; ранние
   * :574–:575 переобъявлены ниже по файлу и мертвы, брать их было бы ошибкой) ──────────────
   * ⚠ Ход ручки не задаю: ядро считает его формулой ширина − 2×поля − ручка = 46 − 6 − 20 = 20,
   * и это ровно канонный `translateX(20px)`. Число, заданное вторым автором, разъехалось бы
   * с размерами при первой же правке. */
  --ds-switch-width: 46px;
  --ds-switch-height: 26px;
  --ds-switch-pad: 3px;
  --ds-switch-knob: 20px;
  --ds-switch-track-bg: linear-gradient(180deg, var(--ds-surface-raised), var(--ds-surface-card));
  --ds-switch-track-shadow:
    inset 0 0 0 1.5px var(--ds-border-default),
    inset 0 2px 4px rgba(29, 29, 27, .07);
  --ds-switch-hover-shadow:
    inset 0 0 0 1.5px var(--ds-color-primary),
    inset 0 2px 4px rgba(29, 29, 27, .07);
  --ds-switch-knob-bg:
    radial-gradient(circle at 32% 26%, #FFFFFF, var(--ds-surface-card) 58%, var(--ds-surface-raised));
  --ds-switch-knob-shadow: 0 1px 2px rgba(29, 29, 27, .28), inset 0 1px 0 rgba(255, 255, 255, .9);
  --ds-switch-on-bg:
    radial-gradient(120% 130% at 28% 10%, rgba(255, 255, 255, .45), rgba(255, 255, 255, 0) 55%),
    linear-gradient(180deg, #7CC43C, var(--ds-color-primary-hover, #63A427));
  --ds-switch-on-shadow: inset 0 0 0 1.5px #5B9624, inset 0 1px 0 rgba(255, 255, 255, .4);
  --ds-switch-on-knob-bg: radial-gradient(circle at 32% 26%, #FFFFFF, #F5F8F1 58%, #E7EFE1);

  --ds-segment-gap: 5px;
  --ds-segment-track-pad: 5px;
  --ds-segment-track-mar-bottom: 6px;
  --ds-segment-btn-pad: 8px 16px;
  --ds-segment-btn-display: flex;
  --ds-segment-btn-row-gap: 1px;
  --ds-segment-btn-lh: 1.25;
  --ds-segment-btn-wrap: nowrap;
  --ds-segment-size: 13px;
  --ds-segment-weight: 800;
  --ds-segment-hint-size: 11px;
  --ds-segment-hint-weight: 700;
  /* 🔴 Цвет неактивной подписи — СВОЯ пара по темам, не вторичный текст: канон держит его
     отдельным токеном `--ctab-fg`. Тёмное значение — в тёмном блоке ниже. */
  --ds-segment-ink: #5A6270;
  --ds-segment-active-hint-ink: #2A2A28;
  --ds-segment-active-shadow: inset 0 1px 0 rgba(255, 255, 255, .4), 0 2px 0 #5B9624;
  --ds-segment-active-bg: var(--ds-surface-highlight);
  --ds-segment-active-ink: var(--ds-text-primary);
  --ds-segment-active-border: var(--ds-color-primary);
  --ds-surface-raised: #ecf2f2;
  --ds-surface-card: #FFFFFF;      /* канон `--card` в светлой */
  --ds-surface-sunken: #dfe8e8;
  --ds-surface-inverse: #1d1d1b;

  /* 🔴 ОСНОВНОЙ ТЕКСТ — КАНОННЫЙ #1D1D1B (15.08, решение integrator-c2; «ровно как на макете»).
   * Ядро даёт #1a1f2b — СИНЕВАТЫЙ серый нейтрального языка системы; канон forbion держит
   * #1D1D1B (замер: 252 узла из всех текстовых — самый частый цвет страницы).
   * Контраст на нашей странице #F7FAF3: было 15.63, стало 16.02 — выше, не ниже.
   * ⚠ Это тот же чёрный, что `--ds-surface-inverse` и `--ds-color-on-primary`: у бренда ОДИН
   *   чернильный цвет, и теперь он один во всех трёх ролях, а не в двух из трёх. */
  --ds-text-primary: #1D1D1B;

  /* 🔴 СЕРАЯ ШКАЛА — К КАНОНУ (15.08, решение integrator-c2). У КАНОНА ОДИН СЕРЫЙ, а не два.
   * Замер по ролям: описание промо-карточки · описание карточки хаба · сноска тарифов ·
   * сноска калькулятора · строка реестра в герое · ответ FAQ · сноска блока доверия ·
   * подводка формы — ВСЕ #6B726C, от 9.5px до 15.5px. Итого 129 узлов, вторая по площади
   * текстовая поверхность страницы.
   * ⇒ наши ДВЕ ступени (secondary/muted) отображаются в ОДНО канонное значение. Это не потеря
   *   роли у нас, а отсутствие этой роли У КАНОНА: сводим к тому, что в макете, а не к среднему.
   * ⚠ ДЛЯ ПРИЁМКИ, число против числа:
   *     secondary: было #5a6274 = 5.80 → стало 4.69 — контраст СНИЗИЛСЯ (AA берёт, запас тоньше);
   *     muted:     было #8b92a3 = 2.96 🔴 НИЖЕ AA → стало 4.69 ✓ — контраст ВЫРОС и порог взят.
   *   То есть «как в макете» здесь одну ступень ослабляет, а вторую ЧИНИТ. */
  --ds-text-secondary: #6B726C;
  --ds-text-muted: #6B726C;

  /* Шрифты: Raleway (SIL OFL; загрузка @font-face — зона шаблона) */
  --ds-font-base: 'Raleway', 'Segoe UI', system-ui, sans-serif;
  --ds-font-heading: 'Raleway', 'Segoe UI', system-ui, sans-serif;

  /* Геометрия: бренд угловатый (полосы 25°, параллелограммы) — скругления минимальные.
   * ⚠ 15.08: угловатость осталась ТОЛЬКО на шкале (sm/md/lg) и на мелких элементах.
   * Крупные носители — кнопки, карточки, купон — сведены к канону токенами назначения ниже. */
  --ds-radius-sm: 2px;
  --ds-radius-md: 3px;
  --ds-radius-lg: 6px;
  /* 🔴 КНОПКИ — ПИЛЮЛЯ (15.08, решение integrator-c2 по приказу владельца «ровно как на макете»).
   * Замер канона: у кнопок радиус 999px (27 вхождений), у чипов тоже 999px (28).
   * Правлю ОДИН токен назначения `--ds-radius-btn`, а НЕ шкалу `--ds-radius-md`:
   *   · угловатость 3px — решение брендбука 09.07 и относится к ПОВЕРХНОСТЯМ (карточки, панели);
   *   · канон требует пилюлю у КНОПОК. Меняя шкалу, я отменил бы брендбук целиком ради кнопок.
   * ⚠ И НЕ переопределением по месту: у нас уже есть `--ds-text-link` с тремя определениями,
   * где верное значение держится ТОЛЬКО порядком подключения. Второго такого токена не завожу —
   * условие integrator-c2, и оно же наш сегодняшний урок.
   * ↩ ОТКАТ — одна строка: убрать объявление ниже, и всё вернётся к брендбуку. */
  --ds-radius-btn: var(--ds-radius-full);
  /* 🔴 КАРТОЧКИ И ПАНЕЛИ — К КАНОНУ (15.08, решение integrator-c2, та же датировка, что у кнопок:
   * брендбук 09.07 в этой части уступает приказу «ровно как на макете»; отзыва брендбука не было;
   * ↩ откат — удаление двух строк ниже).
   *
   * ⚠ ШКАЛУ НЕ ДВИГАЮ. Правлю ТОКЕНЫ НАЗНАЧЕНИЯ, как с кнопкой: `--ds-radius-card` и
   * `--ds-radius-xl` (на нём купон и сплит-панель). `--ds-radius-sm/md/lg` остаются брендбучными —
   * на них стоят мелкие элементы, и канон для них своего числа не даёт единообразно.
   *
   * Значения СНЯТЫ ПОЭЛЕМЕНТНО, а не «26 везде» (замер канона):
   *   промо-карточка 355×141 → 26 · карточка «почему мы» 374×161 → 26 · карточка хаба 531×214 → 24
   *   КУПОН 236×359 → 28 · таблица тарифов → 0 · чипы и вкладки → 999 (уже пилюля)
   * Беру 26 как значение карточки (две роли из трёх, 11 вхождений — самое частое у крупных)
   * и 28 для `xl` — купон. Разброс 24…28 в каноне НЕ свожу к одному: у канона он есть,
   * а «привести к единому» значило бы решить за макет. */
  /* 🔴 ШИРИНА КОНТЕЙНЕРА — К КАНОНУ (15.08, решение integrator-c2).
   * 🔴 В БРЕНД-ПАКЕТЕ, А НЕ В ЯДРЕ: `--ds-container-max` общий для izibuh и tezum, а приказ
   * 15.08 — про forbion. ОБЛАСТЬ ПРАВКИ = ОБЛАСТЬ РЕШЕНИЯ. ↩ откат — одна строка.
   *
   * ЗАМЕР КАНОНА (playwright, vw 1440/1280/1920) — сперва я померил ОДИН элемент и назвал его
   * «контейнер»; перемер показал, что моделей ДВЕ:
   *   секции `.wrap` → `max-width: 1140px`, `border-box`, padding 26/26 ⇒ ВНЕШНЯЯ 1140,
   *     КОНТЕНТ 1088, левый край контента x=176 — на всех трёх ширинах одинаково;
   *   шапка `.wrap` → `max-width: 88%` — ТЕКУЧАЯ: 1126 @1280 · 1267 @1440 · 1690 @1920.
   * Здесь закрыта только СЕКЦИОННАЯ модель. Текучая шапка — предмет `c-tpl`, не токен.
   *
   * 🔴 ЧИСЛО БЕРУ КАНОННОЕ (1140), А НЕ ПОДОГНАННОЕ ПОД НАШ РЕНДЕР. Наш `.ds-section__inner` —
   * `content-box`, поэтому на живом выйдет 1172 (1140 + pad 16×2), а колонка контента — 1140
   * против канонных 1088. Это ИЗВЕСТНЫЙ дефект ядра, а не промах числа: `docs/WINDOW-container-
   * metrics.md` уже держит его для izibuh (токен 1100 → рендер 1132, ровно те же +32) и прямо
   * запрещает подгонять токен под неверную метрику. Подставить 1088 значило бы спрятать дефект
   * ядра в бренд-пакете и потерять канонное число.
   * ⚠ Остаточная дельта после закрытия окна будет ещё 20px: у канона padding 26, у нас 16.
   *   `--ds-container-pad` НЕ трогаю здесь — он часть того же окна (см. пункт 2 файла окна). */
  --ds-container-max: 1140px;

  /* 🔴 КИКЕР — ГОЛАЯ ПОДПИСЬ, А НЕ ПЛАШКА (замер канона 15.08).
   * Канон: `padding 0`, фона нет, высота **14**, `font-size 11.5px`, `letter-spacing 1.61px`
   * (= 0.14em), вес 800, `margin-bottom: 8px` — одинаково во всех 10 вхождениях.
   * У нас была плашка высотой **34**: это не «другой отступ», а ДРУГОЙ ОБЪЕКТ, и разница
   * в 20px копилась на каждой из 12 секций.
   * ⚠ ЗАЗОР 8 ≠ ШАГ 22: моя партия 4 отдавала 22 — это расстояние между ВЕРХАМИ узлов
   *   (8 + высота кикера 14). Поставить 22 в margin — получить шаг 36. */
  --ds-eyebrow-gap: 8px;
  --ds-eyebrow-bg: transparent;
  --ds-eyebrow-pad: 0;
  --ds-eyebrow-tracking: 0.14em;
  --ds-eyebrow-size: 11.5px;
  /* 🔴 Канон даёт кикеру `line-height: normal`, а не число: замер обеих сторон 16.08 —
     канон `normal` на всех пяти ширинах, у нас `14.03px` (= 1.22 × 11.5). Прежняя пометка
     «канон даёт высокий интерлиньяж» была догадкой о причине, а не замером.
     ⚠ Пятый за сутки случай одной формы: где канон оставляет `normal`, мы ставим число
     (зазоры шагов калькулятора · блок итога · карточка тарифа · степпер · теперь кикер). */
  --ds-eyebrow-lh: normal;

  /* 🔴 ШИРИНА ШАПКИ — ОТДЕЛЬНЫЙ ТОКЕН (15.08, запрос c-tpl и integrator-c2).
   * Канон: у шапки `max-width: 88%` — ТЕКУЧАЯ модель, у секций `1140px` — фиксированная.
   * Одним `--ds-container-max` их не развести: сделаешь шапку текучей — поедут секции.
   * Замер: 1126 @1280 · 1267 @1440 · 1690 @1920.
   * Ядро объявляет `--ds-header-max: var(--ds-container-max)` — у izibuh и tezum ничего
   * не меняется; здесь бренд берёт канонное 88%. ↩ откат — одна строка. */
  --ds-header-max: 88%;

  --ds-radius-card: 26px;
  --ds-radius-xl: 28px;

  /* 🔴 РАДИУС КАРТОЧЕК ХАБА — 24, СВОЁ ЗНАЧЕНИЕ (ответ на замер c-ops 15.08).
   * `c-ops` не нашёл на живом ни одного узла с 24 — и был прав: карточки хаба получили
   * общий `--ds-radius-card` = 26. Замер канона подтверждает 24: `.hcard` ×5 (две крупные
   * 537×217 и три 353×232) — все 24. Разброс канона при сведении к одному токену ТЕРЯЕТСЯ,
   * поэтому у хаба своё назначение, а не общее. Полная канон-таблица радиусов —
   * `concept/forbion-1c/CANON-COMPOSITIONS.md`, раздел «радиусы». */
  --ds-radius-card-hub: 24px;

  /* 🔴 ПОДВАЛ — СВЕТЛЫЙ, К КАНОНУ (15.08, решение integrator-c2; макет ответил, владельца не спрашивали).
   * Замер канона: подвал ПРОЗРАЧНЫЙ (лежит на странице), текст #6B726C, ссылки #3E7013.
   * Тёмный подвал был нашей конструкцией; из-за него ссылка бренда давала на нём 2.95 —
   * и сведение цвета к AA сделало там ХУЖЕ (было 3.51), потому что цвет один на оба фона.
   * На светлом подвале тот же #3F7314 даёт 5.42 — ухудшение исчезает вместе с причиной.
   * ⚠ Ядро не тронуто: у izibuh и tezum подвал остаётся тёмным. */
  --ds-footer-surface: var(--ds-surface-page);
  --ds-footer-text: var(--ds-text-primary);
  --ds-footer-link: var(--ds-text-link);
  --ds-footer-muted: var(--ds-text-muted);
  --ds-footer-rule: var(--ds-border-default);

  /* Вопрос и ответ FAQ — канон: 17/700 и 15.5/500 (у нас было 14/600 на обоих) */

  /* Строка FAQ — канон `#faq` (замер 15.08, 1366, СВЕТЛАЯ тема). Рамки нет, держит плита. */
  --ds-faq-gap: 10px;
  --ds-faq-item-radius: 22px;
  --ds-faq-item-border-width: 0px;
  --ds-faq-item-bg:
    radial-gradient(130% 90% at 18% 0%, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0) 55%),
    linear-gradient(165deg, #FFFFFF 0%, #FDFEFB 55%, #F3F7EE 100%);
  --ds-faq-item-shadow:
    inset 0 1.5px 0 rgba(255, 255, 255, 0.85),
    inset 0 -1.5px 0 rgba(29, 29, 27, 0.05),
    inset 0 22px 40px -26px rgba(255, 255, 255, 0.6),
    0 6px 14px rgba(29, 29, 27, 0.07),
    0 34px 72px -26px rgba(29, 29, 27, 0.3);
  /* 🔴 ВЫСОТУ КАНОННОЙ СТРОКИ ДЕРЖИТ НЕ ТЕКСТ И НЕ РЕЗЕРВ, А КРУЖОК ПЕРЕКЛЮЧАТЕЛЯ.
     Разложил, прежде чем давать число (`#faq > * > summary`, 15.08): `min-height: 0`,
     `padding: 17px 20px`, флекс по центру, в потоке один ребёнок `pm` **31×31**, строка
     текста 20. Значит 65 = 17 + **31** + 17, и автор высоты — переключатель, а не подпись.
     Поэтому `--ds-faq-q-min-h: 31px` — это канонный кружок, названный по имени, а не
     подобранное число: у величины есть автор, и он предъявлен.
     У izibuh резерв в две строки — ПРИНЯТЫЙ вид (канон izibuh, решение владельца), он токен
     не объявляет и остаётся при `2lh`. */
  --ds-faq-q-min-h: 31px;
  --ds-faq-q-pad: 17px 0;
  --ds-faq-q-size: 17px;
  --ds-faq-q-weight: 700;
  --ds-faq-a-size: 15.5px;
}

/* ── ОРБЫ В ТЁМНОЙ ТЕМЕ (c-design, 12.08) ──────────────────────────────────────
 * Класс описан в tokens.css:336 и до сих пор не был закрыт для forbion:
 * цвет орба выведен из primary, а primary НЕ флипается (do-not-flip, и правильно) —
 * значит производная не флипается тоже, хотя ПОВЕРХНОСТЬ под ней флипается.
 * Та же альфа на тёмном читается слабее, и атмосфера пропадает.
 *
 * Значения сняты С КАНОНА concept-v0.30.4 (DESIGN v0.60.0), а не подобраны:
 *   светлая  орб1 rgba(112,182,44,.16)  орб2 rgba(112,182,44,.09)
 *   тёмная   орб1 rgba(139,214,69,.10)  орб2 rgba(139,214,69,.05)
 * В тёмной меняется И оттенок, И альфа — это не «тот же цвет тише».
 *
 * Светлую НЕ переопределяю: ядро уже даёт primary 16 %, что совпадает с каноном
 * бит-в-бит. Переопределять совпадающее — заводить второй источник на ровном месте.
 * Задаю только орб2 (в ядре -accent выведен из accent #478016, а канон хочет тот же
 * оттенок, что орб1, но тише) и обе тёмные величины.
 *
 * СПЕЦИФИЧНОСТЬ: ядро объявляет эти токены на :root = (0,1,0). Бренд грузится ПОСЛЕ,
 * поэтому :root достаточно для светлой. Для тёмной беру :root:not([data-theme="light"])
 * и :root[data-theme="dark"] — переключатель темы обязан побеждать медиазапрос
 * в ОБЕ стороны, а не только включать тёмную.
 *
 * ⚠ ОТСТУПЛЕНИЕ ОТ СВОЕГО ЖЕ КОНТРАКТА, называю вслух: brand.json объявлен источником
 * истины для токенов, но его секция tokens ПЛОСКАЯ — измерения тем в ней нет. Класть
 * туда тёмные значения значило бы менять интерфейс бренд-пакета, а его читает валидатор
 * c-tpl (гейт 3). Поэтому пока живут здесь; расширение brand.json под темы — письмо-ДО
 * к c-tpl, отдельным предметом. Два источника на один токен я не завожу: в brand.json
 * этих ключей НЕТ вовсе, они существуют только тут. */
:root {
  --ds-orb-color-accent: rgba(112, 182, 44, 0.09);
}
/* 🔴 14.08: орб-блок висел на СИСТЕМНОЙ схеме и расходился с брендовым умолчанием —
   при системной тёмной орбы брали тёмные значения на СВЕТЛОМ фоне. Медиа-вариант снят,
   остаётся явный [data-theme="dark"] ниже: орбы следуют ТЕМЕ БРЕНДА, а не системе.
   Значения не потеряны — двойник уже существовал. Класс тот же, что у логотипа. */
:root[data-theme="dark"] {
  --ds-orb-color-primary: rgba(139, 214, 69, 0.10);
  --ds-orb-color-accent:  rgba(139, 214, 69, 0.05);
}

/* ── ПЛОТНОСТЬ ПАТТЕРНА (c-design, 12.08) ─────────────────────────────────────
 * Значения СНЯТЫ С КАНОНА concept-v0.30.4, а не подобраны. Замер: декоративные
 * бруски 25° в каноне встречаются ТРИЖДЫ, с инлайн-плотностями .07 / .09 / .16 —
 * называю число вхождений, потому что сегодня уже ошибся, взяв одно значение из
 * нескольких и выдав за единственное.
 * Интерфейс c-tpl (TEMPLATE v0.87.x) даёт две ступени, поэтому:
 *   soft   = 0.07  — самая частая, ею живёт герой;
 *   strong = 0.16  — верхняя канонная.
 * Средняя .09 слота не имеет; если понадобится — это третья ступень у c-tpl,
 * а не «подберём между».
 *
 * ТЁМНАЯ ТЕМА: в каноне бруски НЕ переопределяются (проверил — правил нет), в
 * отличие от шаров, у которых своя пара (--sphop .5 / .2). Повторяю канон:
 * переопределения не завожу. Это ЗАМЕР, а не утверждение, что так верно, — если
 * на тёмной 0.07 окажется невидимым, это отдельная правка с отдельным замером. */
:root {
  --ds-pattern-opacity-soft: 0.07;
  --ds-pattern-opacity-strong: 0.16;
  /* 🔴 ТРЕТЬЯ СТУПЕНЬ (14.08, запрос c-tpl). Завожу не потому, что «нужно 0.10 между 0.07 и 0.16»,
   * а потому, что он назвал РОЛЬ — мой же критерий: soft = фон СЕКЦИИ · strong = ВСТАВКА ·
   * card = ДЕКОР ВНУТРИ КАРТОЧКИ (площадь мельче, фон под ним плотнее, поэтому и плотность выше
   * soft). Три роли — три ступени; подбирать «между» я запретил сам и не подбираю.
   * Значение СНЯТО С КАНОНА: паттерн в углу карточки хаба идёт opacity .10 (замер, не выбор). */
  --ds-pattern-opacity-card: 0.10;
}

/* ══ УМОЛЧАНИЕ СВЕТЛОЕ — ВОЗВРАТ СВЕТЛОЙ ПРИ СИСТЕМНОЙ ТЁМНОЙ (решение владельца 12.08,
   наряд integrator-c2 13.08: снимаем НА УРОВНЕ БРЕНДА, ядро не трогаем) ══
   Ядро (`tokens/tokens.css`) применяет тёмную по системной схеме через
   `@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) {…} }`.
   Это верно для izibuh и остальных на ядре — они за наше решение платить не должны.
   Здесь, в бренд-пакете forbion, возвращаем светлые значения ТОЛЬКО когда посетитель
   НЕ выбрал тёмную явно. Бренд грузится ПОСЛЕ ядра, специфичность равная (0,2,0) —
   значит побеждает порядком, а `[data-theme="dark"]` продолжает побеждать оба.
   🔴 ЭТО ДУБЛИКАТ ЗНАЧЕНИЙ ЯДРА, а дубликат протухает по построению — поэтому он
   ПРОВЕРЯЕТСЯ: гейт `tools/check-brand-light.py` сверяет каждую строку ниже с базовым
   `:root` ядра и краснеет при расхождении. Список без сверки был бы миной. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="dark"]) {
    /* 🔴 возврат обязан возвращать БРЕНДОВУЮ светлую (#F7FAF3), а не ядровую (#FFFFFF):
     * иначе посетитель с системной тёмной получил бы белую страницу там, где у всех зеленоватая.
     * Гейт 13 расширен под это: он сверяет с ЭФФЕКТИВНОЙ светлой = переопределение бренда,
     * если оно есть, иначе базовый :root ядра. */
    --ds-surface-page: #f7faf3;
    --ds-surface-section: #ffffff;  /* канон: окрашенная секция белая */
    --ds-surface-highlight: #edf6e3;/* канон: поверхность выделения */
    --ds-surface-raised: #ecf2f2;   /* канон: поверхность неактивного контрола */
    --ds-surface-sunken: #dfe8e8;   /* БРЕНДОВАЯ светлая, не ядровая */
    --ds-text-primary: #1D1D1B;   /* канон, см. блок :root выше */
    --ds-text-secondary: #6B726C; /* канон: серый ОДИН на все роли, см. блок :root выше */
    --ds-text-muted: #6B726C;
    --ds-border-default: #E2E8E4;   /* канон `--ln`; поймал гейт 13 — дубликат протух
                                     * ровно так, как обещал комментарий к этому блоку */
    --ds-border-strong: #b7bdca;
      --ds-text-link: #3F7314;        /* 🔴 было var(--ds-color-primary) = #70B62C — значение из
                                     * ТЁМНОГО блока ядра, скопированное в блок ВОЗВРАТА СВЕТЛОЙ.
                                     * Посетитель с системной тёмной получал ссылку с контрастом
                                     * 2.37 на светлой странице. Замер рендером, не рассуждение. */
    --ds-border-focus: var(--ds-color-primary);
    --ds-color-success: #188a42;
    --ds-color-warning: #b45309;
    --ds-color-error: #c0262c;
    --ds-color-info: #2456d6;
    --ds-shadow-sm: 0 1px 2px rgba(22, 26, 35, 0.08);
    --ds-shadow-md: 0 4px 12px rgba(22, 26, 35, 0.1);
    --ds-shadow-lg: 0 12px 32px rgba(22, 26, 35, 0.14);
    --ds-focus-ring: color-mix(in srgb, var(--ds-color-primary) 15%, transparent);
    --ds-gradient-soft: linear-gradient(160deg, var(--ds-surface-raised), var(--ds-surface-sunken));
    /* Пилюля залита зелёным в ОБЕИХ темах ⇒ глиф остаётся тёмным и здесь: инверсия
       чернил на зелёном дала бы белое по светло-зелёному. Значение то же, что в светлой,
       и объявлено явно — пара обязана быть, даже когда значения совпадают. */
    --ds-carousel-arrow-ink: #1D1D1B;
    --ds-carousel-arrow-border: var(--ds-border-default);
    --ds-mark-color: color-mix(in srgb, var(--ds-color-accent) 30%, transparent);
    --ds-gradient-text: var(--ds-gradient-brand);
    --ds-shadow-brand: 0 24px 60px -18px color-mix(in srgb, var(--ds-color-primary) 22%, transparent);
  }
}

/* ══ ВОЗВРАТ ЛОГОТИПА (корень кляксы, нашёл integrator-c2 на живом 14.08) ══
   Ядро переключает логотип по СИСТЕМНОЙ схеме — `components/header/header.css:138`,
   `:root:not([data-theme="light"]) .ds-header__logo-*`. Мой брендовый возврат покрывал только
   ТОКЕНЫ, поэтому фон брался светлый (бренд), а логотип тёмный (система).
   🔴 Тёмный логотип на светлом фоне — это и есть «клякса», которую увидел владелец.
   Базовое `.ds-header__logo-dark{display:none}` проигрывает по специфичности (0,1,0 против 0,3,0),
   поэтому нужен встречный блок ТОЙ ЖЕ специфичности, выигрывающий ПОРЯДКОМ загрузки.
   Ядро не трогаем: у izibuh и остальных переключение по системе остаётся рабочим. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="dark"]) .ds-header__logo-light { display: inline; }
  :root:not([data-theme="dark"]) .ds-header__logo-dark  { display: none; }
}

/* ══ ТЁМНАЯ ТЕМА БРЕНДА (c-design, 15.08, партия 5 диффа глазами) ══════════════
 * 🔴 ПОЧЕМУ ЭТОГО БЛОКА НЕ БЫЛО ДО СЕГОДНЯ — И ПОЧЕМУ ЭТО КЛАСС, А НЕ ЗАБЫВЧИВОСТЬ.
 * За день бренду forbion описаны ВСЕ светлые поверхности (page/section/highlight/picked,
 * чернила, серый, ссылка) и НИ ОДНОЙ тёмной. Тёмная всё это время приходила из ядра, а ядро
 * СИНЕЕ: `#1a1e27` фон, `#93a4f0` ссылка, `#545e73` линия. На кадре это читается сразу —
 * канон тёмно-оливковый, живое тёмно-синее. Ровно тот механизм, на котором я обжёгся утром
 * в v0.160.0 (белое на белом): ПРАВКА СВЕТЛОЙ БЕЗ ПАРЫ В ТЁМНОЙ РАСХОДИТСЯ МОЛЧА, потому
 * что автор смотрит на светлую. Гейт 20 (`check-theme-pair.py`) ловит отсутствие пары
 * у ОТДЕЛЬНОГО токена; он не умел сказать «у бренда нет тёмной темы как таковой» —
 * это его слепое пятно, и оно теперь названо.
 *
 * ЗНАЧЕНИЯ СНЯТЫ С КАНОНА, строка 135 `concept-v0.30.20-draft.html`, `:root[data-theme="dark"]`.
 * Соответствие РОЛЕЙ проверено по светлой паре, а не по имени переменной:
 *   --warm  #F7FAF3 → #22221E   фон страницы (у канона `body{background:var(--warm)}`)
 *   --card  #FFFFFF → #27271F   окрашенная секция / карточка
 *   --rz    #ECF2F2 → #27271F   поверхность неактивного контрола
 *   --soft  #EDF6E3 → #2B331F   поверхность выделения
 *   --glass rgba(255,255,255,.72) → rgba(35,35,29,.68)   «стеклянная» выбранная
 *   --ink   #1D1D1B → #F4F4F0   чернила · --sub #6B726C → #B3B9AC   вторичные
 *   --ln    #E2E8E4 → #3A3A33   линия · --gtxt #3E7013 → #8BD645   текстовая ссылка
 *
 * ⚠ ЗАМЕР, А НЕ ВЫБОР — две вещи, которые канон СХЛОПЫВАЕТ в тёмной, и я схлопываю следом:
 *   1. `--card` и `--rz` в тёмной РАВНЫ (#27271F), хотя в светлой различаются (#FFFFFF/#ECF2F2).
 *      Секция и контрол в тёмной у канона — одна поверхность.
 *   2. Линия в каноне ОДНА (`--ln`), пары «сильная/обычная» нет вовсе. Поэтому оба наших
 *      токена берут одно значение. Различить их в тёмной — это отдельная правка с отдельным
 *      замером, а не «подберём потемнее»: подбор «между» я себе запретил на плотностях паттерна.
 *
 * ⚠ И одно, чего в каноне НЕТ ВОВСЕ: `--ds-surface-sunken` (у канона нет ни светлой, ни тёмной
 * пары этой роли). Беру самый глубокий тон канонной тёмной палитры — `--pg` #1D1D1B.
 * Это ВЫВОД, не замер, и помечен так, чтобы следующий не принял его за канонное число. */
:root[data-theme="dark"] {
  /* 🔴 ТЁМНУЮ ДЛЯ FAQ НЕ МЕРИЛ: В КАНОННОМ ФАЙЛЕ НЕТ ПЕРЕКЛЮЧАТЕЛЯ ТЕМЫ (искал
     `label.tpl-theme-sw` и соседей — нет). Канонная плита снята в СВЕТЛОЙ; её белый градиент
     в тёмной стал бы литералом-протечкой. Здесь тёмная держит ПРЕЖНИЙ рендер — плоская
     поверхность и рамка. Это не решение о том, как должно быть в тёмной, а отказ угадывать
     неизмеренное: измерят — заменим числом, а не мнением.
     ⚠ И место этих трёх строк само стоило одного красного: сперва я вписал их в блок
     ВОЗВРАТА СВЕТЛОЙ (`prefers-color-scheme: dark` + `:not([data-theme="dark"])`), потому что
     искал первое вхождение подстроки `[data-theme="dark"]`, а она встречается там ОТРИЦАНИЕМ.
     Тот же промах, что был с гейтом 20: подстрока `[data-theme="dark"]` живёт и внутри
     `:not([data-theme="dark"])`. */
  --ds-faq-item-bg: var(--ds-surface-page);
  --ds-faq-item-border-width: 1.5px;
  --ds-faq-item-shadow: none;

  --ds-surface-page:      #22221E;
  /* 🔴 ИСПРАВЛЕНИЕ МОЕЙ ЖЕ ПРАВКИ ОТ v0.190.0: здесь стояло `#27271F`, и это цвет КАРТОЧКИ,
   * а не окрашенной СЕКЦИИ. В светлой обе роли у канона совпадают (`--pg` и `--card` = #FFFFFF),
   * и я свёл их в тёмной по светлой паре — а там они РАСХОДЯТСЯ.
   * Замер канона, тёмная, все окрашенные секции: `#calc` `#inc` `#srv` `#form` = **#1D1D1B**
   * (это `--pg`), тогда как карточки и плитки — `#27271F` (`--card`/`--rz`).
   * ⇒ Секция обязана быть ГЛУБЖЕ карточки, у нас же они были почти равны, и плита на секции
   * не читалась бы вовсе. Совпадение в светлой скрыло различие ролей — ровно тот класс,
   * за который я сегодня ловил себя четырежды. */
  --ds-surface-section:   #1D1D1B;
  --ds-surface-raised:    #27271F;
  --ds-surface-highlight: #2B331F;
  --ds-surface-card:      #27271F;   /* канон `--card` в тёмной */
  --ds-segment-ink:       #C4CABD;   /* канон `--ctab-fg` в тёмной */
  /* 🔴 АКЦЕНТ В ТЁМНОЙ — ПАРА, КОТОРОЙ НЕ БЫЛО. `--ds-color-accent: #478016` объявлен только в
     светлой; в тёмной тёмно-зелёный текст ложился на #22221E и давал 3.51 при пороге 4.5
     (замер краской под текстом, не по предку). Канон флипает эту роль: `--gtxt` #3E7013 → #8BD645.
     ⚠ Гейт пар молчал по той же причине, что утром у плиты: его единица — имена
     `--ds-surface-*` / `--ds-text-*`, а это `--ds-color-*`. Третий случай за сутки, когда
     предмет вышел из области нормы через ИМЯ. */
  --ds-color-accent:      #8BD645;
  /* 🔴 ПЛИТА В ТЁМНОЙ — МОЯ ЖЕ СЕГОДНЯШНЯЯ ПРОТЕЧКА, ПОЙМАННАЯ ЗАМЕРОМ.
     Утром я вынес подложку и тень плиты в общий токен и объявил их ЛИТЕРАЛАМИ в светлом `:root`.
     Тёмной пары не завёл — и замер это подтвердил: при `data-theme="dark"` страница #22221E,
     текст перекрашивается в #F4F4F0, а плита остаётся СВЕТЛОЙ. Светлый текст на светлой плите.
     ⚠ ПОЧЕМУ ГЕЙТ ПАР МОЛЧАЛ: его единица — имя `--ds-surface-*` / `--ds-text-*`, а я назвал
     токен `--ds-plate-*`. Гейт не соврал — он ответил на свой вопрос. Поэтому токен ПЕРЕИМЕНОВАН
     в `--ds-surface-plate`: дешевле подвести предмет под существующую норму, чем расширять её.
     📌 И рядом стоит контрпример: подложка значка (`--ds-card-icon-bg`) собрана ИЗ ТОКЕНОВ и
     тему держит сама, без второй записи. Литерал требует пары; композиция из ролей — нет.
     Значения — из источника канона (`--silk` и `--sh` под `[data-theme="dark"]`). */
  --ds-surface-plate:
    radial-gradient(130% 90% at 18% 0%, rgba(255, 255, 255, .07), rgba(255, 255, 255, 0) 55%),
    linear-gradient(165deg, #2C2C24 0%, #28281F 55%, #23231C 100%);
  /* 🔴 ЗАВЕСА ОКНА В ТЁМНОЙ — ТОТ ЖЕ КЛАСС, ЧТО ПЛИТА ВЫШЕ, И ПОЙМАН ТЕМ ЖЕ СПОСОБОМ.
     Светлое значение `rgba(29,29,27,.52)` объявлено литералом в `:root`, и гейт пар его НЕ судит:
     его единица — имена `--ds-surface-*`/`--ds-text-*`, а это `--ds-dialog-*`. Гейт не соврал —
     предмет опять вышел из области нормы ЧЕРЕЗ ИМЯ.
     Счёт (смешение по альфе на ПЛОСКОМ цвете страницы, арифметика — не съём краски):
        светлая: страница #F7FAF3 под завесой → ≈ #868783 · плита ≈ #FDFEFB  — разделяет уверенно
        тёмная:  страница #22221E под завесой → ≈ #1F1F1C · плита #28281F    — 31 против 40
     ⇒ в тёмной окно почти сливается с тем, что за ним: завеса, рассчитанная гасить СВЕТЛУЮ
     страницу, на тёмной гасить уже нечего, и разделения не остаётся. Поэтому в тёмной завеса
     ПЛОТНЕЕ, а не такая же: её работа — не «затемнить», а ОТДЕЛИТЬ.
     ⚠ ЧЕСТНАЯ ГРАНИЦА ЗАМЕРА: страница не плоская (градиенты секций, орбы), поэтому число
     приблизительное, а направление — нет. Как только `c-tpl` соберёт окно на живой поверхности,
     перемерить съёмом краски по рецепту из `f7c_hq/DEVIATIONS.md` («D-контраст»), а не повторять
     эту арифметику. */
  --ds-dialog-veil-bg: rgba(0, 0, 0, .72);
  --ds-shadow-plate:
    inset 0 1px 0 rgba(255, 255, 255, .08),
    inset 0 -1px 0 rgba(0, 0, 0, .45),
    inset 0 22px 40px -26px rgba(255, 255, 255, .04),
    0 6px 14px rgba(0, 0, 0, .44),
    0 34px 72px -26px rgba(0, 0, 0, .64);
  --ds-surface-sunken:    #1D1D1B;   /* вывод, не замер: у канона роли нет */
  --ds-text-primary:      #F4F4F0;
  --ds-text-secondary:    #B3B9AC;
  --ds-text-muted:        #B3B9AC;   /* канон: `--sub` ОДИН на обе роли, как и в светлой */
  --ds-border-default:    #3A3A33;
  --ds-border-strong:     #3A3A33;   /* канон различия не делает, см. п.2 выше */
  --ds-text-link:         #8BD645;   /* контраст на #22221E = 9.6 — AA с запасом */
  --ds-border-focus:      #8BD645;

  /* поверхности-роли, заведённые сегодня для светлой; тёмные пары канона */
  --ds-surface-picked:      rgba(35, 35, 29, 0.68);
  --ds-surface-picked-chip: #27271F;
  --ds-chip-bg:             rgba(35, 35, 29, 0.68);
  --ds-chip-border:         #3A3A33;
  --ds-calc-panel-bg:       rgba(35, 35, 29, 0.68);

  /* 🔴 СФЕРА. Канон гасит её в тёмной: `--sphop` .5 → .2. У нас в тёмной сфера светится
   * ЯРЧЕ, чем в светлой, потому что непрозрачность зафиксирована в компоненте (0.5) и темы
   * не знает. Это единственная величина партии 5, где расхождение не в цвете, а в том, что
   * у свойства вообще НЕТ второго значения. */
  --ds-sphere-opacity: 0.2;

  /* Блик подложки значка: канон `--orbhi` .95 → .22 в тёмной — это ЗАМЕР, он остаётся. */
  --ds-card-icon-hi: rgba(255, 255, 255, 0.22);

  /* Плита в тёмной — канонный `--silk` тёмной пары и его же тень. */
  --ds-surface-silk:
    radial-gradient(130% 90% at 18% 0%, rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0) 55%),
    linear-gradient(165deg, #2C2C24 0%, #28281F 55%, #23231C 100%);
  --ds-shadow-silk:
    inset 0 1px 0 rgba(255, 255, 255, 0.08), inset 0 -1px 0 rgba(0, 0, 0, 0.45),
    inset 0 22px 40px -26px rgba(255, 255, 255, 0.04), 0 6px 14px rgba(0, 0, 0, 0.44),
    0 34px 72px -26px rgba(0, 0, 0, 0.64);
  /* Блик выделенной карточки в тёмной: .75 → .10, иначе верх карточки выбеливается */
  --ds-card-highlight-bg:
    radial-gradient(120% 90% at 25% 0%, rgba(255, 255, 255, 0.10), rgba(255, 255, 255, 0) 60%),
    linear-gradient(165deg, var(--ds-surface-highlight), var(--ds-surface-raised));
  /* 🔴 ВНУТРЕННЯЯ КРОМКА: снимаю СВОЁ ослабление до .10 — это был подбор на глаз («чтобы не
   * светилась»), которого я сам не разрешаю. У канона кромка `.45` в ОБЕИХ темах, тёмного
   * переопределения у `.lic` нет вовсе — проверил.
   * Повод перемерить дал `c-ops`: средняя разница «подложка против карточки» у нас тёмная 20 ·
   * светлая 4. Я померил тем же способом КАНОН: **светлая 0.8 · тёмная 42.4**.
   * ⇒ Подозрение было на светлую («почти сливается») — а она сливается И У КАНОНА, даже сильнее
   * нашего. Расходится ТЁМНАЯ, и в другую сторону: у нас подложка была СЛАБЕЕ канонной.
   * Поэтому в тёмном блоке кромки больше нет: работает светлое значение бренда, как у канона. */

  /* Тень карточки цены в тёмной — канонный `--glow` (.25 против .45 в светлой).
   * Токен КУПОНА, не бренда: см. разбор у светлой пары ниже. */
  --ds-coupon-shadow: 0 10px 50px -12px rgba(112, 182, 44, 0.25);
}

/* 🔴 КОЛЬЦО КУПОНА СНИМАЕТСЯ В ОБЕИХ ТЕМАХ, не только в тёмной: у канона `.pcard` рамки нет
 * ни в светлой, ни в тёмной. Поэтому правило стоит на :root бренда, а не внутри dark-блока —
 * иначе я закрыл бы половину расхождения и оставил вторую жить на светлой, где её и не заметили
 * четыре партии подряд. Ядро сохраняет 2px по умолчанию: izibuh кольцо принял, платить за
 * канон forbion он не должен. */
:root {
  --ds-coupon-border-width: 0px;
  /* Рамки нет ⇒ и красить нечем: иначе зелёный слой просвечивает сквозь стекло .72. */
  --ds-coupon-ring: none;

  /* Карточка цены героя — числа канона `.price-tag` (замер 1366, тег v0.30.21-draft):
   * поля 22/26 · число 41.663px · описание 11.5px. Разложение разницы 564 против 357 —
   * в журнале: число 129 · описание 88 · поля 20 · прочее 18 · оферта −48. */
  --ds-coupon-pad: 22px 26px;
  /* 🔴 41.663 БЫЛО ЗНАЧЕНИЕМ ФОРМУЛЫ РОВНО НА 1366 — ТО ЕСТЬ НА ШИРИНЕ МОЕГО ЗАМЕРА.
     Ряд по десяти ширинам (16.08): 29 @390 · 29 @700 · 29 @950 · 30.5 @1000 · 33.55 @1100 ·
     36.6 @1200 · 40.26 @1320 · 41.663 @1366 · 43.92 @1440 · 44 @1600.
     ⇒ у канона это НЕ ЧИСЛО И НЕ СТУПЕНЬ, а ТЕКУЧАЯ величина `clamp(29px, 3.05vw, 44px)`:
     3.05 % от ширины, пол 29 (держится до 950 = 29/0.0305), потолок 44.
     ⚠ Четвёртый раз за сутки ширина замера принята за величину (после `ladder 104`,
     `srv 58`, кикера 11.5). Признак один и тот же: ровное число на всех ширинах —
     это ГИПОТЕЗА, и проверяется она РЯДОМ, а не повтором на той же ширине.
     ⚠ Вес: канон 900, наша шкала кончается на 800 — отдельным токеном, шкалу не двигаю. */
  --ds-coupon-off-size: clamp(29px, 3.05vw, 44px);
  --ds-coupon-off-weight: 900;
  /* Единица цены: канон РЕНДЕРИТ 15 (обе ширины), хотя пометка ниже цитировала 16 из его
     исходника — рендер авторитетнее цитаты, сверяем то, что видно. */
  --ds-coupon-unit-size: 15px;
  --ds-coupon-desc-size: 11.5px;

  /* 🔴 ТЕКУЧАЯ КАРТОЧКА ЦЕНЫ — вторая половина пары с сеткой `c-tpl` (`TEMPLATE v0.154.0`).
   * Ставится ПО ЕГО СИГНАЛУ, а не заранее: до сетки `100%` растёк бы карточку во всю ширину
   * блока, после — жёсткие 360 остались бы в колонке 236 и снова вытолкнули чипы.
   * Замер канона: карточка 236 на ВСЕХ ширинах 1366…2560 — её держит не собственный
   * `max-width` (330px у канона НИКОГДА не срабатывает), а колонка `1.15fr` внутри блока,
   * который сам упёрт в контейнер. Поэтому у нас `100%`: ширину задаёт колонка.
   * `min-width: 0` — не украшение: у элемента сетки умолчание `auto` = min-content, и оно
   * перебивает `max-width`. Отношение колонок 1.53 вместо 1.15 на 1024 (замер `c-tpl`) —
   * это оно. */
  --ds-coupon-max: 100%;
  --ds-coupon-min: 0;

  /* 🔴 ТЕНЬ И ФОН КУПОНА — И ОТМЕНА МОЕЙ ЖЕ ПРАВКИ ИЗ v0.190.0, ВНУТРИ ТОГО ЖЕ ДНЯ.
   * Там я подставил в `--ds-shadow-brand` канонную `--sh` (пятислойную) и написал, что значение
   * «скопировано с канона». Скопировано верно — **взято не у того носителя**:
   *     `.price-tag` (карточка цены ГЕРОЯ, наш `.ds-coupon`)  →  box-shadow: var(--glow)
   *     `.pcard`     (универсальная плитка: подарки, сервер, спицы)  →  box-shadow: var(--sh)
   * Правильный файл, неправильный носитель — класс «ошибка предмета, не арифметики», третий раз
   * за день. ⚠ И цена ошибки была шире одной карточки: `--ds-shadow-brand` читают ДЕВЯТЬ мест
   * (карточки, кнопки, калькулятор, сравнение, отзывы). Подменив бренд-токен тенью соседнего
   * носителя, я менял тень везде, где она есть, ради одного купона.
   * ⇒ Поэтому теперь у купона СВОЙ токен с умолчанием `--ds-shadow-brand`: прежний рендер цел
   * у всех, канонное значение получает только тот носитель, у которого оно замерено.
   * Фон: канон `.price-tag` держит `--glass` (наш `--ds-surface-picked`) со стеклом — в ОБЕИХ
   * темах, поэтому здесь, а не в тёмном блоке. */
  --ds-coupon-shadow: 0 10px 50px -12px rgba(112, 182, 44, 0.45);
  --ds-coupon-bg:     var(--ds-surface-picked);
  --ds-coupon-blur:   blur(16px) saturate(1.4);
}

/* ── РОЛИ КАРТОЧЕК: КАНОННЫЕ КЕГЛИ И ВЕСА (c-design, 15.08) ────────────────────
 * Замер живого: `.ds-card__title` = **18/600 у ВСЕХ** карточек — хаба, состава, промо,
 * лесенки. Канон различает пять ролей:
 *   хаб крупный 21/800 · хаб обычный 17/800 · лесенка 18/800 · состав 16/700 · промо 13.5/700
 * Сведение к одному стилю ТЕРЯЕТ РОЛЬ — третий такой случай за день после радиусов
 * (11 значений) и полей секций (6).
 * 🔴 ЗДЕСЬ, А НЕ В ЯДРЕ: это числа канона forbion; в ядре они стали бы обязательными для
 * izibuh и tezum, у которых свой макет. Ядро даёт только точку входа.
 * ⚠ Класс ставит ШАБЛОН. Пока не поставит — значения не доедут: тот же зазор, что был
 *   у `--ds-radius-card-hub`, и он закрылся за час, когда адресат был назван. */
.ds-card--hub-lg { --ds-card-title-size: 21px;   --ds-card-title-weight: 800; --ds-card-text-size: 13.5px;
                   --ds-card-title-lh: 1.14; --ds-card-title-mar-top: 4px;
                   /* 🔴 РАДИУС РАСХОДИТСЯ ТОЛЬКО У КРУПНОЙ (26 против канонных 24), у обычной
                      24 = 24 ⇒ промах по РОЛИ, а не по компоненту: в общем правиле карточки
                      искать было бы нечего. Признак дешёвый и годится впредь: расходится ОДНА
                      роль из двух — предмет в ролевом правиле. */
                   --ds-card-radius: 24px; }
.ds-card--hub    { --ds-card-title-size: 17px;   --ds-card-title-weight: 800; --ds-card-text-size: 13.5px;
                   --ds-card-title-lh: 1.14; --ds-card-title-mar-top: 4px; }
.ds-card--ladder { --ds-card-title-size: 18px;   --ds-card-title-weight: 800; --ds-card-text-size: 15px; }

/* ── КАРТОЧКА ПРЕИМУЩЕСТВА, слайд 3 «Почему мы» — числа канона (c-design, 17.08) ───────────
 * У канона узел зовётся `.wcard` и лежит в `.power-grid`; наша пара — `.ds-card--why`.
 * 🔴 ПРЕДМЕТ БЫЛ НЕ В РАЗМЕРЕ, А В КОМПОНЕНТЕ: у канона четыре карточки-преимущества,
 * у нас на том же месте навигатор из пяти ссылок. Замер (integrator-c + c-copy тег-стрипом):
 * `wcard ×4 / ссылок ×2` против `wcard ×0 / ссылок ×5`. Заголовок секции совпадает дословно —
 * то есть расходится не текст, а ТЕЛО. Поэтому это не правка чисел, а перенос компонента.
 *
 * ФОРМА КАНОНА (прогон 390/901/1366, offsetHeight и computed):
 *     плитка   radius 26 · поля 14/16 · flex row · зазор до текста 14 · align start
 *     значок   46×46 круглый, подложка и внутренний блик — ТЕ ЖЕ, что у значка карточки
 *              (сверено computed-строками) ⇒ читаю готовые токены, а не копирую
 *     глиф     22
 *     имя      14.5 / вес 700 / интерлиньяж normal
 *     текст    12.5 / 18.75 (1.5) / приглушённый, отступ сверху 3
 *     подложка «плита» — та же, что у панели доверия (см. `--ds-plate-*` выше)
 * ⚠ СЕТКА НЕ МОЯ: у канона `.power-grid` — @390 колонка, зазор 10, поле снизу 6;
 *   от 901 сетка 2×374, зазор 12. Это раскладка слайда, держатель `c-tpl`; числа отданы им. */
.ds-card--why {
  --ds-card-radius: 26px;
  --ds-card-pad: 14px 16px;
  --ds-card-border: 0;
  --ds-card-bg: var(--ds-surface-plate);
  --ds-card-shadow: var(--ds-shadow-plate);
  --ds-card-icon-size: 46px;
  --ds-card-icon-radius: 50%;
  --ds-card-icon-gap: 14px;
  --ds-card-glyph-size: 22px;   /* канон: глиф 22, общий по ядру 26 */
  /* 🔴 У ЭТИХ ТРЁХ ПИКСЕЛЕЙ БЫЛО ДВА АВТОРА, И ОТРИСОВКА ЭТО ПОКАЗАЛА. Сетка `--icon-lead`
     даёт `row-gap`, абзац — `margin-top`; оба по 3, и плитка выходила 89 против канонных 86.
     У канона механизм ОДИН: расстояние несёт сам абзац (`span { margin: 3px 0 0 }`).
     ⇒ зазор строки гашу, отступ оставляю на абзаце. Числа совпали бы и наоборот — но тогда
     мы воспроизвели бы не канон, а своё совпадение с ним. */
  --ds-card-lead-row-gap: 0;
  --ds-card-title-size: 14.5px;
  --ds-card-title-weight: 700;
  --ds-card-title-lh: normal;
  --ds-card-text-size: 12.5px;
  --ds-card-text-lh: 1.5;
  --ds-card-text-mar-top: 3px;
}

/* ── ВНУТРЕННИЕ РАССТОЯНИЯ ПЛИТКИ ЛЕСЕНКИ — ЧИСЛА КАНОНА (c-design, 17.08) ────────────────
 * 🔴 ПРЕДМЕТ — МЕХАНИЗМ, А НЕ ВЕЛИЧИНА. У канона плитка не имеет зазора вовсе: расстояния
 * несут ПОЛЯ КАЖДОГО ребёнка, и они РАЗНЫЕ — 14 · 10 · 0 · 10/2 · 8 · 16. У нас стоял один
 * `gap` 12 (фолбэк `--ds-space-3`, роль никем не заявлена) — шесть разных расстояний одним
 * числом не выражаются в принципе, поэтому «подобрать зазор» тут нельзя, только развести.
 * Вклад одного этого зазора: 60 px на плитку ниже 1100, 48 выше (там значок вне потока).
 *
 * ЗАМЕР (offsetHeight, reducedMotion, канон 1c.f7cloud.ru против живого ts.f7cloud.ru,
 * опыт подменой БАЙТОВ `site-theme.css` до разбора — не через CSSOM, см. ниже):
 *     было   @390 +76 · @901 +71 · @1366 +40   сумма модулей по секции 187
 *     стало  @390  +9 · @901 +49 · @1366 +16   сумма модулей по секции  74
 *
 * ⚠ ЧЕГО ЭТА ПРАВКА НЕ ЗАКРЫВАЕТ И ПОЧЕМУ — ЧУЖОЕ, НАЗВАНО ИМЕНЕМ:
 *   · подвал плитки: у канона текстовая ссылка 16 px, у нас `a.ds-btn--ghost` 32 в поле 12.
 *     Это РОЛЬ УЗЛА, состав разметки — держатель `c-tpl` (тот же случай уже описан в
 *     `components/card/card.css` для карточек хаба). Опыт: −22 к остатку.
 *   · поля цены `.tpl-card__price` 8/0 против канонных 10/2 — класс шаблона, не мой.
 *     🔴 Опыт: правка ОДНОЙ этой пары даёт +20 к остатку, а не минус: наши 8/0 сейчас
 *     компенсируют кнопку-подвал. Две чужие правки имеют смысл только ВМЕСТЕ.
 *   · длина текстов: канон @390 даёт 70/93/93, у нас 68/68/45. После сведения отступов
 *     знак расхождения на 390 переворачивается — это СОДЕРЖИМОЕ (`c-copy`), не вёрстка. */
.ds-card--ladder {
  --ds-card-gap: 0;              /* канон: зазора нет, расстояния — полями детей */
  --ds-card-pad: 26px;           /* канон 26 против наших 24 */
  --ds-card-title-lh: 1.14;      /* канон 20.52/18; у нас было 1.5 — та же роль, что у `hub` */
  --ds-card-icon-mar-bottom: 14px;
  --ds-badge-mar-bottom: 10px;
  --ds-badge-pad-y: 4px;         /* канон: метка 20 высотой, у нас 27 */
  --ds-card-text-mar-top: 8px;
  --ds-card-footer-mar-top: 16px;
  /* Источник канона (`concept-latest.html:633`): `.lad .for{font-size:15px;line-height:1.55;
     margin-top:8px;flex:1}`. Интерлиньяж у нас был 1.5 — рендер обеих сторон: 23.25 против 22.5.
     `flex:1` — канонный способ прижать подвал: см. разбор в `components/card/card.css`. */
  --ds-card-text-lh: 1.55;
  --ds-card-text-flex: 1;
  /* Подвал плитки: у канона `.lad .go` — прямой текст, только `margin-top:16` и никакого
     внутреннего поля (источник `:634`). Наш подвал — обёртка с `padding-top` из шкалы (12).
     Тот же приём уже применён к `hub-lg` (строка 494). Запрос `c-tpl`, проверен по источнику,
     а не по письму: граница их файла прямо запрещает им трогать `--ds-*`. */
  --ds-card-footer-pad-top: 0;/* канон держит постоянный отступ; `auto` ехал 0/56/23 */
}
.ds-card--inc    { --ds-card-title-size: 16px;   --ds-card-title-weight: 700; }
.ds-card--promo  { --ds-card-title-size: 13.5px; --ds-card-title-weight: 700; --ds-card-text-size: 12px; }

/* ── СЛОВАРЬ ПОЗИЦИЙ СФЕР (c-design, 15.08; форма предложена c-tpl) ────────────
 * Канон НЕ знает углов: координаты свободные, и три сферы стоят в ТРЁХ РАЗНЫХ секциях.
 * Проверено на 1280/1440/1920 — числа канона оказались ПРОЦЕНТАМИ, а не пикселями,
 * и воспроизводятся ровно:
 *   hero-center    left 44%  → 563.2 / 633.6 / 844.8 (канон 563.19 / 633.59 / 844.80)
 *   formats-right  right 4%  → 1156.8 / 1310.4 / 1771.2 (канон 1156.81 / 1310.41 / 1771.20)
 *   form-right     right 7%  → 1100.4 / 1249.2 / 1695.6 (канон 1100.41 / 1249.20 / 1695.61)
 * 🔴 Поэтому ни одна канонная сфера НЕ пересекает край экрана ни на какой ширине —
 * а наш прежний словарь углов с выносом −32px обрезал их ПО ПОСТРОЕНИЮ.
 * Размеры канона 110 / 72 / 90 ложатся на нашу шкалу как lg / sm / md.
 * ⚠ Классы ставит ШАБЛОН по имени места; углы (tl/tr/bl/br) уходят совсем. */
.ds-sphere--hero-center   { left: 44%;  top: 52px;  right: auto; bottom: auto; }
.ds-sphere--formats-right { right: 4%;  top: 67px;  left: auto;  bottom: auto; }
.ds-sphere--form-right    { right: 7%;  top: 75px;  left: auto;  bottom: auto; }

/* 🔴 ЗАГОЛОВОК ГЕРОЯ: ОКНО 768…900 — КАНОН ТАМ ЕЩЁ МОБИЛЬНЫЙ (15.08).
 * Канон переключает раскладку на 901, наш брейк — 768. В окне между ними канон держит
 * фиксированные 34px, а `clamp(28px, 3vw, 36px)` дал бы 28 (3vw от 768 = 23 → пол).
 * Одним `clamp` это не выразить: у канона на 901 кегль ПАДАЕТ 34 → 28, а clamp монотонен.
 * ⚠ Правило в бренд-пакете, потому что число и брейк — канонные, forbion-овские;
 * ядро остаётся с прежним умолчанием, izibuh и tezum не двигаются. */
@media (min-width: 768px) and (max-width: 900px) {
  :root { --ds-hero-title-size-md: 34px; }
}

/* 🔴 ССЫЛКИ ШАПКИ УЖИМАЮТСЯ НИЖЕ 1040 — как в каноне (15.08, замер c-tpl).
 * Канон: `font-size: 12.5px; padding: 7px 7px` ниже 1040; выше — обычный кегль.
 * У нас было 14px без полей на всех ширинах, отчего пилюля шапки на 1024 упиралась в край.
 * ⚠ Брейк 1040 — канонный, в нашей шкале его нет; поэтому правило живёт в бренд-пакете. */
@media (max-width: 1040px) {
  :root { --ds-header-link-size: 12.5px; --ds-header-link-pad: 7px 7px; }
}

/* 🔴 ПОЛЕ КОНТЕЙНЕРА 26 — ТОЛЬКО ДЕСКТОП (15.08, решение integrator-c2, вариант «в»).
 * Канон forbion держит `padding 26`, ядро — 16 (`--ds-space-4`); на 1024 разница видна глазом.
 * ⚠ ПОЧЕМУ НЕ В `:root`: планшетное значение — предмет ОКНА МЕТРИК
 * (`docs/WINDOW-container-metrics.md`), там остаток зависит и от бренда, и от брейка
 * (на планшете ядро даёт 12 ⇒ остатки 28 у forbion и 24 у izibuh). Правка в `:root` закрыла бы
 * видимое на десктопе и **обогнала окно**, оставив таблицу по брейкам ненаписанной.
 * ⇒ закрываем ровно то, что видно владельцу, и не трогаем то, что держит окно. */
/* ══ КОНТЕЙНЕР forbion: КАНОННАЯ КОРОБКА, А НЕ КАНОННОЕ ЧИСЛО (c-design, 15.08) ══════════
 * Наряд integrator-c2: контейнер содержимого у нас 1140, у канона 1088; правка на уровне
 * БРЕНДА, ядро и соседей не трогать.
 *
 * 🔴 ЧЕГО Я НЕ СДЕЛАЛ И ПОЧЕМУ — ЭТО ВАЖНЕЕ САМОЙ ПРАВКИ. Напрашивалось поставить
 * `--ds-container-max: 1088`. Ровно это `docs/WINDOW-container-metrics.md` запрещает, и запрет
 * писал я же: подгонка токена под неверную метрику **прячет дефект ядра внутрь бренда**
 * и стирает канонное число. 1140 — канон-истина (внешняя ширина секции канона), и она остаётся.
 *
 * ✅ ЧТО СДЕЛАНО ВМЕСТО: исправлена КОРОБКА, а не число. Канон считает 1140 по внешнему краю
 * (`box-sizing: border-box`, `concept-v2.2.0:77` — разбор c-design-2), у нас коробка
 * content-box, поэтому поля 26+26 вылезали НАРУЖУ: внешняя 1192, содержимое 1140.
 * С border-box те же 1140 и те же 26 дают внешнюю **1140** и содержимое **1088** — оба числа
 * канонные, и ни одно не подогнано.
 * ⚠ Правило, а не токен, и потому в бренд-пакете: `box-sizing` — это КОРОБКА, а не величина;
 * в ядре оно тронуло бы izibuh и tezum, у которых первый экран принят владельцем в текущем
 * габарите. Глобальный ресет остаётся отложенным предметом окна, с держателем.
 * 🔴 15.08, ЧАС СПУСТЯ: В ПЕРВОЙ РЕДАКЦИИ СПИСОК БЫЛ НЕПОЛОН — и это мой же класс, который
 * я в тот же день называл дважды: **правка сработала ровно на предмете, НАЗВАННОМ в селекторе**.
 * Носителей метрики в ядре ТРИ (`max-width: var(--ds-container-max)`): `.ds-section__inner`,
 * `.ds-hero__inner`, `.ds-footer__inner`. Я перечислил один и `.ds-container`.
 * Нашёл `c-ops` на живом: секция 1140/1088 border-box ✓, а герой остался 1192/1140 content-box —
 * первый экран шире прочих ровно на удвоенное поле, левый край левее на 26.
 * ⚠ И **моё несбывшееся предсказание объясняется этим же**, а не `fit-content`, как предположил
 * `c-tpl`: до героя правило просто не доехало. Он объяснял тем, чем мог.
 * ⇒ Список остаётся списком (селектор «использует токен» в CSS не выражается), но теперь его
 * держит ГЕЙТ 24: каждый носитель метрики в ядре обязан быть в этом перечне.
 * ⚠ И следствие, которое я обязан назвать смежникам сам: правый блок первого экрана и рама
 * карусели становятся уже на 52 px. Вынос стрелок ограничен фактическим гаттером (`v0.194.0`)
 * и поедет сам; носитель долей лесенки (`.ds-chip-anchor`) сузится — числа у c-tpl сместятся,
 * и это ожидаемо, а не регресс. */
/* Та же коробка, что у контейнеров: канон считает высоту поля по ВНЕШНЕМУ краю
   (`min-height: 66` при полях 13 сверху и снизу даёт рендер 70). У нас content-box давал
   66 + 26 = 92. ⚠ Число не подгоняю — правлю КОРОБКУ, как и с контейнером: подставить сюда
   44 значило бы спрятать разницу коробок внутрь величины. */
.ds-textarea {
  box-sizing: border-box;
  /* Канон: `lh: 21.025` при кегле 14.5 (= 1.45), а НЕ `normal`. Из-за этого две строки дают
     рендер 70 при `min-height: 66` — то есть 66 у канона это ПОЛ, а не высота. Моя прежняя
     пометка «канон 66 при двух строках» брала объявленное число за наблюдаемое. */
  line-height: 1.45;
}

/* Коробка поля — та же, что у комментария: канон держит `border-box` на всех контролах,
   и без этого поля 13/15 дали бы другую высоту при том же числе. */
.ds-input,
.ds-select {
  box-sizing: border-box;
}

.ds-section__inner,
.ds-hero__inner,
.ds-footer__inner,
.ds-header__inner,
.ds-container {
  box-sizing: border-box;
}
/* 🔴 `.ds-header__inner` ДОПИСАН 16.08 (сверка пометок, группа 3), и это ЧЕТВЁРТЫЙ носитель,
   уехавший из перечня по той же причине, что герой 15.08. Замер @1366: у канона и у нас
   ОДНО И ТО ЖЕ `max-width: 88%`, но канон border-box → 1202, мы content-box → 1250 (+48,
   ровно удвоенное поле 24). **Число совпадало, расходилась КОРОБКА** — глазами это не
   ловится, дифф чисел показывает «88% = 88% ✓».
   ⚠ И почему не поймал гейт 24: он судит носителей `max-width: var(--ds-container-max)`,
   а шапка носит `--ds-header-max` — **единица гейта не покрывает часть объектов**. Гейт
   зелёный и честный, объект вне его области. Расширение области — отдельным заходом,
   потому что менять предмет гейта заодно с правкой значит потерять калибровку. */

/* ── ПОЛЯ СЕКЦИЙ НА УЗКИХ: роль «tight» у канона ДЕСКТОПНАЯ (c-design, 15.08) ────────
 * Вопрос integrator-c2 после роста мобильной страницы (+269 @390). Замер канона по ряду ширин:
 *     calc  1024 · 940 → 24/24      900 · 760 · 560 · 390 → 50/58   ⇒ порог 901
 *     srv · inc  62/62 на ВСЕХ ширинах      form  96/96 на всех     ⇒ рост по ним КАНОННЫЙ
 *     обычная 50 на десктопе → 48 ниже 761  (наши 64 — отдельный предмет с ре-визой)
 * ⇒ из четырёх ролей брейк нужен ровно ОДНОЙ. Остальные три подтверждены как канон, и рост
 * страницы по ним — цена канона, а не регресс.
 * ⚠ Поля у канона АСИММЕТРИЧНЫ (50 сверху, 58 снизу) — `padding-block` принимает пару,
 * поэтому роль остаётся одним токеном, а не распадается на два. */
@media (max-width: 900px) {
  /* 🔴 ВОЗВРАТ СВОЕГО ЖЕ РЕШЕНИЯ ТАМ, ГДЕ ДЛЯ НЕГО НЕТ МЕСТА. Выше по файлу я поставил
     `nowrap` и равные доли по канону лестницы ступеней (`630×54`, пять детей по 121).
     На узком тот же набор — три подписи по 155 в контейнере 354: ряд невозможен, а равные
     доли режут «До 10 пользователей» на 40. Канон на 390 показывает то же решение:
     `.ctabs` у него `flex-wrap: wrap`, 294×159, узлов за краем ноль.
     Возвращаю умолчания ядра — перенос и ширину по содержимому. */
  /* ⚠ ОБЪЯВЛЕНИЯ ОБЯЗАНЫ ЛЕЖАТЬ В СЕЛЕКТОРЕ, А НЕ ПРЯМО В МЕДИАБЛОКЕ: первая редакция
     положила их сюда голыми, браузер отбросил весь кусок молча, и замер на собранном
     артефакте дал прежние 18 узлов за краем. Гейты этого не ловят — синтаксис валиден
     как «неизвестное правило». */
  :root {
    --ds-calc-panel-pad: 12px;   /* канон `#calc .cr` @390 */
    --ds-calc-form-pad: 18px 20px;   /* канон `#calc .cl` ниже 901 (бисекция 16.08) */
    --ds-segment-wrap: wrap;
    --ds-segment-item-flex: 0 1 auto;
    --ds-section-pad-tight: 50px 58px;
  }
}

@media (max-width: 760px) {
  :root {
    /* 🔴 ЧЕТВЁРТАЯ СТУПЕНЬ КАНОНА, КОТОРУЮ Я НЕ ВОСПРОИЗВЁЛ (замер 16.08, четыре ширины):
       поля обычной секции у канона **48 ниже 761 и 50 от 761** (порог уточнён бисекцией 759/761; сперва я написал 768 — это была ширина замера, а не порог) (`#t`, `#hub`, `#faq` — все три
       одинаково). Мой `--ds-section-pad-normal: 50px` стоял безусловно: на широком совпадал,
       на узком давал +2 на каждый край — +4 секции и +20 странице при пяти носителях.
       ⚠ Нашёл САМ, а не по наряду, и только потому, что искал ступени специально: три
       предыдущих случая научили, что ровное число на всех ширинах — это гипотеза, а не факт. */
    --ds-section-pad-normal: 48px;

    /* Лид героя ступает на том же рубеже 761, что поля секции и кикер (бисекция 16.08:
       @760 = 13px/18.2 · @761 = 14px/22.4). Третий узел на этом рубеже.
       🔴 ПЕРВАЯ ПОПЫТКА ЭТОЙ ВСТАВКИ МОЛЧА НЕ СРАБОТАЛА: я привязался к строке
       `--ds-eyebrow-size: 10px`, которую САМ ЖЕ часом раньше перенёс отсюда на роль героя.
       Замена не нашла якорь и не сделала ничего — а гейты остались зелёными, потому что
       предмет правки не объявлен нигде. Поймал РЕНДЕР: на 390 кегль остался 14. */
    --ds-hero-lead-size: 13px;
    --ds-hero-lead-leading: 1.4;

    /* 🔴 ЭТА СТУПЕНЬ ПРИНАДЛЕЖИТ ГЕРОЮ, А НЕ РОЛИ — ИСПРАВЛЕНО 16.08 ДО ВЫКЛАДКИ.
       Первая редакция ставила `--ds-eyebrow-size: 10px` при `:root`, то есть ВСЕМ кикерам.
       Перемер ВСЕХ десяти кикеров канона @390:
           #topSlider ×2 → 10px (h11)   ·   #t #calc #srv #inc #hub #faq и два без id → 11.5 (h14)
       ⇒ ступень несут ДВА узла героя, остальные восемь держат 11.5 на всех ширинах.
       Моя правка делала их 11 там, где канон даёт 14, — **регресс на восьми узлах**,
       и родился он из замера ОДНОГО узла (`document.querySelector('.eyebrow')` берёт первый,
       а первый — как раз геройский).
       ⚠ Класс мой же и записанный: проверив один элемент, о наборе заключать нельзя.
       Ступень оставлена, но с ОБЛАСТЬЮ — ниже, на роли героя. */
  }
}

@media (min-width: 768px) {
  :root { --ds-container-pad: 26px; }
}

/* 🔴 СТРЕЛКИ КАРУСЕЛИ СКРЫТЫ НИЖЕ 900 — ЧИСЛО КАНОНА (c-design, 17.08).
 * Источник канона: `@media (max-width:900px){.sarr{display:none}}`. Ядро прячет их с 640,
 * то есть в полосе 641…900 у нас есть орган, которого у канона нет.
 * ⚠ Проверено, что карусель остаётся управляемой: точки видимы на всех ширинах (3 из 3),
 * свайп у шаблона. Прятать орган, не проверив, чем он заменён, значило бы сверить вид и
 * сломать поведение. */
@media (max-width: 900px) {
  :root { --ds-carousel-arrow-display: none; }
}

@media (min-width: 1100px) {
  :root {
    /* Ступень значка ступени — канон `.lad .lic` от 1100: плита 104, глиф 48. */
    --ds-card-ladder-icon-size: 104px;
    --ds-card-ladder-glyph: 48px;
  }
}

@media (min-width: 901px) {
  :root {
    /* 🔴 ПОРОГ ИСПРАВЛЕН 16.08 С 1100 НА 901: бисекция 899/901 показала переход значка
       (44→58) и его полей (8/12→10/14) ровно на 901, а 1100 я взял из канонного медиазапроса
       `.pcard`, который управляет ДРУГИМ. Второй раз тот же промах: порог у канона был,
       но не тот, что нужен этой величине.
       🔴 СТУПЕНЬ ВЕШАЮ НА РОЛЬ, А НЕ НА `:root`. Первая редакция объявила здесь общий
       `--ds-card-icon-size`, и он не доехал вовсе: у промо-плитки размер пришпилен ролью
       `.ds-card--promo` в ЯДРЕ, а она ближе к узлу. Второй автор — и снова тот, чьё
       объявление я сам же и написал раньше.
       ⚠ Хуже того: доехав, он менял бы значки ДРУГИХ ролей (`--inc`, `--hub`), которых
       я не мерил. Ступень принадлежит промо-плитке, а не всем карточкам. */
    --ds-card-promo-icon-size: 58px;
    --ds-card-icon-inline-margin: 0 0 10px 14px;
  }
}

/* 🔴 МЕТКА-БЕЙДЖ ПО КАНОНУ — ПРАВИЛОМ В БРЕНДЕ, А НЕ ТОКЕНОМ В ЯДРЕ (15.08).
 * Замер канона: 10.5px, UPPERCASE, разрядка 0.945.
 * ⚠ Первая редакция вынесла это токенами в ядро — и СЛОМАЛА izibuh: `.ds-badge` начал
 * ЗАДАВАТЬ свойства, которых прежде не ставил, и чужой каскад (капс, разрядка 1.44) проиграл.
 * Фолбэк выглядит умолчанием, но в новом правиле он ПРИСВОЕНИЕ. Здесь правило видит только
 * forbion, и ни одно чужое свойство не появляется. */
.ds-badge {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.945px;
}


/* 🔴 МОСТ: РОЛЬ ШАБЛОНА → ТОКЕН КЕГЛЯ. `c-tpl` завёл `[data-tpl-role="legal-note"]`
   (`TEMPLATE v0.183.0`) и повесил тот же атрибут у izibuh и tezum — сноска юридическая
   у всех троих. Канонные 12 — НАШИ, поэтому связка живёт в бренд-пакете forbion:
   у соседей атрибут остаётся, а размер прежний. Объявление здесь и есть согласие
   на канонное число — та же формула, которой `c-tpl` сегодня удержал `--ds-field--row`
   в своём бренде.
   ⚠ Фолбэк — 13, а не 14: замер живого узла согласия (`ts.f7cloud.ru`, 15.08) даёт
   именно 13px/19.5. Ставить 14 значило бы «вернуть» туда, где никогда не было. */
[data-tpl-role="legal-note"] {
  font-size: var(--ds-consent-size, var(--ds-field-label-size, 13px));
}

/* 🔴 ПАНЕЛЬ ИТОГА ПЕРЕСТАЁТ КРАСИТЬСЯ, КОГДА КРАСИТ КАРТОЧКА ВНУТРИ (роль `c-tpl`, `v0.189.0`).
   Канон `#calc .cr`: колонка ПРОЗРАЧНА, а поверхность держит карточка `.tcard` 381×299
   (`rgba(255,255,255,0.72)`, radius 16). У нас красилась вся колонка 417×635 — расхождение
   было не в цвете (заливка совпадала бит в бит), а в ОБЛАСТИ окраски.

   Одно правило на обе темы, и это НЕ экономия: объявление на самом элементе побеждает
   значение, унаследованное от `:root`, в любой теме — а у панели своя тёмная
   (`rgba(35,35,29,0.68)`), и половинное снятие оставило бы плиту под карточкой в тёмной.
   Проверено опытом на обеих, не выведено.

   ⚠ Роль `--carded` объявляет ГЕНЕРАТОР шаблона, а не `:has(.ds-card--picked)` у меня:
   селектор по содержимому читал бы СЛЕДСТВИЕ и выдавал за НАМЕРЕНИЕ — положи кто-нибудь
   в панель другую `--picked` карточку, колонка молча стала бы прозрачной.
   🔴 ПОСЛЕДНЯЯ ФРАЗА ЗДЕСЬ БЫЛА НЕВЕРНА И ИСПРАВЛЕНА В v0.253.0. Я написал «izibuh со своей
   крашеной панелью не двигается» — это было верно, пока правило было МОИМ и лежало в
   бренд-пакете. Держателем стал `c-tpl` (`tpl.css`), а его правило **общее для всех брендов**:
   замер `c-tpl` показывает, что панель izibuh ТОЖЕ прозрачна. Сегодня безвредно — карточка
   внутри есть, двойной белизны нет, — но **область довода сменилась вместе с держателем**.
   ⚠ Общее отсюда: «бренд-пакет грузится только у нас» защищает **правило в бренде** и НЕ
   защищает **класс в ядре или в шаблоне**. Два похожих довода с разной областью; `c-tpl`
   поймал это же на `.ds-btn--block` и закрыл опт-ином, а не безусловным классом.
   Если izibuh должен остаться крашеным — это отдельный опт-ин у `c-tpl`; чужой бренд
   на паузе, сам не двигаю. */
/* 🔴 СТРОКА БЫЛА ЗДЕСЬ И СНЯТА В v0.251.0: у прозрачности оказалось ДВА АВТОРА.
   Ровно та же строка вышла у `c-tpl` (`TEMPLATE v0.190.0`, `tpl.css:1376`), и по признаку
   она его: селектор в пространстве `tpl-*`, класс печатает его генератор.
   ⚠ Сегодня совпадение значений безвредно; завтра один поправит своё — и величина
   разъедется МОЛЧА, без единого красного. Тот же класс, что второй автор зазора в `max()`.
   🔴 И как это вышло, для тех, кто будет читать: я написал «от меня ни тега, ни строки» —
   и приложил строку ТЕМ ЖЕ ТЕГОМ, что и комментарий об отказе её ставить.
   **Отказ, записанный рядом с исполнением, читается как исполнение.**
   Объяснение оставляю намеренно: следующий не полезет вешать сюда `:has(.ds-card--picked)` —
   селектор по содержимому читает СЛЕДСТВИЕ и выдаёт за НАМЕРЕНИЕ. */

/* Канонные размеры правой панели калькулятора (замер `#calc .cr`, 15.08, 1366).
   Пишу правилами в бренде, а не токенами у потребителя: числа канонные, значит мои,
   а `.tpl-calc__cta` — один узел, у него не бывает двух видов. izibuh не затронут:
   бренд-пакет грузится только на наших площадках.
   ⚠ Побеждает `.ds-btn--lg` ПОРЯДКОМ, не весом: специфичность равна (0,1,0), а бренд-лист
   идёт после ядра. Проверено опытом, не выведено.
   Ширину задаёт роль `.ds-btn--block` в ядре — её ставит `c-tpl` классом: у ширины
   один автор, и это не я. */
.tpl-calc__cta {
  padding: 11px 20px;
  font-size: 13px;
  /* Вес 800 — замер канона той же кнопки. Ставлю по слову integrator-c2: «замер канона
     и есть заказ»; молчать о снятом числе потому, что его не назвали в наряде, — значит
     отдавать разложение неполным. */
  font-weight: 800;
}

/* Карточка тарифа внутри прозрачной панели: канон `.tcard` — радиус 16 при общем 26.
   Роль радиуса, а не ступень: первая редакция взяла `--ds-radius-md` и дала 3 px. */
.tpl-calc__panel--carded .ds-card {
  /* Ритм карточки тарифа: у канона имя→цена 4, цена→список 9 (замер `#calc .tcard`,
     поля несут сами узлы). Зазор контейнера = 4, добор до 9 даёт `--ds-calc-includes-gap`. */
  --ds-card-gap: 4px;
  --ds-card-radius: 16px;
  --ds-card-pad: 13px 15px;   /* канон `.tcard`: поля 13/15 при общих 24 */
}

/* Пилюли «что входит всегда» — кегль канона. Замер `#calc .cr .csat span`: 10.5px,
   высота 20, фон непрозрачный белый, r=999.
   ⚠ И сразу честно о том, чего это НЕ чинит: у нас четыре подписи дают 439 при ширине 353
   (замер `c-tpl`); на 10.5 сумма станет 408 — **всё равно больше 353**, ряд останется в две
   строки. Кегль мой, длина подписей — `c-copy`. Ставлю своё, не выдавая это за починку ряда. */
.tpl-calc__pill { font-size: 10.5px; }

/* Два узла карточки тарифа — числа канона (`#calc .tcn` / `.tcp`, замер 15.08, подпись
   канона `bba96ebac217`). Узлы объявил `c-tpl` (`TEMPLATE v0.193.0`) и кеглей не поставил
   намеренно: числа канонные ⇒ держатель их я, держатель узла — он.
   ⚠ ВЕС ИМЕНИ (800) НЕ СТАВЛЮ: его уже объявил `c-tpl` в своём правиле. Канон даёт то же
   значение — и именно поэтому второй автор здесь был бы незаметен до первой правки.
   ⚠ Цвет подписи: у канона `rgb(62,112,19)`, у нас токен `--ds-text-link` = `#3F7314`
   (`rgb(63,115,20)`). Расхождение 1–3 единицы на канал, глазом неразличимо. Беру ТОКЕН,
   а не канонный литерал: связность бренда дороже совпадения со случайным значением
   в макете, и второй зелёный литерал в теме — это будущий вопрос «который из них наш».
   Объявляю это решением, а не молчу о нём. */
.tpl-calc__tariff {
  /* 🔴 ВЕС ВЕРНУЛСЯ СЮДА, ПОТОМУ ЧТО У ВЕЛИЧИНЫ ОСТАЛОСЬ НОЛЬ АВТОРОВ (нашёл `c-tpl`, 15.08:
     рендерилось 400 при каноне 800). Я написал «вес не ставлю, его уже объявил c-tpl», он снял
     своё «потому что число канонное, держатель — c-design». **Порознь оба верны, вместе —
     пусто.** И обе стороны были ЗЕЛЁНЫМИ: гейты спрашивают «объявлено ли МОЁ», а не
     «доезжает ли КАНОННОЕ».
     ⚠ Мой довод нёс непроизнесённое условие — «пока его объявляет он». Условие не было
     записано нигде, поэтому и не сработало, когда перестало быть истинным.
     ⇒ уступая величину, называй не только что снимаешь, но и КТО ОСТАЁТСЯ автором. */
  font-weight: 800;
  font-size: 21px;
  line-height: 25.62px;
  letter-spacing: -0.21px;
  color: var(--ds-text-primary);
}

.tpl-calc__price {
  font-size: 15px;
  font-weight: var(--ds-fw-bold, 700);
  line-height: 21.75px;
  color: var(--ds-text-link);
}

/* 🔴 ПЯТАЯ СТУПЕНЬ КАНОНА — И ЭТО МОИ ЖЕ СЕГОДНЯШНИЕ ЧИСЛА, СНЯТЫЕ НА ОДНОЙ ШИРИНЕ.
   Кегли карточки тарифа (`v0.259.0`) и её поля (`v0.252.0`) я взял замером на 1366 и объявил
   безусловно. Замер по восьми ширинам (16.08) показывает ступень ровно на **1024**:
       ниже:  имя 16.5 / lh normal / разрядка normal · цена 13 / normal · поля 16px 18px
       выше:  имя 21   / lh 25.62  / разрядка −0.21  · цена 15 / 21.75  · поля 13px 15px
   ⚠ Обратите внимание, что ниже порога канон снимает и `line-height`, и разрядку — то есть
   ступень не «то же самое, но мельче», а ДРУГАЯ типографика. Воспроизвожу обе половины.
   📌 Нашёл своим же вопросом «при какой ширине это число перестаёт быть верным?» — тем самым,
   которым за сутки нашлись четыре чужие ступени. Пятая оказалась моей, и это ожидаемо:
   любое число, снятое на ОДНОЙ ширине, есть гипотеза о всех остальных. */
@media (max-width: 900px) {
  .tpl-calc__panel--carded .ds-card { --ds-card-pad: 16px 18px; }

  .tpl-calc__tariff {
    font-size: 16.5px;
    line-height: normal;
    letter-spacing: normal;
  }

  .tpl-calc__price {
    font-size: 13px;
    line-height: normal;
  }
}

/* 🔴 КОРИДОР 820–900: FAQ У НАС В ДВЕ КОЛОНКИ, У КАНОНА В ОДНУ.
   Замер канона `.faq` по четырнадцати ширинам: одна колонка до 900, две с 901 — граница
   ровно та же пара `900|901`, что у карточки, значка, полей формы и раскладки калькулятора.
   У меня в ядре стоит `max-width: 819px` — то есть с 820 мы уже двухколоночные, и на
   участке 820…900 расходимся с каноном на целых 81 px ширины.

   ⚠ ПОЧЕМУ НЕ ДВИГАЮ ГРАНИЦУ В ЯДРЕ, хотя это выглядело бы чище. `.ds-faq` едет ко ВСЕМ
   брендам, а izibuh я сейчас **не могу измерить** (его площадка не отдаёт ни одного узла
   компонента). Двигать чужую раскладку вслепую нельзя — это ровно то «правка по всем
   потребителям сразу», за которое я себя ловил на `:root` и на порогах. По нашей норме
   «нечем посмотреть — это вопрос, а не вердикт»: вопрос задан, ядро не тронуто.
   ⇒ канонное поведение восстанавливаю ТОЛЬКО для forbion, в коридоре и ровно на нём.
   📌 Когда izibuh снова можно будет мерить — это кандидат на перенос в ядро одной строкой. */
@media (min-width: 820px) and (max-width: 900px) {
  .ds-faq { grid-template-columns: 1fr; }
}

/* ── ЗНАЧОК ЛЕСЕНКИ С 1100: ВНЕ ПОТОКА (c-design, 16.08, разложение `#ladder`) ──────────
 * 🔴 МОЙ ЖЕ `v0.284.0` ПОЧИНИЛ ПОЛОВИНУ ПРЕДМЕТА И ОСТАВИЛ ВТОРУЮ. Тогда я свёл РАЗМЕР
 * (канон 46 ниже 1100, 104 выше) и записал в сверке «ladder 46/46/104 ✅ сошлось» — потому
 * что сравнивал ЧИСЛА. Замер расположения:
 *     канон @1099 static 46×46  ·  @1100 position: absolute, top 18, right 18, 104×104
 *     живое @1099 static 104    ·  @1100 static 104          ← в потоке на всех ширинах
 * ⇒ у канона с 1100 значок ВЫХОДИТ ИЗ ПОТОКА и высоты карте не добавляет; у нас добавляет
 * ровно свои 104. Отсюда весь остаток `#ladder` на широком (+155 @1366).
 * ⚠ КЛАСС: «размер сошёлся» и «узел ведёт себя как у канона» — РАЗНЫЕ утверждения, и первое
 * я принял за второе в собственной сверке. Числу мало значения и ширины: у него есть ещё
 * и СПОСОБ УЧАСТИЯ В ПОТОКЕ.
 * ⚠ Область — только forbion и только эта роль: `position` в ядре сменил бы контекст
 * наложения всем карточкам трёх брендов. */
@media (min-width: 1100px) {
  .ds-card--ladder { position: relative; }
  .ds-card--ladder .ds-card__icon {
    position: absolute;
    top: var(--ds-card-ladder-icon-top, 18px);
    right: var(--ds-card-ladder-icon-right, 18px);
  }
}


/* Кикер ПЕРВОГО ЭКРАНА ниже 761 — 10px (замер: два узла `#topSlider` канона дают 10/h11,
   остальные восемь кикеров — 11.5/h14 на всех ширинах). Область — только герой. */
@media (max-width: 760px) {
  .ds-hero .ds-eyebrow { --ds-eyebrow-size: 10px; }
}


/* ── СТРЕЛКА КАРУСЕЛИ: ЗАЛИТАЯ ПИЛЮЛЯ ВМЕСТО КОНТУРА (c-design, 16.08) ────────────────────
 * 🔴 ПРЕДМЕТ — НЕ ЦВЕТ, А НАБОР СЛОЁВ. Замер канона `.sarr`:
 *     bg-color прозрачный, но красит bg-IMAGE: блик radial + зелёный linear
 *     тень: ВНУТРЕННЯЯ белая 1.5px + СПЛОШНАЯ зелёная 3px снизу · рамки НЕТ · глиф ТЁМНЫЙ
 *   у нас было: плоский #F7FAF3 · картинки нет · рамка 1px · мягкая тень-падение · глиф зелёный
 * ⇒ «прозрачная против бледной» было бы ложным диагнозом: у канона НАСЫЩЕННЫЙ круг.
 * 🔴 И ПОПРАВКА `c-ops`, принятая: `--ds-surface-silk` СЮДА НЕ ГОДИТСЯ — он БЕЛЫЙ, для светлых
 * карточек. Нужная форма у нас есть в другом экземпляре: градиент `.ds-btn`. **Класс приёма
 * я назвал верно, экземпляр — нет.** Для карточек хаба `silk` при этом годится: там светло.
 * ⚠ ЧЕГО ЭТОТ ТЕГ НЕ ДЕЛАЕТ И ГДЕ НУЖЕН ГЛАЗ: у канона глиф — ТЕКСТОВЫЙ «‹» кегль 24 вес 800,
 * инок 8×27; у нас штриховой `svg` 5×10 при толщине 2.4. Я свожу РАЗМЕР и ЦВЕТ (измеримы);
 * РИСУНОК (толщина штриха и пропорция) не свожу — он не выражается числом, которое я могу
 * проверить, и уходит на стенд отдельной строкой. */
:root {
  /* 🔴 ГРАДИЕНТ ПРАВЛЕН ПО ЗАМЕРУ `c-ops` (16.08): я взял `.ds-btn` как «нужную форму»,
     и она оказалась НЕ ТЕМ ЭКЗЕМПЛЯРОМ — у канона другой УГОЛ (без градуса, сверху вниз)
     и обе точки СВЕТЛЕЕ: 124,196,60 → 99,164,39 против наших 112,182,44 → 71,128,22. */
  --ds-carousel-arrow-bg:
    radial-gradient(95% 130% at 30% 12%, rgba(255, 255, 255, 0.45), rgba(255, 255, 255, 0) 55%),
    linear-gradient(rgb(124, 196, 60), rgb(99, 164, 39));
  --ds-carousel-arrow-border-width: 0;
  /* Третий слой — ОРЕОЛ, его у нас не было вовсе (замер канона: три слоя, у нас два). */
  --ds-carousel-arrow-shadow:
    inset 0 1.5px 0 rgba(255, 255, 255, 0.45),
    0 3px 0 #5B9624,
    0 10px 50px -12px rgba(112, 182, 44, 0.45);
}

/* Глиф: канон даёт инок 27 высотой, у нас 10 — свожу высоту, носитель оставляю `svg`
   (текстовый символ задел бы закрытое решение по доступности). */
.ds-carousel__arrow svg {
  width: var(--ds-carousel-arrow-glyph, 20px);
  height: var(--ds-carousel-arrow-glyph, 20px);
  /* Толщина штриха и форма концов — числа канона (замер `c-ops`): 1.93 против наших 2.30,
     срез ПЛОСКИЙ против скруглённого. Вторичны против размера, но предмет тот же. */
  stroke-width: 1.93;
  stroke-linecap: butt;
}

/* ── ПОДЛОЖКА КАРТОЧЕК ХАБА: приём есть, применён к одной из пяти (c-design, 16.08) ────────
 * Замер: у канона ВСЕ ПЯТЬ несут фон-картинку («шёлк») и внутреннюю белую линию; первая
 * дополнительно выделена классом `hi`. У нас «шёлк» только у первой, остальные четыре —
 * плоский #F7FAF3 с рамкой 1px и без тени.
 * ⚠ Контрфакт: `#navi` 717 → 717, высоты карточек не меняются — правка чисто визуальная.
 * ⚠ Рамку снимаю ШИРИНОЙ, а не цветом — тот же урок, что у стрелки. */
/* 🔴 ПРАВЛЕНО 16.08 ПО ЗАМЕРУ `c-ops`, И ЗДЕСЬ БЫЛИ ДВА МОИХ ДЕФЕКТА СРАЗУ.
   1. СЕЛЕКТОР ПОБЕЖДАЛ МОДИФИКАТОР. `.tpl-grid--hub > .ds-card` — специфичность 0-2-0,
      `.ds-card--highlight` — 0-1-0 ⇒ выделение первой карточки гасилось МОИМ ЖЕ правилом,
      и модификатор не работал НИГДЕ (узлов с ним 1 из 1, и он побеждён).
      **«Токен приехал» и «правило действует» — разные утверждения, между ними СПЕЦИФИЧНОСТЬ.**
   2. ТЕНЬ Я СПЛЮЩИЛ ДО ОДНОГО СЛОЯ. Канон даёт ПЯТЬ и ОДИНАКОВО всем трём карточкам
      (замер: две крупные и обычная — стек совпадает байт в байт), а у нас стек уже был
      объявлен как `--ds-shadow-silk` — я его не применил, а написал свой однослойный.
      ⇒ приём был у нас целиком, и я заменил его обеднённой копией.
   ⚠ Выделение первой у канона НЕ тенью и не фоном: стек и фон-картинка у всех пяти одни.
   Чем именно `hi` отличается — не мерил и не выдумываю; `--ds-card--highlight` просто
   перестаёт быть побеждённым, а его собственное значение остаётся как было. */
.tpl-grid--hub > .ds-card:not(.ds-card--highlight) {
  background: var(--ds-surface-silk);
}
.tpl-grid--hub > .ds-card {
  border-width: 0;
  box-shadow: var(--ds-shadow-silk);
}


/* ── ЗАГОЛОВОК КОЛОНКИ СРАВНЕНИЯ = ПИЛЮЛЯ (числа канона `.cmp .cc .ct`) ──────────────────
 * ⚠ Фон РАЗНЫЙ по колонкам и это канон, а не небрежность: на зелёной колонке пилюля
 * прозрачная, на белой — `#ECF2F2`. Одним значением не выражается.
 * ⚠ Правый текст `c-copy` — 29 символов; при кегле 11 это ≈244 px в колонке 482 ⇒ ВЛЕЗАЕТ,
 * и менять его не нужно. Проверено расчётом до правки, а не после. */
:root {
  --ds-compare-title-display: inline-block;
  --ds-compare-title-self: start;
  --ds-compare-title-size: 11px;
  --ds-compare-title-weight: 800;
  --ds-compare-title-transform: uppercase;
  --ds-compare-title-tracking: 1.1px;
  --ds-compare-title-pad: 5px 13px;
  --ds-compare-title-gap: 14px;
  --ds-compare-title-radius: 999px;
  --ds-compare-title-ink: #1D1D1B;
}
.ds-compare__col--muted .ds-compare__title { --ds-compare-title-bg: #ECF2F2; }


/* 🔴 ЭКЗЕМПЛЯР ПОЛОС ДЛЯ СЕКЦИИ СРАВНЕНИЯ (16.08, отзыв `c-ops`).
 * Мы поставили сюда экземпляр ГЕРОЯ: 360×320 при opacity .07, посадка в правый верхний
 * угол. Канонная пара `.cmp-sec` держит СВОЙ: **220×190, opacity .16, bottom −30, right −40**.
 * ⇒ расходились размер (в 1.6 раза), прозрачность (вдвое бледнее) и посадка (угол против низа).
 * ⚠ Числа взяты ИЗ РАЗМЕТКИ канона (инлайновый `style` узла), а не с рендера: `c-ops` снял
 * посадку рендером и получил «середина секции, целиком внутри», тогда как источник говорит
 * `bottom: -30; right: -40`, то есть узел ВЫХОДИТ за край. Два замера об одном узле
 * расходятся — беру авторский, а расхождение называю ему вслух. */
/* 🔴 НОСИТЕЛЬ ДЕКОРА У КАНОНА — КОЛОНКА, А НЕ СЕКЦИЯ (16.08, замер integrator-c2).
   `svg.bars` лежит внутри `div.cc.us.rev` (`position: relative`), и `bottom/right`
   отсчитываются ОТ НЕЁ. Мои числа `−30/−40`, поставленные на `::after` СЕКЦИИ, дали
   посадку x≈1186 y≈674 вместо канонных 490/301 — значение верное, ТОЧКА ОТСЧЁТА другая.
   ⚠ Седьмое условие числа: носитель · область · слой · ширина · слой темы · уровень
   объявления · ТОЧКА ОТСЧЁТА. И третий за вечер случай, когда «перенести как есть»
   ломается о контекст (после стрелок и пилюли).
   ⇒ секционный экземпляр гашу целиком, декор вешаю на колонку — как у канона.
   Проверка после: полосы от секции x=491 против канонных 490. */
.tpl-section--honest { --ds-bars-content: none; }

.ds-compare__col--highlight::after {
  content: "";
  position: absolute;
  z-index: 0;
  pointer-events: none;
  right: -40px;
  bottom: -30px;
  width: 220px;
  height: 190px;
  opacity: 0.16;
  background: var(--ds-bars-color, var(--ds-color-primary));
  -webkit-mask: var(--ds-bars-shape, none) center / 100% 100% no-repeat;
  mask: var(--ds-bars-shape, none) center / 100% 100% no-repeat;
}

/* ── ПОЛОСЫ-ПОДЛОЖКА: ДВА ОСТАВШИХСЯ ЭКЗЕМПЛЯРА (c-design, 16.08) ─────────────────────────
 * 🔴 ЧИСЛА ВЗЯТЫ ИЗ РАЗМЕТКИ КАНОНА, А НЕ С РЕНДЕРА — и разница между ними здесь реальна:
 * у секции формы рендер даёт 297×257 и left −69, а инлайновый `style` автора говорит
 *     `top:-30px; left:-70px; width:300px; height:260px; opacity:.09`
 * (расхождение даёт анимация `sanim`, масштабирующая секцию на ~1 %). Беру авторские —
 * тот же выбор, что и с полосами секции сравнения, где стороны разошлись так же.
 * ЗАМЕР ТРЁХ ЭКЗЕМПЛЯРОВ КАНОНА, все `svg.bars`, все с одним контуром 100×100:
 *     слайдер   `top:-40 right:-60  360×320 op .07`   носитель — ПЕРВЫЙ слайд
 *     сравнение `bottom:-30 right:-40 220×190 op .16` носитель — колонка   ✅ уже стоит
 *     форма     `top:-30 left:-70   300×260 op .09`   носитель — сама секция
 * ⚠ ТОЛЬКО ПЕРВЫЙ СЛАЙД, А НЕ АКТИВНЫЙ. У канона узел лежит в слайде 0 постоянно и с
 * прокруткой карусели НЕ переезжает; повесить его на `.is-active` значило бы сделать
 * декор, которого у канона нет — полосы бегали бы за экраном. */
.ds-carousel__slide:first-child::after {
  content: "";
  position: absolute;
  z-index: 0;
  pointer-events: none;
  top: -40px;
  right: -60px;
  width: 360px;
  height: 320px;
  opacity: 0.07;
  background: var(--ds-bars-color, var(--ds-color-primary));
  -webkit-mask: var(--ds-bars-shape, none) center / 100% 100% no-repeat;
  mask: var(--ds-bars-shape, none) center / 100% 100% no-repeat;
}

/* 🔴 У СЕКЦИИ ФОРМЫ ОБА ПСЕВДОЭЛЕМЕНТА ЗАНЯТЫ ВОЛНОЙ — И ЭТО ПРЕДЕЛ КОНСТРУКЦИИ, А НЕ
   МЕЛОЧЬ. Роль `--bars` рисует собой `::after` СЕКЦИИ, волна занимает `::before` (верх) и
   `::after` (низ); `scaffold` отказывает на паре `bars` + `wave` именно поэтому — и отказ
   ВЕРНЫЙ, он громко называет то, что иначе молча съело бы слой.
   ⚠ Но у канона эта секция несёт И ВОЛНУ, И ПОЛОСЫ: у него полосы — настоящий узел
   `<svg>`, а не псевдоэлемент, и предела нет вовсе. ⇒ **наша роль не выражает канонную
   страницу**, и закрываю я это переносом декора на ВНУТРЕННИЙ носитель — тем же приёмом,
   которым канон вешает полосы секции сравнения на колонку.
   ⚠ КРЮЧОК НАЗЫВАЮ ЧЕСТНО: `--pad-final` — роль ОТБИВОК, и я использую её как адрес
   декора, потому что другого устойчивого у секции нет (её `id` приходит из конфига
   потребителя). Это подмена роли, и правильный вход — носитель полос, не конфликтующий
   с волной. Держатель входа `c-tpl`, ему сказано; до тех пор экземпляр стоит здесь.
   🔴 НОСИТЕЛЬ ПСЕВДОЭЛЕМЕНТА И ТОЧКА ОТСЧЁТА — РАЗНЫЕ ВЕЩИ, И ЗДЕСЬ ЭТО РЕШАЕТ ВСЁ.
   Сперва я дал внутреннему контейнеру `position: relative` и возвращал полосы к краю окна
   через `calc((100% - 100vw)/2 - 70px)`. Замер: @390 сошлось, @1366 полосы встали на
   x ≈ −44 против канонных −64. **`100vw` считает и полосу прокрутки, поэтому выражение
   зависит от того, чего в макете нет вовсе.**
   ⇒ контейнер оставляю СТАТИЧНЫМ: тогда его `::after` отсчитывается от СЕКЦИИ (она уже
   `relative` из-за волны), и канонные `top: -30 · left: -70` работают КОНСТАНТАМИ на всех
   ширинах. Носитель нужен был только ради свободного псевдоэлемента, а не ради отсчёта. */
.ds-section--pad-final > .ds-section__inner::after {
  content: "";
  position: absolute;
  z-index: 0;
  pointer-events: none;
  top: -30px;
  left: -70px;
  width: 300px;
  height: 260px;
  opacity: 0.09;
  background: var(--ds-bars-color, var(--ds-color-primary));
  -webkit-mask: var(--ds-bars-shape, none) center / 100% 100% no-repeat;
  mask: var(--ds-bars-shape, none) center / 100% 100% no-repeat;
}


/* ── ОРГАНЫ СЛАЙДЕРА ВНЕ ПОТОКА: ВТОРАЯ ПОЛОВИНА (c-design, 16.08) ────────────────────────
 * 🔴 УСЛОВИЕ ВЫПОЛНЕНО И ПРОВЕРЕНО НА СБОРКЕ, А НЕ ОЖИДАНИЕМ. Полтора часа назад я держал
 * эту половину, потому что на ЖИВОМ `.tpl-carousel-frame` был `static`, и `absolute` увёл бы
 * органы к неизвестному предку. Собрал forbion текущим шаблоном (`scaffold.py`, `v0.231.0`)
 * и померил: рамка **`relative`** ⇒ половина `c-tpl` готова В ТЕГЕ, не доехала только выкладка.
 * ⚠ ТРЕБУЕТ `TEMPLATE ≥ v0.229.0` НА ТОЙ ЖЕ ПОВЕРХНОСТИ. Приедь этот тег раньше шаблона —
 * точки уедут к ближайшему позиционированному предку. Условие называю в теге, а не в письме:
 * письмо разминётся, тег поедет.
 * Замер на сборке @1366: точки `static` → `absolute`, от низа секции 26 → **15 = канон**,
 * `#hero` 512 → 476 (−36 = высота 6 + отступ 30, ровно как считал).
 * 📌 Остаток −62 добирает `c-tpl`: его `.tpl-slabel` (18) тоже в потоке. */
:root {
  /* Отбивки слайда: канон 52/96 ниже 901 и 36/84 с 901 (замер пяти ширин). */
  --ds-carousel-slide-pad: 52px 0 96px;
  --ds-carousel-dots-position: absolute;
  --ds-carousel-dots-bottom: 15px;
  --ds-carousel-dots-gap: 0;
}

@media (min-width: 901px) {
  :root { --ds-carousel-slide-pad: 36px 0 84px; }
}
