/*
 * f7c_template :: layout-обвязка (.tpl-*).
 * Граница с дизайн-системой — f7c_design docs/THEMING.md, раздел
 * «Граница с шаблоном»: только композиция и геометрия на токенах --ds-*;
 * никаких новых визуальных компонентов, никаких переопределений .ds-*.
 * Брейкпоинты — контрактные (sm 640 / md 768 / lg 1024 / xl 1280).
 */

/* Сетка карточек: 1 колонка → 2 → 3 */
.tpl-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--ds-space-6);
}

@media (min-width: 640px) {
  .tpl-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
  .tpl-grid { grid-template-columns: repeat(3, 1fr); }
}

/* Читабельная ширина текстовых секций */
.tpl-prose {
  max-width: 44rem;
}

.tpl-prose p {
  margin: 0 0 var(--ds-space-4);
}

/* Узкая обёртка (формы и пр.) — не растягивать на всю ширину контейнера */
.tpl-narrow {
  max-width: 32rem;
}

/* Чекбокс согласия 152-ФЗ: только компоновка, стили текста наследуются */
.tpl-consent {
  display: flex;
  gap: var(--ds-space-2);
  align-items: flex-start;
}

.tpl-consent input {
  margin-top: 0.25em;
}

/* Калькулятор: только ритм; типографика итога — семантика strong */
.tpl-calc__total {
  margin: var(--ds-space-6) 0 var(--ds-space-3);
}

.tpl-calc__disclaimer {
  margin: var(--ds-space-3) 0 0;
}

/* Замещающий текст на месте исчезнувшего по `when` поля (санкция 04.08,
   модель forbion-1c «1С:Фреш» п.4 — «Базовый»: доп. база не продаётся,
   счётчик убран, на его месте «по запросу»). Не форм-контрол — hidden
   переключается JS напрямую, без истинного удаления из DOM. */
.tpl-calc-unavailable {
  color: var(--ds-text-muted);
  font-size: 0.9em;
}

/* Раскрывашка «Ставки расчёта» в калькуляторе (не FAQ — FAQ теперь ds-faq
   дизайн-системы): только ритм, без визуальных стилей */
.tpl-disclosure {
  margin: 0 0 var(--ds-space-3);
}

.tpl-disclosure__q {
  cursor: pointer;
}

.tpl-disclosure__a {
  margin: var(--ds-space-2) 0 0;
  padding-left: var(--ds-space-4);
}

/* Аккордеон тарифов (наряд integrator-c 02.08, решение владельца: аккордеон
   вместо новой табличной секции — переиспользует .tpl-disclosure выше, здесь
   только ритм между группами и раскладка чипов). Сам <details> — нативный,
   без JS: содержимое присутствует в HTML независимо от open/closed.
   Чип .cfgc (наряд c-seo §K67/K75/K78, форма — из concept): цвет/декорация
   заданы ЯВНО, не через наследование — тот класс дефекта («правило живёт не
   в классе, а в его СИЛЕ над соседним», .ttab td a перекрашивал чип в
   концепте) здесь структурно исключён: у чипа нет table/td-контекста, где
   могло бы стоять конкурирующее по специфичности правило. */
.tpl-tariff-accordion {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-3);
}

.tpl-tariff-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-2);
}

.cfgc {
  display: inline-block;
  padding: var(--ds-space-1) var(--ds-space-3);
  border-radius: var(--ds-radius-full);
  background: var(--ds-surface-raised);
  color: var(--ds-text-primary);
  font-size: 12.5px;
  font-weight: 600;
  text-decoration: none;
  line-height: 1.4;
}

a.cfgc:hover { background: var(--ds-surface-sunken); }

/* Счётчик конфигураций (правка c-design 04.08): факт «сколько внутри»
   обязан читаться и при закрытой группе — живёт В summary, не в
   сворачиваемой части, приглушённым весом относительно цены. */
.tpl-tariff-count {
  font-weight: 400;
  color: var(--ds-text-muted);
}

/* Сноска-дисклеймер под секцией (`note` у `cards`/`text`, v0.89.0). ОДИН класс
   на всех потребителей идиомы — заводить `.tpl-cards-note` и `.tpl-text-note`
   отдельно значило бы через три релиза иметь пять почти одинаковых правил,
   которые разойдутся. Вид — как у `.tpl-compare-foot__note` (вторичный текст,
   ограниченная строка): сноска обязана читаться как сноска, а не как лид.
   Повод не косметический: юр-дистанция «цена ↔ дисклеймер» ±2 секции, и без
   слота её чинили бы перестановкой канонного порядка. */
.tpl-section-note {
  margin: var(--ds-space-4) 0 0;
  font-size: var(--ds-fs-sm);
  color: var(--ds-text-secondary);
  max-width: 44rem;
}

/* БРЕНД-ПАТТЕРН декор-слоем секции (`pattern`, v0.87.0). Слой выбран c-design:
   механизм нейтральный здесь, ассет и его правила — в бренд-пакете. Раскладка
   один-в-один с орбами: угол + ступень размера, ничего свободного (свободное
   число потребовало бы inline style, а его запрещает CSP и ловит гейт).

   🔴 ПЛОТНОСТЬ — ССЫЛКА НА ТОКЕН БРЕНДА С РАБОЧИМ ФОЛБЭКОМ, и это не лень.
   `--ds-pattern-opacity-soft/-strong` заводит c-design своим тегом; на момент
   этого релиза их в ДС ЕЩЁ НЕТ (проверил и тег v0.61.0, и её рабочее дерево —
   0 вхождений). `var(--x, 0.06)` в этом случае НЕ немой отказ: применяется
   фолбэк, эффект есть, а как только она затегает токен — её значение победит
   автоматически, без правки шаблона. Поэтому мой же токен-гейт требует
   объявления только для `var()` БЕЗ фолбэка: молча умирает именно такой,
   а не этот. */
