@charset "UTF-8";
/* ============================================================================
   poleznoe.css — НОВЫЕ компоненты раздела /poleznoe/ (блог: хаб + статья)
   Дбрус · new_design · 2026-07-22
   ----------------------------------------------------------------------------
   ЧТО ЭТО. Один production-файл со стилями ТОЛЬКО НОВЫХ классов, которые
   используют боевые Fenom-шаблоны:
     • new_design/pages/poleznoe_hub.tpl     — хаб /poleznoe/
     • new_design/pages/poleznoe_article.tpl — страница статьи /poleznoe/<slug>/

   КУДА КЛАСТЬ. /assets/template/new_design/css/poleznoe.css — ОТДЕЛЬНЫМ файлом,
   подключается своим <link> из pages/poleznoe_hub.tpl и pages/poleznoe_article.tpl
   ПОСЛЕ живого styles.css (через meta.tpl). В бандл styles.css НЕ вливать —
   base/reset, шрифты, иконки и типографика уже на боевом; poleznoe.css несёт
   только новые компоненты блога поверх них.

   ИСТОЧНИК. Materials/07-tech/poleznoe-modx-integration-2026-06-20/prototypes/
   _ds2/styles/components/*.css (16 файлов, порядок ниже) + инлайн-<style> двух
   канон-прототипов (article-sroki-v1-ds2-2026-06-10.html,
   prototype-poleznoe-hub-ds2-2026-06-09.html). Эталон подхода и структуры —
   задеплоенный voprosy.css (/voprosy/, 21.06.2026): шапка-провенанс, :root
   rem-фолбэк токенов, компонентные секции, финальный порт живых компонентов.

   НЕ ВКЛЮЧЕНО (сознательно):
     • base.css / typography.css / tokens.css / icons.css / fonts.css —
       ресет, типографика, базовые токены, шрифты, иконочный шрифт уже
       в живом styles.css; дублирование не требуется.
     • components/header.css / components/footer.css — хром сайта живой,
       новые классы блог-страницы его не трогают.

   ВКЛЮЧЁННЫЕ КОМПОНЕНТЫ (порядок 1-16 — см. секции ниже) + 2 инлайн-блока
   канон-прототипов (17-18) + финальный порт живых компонентов (19).

   ПРИМЕНЁННЫЕ ПАТЧИ (обязательные, из ТЗ):
     PATCH-A — :root rem-фолбэк отсутствующих в боевом бандле токенов (ниже).
     PATCH-B — accordion.css: убрано display:block по .active .item-descr
               (боевой common.js анимирует jQuery-slideDown/Up, CSS-правило
               по .active «щёлкало» вместо плавной анимации).
     PATCH-C — button.css: убрана собственная word-анимация .btn-txt .word
               (дублирует боевой TextAnimator common.js) + анти-дребезг
               .btn-txt{flex:1 1 auto} + вынос .primary-btn padding/min-width/
               /min-height в §19 (см. PATCH-C и §19 ниже — сверка с живым
               styles.css 22.07.2026 нашла конфликт значений).
     PATCH-D — после breadcrumbs.css: flex-wrap:wrap на ≤575px (живое
               nowrap уводит длинные крошки статьи/хаба за экран).
     PATCH-E — article.css: относительный url() → прод-абсолютный путь.
     PATCH-F — эта шапка-провенанс.

   ДОПОЛНИТЕЛЬНАЯ НАХОДКА (не из явного ТЗ, но по методологии §19/voprosy-§15
   «порт живых компонентов» — сверка новых классов с живым styles.css перед
   деплоем): .primary-btn на боевом имеет padding:0 и НЕ имеет min-width/
   min-height (габариты каждый живой инстанс — напр. хедер-CTA «Выставочные
   дома», .header__content .main-menu .projects-btn — получает от СВОЕГО
   более специфичного правила). poleznoe.css грузится ПОСЛЕ styles.css, и при
   безусловном .primary-btn{padding:0 3.2rem;min-width:28rem;min-height:6rem}
   (как в исходном _ds2/button.css) это правило той же специфичности (0,1,0)
   выигрывает у живого — и меняет вид хедер/футер-кнопок именно на страницах
   блога. Решение: сами габариты вынесены из §8 в §19, применяются ТОЛЬКО в
   скоупе .blog-page/.article. См. подробный комментарий в §19.
   ============================================================================ */


/* ----------------------------------------------------------------------------
   PATCH-A. rem-ФОЛБЭК ТОКЕНОВ НОВОЙ DS.
   Список собран grep'ом var(--...) по ВСЕМ включаемым файлам (16 компонентов +
   2 инлайн-блока canon-прототипов) и сверен с живым styles.css (скачан
   22.07.2026, https://dbrus.ru/assets/template/new_design/css/styles.css,
   250 КБ). Переменные, которые живой бандл УЖЕ объявляет, сюда НЕ включены —
   не переопределяем: --brand-* --white-* --yellow-* --bg-color --size-index
   --container-width --grey-low --brand-second-extra-low --container-padding
   (все подтверждены присутствующими в живом :root, проверено 22.07.2026).

   ОТКЛОНЕНИЕ ОТ БУКВЫ ТЗ (--font-*): ТЗ просило исключить --font-* целиком
   как «уже в боевом бандле». Проверка живого styles.css показала, что это
   верно только для --font-sans: боевой не объявляет саму переменную, но
   font-family на .primary-btn и на классах .blog-… наследуется от body, а
   body{font-family:var(--default-font)...} = Inter — тот же стек, что и
   --font-sans в фолбэке voprosy-ref.css. Пропуск --font-sans безопасен
   (вычисленное значение совпадает что с фолбэком, что без него).
   Для --font-mono это НЕ так: живой бандл грузит шрифт "RobotoMono" (@font-face
   подтверждён, используется как литерал `font-family: RobotoMono, sans-serif`
   в разных местах), но переменной --font-mono НЕ объявляет. Без фолбэка все
   моно-элементы блога (toc, checklist, quote-mark, chip-моно, article-subhead,
   cell-type таблиц и т.д. — это сквозной приём DS) наследовали бы Inter вместо
   RobotoMono — заметная потеря брендового акцента. Поэтому --font-mono
   ДОБАВЛЕН вопреки формулировке ТЗ; --font-sans — пропущен, как и просили.
   ---------------------------------------------------------------------------- */
:root {
  --font-mono: "Roboto Mono", "RobotoMono", ui-monospace, SFMono-Regular, Menlo, monospace;
  /* Срез углов («обрубленные» уголки бренда) — три размерных шага. Значения
     1:1 из voprosy-ref.css / dbrus-design tokens.css, не варьируются по брейку. */
  --chamfer-lg: 2.2rem;
  --chamfer-md: 0.8rem;
  --chamfer-sm: 0.6rem;
  /* Токены в rem, НЕ px (владелец 21.07): боевой масштабирует rem через
     html{font-size:var(--size-index)} (vw), px-значения «отставали» на мобиле.
     Значения и медиа-шаги — те же, что в voprosy-ref.css (единая DS-шкала):
     --surface-base — ритм паддингов карточек блога / faq-experts;
     --size-headings-h1 — H1 хаба (.blog-page__title);
     --size-body-m — лид хаба и «пусто по фильтру» (.blog-page__lead/__empty). */
  --surface-base: 2.4rem;
  --size-headings-h1: 8rem;
  --size-body-m: 1.8rem;
}
@media (max-width: 992px) {
  :root { --surface-base: 1.6rem; --size-headings-h1: 4.6rem; --size-body-m: 1.6rem; }
}
@media (max-width: 575px) {
  :root { --surface-base: 1.6rem; --size-headings-h1: 3rem; --size-body-m: 1.6rem; }
}

/* ==========================================================================
   1. CHAMFER — утилита среза углов (chamfer.css)
   ========================================================================== */
.chamfered {
  --chamfer: var(--chamfer-lg);
  clip-path: polygon(
    var(--chamfer) 0,
    100% 0,
    100% calc(100% - var(--chamfer)),
    calc(100% - var(--chamfer)) 100%,
    0 100%,
    0 var(--chamfer)
  );
}
.chamfered--lg {
  clip-path: polygon(
    var(--chamfer-lg) 0, 100% 0,
    100% calc(100% - var(--chamfer-lg)), calc(100% - var(--chamfer-lg)) 100%,
    0 100%, 0 var(--chamfer-lg)
  );
}
.chamfered--md {
  clip-path: polygon(
    var(--chamfer-md) 0, 100% 0,
    100% calc(100% - var(--chamfer-md)), calc(100% - var(--chamfer-md)) 100%,
    0 100%, 0 var(--chamfer-md)
  );
}
.chamfered--sm {
  clip-path: polygon(
    var(--chamfer-sm) 0, 100% 0,
    100% calc(100% - var(--chamfer-sm)), calc(100% - var(--chamfer-sm)) 100%,
    0 100%, 0 var(--chamfer-sm)
  );
}

/* Reverse chamfer — bottom-left + top-right cuts (used on .scroll-link). */
.chamfered--reverse {
  clip-path: polygon(
    0 var(--chamfer-md),
    var(--chamfer-md) 0,
    100% 0,
    100% calc(100% - var(--chamfer-md)),
    calc(100% - var(--chamfer-md)) 100%,
    0 100%
  );
}

/* When the chamfer needs a "frame" (e.g. dark close-button inside a
   beige rim), put `.chamfered--framed` on the OUTER element and a
   nested `.chamfered__inner` will inherit a 1px inset clip. */
.chamfered--framed { position: relative; }
.chamfered--framed > .chamfered__inner {
  position: absolute;
  inset: 0.1rem;
  clip-path: inherit;
}

/* ==========================================================================
   2. ХЛЕБНЫЕ КРОШКИ (breadcrumbs.css) + PATCH-D
   ========================================================================== */
.breadcrumbs-row {
  margin-top: 2.5rem;
  position: relative;
  z-index: 1;
}
@media (max-width: 992px) { .breadcrumbs-row { margin-top: 2rem; } }
@media (max-width: 575px) { .breadcrumbs-row { margin-top: 2.5rem; } }

.breadcrumbs-row ol {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  column-gap: 1.8rem;
  flex-wrap: nowrap;
}

.breadcrumbs-row ol li {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  column-gap: 2.2rem;
  flex: 0 0 auto;
  width: auto;
}

.breadcrumbs-row ol li::after {
  content: '\e802'; /* icon-link_arrow */
  font-family: "fontello";
  font-style: normal;
  font-weight: normal;
  display: inline-block;
  /* 1:1 с боевым dbrus.ru: разделитель — мелкий глиф 0.5rem (был 0.8rem — расходились). */
  font-size: 0.5rem;
  line-height: 0.5rem;
  transform: rotate(-90deg);
  color: var(--brand-main-mid);
}

.breadcrumbs-row ol li a,
.breadcrumbs-row ol li > span {
  display: inline-block;
  font-size: 1.4rem;
  line-height: 100%;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--brand-main-mid);
  transition: color 0.3s;
  text-decoration: none;
}
@media (max-width: 575px) {
  .breadcrumbs-row ol li a,
  .breadcrumbs-row ol li > span { font-size: 1.2rem; }
}

.breadcrumbs-row ol li a:hover { color: var(--brand-main-base); }
.breadcrumbs-row ol li > span { color: var(--brand-main-base); }
.breadcrumbs-row ol li:last-child::after { display: none; }

/* PATCH-D: живое правило .breadcrumbs-row ol { flex-wrap: nowrap } (styles.css)
   уводит длинные крошки статьи/хаба за экран на мобиле — переносим их в скоупе
   наших страниц. */
@media (max-width: 575px) {
  .blog-page .breadcrumbs-row ol,
  .article-hero-zone .breadcrumbs-row ol { flex-wrap: wrap; }
}

/* ==========================================================================
   3. ТЕГИ / ЧИПЫ (tag.css)
   ========================================================================== */
.tag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background-color: var(--brand-main-low);
  border: 0.1rem solid var(--brand-main-low);
  color: var(--brand-main-base);
  font-family: var(--font-sans);
  font-size: 1.4rem;
  line-height: 100%;
  font-weight: 500;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  padding: 1.2rem 1.6rem;
  position: relative;
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
  transition: background-color 0.3s, color 0.3s, border-color 0.3s;
}
@media (max-width: 575px) {
  .tag { font-size: 1.2rem; padding: 1rem 1.3rem; }
}

/* Hover — border darkens (matches catalog-filter checkbox-label) */
.tag:hover {
  border-color: var(--brand-main-base);
}

/* Active / selected — beige fill + mid border */
.tag--active,
.tag--active:hover {
  background-color: var(--brand-second-mid);
  border-color: var(--brand-main-mid);
}

/* ---- Removable: applied-filter pill with trailing × ---- */
.tag--removable {
  padding-right: 3.6rem;
}
.tag--removable::after {
  /* Fontello icon-close × — тот же глиф, что и у .check-item (filter.css),
     а не две CSS-палки (давали неравные диагонали + иной размер). */
  content: "\e801";
  font-family: "fontello";
  font-style: normal;
  font-weight: normal;
  font-variant: normal;
  text-transform: none;
  display: block;
  position: absolute;
  top: 50%;
  right: 1.2rem;
  transform: translateY(-50%);
  font-size: 1.2rem;
  line-height: 1;
  color: currentColor;
  transition: color 0.3s;
}
.tag--removable:hover {
  background-color: var(--brand-second-mid);
  border-color: var(--brand-main-mid);
}

/* ---- Product card badge (translucent beige + thin rim) ---- */
.tag--product {
  background-color: var(--brand-third-mid);
  border-color: var(--brand-main-low);
  padding: 0.8rem 1.1rem;
  letter-spacing: -0.02em;
}
.tag--product:hover {
  border-color: var(--brand-main-mid);
}

/* ---- Square icon chip (overflow / "more") ---- */
.tag--icon {
  width: 4.2rem;
  height: 4.2rem;
  flex: 0 0 4.2rem;
  padding: 0;
}
.tag--icon [class^="icon-"],
.tag--icon [class*=" icon-"] {
  font-size: 1.4rem;
  line-height: 1;
}

/* ---- Large variant: paired with the catalog-filter dropdown chips ----
   The filter dropdown uses the same colour rules at a roomier size so
   options are easier to hit. Use .tag--lg to apply the same dimensions
   anywhere outside the filter panel. */
.tag--lg {
  font-size: 1.6rem;
  letter-spacing: -0.06em;
  padding: 1.6rem 2rem;
  min-width: 7.2rem;
}
@media (max-width: 575px) {
  .tag--lg { font-size: 1.4rem; padding: 1.3rem 1.6rem; }
}

/* ---- Chamfer composition ----
   When the tag carries `.chamfered--sm` (6px corner skew), the chopped
   corner replaces the visual border on top-left/bottom-right. Drop the
   border so the silhouette stays clean. */
.tag.chamfered,
.tag.chamfered--sm,
.tag.chamfered--md {
  border: none;
}

/* ---- Mono tag-card (product badges: МАТКАПИТАЛ / ПОПУЛЯРНЫЙ) ----
   Roboto Mono micro-badge, sharp corners, no border. White by default,
   .tag--dark inverts to slate ink. Used on the product card image.
   Note: this is its own silhouette — does NOT inherit the .tag padding. */
.tag--mono {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 1.4rem;
  line-height: 100%;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  padding: 0.4rem 0.6rem;
  border: none;
  background-color: var(--white-base);
  color: var(--brand-main-base);
}
.tag--mono:hover { border-color: transparent; }
.tag--mono.tag--dark {
  background-color: var(--brand-main-base);
  color: var(--white-base);
}
@media (max-width: 575px) {
  .tag--mono { font-size: 1.2rem; padding: 0.4rem 0.6rem; }
}

/* ---- Chip list (catalog filter row) ---- */
.tag-list {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.8rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* ==========================================================================
   4. ОБЛАКО SEO-ТЕГОВ / СЛАЙДЕР (tags-section.css)
   ========================================================================== */
/* ─────────────────────────────────────────────────────────
   1. Боевые правила (1:1 из 1.mhtml)
   ───────────────────────────────────────────────────────── */
/* width:100% — секция инжектится партиалом как ПРЯМОЙ ребёнок body
   (include-partials заменяет div-обёртку самим <section>), а base.css
   тянет width:100% только у main/header/footer/body>div. Без этого при
   body{align-items:flex-start} секция схлопывается до max-content и
   распирает страницу по горизонтали, а слайдер тегов не клипуется
   (стрелка next не появляется). */
.tags-section { padding: 10rem 0; width: 100%; }

@media (max-width: 575px) {
  .tags-section { padding: 5rem 0; }
}

.tags-section .tags-slider { position: relative; }

.tags-section .tags-slider .swiper-slide { width: auto; padding: 0 0.4rem; }

.tags-section .tags-slider .swiper-slide:nth-of-type(1) { padding-left: 0; }

.tags-section .tags-slider .swiper-slide:last-child { padding-right: 0; }

.tags-section .tags-slider .swiper-slide a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: auto;
  background-color: var(--brand-second-extra-low);
  border: 1px solid var(--brand-second-strong);
  font-size: 1.6rem;
  font-weight: 400;
  line-height: 100%;
  white-space: nowrap;
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: -0.06em;
  color: var(--brand-second-strong);
  margin: 0;
  /* Боевое значение было симметричным 0.2rem 1.6rem, но UPPERCASE при
     line-height:100% оптически прижимается к верхней рамке. Лёгкая
     оптическая коррекция (чуть больше воздуха сверху). */
  padding: 0.3rem 1.6rem 0.2rem;
  transition: color 0.3s, background-color 0.3s, border-color 0.3s;
}

.tags-section .tags-slider .swiper-slide a:hover {
  border-color: var(--brand-main-base);
  color: var(--brand-main-base);
}

/* ─────────────────────────────────────────────────────────
   Адаптив высоты чипов. В полосах 576–992 и ≤575 --size-index
   раздувает rem (1rem доходит до ~12.9px на 992 и ~15.3px на 575),
   из-за чего чипы становятся выше нужного. Шагаем размер/паддинг
   вниз — как это делает blog.css для типографики.
   ───────────────────────────────────────────────────────── */
@media (max-width: 992px) {
  .tags-section .tags-slider .swiper-slide a {
    font-size: 1.3rem;
    padding: 0.3rem 1.2rem 0.2rem;
  }
}
@media (max-width: 575px) {
  .tags-section .tags-slider .swiper-slide a {
    font-size: 1.2rem;
    padding: 0.25rem 1rem 0.18rem;
  }
}

.tags-section .tags-slider .slider-navigation {
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: absolute;
  width: 100%;
  height: 0;
  top: 50%;
  left: 0;
  z-index: 1;
}

.tags-section .tags-slider .slider-navigation .nav-btn {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  width: 6rem;
  height: 4rem;
  transition: color 0.3s, opacity 0.3s;
  background: linear-gradient(270deg, var(--brand-third-mid) 30%, rgba(238, 235, 229, 0.5) 70%, rgba(238, 235, 229, 0) 100%);
}

.tags-section .tags-slider .slider-navigation .nav-btn.prev-btn { transform: scale(-1, 1); }

.tags-section .tags-slider .slider-navigation .nav-btn.swiper-button-disabled { opacity: 0; pointer-events: none; }

.tags-section .tags-slider .slider-navigation .nav-btn:hover { color: var(--brand-main-base); }


/* ─────────────────────────────────────────────────────────
   2. Фолбэк без Swiper (наша DS не грузит swiper.js)
   ---------------------------------------------------------
   Делаем .swiper-wrapper горизонтальным скролл-контейнером:
   так чипы листаются трекпадом/тачем, а .nav-btn проматывают
   его из ui-interactions.js. Полоса скролла скрыта.
   Эти правила НЕ конфликтуют с боевыми — на сайте поверх них
   работает Swiper, у нас — нативный overflow-скролл.
   ───────────────────────────────────────────────────────── */
