/* ===== site-v2 — каркас (шапка/меню/подвал/эффекты), поверх prod/assets/styles.css =====
   Токены и палитра НЕ переопределяются — только компоновка и эффекты нового каркаса.
   Подключать после fonts.css + styles.css.

   Меню (десктоп-дропдауны "Услуги"/"Материалы" и мобильный бургер) собраны на
   нативных <details>/<summary> — работают без единого байта JS. Скрипт (motion.js)
   только ДОБАВЛЯЕТ анимацию открытия и мелкие удобства (закрытие по Escape,
   закрытие соседних пунктов, блокировка скролла фона). Если JS не выполнился —
   меню всё равно открывается/закрывается кликом или клавиатурой (родное поведение
   браузера для <details>). */

/* ---------- Фокус с клавиатуры (в styles.css не определён явно) ---------- */
.shell-header a:focus-visible,
.shell-header summary:focus-visible,
.navpanel a:focus-visible,
.mobilemenu a:focus-visible,
.door:focus-visible,
.dnum:focus-visible,
.kcard:focus-visible,
.kcard-hit:focus-visible,
.kcard-yt:focus-visible,
.dnum-hit:focus-visible,
.dnum-yt:focus-visible {
  outline: 2px solid var(--accent-ink);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ---------- Шапка ----------
   Специфичность важна: базовое правило в styles.css — `header.site .wrap`
   (тип + 2 класса). Слабый класс-селектор молча проигрывал бы ему, и
   на телефоне действовало бы старое канон-правило `@media(max-width:640px)
   header.site .wrap { flex-direction:column }` (оно ставило шапку в столбик,
   когда меню ещё не переносилось в бургер, а просто переносилось строкой
   под лого). С бургером шапка всегда однострочная — логотип слева, бургер
   справа, — поэтому здесь перебиваем И flex-direction, И align-items, а не
   только flex-wrap. */
header.site.shell-header .wrap { flex-wrap: nowrap; flex-direction: row; align-items: center; gap: 18px; }
.shell-header .sitenav { flex: 1 1 auto; align-items: center; }
.navcta { margin-top: 0; padding: 10px 22px; font-size: 14px; white-space: nowrap; }

/* ---------- Выпадающие пункты меню: <details class="navdd"> ---------- */
.navdd { position: relative; list-style: none; }
.navdd > summary {
  list-style: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  font: inherit; font-size: 14px; font-weight: 600; color: var(--text);
  padding: 6px 0;
}
.navdd > summary::-webkit-details-marker { display: none; }
.navdd > summary::marker { content: ''; }
.navdd > summary:hover,
.navdd[open] > summary { color: var(--accent-ink); }
.navdd > summary .car {
  width: 7px; height: 7px; margin-top: -2px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg); transition: transform .2s var(--ease);
}
.navdd[open] > summary .car { transform: rotate(225deg) translate(2px, 2px); }

.navpanel {
  position: absolute; top: 100%; left: -14px; margin-top: 14px;
  min-width: 250px; background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; padding: 8px; box-shadow: 0 14px 32px rgba(23, 34, 44, .14);
  z-index: 60;
}
.navpanel a { display: block; padding: 10px 12px; border-radius: 6px; text-decoration: none; color: var(--ink); }
.navpanel a:hover { background: var(--bg); }
.navpanel .lbl { display: block; font-size: 14px; font-weight: 600; }
.navpanel .who { display: block; margin-top: 3px; font-family: 'JetBrains Mono', monospace; font-size: 11px; letter-spacing: .03em; color: var(--muted); }
.navpanel .soon { display: block; padding: 10px 12px; font-size: 13px; color: var(--faint); }