.tpl-pattern {
  position: absolute;
  z-index: 0;
  pointer-events: none;
  width: 200px;
  height: auto;
}

.tpl-pattern--sm { width: 140px; }
.tpl-pattern--md { width: 200px; }
.tpl-pattern--lg { width: 300px; }

.tpl-pattern--soft   { opacity: var(--ds-pattern-opacity-soft, 0.06); }
.tpl-pattern--strong { opacity: var(--ds-pattern-opacity-strong, 0.12); }

.tpl-pattern--tl { top: 0; left: 0; }
.tpl-pattern--tr { top: 0; right: 0; }
.tpl-pattern--bl { bottom: 0; left: 0; }
.tpl-pattern--br { bottom: 0; right: 0; }
.tpl-pattern--c  { top: 50%; left: 50%; transform: translate(-50%, -50%); }

/* ОБЩИЙ CTA под рядом карточек (`cards.cta`, v0.86.0). Одно действие на все
   карточки ряда — центрируем под сеткой, отступ ритмом секции. Кнопка своих
   размеров не получает: она ядровая `.ds-btn--lg`, шаблон задаёт только МЕСТО.
   Тот же раздел труда, что у орбов: размещение моё, вид — ядра. */
.tpl-cards-cta {
  display: flex;
  justify-content: center;
  margin-top: var(--ds-space-6);
}

/* ТАБЛИЧНАЯ ФОРМА тарифного блока (form:"table", наряд integrator-c2 11.08,
   решение владельца «таблица, как в прототипе»; CALC-MODEL.md §4-бис).

   🔴 ЗДЕСЬ Я СНОШУ СВОЮ ЖЕ СТРУКТУРНУЮ ЗАЩИТУ, И ЭТО НАДО ЧИТАТЬ ВМЕСТЕ
   С КОММЕНТАРИЕМ ВЫШЕ. Там сказано: дефект «.ttab td a перекрашивал чип»
   (кегль 12.5→13.5, вес 600→800, цвет чернильный→зелёный, ширина 139→151 —
   замер c-design в концепте) исключён СТРУКТУРНО, потому что у чипа нет
   table/td-контекста. Таблица этот контекст ВОЗВРАЩАЕТ — значит структурной
   защиты больше нет, и на её место обязана встать проверяемая:
     1. я НЕ пишу ни одного правила вида `.ttab td a` / `.ttab a` — по
        построению нет конкурента, который перебил бы `.cfgc` по специфичности
        (у `.cfgc` (0,1,0), у `.ttab td a` было бы (0,1,2) и оно бы выиграло);
     2. `.cfgc` выше задаёт цвет, кегль, вес и декорацию ЯВНО, а не
        наследованием — то есть даже унаследованные от таблицы значения до
        чипа не доходят;
     3. проверка — НЕ рассуждением: тест сверяет обе формы на СМЕШАННОМ
        наборе чипов (часть с href, часть без), а равенство computed
        снимается рендером. Структурный довод здесь недостаточен by design:
        он и в прошлый раз звучал убедительно.
   Тот, кто соберётся добавить сюда `.ttab td a { … }`, — прочти пункт 1
   и сначала объясни, почему чип это переживёт. */
.tpl-ttab-wrap {
  /* Три колонки на 360px не помещаются. Прокрутка обязана жить ЗДЕСЬ, иначе
     таблица роняет горизонтальный скролл ВСЕЙ страницы — дефект, невидимый
     для boundingBox секции (переполнение вытекает за коробку, коробка в норме). */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.ttab {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
}

.ttab th,
.ttab td {
  padding: var(--ds-space-3);
  border-bottom: 1px solid var(--ds-border-default);
  vertical-align: top;
}

.ttab thead th {
  font-size: 13px;
  font-weight: 600;
  color: var(--ds-text-muted);
  white-space: nowrap;
}

.ttab tbody th[scope="row"] {
  font-weight: 700;
  color: var(--ds-text-primary);
  white-space: nowrap;
}

.ttab small {
  font-size: 12px;
  font-weight: 400;
  color: var(--ds-text-muted);
}

/* Выделенная ступень («выбирают чаще всего») — фон строки, не цвет текста:
   перекраска текста поехала бы по наследованию в чипы (см. блок выше). */
.ttab tr.hi {
  background: var(--ds-surface-raised);
}

/* Метка ступени. Цвет — `--ds-color-accent` (тем же токеном красит акцентный
   текст ядро: badge/mark). ⚠ Изобретённый токен здесь стоил бы молча: неизвестная
   var делает объявление НЕВАЛИДНЫМ, свойство просто не применяется — ни ошибки,
   ни красного гейта. Поймал на себе в этой же правке: писал `--ds-text-accent`
   и `--ds-border-muted`, в ДС нет ни того, ни другого. */
.rmark {
  display: block;
  margin-top: var(--ds-space-1);
  font-size: 12px;
  font-weight: 600;
  color: var(--ds-color-accent);
  white-space: nowrap;
}

/* Ячейка состава: те же flex-правила, что у аккордеонной .tpl-tariff-chips —
   раскладка чипов одна на обе формы, различается только обёртка строки. */
.cfgcell {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-2);
  min-width: 22ch;
}