.tags-section .tags-slider .swiper-wrapper {
  display: flex;
  overflow-x: auto;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.tags-section .tags-slider .swiper-wrapper::-webkit-scrollbar { display: none; }

/* Стрелка-глиф внутри кнопки (живой .icon-btn_arrow) — видимый цвет. */
.tags-section .tags-slider .slider-navigation .nav-btn .icon {
  font-size: 1.6rem;
  line-height: 1;
  color: var(--brand-second-strong);
  transition: color 0.3s;
}
.tags-section .tags-slider .slider-navigation .nav-btn:hover .icon { color: var(--brand-main-base); }

/* ==========================================================================
   5. BLOG UI KIT — карточки/лента/фильтры (blog.css)
   ========================================================================== */
/* =========================================================
   1. Карточка статьи — .blog-card
   ========================================================= */
.blog-card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background-color: var(--brand-third-mid);
  text-decoration: none;
  transition: background-color 0.3s;
}
/* Подсветка под курсором — СВЕТЛЕЕ фона страницы (решение владельца 30.08.2026,
   вариант «мягкий белый» из примерки _primerka-podsvetka-2026-08-30).
   Было var(--brand-second-base) #e6e1db — темнее фона: карточка в покое и фон
   страницы это один цвет #eeebe5, и подсветка утапливала карточку вместо того,
   чтобы вывести её вперёд. Полшага к белому, лента остаётся кремовой. */
.blog-card:hover {
  background-color: #f7f6f3;
}

.blog-card__media {
  position: relative;
  width: 100%;
  aspect-ratio: 330 / 248;
  overflow: hidden;
  background-color: var(--brand-third-base);
}
/* Единый фильтр обложек ленты (решение владельца 30.08.2026, вариант B из примерки
   _primerka-oblozhki-2026-08-30). Кадры приходят от разных съёмок: замер HSL по
   двенадцати обложкам дал насыщенность от 13 до 46 — разброс в 3,4 раза, из-за
   него блёклый кадр рядом с сочным читался выцветшим. Фильтр стягивает
   насыщенность и чуть добавляет контраста; светлота не трогается — её разброс
   (38…58) фильтром не лечится и сейчас не мешает. Действует на все будущие
   обложки сам, перекрашивать файлы не нужно. */
.blog-card__media img {
  filter: saturate(0.72) contrast(1.04);
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.blog-card:hover .blog-card__media img {
  transform: scale(1.03);
}

.blog-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--surface-base);
  padding: var(--surface-base);
  border: 0.1rem solid var(--brand-main-low);
  flex: 1 1 auto;
}
.blog-card__group {
  display: flex;
  flex-direction: column;
  gap: 1.6rem;
}
.blog-card__head {
  display: flex;
  flex-direction: column;
  gap: 1.6rem;
}

/* Category badge — translucent beige + cool-taupe rim (brand «meta-tag»). */
/* Кегль и поля чипа на полшага меньше прежних: 1.6rem капса рядом с 2rem заголовка
   карточки читались одним уровнем, и рубрика спорила с названием материала.
   Трекинг ослаблен до -0.04em — на меньшем кегле -0.06em сжимал капс.
   min-width держит одинаковую ширину коротким рубрикам («Цены», «Сроки»). */
.blog-card__cat {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 6.8rem;
  padding: 0.35rem 1.2rem;
  background-color: var(--brand-second-extra-low);
  border: 0.1rem solid var(--brand-second-strong);
  backdrop-filter: blur(0.5rem);
  -webkit-backdrop-filter: blur(0.5rem);
  font-family: var(--font-sans);
  font-size: 1.4rem;
  line-height: 100%;
  letter-spacing: -0.04em;
  text-transform: uppercase;
  color: var(--brand-second-strong);
}

.blog-card__title {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 2rem;
  line-height: 120%;
  letter-spacing: -0.04em;
  text-transform: uppercase;
  color: var(--brand-main-base);
  text-wrap: balance;
}

.blog-card__desc {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 1.8rem;
  line-height: 130%;
  letter-spacing: -0.02em;
  color: var(--brand-main-mid);
  /* 4-line clamp — keeps every card the same height in a row. */
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.blog-card__date {
  font-family: var(--font-sans);
  font-size: 1.4rem;
  line-height: 100%;
  letter-spacing: -0.02em;
  color: var(--brand-main-mid);
}

/* Body type steps down with the brand scale. Mirrors .item-title /
   .subtitle in typography.css — a 992 step AND a 575 step, because the
   fluid --size-index inflates rem in the 576–992 band; without the 992
   override the description would read LARGER on tablet than on desktop. */
@media (max-width: 992px) {
  .blog-card__title { font-size: 1.8rem; }
  .blog-card__desc { font-size: 1.6rem; }
}
@media (max-width: 575px) {
  .blog-card__title { font-size: 1.6rem; }
  .blog-card__desc { font-size: 1.4rem; }
  .blog-card__cat  { font-size: 1.25rem; }
  .blog-card__date { font-size: 1.2rem; }
}

/* =========================================================
   1b. Карточка-видео — .blog-card--video
   ---------------------------------------------------------
   Та же карточка, но поверх обложки — круглая кнопка play
   (переиспользуем .player-control из player.css), а в мета-строке
   рядом с категорией — моно-плашка тайм-кода (.player-timecode)
   с мелким глифом play. Вся карточка — ссылка (на player.html),
   поэтому play-control делаем НЕинтерактивным <span> — не
   вкладываем <button> в <a>; клики идут по карточке.
   ========================================================= */
.blog-card__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
  width: 100%;
}
/* Лёгкое затемнение обложки видео, чтобы кнопка читалась на фото. */
.blog-card--video .blog-card__media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background-color: rgba(55, 61, 66, 0.18);
  transition: background-color 0.3s;
}
.blog-card--video:hover .blog-card__media::after {
  background-color: rgba(55, 61, 66, 0.3);
}
.blog-card__play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  pointer-events: none; /* клики идут по карточке-ссылке */
}
/* Сплошная пшеничная заливка — кнопка читается поверх фото. */
.blog-card__play.player-control {
  background-color: var(--brand-second-mid);
  color: var(--brand-main-base);
}
.blog-card--video:hover .blog-card__play {
  background-color: var(--brand-main-base);
  color: var(--brand-second-mid);
}
/* Тайм-код в мета-строке: моно-плашка + мелкий глиф play. */
.blog-card__time { gap: 0.4rem; }
.blog-card__time svg {
  flex: 0 0 auto;
  width: 1rem;
  height: 1rem;
  fill: currentColor;
  display: block;
}

/* =========================================================
   2. Сетка / лента + переключатель вида — .blog-grid
   ---------------------------------------------------------
   The .blog-modes switcher flips a `data-view` on this grid:
     grid  → 3-up responsive columns
     video → 2-up
     doc   → single-column "reading list"
   ========================================================= */
.blog-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.6rem;
  width: 100%;
}
.blog-grid[data-view="video"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.blog-grid[data-view="doc"]   { grid-template-columns: minmax(0, 1fr); }

/* In single-column "doc" view the card becomes a horizontal row. */
.blog-grid[data-view="doc"] .blog-card {
  flex-direction: row;
  align-items: stretch;
}
.blog-grid[data-view="doc"] .blog-card__media {
  flex: 0 0 32rem;
  aspect-ratio: 16 / 10;
}
.blog-grid[data-view="doc"] .blog-card__body { border-left: none; }

@media (max-width: 992px) {
  .blog-grid,
  .blog-grid[data-view="video"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .blog-grid[data-view="doc"] .blog-card { flex-direction: column; }
  .blog-grid[data-view="doc"] .blog-card__media { flex: none; aspect-ratio: 330 / 248; }
  .blog-grid[data-view="doc"] .blog-card__body { border-left: 0.1rem solid var(--brand-main-low); }
}
@media (max-width: 575px) {
  .blog-grid,
  .blog-grid[data-view="video"],
  .blog-grid[data-view="doc"] { grid-template-columns: minmax(0, 1fr); }
}

/* =========================================================
   3. Теги статей — .blog-tag (chamfered)
   ---------------------------------------------------------
   Solid-filled chopped-corner chip. Compose with
   `.chamfered .chamfered--sm` (chamfer.css). Default beige,
   :hover & --active fill wheat. No border (chamfer is the edge).
   ========================================================= */
.blog-tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.6rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.blog-tag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 3.2rem;
  padding: 0 1.6rem;
  background-color: var(--brand-second-base);
  color: var(--brand-main-base);
  font-family: var(--font-sans);
  font-size: 1.6rem;
  line-height: 100%;
  letter-spacing: -0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.3s;
}
.blog-tag:hover,
.blog-tag--active { background-color: var(--brand-second-mid); }

/* =========================================================
   4. Фильтр категорий со счётчиком — .blog-filters
   ---------------------------------------------------------
   Chopped-corner buttons: label + count. Compose with
   `.chamfered .chamfered--md`. Inactive = 10%-ink wash;
   :hover = wheat; .is-active = dark fill + light text.
   ========================================================= */
.blog-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.6rem;
}
.blog-filter {
  display: inline-flex;
  align-items: center;
  gap: 0.8rem;
  padding: 1rem 1.6rem;
  background-color: var(--brand-main-low);
  color: var(--brand-main-base);
  border: none;
  cursor: pointer;
  text-decoration: none;
  transition: background-color 0.3s, color 0.3s;
}
/* Leading icon — inline SVG drawn in the brand 1.5px line style.
   Inherits the chip's `color`, so it flips light on the active dark
   fill automatically. Sits flush-left of the label (see Figma «ВСЕ 32»). */
.blog-filter__icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  margin-right: -0.2rem;
  color: inherit;
}
.blog-filter__icon svg {
  width: 100%;
  height: 100%;
  display: block;
}
.blog-filter__label {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 1.6rem;
  line-height: 112%;
  text-transform: uppercase;
  letter-spacing: 0;
}
.blog-filter__count {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 1.4rem;
  line-height: 100%;
  color: var(--brand-main-mid);
  transition: color 0.3s;
}
.blog-filter:hover { background-color: var(--brand-second-mid); }
.blog-filter.is-active { background-color: var(--brand-main-base); color: var(--white-base); }
.blog-filter.is-active .blog-filter__count { color: var(--white-mid); }

/* =========================================================
   5. Переключатель вида — .blog-modes
   ---------------------------------------------------------
   doc (список) / video / grid. Icons are inline SVG (the
   fontello set has no doc/play/grid glyphs) drawn in the
   brand 1.5px architectural-line style. 44px hit target.
   ========================================================= */
.blog-modes {
  display: inline-flex;
  align-items: center;
  gap: 0.8rem;
}
.blog-mode {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 4.4rem;
  height: 4.4rem;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--brand-main-mid);
  transition: color 0.3s;
}
.blog-mode svg {
  width: 2.4rem;
  height: 2.4rem;
  display: block;
}
.blog-mode:hover { color: var(--brand-main-base); }
.blog-mode.is-active { color: var(--brand-main-base); }
.blog-mode:focus-visible {
  outline: 0.2rem solid var(--brand-main-base);
  outline-offset: 0.2rem;
}

/* =========================================================
   Responsive type — body / labels step down on tablet & mobile
   (rem + explicit breakpoints, per the typography.css convention)
   ========================================================= */
@media (max-width: 575px) {
  .blog-tag           { font-size: 1.4rem; }
  .blog-filter__label { font-size: 1.4rem; }
}

/* ==========================================================================
   6. ВИДЕО-ПЛЕЕР (player.css)
   ========================================================================== */
/* ---- Timecode chip ---- */
.player-timecode {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.4rem 0.6rem;
  background-color: rgba(0, 0, 0, 0.55);
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 1.3rem;
  line-height: 100%;
  letter-spacing: -0.02em;
  color: var(--white-base);
  white-space: nowrap;
}

/* ---- Play / pause control ---- */
.player-control {
  --size: 8rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--size);
  height: var(--size);
  flex: 0 0 auto;
  padding: 0;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  background-color: var(--brand-second-mid);
  color: var(--brand-main-base);
  transition: background-color 0.25s, color 0.25s;
}
.player-control:hover,
.player-control:focus-visible {
  background-color: var(--brand-main-base);
  color: var(--brand-second-mid);
  outline: none;
}
.player-control svg {
  width: 40%;
  height: 40%;
  display: block;
  fill: currentColor;
}
/* Pause glyph hidden by default; play glyph hidden on --pause.
   Scoped with .player-control to beat `.player-control svg { display:block }`. */
.player-control .player-control__pause { display: none; }
.player-control--pause .player-control__play { display: none; }
.player-control--pause .player-control__pause { display: block; }

/* Compact size for inline use (e.g. on a poster). */
.player-control--sm { width: 5.6rem; height: 5.6rem; }

/* ---- Timeline ---- */
.player-timeline {
  display: block;
  width: 100%;
  height: 0.4rem;
  background-color: rgba(255, 255, 255, 0.2);
  overflow: hidden;
}
.player-timeline__fill {
  display: block;
  height: 100%;
  width: var(--progress, 0%);
  background-color: var(--yellow-base);
}
/* On a light surface, darken the track. */
.player-timeline--light { background-color: var(--brand-main-low); }

/* ---- Video player poster ---- */
.video-player {
  display: flex;
  flex-direction: column;
  width: 100%;
}

.video-poster {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1.8;
  padding: 1.6rem;
  background: linear-gradient(90deg, #555d63 0%, #373d42 100%);
  overflow: hidden;
}

/* If a real poster image is dropped in, it fills the gradient frame. */
.video-poster > .video-poster__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}

/* 4 corner ticks (brand motif) */
.video-poster::before,
.video-poster::after,
.video-poster > .corner-bl,
.video-poster > .corner-br {
  content: "";
  position: absolute;
  width: 1.2rem;
  height: 1.2rem;
  z-index: 2;
  pointer-events: none;
}
.video-poster::before {
  top: 0; left: 0;
  border-top: 0.1rem solid var(--white-base);
  border-left: 0.1rem solid var(--white-base);
}
.video-poster::after {
  top: 0; right: 0;
  border-top: 0.1rem solid var(--white-base);
  border-right: 0.1rem solid var(--white-base);
}
.video-poster > .corner-bl {
  bottom: 0; left: 0;
  border-bottom: 0.1rem solid var(--white-base);
  border-left: 0.1rem solid var(--white-base);
}
.video-poster > .corner-br {
  bottom: 0; right: 0;
  border-bottom: 0.1rem solid var(--white-base);
  border-right: 0.1rem solid var(--white-base);
}

.video-poster .player-control { position: relative; z-index: 2; }

/* Bottom timeline overlay: duration chip right-aligned + progress */
.video-poster__timeline {
  position: absolute;
  left: 1.6rem;
  right: 1.6rem;
  bottom: 1.6rem;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.8rem;
}
.video-poster__timeline .player-timeline { width: 100%; }

/* ---- Caption under a poster ---- */
.video-caption {
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
  padding: 1.6rem 0 0.8rem;
}
.video-caption__title {
  margin: 0;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 1.5rem;
  line-height: 110%;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--brand-main-base);
}
.video-caption__text {
  margin: 0;
  font-size: 1.4rem;
  line-height: 135%;
  letter-spacing: -0.01em;
  color: var(--brand-main-mid);
}

/* ==========================================================================
   7. ПАГИНАЦИЯ (pagination.css)
   ========================================================================== */
.pagination-row {
  margin-top: 4.8rem;
}
@media (max-width: 992px) { .pagination-row { margin-top: 3.2rem; } }
@media (max-width: 575px) { .pagination-row { margin-top: 2.4rem; } }

.pagination-list {
  display: flex;
  align-items: center;
  justify-content: center;
  column-gap: 0.8rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.pagination-list li {
  flex: 0 0 auto;
  width: auto;
}

/* ---- Числовая ячейка + активная ---- */
.pagination-list li:not([class]) a,
.pagination-list li.active a {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.2rem;
  height: 3.2rem;
  font-family: var(--font-sans);
  font-size: 1.4rem;
  line-height: 112%;
  font-weight: 500;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--brand-main-mid);
  background-color: var(--brand-main-low);   /* рамка */
  clip-path: polygon(
    0.6rem 0,
    100% 0,
    100% calc(100% - 0.6rem),
    calc(100% - 0.6rem) 100%,
    0 100%,
    0 0.6rem
  );
  transition: background-color 0.3s, color 0.3s;
}

/* Внутренняя заливка — inset 0.1rem, рамка читается как тонкая. */
.pagination-list li:not([class]) a::before,
.pagination-list li.active a::before {
  content: "";
  display: block;
  position: absolute;
  top: 0.1rem;
  left: 0.1rem;
  width: calc(100% - 0.2rem);
  height: calc(100% - 0.2rem);
  background-color: var(--bg-color);
  clip-path: inherit;
  transition: background-color 0.3s;
  z-index: -1;
}

/* ---- Hover (числовые) — темнеет только рамка ---- */
.pagination-list li:not([class]) a:hover {
  background-color: var(--brand-main-mid);
}

/* ---- Активная страница ---- */
.pagination-list li.active a {
  background-color: var(--brand-second-mid);
  color: var(--brand-main-base);
  pointer-events: none;
  cursor: default;
}
.pagination-list li.active a::before {
  background-color: var(--brand-second-mid);
}

/* ---- Контролы: текст + стрелка-глиф ---- */
.pagination-list li.first a,
.pagination-list li.prev a,
.pagination-list li.next a,
.pagination-list li.last a {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  font-family: var(--font-sans);
  font-size: 1.4rem;
  line-height: 112%;
  font-weight: 500;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--brand-main-base);
  cursor: pointer;
}
.pagination-list li.first { margin-right: 2rem; }
.pagination-list li.prev  { margin-right: 2.4rem; }
.pagination-list li.next  { margin-left: 2.4rem; }
.pagination-list li.last  { margin-left: 2rem; }

/* Стрелка-глиф (fontello slider_arrow \e807). По умолчанию вправо. */
.pagination-list li.first a::before,
.pagination-list li.first a::after,
.pagination-list li.prev a::before,
.pagination-list li.next a::before,
.pagination-list li.last a::before,
.pagination-list li.last a::after {
  font-family: "fontello";
  content: "\e807";
  font-size: 1rem;
  line-height: 0;
  font-weight: normal;
  display: inline-block;
  transition: transform 0.3s;
}

/* Пред. / Первая → стрелки влево, перед текстом */
.pagination-list li.prev a::before {
  order: -1;
  margin-right: 0.8rem;
  transform: scaleX(-1);
}
.pagination-list li.first a::before {
  order: -1;
  transform: scaleX(-1);
}
.pagination-list li.first a::after {
  order: -1;
  margin-right: 0.8rem;
  transform: scaleX(-1);
}

/* След. / Последняя → стрелки вправо, после текста */
.pagination-list li.next a::before {
  order: 2;
  margin-left: 0.8rem;
}
.pagination-list li.last a::before {
  order: 2;
  margin-left: 0.8rem;
}
.pagination-list li.last a::after {
  order: 2;
}

/* Hover — стрелки уезжают наружу */
.pagination-list li.next a:hover::before,
.pagination-list li.last a:hover::before,
.pagination-list li.last a:hover::after {
  transform: translateX(0.5rem);
}
.pagination-list li.first a:hover::before,
.pagination-list li.first a:hover::after,
.pagination-list li.prev a:hover::before {
  transform: scaleX(-1) translateX(0.5rem);
}

/* ---- Отключённый контрол (напр. «Первая» на стр. 1) ---- */
.pagination-list li.disable {
  opacity: 0;
  pointer-events: none;
}

/* ---- Мобильный: контролы скрываются, остаются числа ---- */
@media (max-width: 575px) {
  .pagination-list li.first,
  .pagination-list li.prev,
  .pagination-list li.next,
  .pagination-list li.last {
    display: none;
  }
}

/* ==========================================================================
   8. КНОПКИ (button.css) + PATCH-C
   ========================================================================== */