/* ---------- Бургер + полноэкранное меню: <details class="mobiletoggle"> ---------- */
.mobiletoggle { display: none; list-style: none; }
.mobiletoggle > summary.burger {
  list-style: none; cursor: pointer;
  width: 44px; height: 44px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
}
.mobiletoggle > summary.burger::-webkit-details-marker { display: none; }
.mobiletoggle > summary.burger::marker { content: ''; }
.mobiletoggle > summary.burger span { display: block; width: 18px; height: 2px; background: var(--ink); transition: transform .2s var(--ease), opacity .2s var(--ease); }
.mobiletoggle[open] > summary.burger { position: fixed; top: 18px; right: 6%; z-index: 110; }
.mobiletoggle[open] > summary.burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.mobiletoggle[open] > summary.burger span:nth-child(2) { opacity: 0; }
.mobiletoggle[open] > summary.burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.mobilemenu { position: fixed; inset: 0; z-index: 100; background: var(--bg); overflow-y: auto; }
/* Не переиспользуем класс .wrap: этот блок лежит внутри <header> (того требует
   вложенность <details>), и общий селектор `header.site .wrap` (тип+2 класса)
   перебивал бы направление и паддинги сильнее, чем локальный класс — уже
   ловили ровно этот баг на самой шапке. Даём контейнеру своё имя. */
.mm-inner { max-width: 1120px; margin: 0 auto; padding: 80px 6% 40px; min-height: 100%; display: flex; flex-direction: column; }
.mm-logo { font-family: 'Daray', sans-serif; font-size: 20px; color: var(--muted); }
.mobilemenu nav { display: flex; flex-direction: column; margin-top: 18px; }
.mobilemenu nav > a { font-family: 'Daray', sans-serif; font-size: 26px; color: var(--ink); text-decoration: none; padding: 16px 0; border-bottom: 1px solid var(--line); }

.maccordion { border-bottom: 1px solid var(--line); }
.maccordion > summary {
  font-family: 'Daray', sans-serif; font-size: 26px; color: var(--ink); padding: 16px 0; cursor: pointer; list-style: none;
}
.maccordion > summary::-webkit-details-marker { display: none; }
.maccordion > summary::marker { content: ''; }
/* Тот же маркер, что уже используют .faqlist/.caselist в styles.css — не заводим второй визуальный язык раскрывашек */
.maccordion > summary::after { content: '\25B8'; float: right; font-family: 'JetBrains Mono', monospace; color: var(--accent-ink); }
.maccordion[open] > summary::after { content: '\25BE'; }
.maccordion a { display: block; padding: 10px 0 10px 4px; text-decoration: none; color: var(--text); font-size: 16px; border-top: 1px solid var(--line); }
.maccordion a:first-of-type { border-top: none; margin-top: 4px; }
.maccordion a small { display: block; margin-top: 2px; font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--muted); }
.maccordion .soon { display: block; padding: 10px 0 4px 4px; font-size: 14px; color: var(--faint); }
.mm-cta { padding-top: 0; }

@media (max-width: 860px) {
  .shell-header .sitenav, .navcta { display: none; }
  .mobiletoggle { display: inline-flex; }
}

/* ---------- Hero: один сдержанный жест на загрузке первого экрана ----------
   DESIGN-REVIEW #3: единственное место, где motion-on-load оправдан (дальше —
   всё по скроллу). Строка мини-фактов, которая тут раньше стояла, снята
   целиком (решение по CA-REVIEW/DESIGN-REVIEW — см. README, "Hero-факты"):
   3 персонажа из 4 читали три неподписанных числа подряд как шум, а не как
   довод, и те же числа уже полностью раскрыты ниже, в "Реальных результатах",
   с подписью и мини-визуалом у каждого. */
.js .hero-load .txt > * {
  opacity: 0; transform: translateY(14px);
  animation: heroIn .6s var(--ease) forwards;
}
.js .hero-load .txt > *:nth-child(1) { animation-delay: .05s; }
.js .hero-load .txt > *:nth-child(2) { animation-delay: .13s; }
.js .hero-load .txt > *:nth-child(3) { animation-delay: .21s; }
.js .hero-load .txt > *:nth-child(4) { animation-delay: .29s; }
.js .hero-load .txt > *:nth-child(5) { animation-delay: .37s; }
@keyframes heroIn { to { opacity: 1; transform: none; } }

/* ---------- Ярлык аудитории над заголовком: .who-tag ----------
   Раньше дублировался: .door .who (тут) и отдельно .kons-who в pages.css —
   один и тот же mono/uppercase/accent-ink вид, разный margin-bottom.
   Сведено к одному классу (30.09, доводка) — .navpanel .who НЕ трогаем,
   это другой компонент (серая подпись под пунктом меню, другой цвет/трекинг). */