/* Карусель героя (hero.slides[]): контейнер/слайды/точки/стрелки и их состояние
   .is-active — теперь ВЛАДЕЕТ ЯДРО ДС (components/carousel/carousel.css, DESIGN
   v0.19.0). Здесь остаётся только раскладка панели внутри слайда (зона шаблона):
   центрируем ds-компонент (купон/аудит). Две площадки, один хелпер:
   1) слайд БЕЗ copy — панель центрируется на всю площадь слайда (как было);
   2) слайд С copy (v0.40.0) — обёртка внутри .ds-hero__media центрирует панель
      в ПРАВОЙ КОЛОНКЕ, паритет с эталоном (.promo-visual{justify-content:center},
      сверка c-design-2). Центруем именно обёрткой, а не флексом на самом
      .ds-hero__media: тот глобально сломал бы .ds-media-stack{margin-left:auto}
      слайда-1 — чат-сцена уехала бы от правого края. */
.tpl-carousel__panel {
  display: grid;
  place-items: center;
  min-height: 100%;
  /* 🔴 ГАТТЕР КОНТЕЙНЕРА — обязателен, а не косметика (c-design, контракт купона
     v0.44.0). Декор ядра намеренно торчит наружу: .ds-coupon__hole вынесен на
     -min(15px, --ds-container-pad). Канон это не переполняет, потому что купон
     стоит В КОНТЕЙНЕРЕ, и вылет уходит в его поле.
     Слайд С `copy` рендерится через .ds-hero__inner — там паддинг есть. А ЭТА
     ветка (панель БЕЗ копи-колонки) клала панель голой: поля нет → вылет упирался
     во вьюпорт и давал горизонтальный скролл на узких. Я сам померил это на своей
     фикстуре и передал c-design как ДЕФЕКТ ЯДРА — но корень был здесь, в моей
     разметке (izibuh чист именно потому, что у него слайды с copy).
     Поле даём здесь: «плейсмент — зона шаблона», ядру незачем знать, кто его
     обернул.
     🔴 ТОЛЬКО на --bare: у слайда С `copy` поле уже даёт .ds-hero__inner, и общий
     padding удвоил бы гаттер (16+16=32) — замер izibuh @360 показал сужение
     купона 396→364. Вопрос задал c-design, подтвердил замером я. */
}

.tpl-carousel__panel--bare {
  padding-inline: var(--ds-container-pad);
}

/* Рамка карусели — сужает ЯДРОВУЮ .ds-carousel до фактической контент-ширины,
   чтобы вынос стрелки (.ds-carousel__arrow left/right:-54px @≥1200px, оффсет ядра)
   лёг в боковое поле, а не за вьюпорт. Секция полноширинная (фон), поэтому
   несуженная .ds-carousel растягивалась бы во всю ширину и стрелки уезжали за
   экран (замер c-design-2 на корне: prev −54, next 1493). Сужаем шаблонной
   обёрткой, НЕ оверрайдя .ds-* (§2).
   ⚠ Ширина = fit-content, НЕ var(--ds-container-max): ядровый .ds-hero__inner —
   grid (1.05fr 0.95fr), его min-content ПРЕВЫШАЕТ --ds-container-max (замер: токен
   1100, реальная колонка 1132 — max-width у грида не зажимает min-content). Рамка
   с фикс-токеном 1100 сдавила бы герой на 32px (регресс). fit-content ужимает
   рамку по НАТУРАЛЬНОЙ ширине содержимого — колонка не едет (1132→1132), стрелки
   садятся в гаттер относительно ИСТИННОГО края, и это отслеживает контент, а не
   прибитое число. max-width:100% — фолбэк на узких (< контент-ширины). */
.tpl-carousel-frame {
  width: fit-content;
  max-width: 100%;
  margin-inline: auto;
}

/* Отзывы-strip (reviews.paged, concept-v1.7.2): горизонтальный скролл-вьюпорт с
   листанием на ЯДРОВОЙ стрелке .ds-carousel__arrow (её визуал/позиция берём из
   ядра). Здесь — только раскладка strip'а (зона шаблона) + состояние гашения
   стрелки на краю: скоуплено в .tpl-reviews + data-tpl-off, чтобы НЕ рестайлить
   глобально DS-класс. Без JS вьюпорт скроллится/свайпается нативно. */
.tpl-reviews { position: relative; margin-top: var(--ds-space-6); }

.tpl-reviews__viewport {
  overflow-x: auto;
  scroll-behavior: smooth;
  scroll-snap-type: x proximity;
  scrollbar-width: none;               /* Firefox */
}
.tpl-reviews__viewport::-webkit-scrollbar { display: none; }

.tpl-reviews__track {
  display: flex;
  gap: var(--ds-space-4);
  width: max-content;
}

.tpl-reviews__track > .ds-review {
  width: var(--ds-marquee-item-width, 340px);   /* тот же токен, что у ленты */
  flex-shrink: 0;
  scroll-snap-align: start;
}

/* гашение стрелки на краю — template-состояние, скоуплено внутри .tpl-reviews */
.tpl-reviews .ds-carousel__arrow[data-tpl-off] {
  opacity: 0;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .tpl-reviews__viewport { scroll-behavior: auto; }
}