/* ---- PRIMARY-BTN ----
   Matches production styles 1:1:
     • inline-flex centered, column-gap 1.2rem
     • padding: 0 3.2rem  (horizontal breathing room so long labels
       clear the chamfered corners; min-width/height set the floor)
     • chamfered top-left + bottom-right via clip-path
     • beige `--brand-second-mid` fill
     • hover → the TEXT label splits into .word spans that run the MoveRight
       shuffle (each word slides out right and re-enters from the left, with a
       small per-word stagger) — exactly like the live d-brus site. The arrow
       icon stays put.
   The arrow is drawn by icons.css (masked ::before) — the markup just needs an
   empty <span class="icon icon-btn_arrow"></span>.
   ========================================================= */
.primary-btn {
  /* Height ≥ 60px → large chamfer. Override --chamfer per-instance if needed. */
  --chamfer: var(--chamfer-lg);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  column-gap: 1.2rem;
  font-family: var(--font-sans);
  font-size: 1.6rem;
  line-height: 100%;
  font-weight: 500;
  text-transform: uppercase;
  color: var(--brand-main-base);
  background-color: var(--brand-second-mid);
  border: none;
  clip-path: polygon(
    var(--chamfer) 0, 100% 0,
    100% calc(100% - var(--chamfer)), calc(100% - var(--chamfer)) 100%,
    0 100%, 0 var(--chamfer)
  );
  transition: background-color 0.3s;
  text-decoration: none;
  cursor: pointer;
  /* padding/min-width/min-height НЕ здесь — сверка с живым styles.css (22.07.2026)
     показала .primary-btn там padding:0 и без min-width/min-height (габариты
     каждого инстанса боевой задаёт свой контекст, напр. хедер-CTA «Выставочные
     дома» — .header__content .main-menu .projects-btn). poleznoe.css грузится
     ПОСЛЕ styles.css (одинаковая specificity 0,1,0 у .primary-btn — выигрывает
     порядок подключения), поэтому безусловный padding здесь испортил бы хедер/
     футер на страницах блога. Восстановление — ТОЛЬКО в скоупе блога, см. §19
     ПОРТ ЖИВЫХ КОМПОНЕНТОВ в конце файла. */
}
@media (max-width: 992px) {
  .primary-btn { font-size: 1.6rem; letter-spacing: -0.02em; }
}
.primary-btn .icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.8rem;
  line-height: 1.8rem;
  /* No overflow clip: on primary-btn the arrow stays put (the words animate),
     so clipping only risked trimming/flickering the glyph's top fin. */
  overflow: visible;
}
.primary-btn .icon::before {
  display: inline-block;
  font-size: 1.8rem;
  line-height: 1;
  vertical-align: middle;
}
.primary-btn .btn-txt {
  white-space: nowrap;
  overflow: hidden;
  text-align: left;
  display: inline-flex;
  align-items: center;
  column-gap: 0.4em;
  /* flex НЕ задаём: замер боевого 22.07.2026 (/voprosy/, computed style) — у живого
     .btn-txt `flex: 0 1 auto`, то есть правило отсутствует, и в прототипах _ds2
     его тоже нет. Прежний `flex: 1 1 auto` растягивал бокс на всю свободную ширину,
     а при text-align:left это прижимает лейбл к левому краю — ровно тот вид,
     который владелец забраковал 21.07 на /voprosy/. Анти-дребезг скрэмбла решается
     per-instance фикс-ширинами .btn-txt по замеру (см. .article-cta__btn ниже и
     voprosy.css §15.2, деплой voprosy-btn-antijitter-2026-07-21). */
}
/* PATCH-C: собственная word-анимация УДАЛЕНА — дублирует боевой TextAnimator
   (common.js). Сверка с живым styles.css (22.07.2026): там уже есть
   `.primary-btn .word { text-wrap: nowrap; }` + глобальные @keyframes
   MoveRightInitial/MoveRightEnd, а скрэмбл вешает JS, а не CSS :hover.
   Оставлены только layout-правила (display/will-change нужны, чтобы
   transform от JS-скрэмбла применялся к inline-элементам корректно). */
.primary-btn .btn-txt .word { display: inline-block; will-change: transform; }


/* ---- PRIMARY-BTN variants ---- */
/* Grey (secondary): same silhouette + chamfer, neutral warm-grey fill.
   Used when the CTA must sit quieter than the beige primary. */
.primary-btn--grey { background-color: var(--brand-third-base); }

/* Compact: smaller floor + medium chamfer for inline / card CTAs.
   Keeps the word-run hover and the arrow icon. */
.primary-btn--sm {
  min-width: 0;
  min-height: 4.4rem;
  font-size: 1.4rem;
  column-gap: 0.8rem;
  padding: 0 2rem;
  /* medium chamfer consumed directly from the root token */
  clip-path: polygon(
    var(--chamfer-md) 0, 100% 0,
    100% calc(100% - var(--chamfer-md)), calc(100% - var(--chamfer-md)) 100%,
    0 100%, 0 var(--chamfer-md)
  );
}
.primary-btn--sm .icon { font-size: 1.5rem; line-height: 1.5rem; }
.primary-btn--sm .icon::before { font-size: 1.5rem; }

/* ---- BTN-ARROW ----
   Inner icon wrapper class .icon-btn_arrow matches the original markup. */
.btn-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  border: 0.1rem solid var(--grey-low);
  padding: 0;
  margin: 0;
  font-family: var(--font-sans);
  font-size: 1.6rem;
  line-height: 112%;
  font-weight: 500;
  text-transform: uppercase;
  color: var(--brand-main-base);
  overflow: hidden;
  text-align: left;
  background: transparent;
  transition: border-color 0.3s;
  text-decoration: none;
  cursor: pointer;
}
.btn-arrow .btn-txt {
  padding: 0 2rem;
  flex: 0 0 auto;
  width: auto;
  white-space: nowrap;
  letter-spacing: 0;
}
.btn-arrow .icon-btn_arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 5.1rem;
  width: 5rem;
  height: 5rem;
  font-size: 1.8rem;
  line-height: 1.8rem;
  background-color: var(--yellow-base);
  border-left: 0.1rem solid var(--brand-third-base);
  overflow: hidden;
}
.btn-arrow .icon-btn_arrow::before {
  display: inline-block;
  font-size: 1.8rem;
  line-height: 1;
}
.btn-arrow:hover { border-color: var(--yellow-base); }
.btn-arrow:hover .icon-btn_arrow::before {
  animation: 0.3s forwards MoveRightInitial,
             0.5s 0.3s forwards MoveRightEnd;
}

/* Compact size */
.btn-arrow--sm .icon-btn_arrow {
  flex: 0 0 3.2rem;
  width: 3.2rem;
  height: 3.2rem;
  font-size: 1.4rem;
}
.btn-arrow--sm .icon-btn_arrow::before { font-size: 1.4rem; }
.btn-arrow--sm .btn-txt { padding: 0 1.2rem; font-size: 1.4rem; }

/* ---- BTN-ARROW: правило отступа стрелки (источник истины) ----
   Принцип НЕ «запрет ширины 100%», а «жёлтый квадрат ВСЕГДА вплотную к
   подписи — без лишнего зазора между текстом и стрелкой».
   Кнопка-стрелка = подпись + квадрат впритык, и ширина по содержимому.
     • .btn-txt не растягивается (flex:0 0 auto, базовый стиль) и НЕ переносится
       (nowrap) — текст в одну строку, пока есть место; не форсим перенос.
     • Квадрат стоит сразу за текстом (justify-content:flex-start). Его НЕЛЬЗЯ
       толкать к правому краю через margin-left:auto на иконке или flex:1 1 auto
       на .btn-txt — именно это раньше создавало «баннер» с дырой посередине.
   max-width:100% — лишь страховка от переполнения узкого контейнера.
   Для РЕДКИХ намеренных full-width (CTA во всю ширину карточки калькулятора)
   есть явный .btn-arrow--block — он сознательно создаёт этот зазор. */
.btn-arrow { max-width: 100%; }

/* Явный full-width — ТОЛЬКО по требованию, не по умолчанию:
   подпись растёт и тянет жёлтый квадрат к правому краю. */
.btn-arrow--block { width: 100%; }
.btn-arrow--block .btn-txt { flex: 1 1 auto; width: auto; min-width: 0; }
.btn-arrow--block .icon-btn_arrow { margin-left: auto; }

/* ---- NAV-BTN ---- */
.nav-btn {
  /* 48×48 → medium chamfer (8px). */
  --chamfer: var(--chamfer-md);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 4.8rem;
  height: 4.8rem;
  font-size: 2rem;
  line-height: 2rem;
  clip-path: polygon(
    var(--chamfer) 0, 100% 0,
    100% calc(100% - var(--chamfer)), calc(100% - var(--chamfer)) 100%,
    0 100%, 0 var(--chamfer)
  );
  background-color: var(--brand-second-mid);
  transition: background-color 0.3s;
  color: var(--brand-main-base);
  border: none;
  cursor: pointer;
}
.nav-btn [class^="icon-"]::before,
.nav-btn [class*=" icon-"]::before { font-size: 2rem; line-height: 1; }
.nav-btn.prev-btn,
.nav-btn.nav-btn--prev { transform: scale(-1, 1); }
.nav-btn:hover { background-color: var(--yellow-base); }

/* ---- ICON-BTN — compact icon button ---- */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3.2rem;
  height: 3.2rem;
  background-color: var(--yellow-base);
  color: var(--brand-main-base);
  border: none;
  cursor: pointer;
  transition: background-color 0.3s;
}
.icon-btn [class^="icon-"]::before,
.icon-btn [class*=" icon-"]::before { font-size: 1.6rem; line-height: 1; }
.icon-btn--dark {
  background-color: var(--brand-main-base);
  color: var(--white-base);
}

/* ---- BACKCALL-LINK ----
   Used in the header: text + yellow square with arrow icon. */
.backcall-link {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  column-gap: 1.2rem;
  font-family: var(--font-sans);
  font-size: 1.4rem;
  line-height: 112%;
  font-weight: 500;
  text-transform: uppercase;
  color: var(--brand-main-base);
  text-decoration: none;
  position: relative;
  cursor: pointer;
}
.backcall-link span:not(.icon) {
  position: relative;
}
.backcall-link span:not(.icon)::before {
  content: "";
  display: block;
  width: 0;
  height: 0.1rem;
  background-color: var(--brand-main-base);
  position: absolute;
  bottom: -0.4rem;
  left: 0;
  transition: width 0.3s;
}
.backcall-link .icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 4rem;
  height: 4rem;
  font-size: 1.8rem;
  background-color: var(--yellow-base);
  overflow: hidden;
}
.backcall-link .icon::before { font-size: 1.8rem; line-height: 1; }
.backcall-link:hover span:not(.icon)::before { width: 100%; }
.backcall-link:hover .icon-btn_arrow::before {
  animation: 0.3s forwards MoveRightInitial,
             0.5s 0.3s forwards MoveRightEnd;
}

/* ==========================================================================
   9. РАМКИ-УГОЛКИ / СКОШЕННОЕ ПОДЧЁРКИВАНИЕ (frame.css)
   ========================================================================== */
/* ---- CORNER BRACKETS ----
   .frame-corners gives an element four 0.8x0.8rem brackets
   drawn via :before/:after on the parent + child elements.
   CSS variables let you tweak size/thickness/color. */

.frame-corners {
  position: relative;
  --corner-size: 0.8rem;
  --corner-thickness: 0.2rem;
  --corner-color: var(--brand-main-base);
}

.frame-corners::before,
.frame-corners::after,
.frame-corners > .frame-corner-bl,
.frame-corners > .frame-corner-br {
  content: "";
  display: block;
  width: var(--corner-size);
  height: var(--corner-size);
  position: absolute;
  pointer-events: none;
}

/* top-left */
.frame-corners::before {
  top: 0;
  left: 0;
  border-top: var(--corner-thickness) solid var(--corner-color);
  border-left: var(--corner-thickness) solid var(--corner-color);
}
/* top-right */
.frame-corners::after {
  top: 0;
  right: 0;
  border-top: var(--corner-thickness) solid var(--corner-color);
  border-right: var(--corner-thickness) solid var(--corner-color);
}
/* bottom-left — added via child element */
.frame-corners > .frame-corner-bl {
  bottom: 0;
  left: 0;
  border-bottom: var(--corner-thickness) solid var(--corner-color);
  border-left: var(--corner-thickness) solid var(--corner-color);
}
/* bottom-right */
.frame-corners > .frame-corner-br {
  bottom: 0;
  right: 0;
  border-bottom: var(--corner-thickness) solid var(--corner-color);
  border-right: var(--corner-thickness) solid var(--corner-color);
}

/* Variant via background-image only (no child elements needed)
   (used when you cannot add a child) */
.frame-corners--auto {
  background-image:
    linear-gradient(to right, var(--corner-color, var(--brand-main-base)) var(--corner-size, 0.8rem), transparent var(--corner-size)),
    linear-gradient(to bottom, var(--corner-color, var(--brand-main-base)) var(--corner-size, 0.8rem), transparent var(--corner-size)),
    linear-gradient(to left, var(--corner-color, var(--brand-main-base)) var(--corner-size, 0.8rem), transparent var(--corner-size)),
    linear-gradient(to bottom, var(--corner-color, var(--brand-main-base)) var(--corner-size, 0.8rem), transparent var(--corner-size)),
    linear-gradient(to right, var(--corner-color, var(--brand-main-base)) var(--corner-size, 0.8rem), transparent var(--corner-size)),
    linear-gradient(to top, var(--corner-color, var(--brand-main-base)) var(--corner-size, 0.8rem), transparent var(--corner-size)),
    linear-gradient(to left, var(--corner-color, var(--brand-main-base)) var(--corner-size, 0.8rem), transparent var(--corner-size)),
    linear-gradient(to top, var(--corner-color, var(--brand-main-base)) var(--corner-size, 0.8rem), transparent var(--corner-size));
  background-size:
    var(--corner-size, 0.8rem) var(--corner-thickness, 0.2rem),
    var(--corner-thickness, 0.2rem) var(--corner-size, 0.8rem),
    var(--corner-size, 0.8rem) var(--corner-thickness, 0.2rem),
    var(--corner-thickness, 0.2rem) var(--corner-size, 0.8rem),
    var(--corner-size, 0.8rem) var(--corner-thickness, 0.2rem),
    var(--corner-thickness, 0.2rem) var(--corner-size, 0.8rem),
    var(--corner-size, 0.8rem) var(--corner-thickness, 0.2rem),
    var(--corner-thickness, 0.2rem) var(--corner-size, 0.8rem);
  background-position:
    top left, top left,
    top right, top right,
    bottom left, bottom left,
    bottom right, bottom right;
  background-repeat: no-repeat;
  position: relative;
}

/* ---- SKEWED UNDERLINE ----
   Decorative slanted parallelogram drawn under big numbers.
   Drawn via :after pseudo on .skewed-underline. */
.skewed-underline {
  position: relative;
  display: inline-block;
  padding-left: 0.8rem;
}
.skewed-underline::after {
  content: "";
  display: block;
  width: 100%;
  height: 1.3rem;
  border-top: 0.1rem solid var(--grey-low);
  border-left: 0.1rem solid var(--grey-low);
  position: absolute;
  top: calc(100% + 0.5rem);
  left: 0.4rem;
  transform: skewX(-34deg);
  pointer-events: none;
}
@media (max-width: 575px) {
  .skewed-underline::after { max-width: calc(100% - 0.8rem); }
}

/* Mirrored variant (used by filter-title) */
.skewed-underline--mirror::after {
  border-top: 0.1rem solid var(--grey-low);
  border-right: 0.1rem solid var(--grey-low);
  border-left: none;
  transform: skewX(34deg);
}

/* Yellow accent */
.skewed-underline--accent::after {
  border-color: var(--yellow-base);
  border-width: 0.2rem;
}

/* ==========================================================================
   10. ТАБЛИЦА СРАВНЕНИЯ (compare-table.css)
   ========================================================================== */
.table-scroll { width: 100%; overflow-x: auto; }

.compare-table {
  display: grid;
  grid-template-columns: minmax(20rem, 0.45fr) minmax(20rem, 1fr);
  min-width: 56rem;
  gap: 0.1rem;
  background-color: var(--bg-color);
  border: 0.1rem solid var(--brand-main-low);
}

.compare-table .cell {
  background-color: var(--brand-third-base);
  padding: 2.4rem;
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
  min-width: 20rem;
}

/* Тёмная строка-шапка */
.compare-table .cell--head {
  background-color: var(--brand-main-base);
  padding: 1.6rem 2.4rem;
}
.compare-table .cell--head .cell-title {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 2rem;
  line-height: 118%;
  letter-spacing: -0.04em;
  text-transform: uppercase;
  color: var(--white-base);
}

/* Левая колонка — моно-капс «тип» */
.compare-table .cell-type {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 2.2rem;
  line-height: 122%;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  color: var(--brand-main-base);
}

/* Правая колонка — описание */
.compare-table .cell-desc {
  font-family: var(--font-sans);
  font-size: 1.7rem;
  line-height: 150%;
  letter-spacing: -0.02em;
  color: var(--brand-main-mid);
}

@media (max-width: 575px) {
  .compare-table .cell { padding: 1.6rem; }
  .compare-table .cell--head { padding: 1.4rem 1.6rem; }
}

/* ==========================================================================
   11. ЧЕК-ЛИСТ (checklist.css)
   ========================================================================== */
.checklist { display: flex; flex-direction: column; }

.checklist__item {
  display: flex;
  align-items: flex-start;
  gap: 2.4rem;
  padding: 1.6rem 0;
  border-bottom: 0.1rem solid var(--brand-main-low);
}
.checklist__item:first-child { padding-top: 0; }

/* Моно-номер в бежевом квадрате */
.checklist__num {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  padding: 0.4rem 0.9rem;
  background-color: var(--brand-third-base);
  border: 0.1rem solid var(--brand-main-low);
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 1.4rem;
  color: var(--brand-main-base);
}

.checklist__text {
  margin: 0;
  padding-top: 0.1rem;
  font-family: var(--font-sans);
  font-size: 1.8rem;
  line-height: 150%;
  letter-spacing: -0.02em;
  color: var(--brand-main-base);
}
.checklist__text b { font-weight: 600; }

@media (max-width: 992px) {
  .checklist__item { padding: 1.4rem 0; }
}
@media (max-width: 575px) {
  .checklist__item { gap: 1.6rem; }
  .checklist__text { font-size: 1.6rem; }
}

/* ==========================================================================
   12. ЦИТАТА (quote.css)
   ========================================================================== */
.quote-block {
  display: flex;
  flex-direction: column;
  gap: 3.2rem;
  margin: 0;
  padding: 3.2rem;
  background-color: var(--brand-second-base);
}

.quote-mark {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 6rem;
  line-height: 0.6;
  color: var(--brand-main-base);
}

.quote-text {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 2.2rem;
  line-height: 140%;
  letter-spacing: -0.03em;
  color: var(--brand-main-base);
}

.quote-author { display: flex; align-items: center; gap: 1.6rem; margin-top: 0.8rem; }

.quote-avatar {
  flex: 0 0 auto;
  width: 4.8rem;
  height: 4.8rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--brand-main-base);
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 1.6rem;
  letter-spacing: -0.02em;
  color: var(--brand-second-mid);
}

.quote-author__name {
  display: block;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 1.8rem;
  line-height: 118%; /* капс-имя при переносе на узком не слипается */
  letter-spacing: -0.04em;
  text-transform: uppercase;
  color: var(--brand-main-base);
}
.quote-author__role {
  display: block;
  margin-top: 0.6rem;
  font-family: var(--font-sans);
  font-size: 1.5rem;
  line-height: 130%; /* без явного l-h наследовал тесное → длинная роль на моб слипалась (ratio 0.93) */
  letter-spacing: -0.02em;
  color: var(--brand-main-mid);
}

@media (max-width: 575px) {
  .quote-block { padding: 2rem; gap: 2.4rem; }
  .quote-text { font-size: 1.9rem; }
  .quote-mark { font-size: 4.8rem; }
}

/* ==========================================================================
   13. ОГЛАВЛЕНИЕ / TOC (toc.css)
   ========================================================================== */