.who-tag { display: block; margin-bottom: 12px; font-family: 'JetBrains Mono', monospace; font-size: 11px; letter-spacing: .06em; color: var(--accent-ink); text-transform: uppercase; }

/* ---------- Три пути: дополнения к .door (переиспользуем компонент) ---------- */
.door .badge { display: inline-block; margin: -4px 0 12px; padding: 3px 9px; border-radius: 999px; background: var(--bg); font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--accent-ink); }
.door .price { font-family: 'Daray', sans-serif; font-size: 30px; color: var(--ink); margin: 10px 0 4px; line-height: 1.15; min-height: 45px; }
.door .price.small { font-family: 'Onest', system-ui, sans-serif; font-size: 15px; font-weight: 600; color: var(--text); display: flex; align-items: center; }
.door.main { border-color: var(--ink); }
.door-btn { margin-top: 14px; padding: 10px 20px; font-size: 14px; }
.door-fine { margin-top: 10px; font-size: 13px; color: var(--muted); line-height: 1.5; }
/* Три равные карточки в ряд — .doors по умолчанию просто flex-wrap:wrap, и при
   320px+320px+320px впритык к ширине контента третья карточка перескакивала
   на свою строку и визуально "растягивалась" на всю ширину (это и заметил
   Илья). Грид с фиксированными тремя колонками не зависит от такой арифметики. */
.doors.three { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; align-items: stretch; }
.doors.three .door { flex: none; display: flex; flex-direction: column; }
.doors.three .door-btn { margin-top: auto; align-self: flex-start; }
@media (max-width: 900px) { .doors.three { grid-template-columns: 1fr; } }

/* ---------- Ситуации-карточки ---------- */
.painlist { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 8px; }
/* 5-я карточка (новичок) — нечётная и последняя, растягиваем на всю ширину,
   тем же приёмом, что styles.css уже применяет к .tiles/.dgrid в похожей ситуации. */
.painlist > .pain:last-child:nth-child(odd) { grid-column: 1 / -1; }
@media (max-width: 640px) { .painlist { grid-template-columns: 1fr; } }

/* ---------- Реальные результаты: крупные цифры + мини-визуал данных ----------
   Масштаб цифр — как на хабе /keysy/ (.kcard .big), а не мелкий mono-стиль
   штатного .dnum b с обычных страниц кейсов: это визуальная вершина главной.

   Раскладка карточек — своя, не штатная .dgrid/.dnum: канон держит на планшете
   grid 2 колонки (styles.css:319) и явно форсирует grid 2 колонки на телефоне
   (styles.css:357) с общими границами между ячейками (border-right/-bottom) —
   рассчитано на короткие терминальные строки без мини-визуала. С крупными
   Daray-цифрами и столбиками/точками внутри та же 2-колоночная сетка на
   телефоне превращается в тесноту с разрезающей вертикальной линией (замечено
   CA-REVIEW, персонажи 1/2/4). Вместо правки общих .dgrid/.dnum — даём этому
   конкретному блоку свою раскладку: карточки с собственной рамкой на каждой
   (как .door/.kcard), не общий контур с внутренними границами. */
.dgrid.big { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; border: none; background: none; }
.dgrid.big .dnum { border: 1px solid var(--dark-line); border-radius: 8px; padding: 26px 26px 24px; }
.dgrid.big .dnum b {
  display: block; font-family: 'Daray', sans-serif; font-weight: 400;
  font-size: clamp(40px, 28px + 2.4vw, 60px); line-height: .98; letter-spacing: .5px;
  color: var(--dark-text); margin-bottom: 10px; white-space: nowrap;
}
.dgrid.big .dnum p { margin-bottom: 14px; }
@media (max-width: 640px) { .dgrid.big { grid-template-columns: 1fr; } }