/* Лого в подвале (плейсмент — зона шаблона; ассет/вариант — владелец бренда).
   Только раскладка: инлайн-блок + отступ до описания. Визуал лого — из ассета. */
.tpl-footer-logo {
  display: inline-block;
  margin-bottom: var(--ds-space-3);
}

/* 🔴 Мобильный горизонтальный скролл (замер c-ops playwright@360, воспроизвёл:
   docScrollWidth=416 при vw=360, +56px). Причина: подвальное лого несёт АТРИБУТЫ
   width/height из logo.display.footer пакета (izibuh 400×92) — они обязательны
   (анти-CLS, P1.6 c-seo), но без max-width дают min-content 400px, и 1fr-трек
   .ds-footer__inner растягивает контейнер за вьюпорт. Глобального img-ресета в
   ЯДРЕ нет (шапку ядро клампит точечно с DESIGN v0.26.0, подвал — нет).
   Клампим СВОЁ лого (наш класс, наша разметка — плейсмент подвала зона шаблона),
   ядро не оверрайдим. height:auto обязателен в паре: без него атрибутная высота
   92px осталась бы при сузившейся ширине и лого исказилось бы. */
.tpl-footer-logo img {
  max-width: 100%;
  height: auto;
}

/* Дисклеймер У ЦЕНЫ в split-панели (v0.65.0, условие входной визы c-legal).
   Стоит ПОД ядровым __foot (цена ↔ кнопка) — тот flex-ряд, третий элемент внутри
   встал бы в строку с ценой.
   🔴 Цвет — ТА ЖЕ идиома, что у ядрового .ds-split-panel__lead:
   color-mix(on-primary 80%). Не изобретаю свой уровень контраста и не беру
   --ds-text-muted: панель тёмная градиентная, а on-primary парен к ней по норме
   п.12 (у forbion on-primary ЧЁРНЫЙ — литерал #fff сломал бы его).
   Кегль sm, не xs: это юридическое примечание, его обязано быть видно. */
.tpl-split-note {
  margin: var(--ds-space-4) 0 0;
  font-size: var(--ds-fs-sm);
  color: color-mix(in srgb, var(--ds-color-on-primary) 80%, transparent);
}

/* Лид секции (наряд D-4 п.2). В ядре есть только .ds-hero__lead — секционного
   нет, а заводить визуальный компонент шаблону нельзя (CONTRACT §2), поэтому
   здесь только композиция на токенах, ритм как у ядрового лида героя. */
.tpl-section-lead {
  max-width: 40rem;
  margin: var(--ds-space-3) 0 0;
  color: var(--ds-text-secondary);
  font-size: var(--ds-fs-lg);
  line-height: var(--ds-lh-loose);
}

/* Карточка с НОМЕРОМ-МЕТКОЙ (v0.70.1, вердикт c-design-2 по канону
   concept-izibuh-v2.3.0: `.card + card-num`). Номер — ТЕКСТ в углу, иконка
   ПЕРВОЙ в потоке.
   🔴 Почему не ядровый .ds-card--step: его счётчик-кружок ::before стоит В
   ПОТОКЕ сверху и выталкивает иконку вниз на 69px — это и был дефект блока
   «Что берёт главбух». Ядро не трогаем: --step ВЕРЕН для «Недели» (там иконок
   нет), правка ядра сломала бы соседний блок.
   Здесь только КОМПОЗИЦИЯ: position + типографика на токенах. Новый визуальный
   компонент не заводится, `.ds-card` не переопределяется — `position:relative`
   висит на МОЁМ классе, добавленном к тому же элементу.
   Смещения 22/24px — из канона дословно (24 = --ds-space-6; для 22 точного
   токена нет, канон-паритет важнее округления до шкалы). */
.tpl-card--num {
  position: relative;
}

.tpl-card-num {
  position: absolute;
  top: 22px;
  right: var(--ds-space-6);
  font-size: var(--ds-fs-sm);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-text-muted);
  line-height: 1;
}

/* Выравнивание строк FAQ (S3, вердикт владельца: TOP-anchor). Свёрнутые summary
   разной длины (1 строка vs 2) давали разную высоту → ряды не выровнены (замер
   c-ops-2: 53 vs 74). Равняем к 2 строкам min-height'ом; первые строки вопросов
   встают на один уровень, номер (.ds-faq__num, top:15 у первой строки) — вровень.
   🔴 min-height:2lh — content-box (в ядре border-box нет): 42 контента + 32
   паддинга ядра = 74; НЕ 84 (тот при content-box дал бы 116 — box-sizing).
   align-items — СЕГОДНЯ не несущий (A/B-замер playwright, v0.52.0, izibuh-тема:
   flex-start и ядровый baseline дают ИДЕНТИЧНО boxH=74, текст=18, номер=15 и на
   1-, и на 2-строчном summary — байт-в-байт). Причина: единственный in-flow
   flex-элемент здесь — текст (номер absolute, шеврон align-self:center), а для
   одного baseline-элемента baseline ≡ flex-start. Ядро на v0.52.0 = baseline
   (center был лишь в откаченном v0.53.0). Фиксирую start ЯВНО как робастность:
   держу izibuh-намерение «первая строка» независимо от дефолта ядра, если в
   summary появится второй in-flow элемент иной высоты. Это вид, решённый
   владельцем, а не расчёт на текущее значение ядра.
   min-height аддитивен (в ядре его нет), align-items — по указанию integrator-c
   в мой слой (развилка «в шаблон», не в ядро). */