.toc-col { position: relative; }

.toc {
  position: sticky;
  top: 11rem;
  display: flex;
  flex-direction: column;
  gap: 2.4rem;
  padding: 2.4rem;
  background-color: var(--brand-second-base);
}

.toc__head {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 1.4rem;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--brand-main-base);
}

.toc__list { display: flex; flex-direction: column; }

.toc__item {
  display: flex;
  align-items: stretch;
  gap: 1.6rem;
  padding: 1.6rem;
  text-decoration: none;
  transition: background-color 0.3s;
}
.toc__indicator {
  flex: 0 0 0.2rem;
  width: 0.2rem;
  background-color: var(--brand-main-low);
  transition: background-color 0.3s, flex-basis 0.3s;
}
.toc__label { display: flex; align-items: flex-start; gap: 1.2rem; }
.toc__num {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 1.4rem;
  color: var(--brand-main-mid);
  transition: color 0.3s;
}
.toc__title {
  font-family: var(--font-sans);
  font-size: 1.6rem;
  line-height: 120%;
  letter-spacing: -0.02em;
  color: var(--brand-main-mid);
  transition: color 0.3s;
}

.toc__item:hover { background-color: var(--white-mid); }

.toc__item.is-active { background-color: var(--brand-second-mid); }
.toc__item.is-active .toc__indicator {
  background-color: var(--brand-main-base);
  flex-basis: 0.3rem;
  width: 0.3rem;
}
.toc__item.is-active .toc__num,
.toc__item.is-active .toc__title { color: var(--brand-main-base); }

/* На планшете/мобиле оглавление перестаёт «прилипать» (становится
   обычным блоком). Переезд наверх колонки — забота раскладки-родителя
   (см. article.css → .article-wrapper). */
@media (max-width: 992px) {
  .toc { position: relative; top: 0; padding: 1.6rem; }
}

/* ==========================================================================
   14. FAQ-АККОРДЕОН (accordion.css) + PATCH-B
   ========================================================================== */
.faq-list {
  counter-reset: item 0;
}

/* ---- Обрамлённый вариант (faq-section__content) ----
   Боевая обёртка с главной/ипотеки: тонкая рамка вокруг всей
   стопки. Имя 1:1 с dbrus.ru. Внутренние разделители .faq-item
   рисуются как обычно; у первого border-top уже снят, поэтому
   двойной линии у верхней кромки рамки нет. */
.faq-section__content {
  border: 0.1rem solid var(--grey-low);
}

.faq-list .faq-item {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  column-gap: 6.5rem;
  padding: 3.2rem 8rem 3.1rem 1.5rem;
  border-top: 0.1rem solid var(--grey-low);
  counter-increment: item 1;
  position: relative;
}
.faq-list .faq-item:first-child { border-top: none; }

@media (max-width: 1440px) {
  .faq-list .faq-item { column-gap: 4.5rem; }
}
@media (max-width: 1336px) {
  .faq-list .faq-item { grid-template-columns: 60rem 1fr; }
}
@media (max-width: 992px) {
  .faq-list .faq-item {
    grid-template-columns: 100%;
    row-gap: 3rem;
    padding: 1.8rem 1.6rem;
  }
}
@media (max-width: 575px) {
  .faq-list .faq-item { row-gap: 2.7rem; }
}

/* ---- Сторона вопроса ---- */
.faq-list .item-title {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  align-self: flex-start;
  column-gap: 3.2rem;
  font-family: var(--font-sans);
  font-size: 2rem;
  line-height: 100%;
  letter-spacing: -0.04em;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--brand-main-base);
  margin: 0;
  cursor: pointer;
}
.faq-list .item-title:hover { color: var(--brand-second-strong); }
@media (max-width: 992px) {
  .faq-list .item-title {
    padding: 0 4rem 0 0;
    font-size: 1.8rem;
    column-gap: 1.6rem;
  }
}
@media (max-width: 575px) {
  .faq-list .item-title { font-size: 1.6rem; line-height: 120%; }
}

/* Нумерованная плашка-префикс */
.faq-list .item-title::before {
  content: counter(item);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.8rem;
  height: 2.8rem;
  flex: 0 0 2.8rem;
  border: 0.1rem solid var(--brand-main-low);
  background-color: var(--brand-main-low);
  font-family: var(--font-mono);
  font-size: 1.4rem;
  line-height: 100%;
  letter-spacing: -0.02em;
  color: var(--brand-main-base);
}
@media (max-width: 992px) {
  .faq-list .item-title::before {
    width: 2.7rem;
    height: 2.7rem;
    flex: 0 0 2.7rem;
  }
}

/* ---- Сторона ответа ---- */
.faq-list .item-descr {
  display: none;
  font-size: 1.8rem;
  line-height: 100%;
  letter-spacing: -0.04em;
  max-width: 45rem;
  color: var(--brand-main-mid);
}
/* PATCH-B: правило display:block по .active УДАЛЕНО (live-theme-map §1.10).
   Боевой common.js тогглит .active мгновенно по клику и АНИМИРУЕТ .item-descr
   jQuery-инлайном (slideUp/slideDown 300ms). Любое CSS display-правило по
   .active показывает/прячет элемент ДО старта слайда — аккордеон «щёлкает»
   вместо плавной анимации. Оставлен только базовый display:none выше. */
@media (max-width: 992px) {
  .faq-list .item-descr {
    font-size: 1.6rem;
    padding: 0 4.4rem;
    max-width: calc(100% - 4rem);
  }
}
@media (max-width: 575px) {
  /* 18.08: номер вопроса съедал ширину заголовка на узком экране — прячем его
     и снимаем отступ ответа, который стоял ровно под цифру. */
  .faq-list .item-title::before { display: none; }
  .faq-list .item-descr { padding: 0; }
}
.faq-list .item-descr p + p { margin-top: 1.8rem; }

/* ---- Тоггл (срезанный квадрат, внутренний слой для hover) ---- */
.faq-list .item-link {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 4.8rem;
  height: 4.8rem;
  background-color: var(--brand-second-mid);
  color: var(--brand-main-base);
  border: none;
  position: absolute;
  top: 3.1rem;
  right: 1.4rem;
  cursor: pointer;
  clip-path: polygon(16% 0%, 100% 0, 100% 0, 100% 84%, 84% 100%, 0 100%, 0 100%, 0% 16%);
}

/* Внутренняя заливка — по умолчанию совпадает с фоном плашки (рамки
   не видно); на hover становится третичным бежевым, проявляя уголки. */
.faq-list .item-link::before {
  content: "";
  position: absolute;
  top: 0.2rem;
  left: 0.2rem;
  width: calc(100% - 0.4rem);
  height: calc(100% - 0.4rem);
  background-color: var(--brand-second-mid);
  clip-path: polygon(16% 0%, 100% 0, 100% 0, 100% 84%, 84% 100%, 0 100%, 0 100%, 0% 16%);
  transition: background-color 0.3s;
  pointer-events: none;
}
.faq-list .item-link:hover::before { background-color: var(--brand-third-mid); }
@media (max-width: 992px) {
  .faq-list .item-link {
    width: 3.2rem;
    height: 3.2rem;
    top: 1.5rem;
    right: 1.6rem;
  }
}

/* Иконка-крест: в покое rotate(45deg) → «+», в .active rotate(0) → «×» */
.faq-list .item-link .icon {
  pointer-events: none;
  position: relative;
  z-index: 1;
  font-size: 1.8rem;
  line-height: 1.8rem;
  color: var(--brand-main-base);
  transform: rotate(45deg);
  transition: transform 0.3s;
}
@media (max-width: 992px) {
  .faq-list .item-link .icon { font-size: 1.4rem; line-height: 1.4rem; }
}
.faq-list .faq-item.active .item-link .icon { transform: rotate(0deg); }

/* ==========================================================================
   15. ШАБЛОН СТАТЬИ — каркас/типографика (article.css) + PATCH-E
   ========================================================================== */
.article {
  position: relative;
  width: 100%;
  padding: 13rem 0 10rem;
  /* NB: без overflow:hidden — иначе ломается sticky-оглавление.
     Горизонтальный вынос watermark клипает body{overflow-x:hidden}. */
}
.article__bg {
  position: absolute;
  top: 0;
  right: 0;
  width: 60.8rem;
  height: 43.9rem;
  max-width: 45vw;
  /* PATCH-E: относительный путь → прод-абсолютный (файл уже на боевом). */
  background: url('/assets/template/new_design/images/svg/main_bg.svg') no-repeat top right / contain;
  opacity: 0.6;
  pointer-events: none;
  z-index: 0;
}
.article__inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 8rem;
}

/* ───── Шапка: мета + заголовок ───── */
.article-head { display: flex; flex-direction: column; gap: 4.8rem; }

.article-title-group { display: flex; flex-direction: column; gap: 2.4rem; }
.article-meta { display: flex; align-items: center; gap: 3.2rem; }
.article-date {
  font-family: var(--font-sans);
  font-size: 1.8rem;
  letter-spacing: -0.04em;
  color: var(--brand-main-mid);
}
.article-title { margin: 0; max-width: 150rem; text-wrap: balance; }

/* ───── Двухколоночная раскладка: тело + оглавление ───── */
.article-wrapper {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 38rem;
  gap: 6.4rem;
}
.article-body {
  display: flex;
  flex-direction: column;
  gap: 6.4rem;
  min-width: 0;
}
.article-section {
  display: flex;
  flex-direction: column;
  gap: 2.4rem;
  scroll-margin-top: 11rem;
}
.article-section .section-title { margin: 0; }

/* Подзаголовок H3 (моно-капс, шкала h3) */
.article-subhead {
  margin: 0;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 2.5rem;
  line-height: 104%;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  color: var(--brand-main-base);
}

/* Абзац тела */
.article-p {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 1.8rem;
  line-height: 160%;
  letter-spacing: -0.02em;
  color: var(--brand-main-mid);
}
.article-p--lead {
  font-size: 2.2rem;
  line-height: 150%;
  color: var(--brand-main-base);
}
/* Ссылка в тексте — тон тела, подчёркивание */
.article-p a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.3rem;
  transition: color 0.3s;
}
.article-p a:hover { color: var(--brand-main-base); }

/* ───── Медиа-фигуры ───── */
.media-figure { display: flex; flex-direction: column; gap: 1.6rem; margin: 0; }

/* Видео-постер — компонент player.css (.video-player/.video-poster).
   Герой статьи — кинематографичная пропорция. */
.media-figure--hero .video-poster { aspect-ratio: 2.7; }

/* Фото с фирменными уголками (frame.css → .frame-corners).
   Локально увеличиваем уголок до 1.4rem (как в макете статьи). */
.photo-figure {
  position: relative;
  width: 100%;
  aspect-ratio: 1.7;
  overflow: hidden;
  background-color: var(--brand-third-base);
  --corner-size: 1.4rem;
  --corner-thickness: 0.2rem;
  --corner-color: var(--brand-main-base);
}
.photo-figure img { width: 100%; height: 100%; object-fit: cover; }

/* Галочка «показать кадр целиком» блока «Медиа» (решение владельца 06.09.2026).
   Коробка кадра держит aspect-ratio 1.7 и режет всё, что в неё не укладывается:
   схема «финская против канадской» 1479 × 1063 теряла 18 % с подписями, скриншот
   Домклика 1400 × 410 резался по краям. Обход был — поле «Пропорция кадра» инлайном,
   — но его надо знать и вписывать руками, и менеджер про него забывает.
   С галочкой кадр получает СВОЮ пропорцию: высокий станет выше коробки (1600 × 1429
   в колонке 916 px даёт 818 px вместо 539), широкий — ниже (1400 × 410 даёт 268 px).
   Замер headless 06.09 на демо-странице Materials/00-meta/quality-reports/media-fit-demo-2026-09-06.

   Фотографии галочкой не лечат: им место в файле подрезать (решение 04.09) — иначе
   вернётся та самая высота, из-за которой подрезку и делали.

   Специфичность равна базовому правилу и ниже боковых раскладок (.media-figure--side
   .photo-figure — 0,2,0), поэтому боковые врезки и видео своё поведение сохраняют. */
.photo-figure--fit { aspect-ratio: auto; }
.photo-figure--fit > img { height: auto; object-fit: contain; }

.figure-caption {
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
  padding: 0.8rem 0 0;
}
.figure-caption__eyebrow {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 1.4rem;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--brand-main-base);
}
.figure-caption__text {
  font-family: var(--font-sans);
  font-size: 1.6rem;
  line-height: 140%;
  letter-spacing: -0.02em;
  color: var(--brand-main-mid);
  max-width: 78rem;
}

/* ───── CTA-плитка ───── */
.article-cta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2rem;
  padding: 3.2rem;
  background-color: var(--brand-second-base);
}
.article-cta__title {
  margin: 0;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 3.2rem;
  line-height: 104%;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  color: var(--brand-main-base);
}
.article-cta__text {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 1.7rem;
  line-height: 155%;
  letter-spacing: -0.02em;
  color: var(--brand-main-mid);
}
.article-cta__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
  font-family: var(--font-sans);
  font-size: 1.7rem;
  line-height: 150%;
  letter-spacing: -0.02em;
  color: var(--brand-main-mid);
}
.article-cta__list li {
  position: relative;
  padding-left: 2.4rem;
}
.article-cta__list li::before {
  content: "";
  position: absolute;
  left: 0.4rem;
  top: 0.85em;
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  background-color: var(--brand-main-mid);
}
.article-cta__list a,
.article-cta__text a {
  color: var(--brand-main-base);
  text-decoration: underline;
  text-underline-offset: 0.3rem;
  white-space: nowrap;
}
/* Кнопка пошире, чтобы длинный лейбл всегда влезал */
.article-cta__btn {
  margin-top: 0.8rem;
  width: auto;
  min-width: 0;
  padding: 0 6.4rem;
}
/* Анти-дребезг ховер-скрэмбла: боевой common.js (TextAnimator) вешается на все
   .primary-btn и подменяет буквы — без фикс-ширины .btn-txt коробка кнопки
   «скачет». Приём и величина — по прецеденту /voprosy/ (voprosy.css §15.2,
   деплой voprosy-btn-antijitter-2026-07-21, тот же лейбл «Записаться на
   экскурсию»); 26rem = замер 25.15rem на стенде + запас до целого rem. */
.article-cta__btn .btn-txt { overflow: visible; white-space: nowrap; width: 26rem; }

/* ───── Строка тегов + ссылка назад ───── */
.article-tags {
  display: flex;
  flex-wrap: wrap;              /* 15.08: без переноса чипы уходили за правый край статьи */
  align-items: baseline;
  gap: 1.6rem;
  padding-top: 2.4rem;
  border-top: 0.1rem solid var(--brand-main-low);
}
.article-tags__label {
  flex: 0 0 auto;
  font-family: var(--font-sans);
  font-size: 1.6rem;
  letter-spacing: -0.06em;
  text-transform: uppercase;
  color: var(--brand-main-base);
}
/* Теги статьи — бежевый контурный вид (наследуют тип от .tag,
   переопределяем только цвет/вес/паддинг). */
.article-tags .tag {
  background-color: transparent;
  border: 0.1rem solid var(--brand-second-strong);
  color: var(--brand-second-strong);
  font-weight: 400;
  padding: 0.3rem 1.6rem;
  letter-spacing: -0.02em;
}
.article-tags .tag:hover {
  background-color: transparent;
  border-color: var(--brand-main-base);
  color: var(--brand-main-base);
}

.article-back {
  display: inline-flex;
  align-items: center;
  gap: 0.8rem;
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 1.4rem;
  text-transform: uppercase;
  color: var(--brand-main-base);
  text-decoration: none;
}
.article-back .icon-slider_arrow {
  transform: scale(-1, 1);
  display: inline-flex;
  font-size: 1.6rem;
}
.article-back:hover .article-back__txt {
  text-decoration: underline;
  text-underline-offset: 0.3rem;
}

/* ════════════ Адаптив ════════════ */
/* ПЛАНШЕТ (≤992px): одна колонка, оглавление наверх (order:-1)
   и без sticky (см. toc.css). Поджатые вертикальные ритмы. */
@media (max-width: 992px) {
  .article { padding: 8.8rem 0 7rem; }
  .article__inner { gap: 4rem; }
  .article-head { gap: 3.2rem; }

  .article-wrapper { grid-template-columns: 1fr; gap: 2.4rem; }
  .toc-col { order: -1; }

  .article-body { gap: 4rem; }
  .article-section { gap: 2.8rem; }
  .article-subhead { font-size: 2.2rem; }
  /* Промежуточная ступень — симметрично .article-subhead (см. ≤575 ниже). */
  .article-p--lead { font-size: 2rem; }
  .article-cta__title { font-size: 2.8rem; }
}
@media (max-width: 575px) {
  .article-meta { flex-wrap: wrap; gap: 1.6rem; }
  .article-p--lead { font-size: 1.9rem; }
  /* Герой-видео: c кинематографичной 2.7 на телефоне — узкая полоса,
     поэтому ближе к портрету. Прочие фигуры держат свои пропорции. */
  .media-figure--hero .video-poster { aspect-ratio: 1.6; }
  .article-cta { padding: 2rem; }
  .article-cta__title { font-size: 2.6rem; }
  .article-cta__btn { width: 100%; min-width: 0; padding: 0 2rem; }
  /* фикс-ширина .btn-txt нужна только под ховер-скрэмбл (десктоп); на телефоне
     ховера нет, а 26rem в узкой кнопке пришлось бы сжимать flex-shrink'ом */
  .article-cta__btn .btn-txt { width: auto; }
  .article-tags { flex-direction: column; }
  .article-tags .tag { padding: 0.5rem 1.4rem; }
  .article-subhead { font-size: 2rem; }
}

/* ==========================================================================
   16. МЕЛКИЕ БЛОКИ ТЕЛА СТАТЬИ (article-extra.css)
   ========================================================================== */
/* Подзаголовок H3 (.article-subhead из article.css) внутри секции: воздух
   сверху, чтобы группировался со СЛЕДУЮЩИМ блоком и отделялся от предыдущего
   (gap секции 2.4rem + этот margin = ~4rem над подзаголовком). */
.article-subhead { margin-top: 1.6rem; }
.article-section > .article-subhead:first-child { margin-top: 0; }

/* Лейбл под-блока (моно-капс) — как figure-caption__eyebrow */
.article-eyebrow {
  margin: 0;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 1.6rem;
  line-height: 120%;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--brand-main-base);
}

/* ───── Маркированный список тела ───── */
.article-list {
  margin: 0; padding: 0; list-style: none;
  display: flex; flex-direction: column; gap: 1.4rem;
  font-family: var(--font-sans);
  font-size: 1.8rem; line-height: 150%; letter-spacing: -0.02em;
  color: var(--brand-main-mid);
}
.article-list > li { position: relative; padding-left: 2.8rem; }
/* Круглый маркер по образцу Figma (обычная «точка») во ВСЕХ маркированных
   списках тела, включая callout «Что должно насторожить» (правка владельца 09.06).
   Нумерованные списки используют свою квадратную плашку (см. ниже). */
.article-list > li::before {
  content: ""; position: absolute; left: 0.4rem; top: 0.6em;
  width: 0.7rem; height: 0.7rem; border-radius: 50%;
  background-color: var(--brand-second-strong);
}
.article-list b { color: var(--brand-main-base); }
.article-list a {
  color: var(--brand-main-base);
  text-decoration: underline; text-underline-offset: 0.3rem;
}

/* Нумерованный список — DS-плашка номера (как checklist__num / accordion item-title::before):
   моно-номер «01» в бежевом квадрате с рамкой. Острые углы, без жёлтого. */