.miniviz { margin: 4px 0 14px; }
.mv-row { display: grid; grid-template-columns: 1fr; margin-top: 6px; }
.mv-bar {
  height: 26px; border-radius: 4px; display: flex; align-items: center; padding: 0 10px;
  font-family: 'JetBrains Mono', monospace; font-weight: 700; font-size: 12.5px; white-space: nowrap;
  transition: width .9s var(--ease); /* та же длительность, что у счёта цифры (900мс в motion.js) — оба заканчиваются вместе */
}
.mv-bar.hi { background: var(--dark-text); color: var(--ink); }
.mv-bar.lo { background: transparent; border: 1px dashed var(--dark-muted); color: var(--dark-muted); }
/* Столбик считается синхронно с цифрой над ним (один и тот же триггер в
   motion.js: пересечение карточки в кадре). До этого момента — прижат к 0
   ТОЛЬКО когда есть JS; без JS/при reduced-motion инлайновая width из HTML
   (финальное значение) ничем не перебита — см. правило ниже и в README. */
.js .miniviz:not(.in) .mv-bar { width: 0 !important; }

.mv-dots { display: grid; grid-template-columns: repeat(23, 8px); gap: 4px; }
.mv-dots i { width: 9px; height: 9px; border-radius: 50%; background: var(--dark-text); display: block; transition: opacity .3s var(--ease); transition-delay: calc(var(--i, 0) * 18ms); }
.mv-dots i.miss { background: transparent; border: 2px solid var(--dark-muted); }
/* Второй пропущенный кружок терялся на обычном расстоянии просмотра на 1440px
   (DESIGN-REVIEW №9) — обводка и сам кружок чуть крупнее (было 8px/1.5px). */
.js .miniviz:not(.in) .mv-dots i { opacity: 0; }
@media (max-width: 640px) { .mv-dots { grid-template-columns: repeat(12, 8px); } .mv-dots i { width: 8px; height: 8px; } }

/* ---------- Как это устроено: горизонтальный поток (вертикальный на телефоне),
   переиспользует .flow/.node/.arr из кейсов + собственная линия-прогресс ---------- */
.howflow { position: relative; margin-top: 44px; }
.howline { display: block; width: 100%; height: 6px; margin-bottom: 22px; overflow: visible; }
.howline line { stroke: var(--line); stroke-width: 2; }
.js .howline line { stroke-dasharray: 100; stroke-dashoffset: 100; transition: stroke-dashoffset 1s var(--ease); }
.howflow.in .howline line { stroke: var(--accent-ink); stroke-dashoffset: 0; }
@media (max-width: 640px) { .howline { display: none; } }

.howflow .flow .node { flex-direction: column; align-items: flex-start; gap: 10px; text-align: left; padding: 18px 18px; }
.howflow .flow .node b { font-weight: 600; font-size: 15px; }
.howflow .flow .node .desc { display: block; margin-top: 3px; font-size: 13px; font-weight: 500; color: var(--muted); }
.howflow .nic {
  width: 36px; height: 36px; border-radius: 8px; background: var(--surface); border: 1px solid var(--line);
  color: var(--accent-ink); display: flex; align-items: center; justify-content: center; flex: none;
}
.howflow .node.end .nic { background: var(--ink); color: var(--dark-text); border-color: var(--ink); }
.howflow .flow .arr { color: var(--faint); }
.js .howflow .flow > li { opacity: 0; transform: translateY(10px); transition: opacity .5s var(--ease), transform .5s var(--ease); }
.howflow.in .flow > li { opacity: 1; transform: none; }
.howflow.in .flow > li:nth-child(2) { transition-delay: .12s; }
.howflow.in .flow > li:nth-child(3) { transition-delay: .22s; }
.howflow.in .flow > li:nth-child(4) { transition-delay: .34s; }
.howflow.in .flow > li:nth-child(5) { transition-delay: .44s; }

/* ---------- Числа считаются: не дёргаем ширину цифр ---------- */
.dnum b, .num b, .mini b { font-variant-numeric: tabular-nums; }
/* "80/день" переносился ровно после слэша ("80/" и "день" на разных строках) —
   выглядело как обрыв слова (CA-REVIEW №5). Канон .mini b такого правила не
   задаёт (короткие цифры вроде дат туда не переносятся), здесь у нас составной
   текст с "/" — держим его одной строкой явно. */
.mini b { white-space: nowrap; }

/* ---------- Полноэкранное меню: соцсети над кнопкой, чтобы не было пустоты
   на высоких экранах (DESIGN-REVIEW №5) — переиспользуем .socials из подвала ---------- */
.mm-socials { margin-top: auto; padding-top: 24px; }
.mm-socials.socials { text-align: left; }
.mm-cta { margin-top: 18px; }