.tpl-faq-q {
  min-height: 2lh;
  align-items: flex-start;
}

/* Визуально скрыто, семантически ЕСТЬ (sr-only). Для осиротевшего label
   поля-матрицы (v0.71.0): с JS оси подписаны легендами сегментов, обёрточный
   заголовок «стаканит»; но БЕЗ JS единственный контроль — <select>, и подпись
   ему нужна. Прячем визуально, оставляем скринридеру и no-JS-семантике.
   Стандартный sr-only-паттерн (clip-rect), не display:none — иначе label
   выпал бы и из доступности тоже. */
.tpl-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Матрица калькулятора (зависимые оси, RFC): SSG-база — один select валидных
   пар; JS enhance'ит в два сегмента. Здесь только раскладка — стили сегмента и
   инпутов приходят из дизайн-системы; гашение несовместимой опции — по классу
   .is-disabled (aria-disabled ставит JS), не inline-style. */
.tpl-matrix {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-4);
}

.tpl-matrix__axis .ds-field__label {
  margin-bottom: var(--ds-space-2);
}

.ds-segment__btn.is-disabled {
  opacity: .4;
  cursor: not-allowed;
}

/* Калькулятор v0.5: смета и заголовки вариантов (табы — прогрессивное улучшение) */
.tpl-calc__lines {
  margin: var(--ds-space-3) 0 0;
  padding-left: var(--ds-space-4);
}

.tpl-calc__variant-title {
  cursor: pointer;
  margin: var(--ds-space-6) 0 var(--ds-space-3);
}

.tpl-calc__variant-title--active {
  text-decoration: underline;
}

/* Плавный скролл к якорям — поведение страницы (зона шаблона, согласовано
   с c-design); гасится предпочтением пользователя */
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

/* Honeypot-поле формы (антиспам c-api): визуальное скрытие без display:none
   и без inline-style; вне таб-порядка и вне aria-дерева */
.tpl-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* 🔴 [hidden] ОБЯЗАН ГАСИТЬ (v0.55.0). Браузерный `[hidden]{display:none}` имеет
   специфичность (0,1,0) и ПРОИГРЫВАЕТ любому компонентному правилу с display:
   `.ds-calc__includes li{display:flex}` = (0,1,1) перебивает его → скрытая строка
   состава остаётся ВИДНОЙ. c-ops поймал рендером на превью: на ОСН показаны
   строки УСН/АУСН — ЛОЖНЫЙ состав платной услуги. Баг прошёл ТРИ итерации, потому
   что мерили HTML-атрибут (он есть), а не РЕНДЕР (display) — мой же класс
   «генерация ≠ исполнение».
   Чиним КЛАСС, а не инстанс: единое правило на ВСЕ [hidden] (стандартный
   reset-приём, как в normalize). Задевает и тумблер темы (.tpl-theme-sw —
   display:inline-flex, показывался бы в SSG без JS), и любой будущий hidden на
   компоненте с display. !important здесь ЗАКОНЕН: у [hidden] нет валидного
   состояния «скрыт И виден» — это семантический контракт, а не борьба стилей.
   JS-энхансмент не задет: он УБИРАЕТ атрибут (prev.hidden=false), правило
   перестаёт матчиться. Слайды карусели не [hidden] (они .is-active+opacity) —
   кроссфейд цел. */
[hidden] { display: none !important; }
/* Defense-in-depth (v0.58.0, запрос c-ops): scoped-дубль на строки состава.
   Глобальное правило выше УЖЕ гасит их — доказано на DESIGN v0.32.0
   (getComputedStyle=none, выигравшее правило «[hidden] !important»): `!important`
   бьёт специфичность безусловно, а `.ds-calc__includes li{display:flex}` —
   (0,1,1) БЕЗ важности. Это правило — страховка на случай, если ядро когда-то
   добавит `display:…!important` (тогда при РАВНОМ !important победит бОльшая
   специфичность (0,2,1) этого селектора). Сегодня оно избыточно, но стоит
   дёшево и закрывает класс окончательно. */
.ds-calc__includes li[hidden] { display: none !important; }

/* ── ЛОГО ШАПКИ ПО ТЕМЕ: механика УШЛА В ЯДРО (DESIGN v0.29.0).
   Здесь были свои .tpl-logo--light/--dark с теми же правилами — это был ДУБЛЬ:
   два источника истины о том, кто виден в тёмной. c-design прав по слою:
   «шаблон даёт data-theme, ядро даёт палитру» (граница v0.25.0). Рендер теперь
   эмитит классы ядра .ds-header__logo-light/-dark, правил здесь нет.
   Один вопрос — один механизм. */

/* Кнопка действия в панели итога (v0.50.0). Панель — flex-колонка (ядро), и
   кнопка обязана быть ВНИЗУ: посетитель дочитал цифру → действие под рукой.
   `margin-top:auto` прижимает её к низу, а заодно съедает часть пустоты между
   строками и низом панели. ⚠ Пустоту это НЕ лечит целиком: в каноне высоту
   держит растягивающийся блок «что входит» (.calc-includes{flex:1}) — его в
   ядре нет, наряд у c-design. Не выдаю полумеру за решение.
   Инверсия цвета: панель тёмная/градиентная, поэтому кнопка светлая (как в
   каноне: .calc-out .btn{background:#fff}) — на токенах, без своих цветов. */