.article-list--num { counter-reset: aln; gap: 0; }
.article-list--num > li { padding: 1.6rem 0 1.6rem 4.4rem; }
.article-list--num > li + li { border-top: 0.1rem solid var(--brand-main-low); }
.article-list--num > li::before {
  counter-increment: aln;
  content: counter(aln); /* обычный номер 1, 2, 3 (без ведущего нуля — правка владельца) */
  border-radius: 0; /* острый квадрат-плашка по бренду; гасит круглый маркер .article-list */
  top: 1.6rem; left: 0;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 2.8rem; height: 2.8rem; padding: 0 0.6rem;
  background-color: var(--brand-third-base);
  border: 0.1rem solid var(--brand-main-low);
  font-family: var(--font-mono); font-weight: 500; font-size: 1.4rem;
  line-height: 1; letter-spacing: -0.02em;
  color: var(--brand-main-base);
}

/* ───── Callout «Что должно насторожить» — НЕЖНАЯ кремово-бежевая подложка
   по образцу DS-капсулы faq-хаба (.faq-capsule: rgba(235,211,175,0.35)).
   Сплошной --brand-second-mid (#ebd3af) был слишком плотным (как вкладка-фильтр),
   а нейтральный #e6e1db сливался с цитатой. Полупрозрачный пшеничный 35% —
   тёплый «сигнал, осторожнее», отделён и от цитаты, и от белых карточек. ───── */
.article-callout {
  /* gap = отступ метки от текста; 1.6rem владелец счёл тесным (22.07) */
  display: flex; flex-direction: column; gap: 2.4rem;
  padding: 2.4rem 2.8rem;
  background-color: rgba(235, 211, 175, 0.35);
  border-left: 0.3rem solid var(--brand-second-strong);
}
/* Шрифт метки — «обычный» Inter 600 капсом, 1:1 с «СОДЕРЖАНИЕ СТАТЬИ» (.toc__head).
   Правка владельца 22.07 (тот же заход, что и метка «Краткое содержание»). */
.article-callout__label {
  margin: 0;
  font-family: var(--font-sans); font-weight: 600; font-size: 1.6rem;
  line-height: 125%; /* без явного l-h наследовал тесное значение → на узком капс-строки слипались (моб ratio 0.88) */
  letter-spacing: -0.02em; text-transform: uppercase; color: var(--brand-main-base);
}

/* ───── «Как у нас» — нативная самопрезентация: тонкий левый акцент, БЕЗ коробки/заливки ───── */
.article-brand { padding-left: 2rem; border-left: 0.2rem solid var(--brand-second-strong); }
.article-brand .article-p { color: var(--brand-main-base); }
.article-brand .article-eyebrow { margin-bottom: 0.8rem; color: var(--brand-second-strong); }

/* ───── Редакторский флаг «нужны данные владельца» (виден; в прод не идёт) ───── */
.article-flag {
  font-family: var(--font-mono); font-size: 1.4rem; line-height: 140%;
  color: var(--brand-main-base);
  border: 0.1rem dashed var(--brand-second-strong);
  padding: 0.2rem 0.8rem; display: inline;
}

/* ───── Сравнение фото 2-в-ряд (окно/угол: тёплый vs холодный) ───── */
.article-duo { display: grid; grid-template-columns: 1fr 1fr; gap: 1.6rem; }
@media (max-width: 575px) { .article-duo { grid-template-columns: 1fr; } }

/* ───── FAQ (нативный details — file://-надёжно; на проде = живой accordion.css) ───── */
.article-faq { display: flex; flex-direction: column; }
.article-faq__item { border-top: 0.1rem solid var(--brand-main-low); }
.article-faq__item:last-child { border-bottom: 0.1rem solid var(--brand-main-low); }
.article-faq__q {
  list-style: none; cursor: pointer;
  display: flex; justify-content: space-between; align-items: flex-start; gap: 2rem;
  padding: 2.4rem 0;
  font-family: var(--font-mono); font-weight: 500; font-size: 2rem; line-height: 120%;
  letter-spacing: -0.03em; text-transform: uppercase; color: var(--brand-main-base);
}
.article-faq__q::-webkit-details-marker { display: none; }
.article-faq__q::after {
  content: "+"; flex: 0 0 auto;
  font-family: var(--font-mono); font-weight: 400; font-size: 2.8rem; line-height: 0.8;
}
.article-faq__item[open] .article-faq__q::after { content: "\2013"; }
.article-faq__a { padding: 0 0 2.8rem; display: flex; flex-direction: column; gap: 1.2rem; }

/* ───── Источники ───── */
.article-sources {
  margin: 0; padding: 0; list-style: none; counter-reset: asrc;
  display: flex; flex-direction: column; gap: 1.2rem;
  font-family: var(--font-sans); font-size: 1.6rem; line-height: 150%;
  letter-spacing: -0.02em; color: var(--brand-main-mid);
}
.article-sources > li { position: relative; padding-left: 3.2rem; }
.article-sources > li::before {
  counter-increment: asrc; content: counter(asrc) ".";
  position: absolute; left: 0; top: 0;
  font-family: var(--font-mono); font-weight: 500; color: var(--brand-main-base);
}
.article-sources a { color: var(--brand-main-base); text-decoration: underline; text-underline-offset: 0.3rem; }

/* ───── Блок авторов (E-E-A-T) ───── */
.article-authors {
  display: flex; flex-direction: column; gap: 2.4rem;
  padding: 2.8rem 0; border-top: 0.1rem solid var(--brand-main-low);
  border-bottom: 0.1rem solid var(--brand-main-low);
}
.article-authors__head {
  margin: 0;
  font-family: var(--font-mono); font-weight: 500; font-size: 1.4rem;
  letter-spacing: -0.02em; text-transform: uppercase; color: var(--brand-main-mid);
}
.article-author { display: flex; align-items: flex-start; gap: 1.6rem; }
.article-author__avatar {
  flex: 0 0 auto; width: 5.6rem; height: 5.6rem; border-radius: 50%;
  object-fit: cover; background-color: var(--brand-third-base);
  filter: grayscale(1);
}
.article-author__info { display: flex; flex-direction: column; gap: 0.4rem; min-width: 0; }
.article-author__name {
  font-family: var(--font-sans); font-weight: 600; font-size: 1.8rem;
  letter-spacing: -0.02em; color: var(--brand-main-base);
}
.article-author__role {
  font-family: var(--font-sans); font-size: 1.6rem; line-height: 150%;
  letter-spacing: -0.02em; color: var(--brand-main-mid);
}

/* Заголовок «Источники / Вопросы и ответы» — как section-title, но без огромной шкалы H2 при желании
   (оставляем section-title из DS; здесь только мелкие хвосты). */
.article-section--tail { gap: 2rem; }

@media (max-width: 992px) {
  .article-list, .article-sources { font-size: 1.7rem; }
  .article-callout { padding: 2rem 2.2rem; }
  .article-faq__q { font-size: 1.8rem; }
}
@media (max-width: 575px) {
  .article-faq__q { font-size: 1.6rem; }
  .article-callout { padding: 1.8rem 2rem; }
}

/* ───── Докрутка 2026-06-08 (по правкам владельца) ───── */

/* Номер секции в заголовке (вместо «Проверка N из 10»): моно-цифра-акцент. */
.article-secnum {
  font-family: var(--font-mono);
  font-weight: 500;
  margin-right: 1.6rem;
}
.article-secnum::after { content: "."; }

/* Видео-анимация в photo-figure ведёт себя как img (DS .photo-figure img):
   заполняет рамку, object-fit cover. Aspect задан inline на .photo-figure. */
.photo-figure video { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Медиа-фигура «видео слева, подпись справа» (компактное квадратное видео
   не центрируем, а прижимаем влево; текст-описание идёт колонкой справа). */
.media-figure--side { flex-direction: row; align-items: flex-end; gap: 2.8rem; margin-top: 2.8rem; }
.media-figure--side .photo-figure { flex: 0 0 40rem; max-width: 40rem; margin: 0; }
/* Пропорция — по натуральному размеру медиа. Конструктор inline-стиль
   aspect-ratio не выводит (в ручной вёрстке он был), а дефолт 1.7 у
   .photo-figure резал вертикальное видео в полосу.
   Коробку задаёт картинка: у <img> высота auto считается по натуральному
   размеру, у <video> — нет (замер 17.08: 500×150 вместо 500×519). Поэтому
   меркой под видео служит его же постер (.media-sizer), а видео кладётся
   в ту же ячейку сетки поверх. Сетка, а не absolute: абсолютное видео
   перекрыло бы левый верхний уголок рамки (он идёт ::before, то есть
   раньше по документу). Видео без постера — .photo-figure--fixed ниже. */
.media-figure--side .photo-figure { aspect-ratio: auto; display: grid; }
.media-figure--side .photo-figure > img,
.media-figure--side .photo-figure > video { grid-area: 1 / 1; }
.media-figure--side .photo-figure > img { height: auto; }
/* Мерка держит высоту, но не рисуется: видимой она просвечивает под видео
   (кадр постера поверх кадра анимации). visibility, а не display — коробку
   надо сохранить. Свой постер видео показывает само, атрибутом poster. */
.media-figure--side .photo-figure > .media-sizer { visibility: hidden; }
.media-figure--side .photo-figure--fixed { aspect-ratio: 1.7; }
/* Узкая врезка под вертикальный кадр: ролики канала снимают вертикалью 9:16, и в
   колонке 40rem такое видео вырастает до ~71rem по высоте — полстраницы на телефон
   в руке. 30rem дают 53rem высоты. Класс ставит шаблон сам, когда у медиа есть и свой
   файл, и ссылка на первоисточник (23.08, плеер ролика «Главные минусы каркасного дома»). */
.media-figure--side-narrow .photo-figure { flex-basis: 30rem; max-width: 30rem; }
.media-figure--side-narrow .photo-figure > video { width: 100%; height: 100%; }
.media-figure--side .figure-caption { flex: 1 1 auto; padding: 0; }
.media-figure--side .figure-caption__text { font-size: 1.5rem; line-height: 150%; }
@media (max-width: 767px) {
  .media-figure--side { flex-direction: column; align-items: stretch; gap: 1.6rem; }
  .media-figure--side .photo-figure { flex: 1 1 auto; max-width: 36rem; }
  .media-figure--side-narrow .photo-figure { max-width: 30rem; }
}

/* Потолок высоты бокового кадра — 39rem (решение владельца 23.08: «иллюстрация не такая
   огромная»). Вертикальная картинка при ширине 40rem вырастала до 52rem и подавляла
   разворот. Ограничиваем высоту, ширину коробки отдаём самой картинке; горизонтальные
   кадры потолка не достают (замер на м4/м5: высоты 248–357 px) и не меняются.
   Три оговорки, без которых правило не работает:
     • aspect-ratio: auto — иначе базовое 1.7 режет кадр в полосу (было 235 px);
     • flex: 0 0 auto — при flex-shrink: 1 строка дополнительно сжимала кадр;
     • :not(:has(video)) — у 3D-видео коробка обязана оставаться grid, там .media-sizer
       лежит вторым слоем и держит высоту (замер 17.08). */
/* 10.G-krug3 — боковая врезка: рамка в половину колонки, кадр по центру, подпись
   справа внизу. Решение владельца 24.08 по живой примерке в статье м5
   (`Materials/07-tech/prototypes-poleznoe/_primerka-3d-vrezki-2026-08-24.html`).
   Заменяет правила круга 2, где ширину рамки задавала сама картинка.

   Зачем половина. Рамка облегала кадр, и у трёх врезок м5 она выходила 260, 299 и 328 px
   при колонке 955 — блоки читались вразнобой, а справа оставалось 54–57% пустого поля.
   Теперь рамка у всех 478 px, объект стоит в ней по центру. Замер: блок 448 px против
   390 прежних, раздел «Плюсы» растёт с 1177 до 1235.

   Ко всем боковым врезкам, а не только к 3D-схемам (второе решение владельца 24.08):
   из 14 боковых врезок блога 10 — именно 3D-схемы, включая все шесть в уже
   опубликованных статьях, и отдельная галочка в конструкторе не окупается. На четырёх
   фотографиях м4 приём проверен снимком (proba-vse-bokovye-m4-*.png).

   Подложку под кадр не возвращать: светлая плашка ломает гашение белого фона — multiply
   умножает белое поле рендера на неё, и белый прямоугольник возвращается (замер 24.08,
   снимок scena-sh48p-1440-plyusy.png). */
.media-figure--side .photo-figure:not(:has(video)) {
  display: grid; place-items: center; flex: 0 0 50%; width: 50%;
  /* Поля со ВСЕХ сторон, а не только сверху и снизу (решение владельца 29.08): при
     `2.4rem 0` кадр упирался в боковые уголки рамки, и она читалась как обрезка, а не
     как рамка. Замер того же дня по схеме укосины: объект занимает 1096 px из 1100 по
     ширине — собственных полей у файла нет, поле обязана дать вёрстка. */
  max-width: none; max-height: none; aspect-ratio: auto; padding: 2.4rem;
  /* Подложку рамки снимаем. У .photo-figure она задана базовым правилом темы
     (--brand-third-base, на боевом это #e6e1db) и раньше не показывалась: рамка
     облегала кадр. Теперь рамка шире объекта, и подложка встала вокруг него светлой
     плашкой — поймано на стенде 24.08, снимок stend-m5-1440-2.png. */
  background-color: transparent;
}
.media-figure--side .photo-figure:not(:has(video)) > img {
  display: block; width: auto; max-width: 100%; height: auto; max-height: 40rem;
  object-fit: contain;
}
/* Ниже 768 боковая раскладка складывается в колонку, и «половина» мерит уже долю по
   главной оси, а не ширину: замер 24.08 на 390 — рамка 179 px при колонке 359, кадр
   вдвое меньше нужного. На телефоне рамка занимает колонку целиком, кадр идёт по её
   ширине, а потолок высоты снимается: с ним вертикальная схема упиралась в 40rem и
   выходила 306 px вместо 359 — на телефоне кадр стал бы МЕЛЬЧЕ прежнего (замер 24.08).
   Поля сцены там тоже не нужны: рамка облегает кадр, как было. */
@media (max-width: 767px) {
  .media-figure--side .photo-figure:not(:has(video)) {
    flex: 1 1 auto; width: 100%; max-width: 36rem; padding: 0;
  }
  .media-figure--side .photo-figure:not(:has(video)) > img {
    width: 100%; max-height: none;
  }
}

/* Ролик, который играет прямо в статье: текст обтекает кадр (решение владельца 23.08).
   Вертикальный кадр 9:16 рядом с подписью в две строки оставлял пустое поле во весь свой
   рост, и боковая раскладка не спасала ни одним выравниванием подписи. Кадрируем до 3:4
   средствами страницы — сам mp4 не трогаем, пропорция меняется правкой одной строки.
   Смещение 22% от верха: лицо в верхней половине кадра, вшитые субтитры на 64–70% высоты,
   в 3:4 помещается и то, и другое (замер по стоп-кадрам 23.08). Класс ставит шаблон сам,
   когда у медиа есть и свой файл, и ссылка на первоисточник. */
/* Ролик канала — та же раскладка, что у всех фото статьи (правка владельца 24.08:
   «текст должен быть справа внизу от видео, как и все фото»): кадр слева, подпись
   колонкой справа, прижата к низу кадра. Отличий от --side ровно два: ширина 34rem
   и пропорция 3/4 с кадрированием, потому что исходник вертикальный 9:16.
   Коробка — grid, как у --side, и мерка скрыта. Без этого <video> вставал ПОД
   меркой-постером и целиком уходил под overflow: hidden: на странице был виден
   постер, клик попадал в картинку, и ролик «не воспроизводился» (замер 24.08 —
   мерка на 0, видео на 453 при высоте рамки 453). */
.media-figure--flow { flex-direction: row; align-items: flex-end; gap: 2.8rem; margin-top: 2.8rem; }
.media-figure--flow .photo-figure {
  flex: 0 0 34rem; max-width: 34rem; margin: 0;
  aspect-ratio: 3 / 4; display: grid; grid-template-rows: minmax(0, 1fr);
  grid-template-columns: minmax(0, 1fr); overflow: hidden;
}
.media-figure--flow .photo-figure > img,
.media-figure--flow .photo-figure > video {
  grid-area: 1 / 1; width: 100%; height: 100%;
  object-fit: cover; object-position: center 22%; display: block;
}
.media-figure--flow .photo-figure > .media-sizer { visibility: hidden; }
.media-figure--flow .figure-caption { padding: 0; }
@media (max-width: 767px) {
  /* На узком экране кадр занимает всю колонку, как у обычных фото статьи: при
     max-width: 34rem справа оставалось 20 px пустоты, которой у --side нет
     (замер 24.08 на 390: фото 360, ролик 340 при колонке 360). */
  .media-figure--flow { flex-direction: column; align-items: stretch; gap: 1.6rem; }
  .media-figure--flow .photo-figure { flex: 1 1 auto; max-width: 100%; }
}

/* ───── Карточка «о чём ролик» рядом с кадром (вид принят владельцем 24.08) ─────
   Справа от вертикального кадра оставалось пустое поле ≈400×380, заполненное тремя
   строками подписи, — владелец на приёмке: «мне сам блок не нравится, большая дыра
   справа». Поле занимает содержание ролика: название, тезисы с таймкодами, подпись
   говорящего. Кроп до 3:4 на десктопе при этом снят — высоту держит карточка, и
   резать вертикальный ролик больше незачем (на узком экране кроп возвращается).
   Собрано на превью _preview-kartochka-rolika-2026-08-24.html: варианты А–Г →
   доводка Г → шапки Ш0–Ш3 → мобильные М1–М4; принят Ш3 + М4. */

/* Скобки рамки на тёмном кадре. Дефолт --corner-color графитовый (тот же #373d42,
   что и кадр ролика) — на фото фон светлый и скобки читаются, на ролике их не видно
   вовсе (замер 24.08). Здесь уводим в кремовый цвет фона страницы. */
.media-figure--flow .photo-figure { --corner-color: var(--bg-color); }

/* Полный экран и «картинка в картинке»: кадрирование снимается. Правила рамки
   действуют и на развёрнутом видео — object-fit: cover растягивал вертикальный
   ролик 720×1280 на экран 1280×800 и резал его до горизонтальной полосы (замер
   24.08: fit=cover, pos=50% 22%). Три селектора РАЗДЕЛЬНЫМИ правилами, не через
   запятую: неизвестный браузеру псевдокласс в общем списке роняет всё правило
   целиком, и Firefox остался бы без правки из-за вебкитового -webkit-full-screen. */
.media-figure--flow .photo-figure > video:fullscreen { object-fit: contain; object-position: center center; }
.media-figure--flow .photo-figure > video:-webkit-full-screen { object-fit: contain; object-position: center center; }
.media-figure--flow .photo-figure > video:picture-in-picture { object-fit: contain; object-position: center center; }

/* Кадр рядом с карточкой: 24rem (240×427) в своей пропорции 9:16, без обрезки.
   Класс ставит шаблон, когда у медиа-блока заполнены тезисы. */
.media-figure--vidcard .photo-figure { flex: 0 0 24rem; max-width: 24rem; aspect-ratio: 9 / 16; }
.media-figure--vidcard .photo-figure > img,
.media-figure--vidcard .photo-figure > video { object-position: center center; }

/* Сама карточка: подложка во весь рост кадра, скос справа внизу. В системе
   .chamfered режет два угла (левый верхний и правый нижний) — здесь по скрину
   владельца режется только правый нижний. */
.vidcard {
  flex: 1 1 auto; align-self: stretch;
  display: flex; flex-direction: column;
  padding: 2.4rem;
  background-color: rgba(255, 255, 255, 0.45);
  clip-path: polygon(
    0 0, 100% 0,
    100% calc(100% - var(--chamfer-lg)), calc(100% - var(--chamfer-lg)) 100%,
    0 100%
  );
}
/* Шапка — название ролика набором прежнего лейбла: моно, капс. Заголовком карточки
   (крупным сансом) оно читалось дублем H2 раздела: «Минусы каркасного дома» против
   «Главные минусы каркасного дома» с канала. */
.vidcard__name {
  margin: 0 0 1.6rem;
  font-family: var(--font-mono); font-weight: 500;
  font-size: 1.5rem; line-height: 135%; letter-spacing: -0.02em;
  text-transform: uppercase; color: var(--brand-main-base);
}
.vidcard__list { margin: 0; padding: 0; list-style: none; }
.vidcard__list > li {
  display: flex; align-items: flex-start; gap: 1.4rem; padding: 1.2rem 0;
  border-top: 0.1rem solid rgba(55, 61, 66, 0.08);
}
.vidcard__list > li:last-child { border-bottom: 0.1rem solid rgba(55, 61, 66, 0.08); }
.vidcard__txt {
  font-size: 1.5rem; line-height: 155%; letter-spacing: -0.02em;
  color: var(--brand-main-mid);
}
.vidcard__txt b { color: var(--brand-main-base); font-weight: 500; }
/* Подпись у нижней кромки, но с полем плашки: вплотную к краю владелец забраковал. */
.vidcard__by { display: flex; align-items: center; gap: 1.2rem; margin-top: auto; padding-top: 2rem; }
.vidcard__ava { flex: 0 0 auto; width: 4rem; height: 4rem; border-radius: 50%; object-fit: cover; }
.vidcard__who { font-size: 1.4rem; line-height: 140%; letter-spacing: -0.02em; color: var(--brand-main-base); }
.vidcard__who span { display: block; color: var(--grey-base); }

/* Чип таймкода: перематывает ролик на свою секунду (обработчик в poleznoe.js).
   Силуэт из дизайн-системы — .tag--mono (моно, компактные поля) со скосом
   .chamfered--sm; цвет и наведение от тега блога .blog-tag (уточнение владельца
   24.08: «речь только про цвет была, высоту и шрифт оставить как было»). */
.tcode {
  flex: 0 0 auto; margin-top: 0.2rem;
  display: inline-flex; align-items: center; gap: 0.6rem;
  padding: 0.6rem 0.8rem; border: 0; cursor: pointer;
  font-family: var(--font-mono); font-weight: 500;
  font-size: 1.3rem; line-height: 100%; letter-spacing: -0.02em;
  background-color: var(--brand-second-base); color: var(--brand-main-base);
  clip-path: polygon(
    var(--chamfer-sm) 0, 100% 0,
    100% calc(100% - var(--chamfer-sm)), calc(100% - var(--chamfer-sm)) 100%,
    0 100%, 0 var(--chamfer-sm)
  );
  transition: background-color 0.3s;
}
.tcode:hover { background-color: var(--brand-second-mid); }
.tcode svg { display: block; width: 1.1rem; height: 1.1rem; fill: currentColor; }

/* Свёртка тезисов — та же механика, что у «Источников» (см. три оговорки ниже):
   своя колонка, summary с order: 2 под содержимым, скрытие содержимого своим
   правилом. На десктопе кнопки нет и тезисы видны всегда; правило скрытия живёт
   ТОЛЬКО в мобильном медиазапросе, поэтому <details> без атрибута open на широком
   экране всё равно раскрыт — свой display на details отменяет скрытие браузером. */
.vidcard__fold { display: flex; flex-direction: column; }
.vidcard__fold > summary { display: none; }
.vidcard__fold > summary::-webkit-details-marker { display: none; }

@media (max-width: 767px) {
  /* Кадр возвращается к обрезке 3:4: 9:16 во всю колонку 390 даёт 693 px одного
     только ролика. Смещение 22% от верха — лицо в верхней половине кадра, вшитые
     субтитры на 64–70% высоты, в 3:4 помещается и то, и другое. */
  /* Ширину возвращаем колонке: правило 24rem выше стоит ПОЗЖЕ мобильного правила
     --flow и без этой строки перебивает его — кадр оставался 240 px при колонке 354
     (замер 24.08 на 390). */
  .media-figure--vidcard .photo-figure { flex: 1 1 auto; max-width: 100%; aspect-ratio: 3 / 4; }
  .media-figure--vidcard .photo-figure > img,
  .media-figure--vidcard .photo-figure > video { object-position: center 22%; }
  .vidcard { align-self: auto; }
  /* Тезисы под кнопкой: блок на 390 — 711 px против 1109 без свёртки (замер 24.08). */
  .vidcard__fold:not([open]) > *:not(summary) { display: none; }
  .vidcard__fold > summary {
    order: 2; margin-top: 1.6rem; width: fit-content;
    display: inline-flex; align-items: center; gap: 1rem;
    cursor: pointer; list-style: none;
    font-family: var(--font-sans); font-size: 1.2rem; font-weight: 500;
    text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--brand-main-base);
    transition: color 0.2s ease;
  }
  .vidcard__fold > summary::after {
    content: ""; width: 0.8rem; height: 0.8rem;
    border-right: 0.1rem solid currentColor; border-bottom: 0.1rem solid currentColor;
    transform: rotate(45deg); margin-bottom: 0.3rem;
  }
  .vidcard__fold[open] > summary::after { transform: rotate(225deg); margin-bottom: -0.2rem; }
  .vidcard__fold > summary:hover { color: var(--brand-second-strong); }
}