/* ---------- Параллакс hero-фото ---------- */
.hero .pic { overflow: hidden; }
.js .hero .pic img { will-change: transform; }

/* ---------- Канон .dots/.bar: появление в кадре ----------
   Перенесено из pages-keysy.css (30.09, доводка) — использовалось на 2+
   страницах (.dots: keysy-prodazhi.html, keysy-kurator.html; .bar:
   keysy-smeta.html), page-файл после переноса стал пустым и удалён.
   Сами .dots/.bar/.bars — канон-классы из prod/assets/styles.css, здесь
   только анимация появления при пересечении [data-reveal] с кадром. */
.js .dots i {
  opacity: 0;
  transition: opacity .3s var(--ease);
  transition-delay: calc(var(--i, 0) * 14ms);
}
.js [data-reveal].in .dots i { opacity: 1; }
.js [data-reveal] .bar { transition: width .9s var(--ease); }
.js [data-reveal]:not(.in) .bar { width: 0 !important; }

/* ---------- Активный пункт меню: aria-current="page" ----------
   Ставится в разметке на ссылку своей страницы (шапка + мобильное меню).
   Цвет — тот же accent-ink, что уже используют hover/open состояния меню. */
.sitenav > a[aria-current="page"],
.mobilemenu nav > a[aria-current="page"] { color: var(--accent-ink); }
.navpanel a[aria-current="page"] .lbl,
.maccordion a[aria-current="page"] { color: var(--accent-ink); }
.navdd:has(a[aria-current="page"]) > summary,
.maccordion:has(a[aria-current="page"]) { border-color: var(--accent-ink); }
.navdd:has(a[aria-current="page"]) > summary { color: var(--accent-ink); }

/* ---------- prefers-reduced-motion: гасим то, что не покрыто глобальным правилом styles.css ----------
   Глобальное правило в styles.css (`* { transition:none!important; animation:none!important; }`)
   отключает САМИ переходы/анимации, но не трогает литеральные opacity/transform, заданные
   вне keyframe-а как стартовое состояние. .hero-load задаёт `opacity:0; transform:translateY(14px)`
   прямо на селекторе (не в @keyframes) — без анимации это состояние никогда не сменится на видимое,
   и текст/фото первого экрана остаются невидимыми навсегда при выключенном JS-флаге motion. Известный
   гэп (README/задача 30.09) — чинится явным принудительным сбросом здесь. */
@media (prefers-reduced-motion: reduce) {
  .js .hero .pic img { transform: none !important; }
  .js .hero-load .txt > *,
  .js .hero-load .pic { opacity: 1 !important; transform: none !important; }
  .js .dots i { transition: none; }
  .js [data-reveal] .bar { transition: none; }
}

/* ---------- /biznesu/ — правки, специфичные для этой страницы (перенос pages-biz.css, 30.09) ----------
   Четвёртая карточка "Кейсы" (CRM iCambio, 80/день) — единственная без .miniviz (для
   рассылок/CRM нет чистой пары чисел для mv-bars, придумывать не стал). Без flex-колонки
   её "→ разбор кейса" повисает сразу под текстом, а не у нижнего края карточки вровень
   с соседями, у которых есть miniviz. Scope-id исправлен на реальный id прод-страницы
   (#p-biz-v2 был id прототипа, боевая страница — #p-biz). */
#p-biz .dgrid.big .dnum { display: flex; flex-direction: column; }
#p-biz .dgrid.big .dnum .go { margin-top: auto; padding-top: 10px; }

/* ================================================================
   30.09 — визуальный слой (иконки, обложки кейсов, тонированные подложки,
   генеративный фон). Ничего из существующего выше не менялось — только
   новые классы поверх канона и текущего каркаса. */

/* ---------- Иконки: общий квадрат под линейный SVG из /assets/icons.svg
   (тот же визуальный язык, что .did .ic уже даёт на страницах кейсов —
   24×24 viewBox, stroke 1.7, круглые концы, currentColor) ---------- */