.tpl-calc__cta {
  margin-top: auto;
  align-self: flex-start;
  /* 🔴 v0.51.1: было var(--ds-surface-page) — он ПЕРЕВОРАЧИВАЕТСЯ в тёмной теме
     (#ffffff → #1a1e27), а панель под кнопкой --ds-gradient-panel НЕ
     переворачивается (её нет в тёмном блоке ядра). В тёмной теме получалась
     тёмная кнопка на тёмной панели. Тот же корень, что у лого шапки: поверхность
     ВСЕГДА тёмная, значит и контент на ней обязан быть стабильным, а не
     «страничным».
     Берём ПАРУ on-primary/primary — ту же, которой панель красит свой текст
     (норма п.12: ломается пара, а не значение; у forbion on-primary ЧЁРНЫЙ
     намеренно, и пара это учитывает — фиксированный #fff сломал бы его). */
  background: var(--ds-color-on-primary);
  color: var(--ds-color-primary);
  box-shadow: none;
}
.tpl-calc__cta:hover { opacity: 0.9; }

/* ── ПОЛОСКА ПОТОЛКА (v0.48.0, наряд integrator-c; канон concept-v2.1.0):
   часы + tel: + переключатель темы. НЕ sticky (требование наряда).
   Классы ШАБЛОННЫЕ: компонента topbar в ядре ДС нет (проверено на v0.26.0),
   изобретать ds-* из шаблона нельзя. Стиль — только на токенах, поэтому
   тёмная тема ядра красит полоску сама, без единого своего цвета. */
.tpl-topbar {
  background: var(--ds-surface-sunken, var(--ds-surface-raised));
  border-bottom: 1px solid var(--ds-border-default);
  font-size: var(--ds-fs-xs);
  color: var(--ds-text-muted);
}

.tpl-topbar__in {
  max-width: var(--ds-container-max);
  margin: 0 auto;
  padding: var(--ds-space-2) var(--ds-container-pad);
  display: flex;
  align-items: center;
  gap: var(--ds-space-4);
  flex-wrap: wrap;
}

/* часы занимают свободное место, tel: и переключатель прижаты вправо */
.tpl-topbar__hours { flex: 1 1 auto; min-width: 0; }

.tpl-topbar__tel {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-1);
  color: var(--ds-text-primary);
  text-decoration: none;
  font-weight: var(--ds-fw-bold);
  white-space: nowrap;
}
.tpl-topbar__tel:hover { color: var(--ds-color-primary); }

/* Переключатель темы: нативный checkbox + рисованная «капсула».
   Сам input оставляем доступным клавиатуре (не display:none) — прячем
   визуально, фокус ловим на капсуле через :focus-visible + . */
.tpl-theme-sw { position: relative; display: inline-flex; cursor: pointer; }
.tpl-theme-sw input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}
/* Тумблер темы по КАНОНУ (v0.60.0, спека c-design-2): скруглённый КВАДРАТ 34×34
   с ЛУНОЙ, на checked заливается брендовым градиентом. Было — iOS-пилюля.
   ⚠ Луна — через `mask` + `background-color` ТОКЕНОМ, а НЕ `background-image:
   data:` с литеральными цветами (как в исходной спеке): так луна ТЕМИЗИРУЕТСЯ
   (--ds-text-muted флипается в тёмной), а не прибита к #5b6178, и CSP чист
   (mask data: под `img-src 'self' data:`, цвет — обычное свойство). Тот же приём,
   что «шеврон маской» в ядре. Визуал канона идентичен. Маппинг c-design-2:
   surface→--ds-surface-raised, line→--ds-border-default, grad→--ds-gradient-brand,
   pink-soft→--ds-color-accent, cobalt→--ds-border-focus. */
.tpl-theme-sw__box {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  border: 1.5px solid var(--ds-border-default);
  background: var(--ds-surface-raised);
  display: grid;
  place-items: center;
  transition: background var(--ds-anim-pop-duration, .18s) ease,
              border-color var(--ds-anim-pop-duration, .18s) ease;
}
.tpl-theme-sw__box::after {
  content: "";
  width: 17px;
  height: 17px;
  background-color: var(--ds-text-muted);
  -webkit-mask: var(--tpl-moon) no-repeat center / 17px;
  mask: var(--tpl-moon) no-repeat center / 17px;
  transition: background-color var(--ds-anim-pop-duration, .18s) ease;
}
/* луна-маска (fill=none stroke — как в каноне); цвет даёт background-color выше */
.tpl-theme-sw__box {
  --tpl-moon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z'/%3E%3C/svg%3E");
}
.tpl-theme-sw:hover .tpl-theme-sw__box { border-color: var(--ds-color-accent); }
.tpl-theme-sw input:checked + .tpl-theme-sw__box {
  background: var(--ds-gradient-brand);
  border-color: transparent;
}
/* луна на градиенте: цвет-на-primary (у forbion он ЧЁРНЫЙ — норма п.12, не #fff) */
.tpl-theme-sw input:checked + .tpl-theme-sw__box::after {
  background-color: var(--ds-color-on-primary);
}
.tpl-theme-sw input:focus-visible + .tpl-theme-sw__box {
  outline: 2px solid var(--ds-border-focus);
  outline-offset: 2px;
}

/* ── ОКНО ЗАЯВКИ (v0.48.0): нативный <dialog>. Esc/focus-trap/inert фона даёт
   браузер — своего не пишем. Без JS окна нет вовсе, а CTA ведёт якорем к форме
   (честная деградация, требование c-design-2). */