/* ───── «Источники»: хвост под кнопкой ─────
   Видны первые 3 пункта, третий растворяется затуханием; остальное под кнопкой.
   Вид кнопки — макет новой темы (правки владельца 24.08): без рамки, капслок
   с разрядкой, тонкий шеврон, наведение уводит в приглушённый графит.
   Кнопка появляется, только если прячется 3 и больше — иначе список печатается
   целиком (замер 24.08 по 20 прототипам блога: медиана 5 источников, сворачивание
   трогает 8 статей). Текст остаётся в разметке, поэтому поиск и ИИ-ответы видят
   список целиком — проверено на боевой /ipoteka.html, где свёрнутые ответы
   аккордеона отдаются в HTML полностью.
   Три оговорки, без любой из них ломается:
   1. details — своя колонка, у summary order: 2. Иначе браузер рисует кнопку ПЕРЕД
      раскрытым содержимым и «Свернуть» встаёт в середину списка.
   2. при своём display браузер перестаёт прятать содержимое сам — правило
      `:not([open]) > *:not(summary)` обязательно, иначе хвост виден всегда.
   3. отступ до кнопки живёт на summary, а не на списках: шов «3-й → 4-й пункт»
      обязан равняться шагу списка (1.2rem), иначе на разрыве дырка.
   Затухание — маской на самом пункте, а не полосой поверх списка: пункты бывают
   в одну строку и в пять. :has() нужен потому, что details стоит в DOM после
   списка; где :has() нет (Safari до 15.4) — затухания просто не будет. */
.article-sources--rest { counter-reset: asrc 3; margin-top: 1.2rem; }
.sources-more { display: flex; flex-direction: column; }
.sources-more:not([open]) > *:not(summary) { display: none; }
.sources-more > summary {
  order: 2; margin-top: 2.4rem; width: fit-content;
  cursor: pointer; list-style: none; display: inline-flex; align-items: center; gap: 1.2rem;
  font-family: var(--font-sans); font-size: 1.6rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--brand-main-base); padding: 0; border: 0; background: none;
  transition: color 0.2s ease;
}
.sources-more > summary::-webkit-details-marker { display: none; }
.sources-more > summary:hover { color: var(--brand-main-mid); }
.sources-more__chev { flex: none; width: 1.1rem; height: 1.1rem; transition: transform 0.25s ease; }
.sources-more[open] .sources-more__chev { transform: rotate(180deg); }
.sources-more:not([open]) .sources-more__open { display: none; }
.sources-more[open] .sources-more__closed { display: none; }
.article-sources-fold:has(.sources-more:not([open])) > .article-sources:not(.article-sources--rest) > li:last-child {
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 18%, transparent 94%);
          mask-image: linear-gradient(to bottom, #000 0%, #000 18%, transparent 94%);
}

/* Больше воздуха между блоками внутри секции. */
.article-section { gap: 3.2rem; }
.article-callout { margin: 0.4rem 0; }

/* Теги статьи = живой SEO-тег (tags-section): бежевый фон-токен, тонкая
   рамка, низкая высота (padding как на боевом), uppercase, ховер в графит. */
.article-tags .tag {
  background-color: var(--brand-second-extra-low);
  border: 0.1rem solid var(--brand-second-strong);
  color: var(--brand-second-strong);
  font-family: var(--font-sans);
  font-size: 1.6rem;
  font-weight: 400;
  line-height: 100%;
  letter-spacing: -0.06em;
  text-transform: uppercase;
  padding: 0.3rem 1.6rem 0.2rem;
}
.article-tags .tag:hover {
  background-color: var(--brand-second-extra-low);
  border-color: var(--brand-main-base);
  color: var(--brand-main-base);
}

/* «Вернуться к списку статей» — ховер: стрелка уезжает влево + графит, без подчёркивания. */
.article-back { transition: color 0.3s; }
.article-back .icon-slider_arrow { transition: transform 0.3s; }
.article-back:hover { color: var(--brand-second-strong); }
.article-back:hover .icon-slider_arrow { transform: scale(-1, 1) translateX(-0.5rem); }
.article-back:hover .article-back__txt { text-decoration: none; }

/* TOC: проверки 1-10 пронумерованы, рамочные (Введение/Чек-лист/Вопросы) без
   номера — резервируем ширину номера, чтобы заголовки выровнялись. */
.toc__num { min-width: 2.2rem; }
/* Безномерные пункты TOC (Введение / Чек-лист / Вопросы) — без резерва ширины
   номера: текст прижимается влево, на одну вертикаль с цифрами нумерованных. */
.toc__num:empty { display: none; }

/* ───── Блок «Над материалом работали» — паттерн FAQ-хаба (.faq-experts) ─────
   Перенос из faq-experts.css + классы .faq-author / .faq-topic из faq-extended.css.
   Источник: voprosy-hub.html (хаб /voprosy/). Аватары команды ч/б (grayscale).
   Все токены уже есть в tokens.css статьи. Кандидат в article.css DS. */
.faq-experts {
  display: flex; flex-direction: column; align-items: flex-start; gap: 0;
  padding: var(--surface-base);
  background-color: var(--white-mid);
  border: 0.1rem solid var(--brand-main-low);
}
.faq-experts__header {
  margin: 0; align-self: stretch;
  padding-bottom: var(--surface-base);
  border-bottom: 0.1rem solid var(--brand-main-low);
  /* основной шрифт капсом, жирнее — владелец, 19.07; на боевой доехало 15.08.
     До этого тут стоял --font-mono: правка жила только в прототипе (article-extra.css),
     прод-CSS собрался из общего faq-experts.css и разъехался с /voprosy/. */
  font-family: var(--font-sans); font-weight: 600; font-size: 1.4rem;
  line-height: 100%; letter-spacing: -0.02em; text-transform: uppercase;
  color: var(--brand-main-base);
}
.faq-experts__list { display: flex; flex-direction: column; align-self: stretch; width: 100%; }
.faq-experts__row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 1.6rem 1.2rem;
  padding: 1.6rem 0; border-bottom: 0.1rem solid var(--brand-main-low);
}
.faq-experts__row .faq-author { flex: 1 1 auto; align-items: center; }
.faq-experts__topics {
  display: inline-flex; flex-wrap: wrap; align-items: center;
  justify-content: flex-start; gap: 0.8rem;
  /* Своя строка под человеком, а не хвост справа. До 20.08 стояло
     flex: 0 0 auto — теги вставали в строку с должностью, если помещались,
     и переносились вниз, если нет. Раскладка зависела от длины подписи и
     числа тем: у автора с двумя короткими темами теги уезжали вправо, у
     автора с четырьмя — ложились под ним. Одинаковый вид важнее экономии
     строки, тем более что состав тем правится в админке и меняется. */
  flex: 1 0 100%;
}
.faq-experts__note {
  margin: 0; margin-top: 2.4rem; align-self: stretch;
  font-family: var(--font-sans); font-weight: 400; font-size: 1.6rem;
  line-height: 130%; letter-spacing: -0.02em; color: var(--brand-main-mid);
}

/* .faq-author (из faq-extended.css) — плашка человека */
.faq-author { display: inline-flex; align-items: center; column-gap: 1.2rem; }
.faq-author__avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 4.8rem; height: 4.8rem; flex: 0 0 4.8rem; border-radius: 50%;
  background-color: var(--brand-third-base); overflow: hidden;
}
.faq-author__avatar img {
  width: 100%; height: 100%; object-fit: cover; object-position: center top;
  display: block; filter: grayscale(1);
}
.faq-author__info { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem 0.8rem; min-width: 16rem; }
.faq-author__name {
  font-family: var(--font-sans); font-weight: 600; font-size: 1.8rem;
  line-height: 130%; letter-spacing: -0.02em; color: var(--brand-main-base);
}
.faq-author__role {
  font-family: var(--font-sans); font-weight: 400; font-size: 1.6rem;
  line-height: 130%; letter-spacing: -0.02em; color: var(--brand-main-mid);
}
/* В блоке авторов имя и роль — всегда колонкой (имя на своей строке, роль на
   следующей), независимо от длины роли. Иначе короткая роль «прилипает» в строку
   к имени (Андрей), а длинная переносится (Алексей) — разнобой. */
.faq-experts .faq-author__info { flex-direction: column; align-items: flex-start; gap: 0.2rem; }

/* .faq-topic (из faq-extended.css) — чип темы, sentence case, острые углы.
   Кликабельный: ведёт на секцию статьи, которую эксперт комментирует. */
.faq-topic {
  display: inline-flex; align-items: center; padding: 0.4rem 1rem;
  background-color: var(--brand-third-base);
  font-family: var(--font-sans); font-weight: 500; font-size: 1.2rem;
  line-height: 1; letter-spacing: -0.02em; color: var(--brand-main-base);
  white-space: nowrap; text-decoration: none;
  transition: background-color 0.2s, color 0.2s;
}
a.faq-topic { cursor: pointer; }
a.faq-topic:hover { background-color: var(--brand-main-base); color: var(--brand-third-base); }

/* ───── Светлая карточка-подложка (--white-mid, как .faq-experts) для акцентных
   врезок «Три вопроса подрядчику»: ритм светлой подложки по статье, не только в конце. */
.article-card {
  display: flex; flex-direction: column; gap: 2.8rem;
  padding: 3.4rem 2.8rem;
  background-color: var(--white-mid);
  border: 0.1rem solid var(--brand-main-low);
}
.article-card > .article-subhead { margin-top: 0; }
.article-card > .article-list--num > li:first-child { padding-top: 0; }
.article-card > .article-list--num > li:first-child::before { top: 0; }
.article-card > .article-list--num > li:last-child { padding-bottom: 0; }
@media (max-width: 575px) { .article-card { padding: 2rem 1.8rem; } }

@media (max-width: 992px) {
  .faq-experts__note { font-size: 1.4rem; margin-top: 2rem; }
}
@media (max-width: 575px) {
  .faq-experts__header { font-size: 1.2rem; }
  /* Моб-баг 09.06: строка вставала в колонку, но flex-wrap:wrap (из базы) +
     flex:1 1 100% уводили чипы во ВТОРОЙ столбец справа, внахлёст с автором.
     Гасим перенос (nowrap) и делаем автора и чипы полноширинными блоками — стопкой. */
  .faq-experts__row { flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 1.6rem; padding: 2rem 0; }
  .faq-experts__row .faq-author { flex: 0 0 auto; width: 100%; }
  .faq-experts__topics { flex: 0 0 auto; width: 100%; min-width: 0; justify-content: flex-start; }
  .faq-author__name { font-size: 1.6rem; }
  .faq-author__role { font-size: 1.4rem; }
}