.icobox { width: 40px; height: 40px; border-radius: 8px; background: var(--surface); border: 1px solid var(--line); color: var(--accent-ink); display: flex; align-items: center; justify-content: center; flex: none; margin-bottom: 14px; }
.icobox svg { width: 22px; height: 22px; }
.darksec .icobox, .dgrid.big .icobox { background: transparent; border-color: var(--dark-line); color: var(--dark-text); }

/* Иконки болей/услуг (.pain/.door) — подложка surface-на-surface была почти не
   видна (тонкая граница var(--line) на белой карточке), тонируем токеном
   акцента (RED design-review 30.09: «мелкие и бледные — не читаются»). */
.painlist .icobox,
.door .icobox { background: color-mix(in srgb, var(--accent-ink) 10%, var(--bg)); border-color: transparent; }

/* Ситуации (.situ, /praktika/) — иконка в строке слева от текста, не над ним */
.situ { display: flex; align-items: flex-start; gap: 14px; }
.situ .icobox { margin-bottom: 0; }
.situ-txt { display: block; }

/* Факты «Кто ведёт» (.mini) — иконка слева от цифры в одну строку, подпись —
   отдельной строкой ПОД этой парой (RED design-review 30.09: было «иконка
   рядом с подписью, цифра снизу» — порядок перепутан). Затрагивает только
   .mini с .mini-num внутри — голые пары число/подпись без иконки
   («60 минут» / «5 000 ₽» и т.п.) держат канон-раскладку в 2 колонки. */
.mini:has(.mini-num) { grid-template-columns: 1fr; row-gap: 6px; }
.mini-num { display: flex; flex-direction: row; align-items: center; gap: 12px; }
.mini-num .icobox { margin-bottom: 0; width: 38px; height: 38px; border-radius: 9px; background: color-mix(in srgb, var(--accent-ink) 10%, var(--bg)); border-color: transparent; }
.mini-num .icobox svg { width: 21px; height: 21px; }

/* Карточки-двери (.door, главная «Что вы получите») — иконка перед аудиторией */
.door .icobox { margin-bottom: 10px; }

/* Пункты меню «Услуги» — иконка слева от подписи. Специфичность та же
   (класс+тип), но правило идёт ПОСЛЕ исходного `.navpanel a`/`.maccordion a`
   в каскаде — перебивает только display/gap, остальные свойства (padding,
   border-radius, hover) не трогаем. */
.navpanel a { display: flex; align-items: flex-start; gap: 12px; }
.navpanel a .icobox { width: 30px; height: 30px; border-radius: 6px; margin-bottom: 0; flex: none; }
.navpanel a .icobox svg { width: 17px; height: 17px; }
.navpanel a .ntxt { display: block; }
/* nav.sitenav a (inline-block) перебивал раскладку пунктов панели: два пункта без иконок слипались в строку (03.10, пункт «Статьи»). */
nav.sitenav .navpanel a { display: flex; }
.maccordion a { display: flex; align-items: flex-start; gap: 12px; }
.maccordion a .icobox { width: 28px; height: 28px; border-radius: 6px; margin-bottom: 0; flex: none; margin-top: 2px; }
.maccordion a .icobox svg { width: 16px; height: 16px; }
.maccordion a .ntxt { display: block; }

/* ---------- Тонированные подложки из токенов (Илья 30.09: «фон однообразный») ----------
   Только color-mix() из существующих переменных — новых цветов не вводим.
   .tintsec — светлая подложка-«карточка» между обычными белыми секциями:
   лёгкий сдвиг --bg к --line, достаточно для ритма, недостаточно чтобы
   выглядеть отдельным цветом. Используется под «Мне доверяют»/отзывами и
   результатами там, где нет отдельной тёмной секции. */
.tintsec { background: color-mix(in srgb, var(--line) 22%, var(--bg)); }

/* Правило darksec ослаблено (Илья 30.09): раньше — одна тёмная секция на
   страницу. Теперь можно ДВЕ — тёмная полоса результатов (уже была на
   главной/консультации/бизнесу/практике) + тёмный финальный призыв внизу.
   Третьей тёмной секции на странице быть не должно. */