.tpl-lead {
  border: 0;
  padding: 0;
  border-radius: var(--ds-radius-xl, 30px);
  background: var(--ds-surface-page);
  color: var(--ds-text-primary);
  box-shadow: var(--ds-shadow-lg);
  max-width: min(92vw, 32rem);
  width: 100%;
}
.tpl-lead::backdrop { background: rgb(0 0 0 / 0.45); }
.tpl-lead__inner { position: relative; padding: var(--ds-space-8); }

.tpl-lead__close {
  position: absolute;
  top: var(--ds-space-4);
  right: var(--ds-space-4);
  border: 0;
  background: transparent;
  color: var(--ds-text-muted);
  font-size: var(--ds-fs-md);
  line-height: 1;
  padding: var(--ds-space-2);
  cursor: pointer;
  border-radius: var(--ds-radius-full);
}
.tpl-lead__close:hover { color: var(--ds-text-primary); }

.tpl-lead__title { margin: 0; font-size: var(--ds-fs-xl); }
.tpl-lead__sub {
  margin: var(--ds-space-1) 0 var(--ds-space-4);
  font-size: var(--ds-fs-sm);
  color: var(--ds-text-muted);
}

/* Снимок калькулятора: показываем посетителю ровно то, что уедет с формой —
   скрытое поле, о котором он не знает, было бы нечестным. */
.tpl-lead__ctx {
  margin: 0 0 var(--ds-space-4);
  padding: var(--ds-space-3) var(--ds-space-4);
  border-radius: var(--ds-radius-md, 12px);
  background: var(--ds-surface-sunken, var(--ds-surface-raised));
  font-size: var(--ds-fs-xs);
  color: var(--ds-text-muted);
}

@media (max-width: 479px) {
  .tpl-lead__inner { padding: var(--ds-space-6); }
}

/* Группа полей калькулятора (fieldset): сброс рамки + вертикальный ритм.
   ВНУТРЕННИЙ ритм (v0.40.0, замерка c-ops на живом dvl): fieldset по дефолту
   display:block — дочерние .ds-field шли встык, зазор 0px (range-поле низом
   ровно в подпись «Сотрудников»: bottom 2188 == top 2188, константа на всех
   ширинах 360…2560). 24px существовали только МЕЖДУ tpl-group (grid gap
   .ds-calc__form). Лечим сеткой с тем же шагом --ds-space-6 (=1.5rem/24px),
   чтобы ритм внутри группы совпадал с ритмом между группами.
   NB: гипотеза про float:right у .ds-range__value ОПРОВЕРГНУТА замеркой —
   float контейнится (.ds-field держит h=83), в ядро ДС не эскалируем. */
.tpl-group {
  border: 0;
  margin: 0 0 var(--ds-space-4);
  padding: 0;
  display: grid;
  row-gap: var(--ds-space-6);
}

/* 🔴 ПАРНАЯ РАСКЛАДКА ПОЛЕЙ (канон concept-izibuh-v2.3.0 `.calc-row`:
   grid-template-columns: 1fr 1fr — поля идут ПАРАМИ в ряд).
   Было `grid-template-columns: none` → каждое поле на ВСЮ ширину, и справа от
   узкого степпера оставалась пустая зона (её обвёл владелец; замер c-ops-2
   воспроизвёл на 768 и 1440, обе темы; на 360 расхождения нет).
   Легенда группы (`<legend>`) обязана занимать ряд целиком — иначе она встала
   бы первой ячейкой пары и утащила поле к себе в строку.
   Ниже 640 — столбик, как в каноне на 360. */
@media (min-width: 640px) {
  .tpl-group {
    grid-template-columns: 1fr 1fr;
    column-gap: var(--ds-space-6);
  }
  .tpl-group > legend,
  .tpl-group > .tpl-field--wide {
    grid-column: 1 / -1;
  }
}

/* Мелкая сноска-дисклеймер копи-колонки слайда карусели (hero.slides[].copy.note,
   эталон concept-v1.7.3: «не публичная оферта · условия акции — в договоре»).
   Шаблонный класс: компонента в ядре ДС нет; стиль — только на токенах. */
.tpl-hero__note {
  margin: 0;
  font-size: var(--ds-fs-xs);
  color: var(--ds-text-muted);
}

/* Форма-заявка «cta-final»: ТЁМНАЯ ГРАДИЕНТНАЯ КАРТОЧКА (как в концепте) —
   заголовок + инфо-колонка + форма + дисклеймер внутри скруглённого блока.
   Фон — бренд-токен --ds-gradient-panel, текст белый. */
.tpl-cta-card {
  position: relative;
  overflow: hidden;
  border-radius: var(--ds-radius-xl, 30px);
  padding: var(--ds-space-12);
  background: var(--ds-gradient-panel, var(--ds-surface-inverse));
  color: var(--ds-text-inverse);
  box-shadow: var(--ds-shadow-lg);
}

.tpl-cta-card > .ds-section__title { color: var(--ds-text-inverse); margin-top: 0; }

/* Мобиль (аудит под адаптив ДС v0.13.0): крупный внутренний паддинг cta-карточки
   ужимается — на узком экране --ds-space-12 давил контент. Скролла не давал
   (сетка внутри — minmax(min(100%,…))), это ритм, а не переполнение. */
@media (max-width: 479px) {
  .tpl-cta-card { padding: var(--ds-space-6); }
}