/* ==========================================================================
   17. ИНЛАЙН СТАТЬИ — докрутка v7 «подрядчик»/«сроки», TL;DR, hero-маска
   (источник: prototypes-poleznoe/article-sroki-v1-ds2-2026-06-10.html, <head><style>)
   ========================================================================== */
  /* PROVERKA (3): здесь были удалены 2 голых правила html/body — дублировали
     живое body{background-color:var(--bg-color)} (styles.css) и обнуляли
     несуществующий padding-top. См. отчёт сборки. */

  /* ═══ Лонгрид-докрутка (перенесено из утверждённого v7 «подрядчик»; DS-файлы НЕ трогаются) ═══ */

  /* 1. Смягчённая типошкала под длинную статью (H1 ниже DS-landing, H2 ниже H1 на каждом брейке). */
  .article-head .article-title { font-size: 5.2rem; line-height: 102%; }
  .article-section .section-title { font-size: 4.4rem; line-height: 106%; }
  @media (max-width: 992px) {
    .article-head .article-title { font-size: 3.8rem; }
    .article-section .section-title { font-size: 3.2rem; }
  }
  @media (max-width: 575px) {
    .article-head .article-title { font-size: 3rem; }
    .article-section .section-title { font-size: 2.6rem; }
  }

  /* 3. FAQ = живой DS-аккордеон (accordion.css → .faq-list/.faq-item, JS js-faq-link).
        Одноколоночно, вопросы UPPERCASE, тоггл-крест с зазором справа. */
  #faq .faq-list .faq-item { grid-template-columns: 1fr; padding: 2.4rem 8rem 2.4rem 0; }
  #faq .faq-list .item-descr { max-width: none; line-height: 150%; margin-top: 1.6rem; padding-left: 6rem; }
  #faq .faq-list .item-link { top: 1rem; right: 1.4rem; }
  @media (max-width: 992px) {
    #faq .faq-list .faq-item { padding: 1.8rem 5.2rem 1.8rem 0; }
    #faq .faq-list .item-link { top: 1.2rem; right: 1.4rem; }
  }
  @media (max-width: 575px) {
    #faq .faq-list .item-title { align-items: flex-start; }
    #faq .faq-list .item-descr { padding-left: 0; }
  }

  /* 3в. Чипы внизу статьи — перенос на строку, слайдер только на узких экранах.
        Правка прототипа 26.07 («Сроки»): при nowrap последний чип обрезался о край колонки
        без видимой полосы прокрутки и читался багом. Сюда перенос не доехал — блок скопирован
        с более ранней версии прототипа, поэтому 15.08 добавленный `.article-tags{flex-wrap}`
        владелец на боевом не увидел бы: переносился контейнер, а сам список чипов оставался
        слайдером на всех ширинах. На узких экранах перенос дал бы стопку по чипу в строке,
        там слайдер и остаётся. */
  .article-tags .tag-list {
    margin: 0; padding: 0; list-style: none;
    display: flex; flex-wrap: wrap; gap: 0.8rem;
    flex: 1 1 auto; min-width: 0;
  }
  .article-tags .tag-list > li { flex: 0 0 auto; }
  @media (max-width: 575px) {
    /* 18.08: плашки переносятся рядами. Прежний слайдер обрезал последнюю
       плашку о край без всякого признака, что дальше есть ещё — ни полосы
       прокрутки, ни стрелки. Блок стал выше, зато видно всё. */
    .article-tags .tag-list { width: 100%; align-self: stretch; flex-wrap: wrap; }
  }

  /* 4. Аватары цитат: реальные ч/б фото команды, заполняют круг. */
  img.quote-avatar { object-fit: cover; filter: grayscale(1); }

  /* 5. Sticky-оглавление: выше + уплотнено + страховочный overflow. */
  @media (min-width: 993px) {
    .toc { top: 8rem; max-height: calc(100vh - 9rem); overflow-y: auto; }
    .toc__item { padding: 1.2rem 1.6rem; }
  }

  /* 6. Крошки — клиренс под фикс-шапку 1:1 с боевым ipoteka.html. */
  .article { padding-top: 12rem; }
  @media (max-width: 992px) { .article { padding-top: 10rem; } }

  /* 6б. Крошки на мобильном: перенос + поджатые зазоры. */
  .breadcrumbs-row ol { flex-wrap: wrap; }
  @media (max-width: 575px) {
    .breadcrumbs-row ol { column-gap: 1rem; row-gap: 0.8rem; }
    .breadcrumbs-row ol li { column-gap: 1rem; }
  }

  /* 6в. Метка «Обновлено …» — поджать на узком. */
  @media (max-width: 992px) { .article-date { font-size: 1.4rem; } }
  @media (max-width: 575px) { .article-date { font-size: 1.3rem; } }

  /* 7. Увеличенная side-иллюстрация (+25% к 40rem): только десктоп; на мобиле в колонку. */
  @media (min-width: 576px) {
    .media-figure--side-wide .photo-figure { flex-basis: 50rem; max-width: 50rem; }
  }

  /* 8. Больше воздуха ВОКРУГ структурных блоков (карточки, callout, таблицы), не между абзацами. */
  .article-card, .article-callout, .table-scroll { margin-block: 1.2rem; }

  /* ═══ 9. АДАПТИВ. Десктоп ≥993 не трогаем. ═══ */
  /* 9.1 Оглавление на планшете — в 2 колонки. */
  @media (min-width: 576px) and (max-width: 992px) {
    .toc__list { display: block; columns: 2; column-gap: 2rem; }
    .toc__item { break-inside: avoid; }
  }
  /* 9.1б Инлайн-оглавление на мобиле — поджать по вертикали. */
  @media (max-width: 575px) {
    .toc-col .toc { gap: 1.8rem; padding: 1.8rem 1.4rem 1.6rem; }
    .toc-col .toc__item { padding: 1rem 1.2rem; }
  }
  /* 9.2 Капс-заголовки на узком — поднять line-height. */
  @media (max-width: 992px) {
    .article-head .article-title { line-height: 110%; }
    .article-section .section-title { line-height: 114%; }
    .article-subhead { line-height: 116%; }
    .article-cta__title { line-height: 114%; }
  }

  /* ═══ 10. Вид v7 (утверждён владельцем 09.06): таблицы FAQ-стиля, hero split с маской,
            нумерованные списки без подложки, callout «осторожно» на светлой подложке. ═══ */

  /* 10.B — Hero split: крошки сверху, заголовок слева, фото справа. Брендовая «тетрис»-маска
            на фото (как в утверждённой статье «подрядчик»). Маска ВШИТА data-URI, а НЕ внешним
            файлом: внешний big_video.svg как CSS mask не грузится по file:// и прячет фото целиком
            (проверено рендером 10.06; data-URI работает и по file://, и в проде). Уголки рамки при
            маске прячем — брендовую форму даёт сама маска. На проде можно вернуть внешний url. */
  .article-hero-crumbs { margin-bottom: 4.4rem; }
  .article-hero-split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 42rem;
    column-gap: 4.8rem;
    align-items: start;
    margin-bottom: 2.4rem;
  }
  .article-hero-split .article-head { align-self: start; }
  .article-hero-split .media-figure--hero { margin: 0; }
  .article-hero-split .media-figure--hero .photo-figure {
    aspect-ratio: 1;
    -webkit-mask: url("data:image/svg+xml,%3Csvg%20width%3D%22504%22%20height%3D%22504%22%20viewBox%3D%220%200%20504%20504%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%3Cpath%20d%3D%22M503.999%20498.528C503.999%20498.528%20494.089%20498.528%20479.683%20498.528V503.999H161.776V348.911H100.977V249.264H161.776V142.988H302.34V99.6475H403.317V0H503.999V498.528ZM100.977%20249.264H0V99.6475H100.977V249.264ZM302.34%2099.6475H100.977V0H302.34V99.6475Z%22%20fill%3D%22%23ECE2D2%22%3E%3C%2Fpath%3E%0A%3C%2Fsvg%3E") center / contain no-repeat;
            mask: url("data:image/svg+xml,%3Csvg%20width%3D%22504%22%20height%3D%22504%22%20viewBox%3D%220%200%20504%20504%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%3Cpath%20d%3D%22M503.999%20498.528C503.999%20498.528%20494.089%20498.528%20479.683%20498.528V503.999H161.776V348.911H100.977V249.264H161.776V142.988H302.34V99.6475H403.317V0H503.999V498.528ZM100.977%20249.264H0V99.6475H100.977V249.264ZM302.34%2099.6475H100.977V0H302.34V99.6475Z%22%20fill%3D%22%23ECE2D2%22%3E%3C%2Fpath%3E%0A%3C%2Fsvg%3E") center / contain no-repeat;
  }
  .article-hero-split .photo-figure.frame-corners::before,
  .article-hero-split .photo-figure.frame-corners::after,
  .article-hero-split .photo-figure .frame-corner-bl,
  .article-hero-split .photo-figure .frame-corner-br { display: none; }
  .article-hero-split .media-figure--hero img { object-position: center; }

  /* Метка «Обновлено» — режим «линия» из DS rubric-page (.rubric-hero__upd--line),
     перенесён 1:1: «обычный, не заголовочный» шрифт (владелец 21.07 и 22.07) = Inter 600 капсом, не mono; короткая линия-штрих сверху, дата в <b>. Под H1, слева. */
  .article-upd--line {
    align-self: flex-start;
    display: inline-flex; align-items: center; gap: 1rem;
    margin-top: 2.6rem; padding-top: 1.6rem;
    border-top: 0.1rem solid var(--brand-main-low);
    font-family: var(--font-sans); font-weight: 600; font-size: 1.4rem;
    line-height: 100%; letter-spacing: -0.02em; text-transform: uppercase;
    color: var(--brand-main-mid);
  }
  .article-upd--line b { color: var(--brand-main-base); font-weight: 600; }

  /* 10.B-bg — Фон первого экрана чуть темнее (как DS-герои capital-main/mortgage-main). */
  .article-hero-zone { position: relative; isolation: isolate; }
  .article-hero-zone > * { position: relative; z-index: 1; }
  .article-hero-zone::before {
    content: "";
    position: absolute;
    z-index: 0;
    top: -7rem;
    bottom: -4rem;
    left: calc(50% - 50vw);
    width: 100vw;
    background-color: var(--brand-third-base);
    pointer-events: none;
  }
  @media (max-width: 575px) { .article-hero-zone::before { bottom: -2rem; } }
  @media (min-width: 993px) {
    .article-hero-split .article-title { font-size: 6.6rem; line-height: 102%; }
  }
  @media (max-width: 1200px) {
    .article-hero-split { grid-template-columns: minmax(0, 1fr) 34rem; column-gap: 3.2rem; }
  }
  @media (max-width: 992px) {
    .article-hero-split { grid-template-columns: 1fr; row-gap: 2.4rem; }
    .article-hero-split .media-figure--hero .photo-figure { aspect-ratio: 1; max-width: 38rem; margin-inline: auto; }
  }

  /* 10.A — Таблицы compare-table: светлое тело (--white-mid) + обводка + линии, шапка пшеничная.
            (Если на странице есть 2-колоночная compare-table; для 3-колоночной — .sroki-table ниже.) */
  .compare-table {
    grid-template-columns: minmax(15rem, 0.42fr) minmax(20rem, 1fr);
    gap: 0;
    min-width: 0;
    background-color: var(--white-mid);
    border: 0.1rem solid var(--brand-main-low);
  }
  .compare-table .cell { background: transparent; padding: 2rem 2.2rem; min-width: 0; }
  .compare-table .cell:nth-child(even) { border-left: 0.1rem solid var(--brand-main-low); }
  .compare-table .cell:nth-child(n+3) { border-top: 0.1rem solid var(--brand-main-low); }
  .compare-table .cell--head { padding: 1.4rem 2.2rem; background-color: var(--brand-second-mid); }
  .compare-table .cell--head .cell-title {
    font-family: var(--font-sans); font-weight: 600; font-size: 1.4rem; line-height: 130%;
    letter-spacing: 0; text-transform: uppercase; color: var(--brand-main-base);
  }
  .compare-table .cell-type {
    font-family: var(--font-sans); font-weight: 600; font-size: 1.9rem; line-height: 132%;
    letter-spacing: -0.02em; text-transform: none; color: var(--brand-main-base);
  }
  .compare-table .cell-desc { font-size: 1.7rem; }
  @media (max-width: 575px) {
    .compare-table { grid-template-columns: 1fr; }
    .compare-table .cell--head { display: none; }
    .compare-table .cell { border-left: none; border-top: none; padding: 0.4rem 2rem 1.4rem; }
    .compare-table .cell:nth-child(odd) { border-top: 0.1rem solid var(--brand-main-low); padding-top: 1.6rem; font-weight: 600; }
    .compare-table .cell:nth-child(3) { border-top: none; }
  }

  /* 10.A-3col — ТАБЛИЦА СРОКОВ: 3 колонки (Этап | Срок | Что происходит). Scoped в прототип;
                 на тех же токенах и в том же стиле, что compare-table v7 (светлое тело, пшеничная шапка,
                 обводка + вертикальные и горизонтальные линии). DS-файлы не трогаем; кандидат в compare-table--3col. */
  .sroki-table {
    display: grid;
    grid-template-columns: minmax(15rem, 0.9fr) minmax(8rem, 0.45fr) minmax(20rem, 1.7fr);
    gap: 0;
    background-color: var(--white-mid);
    border: 0.1rem solid var(--brand-main-low);
  }
  .sroki-table .cell { background: transparent; padding: 1.8rem 2rem; min-width: 0; }
  /* вертикальные разделители — у 2-й и 3-й ячейки каждой тройки (не первой в строке) */
  .sroki-table .cell:nth-child(3n+2),
  .sroki-table .cell:nth-child(3n) { border-left: 0.1rem solid var(--brand-main-low); }
  /* горизонтальные линии между строками — со 2-й строки (ячейки 4+) */
  .sroki-table .cell:nth-child(n+4) { border-top: 0.1rem solid var(--brand-main-low); }
  /* строка-шапка — пшеничная плашка, метка капс */
  .sroki-table .cell--head { padding: 1.4rem 2rem; background-color: var(--brand-second-mid); }
  .sroki-table .cell--head .cell-title {
    font-family: var(--font-sans); font-weight: 600; font-size: 1.4rem; line-height: 130%;
    letter-spacing: 0; text-transform: uppercase; color: var(--brand-main-base);
  }
  /* колонка «этап» — обычный шрифт, sentence-case */
  .sroki-table .cell-type {
    font-family: var(--font-sans); font-weight: 600; font-size: 1.8rem; line-height: 130%;
    letter-spacing: -0.02em; text-transform: none; color: var(--brand-main-base);
  }
  /* колонка «срок» — моно; короткие числовые держим в строку (nbsp), длинные текстовые переносим */
  .sroki-table .cell-term {
    font-family: var(--font-mono); font-weight: 500; font-size: 1.7rem; line-height: 122%;
    letter-spacing: -0.02em; color: var(--brand-main-base); white-space: normal; overflow-wrap: break-word;
  }
  .sroki-table .cell-desc {
    font-family: var(--font-sans); font-size: 1.6rem; line-height: 148%;
    letter-spacing: -0.02em; color: var(--brand-main-mid);
  }
  @media (max-width: 575px) {
    .sroki-table { grid-template-columns: 1fr; }
    .sroki-table .cell--head { display: none; }
    .sroki-table .cell { border-left: none; border-top: none; padding: 0.3rem 1.8rem; }
    /* этап (1-я в тройке) открывает «карточку» строки */
    .sroki-table .cell:nth-child(3n+1) { border-top: 0.1rem solid var(--brand-main-low); padding-top: 1.6rem; }
    .sroki-table .cell:nth-child(1) { border-top: none; }
    .sroki-table .cell-term::before { content: "Срок: "; font-family: var(--font-sans); font-weight: 600; color: var(--brand-main-mid); }
    .sroki-table .cell-desc { padding-bottom: 1.4rem; }
  }

  /* 10.A-5col — ТАБЛИЦА МАТЕРИАЛОВ, 5 колонок. Перенесено 15.08.2026 из инлайнового <style>
                 прототипа article-uteplitel-m1-ds2-2026-08-10.html БЕЗ изменений: на боевом класса
                 не было вовсе, и таблица статьи м1 разваливалась в столбик (дивы-ячейки без grid).
                 Экстрактор переносит только тело статьи, scoped-стили прототипа оставались за бортом. */
  .matrix-table {
    display: grid;
    /* Колонка λ считана под самое длинное значение «0,032–0,048»: моно 1.5rem ≈ 0.9rem на знак,
       11 знаков ≈ 10rem + горизонтальные отступы 3.2rem. Меньше 13.2rem значение не помещается
       и налезает на соседнюю колонку — так и было в первой сборке (замер 10.08). */
    /* Колонка «Горючесть» держит не значение (НГ, Г2), а собственный заголовок: в 9.6rem
       он ломался на «ГОРЮЧ|ЕСТЬ». Минимум считан по нему же — 9 знаков капса плюс отступы. */
    grid-template-columns: minmax(14rem, 1fr) minmax(13.4rem, 0.8fr) minmax(11.8rem, 0.45fr) minmax(13rem, 1.05fr) minmax(14rem, 1.15fr);
    gap: 0;
    min-width: 64rem;              /* уже — горизонтальный скролл в .table-scroll, а не наползание */
    background-color: var(--white-mid);
    border: 0.1rem solid var(--brand-main-low);
  }
  .matrix-table .cell { background: transparent; padding: 1.6rem 1.6rem; min-width: 0;
    overflow-wrap: anywhere;       /* страховка: длинное значение переносится, а не вылезает из ячейки */
    border-left: 0.1rem solid var(--brand-main-low); border-top: 0.1rem solid var(--brand-main-low); }
  .matrix-table .cell:nth-child(5n+1) { border-left: 0; }
  .matrix-table .cell:nth-child(-n+5) { border-top: 0; }
  .matrix-table .cell--head { padding: 1.4rem 1.8rem; background-color: var(--brand-second-mid); }
  .matrix-table .cell--head .cell-title {
    font-family: var(--font-sans); font-weight: 600; font-size: 1.4rem; line-height: 130%;
    letter-spacing: 0; text-transform: none; color: var(--brand-main-base);
    overflow-wrap: normal;         /* заголовок колонки не рвём посреди слова, ширину даёт minmax */
  }
  .matrix-table .cell-type {
    font-family: var(--font-sans); font-weight: 600; font-size: 1.8rem; line-height: 130%;
    letter-spacing: -0.02em; text-transform: none; color: var(--brand-main-base);
  }
  .matrix-table .cell-num {
    font-family: var(--font-mono); font-weight: 500; font-size: 1.6rem; line-height: 124%;
    letter-spacing: -0.02em; color: var(--brand-main-base); white-space: nowrap;
  }
  .matrix-table .cell-desc {
    font-family: var(--font-sans); font-size: 1.6rem; line-height: 148%;
    letter-spacing: -0.02em; color: var(--brand-main-mid);
  }
  /* ≤992 колонки НЕ переопределяем: свои минимумы здесь узкие, и значения снова наползали
     (замер 10.08, 5 ячеек). Ужимаем только отступы; не хватило ширины — работает скролл
     .table-scroll, как задумано в DS. */
  @media (max-width: 992px) {
    .matrix-table .cell { padding: 1.4rem 1.2rem; }
  }
  @media (max-width: 575px) {
    /* min-width таблицы тут снимаем: в карточном режиме он гнал бы карточки в горизонтальный
       скролл на 64rem вместо ширины экрана (замер 10.08 на 390 px). */
    .matrix-table { grid-template-columns: 1fr; min-width: 0; }
    .matrix-table .cell--head { display: none; }
    .matrix-table .cell { border-left: none; border-top: none; padding: 0.3rem 1.8rem; }
    .matrix-table .cell:nth-child(5n+1) { border-top: 0.1rem solid var(--brand-main-low); padding-top: 1.6rem; }
    .matrix-table .cell:nth-child(1) { border-top: none; }
    .matrix-table .cell:nth-child(5n) { padding-bottom: 1.4rem; }
    .matrix-table .cell[data-label]::before {
      content: attr(data-label) ": "; font-family: var(--font-sans); font-weight: 600;
      color: var(--brand-main-mid);
    }
  }

  /* 10.C — Нумерованные списки без светлой подложки: карточка-обёртка прозрачна (вид v7). */
  .article-card { background: transparent; border: none; padding: 0; }

  /* 10.D — Callout «что должно насторожить» на светлой подложке. */
  .article-callout {
    background-color: var(--white-mid);
    border: 0.1rem solid var(--brand-main-low);
    border-left: 0.3rem solid var(--brand-second-strong);
  }

  /* 10.E — Теги авторов: ховер пшеничный. */
  .faq-experts a.faq-topic:hover { background-color: var(--brand-second-mid); color: var(--brand-main-base); }

  /* 10.F — Нижний CTA: кнопка шире. min-width, а не width: с фикс-шириной .btn-txt
     (анти-дребезг скрэмбла выше) жёсткие 40rem резали текст — flex-shrink сжимал
     бокс, и лейбл вылезал за свои границы. Замер стенда 22.07: контент 41.8rem. */
  .article-cta__btn { min-width: 40rem; max-width: 100%; }
  /* ≤575px кнопка во всю ширину колонки: min-width сильнее max-width и дал бы
     40rem = 400px на экране 375 → горизонтальный скролл (замер 22.07). */
  @media (max-width: 575px) {
    .article-cta__btn { min-width: 0; }
    .article-cta__btn .btn-txt { width: auto; }
  }

  /* 10.G — 3D-видео на белом фоне: подложка-крем + multiply, скобки рамки над видео. */
  .photo-figure.frame-corners::before,
  .photo-figure.frame-corners::after,
  .photo-figure > .frame-corner-bl,
  .photo-figure > .frame-corner-br { z-index: 1; }
  .photo-figure:has(video[src*="pirog"]) { background-color: var(--bg-color); }
  video[src*="pirog"] { mix-blend-mode: multiply; }

  /* ═══ 11. МОБИЛЬНАЯ НАВИГАЦИЯ ПО СОДЕРЖАНИЮ (≤992): кнопка + выпадашка сверху, вне нижней зоны виджетов. ═══ */
  .toc-fab, .toc-sheet, .toc-sheet__backdrop { display: none; }

  @media (max-width: 992px) {
    .toc-fab {
      display: inline-flex; align-items: center; justify-content: center;
      width: 4.2rem; height: 4.8rem; padding: 0; box-sizing: border-box;
      position: fixed; right: 0; top: 82%; margin-top: -2.4rem; z-index: 35;
      background-color: var(--brand-second-base);
      color: var(--brand-main-base);
      border: none;
      cursor: pointer; -webkit-tap-highlight-color: transparent;
      transform: translateX(110%); opacity: 0; pointer-events: none;
      transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.32s;
    }
    .toc-fab.is-visible { transform: translateX(0); opacity: 1; pointer-events: auto; }
    .toc-fab__icon { width: 2.4rem; height: 2.4rem; display: block; }
    .toc-fab__label { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

    .toc-sheet__backdrop {
      display: block; position: fixed; inset: 0; z-index: 33;
      background-color: rgba(55, 61, 66, 0.5);
      opacity: 0; visibility: hidden; transition: opacity 0.3s, visibility 0.3s;
    }
    .toc-sheet__backdrop.is-open { opacity: 1; visibility: visible; }

    .toc-sheet {
      display: flex; flex-direction: column;
      position: fixed; top: 11rem; left: var(--container-padding); right: var(--container-padding); z-index: 34;
      max-height: 82vh;
      background-color: var(--brand-second-base);
      border: none;
      transform: translateY(-1rem); opacity: 0; visibility: hidden;
      transition: transform 0.28s ease, opacity 0.28s, visibility 0.28s;
      padding: 1.6rem;
    }
    .toc-sheet.is-open { transform: translateY(0); opacity: 1; visibility: visible; }
    .toc-sheet__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.8rem; }
    .toc-sheet__title {
      font-family: var(--font-sans); font-weight: 600; font-size: 1.5rem;
      text-transform: uppercase; letter-spacing: -0.02em; color: var(--brand-main-base);
    }
    .toc-sheet__close {
      flex: 0 0 auto; width: 3.6rem; height: 3.6rem; display: inline-flex;
      align-items: center; justify-content: center; cursor: pointer;
      background: transparent; border: none; color: var(--brand-main-base); font-size: 1.6rem;
    }
    .toc-sheet__list { overflow-y: auto; -webkit-overflow-scrolling: touch; }
    .toc-sheet .toc__item { padding: 1.2rem 1.2rem; }
  }

  @media (prefers-reduced-motion: reduce) {
    .toc-fab { transition: opacity 0.2s; transform: none; }
    .toc-fab.is-visible { transform: none; }
  }

  /* ═══ 12. «Коротко» (TL;DR / AI-выжимка): сводка первым блоком тела, зона цитирования ИИ.
            На тех же токенах, что и DS-блоки; кандидат в article-extra.css. ═══ */
  .article-tldr {
    margin: 0 0 3.2rem;
    padding: 2.4rem 2.8rem;
    /* Цвет и рамка 1:1 с .faq-brief рубрики /voprosy/ (faq-extended.css):
       тинт --brand-second-mid (#ebd3af) 30%, рамка 1px #ebd3af, левый акцент 4px, острые углы. */
    background-color: rgba(235, 211, 175, 0.3);
    border: 0.1rem solid var(--brand-second-mid);
    border-left-width: 0.4rem;
  }
  /* Шрифт метки — «обычный» Inter 600 капсом, 1:1 с «СОДЕРЖАНИЕ СТАТЬИ» (.toc__head).
     Правка владельца 22.07. */
  .article-tldr__label {
    font-family: var(--font-sans); font-weight: 600; font-size: 1.4rem;
    letter-spacing: -0.02em; text-transform: uppercase;
    color: var(--brand-main-mid); margin: 0 0 2rem; /* отступ метки от текста, правка 22.07 */
  }
  .article-tldr__list { margin: 0; padding-left: 2rem; list-style: disc; }
  .article-tldr__list > li {
    font-family: var(--font-sans); font-size: 1.7rem; line-height: 150%;
    letter-spacing: -0.01em; color: var(--brand-main-base); margin-bottom: 0.8rem;
  }
  .article-tldr__list > li:last-child { margin-bottom: 0; }
  .article-tldr__list b { font-weight: 600; }
  @media (max-width: 575px) {
    .article-tldr { padding: 1.8rem 2rem; }
    .article-tldr__list > li { font-size: 1.6rem; }
  }