/* ---------- Обложки кейсов (.kcover) — хаб /keysy/, лента результатов, начало страницы кейса ----------
   RED design-review 30.09: старый набор (превью YouTube с play-бейджем,
   разномастные скриншоты, типографские "цифра+бары" карточки) был разнобойным
   и в трёх случаях дублировал крупную цифру дважды. Заменён единой серией из
   7 иллюстраций-обложек в одном стиле (сгенерированы, см. wiki проекта) — все
   на едином соотношении 16:10, поэтому --kar больше не варьируется в разметке.
   .kcover-play/.kcover-data/.kcover-link сняты как осиротевшие. */
.kcover { display: block; position: relative; width: 100%; aspect-ratio: var(--kar, 16 / 10); border-radius: 8px; overflow: hidden; margin-bottom: 16px; background: color-mix(in srgb, var(--line) 22%, var(--bg)); }
.kcover img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* На тёмных карточках (.dnum в .darksec) обложка — часть той же тёмной поверхности, не отдельное светлое пятно */
.dgrid.big .dnum .kcover { background: color-mix(in srgb, var(--dark-line) 55%, var(--dark)); margin-bottom: 14px; }
/* Лента "Реальные результаты" — карточка с обложкой не должна стать тяжелее
   текстовых соседей: обложка здесь ниже, чем на хабе /keysy/ (RED
   design-review 30.09, п.1: "тёмная полоса не должна стать тяжёлой"). */
.dgrid.big .dnum .kcover { max-height: 150px; }
/* Обложка в начале страницы кейса — крупнее, во всю читаемую колонку */
.kase .kcover-page { max-width: 980px; margin: 22px 0 0; }

/* ---------- Карточки-кейсы с видеоразбором (аудит, контент-завод) ----------
   Обложка больше не превью YouTube с play-кнопкой — обычная иллюстрация из
   единой серии, а переход на видео вынесен отдельной строкой-ссылкой под
   карточкой (RED design-review 30.09, п.1: "превью YouTube не использовать
   как обложку"). Из-за двух независимых ссылок карточка из одного <a>
   становится <div class="kcard/dnum"> с двумя дочерними ссылками —
   .kcard/.dnum остаются тем же контейнером (класс без типа `a`, работает
   для обоих случаев разметки), нового визуального языка не вводим. */
.kcard-hit { display: flex; flex-direction: column; flex: 1; text-decoration: none; color: inherit; }
/* Тап-таргет ≥44px (QA 2026-10-01): раньше строчная ссылка без вертикального
   поля — inline-flex + min-height держат размер тапа, не увеличивая текст. */
.kcard-yt { display: inline-flex; align-items: center; min-height: 44px; margin-top: 12px; padding: 12px 0; border-top: 1px solid var(--line); font-size: 14px; font-weight: 600; color: var(--accent-ink); text-decoration: none; }
.kcard-yt:hover { color: var(--ink); }
.dnum-hit { display: block; text-decoration: none; color: inherit; }
.dnum-yt { display: inline-flex; align-items: center; min-height: 44px; margin-top: 8px; padding-block: 8px; font-family: 'JetBrains Mono', monospace; font-size: 11px; letter-spacing: .06em; color: var(--accent); text-decoration: none; }
.dnum-yt:hover { color: var(--dark-text); }

/* ---------- Генеративный фон данных (canvas, ≤4КБ gzip, см. /assets/data-fx.js) ----------
   Контейнер занимает всю секцию позади контента; canvas сам решает частоту
   кадров и паузу (IntersectionObserver + document.hidden + prefers-reduced-motion,
   см. data-fx.js). Без JS — просто нет canvas, секция остаётся на сплошном
   фоне токена, ничего не ломается и не пусто. */
.databg { position: relative; isolation: isolate; }
/* opacity .55 почти гасило и без того полупрозрачную отрисовку в data-fx.js
   (точки .55 alpha, линии до .14) — на глаз эффект был почти не виден
   (RED design-review 30.09). Контраст поднят в обоих местах, цвет токена
   (--dark-text) не менялся. */
.databg canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; opacity: .85; pointer-events: none; color: var(--dark-text); }
.databg > .wrap { position: relative; z-index: 1; }