.tpl-cta {
  display: grid;
  /* auto-fit: две колонки, как только помещаются (~2×22rem), иначе одна. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: var(--ds-space-8);
  align-items: start;
}

@media (min-width: 1024px) {
  .tpl-cta { gap: var(--ds-space-12); }
}

.tpl-cta__info {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-6);
}

.tpl-cta__lead { margin: 0; max-width: 34rem; opacity: .82; }

/* Поля формы на тёмной карточке: белые инпуты, светлые подписи/текст */
.tpl-cta-card .ds-field__label { color: var(--ds-text-inverse); }
.tpl-cta-card .ds-checkbox { color: rgba(255, 255, 255, .72); }
.tpl-cta-card .ds-form a,
.tpl-cta-card .tpl-cta__disclaimer a { color: #fff; text-decoration: underline; }

/* Акция-купон на тёмной карточке: пунктирная светлая рамка (как в концепте) */
.tpl-promo {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-2);
  position: relative;
  padding: var(--ds-space-6);
  margin-top: var(--ds-space-3);
  border-radius: var(--ds-radius-lg);
  border: 2px dashed rgba(255, 255, 255, .4);
  background: rgba(255, 255, 255, .07);
}

.tpl-promo__tag {
  align-self: flex-start;
  font-size: .8em;
  font-weight: 700;
  color: var(--ds-color-on-primary);
  background: var(--ds-color-primary);
  padding: var(--ds-space-1) var(--ds-space-3);
  border-radius: var(--ds-radius-full);
}

.tpl-promo__headline { color: #fff; }
.tpl-promo__note { color: rgba(255, 255, 255, .75); font-size: .95em; }

/* Контакты в инфо-колонке */
.tpl-contacts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-6);
}

.tpl-contact { display: flex; flex-direction: column; }
.tpl-contact b { color: #fff; }
.tpl-contact span { color: rgba(255, 255, 255, .6); font-size: .9em; }

.tpl-cta__disclaimer {
  grid-column: 1 / -1;
  margin: var(--ds-space-8) 0 0;
  padding-top: var(--ds-space-4);
  border-top: 1px solid rgba(255, 255, 255, .14);
  color: rgba(255, 255, 255, .6);
  font-size: .85em;
}

/* Подвал compare: цена + CTA под колонками (напр. «Главбух» в концепте) */
.tpl-compare-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-space-4);
  margin-top: var(--ds-space-8);
}

.tpl-compare-foot__note { color: var(--ds-text-secondary); max-width: 40rem; }

/* Врезка-цитата (напр. «Слово руководителя»); цвета текста наследуются от секции
   (в т.ч. инверсной), роль приглушается opacity — работает на любом фоне */
.tpl-quote {
  display: flex;
  gap: var(--ds-space-6);
  align-items: flex-start;
  max-width: 52rem;
}

.tpl-quote__avatar {
  flex-shrink: 0;
  width: 3.5rem;
  height: 3.5rem;
  display: grid;
  place-items: center;
  border-radius: var(--ds-radius-full);
  background: var(--ds-color-primary);
  color: var(--ds-color-on-primary);
  font-weight: 700;
}

.tpl-quote__text { margin: 0 0 var(--ds-space-3); font-size: 1.15em; }
.tpl-quote__who { display: flex; flex-direction: column; }
.tpl-quote__role { opacity: .7; font-size: .9em; }

/* Плашка согласия на аналитику (наряд integrator-c 01.08, consent-gate).
   SSG отдаёт [hidden] — tpl-consent.js снимает его, только если выбора ещё
   не было (иначе плашка держит счётчик за собой, а хвост тумблера — снаружи
   этого файла: geometry на --ds-* токенах, сам JS-гейт живёт отдельно). */
.tpl-consent {
  position: fixed;
  inset-inline: var(--ds-space-4);
  bottom: var(--ds-space-4);
  z-index: 40;
  max-width: 40rem;
  margin-inline: auto;
  border-radius: var(--ds-radius-xl, 30px);
  background: var(--ds-surface-page);
  color: var(--ds-text-primary);
  box-shadow: var(--ds-shadow-lg);
}

/* Плашка согласия: отступы АСИММЕТРИЧНЫ, и это несущее, а не декор (поправка
   c-design 12.08 по эталону). Канон `.ckbar .in` даёт `13px 26px` — отношение
   ~1:2: у полосы во всю ширину экрана читаются именно ГОРИЗОНТАЛЬНЫЕ поля, при
   равномерных 16px текст прижимается к краю.
   ⚠ В каноне ДВА правила, а не одно: базовое `13px 26px` и под
   `@media (max-width:760px)` — `11px 16px`. c-design процитировала первое;
   второе я нашёл разбором по БАЛАНСУ СКОБОК (первая попытка — «ближайший
   предшествующий @media» — соврала: она читала позицию, а не вложенность).
   Беру оба: узкий экран не должен терять 48px ширины на поля. Ближайшее в
   нашей шкале: 12/24 базово и 12/16 на узком; брейкпоинт — контрактный 768,
   не канонные 760. Если c-design считает, что шаг лишний, — снять один блок. */
.tpl-consent__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ds-space-3);
  padding: var(--ds-space-3) var(--ds-space-4);
}

@media (min-width: 768px) {
  .tpl-consent__inner {
    gap: var(--ds-space-4);
    padding: var(--ds-space-3) var(--ds-space-6);
  }
}

.tpl-consent__text {
  flex: 1 1 16rem;
  margin: 0;
  font-size: var(--ds-fs-sm);
  color: var(--ds-text-secondary);
}

.tpl-consent__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-3);
}