/* ==========================================================================
   18. ИНЛАЙН ХАБА — раскладка /poleznoe/ (.blog-page*)
   (источник: prototypes-poleznoe/prototype-poleznoe-hub-ds2-2026-06-09.html, <head><style>)
   ========================================================================== */
    /* ===========================================================
       Локальная раскладка хаба /poleznoe/ (НОВОЕ · Figma).
       Имена .blog-page*: раскладочные, живут только на этой
       странице. Все компоненты внутри библиотечные (.blog-*,
       .breadcrumbs-row, .mse2_pagination, header/footer).
       1:1 с DS blog-feed.html, наполнено реальным контентом.
       =========================================================== */
    /* PROVERKA (3): здесь было удалено голое правило html/body — дублировало
       живое body{background-color:var(--bg-color)} (styles.css). См. отчёт сборки. */

    /* верхний отступ очищает фиксированную шапку (.header position:fixed) */
    .blog-page { padding: 13rem 0 8rem; }
    @media (max-width: 992px) { .blog-page { padding: 11rem 0 6rem; } }
    @media (max-width: 575px) { .blog-page { padding: 9rem 0 4.8rem; } }

    .blog-page__stack { display: flex; flex-direction: column; gap: 4.8rem; }
    @media (max-width: 575px) { .blog-page__stack { gap: 3.2rem; } }

    /* Шапка раздела: крошки + (заголовок/лид | табы типа) */
    .blog-page__head { display: flex; flex-direction: column; align-items: flex-start; gap: 2.4rem; }
    .blog-page__head .breadcrumbs-row { margin-top: 0; }

    .blog-page__title-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 4rem; width: 100%; }
    @media (max-width: 992px) { .blog-page__title-row { flex-direction: column; align-items: flex-start; gap: 2.4rem; } }

    .blog-page__intro { display: flex; flex-direction: column; gap: 2.4rem; max-width: 88rem; }
    .blog-page__title {
      margin: 0;
      font-family: var(--font-mono); font-weight: 700;
      font-size: var(--size-headings-h1); line-height: 94%;
      letter-spacing: -0.03em; text-transform: uppercase; color: var(--brand-main-base);
    }
    .blog-page__lead {
      margin: 0; max-width: 80rem;
      font-family: var(--font-sans); font-weight: 400;
      font-size: var(--size-body-m); line-height: 120%;
      letter-spacing: -0.03em; color: var(--brand-main-mid); text-wrap: pretty;
    }
    .blog-page__types {
      flex: 0 0 auto; gap: 0.4rem; padding: 0.4rem;
      background-color: var(--brand-third-base);
      /* Скос трека параллелен активной кнопке: её срез 0.8rem + паддинг 0.4rem. */
      --chamfer: 1.2rem;
    }
    .blog-page__types .blog-filter { background-color: var(--brand-third-base); }
    .blog-page__types .blog-filter:hover { background-color: var(--brand-second-mid); }
    .blog-page__types .blog-filter.is-active { background-color: var(--brand-main-base); color: var(--white-base); }

    /* Полоса категорий: подпись + чипы, отбита хайрлайном сверху */
    .blog-page__cats { display: flex; flex-direction: column; align-items: flex-start; gap: 1.6rem; padding-top: 2.4rem; border-top: 0.1rem solid var(--brand-main-low); }
    /* Подпись набирается основным шрифтом — как «Часто ищут» в /voprosy/
       (.faq-queries__label): тот же капс и трекинг, вес 600. Моно тут стоял
       с первой сборки хаба и выбивался из подписей соседних разделов. */
    .blog-page__cats-title { margin: 0; font-family: var(--font-sans); font-weight: 600; font-size: 1.4rem; line-height: 100%; letter-spacing: -0.02em; text-transform: uppercase; color: var(--brand-main-base); }

    .blog-page__feed { display: flex; flex-direction: column; }

    /* Лента: 4 колонки (по макету), зазор 24/16, шаг 4-3-2-1. */
    .blog-page .blog-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 2.4rem 1.6rem; }
    @media (max-width: 1200px) { .blog-page .blog-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
    @media (max-width: 992px)  { .blog-page .blog-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
    @media (max-width: 575px)  { .blog-page .blog-grid { grid-template-columns: minmax(0, 1fr); } }

    /* Чипы-категории: компактный ряд (.blog-tag, зазор 8px). */
    .blog-page__cats-list { gap: 0.8rem; }
    .blog-page__cats-list .blog-tag { border: none; }

    /* Моб: табы типа, равные трети трека, всегда в одну строку. */
    @media (max-width: 575px) {
      .blog-page__types { width: 100%; flex-wrap: nowrap; }
      .blog-page__types .blog-filter { flex: 1 1 0; min-width: 0; justify-content: center; gap: 0.4rem; padding: 0.8rem 0.6rem; }
      .blog-page__types .blog-filter__icon { width: 1.6rem; height: 1.6rem; margin-right: 0; }
      .blog-page__types .blog-filter__label { font-size: 1.2rem; }
      .blog-page__types .blog-filter__count { font-size: 1.2rem; }
    }

    /* Скрытые фильтром карточки выпадают из грид-потока. */
    .blog-card.is-hidden { display: none !important; }

    /* Пустое состояние, если по фильтру ничего не найдено. */
    .blog-page__empty { display: none; padding: 4.8rem 0; font-family: var(--font-sans); font-size: var(--size-body-m); letter-spacing: -0.02em; color: var(--brand-main-mid); }
    .blog-page__feed.is-empty .blog-page__empty { display: block; }
    .blog-page__feed.is-empty .mse2_pagination { display: none; }

    /* Пагинация по центру ленты (как в боевом каталоге: .pagination-list уже
       justify-content:center; дублируем на nav, чтобы центр не зависел от
       ширины ul в этом раскладочном контексте). */
    .blog-page .mse2_pagination { display: flex; justify-content: center; }



/* ============================================================================
   19. ПОРТ ЖИВЫХ КОМПОНЕНТОВ (сверка с боевым styles.css 22.07.2026)
   ----------------------------------------------------------------------------
   По аналогии с §15 voprosy.css: сюда выносятся точечные восстановления/
   расхождения, найденные при сверке НОВЫХ классов раздела с живым бандлом,
   а не предписанные исходным ТЗ буквально. Каждая правка — со ссылкой на
   замер/grep, которым подтверждена.
   ============================================================================ */

/* --- 19.1 .primary-btn: восстановление padding/min-width/min-height ТОЛЬКО
   в скоупе блога. На боевом .primary-btn{padding:0}, без min-width/min-height —
   каждый живой инстанс получает габариты от своего контекста (напр. хедер-CTA
   «Выставочные дома»: .header__content .main-menu .projects-btn{width:100%;
   height:6rem} на ≤992px, специфичность 0,3,0 — сильнее нашего .primary-btn).
   Заголовочный/подвальный CTA размером не заденет: восстановление ниже скоуплено
   под корень страницы, а не глобально. Без этого блока новые CTA раздела
   (.article-cta__btn «Записаться на экскурсию», hero-кнопка хаба) схлопнутся
   в высоту строки текста — padding:0 от живого правила победит по порядку
   подключения (poleznoe.css грузится ПОСЛЕ styles.css, специфичность обеих
   0,1,0). Значения — те же 3.2rem/28rem/6rem, что были в исходном _ds2/button.css
   (см. PATCH-C, §8). */
:where(.blog-page, .article) .primary-btn {
  padding: 0 3.2rem;
  min-width: 28rem;
  min-height: 6rem;
}

/* --- 19.2 Первый экран: клиренс под фикс-шапку — уже задан padding-top
   компонентных секций (.blog-page, §18 инлайн; .article, §15/§17 инлайн) и
   докруткой v7 (.article{padding-top:12rem}, §17). Отдельного порта не
   требуется — в отличие от /voprosy/, здесь ритм первого экрана НЕ перебивается
   живым `main > section:nth-of-type(1)` (тот селектор не совпадает с
   `main.blog-page` / `article.article` — иная разметка корня страницы). */

/* ══════════════════════════════════════════════════════════════════════════════
   §20. КОНСТРУКТОР СТАТЕЙ (16.08.2026) — текст, введённый менеджером в редакторе.

   Редактор классов не ставит: из него приходят голые <p>, <ul>, <ol>, <li>, <b>,
   <a> и <table>. Всё это шаблон заворачивает в .article-text, а правила ниже
   повторяют .article-p / .article-list / .article-sources один в один — чтобы
   страница, собранная в админке, была неотличима от свёрстанной руками.

   Старые классы НЕ трогаются: статьи на прежней разметке выводятся как прежде,
   а .matrix-table остаётся для уже свёрстанных таблиц. Повтор объявлений здесь
   осознанный — правки внутри 137 КБ рабочего файла дороже дубля в конце.
   ══════════════════════════════════════════════════════════════════════════════ */

/* Обёртка держит тот же вертикальный ритм, что и .article-section */
.article-text { display: flex; flex-direction: column; gap: 3.2rem; min-width: 0; }
@media (max-width: 992px) { .article-text { gap: 2.8rem; } }

/* ── Абзац = .article-p ── */
.article-text > p {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 1.8rem;
  line-height: 160%;
  letter-spacing: -0.02em;
  color: var(--brand-main-mid);
}
.article-text > p b, .article-text > p strong { color: var(--brand-main-base); }
.article-text > p a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.3rem;
  transition: color 0.3s;
}
.article-text > p a:hover { color: var(--brand-main-base); }

/* Вводный абзац = .article-p--lead, только самый первый */
.article-text--lead > p:first-child {
  font-size: 2.2rem;
  line-height: 150%;
  color: var(--brand-main-base);
}
@media (max-width: 992px) { .article-text--lead > p:first-child { font-size: 2rem; } }
@media (max-width: 575px) { .article-text--lead > p:first-child { font-size: 1.9rem; } }

/* ── Списки = .article-list / .article-list--num ── */
.article-text ul, .article-text ol {
  margin: 0; padding: 0; list-style: none;
  display: flex; flex-direction: column; gap: 1.4rem;
  font-family: var(--font-sans);
  font-size: 1.8rem; line-height: 150%; letter-spacing: -0.02em;
  color: var(--brand-main-mid);
}
.article-text li { position: relative; padding-left: 2.8rem; }
.article-text ul > li::before {
  content: ""; position: absolute; left: 0.4rem; top: 0.6em;
  width: 0.7rem; height: 0.7rem; border-radius: 50%;
  background-color: var(--brand-second-strong);
}
.article-text li b, .article-text li strong { color: var(--brand-main-base); }
.article-text li a {
  color: var(--brand-main-base);
  text-decoration: underline; text-underline-offset: 0.3rem;
}
/* Нумерованный — та же квадратная плашка номера, что у .article-list--num */
.article-text ol { counter-reset: atn; gap: 0; }
.article-text ol > li { padding: 1.6rem 0 1.6rem 4.4rem; }
.article-text ol > li + li { border-top: 0.1rem solid var(--brand-main-low); }
.article-text ol > li::before {
  counter-increment: atn;
  content: counter(atn);
  position: absolute; border-radius: 0;
  top: 1.6rem; left: 0;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 2.8rem; height: 2.8rem; padding: 0 0.6rem;
  background-color: var(--brand-third-base);
  border: 0.1rem solid var(--brand-main-low);
  font-family: var(--font-mono); font-weight: 500; font-size: 1.4rem;
  line-height: 1; letter-spacing: -0.02em;
  color: var(--brand-main-base);
}

/* ── Врезка: подложка своя (.article-card), ритм внутри поджат ── */
.article-card.article-text { gap: 1.6rem; }
.article-card.article-text > ol:first-child > li:first-child { padding-top: 0; }
.article-card.article-text > ol:first-child > li:first-child::before { top: 0; }
.article-card.article-text > ol:last-child > li:last-child { padding-bottom: 0; }

/* ── Мелкие контейнеры: редактор кладёт внутрь <p>, гасим его отступы ── */
.checklist__text.article-text,
.article-sources > li.article-text,
.article-cta__list > li.article-text { display: block; }
/* Ответ FAQ закрыт по умолчанию: раскрывает его боевой common.js инлайном
   (slideDown), стартово открытый несёт inline style в разметке. Пока правило
   стояло в группе выше, оно перебивало `.faq-list .item-descr{display:none}`
   (то же число классов, но ниже по файлу) — открытыми были сразу все ответы,
   и в мобильной, и в десктопе. Исправлено 18.08.2026. */
.item-descr.article-text { display: none; }
.checklist__text.article-text > p,
.article-sources > li.article-text > p,
.article-cta__list > li.article-text > p,
.item-descr.article-text > p { margin: 0; font: inherit; color: inherit; }
.checklist__text.article-text > p + p,
.item-descr.article-text > p + p { margin-top: 1.2rem; }

/* ══ Таблица из редактора — настоящая <table>, число колонок любое.
   Отличие от .matrix-table: там пять дорожек grid и селекторы nth-child(5n+1)
   зашиты намертво, и таблица на три колонки разваливалась. Здесь раскладку
   держит сам <table>, а горизонтальную прокрутку — обёртка .table-scroll,
   которую вешает poleznoe.js. ══ */
.article-text table {
  width: 100%;
  border-collapse: collapse;
  min-width: 56rem;
  background-color: var(--white-mid);
  border: 0.1rem solid var(--brand-main-low);
}
.article-text th, .article-text td {
  padding: 2rem 2.2rem;
  border: 0.1rem solid var(--brand-main-low);
  text-align: left;
  vertical-align: top;
  overflow-wrap: anywhere;
}
/* Шапка — «вариант A» из прототипа (стенд netlify, выбор владельца 01.08):
   пшеничная плашка, метка КАПСОМ, тёмный текст. Капс при переносе статьи
   в конструктор потерялся: в прототипе шапку рисовал .compare-table
   .cell--head .cell-title, а здесь это обычный <th> из редактора со своей
   веткой стилей. Прочие параметры (фон, вес, кегль, цвет) совпадали и так. */
.article-text th {
  background-color: var(--brand-second-mid);
  padding: 1.4rem 2.2rem;
  font-family: var(--font-sans); font-weight: 600; font-size: 1.4rem;
  line-height: 130%; letter-spacing: 0; text-transform: uppercase;
  color: var(--brand-main-base);
  overflow-wrap: normal;
}
.article-text td {
  font-family: var(--font-sans); font-size: 1.7rem; line-height: 148%;
  letter-spacing: -0.02em; color: var(--brand-main-mid);
}
/* Первая колонка — название строки. В прототипе это .cell-type, и владелец
   выбрал ей обычный шрифт вместо моно-капса: sentence-case, 1.9rem.
   Ширина — доля, а не только минимум. В прототипе колонка задана как
   minmax(20rem, 0.45fr): при 1.45fr на две колонки это ~31% таблицы, и держит
   ширину именно доля. Один min-width: 20rem мало — на боевом 1rem = 10px
   (html { font-size: var(--size-index) }), то есть 200px, и колонка оставалась
   сжатой. Авто-раскладка <table> сама отдаёт ширину второй колонке: там
   длинный текст. */
.article-text th:first-child,
.article-text td:first-child { width: 31%; min-width: 20rem; }
.article-text td:first-child {
  font-weight: 600; font-size: 1.9rem; line-height: 132%;
  letter-spacing: -0.02em; text-transform: none; color: var(--brand-main-base);
}
.article-text td p, .article-text th p { margin: 0; font: inherit; color: inherit; }
@media (max-width: 992px) { .article-text th, .article-text td { padding: 1.4rem 1.2rem; } }

/* Числа в таблице — моноширинные, как в .matrix-table: цифра в DS всегда моно.
   Класс ставит менеджер стилем «Число» из панели редактора (style_formats). */
.article-text .cell-num {
  font-family: var(--font-mono); font-weight: 500; font-size: 1.6rem;
  line-height: 124%; letter-spacing: -0.02em;
  color: var(--brand-main-base); white-space: nowrap;
}

/* ≤575 — карточный режим вместо прокрутки: подписи колонок подставляются из
   data-label, который проставляет poleznoe.js по тексту <th>. */
@media (max-width: 575px) {
  .article-text table { display: block; min-width: 0; border: 0; }
  .article-text thead { display: none; }
  .article-text tbody, .article-text tr, .article-text td { display: block; }
  .article-text tr {
    border-top: 0.1rem solid var(--brand-main-low);
    padding: 1.6rem 0 1.4rem;
  }
  .article-text tr:first-child { border-top: 0; }
  .article-text td { border: 0; padding: 0.3rem 1.8rem; }
  .article-text td[data-label]::before {
    content: attr(data-label) ": ";
    font-family: var(--font-sans); font-weight: 600;
    color: var(--brand-main-mid);
  }
  .article-text td:first-child::before { content: none; }
}

/* ═════════════════════════════════════════════════════════════════════════════
   §21. КОНСТРУКТОР: ТИПЫ БЛОКОВ 20.08.2026
   Статья «Как проверить строительную компанию» принесла три класса, которых
   у конструктора не было: предупреждение «Что должно насторожить», врезка
   «как у нас» и пара фото рядом. Сами компоненты в этом файле уже описаны
   (§17/§19, портированы вместе с вёрсткой v7) — здесь только стыки с рендером
   конструктора: он кладёт текст обычными <p> внутрь .article-text, а прототип
   использовал .article-p.
   ════════════════════════════════════════════════════════════════════════════ */

/* Врезка «как у нас»: тон абзаца задавался .article-brand .article-p — у
   конструктора класса на абзаце нет, тон брала общая шкала .article-text. */
.article-brand .article-text > p { color: var(--brand-main-base); }

/* Подзаголовок во врезке-списке: до 20.08 список всегда был первым ребёнком,
   и верхний паддинг первой строки снимало правило ol:first-child. С
   подзаголовком список первым быть перестал — снимаем по соседству. */
.article-card.article-text > .article-subhead + ol > li:first-child { padding-top: 0; }
.article-card.article-text > .article-subhead + ol > li:first-child::before { top: 0; }