/* ================================================================
   Плашка «Найти задачу для ИИ» (prod/assets/zadacha-popup.js, добавлена 04.10)
   Разметку строит скрипт, на /zadacha/ его нет. Токены и поведение — как у остальных
   компонентов каркаса: тёмная таблетка (тот же --ink, что у главной кнопки .btn),
   карточка в стиле выпадающей панели меню (.navpanel): белая, тонкая рамка, мягкая тень.
   БЛОК ДУБЛИРУЕТСЯ в content/efir/ii-na-zhivyh-zadachah/assets/style.css (+ копия в prod/efir):
   у конспекта эфира свой style.css, shell.css он не грузит. Правишь здесь — правь и там. */
.zp { position: fixed; right: max(16px, env(safe-area-inset-right)); bottom: max(16px, env(safe-area-inset-bottom)); z-index: 80; font-family: 'Onest', system-ui, sans-serif; }
.zp-pill {
  display: inline-flex; align-items: center; gap: 10px; min-height: 44px; padding: 0 18px 0 14px;
  border: 0; border-radius: 999px; background: var(--ink); color: var(--bg);
  font: inherit; font-size: 14px; font-weight: 600; line-height: 1; white-space: nowrap; cursor: pointer;
  box-shadow: 0 10px 24px -8px rgba(23, 34, 44, .45), 0 2px 6px rgba(23, 34, 44, .18);
  opacity: 0; visibility: hidden; transform: translateY(10px);
  transition: opacity .35s var(--ease), transform .35s var(--ease), visibility 0s linear .35s, background .18s ease;
}
.zp-pill svg { width: 20px; height: 20px; flex: none; color: var(--accent); }
.zp-pill:hover { background: var(--text); }
.zp.is-in .zp-pill { opacity: 1; visibility: visible; transform: none; transition-delay: 0s; }
/* таблетка уступает место, когда под ней кнопка или ссылка подвала */
.zp.is-in.is-away .zp-pill { opacity: 0; visibility: hidden; transform: translateY(10px); pointer-events: none; transition: opacity .25s var(--ease), transform .25s var(--ease), visibility 0s linear .25s; }
.zp.is-open .zp-pill { opacity: 0; visibility: hidden; transform: translateY(6px); pointer-events: none; transition: opacity .15s ease, transform .15s ease, visibility 0s linear .15s; }

.zp-card {
  position: absolute; right: 0; bottom: 0; width: min(344px, calc(100vw - 32px));
  padding: 22px 22px 20px; background: var(--surface); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 18px 40px -12px rgba(23, 34, 44, .28), 0 2px 8px rgba(23, 34, 44, .08);
  opacity: 0; visibility: hidden; transform: translateY(12px) scale(.98); transform-origin: right bottom;
  transition: opacity .2s var(--ease), transform .28s var(--ease), visibility 0s linear .28s;
}
.zp.is-open .zp-card { opacity: 1; visibility: visible; transform: none; transition-delay: 0s; }
.zp-card:focus, .zp-card:focus-visible { outline: none; }
.zp-title { margin: 0 34px 8px 0; font-family: 'Daray', sans-serif; font-weight: 400; font-size: 23px; line-height: 1.15; letter-spacing: .5px; color: var(--ink); }
.zp-text { margin: 0; font-size: 15px; line-height: 1.55; color: var(--text); }
.zp-go {
  display: flex; align-items: center; justify-content: center; min-height: 48px; margin-top: 18px; padding: 12px 18px;
  border: 0; border-radius: 6px; background: var(--ink); color: var(--bg);
  font-size: 15px; font-weight: 600; text-align: center; text-decoration: none;
  transition: background .18s ease, transform .18s ease;
}
.zp-go:hover { background: var(--text); transform: translateY(-1px); color: var(--bg); border: 0; }
.zp-more {
  display: flex; align-items: center; min-height: 44px; margin-top: 4px; padding: 0 2px;
  border: 0; font-size: 14px; font-weight: 600; color: var(--accent-ink); text-decoration: none;
}
.zp-more:hover { color: var(--ink); border: 0; }
.zp-x {
  position: absolute; top: 6px; right: 6px; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 8px;
  background: none; color: var(--muted); cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: color .15s ease, background .15s ease;
}
.zp-x:hover { color: var(--ink); background: var(--bg); }
.zp-x svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
.zp-pill:focus-visible, .zp-go:focus-visible, .zp-more:focus-visible, .zp-x:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) {
  .zp-pill, .zp-card, .zp-go { transition: none !important; }
}
