/* ============================================================
   Andre AI web app — визуально идентичен главной andre.technology
   (FR-W9): то же видео-геро слева (67% на десктопе / 64dvh сверху
   на мобильном), тот же спикер-бейдж поверх видео, те же размеры
   лого/кнопок/шрифтов и zoom-скейлинг на больших экранах.

   mode-hero : экраны диагностики (лендинг, форма, тест, результат)
               — контент в правой панели, видео слева, как на главной.
   mode-app  : рабочие экраны (кабинет, отдел) — видео скрыто,
               чистый ЧЁРНЫЙ фон, фейды — из того же чистого чёрного (FR-W23 v4).
   ============================================================ */

:root {
  /* FR-W23 v4 «полосы — раз и навсегда» (замер #167). Механика: плёнка цвета
     фона с ЧАСТИЧНОЙ альфой поверх фона того же цвета в 8 битах НЕ возвращает
     исходный тон — round(c·α) + round(c·(1−α)) ≠ c. При c=5 (#050505) половина
     значений альфы даёт 4 → на экране появляется ВТОРОЙ чёрный #040404, а на
     почти-чёрном шаг 1/255 — это ~20% по светимости, глаз читает его как полосу.
     При c=0 тождество выполняется ТОЧНО при любой альфе.
     Отсюда инвариант: фон тёмной темы и ВСЕ полупрозрачные фейды — из ОДНОГО
     чистого чёрного rgba(0,0,0,α). Ни `transparent` (это rgba(0,0,0,0) — другой
     цвет, если фон не чёрный), ни var(--bg) внутри фейда (в светлой теме
     подставится другой цвет). Замер попиксельно, полоса через пустой фон:
     было 388/720/0 пикселей второго тона (891@1 / 891@1.25 / 1440@1) →
     стало 0/0/0. Снятие фейдов давало 158/284/0 и возвращало «обрубание». */
  --bg: #000000; --surface: #15151b; --border: rgba(255,255,255,0.10);
  --purple: #8854F3; --purple-l: #a071ff; --orange: #F97316; --orange-l: #ff8a33;
  --text: #E5E7EB; --dim: #94a3b8;
  --heading: #ffffff; --body2: #cbd5e1; --track: rgba(255,255,255,0.08);
  --btn-bg: #ffffff; --btn-fg: #000000; --input-bg: #0d0d12;
  --ctrl-bg: rgba(255,255,255,0.05); --ctrl-border: rgba(255,255,255,0.10);
  /* FR-UXI-61/NFR-UXI-16 (владелец 2026-09-01, «Вариант A»): ЕДИНАЯ поверхность
     карточек кабинета — графит без рамки, наведение — белая подсветка 8%.
     Только эти три токена красят карточки/плитки/пункты меню; литералы
     #15151b и rgba(255,255,255,0.08) вне объявлений токенов запрещены. */
  --card: #15151b; --card-border: rgba(0,0,0,0); --hover: rgba(255,255,255,0.08);
  /* NFR-UXI-24 ред. 2 (батч 4 FIX): линии подчинения оргсхемы — токен, а не
     литерал в правиле; светлая тема переопределяет его в html.light-cab */
  --org-line: rgba(255,255,255,0.28);
  /* FR-PRC6: зерно фона — общий источник для .grain и подложки композера,
     чтобы композер был ТОЧНО того же тона, что и фон (иначе он темнее) */
  --grain-img: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E");
}
html, body {
  margin: 0; padding: 0; background: var(--bg); color-scheme: dark;
  font-family: 'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; color: var(--text);
  /* NFR-FE8: у каждого dvh-размера — vh-фолбэк строкой ВЫШЕ (старые
     браузеры/вебвью без dvh иначе роняют всё правило) */
  width: 100%; min-height: 100vh; min-height: 100dvh;
  -webkit-tap-highlight-color: transparent;
}
body { overflow-x: hidden; }
/* FR-W22 v2: НИКАКОГО отдельного закрашенного слоя в нижней safe-area — у
   пользователя он выглядел «серой полоской внизу», которой нет у других
   приложений. Зона остаётся прозрачной: html/body уже красят background
   текущей темы, а theme-color/color-scheme синхронизируются с темой в
   applyMode() — браузер сам продолжает фон под жестовую полосу. */
*, *::before, *::after { box-sizing: border-box; }
/* hidden-атрибут всегда прячет элемент — иначе любой display в CSS его
   перебивает и «скрытая» кнопка остаётся видимой пустышкой (NFR-W6) */
[hidden] { display: none !important; }
*:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; }
::selection { background: var(--purple); color: #fff; }
a { text-decoration: none; color: inherit; }
button { font-family: inherit; }

@keyframes slideInPanel { from { opacity: 0; transform: translateY(44px); } to { opacity: 1; transform: translateY(0); } }
@keyframes gradientShimmer { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } }
@keyframes soundWave { 0% { transform: scale(1); opacity: 0.6; } 100% { transform: scale(2.2); opacity: 0; } }
@keyframes floatSlow { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
@keyframes auraPulse { 0%,100% { opacity: 0.45; transform: translate(-50%,-50%) scale(1); } 50% { opacity: 0.85; transform: translate(-50%,-50%) scale(1.12); } }
@keyframes orbPulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.07); } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes recPulse { 0%,100% { box-shadow: 0 0 0 0 rgba(249,115,22,0.55); } 50% { box-shadow: 0 0 0 12px rgba(249,115,22,0); } }

/* ===== Сцена с видео — CSS главной страницы ===== */
.scene { position: fixed; inset: 0; z-index: 0; overflow: hidden; background: var(--bg); }
/* FR-W10b: два видео-слоя наложены друг на друга; видимость — через opacity,
   переключение плавным кроссфейдом. Активный слой .is-active — непрозрачный,
   буфер — прозрачный (грузит следующий ролик), затем они меняются местами. */
#hero-video, #hero-video-2 { position: absolute; top: 0; left: 0; width: 100vw;
  height: 64vh; height: 64dvh;   /* NFR-FE8: vh-фолбэк */
  object-fit: cover; object-position: center; cursor: pointer;
  opacity: 0; transition: opacity 0.45s ease; }
#hero-video.is-active, #hero-video-2.is-active { opacity: 1; }
.hero-placeholder { position: absolute; top: 0; left: 0; width: 100vw;
  height: 64vh; height: 64dvh;   /* NFR-FE8: vh-фолбэк */
  display: flex; align-items: center; justify-content: center; }
.orb { width: min(38vw, 260px); aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, rgba(160,113,255,0.9), rgba(136,84,243,0.45) 45%, rgba(249,115,22,0.25) 75%, transparent 100%);
  filter: blur(6px); animation: orbPulse 6s ease-in-out infinite; }
.video-shadow { position: absolute; top: 0; left: 0; width: 100%;
  height: 64vh; height: 64dvh;   /* NFR-FE8: vh-фолбэк */
  pointer-events: none; z-index: 2;
  /* FR-W23 v4: все стопы — из ОДНОГО чистого чёрного (см. :root) */
  background: linear-gradient(to bottom, rgba(0,0,0,0) 6%, rgba(0,0,0,0.04) 20%, rgba(0,0,0,0.12) 33%, rgba(0,0,0,0.26) 45%, rgba(0,0,0,0.45) 57%, rgba(0,0,0,0.66) 69%, rgba(0,0,0,0.85) 81%, rgba(0,0,0,1) 94%); }
@media (min-width: 1024px) {
  #hero-video, #hero-video-2, .hero-placeholder { width: 67%; height: 100%; transform: translateX(-6%); }
  /* FR-W23b: постер (до загрузки ролика) маскируется ТЕМИ ЖЕ стопами, что и
     видео в applyVideoMask — иначе на первых кадрах виден резкий прямоугольный
     край. Стопы дублируются осознанно (JS красит уже загруженные слои,
     CSS — постер); расхождение ловит test_video_mask_in_js. */
  .hero-placeholder { -webkit-mask-image: linear-gradient(to right, #000 0%, #000 30%,
      rgba(0,0,0,0.95) 42%, rgba(0,0,0,0.84) 52%, rgba(0,0,0,0.66) 62%,
      rgba(0,0,0,0.46) 72%, rgba(0,0,0,0.28) 81%, rgba(0,0,0,0.14) 88%,
      rgba(0,0,0,0.06) 94%, rgba(0,0,0,0.02) 97%, transparent 100%);
    mask-image: linear-gradient(to right, #000 0%, #000 30%, rgba(0,0,0,0.95) 42%,
      rgba(0,0,0,0.84) 52%, rgba(0,0,0,0.66) 62%, rgba(0,0,0,0.46) 72%,
      rgba(0,0,0,0.28) 81%, rgba(0,0,0,0.14) 88%, rgba(0,0,0,0.06) 94%,
      rgba(0,0,0,0.02) 97%, transparent 100%); }
  /* FR-W23b: второй слой растворения — горизонтальный. Маска гасит сам ролик,
     а этот градиент доводит его правый край до фона страницы (чистый чёрный,
     --bg: #000), поэтому границы «видео | чёрное» не видно вовсе. */
  .video-shadow { height: 100%;
    background:
      linear-gradient(to right, rgba(0,0,0,0) 26%, rgba(0,0,0,0.12) 38%,
        rgba(0,0,0,0.3) 48%, rgba(0,0,0,0.52) 58%, rgba(0,0,0,0.72) 68%,
        rgba(0,0,0,0.88) 78%, rgba(0,0,0,0.97) 86%, rgba(0,0,0,1) 92%),
      linear-gradient(to top, rgba(0,0,0,1) 0%, rgba(0,0,0,0.35) 7%, rgba(0,0,0,0) 16%); }
}
/* app-режим: видео и его градиенты полностью убраны — чистый фон, без полос */
body.mode-app .scene { display: none; }
body.mode-app .speaker { display: none; }

/* FR-W16g: boot-оверлей — непрозрачный чёрный поверх ВСЕГО (лендинг/сцена под
   ним не видны) до первого showScreen; снимается clearBoot. Гасит «мелькание
   формы с шаром»/говорящей головы на холодном старте любого маршрута.
   Инлайн-скрипты запрещены CSP (script-src 'self'), поэтому фейлсейф — чисто
   CSS: если JS не снял оверлей за 12 c (упал на парсинге), он сам гаснет и
   открывает стартовую разметку под собой. */
#boot-cover { position: fixed; inset: 0; z-index: 100; display: flex;
  align-items: center; justify-content: center; background: var(--bg);
  animation: bootFailsafe 0s linear 12s forwards; }
@keyframes bootFailsafe { to { opacity: 0; visibility: hidden; pointer-events: none; } }
/* FR-W16i: ошибка загрузки кабинета в strategy-boot (после ретраев) — текст +
   кнопка «Повторить» по центру, вместо вечного спиннера */
.boot-error { display: flex; flex-direction: column; align-items: center; gap: 1.1rem;
  color: var(--body2); font-size: 14px; text-align: center; padding: 0 1.5rem; }

/* FR-W16h: экраны входа (auth) и приглашения (join) — БЕЗ говорящей головы,
   бейджа спикера и субтитров (это зона входа/стратегии, а не диагностика).
   Форма центрируется, как в app-режиме, а не жмётся в правую колонку. */
body.no-head .caption, body.no-head .scene, body.no-head .speaker { display: none; }
@media (min-width: 1024px) {
  body.no-head .content-layer { justify-content: center; }
  body.no-head .panel { margin: 0 auto; width: 100%; max-width: 34rem; }
}

/* ===== Мобайл: говорящая голова — перетаскиваемый кружок, как на курсе
   automation (FR-W13); тап по кружку — звук/с начала ===== */
@media (max-width: 1023px) {
  .scene { inset: auto; left: clamp(1.5rem, 5vw, 4rem); bottom: clamp(1.5rem, 5vh, 3rem);
    width: clamp(140px, 22vw, 280px); height: clamp(140px, 22vw, 280px);
    border-radius: 999px; overflow: hidden; z-index: 40;
    background: transparent;
    outline: 1px solid rgba(255,255,255,0.2); touch-action: none;
    user-select: none; -webkit-user-select: none; cursor: grab; }
  .bubble-grad { position: absolute; inset: 0; background: linear-gradient(135deg, #8854F3 0%, #F97316 100%); }
  #hero-video, #hero-video-2, .hero-placeholder { position: absolute; inset: 0; width: 100%; height: 100%; transform: none; }
  .orb { width: 72%; filter: blur(4px); }
  .video-shadow { display: none; }
  .bubble-sound { position: absolute; left: 50%; bottom: 8%; transform: translateX(-50%); z-index: 3;
    display: inline-flex; align-items: center; justify-content: center; height: 1.5rem; min-width: 1.5rem;
    padding: 0 0.4rem; border-radius: 999px; background: rgba(0,0,0,0.45); color: #fff; font-size: 0.72rem;
    pointer-events: none; -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); }
  .speaker { display: none; }
}
@media (max-width: 768px) {
  .scene { left: 15px; bottom: calc(15px + env(safe-area-inset-bottom, 0px)); width: 150px; height: 150px; }
}
@media (min-width: 1024px) { .bubble-grad, .bubble-sound { display: none; } }

/* ===== Grain — как на главной ===== */
/* FR-W21b (владелец 2026-09-18: «шапка серым становится на другом экране»):
   зерно лежит ПОВЕРХ шапки (z 31 > 30), а не под ней. Мобильная подложка
   шапки — сплошной чёрный градиент; раньше он закрывал зерно, и рядом
   оказывались два разных «чёрных»: чистый (шапка) и чёрный + 6 % зерна
   (страница). На маке с глубоким чёрным разницы не видно, на мониторе с
   приподнятым чёрным полоса шапки читается другим тоном. Зерно над шапкой
   — и тон у них тождественный по построению. pointer-events: none — клики
   по лого и языку проходят. */
.grain { position: fixed; inset: 0; z-index: 31; pointer-events: none; opacity: 0.06; mix-blend-mode: screen;
  background-image: var(--grain-img); background-size: 180px 180px; }
/* FR-PRC6b «фундаментально»: композер = РОВНО тон фона (или прозрачный), без
   «второго тёмного тона». Раньше на слот накладывалось то же зерно, что на
   странице, чтобы совпасть с ним. Но в app-режиме зерно страницы выключено
   (body.mode-app .grain{display:none}, #78) — а зерно НА СЛОТЕ оставалось, и
   именно оно давало композеру чуть иной тон, чем у фона. Убираем зерно со слота
   полностью: слот прозрачный/в тон --bg, сам .composer — transparent + только
   контур-пилюля. Ничего не «отличается по цвету». В светлой теме и так ок. */
body.mode-app #composer-slot-cab::before { display: none; }
body.mode-app #composer-slot-cab > * { position: relative; z-index: 1; }

/* ===== Header — размеры главной ===== */
header { position: fixed; top: 0; left: 0; right: 0; z-index: 30; pointer-events: none; padding: 1.1rem; }
@media (min-width: 1024px) { header { padding: 2rem; } }
/* FR-W21 (v3): в app-режиме (кабинет/процесс/карта) контент листается ПОД
   шапку — деликатная подложка, чтобы заголовок и кнопки читались поверх
   текста. БЕЗ blur (пользователь: «это должен быть не блюр, а аккуратное
   затемнение») — только полупрозрачный градиент на ::before (под контентом
   шапки), растворяется в ноль к ~70% высоты, поэтому мягко и не доходит до
   низа бокса. Тёмная тема — затемнение, светлая — забеливание; на
   диагностике (mode-hero) шапка остаётся прозрачной */
/* FR-W23 v2: фейд ВОЗВРАЩЁН (пользователь: «надо вернуть как было с плавным
   затуханием») — сплошная подложка жёстко «обрубала» контент.
   FR-W23 v4 (замер #167): вывод v2 «полосы были НЕ от фейда» был НЕВЕРЕН —
   именно этот фейд и давал полосу, потому что был налит цветом #050505 поверх
   фона #050505. Фейд оставляем (обрубать контент нельзя), но строим его из
   ЧИСТОГО ЧЁРНОГО — при c=0 полупрозрачный слой поверх фона тождественен фону
   при любой альфе, полоса физически невозможна (см. :root). */
/* FR-UXI-31 (ред. проход 2026-08-28): верх — НЕПРОЗРАЧНЫЙ на высоту строки
   заголовка (текст ленты читался сквозь буквы шапки), ниже строки фейд
   ОСТАЁТСЯ (пользователь: «плавное затухание», обрубать нельзя) */
/* FR-UXI-31 ред. 2 (B12, обход 2026-09-06): подложка кончалась ровно на
   нижней границе шапки, и хвост фейда (0.45 → 0) приходился на её последние
   пиксели — прокручиваемый текст успевал показаться ПОЛУПРОЗРАЧНЫМ прямо под
   полем «Поиск». На кадрах обхода это видно на каждом шаге интервью: половина
   строки рассказа висит за полем, а на шаге цели так пряталось единственное
   объяснение слова «триггер». Стопы прежние (непрозрачный верх — FR-UXI-31),
   но подложка ПРОДОЛЖАЕТСЯ ниже шапки, и растворение уходит в воздух между
   шапкой и контентом. */
body.mode-app header::before { content: ""; position: absolute;
  inset: 0 0 auto 0; height: calc(100% + 2.2rem); z-index: -1;
  background: linear-gradient(180deg, rgba(0,0,0,1) 0%, rgba(0,0,0,1) 48%, rgba(0,0,0,0.45) 74%, rgba(0,0,0,0) 100%); }
/* светлая тема: фейд — цветом СТРАНИЦЫ (#f8fafc), а не чистым белым: белая
   плёнка поверх near-white тоже даёт второй тон, просто на светлом конце шкалы
   он почти незаметен. Тон-в-тон надёжнее. */
html.light-cab body.mode-app header::before {
  height: calc(100% + 2.2rem);
  background: linear-gradient(180deg, rgba(248,250,252,1) 0%, rgba(248,250,252,1) 48%, rgba(248,250,252,0.45) 74%, rgba(248,250,252,0) 100%); }
/* FR-W20c: высота строки шапки ЗАФИКСИРОВАНА под размер лого — иначе при
   разворачивании сайдбара (лого прячется из шапки, .header-left display:none)
   строка теряла самый высокий элемент, схлопывалась по высоте, и заголовок
   ВЕРТИКАЛЬНО СКАКАЛ ВВЕРХ (пользователь: «вправо перемещаться может, вверх
   скакать — нет»). min-height = высота лого → центр строки не двигается,
   есть логотип в ней или нет. Горизонтальный сдвиг вправо при этом сохранён. */
.header-row { display: flex; align-items: center; justify-content: space-between;
  gap: 0.5rem; min-height: clamp(2.85rem, 12vw, 3.7rem); }
@media (min-width: 1024px) { .header-row { min-height: 3.6rem; } }
/* FR-W20: заголовок экрана (компания/процесс) — в ШАПКЕ, на одной линии с лого
   и кнопками (пользователь: «название должно быть наверху на уровне кнопок и
   лого»). pointer-events:auto — внутри живёт кнопка «назад» процесса;
   min-width:0 + ellipsis — длинное название НЕ выталкивает кнопки справа. */
/* FR-W26b: кнопка «назад» процесса стояла ВПЛОТНУЮ к «развернуть» (»)
   в header-left — на телефоне пальцем не попасть, промахиваешься в сайдбар.
   Отодвигаем весь заголовок (кнопка + текст) от левой группы. */
/* FR-W28: 0.9rem всё равно оказалось мало — на телефоне «»» и «←» читаются как
   одна кнопка (пользователь: «опять стрелочка слишком близко… надо на всех
   экранах адекватное расстояние между стрелками»). Разводим на 1.7rem и даём
   «назад» полноценный тап-таргет 2.4rem, а не 15px-глиф с padding 0.3rem. */
.header-title { pointer-events: auto; flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; gap: 0.8rem; overflow: hidden;
  margin-left: 1.7rem; }
.header-title .link-back.icon-only { width: 2.4rem; height: 2.4rem; padding: 0;
  flex-shrink: 0; display: inline-flex; align-items: center;
  justify-content: center; min-width: 2.4rem; min-height: 2.4rem; }
/* FR-UXI-66 (владелец 2026-09-01: «название процесса… в одну строчку движущийся
   строкой»): многоточие снято — длинное название едет бегущей строкой
   (.hdr-marquee + fitHeaderTitle() в app.js), короткое стоит на месте. */
.header-title .hdr-title-text { font-size: clamp(1.05rem, 1.5vw, 1.5rem);
  font-weight: 800; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--heading); white-space: nowrap; overflow: hidden;
  min-width: 0; flex: 0 1 auto; }
/* FR-W28: без flex-shrink:0 левая группа (лого + ») ужималась под длинный
   заголовок, её содержимое ВЫЛЕЗАЛО за свою коробку — и замеренный зазор до
   стрелки «назад» падал с 35px до 12px (реальный рендер страницы процесса). */
.header-left { pointer-events: auto; display: flex; align-items: center;
  gap: 0.5rem; min-width: 0; flex-shrink: 0; }
.header-right { pointer-events: auto; display: flex; align-items: center; gap: 0.5rem; flex-shrink: 0;
  margin-left: auto; }  /* всегда справа, даже когда header-left скрыт при открытом сайдбаре */
/* FR-W53: текстовый переключатель RU | EN — визуальный канон главной
   (FR-SITE10 сайта): не кнопки, просто текст; активный язык белый, второй
   серый. В кабинете (mode-app) скрыт — кабинет пока только по-русски. */
.lang-switch { display: flex; align-items: center; gap: 0.3rem;
  margin-right: clamp(0.4rem, 2vw, 1rem); flex-shrink: 0; }
.lang-opt { background: none; border: 0; padding: 0.2rem 0.05rem; cursor: pointer;
  font-family: inherit; font-size: 14px; font-weight: 500; letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.45); transition: color 0.3s ease; }
.lang-opt.active { color: #ffffff; font-weight: 700; }
@media (hover: hover) { .lang-opt:hover { color: #ffffff; } }
.lang-sep { color: rgba(255, 255, 255, 0.25); font-size: 13px; user-select: none; }
/* FR-AUTH1d: владелец 2026-08-25 — «RU / EN побольше сделать» (было 11/12px,
   на широком мониторе переключатель терялся в углу) */
@media (min-width: 1024px) { .lang-opt { font-size: 16px; } .lang-sep { font-size: 15px; } }
body.mode-app .lang-switch { display: none; }
/* FR-W56b ред. 2: строка RU | EN в меню профиля — тот же .lang-opt (setLang
   сам подсвечивает active по классу), но цвета от токенов кабинета: шапочные
   rgba(255,255,255,…) на светлой теме кабинета были бы невидимы.
   Ред. 2 (владелец 2026-08-29, «второй язык не видно»): цвет НЕактивного
   языка брался из `--muted`, а такого токена в проекте НЕТ — CSS падал в
   фолбэк rgba(255,255,255,0.45), то есть белый по белому фону светлой темы
   кабинета: контраст 1:1, переключиться было физически некуда. Приглушённый
   тон в этом проекте зовётся `--dim` (#94a3b8 тёмная / #475569 светлая,
   NFR-UXI-48). */
.side-menu-lang { display: flex; align-items: center; gap: 0.4rem;
  justify-content: center; /* FR-W56b ред. 2: язык — снизу ПО ЦЕНТРУ */
  padding: 0.55rem 0.9rem; border-top: 1px solid var(--border); }
.side-menu-lang i { font-size: 12px; color: var(--dim); }
.side-menu-lang .lang-opt { color: var(--dim); font-size: 13px; }
.side-menu-lang .lang-opt.active { color: var(--text); font-weight: 700; }
.side-menu-lang .lang-sep { color: var(--dim); opacity: 0.45; }

/* FR-CAB-LK5: кнопки кабинета (тема · поделиться · дорожная карта) в верхней
   строке с лого, справа. На узких экранах у «Дорожной карты» прячем подпись. */
.header-cab-actions { display: flex; align-items: center; gap: 0.5rem; }
/* FR-UXI-167 (владелец 2026-09-07: «на компе у кнопок тоже не должно быть
   текста — просто кнопки, а текстом типсами показать»): подписи `.rl-txt`
   в шапке спрятаны НА ВСЕХ ширинах, кнопки — круглые иконки того же
   размера, что соседние `.ctrl-round`; имя действия живёт в aria-label и в
   подсказке data-hint (FR-UXI-143 ред. 4). Правила ≤640px и 1024–1439px
   ниже оставлены как были — их пинят тесты батчей 3–4, поведение они
   теперь не меняют. Разрядка .btn-white (0.15em) у одной иконки сдвигала
   бы её от центра — снята. */
.header-cab-actions .rl-btn { padding: 0; width: 2.6rem; height: 2.6rem;
  border-radius: 999px; gap: 0; letter-spacing: 0; font-size: 15px; }
.header-cab-actions .rl-txt { display: none; }
@media (max-width: 640px) {
  .header-cab-actions .rl-txt { display: none; }
  .header-cab-actions .rl-btn { padding: 0; width: 2.6rem; height: 2.6rem;
    border-radius: 999px; gap: 0; }
}
/* FR-W59: с кнопкой «Скачать ИИ-стратегию» в ряду стало ЧЕТЫРЕ кнопки —
   на 360px ряд вылезал за паддинг шапки на 4px и прыгал при открытии
   сайдбара (замер mobile_sidebar_check). На сверхузких ужимаем кнопки и
   зазор — ряд помещается, ничего не ездит. */
@media (max-width: 380px) {
  .header-cab-actions { gap: 0.25rem; }
  .header-cab-actions .rl-btn,
  .header-cab-actions .ctrl-round { width: 2.35rem; height: 2.35rem; }
}
/* FR-W50m: на узких экранах три круглые кнопки процесса оставляли названию
   74 px из 390 («Р…») — действия сворачиваются в одно kebab-меню, названию
   возвращается читаемая ширина. На широких — прежний ряд кнопок. */
.proc-acts-wide { display: flex; align-items: center; gap: 0.5rem; }
.proc-acts-narrow { display: none; position: relative; }
@media (max-width: 640px) {
  .proc-acts-wide { display: none; }
  .proc-acts-narrow { display: block; }
}
.proc-menu { position: absolute; right: 0; top: calc(100% + 0.5rem);
  min-width: 13rem; background: var(--surface); border: 1px solid var(--border);
  border-radius: 0.9rem; padding: 0.35rem; z-index: 60; }
.proc-menu-item { display: flex; align-items: center; gap: 0.6rem; width: 100%;
  padding: 0.7rem 0.9rem; min-height: 44px; background: none; border: 0;
  border-radius: 0.6rem; color: var(--heading); font: inherit; font-size: 13px;
  text-align: left; cursor: pointer; }
@media (hover: hover) { .proc-menu-item:hover { background: var(--ctrl-bg); } }
.logo-btn { cursor: pointer; flex-shrink: 0; }
/* FR-W20c v2: лого — block: инлайновый <img> добавлял под собой baseline-зазор
   (~3-5px), из-за чего строка шапки с лого была ЧУТЬ выше строки без него —
   заголовок «дышал» по вертикали при сворачивании сайдбара */
.logo-img { display: block; }
.logo-img { width: clamp(2.85rem, 12vw, 3.7rem); height: clamp(2.85rem, 12vw, 3.7rem);
  object-fit: contain; }
@media (min-width: 1024px) { .logo-img { width: 3.6rem; height: 3.6rem; } }

/* ===== Спикер-бейдж поверх видео — позиция главной ===== */
/* +5px воздуха между бейджем и контентом панели («Стратегия и управление») */
.speaker { position: fixed; left: 50%; top: calc(60dvh - 5px); transform: translate(-50%, -100%); z-index: 30;
  display: flex; align-items: center; gap: 0.4rem; background: rgba(0,0,0,0.45);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); border: 1px solid rgba(255,255,255,0.10);
  color: #fff; padding: 0.3rem 0.3rem 0.3rem 0.65rem; border-radius: 999px;
  white-space: nowrap; pointer-events: auto; }
@media (min-width: 1024px) {
  .speaker { left: 29%; top: auto; bottom: 8%; transform: translateX(-50%);
    padding: 0.375rem 0.375rem 0.375rem 0.9rem; gap: 0.6rem; }
}
/* мобайл: бейдж не нужен — голова в кружке (FR-W13) */
@media (max-width: 1023px) { .speaker { display: none; } }
.speaker-inner { display: flex; align-items: center; gap: 0.5rem; }
/* FR-W18b: размеры бейджа — В REM, чтобы на широком мониторе они росли вместе
   с корневым шрифтом (18.4/20.8/24px), как на andre.technology, где то же
   укрупнение ×1.15/×1.3/×1.5 задаётся свойством zoom на body. Жалоба владельца по
   живому скрину: «шрифт маленький: на втором скрине норм». clamp с ПОЛОМ в px
   гарантирует, что мельче нынешнего не станет нигде (в т.ч. на низких окнах,
   где FR-W19b ужимает корневой шрифт до 14.5/12.5px). */
.speaker h3 { margin: 0; font-size: calc(13px * var(--ui-scale)); font-weight: 700; line-height: 1;
  white-space: nowrap; }
.speaker-emoji { font-size: calc(15px * var(--ui-scale)); line-height: 1; }
.speaker .sep { color: rgba(255,255,255,0.3); font-size: calc(13px * var(--ui-scale)); line-height: 1; }
.speaker .role { margin: 0; font-size: calc(13px * var(--ui-scale)); color: rgba(255,255,255,0.8);
  text-transform: uppercase; letter-spacing: 0.08em; line-height: 1; white-space: nowrap; }
.mic-btn { width: 2rem; height: 2rem; border-radius: 999px; background: #000; border: 1px solid rgba(255,255,255,0.05);
  color: #fff; display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0;
  padding: 0; }
@media (min-width: 1024px) { .mic-btn { width: 2.25rem; height: 2.25rem; } }
@media (hover: hover) { .mic-btn:hover { background: #111; } }
.mic-inner { position: relative; display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; }
.mic-inner i { font-size: 11px; color: rgba(255,255,255,0.55); }
.mic-wave { position: absolute; inset: 0; }
.mic-wave::before, .mic-wave::after { content: ''; position: absolute; inset: 0; border-radius: 50%;
  border: 1px solid var(--purple); animation: soundWave 2s infinite cubic-bezier(0.4,0,0.2,1); }
.mic-wave::after { animation-delay: 1s; }

/* ===== Субтитры озвучки — стиль главной (FR-W11) ===== */
/* титры как на главной: по центру сайта, по вертикали — на середине кружка (FR-W13) */
.caption { position: fixed; left: 50%; right: auto; top: auto; transform: translate(-50%, 50%);
  bottom: calc(clamp(1.5rem, 5vh, 3rem) + clamp(70px, 11vw, 140px));
  width: max-content; max-width: 92vw;
  white-space: normal; text-align: center; z-index: 41; pointer-events: none; }
@media (max-width: 768px) {
  /* кружок 150px при 15px от края → его середина на 90px от низа */
  .caption { bottom: calc(90px + env(safe-area-inset-bottom, 0px)); }
}
@media (min-width: 1024px) {
  .caption { left: 29%; right: auto; top: auto; bottom: calc(8% + 3.9rem); transform: translateX(-50%);
    white-space: nowrap; text-align: center; z-index: 29; }
}
/* FR-W18b: субтитры тоже в rem — на широком мониторе они читаются так же,
   как на andre.technology (там 15px × zoom 1.15/1.3/1.5) */
.caption span { color: rgba(229,231,235,0.52); font-size: calc(15px * var(--ui-scale));
  font-weight: 500; line-height: 1.4; letter-spacing: 0.02em; }
body.mode-app .caption { display: none; }

/* ===== Кнопки — стиль главной ===== */
.btn-white { background: var(--btn-bg); color: var(--btn-fg); border: 1px solid rgba(255,255,255,0.1); border-radius: 999px;
  font-weight: 700; text-transform: uppercase; display: inline-flex; align-items: center; justify-content: center;
  gap: 0.6rem; cursor: pointer; transition: all 0.3s ease; white-space: nowrap; }
@media (hover: hover) {
  .btn-white:hover { background: linear-gradient(100deg, var(--purple) 0%, var(--orange) 50%, var(--purple) 100%);
    background-size: 250% 250%; color: #fff; border-color: transparent;
    transform: translateY(-2px);
    animation: gradientShimmer 4.5s ease infinite; }
}
.btn-white:disabled { opacity: 0.55; pointer-events: none; }
/* FR-W18b: подписи кнопок — в rem (в кабинете корень 16px, значения те же) */
.btn-white { padding: 0.72rem 1.35rem; font-size: calc(11.5px * var(--ui-scale));
  letter-spacing: 0.15em; }
.btn-white.big { padding: 1.05rem 2.1rem; font-size: calc(12px * var(--ui-scale));
  letter-spacing: 0.15em; gap: 0.75rem; }
.btn-white.alt { background: transparent; color: #fff; border-color: var(--border); }
.cta { padding: clamp(0.62rem, 2.2vw, 0.95rem) clamp(0.85rem, 3.2vw, 1.35rem);
  font-size: clamp(9px, 2.7vw, 12.5px); letter-spacing: clamp(0.06em, 0.4vw, 0.1em); gap: clamp(0.4rem, 1.2vw, 0.6rem); }
/* FR-W18b: кнопка шапки («Переход к ИИ-стратегии») — тоже в rem, иначе на
   широком мониторе она остаётся 11.5px, когда всё вокруг выросло.
   Фидбек владельца 2026-08-06: на КОМПЕ шрифт был МЕЛЬЧЕ, чем на мобиле
   (десктопные ступени 10/11/11.5px против мобильного потолка clamp 12.5px) —
   все десктопные кегли .cta подняты до 12.5px × --ui-scale (≥ мобильного). */
@media (min-width: 1024px) { .cta { padding: 0.72rem 1.35rem;
  font-size: calc(12.5px * var(--ui-scale)); letter-spacing: 0.15em; gap: 0.55rem; } }
/* FR-W66 (B16, аудит narrow/01-n-landing 320×568): «Переход к ИИ-стратегии» в
   шапке выезжал за правый край (правый край кнопки 321px при окне 320, край
   строки шапки — 302): на 320px разрядка clamp давала 0.9px на знак (≈20px на
   подпись), набивка 3.2vw и зазор 1.2vw. На сверхузком телефоне (≤360px)
   подпись остаётся, но кнопка компактнее: без разрядки, набивка 0.5/0.55rem,
   зазор до стрелки 0.3rem; зазоры строки шапки и левой группы тоже ужаты.
   Кегль (9px — прежний пол clamp) не трогаем. Кабинет не задет: там .cta
   скрыта (FR-W16d). */
@media (max-width: 360px) {
  .cta { padding: 0.5rem 0.55rem; letter-spacing: 0; gap: 0.3rem; }
  .header-row, .header-left { gap: 0.35rem; }
  /* RU | EN рядом с кнопкой — на кегль меньше и ближе к ней: запас строки
     нужен под Montserrat, который шире системного фолбэка на ~8 % */
  .lang-switch { margin-right: 0.25rem; }
  .lang-opt { font-size: 13px; }
}
.btn-ghost { background: transparent; border: 1px solid var(--border); border-radius: 999px; color: var(--dim);
  padding: 0.62rem 1.15rem; font-size: 12px; text-transform: uppercase; letter-spacing: 0.08em; cursor: pointer;
  display: inline-flex; align-items: center; gap: 0.5rem; transition: all 0.25s ease; }
@media (hover: hover) { .btn-ghost:hover { color: var(--heading); border-color: var(--purple); } }

/* ===== Layout: панель справа (как на главной) / широкий app-режим ===== */
.content-layer { position: fixed; inset: 0; z-index: 10; display: flex; flex-direction: column;
  pointer-events: none; justify-content: center; }
/* мобайл: тест по центру тёмного фона (FR-W13); голова — в кружке внизу слева */
.panel { width: 100%;
  height: 100vh; height: 100dvh;   /* NFR-FE8: vh-фолбэк */
  padding: calc(4.4rem + env(safe-area-inset-top, 0px)) 1rem calc(2.2rem + env(safe-area-inset-bottom, 0px));
  display: flex; flex-direction: column; justify-content: center; }
.scroll { display: flex; flex-direction: column; align-items: center; gap: 1rem; pointer-events: auto;
  scrollbar-width: none; max-height: 100%; justify-content: flex-start; padding: 0.5rem 0.2rem 0;
  overflow-y: auto; overflow-x: hidden; }
.scroll::-webkit-scrollbar { display: none; }
@media (min-width: 1024px) {
  .content-layer { justify-content: center; }
  .panel { width: 40%; height: auto;
    max-height: 100vh; max-height: 100dvh;   /* NFR-FE8: vh-фолбэк */
    margin-left: auto; padding: 0 2rem; display: block; }
  .scroll { max-height: calc(100vh - 11rem); max-height: calc(100dvh - 11rem);   /* NFR-FE8 */
    justify-content: flex-start; padding: 1.75rem 0.25rem; }
}
/* app-режим: широкий центрированный контент, ничего фиксированного слева */
body.mode-app .content-layer { justify-content: flex-start; }
body.mode-app .panel { width: 100%;
  height: 100vh; height: 100dvh;   /* NFR-FE8: vh-фолбэк */
  max-height: none; margin: 0 auto; max-width: 68rem;
  padding: calc(5.6rem + env(safe-area-inset-top, 0px)) 1.2rem 2rem; justify-content: flex-start; }
body.mode-app .scroll { max-height: 100%; height: 100%; justify-content: flex-start; padding-bottom: 2.2rem; }
/* app-экран растягивается на весь вьюпорт — композер кабинета прижимается
   к низу экрана (margin-top: auto у #composer-slot-cab) с отступом снизу */
body.mode-app .screen.active { flex: 1 0 auto; }
/* десктоп: контент дашборда поднят к уровню лого, композер — почти у
   нижнего края экрана с небольшим отступом (FR-W14) */
@media (min-width: 1024px) {
  /* FR-CAB-LK5/FR-W12: в шапке кнопки кабинета (share/settings) — шапка на
     десктопе ~106px. Запас сверху ДОЛЖЕН перекрывать её (панель 7rem + .scroll
     0.5rem = ~120px), иначе название компании заезжает ПОД шапку и обрезается
     сверху (замер: при 5.4rem заголовок top=94px < низ шапки 106px → срез 11px). */
  body.mode-app .panel { padding-top: calc(7rem + env(safe-area-inset-top, 0px));
    padding-bottom: 0.6rem; }
  body.mode-app .scroll { padding-top: 0.5rem; padding-bottom: 0.4rem; }
  /* ползунок прокрутки ПРИЖАТ к правой границе экрана (FR-PRC8): панель
     распахивается на всю ширину без боковых полей, а контент каждого
     экрана сам ограничивается прежними 68rem по центру */
  body.mode-app .panel { max-width: none;
    padding-left: 0; padding-right: 0; }
  body.mode-app .scroll { width: 100%; }
  body.mode-app .scroll > .screen { width: 100%; max-width: 68rem;
    margin-left: auto; margin-right: auto;
    padding-left: 1.2rem; padding-right: 1.2rem; }
  /* композер кабинета ВСЕГДА виден и на десктопе: липнет к низу зоны
     прокрутки, длинная лента уезжает под него (FR-PRC8); фон — мягкий
     градиент в цвет страницы, никакой чёрной плашки над строкой ввода */
  body.mode-app #composer-slot-cab { position: sticky; bottom: 0; z-index: 20;
    background: var(--bg);
    padding-top: 0.9rem; padding-bottom: 2.4rem; }
}
/* FR-W12 (десктоп): app-режим листается НАТИВНО всей страницей. Композер — В
   ПОТОКЕ (position:sticky bottom:0 + margin-top:auto), НЕ fixed: при коротком
   контенте он внизу вьюпорта, при длинном — липнет к низу при прокрутке и
   САДИТСЯ В КОНЕЦ документа, поэтому лента НИКОГДА не обрезается снизу. Слот
   лежит внутри центрированной 68rem-колонки экрана → сам выравнивается по
   контенту (ручные left/right убраны — из-за них бар и «улетал»). */
@media (min-width: 1024px) {
  body.mode-app .content-layer { position: static; display: block; }
  body.mode-app.side-open .content-layer { margin-left: 280px; }
  /* КРИТ (FR-W12): panel — flex-КОЛОНКА на всю высоту вьюпорта. Базовое правило
     .panel на ≥1024px = display:block (правая панель лендинга), и без явного
     возврата flex здесь вся цепочка margin-top:auto ломалась: при КОРОТКОМ
     контенте (экран интервью) композер садился сразу под контентом, а не у
     низа экрана — «бар улетал наверх», под ним зияла пустота. flex-колонка +
     min-height:100dvh + растущий .scroll снова прижимают композер к низу. */
  body.mode-app .panel { display: flex; flex-direction: column;
    height: auto;
    min-height: 100vh; min-height: 100dvh;   /* NFR-FE8: vh-фолбэк */
    padding-bottom: 0; }
  body.mode-app .scroll { max-height: none; height: auto; overflow: visible; flex: 1 1 auto; }
  body.mode-app #composer-slot-cab { position: sticky; bottom: 0; margin-top: auto;
    z-index: 25; background: linear-gradient(to top, rgba(0,0,0,1) 62%, rgba(0,0,0,0) 100%);
    padding: 1.8rem 0 1.2rem; max-width: none; }  /* фейд к краю, без жёсткой границы снизу */
  body.mode-app #composer-slot-cab .composer,
  body.mode-app #composer-slot-cab .form-error,
  body.mode-app #composer-slot-cab .composer-status {
    max-width: 46rem; margin-left: auto; margin-right: auto; }
  /* FR-W21 (сменило FR-W12 «без фона»): у шапки app-режима лёгкая
     ПОЛУПРОЗРАЧНАЯ подложка с фейдом в ноль (базовое правило выше) — контент
     просвечивает и не «обрубается» (старая боль FR-W12 была от СПЛОШНОГО
     градиента var(--bg) 80%), а заголовок и кнопки читаются при прокрутке. */
}
/* FR-W12 (низ = как верх): гарантированный зазор ПОД контентом, чтобы последняя
   карточка/сообщение НИКОГДА не уходили под липкий композер и его фейд. Композер
   — последний ребёнок .scroll (sticky bottom); при высоком контенте карточка
   могла упираться в его прозрачный верх и «затухать» снизу. Даём контенту явный
   отступ снизу — карточка всегда ПОЛНОСТЬЮ видна над композером (симметрично
   тому, как сверху лента листается до края под прозрачной шапкой). */
body.mode-app #cab-processes,
body.mode-app #cab-log { margin-bottom: 2.4rem; }
/* FR-W62 (свежие глаза #17): при живых процессах renderCabinet переносит
   «Обучение» ПОД сетку процессов (FR-W59) — и тогда последним в ленте стоит
   уже #cab-courses, а не #cab-processes; без своего резерва последняя
   карточка курса уходила под липкий композер и его фейд на десктопе. */
body.mode-app #cab-courses { margin-bottom: 2.4rem; }

/* видимый ползунок прокрутки в app-режиме: юзер видит, что контент
   продолжается ниже (FR-PRC8) */
body.mode-app .scroll { scrollbar-width: thin;
  scrollbar-color: var(--border) transparent; }
body.mode-app .scroll::-webkit-scrollbar { display: block; width: 8px; }
body.mode-app .scroll::-webkit-scrollbar-track { background: transparent; }
body.mode-app .scroll::-webkit-scrollbar-thumb { background: var(--border);
  border-radius: 999px; }@media (hover: hover) { body.mode-app .scroll::-webkit-scrollbar-thumb:hover { background: var(--dim); } }
/* мобайл/планшет: контент в потоке документа — страница скроллится нативно,
   низ никогда не обрезается, даже во встроенных браузерах (Telegram и т.п.),
   где 100dvh больше видимой области (FR-W12) */
@media (max-width: 1023px) {
  .content-layer, body.mode-app .content-layer { position: static; display: block; }
  .panel, body.mode-app .panel { height: auto;
    min-height: 100vh; min-height: 100dvh; min-height: 100svh;
    position: relative; z-index: 10; /* контент поверх зерна, как на десктопе */ }
  /* КРИТИЧНО (FR-W12, «раз и навсегда»): на мобилке .scroll НЕ должен быть
     скролл-контейнером НИ В ОДНОМ режиме (ни app, ни диагностика-hero). Тонкость
     CSS: overflow-y:visible ПРИ overflow-x:hidden вычисляется браузером как
     overflow-y:auto → .scroll превращался в клиппящий бокс фикс.высоты и резал
     тест сверху/снизу на невысоких экранах. Ставим overflow:visible ПО ОБЕИМ
     осям (горизонтальный скролл и так режет body{overflow-x:hidden}) —
     страница листается нативно, ничего не обрезается. */
  .scroll, body.mode-app .scroll { max-height: none; overflow: visible; }
  /* нижний отступ панели резервирует зону кружка: контент (включая кнопки
     теста) центрируется НАД кружком и никогда им не перекрывается (FR-W13) */
  .panel { padding-bottom: calc(clamp(1.5rem, 5vh, 3rem) + clamp(140px, 22vw, 280px)
    + 0.75rem + env(safe-area-inset-bottom, 0px)); }
  /* FR-W24 (мобилка): композер ЖЁСТКО ПРИБИТ к низу вьюпорта (fixed) —
     пользователь: «чат ввода пляшет то вверх, то вниз — он всегда должен быть
     внизу статичен». Sticky-в-потоке прыгал при дорастании ленты и схлопывании
     адресной строки. Панель резервирует место под композер снизу, чтобы
     последняя карточка не пряталась под ним. Фейд — как на десктопе. */
  /* FR-W27b: резерв под фикс-композер нужен ТОЛЬКО там, где композер есть —
     это кабинет (лента сборки) и аудит отдела. На экранах процесса и дорожной
     карты композера нет, а 8.5rem пустоты внизу оставались (пользователь:
     «смотри какое огромное расстояние — надо меньше намного»). */
  body.mode-app .panel { padding-bottom: calc(1.6rem + env(safe-area-inset-bottom, 0px)); }
  /* FR-W30: резерв = ФАКТИЧЕСКАЯ высота композера (--cmp ставит JS
     syncComposerReserve: расстояние от верха строки ввода до низа вьюпорта,
     safe-area и клавиатура уже внутри) + маленький зазор. Фиксированные 8.5rem
     были заметно больше композера, и между концом карточки и строкой ввода
     зияла пустота (пользователь: «на всех формах расстояние больше между
     концом и чатом»). 8.5rem остаётся фолбэком до первого замера. */
  body.mode-app .panel[data-screen-active="cabinet"],
  body.mode-app .panel[data-screen-active="department"] {
    padding-bottom: calc(var(--cmp, 8.5rem) + 0.4rem); }
  /* FR-W30: под лентой стояли ТРИ отступа подряд — margin-bottom #cab-log
     (2.4rem), padding-bottom .scroll (2.2rem) и резерв панели: между кнопкой
     «Выйти» и строкой ввода набегало ~88px пустоты (замер реального рендера).
     Воздух оставляем только в резерве панели. */
  body.mode-app .scroll { flex: 1 1 auto; padding-bottom: 0.4rem; }
  body.mode-app #cab-log { margin-bottom: 0.4rem; }
  body.mode-app #composer-slot-cab { position: fixed; left: 0; right: 0;
    /* FR-W24b: --kb = высота экранной клавиатуры (ставит JS syncKeyboardInset);
       без клавиатуры 0 → композер прибит к низу как раньше (FR-W24), с
       клавиатурой поднимается ровно над ней и не перекрывается */
    bottom: var(--kb, 0px);
    margin: 0; z-index: 25; max-width: none;
    background: linear-gradient(to top, rgba(0,0,0,1) 62%, rgba(0,0,0,0) 100%);
    padding: 1.8rem 0.9rem calc(1rem + env(safe-area-inset-bottom, 0px)); }  /* фейд к краю */
  body.mode-app #composer-slot-cab .composer,
  body.mode-app #composer-slot-cab .form-error,
  body.mode-app #composer-slot-cab .composer-status {
    max-width: 46rem; margin-left: auto; margin-right: auto; }
  /* на диагностике (hero) шапка притеняет видео градиентом; в app-режиме
     работает полупрозрачная подложка FR-W21 (базовое правило) — контент
     просвечивает, заголовок читается, ничего не «обрубается» */
  header { background: linear-gradient(rgba(0,0,0,1) 72%, rgba(0,0,0,0) 100%); }
}
@media (max-width: 768px) {
  .panel { padding-bottom: calc(15px + 150px + 0.75rem + env(safe-area-inset-bottom, 0px)); }
  /* На тесте (quiz) резерв «зоны кружка» задаётся в блоке ≤1023px ниже
     (.panel[data-screen-active="quiz"]) — его clamp-расчёт с запасом покрывает
     и фикс-кружок 150px на телефонах, поэтому отдельный ≤768px-override для
     теста не нужен (он бы всё равно проиграл по порядку каскада правилу
     ≤1023px, идущему позже). */
}

.panel.leaving { opacity: 0; transform: translateY(-26px); transition: opacity 0.22s ease, transform 0.22s ease; }
.panel.entering { animation: slideInPanel 0.5s cubic-bezier(0.22, 1, 0.36, 1); }
/* app-режим: панель НЕ анимируется (FR-PRC8) — transform на предке ломает
   position:fixed у кнопок шапки (они «прыгали» вправо после анимации) */
body.mode-app .panel.entering { animation: none; }
body.mode-app .panel.leaving { transition: none; transform: none; opacity: 1; }

.screen { display: none; flex-direction: column; align-items: center; width: 100%;
  max-width: 36rem; text-align: center; gap: 1.05rem; }
.screen.active { display: flex; }
@media (min-width: 1024px) { .screen { max-width: 32rem; gap: 1.2rem; } }
.screen.wide { max-width: 62rem; text-align: left; align-items: stretch; }
/* FR-W12 (низ, «как сверху»): экраны БЕЗ нижнего композера (страница процесса,
   дорожная карта, результат) должны иметь ЗАПАС снизу — иначе последний блок
   (агенты, кнопка «Разработать», волна карты) «обрубается» у нижнего края,
   особенно на телефонах с жестовой зоной. Композер-экраны (кабинет/аудит) сами
   резервируют низ своим слотом, их не трогаем.
   FR-W12b: НЕ растягиваем эти экраны (flex:0 0 auto вместо 1 0 auto) — иначе при
   коротком контенте экран растёт до низа вьюпорта и под кнопкой «Разработать
   ИИ-агентов» зияет пустота в сотни px (замер: было 551px). Композер кабинета
   держится margin-top:auto и растяжку сохраняет, а этим экранам она не нужна. */
body.mode-app .screen.active[data-screen="process"],
body.mode-app .screen.active[data-screen="roadmap"],
body.mode-app .screen.active[data-screen="result"] {
  flex: 0 0 auto;
  padding-bottom: calc(2.4rem + env(safe-area-inset-bottom, 0px)); }

/* ===== Лендинг «ИИ-диагностика бизнеса» (FR-W8) ===== */
.overview-aura { position: absolute; top: 30%; left: 50%; transform: translate(-50%,-50%);
  width: min(85%, 32rem); height: 15rem; z-index: -1; pointer-events: none;
  background: radial-gradient(closest-side, rgba(136,84,243,0.4), rgba(249,115,22,0.14), transparent 72%);
  filter: blur(34px); animation: auraPulse 5.5s ease-in-out infinite; }
.hero-size { font-size: clamp(1.5rem, 8.6vw, 2.6rem); margin: 0; font-weight: 800; text-transform: uppercase;
  letter-spacing: -0.02em; line-height: 1.12; color: var(--heading); animation: floatSlow 6s ease-in-out infinite;
  position: relative; z-index: 1; }
@media (min-width: 1024px) { .hero-size { font-size: clamp(1.7rem, 3.2vw, 2.8rem); } }
.hero-size .line { display: block; white-space: nowrap; }
.a1 { color: var(--purple-l); }
.a2 { color: var(--orange-l); }

.points-list { list-style: none; margin: 0; padding: 0; width: 100%; max-width: 24rem;
  display: flex; flex-direction: column; text-align: left; }
.points-list li { display: flex; align-items: center; gap: 1rem; padding: 0.6rem 0.15rem;
  border-top: 1px solid rgba(255,255,255,0.10); white-space: nowrap; }
.points-list li:first-child { border-top: 0; }
/* FR-W18b: 7 пунктов диагностики — в rem: на широком мониторе список читается
   как на andre.technology, а не «мелким шрифтом» (жалоба по живому скрину) */
.points-list b { color: var(--purple-l); font-weight: 800;
  font-size: clamp(12.5px, 0.78125rem, 18.75px); letter-spacing: 0.08em; flex-shrink: 0;
  /* FR-W67 (B16): цифры «01…07» моноширинные — левый край названий ровный
     при любом шрифте (без tabular-nums «1» уже «0», и колонка гуляет) */
  font-variant-numeric: tabular-nums; }
.points-list li:nth-child(even) b { color: var(--orange-l); }
.points-list span { font-size: clamp(13.5px, 0.84375rem, 20.25px); color: var(--body2);
  overflow: hidden; text-overflow: ellipsis; }
@media (min-width: 1024px) {
  .points-list { max-width: 27rem; }
  .points-list li { padding: 0.68rem 0.2rem; }
  .points-list b { font-size: clamp(12.5px, 0.9vw, 16px); }
  .points-list span { font-size: clamp(14px, 1vw, 18px); }
}
@media (max-width: 1023px) {
  .points-list li { padding: 0.5rem 0.1rem; }
  .points-list span { font-size: 12.5px; }
}

.h2-size { font-size: clamp(1.4rem, 5vw, 1.9rem); margin: 0; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--heading); }
@media (min-width: 1024px) { .h2-size { font-size: clamp(1.6rem, 1.9vw, 2.4rem); } }
/* FR-W16d: заголовок экрана входа — ВСЕГДА в одну строку (моно-шрифт
   uppercase переносил первое слово на отдельную строку). Кегль здесь —
   лишь БАЗА для замера: фактический ставит `fitAuthHeading` в app.js,
   подгоняя строку под ширину кнопки (FR-AUTH1d). */
[data-screen="auth"] .h2-size { font-size: clamp(1.4rem, 6.8vw, 2.3rem); }
[data-screen="auth"] .h2-size .line { display: block; white-space: nowrap; }
@media (min-width: 1024px) { [data-screen="auth"] .h2-size { font-size: clamp(1.6rem, 2.6vw, 2.5rem); } }
.desc { margin: 0; font-size: 14.5px; line-height: 1.6; color: var(--body2); max-width: 30rem; }
@media (min-width: 1024px) { .desc { font-size: clamp(15px, 1.05vw, 21px); max-width: 34rem; } }
.desc.left { text-align: left; max-width: none; }

/* ===== Формы ===== */
.form { display: flex; flex-direction: column; gap: 0.75rem; width: 100%; max-width: 24rem; }
.form.inline { flex-direction: row; max-width: none; margin-top: 1rem; }
.form.inline .input { flex: 1; }
.input { width: 100%; background: var(--input-bg); border: 1px solid rgba(255,255,255,0.14); border-radius: 0.75rem;
  color: var(--text); font-family: inherit; font-size: 13.5px; padding: 0.9rem 1.05rem; transition: border-color 0.25s ease; }
.input::placeholder { color: rgba(229,231,235,0.4); }
.input:focus { outline: none; border-color: var(--purple); }
/* FR-W19: на десктопе поля формы («Название компании»/«Ваше имя», вход) были
   мелкими (13.5px на любом мониторе) — растим кегль и внутренние отступы. */
@media (min-width: 1024px) { .input { font-size: clamp(14px, 0.95vw, 17px); padding: 1rem 1.15rem; } }
.textarea { resize: vertical; min-height: 8rem; line-height: 1.6; }
.form-error { margin: 0; font-size: 11.5px; color: #f87171; text-align: left; }

/* ===== Тест — крупнее, в правой панели поверх видео ===== */
.quiz { max-width: 36rem; }
@media (min-width: 1024px) {
  .quiz { max-width: 34rem; }
  /* FR-W12b «раз и навсегда» ДЛЯ ДЕСКТОПА: тест не обрезается ничем, кроме краёв
     экрана. Раньше .scroll теста был внутренним боксом max-height:calc(100dvh -
     16rem) по центру вьюпорта → сверху и снизу оставались «мёртвые» поля ~8rem, и
     контент резался ВНУТРИ этих полей, а НЕ по краю экрана (юзер: «обрезается и
     сверху и снизу… только краями экрана, не надо вообще обрезок»). Теперь бокс
     теста = ВСЯ высота вьюпорта (панель на весь экран → центрирование
     .content-layer её уже не сжимает), контент прижат к верху с отступом под
     фикс-шапку, снизу — воздух. Помещается — виден целиком; не помещается —
     нативная прокрутка В САМОМ полноэкранном боксе, и линия отреза строго по краю
     экрана, без мёртвых полей. Хук — атрибут панели, а не :has() (нет в старых
     вебвью), поэтому вёрстка теста надёжна везде. */
  .panel[data-screen-active="quiz"] { height: 100vh; height: 100dvh;   /* NFR-FE8 */
    max-height: 100vh; max-height: 100dvh; }
  /* FR-W19 (десктоп): голова слева, панель теста справа — колонки НЕ
     пересекаются, поэтому центр по вертикали безопасен на любой высоте.
     `safe center`: помещается — тест по центру правой колонки (раньше вечно
     жался к верху с зиянием снизу); не помещается — деградирует в верхний
     якорь и нативно листается, ничего не режется по краям. */
  .panel[data-screen-active="quiz"] .scroll { height: 100vh; height: 100dvh;   /* NFR-FE8 */
    max-height: 100vh; max-height: 100dvh;
    justify-content: safe center; overflow-y: auto; padding: 6.25rem 0.25rem 1.5rem; }
}
.quiz-top { display: flex; justify-content: space-between; align-items: center; width: 100%; gap: 0.8rem; }
.quiz-cat { font-size: 12px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--purple-l); }
.quiz-progress { font-size: 12px; color: var(--dim); white-space: nowrap; }
@media (min-width: 1024px) { .quiz-cat, .quiz-progress { font-size: clamp(12px, 0.85vw, 15px); } }
/* #83: кнопки пропуска диагностики (.quiz-skip / #landing-skip) удалены —
   переход в стратегию теперь через кнопку «ИИ-стратегия» в шапке (header-cta). */
.progressbar { width: 100%; height: 6px; border-radius: 999px; background: var(--track); overflow: hidden; }
.progressbar-fill { height: 100%; border-radius: 999px; width: 0;
  background: linear-gradient(90deg, var(--purple), var(--orange)); transition: width 0.35s ease; }
/* FR-W48: банк вопросов шлёт двухстрочные заголовки с \n — pre-line рисует
   реальный перенос (textContent, не innerHTML); однострочные тексты без \n
   не меняются, повторные пробелы pre-line схлопывает — лишних зазоров нет.
   Вторая строка НЕ занижается — тот же кегль/вес, просто перенос. */
/* FR-W48 ред. 2 (владелец 2026-09-18: «форматирование не перестраивается,
   перестраивается только масштаб»): white-space: pre — строки заголовка
   ровно те, что задал банк (\n), и НИ ОДНА не переносится браузером.
   Если самая длинная строка не влезает в ширину, app.js (fitQuestion)
   уменьшает кегль — верстка одна, меняется масштаб. */
.quiz-question { margin: 0.2rem 0 0; font-size: clamp(1.1rem, 4vw, 1.45rem); font-weight: 700; color: var(--heading); line-height: 1.35; white-space: pre; max-width: 100%; }
@media (min-width: 1024px) { .quiz-question { font-size: clamp(1.2rem, 1.55vw, 1.8rem); } }
.quiz-options { display: flex; flex-direction: column; gap: 0.55rem; width: 100%; }
/* карточка ответа — как карточки главной: плитка-номер, ярлык в одну строку,
   описание не выше двух строк (FR-W12) */
.option-btn { display: flex; align-items: center; gap: 0.85rem; text-align: left; background: var(--surface);
  border: 1px solid var(--border); border-radius: 1rem; color: var(--text); font-family: inherit;
  padding: 0.85rem 1rem; min-height: 5rem; cursor: pointer;
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  transition: transform 0.3s ease, border-color 0.3s ease; }
@media (hover: hover) { .option-btn:hover { border-color: var(--purple); transform: translateY(-2px); } }
.option-btn.selected { border-color: var(--orange); background: rgba(249,115,22,0.10); }
.opt-num { width: 2.4rem; height: 2.4rem; flex-shrink: 0; border-radius: 0.75rem; display: flex;
  align-items: center; justify-content: center; font-size: 15px; font-weight: 800;
  background: rgba(136,84,243,0.2); color: var(--purple-l); }
.option-btn:nth-child(even) .opt-num { background: rgba(249,115,22,0.2); color: var(--orange); }
.option-btn.selected .opt-num { background: rgba(249,115,22,0.22); color: var(--orange); }
.opt-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.2rem; }
.opt-label { font-size: 13px; font-weight: 800; text-transform: uppercase; color: var(--heading); line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* FR-W17 ред. 2 (владелец 2026-09-18): все пять карточек ОДНОЙ высоты —
   коробка описания всегда ровно две строки (height: 2 × line-height), а
   текст в ней ПО ЦЕНТРУ: одна строка — посередине коробки, две — заполняют
   её. Внутренний <span> держит обрезку в две строки (line-clamp), сама
   коробка — flex-центровка; в em, поэтому правило одно на все брейкпоинты. */
.opt-desc { font-size: 11px; line-height: 1.35; color: var(--dim);
  display: flex; align-items: center; height: 2.7em; }
.opt-desc > span { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
@media (min-width: 1024px) {
  .option-btn { min-height: 5.6rem; }  /* все карточки одной высоты */
  .opt-label { font-size: clamp(13px, 0.95vw, 16px); }
  .opt-desc { font-size: clamp(11px, 0.8vw, 13.5px); }
}
/* карточки ответов — вертикальная колонка на всех разрешениях (FR-W12);
   на мобайле тест компактнее и помещается на экран целиком — ничего не
   обрезается; зону кружка резервирует нижний отступ панели (FR-W13) */
@media (max-width: 1023px) {
  .quiz { gap: 0.85rem; padding-bottom: 0.5rem; }
  .option-btn { min-height: 4.5rem; padding: 0.7rem 1rem; }
  /* КЛЮЧЕВОЕ (FR-W12/FR-W12b): когда открыт тест, контент выравнивается ПО
     ВЕРХУ, а не по центру — центрирование при контенте выше экрана обрезало и
     заголовок сверху, и кнопки «Назад»/«Не знаю» снизу. Страница листается
     нативно, кнопки навигации всегда достижимы; зазор под фикс-шапку (верх) и
     резерв «зоны кружка» (низ) — в самом правиле ниже. */
  .panel[data-screen-active="quiz"] { justify-content: flex-start;
    /* верх: гарантированный зазор под фикс-шапкой (высота ~4.9rem) — «Стратегия
       и управление / Вопрос N» больше НЕ прячется под кнопкой шапки (FR-W12).
       низ (FR-W12b, «раз и навсегда»): резервируем ЗОНУ КРУЖКА-ГОЛОВЫ — тот же
       расчёт, что у самого кружка (.scene ≤1023px: bottom clamp(1.5rem,5vh,3rem),
       height clamp(140px,22vw,280px)) + воздух + safe-area. Иначе при полной
       прокрутке длинного вопроса на невысоком экране кнопка «Назад» (левая
       кнопка навигации) ложилась ПОД фикс-кружок слева внизу и перекрывалась им.
       Резерв держит вариант 5 и обе кнопки «Назад»/«Не знаю» ВСЕГДА НАД кружком.
       Значение с запасом покрывает и фикс-кружок 150px на телефонах (≤768px). */
    padding-top: calc(5.2rem + env(safe-area-inset-top, 0px));
    padding-bottom: calc(clamp(1.5rem, 5vh, 3rem) + clamp(140px, 22vw, 280px) + 1rem + env(safe-area-inset-bottom, 0px)); }
}
/* невысокие экраны — ещё компактнее, чтобы тест влезал без прокрутки */
@media (max-width: 1023px) and (max-height: 780px) {
  .panel { padding-top: calc(3.4rem + env(safe-area-inset-top, 0px)); }
  body.mode-app .panel { padding-top: calc(4rem + env(safe-area-inset-top, 0px)); }
  .quiz { gap: 0.7rem; }
  .quiz-question { font-size: clamp(1rem, 3.6vw, 1.25rem); }
  .option-btn { min-height: 3.8rem; padding: 0.55rem 0.9rem; }
}
.quiz-nav { display: flex; justify-content: space-between; width: 100%; gap: 0.8rem; }
/* «Назад» и «Не знаю» — одного размера */
.quiz-nav .btn-ghost { flex: 1 1 0; max-width: 11rem; justify-content: center; }

/* FR-W19: ВЫСОКИЙ мобильный вьюпорт (планшет-портрет / высокое узкое окно) —
   вертикали с избытком, поэтому диагностика прижималась к верху, а снизу зияла
   пустота, и всё выглядело мелко («ужато»). Принцип: НАЛОЖЕНИЯ исключает
   РЕЗЕРВ «зоны кружка» (padding-bottom = место под фикс-кружок головы), а
   центрирование лишь распределяет СВОБОДНОЕ место — поэтому центр безопасен на
   любой высоте: есть запас — контент по центру, нет — деградирует в верхний
   якорь с нативной прокруткой (как на телефонах).
   (1) ЛЕНДИНГ/форма/результат: центр с 820px (контента мало, резерв меньше —
       проверено рендером, ниже 820 оставляем как на телефонах).
   (2) ТЕСТ с 1100px: КРУПНЕЕ (шрифты растут с высотой, vh-clamp) и ПО ЦЕНТРУ —
       резерв кружка при этом НЕ трогаем (в отличие от старого порога 1250 с
       обнулённым резервом), так что кнопки «Назад»/«Не знаю» физически не могут
       лечь на кружок ни на какой высоте.
   (3) ЛЕНДИНГ с 1100px: крупнее список категорий и CTA — экран не «ужат».
   Обычные телефоны (высота ≤800px) не затрагиваются вовсе. */
@media (max-width: 1023px) and (min-height: 820px) {
  /* (1) центрирование диагностики (НЕ теста — у него свой блок ниже) */
  .panel:not([data-screen-active="quiz"]) {
    justify-content: center;
    padding-bottom: calc(3rem + env(safe-area-inset-bottom, 0px));
  }
}
@media (max-width: 1023px) and (min-height: 1100px) {
  /* (2) тест — крупнее и по центру; резерв «зоны кружка» из базового правила
     .panel[data-screen-active="quiz"] сохраняется (наложение исключено) */
  .panel[data-screen-active="quiz"] { justify-content: center; }
  .quiz-question { font-size: clamp(1.5rem, 3.1vh, 2rem); }
  .quiz-cat, .quiz-progress { font-size: 14px; }
  .quiz-options { gap: 0.8rem; }
  .option-btn { min-height: 5.6rem; padding: 1.1rem 1.35rem; gap: 1.1rem; }
  .opt-num { width: 2.9rem; height: 2.9rem; font-size: 1.05rem; border-radius: 0.9rem; }
  .opt-label { font-size: clamp(1rem, 1.9vh, 1.2rem); }
  .opt-desc { font-size: clamp(0.9rem, 1.6vh, 1.05rem); }
  .quiz-nav .btn-ghost { font-size: 13px; padding: 0.85rem 1rem; max-width: 13rem; }
  /* форма (название компании / имя / вход) — тоже не мелкая на высоком экране */
  .input { font-size: clamp(15px, 1.7vh, 17px); padding: 1.05rem 1.2rem; }
  /* (3) лендинг — не «ужат»: список категорий шире/крупнее, CTA заметнее */
  .points-list { max-width: 30rem; }
  .points-list li { padding: 0.85rem 0.2rem; gap: 1.2rem; }
  .points-list b { font-size: 15px; }
  .points-list span { font-size: clamp(15px, 1.5vh, 17px); }
  .btn-white.big { font-size: 13.5px; padding: 1.2rem 2.5rem; }
}
/* FR-W19 (ДЕСКТОП, просторный монитор ≥900px высоты): на больших экранах всё
   выглядело «мелко» (тест 19px, поля 13.5px, список категорий 14px) — при том,
   что места по вертикали в избытке. Голова — в левой колонке, панель — в
   правой, между ними наложений нет, поэтому крупнее + по центру безопасно.
   Порог по ВЫСОТЕ (а не ширине): ноутбуки 768–864px не трогаем (там нет запаса
   и укрупнение вызвало бы прокрутку), мониторы 1080p+ — укрупняем.
   КРИТИЧНО (FR-W19a, «двойное укрупнение»): на ширинах ≥1600px укрупнение УЖЕ
   делает FR-W18 через root-шрифт (18.4/20.8/24px) — rem-значения этого блока
   перемножались с ним, тест распухал (вопрос 37px в 2 строки, карточки 129px)
   и НИЗ НАВИГАЦИИ РЕЗАЛСЯ на окнах ~1900×1100. Поэтому блок действует ТОЛЬКО
   при ширине <1600 (root там всегда 16px, rem-значения = как задуманы);
   на ≥1600 работает один FR-W18 — компактная раскладка в root-масштабе,
   которая гарантированно помещается (проверено рендером на 2000×1100). */
@media (min-width: 1024px) and (max-width: 1599px) and (min-height: 900px) {
  .quiz-question { font-size: clamp(1.6rem, 1.85vw, 2.3rem); }
  .quiz-cat, .quiz-progress { font-size: clamp(13px, 0.95vw, 16px); }
  .quiz-options { gap: 0.8rem; }
  .option-btn { min-height: 6.2rem; padding: 1.2rem 1.45rem; gap: 1.1rem; }
  .opt-num { width: 3rem; height: 3rem; font-size: 1.15rem; border-radius: 0.9rem; }
  .opt-label { font-size: clamp(15px, 1.15vw, 18px); }
  .opt-desc { font-size: clamp(13px, 0.95vw, 15px); }
  .quiz-nav .btn-ghost { font-size: clamp(12px, 0.85vw, 14px); padding: 0.95rem 1.1rem; }
  /* форма компании / вход — крупнее и шире */
  .input { font-size: clamp(15px, 1.05vw, 18px); padding: 1.1rem 1.25rem; }
  .form { max-width: 27rem; }
  /* лендинг — список категорий и CTA заметнее */
  .points-list { max-width: 30rem; }
  .points-list li { padding: 0.8rem 0.2rem; }
  .points-list b { font-size: clamp(13px, 0.95vw, 16px); }
  .points-list span { font-size: clamp(15px, 1.1vw, 18px); }
  .btn-white.big { font-size: 13px; padding: 1.15rem 2.4rem; }
}
/* FR-W19f: ОБРЫВ НА 1600px. Блок выше выключается на ≥1600 (там укрупняет
   root-лестница FR-W18), но кегли теста задавались vw-clamp'ами с потолком в
   ФИКСИРОВАННЫХ px (1.55vw/16px/13.5px/14px) — и эти потолки становились
   связывающим членом, ПРИЖИМАЯ текст. Итог был обратный задуманному: мак 14"
   (1512×1000) показывал вопрос 28px, а мак 16" (1728×1000) — 26.8px. Окно
   ШИРЕ, а текст МЕЛЬЧЕ; на самом стыке падало всё сразу (28→24.8, ярлык
   17.4→15.2). Замерено tools/quiz_fit_check.py, лестница монотонности.

   Принцип (тот же, что у витрины FR-W19d): РОСТ ЗАДАЁТ ШИРИНА (vw — он не
   перемножается с root-шрифтом, поэтому «двойного укрупнения» FR-W19a здесь
   быть не может), а ПОТОЛОК задаёт root-лестница в rem — она знает про
   низкое окно (FR-W19b ужимает root до 14.5/12.5) и сама придержит кегль,
   чтобы тест по-прежнему влезал целиком. Коробочные метрики (min-height
   карточек, паддинги) НЕ трогаем — именно их укрупнение на ≥1600 резало низ
   навигации, см. FR-W19a выше. */
@media (min-width: 1600px) {
  .quiz-question { font-size: clamp(1.3rem, 1.85vw, 1.9rem); }
  .quiz-cat, .quiz-progress { font-size: clamp(12px, 0.95vw, 1rem); }
  .opt-label { font-size: clamp(13px, 1.15vw, 1.1rem); }
  .opt-desc { font-size: clamp(11px, 0.95vw, 0.9rem); }
  .quiz-nav .btn-ghost { font-size: clamp(12px, 0.85vw, 0.78rem); }
}

/* ===== Результат ===== */
.result-ring { position: relative; width: 170px; height: 170px; }
.result-ring svg { width: 100%; height: 100%; }
.result-ring .ring-track { stroke: rgba(255,255,255,0.09); }
/* Аудит 2026-08-31: в светлой теме белый трек кольца растворялся в фоне —
   оранжевая дуга «висела в пустоте» */
html.light-cab .result-ring .ring-track { stroke: rgba(0,0,0,0.08); }
.result-ring .ring-center { position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; }
.result-ring .ring-value { font-size: 30px; font-weight: 800; color: var(--heading); }
/* #84: встроенного плеера ролика уровня больше нет — ролик показывается
   слева (hero-video), без чёрного леттербокса под уровнем зрелости */
.row-buttons { display: flex; gap: 0.7rem; flex-wrap: wrap; justify-content: center; }
/* фидбек владельца 2026-08-06: на результате «Полный отчёт» — заметная кнопка
   хорошего размера СРАЗУ ПОД CTA «Переход к ИИ-стратегии» (CTA главнее) */
.result-actions { flex-direction: column; align-items: center; gap: 0.8rem; }
/* FR-W13 ред. 2 (аудит 2026-08-31): на мобильном РЕЗУЛЬТАТЕ кнопки «Переход
   к ИИ-стратегии»/«Полный отчёт» не перекрываются кружком головы НИ В КАКОЙ
   точке прокрутки — панель резервирует зону кружка тем же расчётом, что квиз
   (FR-W12b п.3): отступ кружка + его высота + воздух + safe-area. Контент
   короче экрана центрируется НАД кружком; длиннее — в нижней точке прокрутки
   кнопки гарантированно выше кружка (сам он по-прежнему перетаскиваемый). */
@media (max-width: 1023px) {
  .panel[data-screen-active="result"] { padding-bottom:
    calc(clamp(1.5rem, 5vh, 3rem) + clamp(140px, 22vw, 280px) + 1rem +
         env(safe-area-inset-bottom, 0px)); }
  /* и сам кружок на результате — вдвое меньше и в самый угол: даже в
     верхней точке прокрутки он задевает разве что край кнопки, а не текст */
  body.on-result .scene { width: 104px; height: 104px; left: 8px;
    bottom: calc(8px + env(safe-area-inset-bottom, 0px)); }
  /* FR-W13 ред. 3 (B12, живой замер 390×853, 360×740 и 320×568): резерв
     панели спасает ТОЛЬКО нижнюю точку прокрутки. Замер сделан на экране с
     семью полосками категорий — он был выше вьюпорта, и в ВЕРХНЕЙ точке
     «Полный отчёт» проезжал ровно сквозь кружок: 1517 px² пересечения на
     390×853 и
     576 px² на 360×740 — левая часть подписи скрывалась под головой.
     Полоски сняты (FR-W58 ред. 3, 2026-09-09), но правила ниже ОСТАЮТСЯ:
     на 360/320px лента результата длиннее экрана и без них (замер
     result_head_check: запас прокрутки 17px и 204px), а на 390px кружок
     стоит вплотную к кнопкам — стоит вернуться любому блоку, и накрытие
     повторится.
     Отступом это не лечится в принципе: кружок закреплён у низа экрана, а
     кнопка проходит мимо него на какой-то позиции прокрутки ВСЕГДА.
     Поднять «ровно кнопки» тоже нельзя: `.panel` — `position: relative;
     z-index: 10`, то есть СОБСТВЕННЫЙ контекст наложения, и любой z-index
     внутри него остаётся под кружком (z-index 40) целиком. Поэтому кружок
     уходит ПОД слой контента. Чтобы он не потерял касание (замер 360×740:
     в своей точке его перехватывала `.scroll`), пустое место результата
     возвращается голове: лента и экран перестают ловить указатель. */
  body.on-result .scene { z-index: 5; }
  body.on-result .scroll,
  body.on-result .panel[data-screen-active="result"] .screen { pointer-events: none; }
  /* указатель ловят ТОЛЬКО кнопки — остальное на результате не кликается и
     не наводится (кольцо, уровень и абзац подсказок не
     несут), а на 320px кружок приходится ровно на полоски: оставь им
     `auto` — и голова снова перестаёт тащиться */
  body.on-result .result-actions { pointer-events: auto; }
  body.on-result .result-actions .btn-white.alt { background: var(--bg); }
}
/* FR-W63 (аудит Н-1, тот же механизм, что FR-W13 ред. 3 у результата): на
   320px кружок головы (150px, z-index 40) в какой-то точке прокрутки
   ВСЕГДА накрывает середину «Пройти тест» — тап уходил в <video>. Отступом
   это не лечится (кружок закреплён у низа экрана, кнопка едет мимо него).
   Поэтому на лендинге кружок уходит ПОД слой контента, а пустое место
   лендинга (лента и экран) перестаёт ловить указатель — голова там
   по-прежнему тащится и тапается; указатель ловят только кнопки и ссылки.
   Класс body.on-landing ставит applyMode рядом с on-result. Только телефон
   и планшет: на десктопе голова живёт в своей колонке и ничего не накрывает. */
@media (max-width: 1023px) {
  body.on-landing .scene { z-index: 5; }
  body.on-landing .scroll,
  body.on-landing .panel[data-screen-active="landing"] .screen { pointer-events: none; }
  body.on-landing .panel[data-screen-active="landing"] .screen button,
  body.on-landing .panel[data-screen-active="landing"] .screen a { pointer-events: auto; }
}
/* FR-W16f ред. 2 (B12): «ПОЛНЫЙ ОТЧЁТ» — nowrap-кнопка в 15rem, и на узком
   телефоне (320–360px) подпись выезжала за край панели и резалась. Ширина
   теперь уступает экрану: min() держит 15rem там, где место есть, а на
   узком — отдаёт кнопке всю доступную строку и ужимает боковые поля. */
.result-actions #result-report-link { min-width: min(15rem, 100%);
  max-width: 100%; justify-content: center; }
/* FR-W64 (аудит Н-2): «Переход к ИИ-стратегии» — nowrap-кнопка без предела
   ширины выезжала на 320px за правый край на 13px (текст срезался, прокрутки
   нет). Предел — ширина панели; на узком телефоне подпись может перенестись
   на вторую строку, но кнопка целиком остаётся в кадре. */
.result-actions .btn-white.big { max-width: 100%; }
@media (max-width: 400px) {
  .result-actions .btn-white.big { padding-left: 1.1rem; padding-right: 1.1rem;
    letter-spacing: 0.08em; white-space: normal; text-align: center;
    line-height: 1.35; }
}

/* ===== Кабинет / отдел (mode-app) ===== */
.cab-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
/* заголовок процесса — того же размера, что и название компании (FR-PRC8) */
.cab-head .h2-size { font-size: clamp(1.15rem, 1.6vw, 1.5rem); }
/* иконка «назад» ПЕРЕД заголовком процесса (FR-PRC16) */
.cab-head-left { display: flex; align-items: center; gap: 0.9rem; min-width: 0; }
/* FR-UXI-64 (владелец 2026-09-01: «стрелка назад везде побольше жирная»):
   единый класс стрелки возврата (.back-btn — алиас-контракт для соседних
   потоков): глиф fa-solid 20px/900, тап-цель 2.5rem, без кружка и фона,
   цвет --heading. Шапка ниже задаёт свою коробку 2.4rem, кегль тот же. */
.link-back.icon-only, .back-btn { font-size: 20px; font-weight: 900; padding: 0;
  min-width: 2.5rem; min-height: 2.5rem; display: inline-flex; align-items: center;
  justify-content: center; color: var(--heading); border: 0; background: transparent;
  border-radius: 0; cursor: pointer; }
.link-back.icon-only i, .back-btn i { margin: 0; font-weight: 900; }
/* «Назад» — просто ссылка, не кнопка (FR-PRC8) */
.link-back { border: 0; background: transparent; padding: 0; font-family: inherit;
  font-size: 13px; color: var(--dim); cursor: pointer; display: inline-flex;
  align-items: center; gap: 0.45rem; transition: color 0.2s ease; }@media (hover: hover) { .link-back:hover, .back-btn:hover { color: var(--heading); opacity: 0.8; } }

/* ===== Модалка подтверждения «да/нет» в стиле сайта (FR-PRC8) ===== */
.modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.55); z-index: 140;
  display: flex; align-items: center; justify-content: center; padding: 1.2rem; }
.modal-overlay[hidden] { display: none; }
.modal-card { background: var(--bg); border: 1px solid var(--border); border-radius: 1.1rem;
  padding: 1.6rem 1.8rem; width: min(24rem, 100%); }
.modal-text { margin: 0 0 1.2rem; font-size: 14.5px; line-height: 1.6; color: var(--text); }
.modal-actions { display: flex; gap: 0.7rem; justify-content: flex-end; }

/* ===== Тизер ИИ-стратегии (FR-W45/FR-W46): та же минималистичная карточка,
   что и confirm-модалка. Канон владельца (живой фидбек 2026-08-06):
   заголовок и текст — ПО ЦЕНТРУ; единая форма — почта на всю ширину,
   «Сообщить мне» ПОД полем; все три кнопки («Сообщить мне» / «Полный
   отчёт» / «Назад к тесту») — ОДНОГО размера, столбиком на всю ширину ===== */
.teaser-card { position: relative; width: min(26rem, 100%); text-align: center; }
.teaser-close { position: absolute; top: 0.8rem; right: 0.8rem; background: transparent;
  border: 0; color: var(--dim); font-size: 15px; cursor: pointer; padding: 0.35rem;
  transition: color 0.2s ease; }@media (hover: hover) { .teaser-close:hover { color: var(--heading); } }
.teaser-title { margin: 0 0 0.8rem; font-size: 1.05rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--heading);
  text-align: center; padding: 0 1.6rem; }  /* симметрия — крестик не сбивает центр */
.teaser-text { margin: 0 0 1.2rem; font-size: 13.5px; line-height: 1.6;
  color: var(--body2); text-align: center; }
.teaser-form { max-width: none; }
/* одна высота/типографика у ВСЕХ кнопок тизера (эталон — «Назад к тесту») */
.teaser-card .btn-white, .teaser-card .btn-ghost { width: 100%;
  box-sizing: border-box; justify-content: center; min-height: 2.9rem;
  padding: 0.72rem 1.2rem; font-size: calc(12px * var(--ui-scale));
  letter-spacing: 0.1em; gap: 0.55rem; }
.teaser-card .form-error { margin-top: 0.6rem; text-align: center; }
.teaser-thanks { margin: 0.2rem 0 0; font-size: 13.5px; line-height: 1.6;
  color: var(--text); text-align: center; }
.teaser-actions { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 1.1rem; }

.muted { color: var(--dim); font-size: 13px; }
.cab-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: 0.9rem; margin-top: 1rem; }
/* FR-UXI-61: карточка — графит --card без рамки/тени/подъёма; наведение —
   слой белой подсветки --hover поверх (цвет поверхности не меняется) */
.card { background: var(--card); border: 1px solid var(--card-border); border-radius: 1.1rem; padding: 1.2rem 1.3rem;
  transition: background-image 0.2s ease; }@media (hover: hover) { .card:hover { background-image: linear-gradient(var(--hover), var(--hover)); } }
.card h4 { margin: 0 0 0.5rem; font-size: 13px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--heading); }
/* эмодзи-плитка карточки — нейтральная подложка (FR-UXI-62: без цветных плашек) */
.card-head { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.9rem; }
.card-head h4 { margin: 0; }
.card-ico { width: 2.7rem; height: 2.7rem; flex-shrink: 0; border-radius: 0.75rem; display: flex;
  align-items: center; justify-content: center; font-size: 19px; }
.card .big-num { font-size: 2.1rem; font-weight: 800;
  background: linear-gradient(100deg, var(--purple-l), var(--orange-l));
  -webkit-background-clip: text; background-clip: text; color: transparent; }
.section-line { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  margin: 2rem 0 1rem; flex-wrap: wrap; }
.h3-line { margin: 0; font-size: 0.95rem; text-transform: uppercase; letter-spacing: 0.13em; color: var(--heading); }
.h-accent { color: var(--purple); margin-right: 0.35rem; }

.dept-card { background: var(--surface); border: 1px solid var(--border); border-radius: 1.1rem;
  padding: 1.1rem 1.25rem; margin-bottom: 0.8rem; }
.dept-card-top { display: flex; align-items: center; justify-content: space-between; gap: 0.9rem; flex-wrap: wrap; }
.dept-name { font-weight: 700; font-size: 14px; color: var(--heading); }
.dept-meta { font-size: 11px; color: var(--dim); margin-top: 0.25rem; }
.dept-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.invite-row { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.75rem; flex-wrap: wrap; }
.invite-input { flex: 1; min-width: 12rem; background: var(--input-bg); border: 1px dashed rgba(255,255,255,0.2);
  border-radius: 0.6rem; color: var(--dim); font-family: inherit; font-size: 11px; padding: 0.5rem 0.7rem; }

/* ===== Композер аудита процессов — как в ChatGPT (FR-PRC6) =====
   микрофон справа; при вводе текста он превращается в кнопку отправки;
   запись показывает живую волну и кнопки ✗ / ✓ */
/* кнопки прижаты к НИЗУ строки и не двигаются при росте текста;
   длинный текст скроллится ползунком внутри поля (как в ChatGPT) */
/* композер — В ТОН страницы (var(--bg)), а не более светлый серый: иначе
   вокруг серого поля был виден чёрный фон, тон не совпадал (FR-PRC6) */
/* FR-PRC6: композер — ОДИН ТОН с фоном страницы. Фон прозрачный (наследует
   тон страницы/липкого слота), поэтому «элемент ввода» никогда не отличается
   по цвету от фона — виден только тонкий контур-пилюля */
.composer { display: flex; align-items: flex-end; gap: 0.5rem; width: 100%;
  background: var(--bg); border: 1px solid var(--ctrl-border); border-radius: 1.6rem;
  padding: 0.4rem 0.4rem 0.4rem 1.1rem; transition: border-color 0.25s ease; }
.composer:focus-within { border-color: var(--purple); }
.composer.recording { border-color: var(--orange); }
.composer-input { flex: 1; background: transparent; border: 0; resize: none; color: var(--text);
  font-family: inherit; font-size: 14px; line-height: 1.55; padding: 0.55rem 0;
  min-height: 2.2rem; max-height: 11rem; overflow-y: auto; scrollbar-width: none;
  align-self: center; }
/* без видимой полоски-скроллбара в строке ввода (FR-PRC6e): при наборе поле само
   прокручивается к курсору — «полоска перемещения» больше не мозолит глаз */
.composer-input::-webkit-scrollbar { display: none; }
.composer-input::placeholder { color: var(--dim); }
.composer-input:focus { outline: none; }
/* строка ввода в кабинете — по центру, прижата к низу экрана (FR-W14);
   СТАТИЧНА: ошибка ложится в зарезервированную зону снизу абсолютом и
   не сдвигает элемент ввода (FR-PRC8) */
#composer-slot-cab { width: 100%; max-width: 46rem; margin: auto auto 0;
  padding-top: 2rem; position: relative; padding-bottom: 2.2rem; }
/* FR-PRC6d: сам элемент ввода СТАТИЧЕН — ошибка/статус ложатся в зону под ним
   абсолютом и НЕ поднимают композер (в обоих слотах — кабинет и аудит отдела).
   Зона снизу зарезервирована паддингом, чтобы текст ошибки был виден. */
#composer-slot-dept { position: relative; padding-top: 2.2rem; }
/* B5 (FR-PRC6d ред. 2, владелец 2026-09-03: «„готово! процесс собран из
   записи экрана“ и подобное — НАД полем ввода, строка ввода никогда не
   двигается»): сообщение ложится абсолютом в зону НАД строкой, по центру */
#composer-slot-cab .form-error, #composer-slot-cab .composer-status,
#composer-slot-dept .form-error, #composer-slot-dept .composer-status,
body.mode-app #composer-slot-cab .form-error,      /* сильнее «> * { position: relative }» */
body.mode-app #composer-slot-cab .composer-status {
  position: absolute; left: 1.1rem; right: 1.1rem; top: 0.15rem; bottom: auto;
  margin: 0; text-align: center; }
/* живая волна занимает всю ширину строки во время записи; min-width:0 + width
   не дают канвасу вылезти за пилюлю на узком экране (иначе волна за рамкой) */
.composer-wave { flex: 1 1 0; min-width: 0; width: 100%; height: 2.4rem;
  align-self: center; overflow: hidden; }
.composer-btn { width: 2.7rem; height: 2.7rem; border-radius: 999px; border: 0;
  display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 15px;
  transition: all 0.25s ease; padding: 0; flex-shrink: 0;
  user-select: none; -webkit-user-select: none; }
.composer-btn[hidden] { display: none; }
.composer-mic { background: var(--ctrl-bg); color: var(--dim); }
@media (hover: hover) { .composer-mic:hover { color: var(--heading); border-color: var(--purple); } }
.composer-send { background: linear-gradient(120deg, var(--purple), var(--orange)); color: #fff; }
.composer-send:disabled { opacity: 0.35; cursor: default; }
@media (hover: hover) { .composer-send:not(:disabled):hover { transform: translateY(-1px); } }
/* ✗ отменить (мягкая) и ✓ подтвердить (акцент) во время записи */
.composer-cancel { background: var(--ctrl-bg); color: var(--dim); }
@media (hover: hover) { .composer-cancel:hover { color: var(--heading); } }
.composer-confirm { background: linear-gradient(120deg, var(--purple), var(--orange)); color: #fff; }
@media (hover: hover) { .composer-confirm:hover { transform: translateY(-1px); } }
/* распознавание и отправка: на кнопке — КРУГОВАЯ загрузка (кольцо), а не
   крутящаяся стрелка; результаты после ответа появляются выше — плитками */
.composer.transcribing .composer-send i,
.composer.sending .composer-send i { display: none; }
.composer.transcribing .composer-send::after,
.composer.sending .composer-send::after { content: ""; width: 1.05rem; height: 1.05rem;
  border-radius: 50%; border: 2.5px solid rgba(255,255,255,0.35);
  border-top-color: #ffffff; animation: spin 0.8s linear infinite; }

/* ===== Кабинет-дашборд стратегии (FR-W14) ===== */
/* светлая тема действует только в app-дашборде; остальной сайт — чёрный */
html.light-cab {
  --bg: #f8fafc; --surface: #ffffff; --border: #e2e8f0;
  /* NFR-UXI-48 (аудит Н-6): подписи 12–13.5px на --dim (автор плитки,
     заметка диагностики, пояснение CTA) при #64748b давали 4.55:1 на #f8fafc
     и проваливались под 4.5:1 везде, где к ним примешана opacity;
     #475569 — 7.2:1 на фоне и 7.6:1 на карточке */
  --text: #1e293b; --dim: #475569; --heading: #0f172a; --body2: #334155;
  --track: #eef2f7; --btn-bg: #0f172a; --btn-fg: #ffffff; --input-bg: #ffffff;
  --ctrl-bg: #f1f5f9; --ctrl-border: #e2e8f0;
  /* FR-UXI-61: светлая тема — белая карточка на #f8fafc с рамкой, подсветка тёмная 6% */
  --card: #ffffff; --card-border: #e2e8f0; --hover: rgba(0,0,0,0.06);
  --org-line: rgba(0,0,0,0.28);
  color-scheme: light;
}
html.light-cab .grain { display: none; }
/* NFR-UXI-48: множители прозрачности поверх --dim в светлой теме мягче —
   «скоро»-карточка (0.72) и «скоро»-строка сайдбара (0.6) роняли подпись
   13px до ~3:1; при 0.85 остаётся ≥5:1 на белой карточке. Догадка системы
   в мыслях операции (11px, 0.6) — 0.8. Разделитель языков «|» (0.45) —
   украшение, не текст, его не трогаем. */
html.light-cab .course-card.soon,
html.light-cab .course-nav.soon { opacity: 0.85; }
html.light-cab .proc-op-thoughts .thought-guess { opacity: 0.8; }
/* FR-W14/#78: в дашборде-кабинете фон ОДНОТОННЫЙ — общий шумовой оверлей
   .grain (fixed, поверх всего экрана) даёт неровный «второй тон» на чёрном
   (в светлой теме он и так скрыт выше — оттого «на белом всё ок»). В app-режиме
   выключаем зерно и в тёмной теме: чистый чёрный без полос-бандинга. */
body.mode-app .grain { display: none; }
/* FR-PRC6h (скрин владельца 2026-07-26: «на белом фоне чёрная полоса за
   строкой ввода»): фейд слота композера (desktop sticky и мобильный fixed —
   оба в медиа-блоках ниже) налит ЖЁСТКИМ чёрным rgba(0,0,0,1). В светлой
   теме фейд строится из цвета СТРАНИЦЫ #f8fafc — тон-в-тон, как фейд шапки
   (FR-W21/FR-W23v4): полупрозрачный слой цвета фона тождественен фону при
   любой альфе, полоса физически невозможна. Специфичность html.light-cab
   выше правил в медиа-блоках, порядок не важен. */
html.light-cab body.mode-app #composer-slot-cab {
  background: linear-gradient(to top, rgba(248,250,252,1) 62%, rgba(248,250,252,0) 100%); }
/* десктоп ≥1024: первый вариант правила красит слот сплошным var(--bg) —
   светлый override обязан победить и его (градиент выше перекрывает) */
@media (max-width: 1023px) {
  /* мобильная подложка шапки (правило `header { background: … }` в блоке
     ≤1023px ниже) — тоже чёрный градиент; светлая тема живёт только в
     app-режиме кабинета, где шапке нужен светлый фейд того же тона */
  html.light-cab header {
    background: linear-gradient(rgba(248,250,252,1) 72%, rgba(248,250,252,0) 100%); }
}

/* сайдбар кабинета существует ТОЛЬКО когда есть процессы (FR-W14):
   докнут, сдвигает контент, кнопки скрыть/раскрыть нет; лого — в нём,
   на своей обычной позиции слева вверху, название компании над «Обзор» */
/* нижний паддинг маленький: профиль (.side-account, margin-top:auto) садится
   ниже, к самому краю, но с небольшим воздухом от нижней кромки экрана */
/* FR-CAB-SIDE1: скроллится не весь сайдбар, а только середина (.side-scroll):
   лого, «ИИ-стратегия» и профиль внизу приклеены и не уезжают */
.cab-side { display: none; position: fixed; top: 0; bottom: 0; left: 0; width: 280px;
  z-index: 70; background: var(--surface); border-right: 1px solid var(--border);
  padding: 1.1rem 1rem 0.5rem; flex-direction: column; gap: 0.4rem; }
.side-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 0.4rem; }
/* FR-CAB-SIDE1e (жалоба владельца 2026-07-26 по скринам с телефона: «лого и
   стрелочки смещаются в самом сайдбаре — выровни»): лого в сайдбаре стоит на
   ТОЙ ЖЕ позиции, что лого в шапке, а стрелка — сразу за ним, как в шапке
   (.header-left: gap 0.5rem). Раньше стрелка уезжала к правому краю панели, и
   при открытии/закрытии оба элемента прыгали. Отступ головы = отступ шапки
   минус паддинг сайдбара: на десктопе 2rem − 1rem = 1rem, на телефоне
   1.1rem − 1rem = 0.1rem (мобильное значение — в блоке ≤1023). */
.side-head { display: flex; align-items: center; justify-content: flex-start;
  gap: 0.5rem; margin: 0.9rem 0.2rem 1.4rem 1rem; }
.side-logo { flex-shrink: 0; }
/* значок «раскрыть» поверх лого живёт ТОЛЬКО в рейке по hover (FR-UXI-20
   ред. 2) — вне эксперимента и в полной панели скрыт, вид v1 не меняется */
.side-logo-open { display: none; }
/* FR-CAB-SIDE1f (владелец 2026-07-27, скрин сайдбара: «стрелочка эта должна
   располагаться справа у границ сайдбара, но не впритык — с отступом»):
   стрелка сворачивания прижата к ПРАВОЙ кромке панели. Двигаем именно кнопку
   (`margin-left: auto`), а не раскладку головы: `justify-content: flex-start`
   у `.side-head` держит лого на вертикали лого шапки (FR-CAB-SIDE1e), и лого
   остаётся на месте. Воздух до кромки = правый отступ головы (0.2rem) + правый
   паддинг сайдбара (1rem) плюс внутренние поля кнопки — «не впритык». */
#side-toggle { margin-left: auto; }
/* плоская иконка (размер как у ctrl-round, но БЕЗ круглой обводки) */
.icon-flat { width: 2.6rem; height: 2.6rem; border: 0; background: transparent;
  color: var(--dim); display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; font-size: 15px; border-radius: 0.6rem; transition: color 0.2s ease;
  pointer-events: auto; }@media (hover: hover) { .icon-flat:hover { color: var(--heading); } }
.header-left { display: flex; align-items: center; gap: 0.5rem; }
@media (min-width: 1024px) {
  body.mode-app.side-open .cab-side { display: flex; }
  /* контент и хедер сдвигаются вправо на ширину сайдбара; лого в хедере
     прячется — его место занимает то же лого в сайдбаре (одна позиция) */
  body.mode-app.side-open .content-layer { left: 280px; }
  body.mode-app.side-open header { left: 280px; }
  body.mode-app.side-open .header-left { display: none; }
}
/* мобилка: развёрнутый сайдбар выезжает поверх контента (FR-PRC8) */
@media (max-width: 1023px) {
  body.mode-app.side-open .cab-side { display: flex; }
  body.mode-app.side-open .header-left { visibility: hidden; }
  /* FR-CAB-SIDE1e: на телефоне отступ шапки 1.1rem, а паддинг сайдбара 1rem —
     значит голове сайдбара нужен всего 0.1rem, иначе лого прыгает 17.6→32
     (замер tools/mobile_sidebar_check.py) */
  body.mode-app .side-head { margin: 0 0.2rem 1.4rem 0.1rem; }
  /* FR-CAB-SIDE1d (жалоба владельца 2026-07-26, скрин с телефона: «при
     открытии сайдбара слева всё сдвигается и кнопки — так быть не должно»):
     открытый сайдбар — МОДАЛЬНЫЙ ОВЕРЛЕЙ, шапка не шевелится.
     Прежнее правило (FR-W20a) уводило заголовок на margin-left:280px, чтобы
     он не прятался под оверлеем, — но margin не сжимается, и на телефоне он
     толкал ВСЮ строку: замер 390px показал сдвиг кнопок 231.6→360.4 и вылет
     за кромку (right=402 > 390). На 390px правее сайдбара остаётся 110px —
     читать там нечего, поэтому под открытым оверлеем заголовок скрываем
     (display:none, чтобы место не резервировалось), а кнопки шапки остаются
     на своих местах: строка выровнена space-between по правому краю. */
  body.mode-app.side-open .header-title { display: none; }
  /* FR-CAB-SIDE1c: НА ТЕЛЕФОНЕ ТОЖЕ split — «ИИ-стратегия» сверху и профиль
     снизу НЕПОДВИЖНЫ, листается только середина (Обучение + Процессы).
     Пользователь: «я же тебе говорил, чтобы сверху стратегия и снизу профиль
     были неподвижны полностью, двигаются только обучение и процессы». Прежнее
     «листается целиком» (#159/#160) как раз и уводило профиль за нижнюю кромку.
     height: 100dvh — иначе при верхней/нижней панели браузера низ сайдбара
     оказывается ЗА видимой областью и профиль обрезается (скрин владельца).
     FR-CAB-SIDE1b: скролл середины не передаётся странице (overscroll contain),
     фон под открытым меню залочен — iOS иначе двигал страницу с адресной
     строкой и весь оверлей визуально съезжал. */
  body.mode-app .cab-side { overflow: hidden; overscroll-behavior: contain;
    height: 100vh; height: 100dvh;   /* NFR-FE8: vh-фолбэк */
    bottom: auto;
    padding-bottom: calc(0.5rem + env(safe-area-inset-bottom, 0px)); }
  body.mode-app .side-scroll { overflow-y: auto; flex: 1 1 auto; min-height: 0;
    overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
  body.mode-app.side-open { overflow: hidden; }
  /* открытое меню = модальная навигация: нижний композер (серая полоса с
     микрофоном) НЕ должен просвечивать под/рядом с меню — прячем его */
  body.mode-app.side-open #composer-slot-cab { display: none; }
}
.nav-label { font-size: 10px; font-weight: 800; text-transform: uppercase; color: var(--dim);
  margin: 0.9rem 0 0.4rem 0.6rem; letter-spacing: 0.12em; }
.nav-item { padding: 0.8rem 0.9rem; border-radius: 0.7rem; cursor: pointer; color: var(--dim);
  display: flex; align-items: center; gap: 0.7rem; font-size: 14px; font-weight: 500;
  transition: all 0.2s ease; }@media (hover: hover) { .nav-item:hover { background: var(--hover); color: var(--text); } }
/* FR-UXI-61: активная строка — та же белая подсветка + текст полужирным,
   без фиолетовой заливки (и без зависимости от hover-медиа) */
.nav-item.active { background: var(--hover); color: var(--text); font-weight: 600; }
/* тематическая иконка процесса в сайдбаре (FR-PRC8) */
.nav-item i { width: 1.1rem; text-align: center; font-size: 13px; flex-shrink: 0; }
/* FR-PRC11·clamp: имя процесса в сайдбаре — максимум 2 строки, дальше «…»
   (min-width:0 нужен, чтобы клампилось внутри flex-строки .nav-item) */
.nav-item .nav-name { min-width: 0;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; line-height: 1.35; }
/* FR-UXI-19 ред. 5 (ux-режим): у строящегося процесса справа маленький
   серый индикатор состояния (часики/диалог/тревога) — узкий (width: auto
   вместо 1.1rem), клампинг имени не ломает, на ховере остаётся серым */
.nav-item .side-proc-state { margin-left: auto; width: auto;
  font-size: 11px; color: var(--dim); }
/* «Создать новый» — монохром, как остальные пункты (FR-UXI-62; было акцентом FR-CAB-LK) */
.nav-new { color: var(--text); }

/* FR-CAB-LK: личный кабинет внизу сайдбара — аватар + имя, меню вверх */
/* личный кабинет — прижат к самому низу, БЕЗ горизонтальной полоски-разделителя */
.side-account { margin-top: auto; position: relative;
  padding-top: 0.6rem; padding-bottom: 0.4rem; }
.account-btn { width: 100%; display: flex; align-items: center; gap: 0.6rem;
  padding: 0.55rem 0.6rem; border: 0; background: transparent; cursor: pointer;
  border-radius: 0.7rem; color: var(--heading); font: inherit; text-align: left; }@media (hover: hover) { .account-btn:hover { background: var(--hover); } }
.account-avatar { width: 2rem; height: 2rem; flex-shrink: 0; border-radius: 999px;
  background: var(--purple); color: #fff; display: inline-flex; align-items: center;
  justify-content: center; font-size: 12px; font-weight: 700; overflow: hidden; }
.account-avatar img { width: 100%; height: 100%; object-fit: cover; }
.account-name { flex: 1; font-size: 13px; font-weight: 600; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.account-caret { font-size: 11px; color: var(--dim); }
.side-menu { position: absolute; left: 0; right: 0; bottom: 100%; margin-bottom: 0.4rem;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 0.8rem; padding: 0.35rem; display: flex; flex-direction: column;
  gap: 0.15rem; }
.side-menu-item { display: flex; align-items: center; gap: 0.6rem; width: 100%;
  padding: 0.6rem 0.7rem; border: 0; background: transparent; cursor: pointer;
  border-radius: 0.6rem; color: var(--dim); font: inherit; font-size: 13px; text-align: left; }@media (hover: hover) { .side-menu-item:hover { background: var(--hover); color: var(--text); } }
.side-menu-item.disabled { opacity: 0.5; cursor: default; }@media (hover: hover) { .side-menu-item.disabled:hover { background: transparent; color: var(--dim); } }
.side-menu-item i { width: 1.1rem; text-align: center; }

/* FR-AUTH1: экран входа в кабинет (код на почту / Google).
   FR-AUTH1c (владелец 2026-08-24, скрин): лого В ЦЕНТРЕ — сильно крупнее
   (это единственный бренд-якорь экрана), «или» между способами входа было
   почти нечитаемым (12px серым), верхнее лого слева дублировало центральное
   и его тут быть не должно (правило ниже, body.screen-auth). */
/* FR-AUTH1d (владелец 2026-08-25, третий скрин): экран входа — ОДНА УЗКАЯ
   КОЛОНКА. «Получить код» одного размера с «Войти через Google» (был вдвое
   шире — 432 против 267), поле ввода под ту же ширину, заголовок подгоняется
   по ней же (JS `fitAuthHeading`, моно-шрифт + nowrap). Лого опускается ниже,
   а связка «лого + форма» вытягивается к середине: обе просьбы («пониже лого»
   и «чуть выше подтяни») закрывает ОДИН рычаг — зазор между лого и формой.
   Блок центрируется целиком, поэтому сжатие зазора на Δ опускает лого на Δ/2
   и ровно на столько же поднимает форму. */
[data-screen="auth"] { --auth-col: min(100%, 18rem); --auth-drop: 2.4rem;
  gap: 0.6rem; }
[data-screen="auth"] .form { max-width: var(--auth-col); }
[data-screen="auth"] .auth-google { width: var(--auth-col); }
[data-screen="auth"] .h2-size { margin-bottom: 0.45rem; }
/* `--auth-drop` — ЕДИНСТВЕННЫЙ рычаг высоты связки. Блок центрируется
   целиком, поэтому +1rem сюда опускает и лого, и форму на полрема: «выше/
   ниже» правится этим значением и больше ничем. Зазор лого↔заголовок трогать
   нельзя — именно он держит лого прижатым к форме (сжали 63px → 25px). */
.auth-logo { display: flex; justify-content: center; margin: var(--auth-drop) 0 0; }
.auth-logo img { height: 6.5rem; width: auto; }
/* FR-AUTH1d ред. 2 (владелец 2026-08-25): «расстояние между кнопками и „или“
   уменьши» — было 1.4rem/0.9rem поверх зазора колонки, разделитель висел
   в пустоте на равном удалении от обеих кнопок вместо того, чтобы их связывать */
.auth-or { text-align: center; color: var(--dim); font-size: 19px;
  letter-spacing: 0.12em; margin: 0.2rem 0 0.1rem; }
/* верхнее лого на экране входа не нужно — в центре есть крупное */
body.screen-auth header .logo-btn { display: none; }
@media (max-width: 640px) {
  .auth-logo { margin-top: 1.6rem; }
  .auth-logo img { height: 4.4rem; }
  .auth-or { font-size: 17px; }
}
/* FR-AUTH1c: «Назад» и «Войти» в форме кода — ОДНОГО размера (было: ghost
   мельче и ниже белой кнопки, пара смотрелась случайной) */
.row-buttons .btn-ghost { padding: 1.05rem 2.1rem;
  font-size: calc(12px * var(--ui-scale)); letter-spacing: 0.15em;
  font-weight: 700; }
.auth-google { display: flex; align-items: center; justify-content: center; gap: 0.6rem; }
.auth-google .fa-google { font-size: 15px; }

/* шапка дашборда: гамбургер + название компании с подписью «ИИ-трансформация»
   слева, кнопка цвета и «Поделиться» справа — всё вверху на одном уровне */
.cab-top { display: flex; justify-content: space-between; align-items: center;
  gap: 1rem; width: 100%; flex-wrap: wrap; }
.cab-top-left { display: flex; align-items: center; gap: 0.9rem; min-width: 0; }
.cab-top .cab-title { font-size: clamp(1.15rem, 1.6vw, 1.5rem); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.cab-top-actions { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
/* Аудит 2026-08-31: на телефоне кнопки задавливали заголовок до «П..» —
   в панели название занимает свою строку, а в фикс-шапке кабинета титулу
   даём две строки компактным кеглем вместо схлопывания в две буквы. */
@media (max-width: 1023px) {
  .cab-top-left { flex: 1 1 100%; }
  .header-title { margin-left: 0.6rem; }
  /* FR-UXI-66: на телефоне тоже ОДНА строка 13px — переполнение едет
     бегущей строкой, а не переносится на вторую строку */
  .header-title .hdr-title-text { font-size: 13px; line-height: 1.25;
    white-space: nowrap; overflow: hidden; }
  /* лого в мобильной шапке кабинета прячем (как на экране входа,
     FR-AUTH1c): бренд есть в сайдбаре, а титулу нужна вся левая часть */
  body.mode-app header .logo-btn { display: none; }
}
/* кнопки кабинета (тема/шаринг/дорожная карта) прилегают к ПРАВОМУ краю
   экрана на десктопе — на уровне шапки, как лого слева (FR-W14) */
@media (min-width: 1024px) {
  body.mode-app #cab-actions { position: fixed; top: 1.4rem; right: 1.4rem;
    z-index: 35; }
}
.cab-top-actions .btn-ghost, .cab-top-actions .btn-white { height: 2.6rem;
  padding: 0 1.2rem; font-size: 12px; display: inline-flex; align-items: center; }
/* круглая кнопка смены фона — как на курсе (sun/moon) */
.ctrl-round { width: 2.6rem; height: 2.6rem; border-radius: 999px;
  border: 1px solid var(--ctrl-border); background: var(--ctrl-bg); color: var(--heading);
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  font-size: 15px; transition: all 0.25s ease; flex-shrink: 0; }@media (hover: hover) { .ctrl-round:hover { background-image: linear-gradient(var(--hover), var(--hover)); } }

/* карточка ИИ-диагностики сверху: уровень зрелости — заголовком, под ним
   короткий комментарий, кнопки примкнуты к нижнему краю карточки (FR-W14) */
.maturity-card { width: 100%; background: var(--card); border: 1px solid var(--card-border);
  border-radius: 1.25rem; padding: 1.3rem 1.5rem; display: flex; align-items: stretch;
  justify-content: space-between; gap: 1.2rem; flex-wrap: nowrap; }
.maturity-card h3 { margin: 0 0 0.5rem; font-size: 18px; color: var(--heading); }
.maturity-card .muted { margin: 0; }
/* карточка индекса открывается как процесс — подсветка при наведении */
.maturity-card.clickable { cursor: pointer; transition: background-image 0.2s ease; }@media (hover: hover) { .maturity-card.clickable:hover { background-image: linear-gradient(var(--hover), var(--hover)); } }
.maturity-card > .btn-white { align-self: center; }
/* FR-W14: форма «диагностика НЕ пройдена» — колонка: текст на ВСЮ ширину
   карточки, кнопка «Пройти ИИ-диагностику» примкнута к НИЗУ-СПРАВА */
.maturity-card.mat-form { flex-direction: column; align-items: stretch; gap: 1rem; }
.maturity-card.mat-form > .btn-white { align-self: center; white-space: nowrap; }
/* текст-блок ужимается, кольцо остаётся СПРАВА и на мобилке (не съезжает вниз) */
.mat-left { display: flex; flex-direction: column; align-items: flex-start;
  flex: 1 1 0; min-width: 0; }
/* в форме «не пройдена» текст занимает всю ширину карточки (кольца нет) */
.maturity-card.mat-form .mat-left { flex: 0 0 auto; width: 100%; }
.maturity-card.mat-form .mat-left .muted { max-width: none; }
/* B5 (FR-W14 ред. 2, скрин владельца): кольцо — к ВЕРХУ карточки, не по центру */
/* владелец 2026-09-10: кольцо справа по центру ПО ВЕРТИКАЛИ */
.mat-score { flex: 0 0 auto; position: absolute; top: 50%; right: 1.3rem; transform: translateY(-50%); }
/* кольцо вынесено в угол абсолютом, чтобы кнопка центрировалась по ВСЕЙ карточке;
   текст под кольцо не заходит — отступ справа на ширину кольца */
.maturity-card { position: relative; }
.maturity-card:not(.mat-form) .mat-left { width: 100%; flex: 1 1 100%; }
.maturity-card:not(.mat-form) .mat-left > h3,
.maturity-card:not(.mat-form) .mat-left > p { padding-right: 8.5rem; }
.mat-note { max-width: 34rem; font-size: 13.5px; line-height: 1.6; }
.mat-btns { justify-content: center; margin-top: auto; padding-top: 1.1rem; width: 100%; }
/* «Пройти ИИ-диагностику» / «Пройти заново» — по центру и в одну строку */
.mat-btns .btn-white, .mat-btns .btn-ghost { white-space: nowrap; }
.mat-score { display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 0.35rem; }
.score-label { font-size: 11px; font-weight: 800; color: var(--dim); text-transform: uppercase;
  letter-spacing: 0.08em; }
/* компактное фиолетово-оранжевое кольцо индекса в карточке */
.result-ring.ring-sm { width: 118px; height: 118px; }
.result-ring.ring-sm .ring-value { font-size: 22px; }
/* мобилка: кольцо остаётся СПРАВА от текста (не съезжает вниз) — ужимаем его и
   базис текста, чтобы оба помещались в строку (FR-CAB-LK4) */
@media (max-width: 560px) {
  .maturity-card { padding: 1.1rem 1.15rem; gap: 0.8rem; }
  .mat-left { flex-basis: 8rem; }
  /* FR-CAB-LK4: узкая колонка рядом с кольцом — заголовок 18px ломался на 3
     строки с переносами посреди слов; 15px даёт 2 чистые строки */
  .maturity-card h3 { font-size: 15px; line-height: 1.3; margin-bottom: 0.35rem; }
  .result-ring.ring-sm { width: 88px; height: 88px; }
  .result-ring.ring-sm .ring-value { font-size: 16px; }
}

/* карточки процессов в обзоре — просто: иконка, тайтл, короткое описание
   (без №, статуса, отдела и горизонтальной черты; FR-PRC8) */
.process-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(16.5rem, 1fr));
  gap: 0.9rem; width: 100%; }
.proc-tile { background: var(--card); border: 1px solid var(--card-border); border-radius: 1.1rem;
  padding: 1.2rem 1.3rem; cursor: pointer; transition: background-image 0.25s ease;
  display: flex; flex-direction: column; gap: 0.7rem; }@media (hover: hover) { .proc-tile:hover { background-image: linear-gradient(var(--hover), var(--hover)); } }
/* FR-UXI-62: плашка иконки нейтральная, чередование purple/orange снято */
.tile-ico { width: 2.7rem; height: 2.7rem; border-radius: 0.8rem; display: inline-flex;
  align-items: center; justify-content: center; font-size: 17px;
  background: var(--ctrl-bg); color: var(--text); }
.proc-tile-name { font-weight: 700; font-size: 15px; color: var(--heading); min-width: 0; }
/* B25-REFRESH (FR-PRC113): значок «Обновить» справа вверху плитки готового
   процесса; шапка плитки уступает ему место, чтобы имя не уходило под значок */
.proc-tile { position: relative; }
.proc-tile.has-refresh .proc-tile-head { padding-right: 2.4rem; }
.tile-refresh { position: absolute; top: 0.75rem; right: 0.75rem; width: 2rem; height: 2rem;
  border: 0; border-radius: 50%; background: transparent; color: var(--dim); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; font-size: 13px; }
.tile-refresh:focus-visible { background: var(--ctrl-bg); color: var(--text); outline: none; }
@media (hover: hover) { .tile-refresh:hover { background: var(--ctrl-bg); color: var(--text); } }   /* NFR-FE10 */
input.ux-field[data-uxf="metric_now"] { margin-top: 0.4rem; }
/* B5 (FR-UXI-104 ред. 3): шапка плитки — иконка и имя в строку, иконка меньше */
.proc-tile-head { display: flex; align-items: center; gap: 0.7rem; min-width: 0; }
.proc-tile-head .tile-ico { width: 2rem; height: 2rem; border-radius: 0.6rem; font-size: 14px; flex: none; }
.proc-tile-sub { font-size: 13.5px; color: var(--dim); margin-top: -0.25rem; line-height: 1.55;
  /* FR-PRC11: описание процесса на карточке — максимум 2 строки, дальше «…» */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

/* FR-EDU1/FR-CAB-LK3: «Обучение» и «Процессы» — НОРМАЛЬНЫЕ секции-заголовки на
   главной кабинета (размер как заголовок карточки диагностики ~18px), а не
   мелкие ярлычки. Раньше courses-title был 10px uppercase «в тон сайдбара». */
.section-title { font-size: clamp(16px, 1.4vw, 20px); font-weight: 800;
  color: var(--heading); margin: 0.9rem 0 0.9rem; }
.courses-block { width: 100%; margin: 0.4rem 0 0.2rem; }
.courses-title { font-size: clamp(16px, 1.4vw, 20px); font-weight: 800;
  color: var(--heading); margin: 0.4rem 0 0.9rem; }
/* FR-EDU1 ред. 2: курс остался ОДИН — жёсткие две колонки оставляли его
   half-width с дырой справа. auto-fit тянет одинокую карточку на всю ширину,
   а когда курсов снова станет несколько — они сами лягут в ряд по два. */
.course-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 0.9rem; }
.course-card { background: var(--card); border: 1px solid var(--card-border);
  border-radius: 1.1rem; padding: 1.15rem 1.25rem; cursor: pointer;
  transition: background-image 0.25s ease; display: flex; align-items: flex-start; gap: 0.9rem; }@media (hover: hover) { .course-card:not(.soon):hover { background-image: linear-gradient(var(--hover), var(--hover)); } }
.course-ico { flex: 0 0 auto; width: 2.7rem; height: 2.7rem; border-radius: 0.8rem;
  display: inline-flex; align-items: center; justify-content: center; font-size: 17px;
  background: var(--ctrl-bg); color: var(--text); }
.course-body { flex: 1 1 auto; min-width: 0; }
.course-name { font-weight: 700; font-size: 15px; color: var(--heading);
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.course-sub { font-size: 13px; color: var(--dim); margin-top: 0.3rem; line-height: 1.5; }
.course-go { color: var(--dim); font-size: 13px; margin-top: 0.15rem; }
.course-card.soon { cursor: default; opacity: 0.72; }
.soon-tag { font-size: 9.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--dim); border: 1px solid var(--border);
  border-radius: 999px; padding: 0.1rem 0.45rem; }
/* сайдбар: курсы как навигация, «скоро» — приглушённые */
.course-nav { display: flex; align-items: center; gap: 0.55rem; }
.course-nav.soon { opacity: 0.6; cursor: default; }
.course-nav .soon-tag { margin-left: auto; }
@media (max-width: 720px) { .course-grid { grid-template-columns: 1fr; } }

/* ===== Лог событий сборки (FR-PRC8) — чат как в ChatGPT ===== */
.build-log { width: 100%; max-width: 46rem; margin: 0.6rem auto 0; display: flex;
  flex-direction: column; gap: 0.8rem; overflow-y: auto; padding-right: 0.2rem; }
/* десктоп: лента сборки начинается НИЖЕ фиксированных кнопок шапки
   (тема/шаринг/дорожная карта at top:1.4rem) — иначе первое сообщение
   уезжало под них и обрезалось «чёрным сверху» (FR-PRC8) */
@media (min-width: 1024px) {
  body.mode-app #cab-log { padding-top: 2.6rem; }
}
.log-row { display: flex; }
.log-row.user { justify-content: flex-end; }
.log-row.agent { justify-content: flex-start; }
/* B5 (FR-PAY4b ред. 2): плашка «первый процесс разобран» — по центру */
.log-row.center { justify-content: center; text-align: center; }
.log-row.center .drawer-cta { justify-content: center; }
/* FR-PRC8h (владелец 2026-08-02, жалоба повторена четырежды): реплика,
   уехавшая из живого виджета в ИСТОРИЮ ленты, обязана сохранить переносы и
   нумерованные пункты. Текст кладётся в бабл через esc() — \n в нём остаются,
   но HTML схлопывал их в пробел, и пачка «1) … 2) …» читалась простынёй.
   pre-line — тот же режим, что у живого вопроса (.q-text.iv2-msg): переносы
   видны, лишние пробелы схлопываются; собранная разметка виджетов строится
   конкатенацией БЕЗ переводов строк, поэтому на неё правило не влияет. */
.log-bubble { max-width: 92%; border-radius: 1.1rem; padding: 0.8rem 1.05rem;
  font-size: 13.5px; line-height: 1.6; color: var(--text); white-space: pre-line; }
.log-row.user .log-bubble { background: rgba(136,84,243,0.16);
  border: 1px solid rgba(136,84,243,0.35); border-bottom-right-radius: 0.35rem; }
.log-row.agent .log-bubble { background: var(--surface); border: 1px solid var(--border);
  border-bottom-left-radius: 0.35rem; }
/* FR-W23 v3 (регресс #162 откачен): широкий виджет-ряд СОХРАНЯЕТ карточку —
   фон var(--surface) + рамку он наследует от `.log-row.agent .log-bubble`
   (у ряда классы «agent widget»). Пользователь: «блять, куда рамки делись?» —
   в #162 я убил подложку в погоне за «полосой», но полоса НЕ воспроизводилась
   ни одним пиксельным сканом (0 швов); карточка виджета интервью/точек/ролей
   обязана быть. Здесь — только ширина на всю ленту, рамка/фон = как у agent. */
.log-row.widget .log-bubble { width: 100%; max-width: 100%; }
.log-row.dim .log-bubble { color: var(--dim); font-size: 12.5px; }
.log-row.live .log-bubble { color: var(--dim); }
.log-err { color: #f87171; }
.log-widget { margin-top: 0.8rem; }
/* выход из режима чата — по центру НАД элементом ввода (FR-PRC8).
   FR-UXI-33 (проход 2026-08-28): выход — ВТОРИЧНАЯ кнопка (обводка, без
   акцентной заливки): разрушительное действие («несобранные процессы будут
   удалены») не может выглядеть важнее продвигающего «Готово»/«Далее». */
.log-exit-row { display: flex; justify-content: center; margin-top: 1.1rem; }
/* FR-PRC60: бабл сбоя разбора — вместо спиннера, с кнопкой «Повторить»
   (обводка красная, как у .form-error — это ошибка, а не реплика агента) */
.log-row.error .log-bubble { border-color: #f87171; }
.log-retry-row { margin-top: 0.7rem; }
.btn-exit { display: inline-flex; align-items: center; gap: 0.55rem;
  border: 1px solid var(--border); border-radius: 999px;
  background: transparent; color: var(--dim); cursor: pointer;
  font-family: inherit; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.1em; font-size: 12px; padding: 0.75rem 1.7rem;
  min-height: 44px; transition: all 0.25s ease; }
@media (hover: hover) {
  .btn-exit:hover { border-color: var(--orange); color: var(--orange-l); }
}
.log-widget .story-list li { background: var(--bg); }
.log-widget .point-card, .log-widget .role-pick { background: var(--bg); }
/* FR-PRC18 (#67): финальная карточка «карточка сохранена» с TO-BE-схемой —
   на всю ширину ленты, с зелёным бейджем-галочкой сверху */
.log-row.done .log-bubble { width: 100%; max-width: 100%; }   /* карточка «сохранено» — с рамкой (наследует от .agent) */
.log-done-badge { display: inline-flex; align-items: center; gap: 0.45rem;
  margin-bottom: 0.65rem; padding: 0.28rem 0.7rem; border-radius: 999px;
  background: rgba(34,197,94,0.14); border: 1px solid rgba(34,197,94,0.4);
  color: #22c55e; font-size: 11px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.08em; }
/* FR-PRC11: текст под бейджем «Процесс сохранён» — с отступом, отдельным блоком */
.done-note { margin-top: 0.2rem; line-height: 1.55; }
.log-widget.log-done { background: var(--bg); border-radius: 1rem;
  padding: 0.9rem; margin-top: 0.9rem; }
.log-widget.log-done .dg-title { font-size: 10px; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--dim); margin-bottom: 0.5rem; }

/* экран процесса: корзина-удаление и кликабельные агенты (FR-PRC8) */
.proc-delete { color: var(--dim); }@media (hover: hover) { .proc-delete:hover { color: #f87171; } }
.agent-card.clickable { cursor: pointer; transition: background-image 0.2s ease; }@media (hover: hover) { .agent-card.clickable:hover { background-image: linear-gradient(var(--hover), var(--hover)); } }
.dr-text { margin: 0; font-size: 15px; line-height: 1.65; color: var(--text); }

/* блок процесса: пункты «в ИИ» и агенты с местом человека */
.proc-points { margin: 0; padding-left: 1.15rem; display: flex; flex-direction: column;
  gap: 0.5rem; font-size: 14px; line-height: 1.6; color: var(--text); }
.proc-points li::marker { color: var(--purple); }
.agent-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
  gap: 0.9rem; }
/* FR-PRC15: подпись под ролью агента — что именно он автоматизирует */
.agent-sub { margin: 0.35rem 0 0; font-size: 12.5px; line-height: 1.5;
  /* FR-PRC19b: описание в карточке агента ВМЕЩАЕТСЯ (до 3 строк, дальше «…») —
     полная версия и детали живут в самой карточке-дровере */
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden; }
.agent-human { margin: 0.6rem 0 0; font-size: 13px; color: var(--orange); }

/* строка статуса записи занимает место только во время записи — ошибки
   стоят сразу под элементом ввода, без пустого зазора (FR-PRC6) */
.composer-status { margin: 0; }
.composer-status:not(:has(#rec-live:not([hidden]))) { display: none; }
.rec-live { color: var(--orange-l); }
.rec-live b { color: #fff; }
.rec-dot { display: inline-block; width: 8px; height: 8px; border-radius: 999px;
  background: #ef4444; margin-right: 0.3rem; animation: recPulse 1.2s infinite; }
/* FR-PRC1b: подсказка про авто-обрыв 15 минут */
.rec-hint { color: var(--orange-l); }
/* FR-PRC1a: повтор распознавания — компактная кнопка под статусом */
.rec-retry { margin-top: 0.5rem; font-size: 12px; padding: 0.3rem 0.7rem; }

/* карточки процессов */
.proc-card { background: var(--surface); border: 1px solid var(--border); border-radius: 1.1rem;
  padding: 1.15rem 1.25rem; margin-bottom: 0.85rem; }
.proc-card-top { display: flex; align-items: center; justify-content: space-between; gap: 0.8rem; flex-wrap: wrap; }
.proc-name { font-weight: 700; font-size: 13.5px; color: #fff; }
.proc-summary { margin: 0.4rem 0 0; font-size: 14.5px; color: var(--dim); line-height: 1.65;
  /* FR-PRC11: описание процесса на карточке — максимум 2 строки, дальше «…» */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.status-chip { border-radius: 999px; padding: 0.25rem 0.7rem; font-size: 10px; text-transform: uppercase;
  letter-spacing: 0.08em; border: 1px solid var(--border); display: inline-flex; align-items: center; gap: 0.4rem; }
.status-chip.generating { color: var(--orange-l); border-color: rgba(249,115,22,0.4); }
.status-chip.ready { color: #4ade80; border-color: rgba(74,222,128,0.35); }
.status-chip.step { color: var(--purple-l); border-color: rgba(136,84,243,0.4); }

/* ===== Drawer процесса — карточка инициативы СПРАВА (FR-W14/FR-PRC7) ===== */
.drawer-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 115; }
.drawer { position: fixed; top: 0; right: 0; bottom: 0; width: min(640px, 100vw);
  background: var(--bg); border-left: 1px solid var(--border); z-index: 120;
  transform: translateX(100%); transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
  /* FR-PRC13·fill: сам drawer КЛИПИТ (не скроллит) — скролл переносим на тело,
     чтобы шапка была зафиксирована, а тело заполняло всю высоту без «пустоты» */
  overflow: hidden; display: flex; flex-direction: column; }
.drawer.active { transform: translateX(0); }
/* карточка агента — узкое правое окно (FR-PRC8) */
.drawer.slim { width: min(460px, 100vw); }
.drawer.slim .drawer-head { padding: 1.8rem 1.6rem 1.2rem; }
.drawer.slim .drawer-body { padding: 1.3rem 1.6rem 2rem; }
.drawer-head { padding: 2.2rem 2.2rem 1.4rem; border-bottom: 1px solid var(--border);
  position: relative; flex-shrink: 0; }
/* FR-PRC13: крестик карточки агента — без кружка/фона, просто иконка */
.drawer-close { position: absolute; top: 1.2rem; right: 1.2rem; width: 2.4rem; height: 2.4rem;
  border-radius: 999px; border: 0; background: transparent;
  color: var(--dim); display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; font-size: 18px; transition: color 0.2s ease; }@media (hover: hover) { .drawer-close:hover { color: var(--heading); } }
.drawer-badge { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.3rem 0.8rem;
  background: rgba(136,84,243,0.14); color: var(--purple-l); border-radius: 999px;
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em;
  margin-bottom: 0.8rem; }
.drawer-title { margin: 0 0 0.4rem; font-size: clamp(1.2rem, 2vw, 1.6rem); font-weight: 800;
  text-transform: uppercase; color: var(--heading); }
.drawer-subtitle { margin: 0; font-size: 13.5px; color: var(--dim); line-height: 1.6; }
/* FR-PRC13·fill: тело drawer РАСТЯГИВАЕТСЯ на всю оставшуюся высоту (flex:1),
   иначе при коротком/прокрученном контенте снизу зияла «пустота» — голый фон
   .drawer вместо фона карточки. min-height:0 — чтобы работал скролл внутри. */
.drawer-body { padding: 1.6rem 2.2rem 2.4rem; flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.drawer-sec { margin: 1.6rem 0 0.9rem; font-size: 11px; font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.12em; color: var(--dim); }
/* иконка секции — монохром (FR-UXI-63; раньше фиолетовая по референсу FR-PRC8) */
.drawer-sec i { color: var(--dim); margin-right: 0.45rem; font-size: 13px; }
/* FR-PRC16c (владелец 2026-07-29): на СТРАНИЦЕ процесса заголовки секций
   («Цель процесса», «Описание процесса — как сейчас/как будет с ИИ») —
   заметно крупнее, чем в узком drawer агента */
#proc-detail .drawer-sec { font-size: 15px; letter-spacing: 0.1em; }
#proc-detail .drawer-sec i { font-size: 16px; }
/* FR-PRC16c ред. 2 / FR-UXI-102 (батч 4): строки-описания #proc-summary на
   странице процесса больше нет — табы идут сразу за заголовком */
/* узкое место процесса — карточка с оранжевой кромкой */
.pain-item { border-left: 3px solid var(--orange); background: var(--surface);
  border-radius: 0 0.7rem 0.7rem 0; padding: 0.75rem 1rem; margin-bottom: 0.6rem;
  font-size: 13.5px; line-height: 1.55; color: var(--text); }
/* номер вопроса в виджете (FR-PRC8: вопросы по одному) */
.q-num { display: inline-flex; padding: 0.3rem 0.8rem; border-radius: 999px;
  background: rgba(136,84,243,0.14); color: var(--purple-l); font-size: 11px;
  font-weight: 800; text-transform: uppercase; letter-spacing: 0.08em;
  margin: 0.8rem 0 0.6rem; }
/* FR-IV2-9n (владелец 2026-07-27, скрин: «„1/2 · Закупка алмазов“ — чуть
   повыше, а то сверху отступ большой»): внутри виджета интервью чип шага —
   первый элемент, его верхний отступ схлопывается с отступом самого виджета
   (.log-widget 0.8rem + .q-num 0.8rem ≈ двойной воздух). Оставляем воздух
   виджету, чип прижимаем. */
.log-widget .q-num { margin-top: 0.1rem; }
/* КАНОН-5 (владелец 2026-07-27): под чипом процесса «1/3 · Процесс» —
   вторая строка «2/6 — Название операции». Отдельная строка, а не хвост
   чипа: длинное название операции иначе разрывало пилюлю. */
.q-op { font-size: 12px; font-weight: 700; color: var(--body2);
  margin: 0 0 0.5rem; letter-spacing: 0.02em; }
.q-text { margin: 0; font-size: 13.5px; line-height: 1.6; color: var(--text); }
/* Интервью v2 (FR-IV2-8a): пачка вопросов одним сообщением — переносы строк
   сохраняются (pre-line) и переживают печать typeInto (textContent с \n). */
.q-text.iv2-msg { white-space: pre-line; }
/* FR-IV2-2c: бейдж подпроцесса в плитке процесса */
.proc-sub-badge {
  display: inline-block; margin-left: 6px; padding: 1px 7px;
  font-size: 10px; line-height: 1.5; border-radius: 999px;
  color: #8854F3; border: 1px solid rgba(136, 84, 243, 0.45);
  vertical-align: middle; white-space: nowrap;
}
/* лейбл «какой процесс разбираем» над виджетом шага (FR-PRC8/FR-PRC9) */
.q-proc { display: block; font-size: 11px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--dim); margin-bottom: 0.55rem; }
.q-proc b { color: var(--purple-l); }
/* живой ack модели — внутри виджета, между лейблом процесса и номером
   вопроса; в ленте не сохраняется (FR-PRC8) */
.q-ack { margin: 0 0 0.7rem; padding-left: 0.75rem; font-size: 13px;
  line-height: 1.55; color: var(--text); border-left: 3px solid var(--orange); }
/* прогресс-бар вопросов — как в тесте ИИ-индекса (FR-PRC8) */
.q-bar { margin: 0.1rem 0 0.8rem; }
.drawer-body > .drawer-sec:first-child { margin-top: 0; }
.drawer-cta { margin-top: 1.4rem; display: flex; gap: 0.7rem; flex-wrap: wrap; }

/* нумерованные вопросы — как story-list референса */
.story-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column;
  gap: 0.7rem; counter-reset: story; }
.story-list li { display: grid; grid-template-columns: 2rem 1fr; gap: 0.8rem;
  align-items: flex-start; background: var(--surface); border: 1px solid var(--border);
  border-radius: 0.8rem; padding: 0.85rem 1rem; }
.story-list li::before { counter-increment: story; content: counter(story);
  background: var(--purple); color: #fff; width: 1.75rem; height: 1.75rem;
  border-radius: 0.5rem; display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700; }
.story-list li span { font-size: 15px; line-height: 1.6; color: var(--text); }
/* детали этапа из нот диаграммы — на странице процесса (FR-PRC8) */
.step-facts { display: flex; flex-direction: column; gap: 0.2rem; margin-top: 0.45rem; }
.step-fact { font-size: 13.5px; line-height: 1.55; color: var(--dim); }
.step-fact b { color: var(--heading); font-weight: 700; margin-right: 0.3rem; }
/* кнопка «Пропустить →» — справа в виджете вопросов (FR-PRC8) */
.drawer-cta.cta-right { justify-content: flex-end; }
/* FR-PRC28: стрелка «назад» в опроснике — без подписи, СЛЕВА внизу виджета
   (margin-right:auto отжимает её от кнопок пропуска к левому краю) */
.drawer-cta .q-back { margin-right: auto; padding-left: 0.9rem; padding-right: 0.9rem; }
/* FR-PRC28b: на телефоне кнопки пропуска переносятся в ДВЕ строки, а стрелка
   «назад» оставалась на верхней — палец тянется вверх, и она висит отдельно
   от кнопок (скрин владельца). Прижимаем её к НИЖНЕЙ кнопке, место под неё
   резервируем только когда она есть (класс has-back ставит renderBuildLog). */
/* внутри стрелки только иконка, и её коробка была на 14px ниже текстовой
   кнопки — «уровень» не сходился; выравниваем высоты кнопок блока */
.drawer-cta .btn-ghost { min-height: 2.25rem; }
.drawer-cta .q-back { display: inline-flex; align-items: center;
  justify-content: center; }
@media (max-width: 1023px) {
  .drawer-cta.cta-right.has-back { position: relative; padding-left: 3.6rem; }
  .drawer-cta.cta-right.has-back .q-back { position: absolute; left: 0; bottom: 0;
    margin-right: 0; }
}
/* FR-IV2-9d: галочка-подтверждение в интервью v2 — иконка БЕЗ слов, правее
   всего; компактная белая кнопка вровень с остальными кнопками блока */
.drawer-cta .iv2-yes { display: inline-flex; align-items: center;
  justify-content: center; min-height: 2.25rem; min-width: 3rem;
  padding-left: 1rem; padding-right: 1rem; }
/* «Как внедрить агентов» — снизу ПО ЦЕНТРУ под AS-IS (FR-PRC12) */
.drawer-cta.cta-center { justify-content: center; }
/* FR-PRC16: описание процесса ПО ЭТАПАМ — римская цифра + название +
   грамотный текст + стандартные иконки для деталей (пустое не выводим) */
.proc-stages { display: flex; flex-direction: column; gap: 1.1rem; }
/* FR-PRC24: этап — серая ПРЯМОУГОЛЬНАЯ КАРТОЧКА (как плитки, но НЕ кликабельная
   и без hover); вертикальная полоска осталась только ВНУТРИ — у операций
   (.proc-op), она соединяет их между собой */
.proc-stage { background: var(--surface); border: 1px solid var(--border);
  border-radius: 0.9rem; padding: 1rem 1.15rem 1.1rem; }
.proc-stage-head { display: flex; align-items: baseline; gap: 0.7rem; }
.proc-stage-head b { font-size: 15.5px; color: var(--heading); }
.proc-stage-num { flex: 0 0 auto; font-size: 13px; font-weight: 800;
  color: var(--purple-l); letter-spacing: 0.05em; min-width: 1.6rem; }
.stage-desc { margin: 0.45rem 0 0; }
/* FR-PRC13·ops: ОПЕРАЦИИ этапа — вложенный список внутри этапа; каждая операция
   с названием («что делается»), комментарием и фактами-иконками */
.proc-ops { display: flex; flex-direction: column; gap: 0.9rem; margin-top: 0.85rem; }
.proc-op { border-left: 2px solid rgba(136,84,243,0.35); padding: 0.05rem 0 0.05rem 0.9rem; }
.proc-op-name { font-size: 14px; font-weight: 600; color: var(--heading); line-height: 1.4; }
.proc-op-num { color: var(--purple-l); font-weight: 800; margin-right: 0.15rem; }
.proc-op-comment { margin: 0.35rem 0 0; font-size: 13px; color: var(--dim);
  font-style: italic; line-height: 1.5; }
/* FR-PRC13g: комментарий операции AS-IS (что плохо/чего не хватает) —
   ОРАНЖЕВЫЙ; в TO-BE и функциях агента комментарий = ЧТО делает (нейтральный),
   а «чем будет лучше» вынесено отдельной ФИОЛЕТОВОЙ строкой .proc-op-improve */
[data-dg-view="asis"] .proc-op-comment { color: var(--orange); }
/* FR-PRC13i: «чем будет лучше того что было» — фиолетовым, отдельной строкой,
   со стрелкой роста; в AS-IS не показывается (там improvement пуст) */
.proc-op-improve { margin: 0.3rem 0 0; font-size: 13px; color: var(--purple-l);
  line-height: 1.5; display: flex; align-items: baseline; gap: 0.45rem; }
.proc-op-improve i { font-size: 11px; flex-shrink: 0; }
.proc-op .stage-facts { margin-top: 0.4rem; gap: 0.35rem; }
/* FR-IV2-8f ред. 7 (канон владельца 2026-07-30): мыслительные шаги операции —
   РАСКРЫВАЮЩИЙСЯ блок ВНУТРИ её карточки, своим цветом (мысль ≠ работа).
   Свёрнут по умолчанию: в живом прогоне на 9 шагов приходилось 37 мыслей, и
   развёрнутыми они хоронили сам процесс. */
.proc-op-thoughts { margin-top: 0.45rem; border-left: 2px solid var(--purple-l);
  padding-left: 0.6rem; }
.proc-op-thoughts > summary { cursor: pointer; list-style: none;
  font-size: 12px; color: var(--purple-l); display: flex; gap: 0.4rem;
  align-items: center; user-select: none; }
.proc-op-thoughts > summary::-webkit-details-marker { display: none; }
.proc-op-thoughts > summary::after { content: "▸"; font-size: 10px;
  transition: transform 0.15s ease; }
.proc-op-thoughts[open] > summary::after { transform: rotate(90deg); }
.proc-op-thoughts > summary i { font-size: 11px; }
.proc-op-thoughts ul { margin: 0.35rem 0 0; padding-left: 1rem;
  font-size: 13px; line-height: 1.5; }
.proc-op-thoughts li { margin: 0.15rem 0; }
.proc-op-thoughts .thought-logic { opacity: 0.72; }
/* FR-IV2-8f ред. 8: мысль-предположение системы — приглушённой пометкой,
   как серая догадка в карточке интервью: владелец видит, что это не его слова */
.proc-op-thoughts .thought-guess { font-size: 11px; opacity: 0.6;
  border: 1px solid var(--border); border-radius: 4px; padding: 0 4px;
  margin-left: 4px; white-space: nowrap; cursor: help; }
/* FR-PRC13: факты этапа — КОЛОНКОЙ (каждый на своей строке, друг за другом,
   а не «сплошняком»); смысл несёт ИКОНКА (без слов-подписей), словесная
   расшифровка — в title по наведению. Порядок задаёт stageFacts() в app.js */
.stage-facts { display: flex; flex-direction: column; gap: 0.45rem; margin-top: 0.6rem; }
.stage-fact, .stage-pain { display: flex; align-items: flex-start; gap: 0.55rem;
  font-size: 13px; line-height: 1.5; color: var(--dim); }
.stage-fact i, .stage-pain i { flex: 0 0 auto; margin-top: 0.15rem; width: 1.1rem; text-align: center; }
/* FR-UXI-63 (владелец 2026-09-01: «метрика, триггер и цель — значки монохромные,
   они везде монохромные»): значки фактов операции/точки — одним --dim */
.stage-fact i { color: var(--dim); font-size: 13px; }
.stage-pain { color: var(--text); }
.stage-pain i { color: var(--dim); font-size: 13px; }
/* факты агента иконками (вход/результат/системы/метрики/эффект) — как у этапа */
.agent-facts { flex-direction: column; gap: 0.55rem; margin-top: 0.8rem; }
.agent-facts .stage-fact { font-size: 13.5px; color: var(--text); }
/* круговая загрузка внутри окна процесса (FR-PRC8) */
.proc-loading { display: flex; justify-content: center; align-items: center; padding: 4rem 0; }
.ui-spinner { width: 2.2rem; height: 2.2rem; border-radius: 999px;
  border: 3px solid var(--border); border-top-color: var(--purple);
  animation: spin 0.8s linear infinite; }
/* FR-PRC16: воздух сверху у нижней CTA («Как внедрить…» / «Разработать…»); снизу
   запас даёт padding-bottom самого экрана (FR-W12b), свой margin-bottom не нужен —
   иначе двойной отступ. */
.proc-tobe-cta { margin-top: 1.6rem; margin-bottom: 0; }
.drawer-cta.cta-agent-dev { margin-top: 1.2rem; }
.dr-answers { margin-top: 1rem; width: 100%; resize: vertical; min-height: 6rem;
  font-size: 14px; }

/* табы AS-IS/TO-BE — по центру, крупные, диаграммы перещёлкиваются (FR-PRC8) */
.dg-tabs-row { display: flex; justify-content: center; position: relative; }
/* FR-W50n ред. 3 / FR-UXI-104 (батч 4): строки фактов .proc-facts над полотном
   больше нет — цель · метрика · триггер живут в карточке кабинета
   (.tile-facts, блок B4-HEADER) */
.dg-tabs { display: inline-flex; gap: 0; border: 1px solid var(--border);
  border-radius: 999px; overflow: hidden; margin-bottom: 0.9rem; }
.dg-tab { border: 0; background: transparent; color: var(--dim); padding: 0.75rem 1.7rem;
  font-family: inherit; font-size: 13.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.08em; cursor: pointer; transition: all 0.2s ease; }
.dg-tab.active { background: rgba(136,84,243,0.16); color: var(--purple-l); }
/* mermaid следует теме кабинета (FR-PRC8): тёмный фон → тёмная схема,
   светлый → белая; тему рендера выбирает сервер (?theme=), подложку — рамка */
.dg-frame { background: #0b0b10; border: 1px solid var(--border); border-radius: 1rem;
  padding: 0.8rem; overflow-x: auto; position: relative; min-height: 4.5rem; }
html.light-cab .dg-frame { background: #ffffff; border-color: #e2e8f0; }
/* FR-PRC12c: спиннер в кадре диаграммы, пока <img> не дозагрузилась
   (JS убирает .dg-load по load/error картинки).
   Ред. 2 (владелец 2026-08-03: «эмблема загрузки куда-то плывёт»), два корня:
   (1) `animation: spin` ЗАМЕЩАЕТ transform целиком на всё время вращения —
   центровка translate(-50%,-50%) исчезала, спиннер висел со сдвигом на
   полразмера от центра; лечится СВОИМИ кейфреймами с запечённым translate
   (тот же приём, что у auraPulse);
   (2) top:50% привязывал спиннер к центру кадра, а кадр РАСТЁТ ещё до
   события load — <img> получает свои размеры с первых байтов картинки, и
   центр уезжает вниз вместе со спиннером (FR-PRC12d держал только скачок в
   момент исчезновения). Теперь якорь фиксированный: top:6rem — центр
   12rem-кадра is-loading, от высоты содержимого не зависит. */
.dg-frame .dg-load { position: absolute; left: 50%; top: 6rem;
  transform: translate(-50%, -50%); z-index: 1;
  animation-name: spinCentered; }
@keyframes spinCentered {
  from { transform: translate(-50%, -50%) rotate(0deg); }
  to { transform: translate(-50%, -50%) rotate(360deg); } }
/* FR-PRC12d: пока картинки нет, кадр держит СВОЮ высоту. Раньше он был
   min-height:4.5rem, спиннер стоял в его центре, а с приходом <img> кадр
   разом вырастал до ~46vh — спиннер «улетал» вниз перед тем, как исчезнуть
   (пользователь: «значок загрузки куда-то улетает»). Класс снимается тем же
   обработчиком, что убирает спиннер. */
.dg-frame.is-loading { min-height: 12rem; }
.dg-frame img { width: 100%; height: auto; display: block; }
/* FR-PRC12: схема «отдалена» — компактный предпросмотр, клик увеличивает;
   справа сверху на рамке — кнопка «Скачать PNG» */
.dg-frame.compact { position: relative; overflow: hidden; }
.dg-frame.compact img { max-height: 46vh; width: auto; max-width: 100%;
  margin: 0 auto; object-fit: contain; cursor: zoom-in; }
/* FR-PRC12: скачать диаграмму — только иконка (без «PNG» и без кружка/фона),
   чуть крупнее; клик по всей карточке диаграммы её увеличивает */
.dg-frame.compact[data-dg-zoom] { cursor: zoom-in; }
.dg-dl { position: absolute; top: 0.7rem; right: 0.9rem; z-index: 5;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 20px; color: var(--dim); background: transparent; border: 0;
  text-decoration: none; transition: color 0.2s ease; cursor: pointer; }@media (hover: hover) { .dg-dl:hover { color: var(--purple-l); } }
/* лайтбокс диаграммы: крупный просмотр со скроллом (FR-PRC12) */
.dg-lightbox { position: fixed; inset: 0; z-index: 90;
  background: rgba(0,0,0,0.86); }
.dg-lightbox[hidden] { display: none; }
/* FR-PRC12f: пока лайтбокс открыт, фон замораживается — жесты и клавиши,
   не съеденные внутренним скроллером, крутили страницу под зумом в конец */
html.lb-open, html.lb-open body { overflow: hidden; }
html.lb-open .panel .scroll { overflow: hidden; }
/* FR-PRC12c: пан «рукой» — зажал и тащишь; во время перетаскивания grabbing */
/* FR-PRC12g (владелец 2026-08-02: «при увеличении картинка не двигается
   влево-вправо, вверх-вниз двигается ограниченно»): центровка флексом
   (justify-content/align-items: center) ОБРЕЗАЕТ прокрутку — переполнение
   уходит в обе стороны, а scrollLeft/scrollTop не бывают отрицательными, и
   левый/верхний край схемы недостижим ни мышью, ни пальцем. Лечится
   центровкой через `margin: auto` на самой картинке: пока она меньше поля —
   стоит по центру, как только больше — авто-поля схлопываются в 0 и обе оси
   прокручиваются целиком. touch-action: none — пан/зум ведёт наш JS. */
.dg-lb-scroll { position: absolute; inset: 0; overflow: auto;
  overscroll-behavior: contain;  /* докрутка не передаётся фону (FR-PRC12f) */
  display: flex;
  padding: 3.5rem 1.5rem 1.5rem; touch-action: none; cursor: grab; }
.dg-lb-scroll.dg-grabbing { cursor: grabbing; }
.dg-lb-scroll.dg-grabbing img { cursor: grabbing; }
/* FR-PRC12b (№4): ширину картинки задаёт JS (data-driven зум); базовая = вписать */
.dg-lb-scroll img { max-width: none; width: min(1400px, 96vw); flex: 0 0 auto;
  height: auto; margin: auto; background: #0b0b10; border-radius: 1rem; padding: 1rem;
  cursor: grab; user-select: none; -webkit-user-select: none;
  -webkit-user-drag: none; }
html.light-cab .dg-lb-scroll img { background: #ffffff; }
.dg-lb-close { position: absolute; top: 1rem; right: 1.2rem; z-index: 5;
  width: 2.6rem; height: 2.6rem; border-radius: 999px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text); cursor: pointer; font-size: 1rem; }@media (hover: hover) { .dg-lb-close:hover { border-color: var(--purple); color: var(--purple-l); } }
/* FR-PRC12b: кнопки зума схемы — снизу по центру, крупные (удобно на телефоне) */
.dg-lb-zoom { position: absolute; left: 50%; bottom: 1.1rem; transform: translateX(-50%);
  z-index: 5; display: flex; gap: 0.5rem; background: var(--surface);
  border: 1px solid var(--border); border-radius: 999px; padding: 0.35rem; }
.dg-lb-zoom button { width: 2.8rem; height: 2.8rem; border-radius: 999px; border: 0;
  background: transparent; color: var(--text); cursor: pointer; font-size: 1rem; }
.dg-lb-zoom button:active { background: rgba(136,84,243,0.22); color: var(--purple-l); }

/* ===== Дорожная карта (FR-SR8/FR-SR9). От прежней карты-таймлайна остались
   только цвета шагов (.road-step / .road-step.edu — FR-SR9 ред. 3) и виджет
   приоритетов; карточки .road-item/.road-card, теги, горизонты и
   «Подготовительные работы» сняты вместе с их разметкой (FR-UXI-90; чистка
   батча 4 — NFR-UXI-42). Сама карта батча 3 — блок B3-ROADMAP ниже */
.road-step { flex: 0 0 auto; width: 1.6rem; height: 1.6rem; border-radius: 0.5rem;
  background: var(--purple); color: #fff; display: inline-flex; align-items: center;
  justify-content: center; font-size: 12px; font-weight: 700; }
/* FR-SR9: обучение — ОРАНЖЕВОЕ (агенты остаются фиолетовыми) */
.road-step.edu { background: var(--orange); }
/* FR-SR8: виджет приоритета дорожной карты (первый вход/настройки) — ПО ЦЕНТРУ */
.prio-widget { margin-top: 1rem; max-width: 40rem; margin-left: auto; margin-right: auto; }
.prio-title { margin: 0 0 0.4rem; font-size: 17px; color: var(--heading); text-align: center; }
.prio-list { display: flex; flex-direction: column; gap: 0.6rem; }
.prio-item { display: flex; align-items: center; gap: 0.85rem; width: 100%;
  text-align: left; padding: 0.85rem 1.05rem; border-radius: 0.9rem;
  border: 1px solid var(--card-border); background: var(--card); color: var(--text);
  font: inherit; font-size: 14.5px; cursor: pointer; transition: background-image 0.2s ease; }
@media (hover: hover) { .prio-item:hover { background-image: linear-gradient(var(--hover), var(--hover)); } }
.prio-item.on { border-color: var(--purple); }
.prio-rank { flex: 0 0 auto; width: 1.7rem; height: 1.7rem; border-radius: 0.5rem;
  display: inline-flex; align-items: center; justify-content: center; font-weight: 700;
  font-size: 13px; border: 1px solid var(--border); color: var(--dim); }
.prio-item.on .prio-rank { background: var(--purple); border-color: var(--purple); color: #fff; }
.prio-widget .drawer-cta { margin-top: 1.3rem; }
/* FR-PRC13: ссылка на процесс в карточке агента — можно уйти в процесс */
.drawer-proc-link { display: inline-flex; align-items: center; gap: 0.55rem;
  width: 100%; text-align: left; background: var(--surface);
  border: 1px solid var(--border); border-radius: 0.7rem; padding: 0.7rem 0.9rem;
  color: var(--text); font-family: inherit; font-size: 13.5px; cursor: pointer;
  transition: background-image 0.2s ease; }@media (hover: hover) { .drawer-proc-link:hover { background-image: linear-gradient(var(--hover), var(--hover)); } }
.drawer-proc-link i:first-child { color: var(--dim); }
.drawer-proc-link i:last-child { margin-left: auto; font-size: 11px; }

/* карточки-точки: что переводим в ИИ (мультивыбор) */
.point-cards { display: flex; flex-direction: column; gap: 0.6rem; }
.point-card { display: grid; grid-template-columns: 1.6rem 1fr; gap: 0.8rem;
  align-items: flex-start; text-align: left; background: var(--surface);
  border: 1px solid var(--border); border-radius: 0.8rem; padding: 0.85rem 1rem;
  cursor: pointer; font-family: inherit; color: var(--text); transition: all 0.2s ease; }
.point-card .point-check { width: 1.35rem; height: 1.35rem; border-radius: 0.4rem;
  border: 1px solid var(--border); display: inline-flex; align-items: center;
  justify-content: center; font-size: 10px; color: transparent; margin-top: 0.1rem; }
.point-card.on { border-color: var(--purple); }
.point-card.on .point-check { background: var(--purple); border-color: var(--purple); color: #fff; }
.point-card .point-text { font-size: 13.5px; line-height: 1.5; }
/* FR-PRC11 (#112): короткое название операции — фиолетовым овалом СВЕРХУ */
.point-card .point-op { display: inline-block; align-self: flex-start;
  background: var(--purple); color: #fff; font-size: 11.5px; font-weight: 600;
  line-height: 1.2; padding: 0.2rem 0.65rem; border-radius: 999px;
  margin-bottom: 0.4rem; }
.point-card .point-desc { display: block; }
.point-card .point-text em { display: block; font-style: normal; color: var(--dim);
  font-size: 12px; margin-top: 0.25rem; }
/* FR-PRC11: архитектура LLM-вызовов агента на карточке точки */
.point-card .llm-chain { display: block; font-size: 11.5px; line-height: 1.5;
  color: var(--purple-l); margin-top: 0.35rem; }
.point-card .llm-chain i { font-size: 10px; margin-right: 0.3rem; }

/* FR-PRC10: роль человека — по одной операции, варианты БЕЗ лишней обёртки:
   просто строки с эмодзи, именем роли и конкретной обязанностью */
.role-picks { display: flex; flex-direction: column; gap: 0.55rem; }
.role-pick { display: grid; grid-template-columns: 2rem 1fr; gap: 0.7rem;
  align-items: flex-start; text-align: left; background: var(--card);
  border: 1px solid var(--card-border); border-radius: 0.8rem; padding: 0.8rem 1rem;
  cursor: pointer; font-family: inherit; color: var(--text);
  transition: background-image 0.2s ease; width: 100%; }@media (hover: hover) { .role-pick:hover { background-image: linear-gradient(var(--hover), var(--hover)); } }
.role-pick.rec { border-color: rgba(136,84,243,0.55); }
.role-pick .role-emoji { font-size: 1.25rem; line-height: 1.3; }
.role-pick .role-body b { display: block; font-size: 13px; color: var(--heading); }
.role-pick .role-body b .role-rec { font-style: normal; font-weight: 700;
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--purple-l); margin-left: 0.4rem; }
.role-pick .role-body > span { display: block; font-size: 12px; color: var(--dim);
  margin-top: 0.2rem; line-height: 1.5; }
/* строка «операция — роль» в ленте + карандаш для правки (FR-PRC10) */
.log-row.role-row .log-bubble { display: inline-flex; align-items: center;
  gap: 0.6rem; }
.log-edit { border: 0; background: transparent; color: var(--dim);
  cursor: pointer; padding: 0.15rem 0.25rem; font-size: 12px;
  transition: color 0.2s ease; }@media (hover: hover) { .log-edit:hover { color: var(--purple-l); } }
.status-chip.error { color: #f87171; border-color: rgba(248,113,113,0.4); }
.spinner { width: 0.85rem; height: 0.85rem; border-radius: 999px; border: 2px solid transparent;
  border-top-color: currentColor; border-right-color: currentColor; animation: spin 0.8s linear infinite; display: inline-block; }
/* AS-IS/TO-BE в блоке процесса — во всю ширину, весь текст схем читается */
.proc-diagrams { display: grid; grid-template-columns: 1fr; gap: 1rem; margin-top: 0.9rem; }
.proc-diagrams img { width: 100%; border-radius: 0.7rem; background: #0d0d12; border: 1px solid var(--border);
  display: block; padding: 0.5rem; }
.proc-diagrams .dg-title { font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--dim); margin-bottom: 0.4rem; }
/* FR-W50g: полотно процесса ВНУТРИ страницы процесса — врезка на всю ширину
   колонки. Высота фиксированная: полотно внутри себя тянется на 100% кадра и
   само вписывает схему, поэтому «резиновая» высота ему не нужна, а страница
   без неё схлопнула бы кадр в ноль. Панорама и зум — внутри кадра. */
.proc-canvas { margin-top: 0.9rem; position: relative; }
.canvas-frame { display: block; width: 100%; height: min(58vh, 520px);
  border: 1px solid var(--border); border-radius: 0.9rem; background: #0d0d12; }
.canvas-frame[hidden] { display: none; }
/* FR-W50g ред. 2 (B12, тур 2026-09-06): пока врезка полотна не сказала
   `canvas:ready`, владелец видел ПУСТУЮ серую рамку — ни схемы, ни признака
   работы; на главном артефакте продукта это читается как «сломалось».
   Показываем то же, что и везде на ожидании: крутилку и одну строку. */
.proc-canvas .canvas-wait { position: absolute; inset: 0; display: none;
  align-items: center; justify-content: center; gap: 0.5rem;
  color: var(--dim); font-size: 12px; pointer-events: none; }
.proc-canvas.loading .canvas-wait { display: flex; }
/* FR-UXI-165 (свежий взгляд 2026-09-07, #33): врезка ответила ошибкой
   (canvas:error) — вместо пустой рамки текст по центру, рамка остаётся
   местом схемы (visibility, а не display — высота кадра не схлопывается). */
.proc-canvas .canvas-err { position: absolute; inset: 0; display: none;
  align-items: center; justify-content: center; text-align: center;
  padding: 1rem 1.5rem; color: var(--dim); font-size: 13px; line-height: 1.5;
  pointer-events: none; }
.proc-canvas.error .canvas-err { display: flex; }
.proc-canvas.error .canvas-frame { visibility: hidden; }
.proc-canvas.error .canvas-wait { display: none; }
@media (max-width: 640px) { .canvas-frame { height: min(58vh, 420px); } }

.agent-chips { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.8rem; }
.chip-agent { border: 1px solid rgba(136,84,243,0.4); color: #c9b1ff; border-radius: 999px;
  padding: 0.28rem 0.7rem; font-size: 10.5px; }

@media (max-width: 640px) {
  .form.inline { flex-direction: column; }
}

/* ===== Скейлинг больших экранов (FR-W9/FR-W18) — через КОРНЕВОЙ ШРИФТ, а не
   `zoom`. Свойство zoom на body НЕ согласовано со 100dvh/fixed: при уменьшении
   масштаба браузера (50–70%) CSS-вьюпорт становится широким, включался zoom
   1.15–1.5 — и 100dvh-панель квиза физически растягивалась за экран, заголовок
   вопроса уезжал ПОД фиксированную кнопку шапки (наложение) и за верхний край.
   Rem-скейл масштабирует те же пропорции, но раскладка (100dvh, fixed, vw)
   остаётся согласованной — наложений нет НИ НА КАКОМ масштабе браузера.
   App-режим (кабинет) остаётся 1:1, как и раньше был без zoom (NFR-W10/FR-PRC8)
   — хук html.app-root ставит applyMode() (класс на <html>, т.к. rem привязан
   к корню, а body-класса для этого недостаточно). */
@media (min-width: 1600px) { html:not(.app-root) { font-size: 18.4px; } }
@media (min-width: 1900px) { html:not(.app-root) { font-size: 20.8px; } }
@media (min-width: 2300px) { html:not(.app-root) { font-size: 24px; } }
/* FR-W18c: множитель ШИРИНЫ отдельной переменной — тот же, что задаёт масштаб
   главной andre.technology. Нужен там, где размер обязан зависеть ТОЛЬКО от
   ширины экрана и не реагировать на высоту окна (бренд-блок шапки). */
:root { --ui-scale: 1; }
@media (min-width: 1600px) { :root { --ui-scale: 1.15; } }
@media (min-width: 1900px) { :root { --ui-scale: 1.3; } }
@media (min-width: 2300px) { :root { --ui-scale: 1.5; } }
/* Кабинет — всегда 1:1 (NFR-W10/FR-PRC8): множитель там нейтрален, иначе
   кнопки и подписи кабинета росли бы на широком мониторе вместе с витриной. */
html.app-root { --ui-scale: 1; }
/* FR-W19b: НЕВЫСОКОЕ десктоп-окно (пользователь подужал браузер) — корневой
   шрифт ужимается ступенями, тест/формы влезают БЕЗ обрезки кнопок при любой
   форме окна. Правила стоят ПОСЛЕ ширинных (FR-W18) и при коротком окне
   перекрывают их (та же специфичность, позже в файле). Мобилку не трогаем
   (min-width:1024). */
@media (min-width: 1024px) and (max-height: 899px) {
  html:not(.app-root) { font-size: 14.5px; }
}
@media (min-width: 1024px) and (max-height: 749px) {
  html:not(.app-root) { font-size: 12.5px; }
}
/* FR-W18c (жалоба владельца: «расположение лого сверху отличается и размеры
   на некоторых устройствах и мониторах»): БРЕНД-БЛОК не подчиняется ужатию
   FR-W19b. Ужатие корневого шрифта нужно контенту (чтобы тест влезал в низкое
   окно) — но лого и отступ шапки от высоты окна зависеть не должны: на
   andre.technology они масштабируются ТОЛЬКО по ширине. Замер против эталона
   показывал расхождение 5.4px на ноутбуке 1366×768 и 22.7px на окне 1920×860.
   Значения = эталонные 2rem/3.6rem при корне 16px, умноженные на ширинный
   множитель. Кабинет (app-root) не трогаем — там масштаб всегда 1:1. */
@media (min-width: 1024px) {
  html:not(.app-root) header { padding: calc(32px * var(--ui-scale)); }
  html:not(.app-root) .logo-img { width: calc(57.6px * var(--ui-scale));
    height: calc(57.6px * var(--ui-scale)); }
}
/* FR-W19d (жалоба владельца 2026-07-26: «на маке лого, бейдж, справа все
   пункты и кнопки ВСЁ РАВНО меньше, чем в andre-ait-page»): предыдущая правка
   развязала с высотой окна только КЕГЛИ, а коробочные метрики витрины
   (паддинги, гэпы, max-width, высота кнопки) остались в rem — и ужимались
   вместе с корневым шрифтом. Замер (tools/compare_with_reference.py):
   1512×982 → 1512×860 строка списка 44.6→37.7, колонка 480→391.5, кнопка
   53.8→46.4; 1920×1080 → 1920×860 ещё и кегль 20.8→14.5. Эталон в тот же
   момент всё УВЕЛИЧИВАЕТ (zoom по ширине) — отсюда «меньше».
   Теперь витрина целиком считается от ШИРИНЫ: px × --ui-scale. Значения =
   те, что были на просторном окне (владелец назвал их «как нормально»),
   поэтому на высоком окне вид не меняется, а на низком больше не сдувается.
   Блок стоит ПОСЛЕ ужатия FR-W19b и после ширинных/высотных блоков лендинга —
   перекрывает их для витрины и только для неё (тест/формы не задеты). */
@media (min-width: 1024px) {
  /* колонка экрана — тоже от ширины: её rem-ограничение (32rem) при корне
     14.5px давало 464px вместо 512, и список 01–07 сужался вместе с ней */
  html:not(.app-root) .screen:not(.wide) {
    max-width: calc(512px * var(--ui-scale)); gap: calc(19.2px * var(--ui-scale)); }
  html:not(.app-root) .hero-size { font-size: calc(44.8px * var(--ui-scale)); }
  html:not(.app-root) .points-list { max-width: calc(480px * var(--ui-scale)); }
  html:not(.app-root) .points-list li {
    padding: calc(12.8px * var(--ui-scale)) calc(3.2px * var(--ui-scale));
    gap: calc(16px * var(--ui-scale)); }
  html:not(.app-root) .points-list b { font-size: calc(13.5px * var(--ui-scale)); }
  html:not(.app-root) .points-list span { font-size: calc(15.5px * var(--ui-scale)); }
  html:not(.app-root) .btn-white.big { font-size: calc(13px * var(--ui-scale));
    padding: calc(18.4px * var(--ui-scale)) calc(38.4px * var(--ui-scale));
    gap: calc(12px * var(--ui-scale)); }
  html:not(.app-root) .speaker { padding: calc(6px * var(--ui-scale))
      calc(6px * var(--ui-scale)) calc(6px * var(--ui-scale))
      calc(14.4px * var(--ui-scale)); gap: calc(9.6px * var(--ui-scale)); }
  html:not(.app-root) .speaker-inner { gap: calc(8px * var(--ui-scale)); }
  /* высоту пилюли бейджа задаёт КРУЖОК МИКРОФОНА — он оставался в rem и
     ужимался (36 → 32.6 → 28.1px), поэтому бейдж выглядел мельче эталонного
     даже при совпадающих кеглях (аудит замером против andre-ait-page) */
  html:not(.app-root) .mic-btn { width: calc(36px * var(--ui-scale));
    height: calc(36px * var(--ui-scale)); }
  html:not(.app-root) .mic-btn i { font-size: calc(11px * var(--ui-scale)); }
  /* правая колонка: отступы и ритм — как у эталона (2rem / 1.75rem / 0.25rem
     и gap 1.75rem при корне 16px), но от ширины, а не от высоты окна */
  html:not(.app-root) .panel { padding: 0 calc(32px * var(--ui-scale)); }
  html:not(.app-root) .scroll { gap: calc(16px * var(--ui-scale));
    padding: calc(28px * var(--ui-scale)) calc(4px * var(--ui-scale));
    /* резерв под фикс-шапку тем же множителем, что и сама шапка: иначе
       выросшая витрина не влезает в бокс прокрутки на низком окне */
    max-height: calc(100vh - calc(176px * var(--ui-scale)));   /* NFR-FE8 */
    max-height: calc(100dvh - calc(176px * var(--ui-scale))); }
  html:not(.app-root) .header-row { min-height: calc(57.6px * var(--ui-scale)); }
  /* FR-W19e: кнопка шапки — ровно как у эталона: у него на ≥1024 задана
     ФИКСИРОВАННАЯ высота 2.85rem (=45.6px) и padding 0 1.4rem, а у нас была
     вертикальная набивка 0.72rem → замер давал 39 против 45.6 (и 43.5 против
     52.4 на 1728, 49.9 против 59.3 на 1920 — кнопка стабильно ниже). */
  html:not(.app-root) .cta { height: calc(45.6px * var(--ui-scale));
    box-sizing: border-box; padding: 0 calc(22.4px * var(--ui-scale));
    font-size: calc(12.5px * var(--ui-scale)); letter-spacing: 0.15em;
    gap: calc(8.8px * var(--ui-scale)); }
}
/* те же две ступени по ширине, что у эталона: на узком десктопе кнопка
   компактнее набивкой/трекингом (подпись влезает в шапку рядом с лого), но
   КЕГЛЬ не ужимается — фидбек владельца 2026-08-06: на компе шрифт не
   должен быть мельче мобильного (потолок clamp 12.5px) */
@media (min-width: 1024px) and (max-width: 1319px) {
  html:not(.app-root) .cta { padding: 0 calc(15.2px * var(--ui-scale));
    font-size: calc(12.5px * var(--ui-scale)); letter-spacing: 0.08em;
    gap: calc(6.4px * var(--ui-scale)); }
}
@media (min-width: 1320px) and (max-width: 1479px) {
  html:not(.app-root) .cta { padding: 0 calc(18.4px * var(--ui-scale));
    font-size: calc(12.5px * var(--ui-scale)); letter-spacing: 0.12em;
    gap: calc(8px * var(--ui-scale)); }
}
/* FR-W65 (B16, аудит 04-result 1440×900: низ «Полного отчёта» срезан при 85px
   чёрного под ним). Колонка результата центрировалась во ВСЁМ окне
   (.content-layer justify-content:center) с резервом 176px «на шапку»,
   поделённым центровкой пополам: бокс .scroll стоял с 88px и кончался на 812,
   а содержимое результата (703px + поля) в него не влезало — кнопки резались
   и уезжали в прокрутку бокса, хотя ниже оставалось место. Теперь колонка
   центрируется в области ПОД лого (шапка 32px + лого 57.6px, тем же
   ширинным множителем, что и сама шапка FR-W18c), а бокс ленты может занять
   эту область целиком до 12px от низа окна; поля бокса — 12px вместо 28.
   Содержимое выше области по-прежнему прокручивается внутри бокса
   (overflow-y:auto). Мобильные правила FR-W13/FR-W16f (≤1023px) не задеты.
   NFR-FE8: dvh с vh-фолбэком. */
@media (min-width: 1024px) {
  html:not(.app-root) body.on-result .content-layer {
    padding-top: calc(89.6px * var(--ui-scale)); padding-bottom: calc(12px * var(--ui-scale)); }
  html:not(.app-root) body.on-result .scroll {
    padding-top: calc(12px * var(--ui-scale)); padding-bottom: calc(12px * var(--ui-scale));
    max-height: calc(100vh - 101.6px * var(--ui-scale));
    max-height: calc(100dvh - 101.6px * var(--ui-scale)); }
}
/* FR-W65 (продолжение): метрики результата заданы в px (кольцо 170, кнопки
   18.4px набивки) и на ужатие корня FR-W19b не отзывались — на 1280×720
   содержимое оставалось 705px при 594 доступных. Две ступени уплотнения по
   высоте окна — те же пороги, что у корневого шрифта (899/749px): кольцо,
   зазоры экрана, абзац и набивка кнопок ужимаются, кегль подписей не ниже
   11px. Полоски областей из этого списка ушли вместе с блоком (FR-W58
   ред. 3, 2026-09-09) — экран стал ниже, но ступени остаются: на 749px
   кольцо и абзац всё ещё не влезали бы без них. */
@media (min-width: 1024px) and (max-height: 899px) {
  html:not(.app-root) body.on-result .result-ring { width: 130px; height: 130px; }
  html:not(.app-root) body.on-result .result-ring .ring-value { font-size: 26px; }
  html:not(.app-root) body.on-result .screen:not(.wide) { gap: calc(12px * var(--ui-scale)); }
  html:not(.app-root) body.on-result .desc { font-size: 14px; }
  html:not(.app-root) body.on-result .btn-white.big {
    padding-top: calc(14px * var(--ui-scale)); padding-bottom: calc(14px * var(--ui-scale)); }
}
@media (min-width: 1024px) and (max-height: 749px) {
  html:not(.app-root) body.on-result .result-ring { width: 110px; height: 110px; }
  html:not(.app-root) body.on-result .result-ring .ring-value { font-size: 22px; }
  html:not(.app-root) body.on-result .screen:not(.wide) { gap: calc(10px * var(--ui-scale)); }
  html:not(.app-root) body.on-result .desc { font-size: 13.5px; line-height: 1.5; }
  html:not(.app-root) body.on-result .result-actions { gap: 0.6rem; }
  html:not(.app-root) body.on-result .btn-white.big {
    padding-top: calc(11px * var(--ui-scale)); padding-bottom: calc(11px * var(--ui-scale)); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001s !important; animation-iteration-count: 1 !important; transition-duration: 0s !important; }
}

/* ===== UX-эксперимент (SPEC-UX-INTERVIEW) =====
   Виджеты интервью (process_list / goal_trigger / step_list / op_card / cta5),
   экран «Артефакты», оргструктура и настройки систем. Канон NFR-UXI-2:
   карточки var(--surface)/var(--bg) с радиусом 1.1rem и рамкой var(--border)
   БЕЗ теней, пилюли 999px, предзаполнение — var(--dim), hover — рамка
   var(--purple); светлая тема кабинета работает через те же токены. */

/* вводная строка виджета списка/CTA-5 */
.ux-title { font-size: 13.5px; line-height: 1.6; color: var(--text);
  margin: 0 0 0.8rem; }

/* карточки процессов/шагов — вертикальный список, перетаскиваются (FR-UXI-1/5) */
.ux-cards { display: flex; flex-direction: column; gap: 0.6rem; }
.ux-card { display: flex; align-items: center; gap: 0.8rem; width: 100%;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: 1.1rem; padding: 0.7rem 0.9rem; cursor: grab;
  -webkit-user-select: none; user-select: none; touch-action: pan-y;
  transition: border-color 0.2s ease, opacity 0.2s ease; }
@media (hover: hover) { .ux-card:hover { background-image: linear-gradient(var(--hover), var(--hover)); } }
/* FR-UXI-1 ред. 2: оригинал во время переноса сильно приглушён — «взятую»
   карточку показывает клон-призрак, а это лишь место, куда она вернётся */
.ux-card.dragging { border-color: var(--purple); opacity: 0.35; cursor: grabbing; }
body.ux-dragging { cursor: grabbing; }
/* клон-призрак: летит за курсором/пальцем (position/left/top/width/transform
   ставит JS), слегка увеличен и наклонён, событий не ловит */
.ux-ghost { position: fixed; z-index: 1000; opacity: 0.9; pointer-events: none;
  will-change: transform; }
/* место вставки: рамка + скруглённая полоса-градиент purple→orange над карточкой */
.ux-drop-hint { position: relative; border-color: var(--purple); }
.ux-drop-hint:before { content: ""; position: absolute; left: 0.3rem;
  right: 0.3rem; top: -0.38rem; height: 2px; border-radius: 999px;
  background: linear-gradient(90deg, var(--purple), var(--orange)); }
.ux-card .tile-ico { width: 2.2rem; height: 2.2rem; border-radius: 0.7rem;
  flex: 0 0 auto; font-size: 13px; }
.ux-card-name { flex: 1 1 auto; min-width: 0; font-size: 13.5px;
  font-weight: 600; color: var(--heading); line-height: 1.4; }
/* NFR-UXI-11: крестик 16×11 px — самая маленькая цель интерфейса, а
   подпись прямо зовёт им пользоваться; прозрачный хит-эриа доводит зону
   нажатия до ≥44 px, не меняя видимый размер */
.ux-card-del, .ux-cta-del { position: relative; border: 0; background: transparent; color: var(--dim);
  cursor: pointer; padding: 0.35rem 0.5rem; font-size: 13px; border-radius: 999px;
  flex: 0 0 auto; transition: color 0.2s ease; }@media (hover: hover) { .ux-card-del:hover, .ux-cta-del:hover { color: #f87171; } }
/* FR-UXI-197: карандаш правки имени — рядом с крестиком, той же величины;
   акцент фиолетовый (правка), у крестика — красный (удаление). Зоны нажатия
   РАЗВЕДЕНЫ (ревью батча 23: расширение крестика перекрывало карандаш, и
   промах удалял процесс вместо правки имени) */
.ux-card-ren { position: relative; border: 0; background: transparent; color: var(--dim);
  cursor: pointer; padding: 0.45rem 0.55rem; font-size: 12px; border-radius: 999px;
  flex: 0 0 auto; transition: color 0.2s ease; }
@media (hover: hover) { .ux-card-ren:hover { color: var(--purple); } }
/* поле правки занимает место имени; высота — как у иконки карточки, иначе
   карточка подпрыгивает при входе в правку и список уезжает под курсором */
.ux-card-input { flex: 1 1 auto; min-width: 0; font-size: 13.5px;
  height: 2.2rem; padding: 0.2rem 0.6rem; }
.ux-card.ux-card-renaming { cursor: default; }
/* на телефоне в поле должно помещаться имя, а не его треть: иконка на
   время правки уходит, поле забирает её место */
@media (max-width: 520px) {
  .ux-card.ux-card-renaming .tile-ico { display: none; }
  .ux-card.ux-card-renaming { gap: 0.5rem; padding-left: 0.7rem; }
}
.ux-add { margin-top: 0.7rem; }
.ux-add-row { display: flex; gap: 0.55rem; margin-top: 0.7rem; align-items: center; }
.ux-add-row .input { flex: 1 1 auto; }

/* галочки-подтверждения — маленькие круглые (по образцу .iv2-yes/.ctrl-round) */
.ux-ok, .ux-cancel { width: 2.1rem; height: 2.1rem; border-radius: 999px;
  border: 1px solid var(--border); background: transparent; color: var(--dim);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; font-size: 12px; flex: 0 0 auto; transition: all 0.2s ease; }@media (hover: hover) { .ux-ok:hover, .ux-cancel:hover { border-color: var(--purple); color: var(--purple-l); } }
.ux-ok.on { background: linear-gradient(120deg, var(--purple), var(--orange));
  color: #fff; border-color: transparent; }

/* блоки-секции: цель/триггер (FR-UXI-3) и пять секций op_card (FR-UXI-6) */
.ux-sec { background: var(--bg); border: 1px solid var(--border);
  border-radius: 1.1rem; padding: 0.85rem 1rem; margin-top: 0.7rem; }
/* ред. 4 (скрин владельца 2026-08-08: иконка оказалась НАД текстом):
   шапка секции — ОДНА строка (nowrap), иконка не схлопывается и всегда
   слева, вопрос переносится по словам внутри своей колонки (min-width: 0) */
.ux-sec-head { display: flex; align-items: center; gap: 0.6rem;
  flex-wrap: nowrap; }
.ux-sec-ico { width: 2rem; height: 2rem; border-radius: 0.6rem; flex: 0 0 auto;
  flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(136,84,243,0.16); color: var(--purple-l); font-size: 12px; }
.ux-sec .ux-sec-ico, .ux-sec.alt .ux-sec-ico { background: var(--ctrl-bg); color: var(--text); }
.ux-sec-q { flex: 1 1 auto; min-width: 0; font-size: 13px; font-weight: 700;
  color: var(--heading); overflow-wrap: break-word; }
.ux-none { font-size: 11px; padding: 0.4rem 0.8rem; }
.ux-none.on { border-color: var(--orange); color: var(--orange-l); }

/* поля виджетов; догадка модели — В value серым (FR-UXI-3/6 ред. 5, класс
   .ux-guess до первого ввода): фокус выделяет всё, печать заменяет, клик
   правит; стёртая догадка остаётся серой подсказкой в placeholder.
   Ред. 6: мышью поле НЕ тянется (resize: none) — textarea растёт сама по
   мере ввода (uxAutosize: height=auto → scrollHeight, потолок ~200px) */
.ux-field { width: 100%; margin-top: 0.6rem; background: var(--surface);
  border: 1px solid var(--border); border-radius: 0.8rem; color: var(--text);
  font-family: inherit; font-size: 13.5px; line-height: 1.55;
  padding: 0.6rem 0.8rem; resize: none; box-sizing: border-box;
  overflow-y: auto; }
textarea.ux-field { min-height: 3.1rem; }
.ux-field:focus { outline: none; border-color: var(--purple); }
.ux-field:disabled { opacity: 0.5; resize: none; }
/* FR-UXI-32 (ред. 2 NFR-UXI-2): догадка — ОБЫЧНЫМ цветом текста с меткой
   «догадка — поправьте»; серый var(--dim) остаётся только настоящему
   плейсхолдеру — прежде они были неотличимы */
.ux-field.ux-guess { color: var(--text); }
.ux-field::placeholder { color: var(--dim); opacity: 1; }

/* шапка карточки операции: иконка + имя + «Оргструктура» справа (FR-UXI-6) */
.ux-op-head { display: flex; align-items: center; gap: 0.7rem; margin: 0.2rem 0 0.3rem; }
.ux-op-head .tile-ico { width: 2.4rem; height: 2.4rem; }
.ux-op-name { flex: 1 1 auto; min-width: 0; font-weight: 700; font-size: 14.5px;
  color: var(--heading); }
.ux-top-btn { font-size: 11px; padding: 0.45rem 0.9rem; flex: 0 0 auto; }

/* ленты-карусели выбора (системы/роли/артефакты/процессы) — чипы-пилюли в
   одну строку, листаются слева направо; скроллбар скрыт (паттерн
   .composer-input), короткая лента видна сразу (FR-UXI-6 ред. 2) */
.ux-dd { display: flex; flex-wrap: nowrap; gap: 0.45rem; margin-top: 0.55rem;
  overflow-x: auto; scroll-behavior: smooth; padding: 0.15rem 0;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
  /* FR-UXI-6 ред. 4: обрезающаяся лента гаснет плавным градиентом справа */
  -webkit-mask-image: linear-gradient(to right, #000 0,
    #000 calc(100% - 32px), transparent 100%);
  mask-image: linear-gradient(to right, #000 0,
    #000 calc(100% - 32px), transparent 100%); }
.ux-dd::-webkit-scrollbar { display: none; }
.ux-dd-item { flex: 0 0 auto; white-space: nowrap;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text); border-radius: 999px; padding: 0.35rem 0.85rem;
  font-family: inherit; font-size: 12px; cursor: pointer;
  transition: border-color 0.2s ease, background 0.2s ease; }@media (hover: hover) { .ux-dd-item:hover { background-image: linear-gradient(var(--hover), var(--hover)); } }
.ux-dd-item.on { border-color: var(--purple); color: var(--purple-l);
  background: rgba(136,84,243,0.14); }
/* FR-UXI-6 ред. 6: крестик снятия на ВЫБРАННОЙ пилюле одиночного выбора
   (система/роль/триггер) — как у чипов; клик по пилюле снимает выбор */
.ux-dd-item .ux-dd-x { font-size: 10px; }
.ux-chips { display: flex; flex-wrap: wrap; gap: 0.45rem; margin-top: 0.55rem; }
.ux-chip { display: inline-flex; align-items: center; gap: 0.4rem;
  border: 1px solid rgba(136,84,243,0.45); background: rgba(136,84,243,0.10);
  color: var(--purple-l); border-radius: 999px; padding: 0.3rem 0.75rem;
  font-family: inherit; font-size: 12px; cursor: pointer; }
.ux-chip i { font-size: 10px; }
/* ── B17-VECTORS (FR-UXI-196): чипы «из справочника» под полем карточки —
   тот же вид, что у чипов выбора, но это подпись, а не кнопка ── */
.ux-known { display: flex; flex-wrap: wrap; gap: 0.45rem; margin-top: 0.45rem; }
.ux-known .ux-known-chip { cursor: default; color: var(--purple-l); }

/* CTA-5: карточка вопроса гаснет по крестику «не отвечаю» (FR-UXI-12) */
.ux-cta.off { opacity: 0.45; }
/* канон 2026-08-31: пояснение серым под вопросом карточки CTA-5 */
.ux-cta-hint { display: block; color: var(--dim); font-size: 12px;
  font-weight: 400; line-height: 1.45; margin-top: 0.15rem; }

/* FR-UXI-12 ред. 5: эхо отправки CTA-5 — компактные пары «вопрос — ответ»
   с переносами (вопрос серым, ответ обычным), «не отвечаю» — серым
   курсивом; никаких таблиц */
.ux-echo { display: flex; flex-direction: column; gap: 0.35rem; }
.ux-echo .ux-echo-q { color: var(--dim); }
.ux-echo .ux-echo-skip { color: var(--dim); font-style: italic; }

/* FR-UXI-2 ред. 6: эхо подтверждения списка — «Итоговый список:» +
   нумерованные строки; переносы держит pre-line (текст уже через esc) */
.ux-echo-list { white-space: pre-line; }

/* ── экран «Артефакты»: папки-блоки (по образцу .process-grid) ── */
.art-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: 1rem; }
.art-folder { background: var(--card); border: 1px solid var(--card-border);
  border-radius: 1.1rem; padding: 1.1rem 1.2rem; cursor: pointer;
  display: flex; flex-direction: column; gap: 0.55rem; align-items: flex-start;
  transition: background-image 0.2s ease; }
@media (hover: hover) { .art-folder:hover { background-image: linear-gradient(var(--hover), var(--hover)); } }
.art-name { font-weight: 700; font-size: 14px; color: var(--heading); }
.art-count { font-size: 12px; color: var(--dim); }
.art-open-name { margin: 1rem 0 0; font-size: 16px; color: var(--heading); }
.art-open-name i { color: var(--dim); margin-right: 0.4rem; }
/* FR-UXI-13 ред. 6: пунктирная зона компактнее по высоте; подсказка и
   кнопка «Загрузить» — ВНУТРИ пунктира, стопкой по центру (.art-drop-cta) */
.art-files { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 1rem;
  border: 1px dashed var(--border); border-radius: 1.1rem; padding: 0.7rem 1rem;
  transition: border-color 0.2s ease; }
.art-drop-cta { display: flex; flex-direction: column; align-items: center;
  gap: 0.55rem; text-align: center; padding: 0.3rem 0; }
.art-drop-cta .muted { margin: 0; }
.art-file { display: flex; align-items: center; gap: 0.7rem; background: var(--card);
  border: 1px solid var(--card-border); border-radius: 0.8rem; padding: 0.6rem 0.85rem;
  font-size: 13px; color: var(--text); }
.art-file > i:first-child { color: var(--dim); }
.art-file-name { flex: 1 1 auto; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; color: var(--text);
  text-decoration: none; }           /* имя — ссылка на содержимое (FR-UXI-14) */@media (hover: hover) { a.art-file-name:hover { color: var(--heading); text-decoration: underline; } }
.art-file-size { flex: 0 0 auto; color: var(--dim); font-size: 11.5px; }

/* drop-зона подсвечивается рамкой на dragover (FR-UXI-14) */
.ux-dropzone.over, .art-folder.over { border-color: var(--purple); }

/* заголовки ux-экранов (FR-UXI-13/16 ред. 5): «назад» — круглая стрелка
   link-back icon-only В СТРОКЕ заголовка (обёртка .cab-head-left, как на
   экране процесса), отдельной строки-кнопки «Назад» больше нет; строка
   держит прежний воздух до контента */
#roles-body .cab-head, #uxset-body .cab-head { margin-bottom: 1rem; }
.art-open-head { margin: 0.4rem 0 0.2rem; }
.art-open-head .art-open-name { margin: 0; }

/* подпись секции (FR-UXI-16; сам паспорт роли заменён панелью — FR-UXI-81) */
.ux-label { font-size: 11px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--dim); margin-top: 0.6rem; }

/* настройки: список систем строками с крестиками (FR-UXI-15) */
/* B5 (FR-UXI-26 ред. 3): секции по процессам на экранах систем и артефактов */
.ux-proc-sec { border-top: 1px solid var(--border); padding: 0.4rem 0 0.6rem; }
.ux-proc-head { display: flex; align-items: center; gap: 0.7rem; width: 100%; background: transparent;
  border: 0; padding: 0.7rem 0; color: var(--heading); font: inherit; font-weight: 700; font-size: 15px;
  cursor: pointer; text-align: left; }
.ux-proc-ico { color: var(--dim); width: 1.2rem; text-align: center; }
.ux-proc-name { flex: 1 1 auto; min-width: 0; }
.ux-proc-count { color: var(--dim); font-size: 12.5px; font-weight: 500; }
.ux-proc-chev { color: var(--dim); font-size: 12px; transition: transform 0.2s ease; }
.ux-proc-head.closed .ux-proc-chev { transform: rotate(-90deg); }
.ux-proc-body { padding-left: 1.9rem; }
.ux-proc-body.art-grid { padding-left: 1.9rem; }
.sys-ops { display: flex; flex-direction: column; gap: 0.6rem; }
.sys-op-line { display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: center; font-size: 13.5px;
  color: var(--text); padding-left: 0.2rem; }
.sys-op-line > i { color: var(--dim); width: 1rem; }
/* B7 (FR-UXI-162 ред. 2, замер 2026-09-05): предел ширины оставляем — строка
   системы короткая, и растягивать её на 1100px нечитаемо; но БЕЗ центрирования
   блок прижимался влево, а заголовок «Системы» стоял по центру панели: на
   1440px расхождение центров было 269px, на 1280px — 221px. Экран артефактов
   рядом центрован (смещение 0), и разница бросалась в глаза. */
.ux-sys-list { display: flex; flex-direction: column; gap: 0.5rem;
  max-width: 32rem; margin-left: auto; margin-right: auto; }
.ux-sys-row { display: flex; align-items: center; gap: 0.7rem;
  background: var(--card); border: 1px solid var(--card-border);
  border-radius: 0.8rem; padding: 0.6rem 0.85rem; font-size: 13px;
  color: var(--text); }
.ux-sys-row > i { color: var(--dim); }
.ux-sys-row span { flex: 1 1 auto; min-width: 0; }

/* адаптив: на узких экранах карточки и секции — во всю ширину, DnD — тачем.
   Ред. 4: прежние order-перестановки шапки убраны — они роняли иконку НАД
   текст (скрин владельца); иконка всегда слева в той же строке, вопрос
   переносится по словам */
@media (max-width: 640px) {
  .art-grid { grid-template-columns: 1fr; }
  .ux-op-head { flex-wrap: wrap; }
}

/* ── FR-UXI-19: секции сайдбара с шевронами (канон владельца 2026-08-08).
   Заголовок — как .nav-item (иконка + имя), шеврон справа; тело сворачивается
   плавно max-height + opacity, БЕЗ display:none; классы closed ставит
   uxApplySideSecState из localStorage (amx_side_sec) ── */
.side-sec { display: flex; align-items: center; gap: 0.7rem;
  padding: 0.8rem 0.9rem; border-radius: 0.7rem; cursor: pointer;
  color: var(--dim); font-size: 14px; font-weight: 500;
  transition: all 0.2s ease; }@media (hover: hover) { .side-sec:hover { background: var(--hover); color: var(--text); } }
.side-sec > i { width: 1.1rem; text-align: center; font-size: 13px;
  flex-shrink: 0; }
.side-sec-name { flex: 1 1 auto; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.side-sec-chev { flex: 0 0 auto; color: var(--dim); padding: 0.1rem 0.35rem;
  position: relative; }
/* NFR-UXI-11: расширенные зоны нажатия мелких целей */
.ux-card-del::after, .ux-cta-del::after, .side-sec-chev::after {
  content: ""; position: absolute; top: -14px; right: -14px;
  bottom: -14px; left: -14px; }
/* соседние кнопки карточки: крестик расширяется ВПРАВО, карандаш — ВЛЕВО,
   между ними остаётся зазор — промах по одному не срабатывает как другой */
.ux-card-ren::after { content: ""; position: absolute; top: -14px;
  right: -3px; bottom: -14px; left: -12px; }
.ux-card .ux-card-del::after { left: -3px; }
.side-sec-chev i { font-size: 11px; transition: transform 0.2s ease; }
.side-sec.closed .side-sec-chev i { transform: rotate(-90deg); }
/* B5 (FR-UXI-19 ред. 7): элементы раскрытой секции сдвинуты правее заголовка */
.side-sec-body .nav-item { padding-left: 1.9rem; }
.side-sec-body { display: flex; flex-direction: column; gap: 0.4rem;
  padding-left: 0.9rem;   /* ред. 5: тело чуть правее заголовка секции */
  /* FR-UXI-29 ред. 2 (проход 1.6, кейс «ИИ-консалтинг»): у открытой секции
     потолка высоты НЕТ. Прежние 120rem (1920 px) были ровно таким же тихим
     обрезанием, как сжатие флексом: список из двух десятков артефактов
     упирался в 2087 px и терял хвост под overflow:hidden. Свёртка шевроном
     осталась (max-height: 0 у .closed), плавность открытия — цена
     честности: анимировать «0 → none» браузер не умеет. */
  overflow: hidden; max-height: none; opacity: 1;
  transition: opacity 0.2s ease; }
.side-sec-body.closed { max-height: 0; opacity: 0; }
/* FR-UXI-19 ред. 7 (проход эксперимента 1.6, 2026-08-27): .side-scroll —
   флекс-колонка с overflow-y: auto, а флекс-дети по умолчанию СЖИМАЮТСЯ,
   чтобы влезть в контейнер. У .side-sec-body стоит overflow: hidden, поэтому
   на длинных списках (24 артефакта, 12 агентов, 4 процесса) секции молча
   схлопывались: scrollHeight совпадал с clientHeight, прокрутка не
   появлялась, и до половины навигации — включая кнопку «Новый процесс» —
   добраться было НЕЛЬЗЯ. Запрет сжатия возвращает прокрутку. Правило общее
   для v1 и эксперимента: в v1 при длинном списке процессов обрыв был тот же
   (NFR-UXI-4 не нарушен — поведение сайдбара без эксперимента только
   чинится, разметка не меняется). */
.side-scroll > * { flex: 0 0 auto; }

/* FR-UXI-26: «где используется» — связь сущности с процессом и операцией.
   Одна строка на карточке в сетке и подробный список на паспорте/в папке.
   Раньше артефакты, системы и роли лежали плоским перечнем без единой
   ссылки: два десятка папок, и непонятно, к какому процессу что относится. */
.ux-use { font-size: 12px; color: var(--dim); line-height: 1.35;
  margin-top: 0.15rem; overflow: hidden; text-overflow: ellipsis;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.ux-use-box { margin: 0 0 1.1rem; }
.ux-use-list { list-style: none; margin: 0.35rem 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 0.35rem; }
.ux-use-list li { display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 0.5rem; font-size: 13px; }
.ux-use-proc { color: var(--text); font-weight: 500; }
.ux-use-op { color: var(--dim); }
.ux-use-op::before { content: "·"; margin-right: 0.5rem; }
.ux-use-empty { font-size: 13px; margin: 0.35rem 0 0; }
/* FR-UXI-40/42/43: вспышка склеенного дубля, слот связи, «Сохранено»,
   кнопки удаления папки/роли */
.ux-sys-row.flash { outline: 2px solid var(--purple); border-radius: 0.6rem; }
.ux-use-slot { margin-left: 0.5rem; font-size: 10px; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--dim);
  border: 1px solid var(--border); border-radius: 999px; padding: 0.1rem 0.5rem; }
.ux-use-item[data-open-proc] { cursor: pointer; }
.art-del-btn { margin-left: auto; }
.ux-sys-name { flex: 1 1 auto; min-width: 0; display: flex;
  flex-direction: column; }

/* FR-UXI-21 (ред. 3): системы прямо в сайдбаре — строка с крестиком
   удаления, БЕЗ формы добавления (руками заводятся только процессы);
   стиль строк — как .nav-item */
.side-sys-row { display: flex; align-items: center; gap: 0.7rem;
  padding: 0.45rem 0.9rem; font-size: 13px; color: var(--text); }
.side-sys-row > i { color: var(--dim); width: 1.1rem; text-align: center;
  font-size: 12px; flex-shrink: 0; }
.side-sys-row .nav-name { flex: 1 1 auto; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }

/* ── FR-UXI-20: рейка — узкая колонка иконок (референс владельца — боковая
   панель ChatGPT: лого сверху, по иконке на секцию, аватар ЛК снизу).
   Только десктоп и только при overview.ux (класс side-rail ставит applyMode);
   на телефоне рейки нет — панель прячется за значком списка (fa-bars) ── */
@media (min-width: 1024px) {
  body.mode-app.side-open .cab-side { transition: width 0.25s ease; }
  body.mode-app.side-open .content-layer { transition: margin-left 0.25s ease; }
  body.mode-app.side-open header { transition: left 0.25s ease; }
  body.mode-app.side-open.side-rail .cab-side { width: 64px;
    padding-left: 0.4rem; padding-right: 0.4rem; }
  /* контент и шапка сдвигаются на ширину рейки (вместо 280px): в app-режиме
     .content-layer статичен и двигается margin-left, left — для fixed-базы */
  body.mode-app.side-open.side-rail .content-layer { left: 64px;
    margin-left: 64px; }
  body.mode-app.side-open.side-rail header { left: 64px; }
  /* голова рейки (FR-UXI-20 ред. 2): сверху ТО ЖЕ лого AIT (#side-logo),
     уменьшенное до вписывания в 64px (ред. 3: 36px — заметно крупнее иконок
     секций, в колонке 64px с паддингами 0.4rem остаётся воздух); отдельной
     кнопки-стрелки нет — hover по лого показывает значок «раскрыть», клик
     по лого разворачивает */
  body.side-rail .side-head { flex-direction: column; gap: 0.3rem;
    align-items: center; margin: 0.9rem 0 1rem; }
  /* стрелка дублировала клик по лого — в рейке её нет (ред. 2) */
  body.side-rail #side-toggle { display: none; }
  body.side-rail .side-logo { position: relative; display: inline-flex;
    align-items: center; justify-content: center; }
  body.side-rail .side-logo .logo-img { display: block; width: 36px;
    height: 36px; }
  /* при наведении поверх лого — ЧИСТЫЕ стрелки «раскрыть» без
     кружка-подложки (ред. 5: background/border/border-radius долой) */
  @media (hover: hover) {
    body.side-rail .side-logo:hover .logo-img { opacity: 0; }
    body.side-rail .side-logo:hover .side-logo-open { display: inline-flex; }
  }
  body.side-rail .side-logo .side-logo-open { position: absolute; inset: 0;
    align-items: center; justify-content: center;
    color: var(--text); font-size: 12px; }
  /* «ИИ-стратегия» (fa-grip) и заголовки секций — только иконки, по центру.
     gap: 0 обязателен: схлопнутый font-size:0 текст остаётся анонимным
     flex-айтемом, и штатный gap 0.7rem уводил иконку влево от центра
     (скрин владельца 2026-08-08) */
  body.side-rail #side-overview { font-size: 0; justify-content: center;
    padding: 0.8rem 0; gap: 0; }
  body.side-rail #side-overview i { font-size: 13px; }
  body.side-rail .side-sec { gap: 0; }
  body.side-rail .side-sec { justify-content: center; padding: 0.8rem 0; }
  body.side-rail .side-sec > i { width: auto; }
  body.side-rail .side-sec-name, body.side-rail .side-sec-chev,
  body.side-rail .side-sec-body, body.side-rail .nav-label { display: none; }
  /* низ: только круглый аватар личного кабинета */
  body.side-rail .account-btn { justify-content: center; padding: 0.55rem 0; }
  body.side-rail .account-name, body.side-rail .account-caret { display: none; }
  /* меню ЛК из рейки выпадает шире колонки, поверх контента */
  body.side-rail .side-menu { right: auto; left: 0.2rem; min-width: 220px; }
}

/* FR-W59/AUTH1e: пустое состояние кабинета, подсветка композера, «Назад к
   результату» (строка объёма лендинга убрана — FR-W57 ред. 2, решение
   владельца 2026-09-01; полоски областей результата сняты — FR-W58 ред. 3,
   решение владельца 2026-09-09) */
.auth-why { max-width: 26rem; margin-left: auto; margin-right: auto; }
.auth-back-result { margin-top: 1rem; }
.composer.glow { outline: 2px solid var(--purple); outline-offset: 2px; }

/* ===== Окно тарифов (FR-PAY2, флаг BILLING) ==============================
   Канон владельца 2026-09-13: «бесплатно 1 процесс до 20 операций, дальше
   пакеты 60/300/1000 за 59/199/499 $»; 2026-08-30: «подсвети бизнес
   фиолетово оранжевым». Дизайн-язык прежний: чистый
   чёрный фон, карточки var(--surface), радиус 1.1rem, БЕЗ теней, воздух.
   Градиент purple→orange — ТОЛЬКО на рамке хит-тарифа, его бейдже и цене:
   залить им карточку целиком значит превратить минимализм в неон. */
.pw-overlay { padding: 0; align-items: stretch; justify-content: stretch;
  background: rgba(0,0,0,0.72); z-index: 150; overflow: auto;
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
body.pw-locked { overflow: hidden; }
.pw-card { position: relative; width: min(62rem, 100%); max-width: 62rem;
  margin: auto; padding: 2rem 2rem 1.6rem; background: var(--bg);
  border: 1px solid var(--border); border-radius: 1.1rem; }
.pw-close { position: absolute; top: 0.9rem; right: 0.9rem; background: transparent;
  border: 0; color: var(--dim); font-size: 16px; cursor: pointer; padding: 0.4rem;
  line-height: 1; transition: color 0.2s ease; }
@media (hover: hover) { .pw-close:hover { color: var(--heading); } }

.pw-head { text-align: center; margin-bottom: 1.5rem; padding: 0 2rem; }
.pw-title { margin: 0; font-size: 1.35rem; line-height: 1.25;
  font-weight: 800; color: var(--heading); text-wrap: balance; }

.pw-grid { display: grid; gap: 0.8rem;
  grid-template-columns: repeat(auto-fit, minmax(12.5rem, 1fr)); }
.pw-plan { position: relative; display: flex; flex-direction: column;
  align-items: center; text-align: center; gap: 0.35rem;
  padding: 1.4rem 1.2rem 1.2rem; background: var(--surface);
  border: 1px solid var(--border); border-radius: 1.1rem; }
/* хит-тариф: рамка-градиент через маску — фон карточки остаётся ровным
   var(--surface), светится только контур (1px), как и просил владелец */
.pw-plan.is-hot { border-color: transparent;
  background:
    linear-gradient(var(--surface), var(--surface)) padding-box,
    linear-gradient(135deg, var(--purple), var(--orange)) border-box;
  border: 1px solid transparent; }
.pw-plan.is-free { background: transparent; border-style: dashed; }
/* бейдж по центру верхней грани: абсолютный блок при left:50% получает
   всего половину ширины карточки и без nowrap ломается на две строки,
   наезжая на иконку */
.pw-badge { position: absolute; top: -0.62rem; left: 50%;
  transform: translateX(-50%); white-space: nowrap;
  padding: 0.24rem 0.65rem; border-radius: 999px; font-size: 9.5px;
  font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  color: #fff; background: linear-gradient(135deg, var(--purple), var(--orange)); }
.pw-badge.pw-badge-now { color: var(--dim); background: var(--bg);
  border: 1px solid var(--border); }
.pw-ic { display: inline-flex; align-items: center; justify-content: center;
  width: 2.2rem; height: 2.2rem; border-radius: 0.8rem; font-size: 14px;
  color: var(--purple-l); background: rgba(136,84,243,0.12);
  margin-bottom: 0.55rem; }
.pw-plan.is-hot .pw-ic { color: #fff;
  background: linear-gradient(135deg, var(--purple), var(--orange)); }
.pw-plan.is-free .pw-ic { color: var(--dim); background: var(--ctrl-bg); }
.pw-ic-sm { width: 2rem; height: 2rem; margin-bottom: 0; font-size: 13px; }
.pw-name { font-size: 13px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--heading); }
/* канон владельца 2026-08-30: ЦЕНА сверху, объём — серым под ней */
.pw-price { margin-top: 0.15rem; font-size: 1.75rem; font-weight: 800;
  line-height: 1.1; color: var(--heading); font-variant-numeric: tabular-nums; }
.pw-plan.is-hot .pw-price { background: linear-gradient(135deg, var(--purple-l), var(--orange-l));
  -webkit-background-clip: text; background-clip: text; color: transparent; }
.pw-vol { font-size: 12px; line-height: 1.5; color: var(--dim);
  font-variant-numeric: tabular-nums; }
.pw-vol-sub { font-size: 11px; }
.pw-plan .pw-take { margin-top: auto; width: 100%; justify-content: center;
  min-height: 2.6rem; }

/* «Корпорация»: объём выбирается ползунком прямо в карточке — 1000 уже
   выбрано, дальше вверх, и цена над ним пересчитывается */
.pw-stepper { display: flex; align-items: center; justify-content: center;
  gap: 0.35rem; margin: 0.15rem 0; width: 100%; }
.pw-step { width: 1.9rem; height: 1.9rem; flex: 0 0 auto; border-radius: 999px;
  background: var(--ctrl-bg); border: 1px solid var(--ctrl-border);
  color: var(--text); font-size: 10px; cursor: pointer; line-height: 1; }
@media (hover: hover) { .pw-step:hover { background-image: linear-gradient(var(--hover), var(--hover)); } }
.pw-ops-input { flex: 1 1 auto; min-width: 0; height: 1.9rem; text-align: center;
  border-radius: 0.6rem; background: var(--input-bg); color: var(--heading);
  border: 1px solid var(--ctrl-border); font-family: inherit; font-size: 13.5px;
  font-weight: 700; font-variant-numeric: tabular-nums; }
.pw-ops-input:focus { outline: 2px solid var(--purple); outline-offset: 1px; }
/* Подпись «операций» принадлежит ПОЛЗУНКУ, а не кнопке (владелец
   2026-08-30: «операций в корпорации надо повыше поднять, а не у кнопки»).
   Карточка с ползунком — самая высокая в ряду, свободного места перед
   кнопкой в ней не остаётся вовсе, и подпись прилипала к «Выбрать»: даём
   ей воздух снизу и убираем сверху. */
.pw-plan.is-custom .pw-stepper { margin-bottom: 0; }
.pw-plan.is-custom .pw-vol-sub { margin-top: 0; margin-bottom: 0.6rem; }
.pw-foot { margin: 1.1rem 0 0; text-align: center; font-size: 11.5px;
  color: var(--dim); display: flex; align-items: center; justify-content: center;
  gap: 0.45rem; }

/* Телефон: окно — лист на весь экран с прокруткой, тарифы столбиком и тем же
   центрированием, что на компьютере (владелец 2026-08-30: «по середине и на
   компе и на мобиле выровни»). Карточка ужимается отступами и кеглями, а не
   перестроением в строку: иначе цена уезжает вправо и центра больше нет. */
@media (max-width: 767px) {
  .pw-card { width: 100%; max-width: none; min-height: 100%; margin: 0;
    border: 0; border-radius: 0; padding: 1.3rem 1.1rem 1.2rem; }
  .pw-head { padding: 0 1.6rem; margin-bottom: 1rem; }
  .pw-title { font-size: 1.1rem; }
  .pw-grid { grid-template-columns: 1fr; gap: 0.85rem; }
  .pw-plan { padding: 0.9rem 1.05rem 0.85rem; gap: 0.15rem; }
  .pw-ic { width: 1.85rem; height: 1.85rem; margin-bottom: 0.25rem;
    font-size: 12px; }
  .pw-price { font-size: 1.45rem; }
  .pw-plan .pw-take { margin-top: 0.55rem; min-height: 2.4rem; }
}

/* FR-PAY5: ошибка оплаты — строкой в самом окне тарифов */
.pw-err { margin: 0.9rem 0 0; text-align: center; font-size: 12.5px;
  color: var(--orange-l, var(--orange)); }

/* ═══════════ Онбординг, блоки 1-5 (SPEC-ONBOARD §6, FR-OB-FE*) ═══════════
   Вёрстка перенесена из утверждённого прототипа prototypes/onboarding/
   (кадры shots/) на токены продукта: светлая тема работает через те же
   переменные, ничего не хардкодим. */

/* ── мастер «создать с нуля» (FR-OB-FE1): баннер, тип, шаблоны, native ── */
.ob-wizard { max-width: 860px; margin: 3vh auto 0; padding: 0 1.2rem 4rem; }
.ob-wizard.wide { max-width: 1020px; }
.ob-center { text-align: center; }
.ob-eyebrow { font-size: 11.5px; letter-spacing: 0.14em; text-transform:
  uppercase; color: var(--dim); margin-bottom: 0.6rem; }
.ob-title { color: var(--heading); font-size: 30px; margin: 0 0 0.6rem;
  letter-spacing: -0.01em; }
.ob-sub { color: var(--dim); font-size: 14px; line-height: 1.6;
  margin: 0 0 1.6rem; }
/* канон 2026-09-01: назад — ЗНАЧОК-стрелка слева вверху, без кружка */
.ob-back { display: inline-flex; align-items: center;
  color: var(--dim); font-size: 18px; margin-bottom: 1rem; background: none;
  border: 0; cursor: pointer; font-family: inherit; padding: 0.2rem 0.6rem 0.2rem 0; }
@media (hover: hover) { .ob-back:hover { color: var(--text); } }
.ob-choice { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2rem;
  margin-top: 1.2rem; }
.ob-tmpl-grid { display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 0.9rem; margin-top: 1.2rem; }
/* FR-OB-FE9: шаблон — строка «иконка · имя+описание · стрелка», без кнопки */
.ob-opt.row { flex-direction: row; align-items: center; gap: 1rem;
  padding: 1rem 1.1rem; }
.ob-opt.row .ico { align-self: center; flex: none; width: 2.9rem;
  height: 2.9rem; font-size: 18px; }
.ob-opt.row .mid { display: flex; flex-direction: column; gap: 0.25rem;
  min-width: 0; flex: 1; }
.ob-opt.row .t { text-align: left; font-size: 16px; }
.ob-opt.row .d { display: -webkit-box; -webkit-line-clamp: 2;
  -webkit-box-orient: vertical; overflow: hidden; font-size: 13px;
  line-height: 1.5; }
.ob-opt.row .go { flex: none; color: var(--dim); font-size: 15px; }
@media (hover: hover) { .ob-opt.row:hover .go { color: var(--text); } }
.ob-opt { background: var(--surface); border: 1px solid var(--border);
  border-radius: 1.2rem; padding: 1.4rem 1.4rem 1.3rem; cursor: pointer;
  display: flex; flex-direction: column; gap: 0.7rem; text-align: left;
  transition: border-color 0.25s ease, transform 0.25s ease;
  position: relative; font: inherit; color: var(--text); }
/* FR-OB-FE9: заголовок, иконка и кнопка — по центру; серый текст и буллеты
   остаются как были (владелец: «по середине и текст и кнопки, кроме
   основного серого текста») */
.ob-opt .ico { align-self: center; }
.ob-opt .t { text-align: center; }
.ob-opt.cur { border-color: var(--purple); }
.ob-opt .t i { color: var(--purple-l); font-size: 14px; margin-left: 0.3rem; }
/* FR-UXI-61/62: карточка-вариант онбординга — ховер белый 8%, плашка иконки нейтральная */
@media (hover: hover) { .ob-opt:hover { background-image: linear-gradient(var(--hover), var(--hover)); } }
.ob-opt .ico { width: 3.3rem; height: 3.3rem; border-radius: 1rem;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 21px; background: var(--ctrl-bg); color: var(--text); }
.ob-opt .t { font-weight: 800; color: var(--heading); font-size: 18px; }
.ob-opt .d { color: var(--dim); font-size: 14px; line-height: 1.6; }
/* FR-OB-FE10: строка «N процессов · M ИИ-агентов» под описанием шаблона */
.ob-opt .ob-counts { font-size: 13px; opacity: .8; -webkit-line-clamp: 1; }
.ob-opt ul { margin: 0; padding: 0 0 0 1.1rem; color: var(--body2, var(--text));
  font-size: 13.5px; line-height: 1.75; }
.ob-opt .foot { margin-top: auto; display: flex; justify-content: center;
  padding-top: 0.4rem; }
.ob-opt .pick { background: var(--btn-bg, #fff); color: var(--btn-fg, #000);
  border: 0; border-radius: 999px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.08em; font-size: 12.5px; padding: 0.75rem 1.2rem;
  cursor: pointer; display: inline-flex; align-items: center; gap: 0.55rem;
  font-family: inherit;
  /* FR-OB-FE9: все кнопки выбора ОДНОГО размера */
  min-width: 14.5rem; justify-content: center; }
.ob-banner-card { max-width: 760px; width: 100%; text-align: center;
  max-height: 94vh; overflow-y: auto; position: relative; }
/* FR-OB-FE10 (аудит Н-7): у окна «С чего начнём?» есть крестик — тот же
   тихий значок в углу, что у окна тарифов (.pw-close); Esc и клик по
   подложке закрывают окно на этот визит, выбор не подменяют */
.ob-banner-x { position: absolute; top: 0.9rem; right: 0.9rem; background: transparent;
  border: 0; color: var(--dim); font-size: 16px; cursor: pointer; padding: 0.4rem;
  line-height: 1; transition: color 0.2s ease; min-width: 44px; min-height: 44px; }
@media (hover: hover) { .ob-banner-x:hover { color: var(--heading); } }
.ob-banner-x:focus-visible { outline: 1px solid var(--dim); outline-offset: 2px; }
.ob-banner-card .ob-choice { margin-top: 1.6rem; }
.ob-dept-h { display: flex; align-items: center; gap: 0.6rem;
  margin: 1.6rem 0 0.6rem; color: var(--heading); font-weight: 700;
  font-size: 15px; }
.ob-dept-h i { color: var(--purple-l); }
.ob-split { font-size: 10.5px; color: var(--orange-l); border: 1px solid
  rgba(249,115,22,0.45); border-radius: 999px; padding: 0.18rem 0.6rem;
  letter-spacing: 0.05em; text-transform: uppercase; font-weight: 600; }
.ob-dept-procs { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.ob-proc-pill { display: inline-flex; align-items: center; gap: 0.4rem;
  font-size: 12px; border: 1px solid var(--ctrl-border, var(--border));
  border-radius: 999px; padding: 0.3rem 0.75rem; color: var(--dim); }
.ob-proc-pill .w { color: var(--purple-l); font-weight: 700; }
.ob-err { color: var(--orange-l); font-size: 13px; margin-top: 1rem; }
@media (max-width: 900px) { .ob-tmpl-grid { grid-template-columns: 1fr; } }
@media (max-width: 720px) { .ob-choice { grid-template-columns: 1fr;
  gap: 0.9rem; margin-top: 1.3rem; } }
@media (max-width: 560px) {
  .ob-title { font-size: 24px; }
  .ob-tmpl-grid { grid-template-columns: 1fr; gap: 0.75rem; margin-top: 0.9rem; }
  .ob-opt { padding: 1.1rem 1rem 1rem; }
  .ob-opt.row { padding: 0.85rem 0.95rem; }
  .ob-banner-card { padding: 1.4rem 1rem 1.2rem; }
  /* мобила: экраны мастера подтянуты вверх — сверху была пустота */
  .screen[data-screen="ob-type"] .ob-wizard,
  .screen[data-screen="ob-templates"] .ob-wizard { padding-top: 0.4rem; }
}

/* ── FR-UXI-45..48: роли в двух видах, системы-аккордеон, экран агентов,
   переименование артефакта, нечеткий поиск ── */
/* .org-tree/.org-node/.org-elbow/.org-tile прежнего дерева-«ёлочки» сняты
   батчем 3: оргсхема теперь уровнями (.org-level/.org-card — блок B3-ORG
   в конце файла, FR-UXI-78/79) */
.org-proc-h { display: flex; align-items: center; gap: 0.55rem;
  margin: 1.4rem 0 0.6rem; color: var(--heading); font-weight: 700;
  font-size: 15px; cursor: pointer; }
.org-proc-h i { color: var(--purple-l); font-size: 13px; }
.org-proc-grid { margin-top: 0.2rem; }
.ux-sys-row { cursor: pointer; }
.ux-sys-chev { color: var(--dim); font-size: 11px; margin-left: auto; }
.ux-sys-row .ux-card-del { margin-left: 0.4rem; }
.ux-sys-uses { margin: -0.2rem 0 0.6rem 1.9rem; }
.ux-card-edit { background: transparent; border: 0; color: var(--dim);
  cursor: pointer; font-size: 13px; padding: 0.25rem 0.45rem; }
@media (hover: hover) { .ux-card-edit:hover { color: var(--text); } }
/* поиск: строка в ШАПКЕ (FR-UXI-67, блок B3-DESIGN в конце файла), выдача поверх контента */
.gs-wrap { position: relative; margin: 0; }
.gs-ico { position: absolute; left: 0.95rem; top: 50%;
  transform: translateY(-50%); color: var(--dim); font-size: 13px; }
.gs-input { width: 100%; padding-left: 2.5rem; }
.gs-results { position: absolute; left: 0; right: 0; top: calc(100% + 6px);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 0.9rem; padding: 0.35rem; z-index: 90; max-height: 21rem;
  overflow-y: auto; }
.gs-row { display: flex; align-items: center; gap: 0.65rem; width: 100%;
  background: transparent; border: 0; color: var(--text); cursor: pointer;
  padding: 0.55rem 0.7rem; border-radius: 0.6rem; font: inherit;
  font-size: 13.5px; text-align: left; }
@media (hover: hover) { .gs-row:hover { background: var(--hover); } }
.gs-row i { color: var(--dim); font-size: 12.5px; width: 1.2rem;
  text-align: center; flex: none; }
.gs-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.gs-sub { color: var(--dim); font-size: 11.5px; max-width: 40%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gs-empty { padding: 0.7rem 0.8rem; font-size: 13px; }

/* ── профиль: баланс операций в раскрытом меню (FR-OB-FE3) ── */
.lk-balance { display: flex; flex-direction: column; align-items: center;
  gap: 0.45rem; padding: 0.75rem 0.8rem 0.8rem; border-bottom: 1px solid
  var(--border); margin-bottom: 0.4rem; }
.lk-balance .bk { font-size: 11px; letter-spacing: 0.09em; text-transform:
  uppercase; color: var(--dim); }
.lk-ringwrap { position: relative; display: inline-flex; }
.lk-ringnum { position: absolute; inset: 0; display: flex; align-items:
  center; justify-content: center; color: var(--heading); font-weight: 800;
  font-size: 15px; }
.lk-ringnum i { font-style: normal; color: var(--dim); font-weight: 500;
  font-size: 11px; margin-top: 0.15rem; }
.lk-topup { color: var(--purple-l); font-size: 12.5px; font-weight: 600;
  background: none; border: 0; cursor: pointer; font-family: inherit; }
/* телефон: сайдбара нет — аватар в шапке открывает меню нижним листом */
.mob-ava { display: none; width: 2.1rem; height: 2.1rem; border-radius: 50%;
  border: 0; background: linear-gradient(135deg, var(--purple), var(--orange));
  color: #fff; font-weight: 700; font-size: 13px; align-items: center;
  justify-content: center; cursor: pointer; font-family: inherit; }
@media (max-width: 1023px) { .mob-ava { display: inline-flex; } }
.side-menu.ob-sheet { position: fixed; left: 16px; right: 16px; bottom: 16px;
  top: auto; margin: 0; z-index: 160; }

/* ── типсы первого входа (FR-OB-FE4) ── */
.ob-veil { position: fixed; inset: 0; background: rgba(0,0,0,0.72);
  z-index: 150; }
/* B28-TIPS (NFR-FE15): слой серий подсказок НЕ перехватывает клики — вуали
   нет, подсветка и карточка лежат поверх, но работать продукту не мешают;
   кликабельна только сама карточка. */
#tip-series { position: fixed; inset: 0; z-index: 150; pointer-events: none; }
#tip-series .tip-s-card { pointer-events: auto; }

.ob-spot { position: fixed; border: 2px solid var(--purple);
  border-radius: 1.2rem; outline: 6px solid rgba(136,84,243,0.25);
  z-index: 151; pointer-events: none; }
.ob-tip { position: fixed; z-index: 152; border: 1px solid transparent;
  border-radius: 1.1rem; padding: 1rem 1.15rem; max-width: 330px;
  background: linear-gradient(var(--surface), var(--surface)) padding-box,
    linear-gradient(120deg, var(--purple), var(--orange)) border-box; }
.ob-tip .n { font-size: 11px; letter-spacing: 0.12em; color: var(--dim);
  text-transform: uppercase; margin-bottom: 0.4rem; }
.ob-tip .tt { font-weight: 700; color: var(--heading); font-size: 14.5px;
  margin-bottom: 0.35rem; }
.ob-tip .td { color: var(--body2, var(--text)); font-size: 13px;
  line-height: 1.6; }
.ob-tip .row { display: flex; align-items: center; gap: 0.7rem;
  margin-top: 0.9rem; }
.ob-tip .dots { display: flex; gap: 0.35rem; margin-right: auto; }
.ob-tip .dot { width: 6px; height: 6px; border-radius: 50%;
  background: var(--ctrl-border, var(--border)); }
.ob-tip .dot.on { background: var(--purple); }
.ob-tip .next { background: var(--btn-bg, #fff); color: var(--btn-fg, #000);
  border: 0; border-radius: 999px; font-weight: 700; font-size: 11px;
  letter-spacing: 0.07em; text-transform: uppercase; padding: 0.5rem 1.1rem;
  cursor: pointer; font-family: inherit; }
.ob-tip .skip { color: var(--dim); font-size: 12px; background: none;
  border: 0; cursor: pointer; font-family: inherit; }

/* ── тост порога операций (FR-OB-FE5) ── */
.ob-toast { position: fixed; top: 4.2rem; right: 1.2rem; z-index: 165;
  max-width: 350px; border: 1px solid transparent; border-radius: 1.1rem;
  padding: 1rem 1.1rem;
  background: linear-gradient(var(--surface), var(--surface)) padding-box,
    linear-gradient(120deg, var(--purple), var(--orange)) border-box; }
.ob-toast[hidden] { display: none; }
.ob-toast .th { display: flex; align-items: center; gap: 0.6rem;
  font-weight: 700; color: var(--heading); font-size: 14.5px;
  margin-bottom: 0.35rem; }
.ob-toast .th i { color: var(--orange-l); }
.ob-toast .tb { color: var(--body2, var(--text)); font-size: 13px;
  line-height: 1.6; }
.ob-toast .tr { display: flex; gap: 0.7rem; margin-top: 0.9rem;
  align-items: center; justify-content: flex-end; }
.ob-toast .later { color: var(--dim); font-size: 12px; background: none;
  border: 0; cursor: pointer; font-family: inherit; }
.ob-toast .x { position: absolute; top: 0.65rem; right: 0.8rem;
  color: var(--dim); background: none; border: 0; cursor: pointer;
  font-size: 13px; }
@media (max-width: 560px) { .ob-toast { left: 0.8rem; right: 0.8rem;
  max-width: none; } }

/* ── папки процессов = отделы (FR-OB-FE6) ── */
/* FR-UXI-61/62: папка — такая же графитовая плитка, иконка монохром
   (отличие — глиф папки и счётчик, а не оранжевая рамка) */
.folder-tile { border-color: var(--card-border); }
.folder-tile .tile-ico { background: var(--ctrl-bg); color: var(--text); }
.fname-row { display: flex; align-items: center; gap: 0.5rem; }
.fname-input { background: var(--input-bg, var(--bg)); border: 1px solid
  var(--purple); border-radius: 0.55rem; color: var(--heading);
  font-family: inherit; font-weight: 700; font-size: 14.5px;
  padding: 0.35rem 0.55rem; width: 100%; min-width: 0; outline: none; }
.ob-drag-ghost { position: fixed; width: 270px; opacity: 0.92;
  transform: rotate(-3deg); border-color: var(--purple) !important;
  pointer-events: none; z-index: 170; margin: 0; }
.proc-tile.drop-hot { border-color: var(--purple);
  outline: 3px solid rgba(136,84,243,0.25); }
.proc-tile.drag-src { opacity: 0.35; }
/* B5 (FR-UXI-19 ред. 7): перетаскивание и в сайдбаре — те же состояния */
#side-processes .nav-item.drop-hot { background: var(--hover); color: var(--text);
  outline: 1px solid var(--purple); outline-offset: -1px; }
#side-processes .nav-item.drag-src { opacity: 0.35; }
#side-processes .nav-folder { color: var(--dim); }
#side-processes .nav-item.nav-sub { padding-left: 1.9rem; }
.ob-drag-ghost.nav-item { width: 14rem; background: var(--card); border: 1px solid var(--card-border); }
.ob-folder-head { display: flex; align-items: center; gap: 0.6rem;
  margin: 1.2rem 0 0.6rem; color: var(--heading); font-weight: 700;
  font-size: 15px; }
.ob-folder-head i { color: var(--orange-l); }
.ob-folder-head .ob-back { margin: 0 0 0 auto; }

/* ── крипто-оплата в окне пополнения (FR-OB-FE7) ── */
/* FR-OB-FE9 (владелец 2026-09-01): «Способ оплаты» — по центру, способы
   и сети — компактные пилюли, без больших карточек и подписей */
.pw-paysec { font-size: 11.5px; letter-spacing: 0.11em; text-align: center;
  text-transform: uppercase; color: var(--dim); margin: 1.2rem 0 0.6rem; }
.pw-methods { display: flex; justify-content: center; gap: 0.6rem; }
.pw-method { background: var(--surface); border: 1px solid var(--border);
  border-radius: 999px; padding: 0.55rem 1.2rem; display: inline-flex;
  align-items: center; gap: 0.5rem; cursor: pointer; font-size: 13.5px;
  font-weight: 700; color: var(--body2, var(--text)); font-family: inherit; }
.pw-method > i { font-size: 14px; color: var(--purple-l); }
.pw-method.sel { border-color: var(--purple); color: var(--heading);
  outline: 3px solid rgba(136,84,243,0.22); }
.pw-nets { display: flex; justify-content: center; flex-wrap: wrap;
  gap: 0.6rem; margin-top: 0.7rem; }
.pw-net { background: var(--surface); border: 1px solid var(--border);
  border-radius: 999px; padding: 0.5rem 1rem; text-align: center;
  cursor: pointer; display: inline-flex; align-items: center; gap: 0.45rem;
  font-size: 12.5px; color: var(--body2, var(--text)); font-family: inherit; }
.pw-net i { color: var(--purple-l); font-size: 12px; }
.pw-net b { color: var(--heading); font-size: 12.5px; font-weight: 700; }
.pw-net.sel { border-color: var(--purple);
  outline: 3px solid rgba(136,84,243,0.22); }
/* счёт: копирование, сети в строке, компактный «Открыть в кошельке»,
   «!» у комментария, стрелка-назад слева вверху (мобильный канон) */
.pw-copy { background: transparent; border: 0; color: var(--dim);
  cursor: pointer; font-size: 12.5px; padding: 0 0 0 0.45rem; }
@media (hover: hover) { .pw-copy:hover { color: var(--text); } }
.pw-inv-nets { display: flex; flex-wrap: wrap; gap: 0.4rem;
  justify-content: flex-end; }
.pw-inv-nets .pw-net { padding: 0.35rem 0.7rem; font-size: 11.5px; }
.pw-bang { color: var(--orange-l); }
.pw-openwrap { display: flex; justify-content: center; margin-top: 0.6rem; }
.pw-open { display: inline-flex; align-items: center; gap: 0.5rem;
  border: 1px solid var(--border); border-radius: 999px; cursor: pointer;
  padding: 0.5rem 1.1rem; font-size: 12.5px; color: var(--text);
  text-decoration: none; }
@media (hover: hover) { .pw-open:hover { background-image: linear-gradient(var(--hover), var(--hover)); } }
.pw-open i { color: var(--dim); }
.pw-back { position: absolute; top: 0.9rem; left: 0.9rem; background:
  transparent; border: 0; color: var(--dim); cursor: pointer; font-size:
  17px; padding: 0.2rem 0.5rem; display: none; }
@media (hover: hover) { .pw-back:hover { color: var(--heading); } }
@media (max-width: 640px) { .pw-back { display: inline-flex; }
  .pw-card .pw-close { display: none; } }
/* операции у обычных планов — на высоте счётчика «Корпорации» */
.pw-plan:not(.is-custom):not(.is-free) .pw-vol { margin-top: 2.55rem; }
.pw-inv { display: flex; gap: 1.4rem; align-items: flex-start;
  margin-top: 1rem; text-align: left; }
.pw-qr { background: #fff; border-radius: 0.9rem; padding: 0.5rem;
  flex: 0 0 auto; }
.pw-qr img { display: block; width: 168px; height: 168px; }
.pw-inv-rows { flex: 1; display: flex; flex-direction: column; gap: 0.55rem;
  min-width: 0; width: 100%; }
.pw-inv-row { display: flex; justify-content: space-between; gap: 0.8rem;
  font-size: 13px; border-bottom: 1px solid var(--border);
  padding-bottom: 0.5rem; }
.pw-inv-row .l { color: var(--dim); flex: 0 0 auto; }
.pw-inv-row .r { color: var(--heading); font-weight: 600; text-align: right;
  overflow-wrap: anywhere; }
.pw-inv-row .r.mono { font-family: ui-monospace, monospace; font-size: 12px;
  font-weight: 500; }
.pw-inv-row .r.memo { color: var(--orange-l); }
.pw-inv-note { background: var(--surface); border: 1px solid var(--border);
  border-radius: 0.9rem; padding: 0.8rem 1rem; color: var(--body2, var(--text));
  font-size: 12.5px; line-height: 1.65; margin-top: 1rem; text-align: left; }
.pw-inv-note b { color: var(--orange-l); }
.pw-inv-num { color: var(--dim); font-weight: 600; font-size: 16px; }
.pw-invfoot { display: flex; justify-content: center; gap: 0.7rem;
  margin-top: 1.5rem; }
.pw-wait { text-align: center; padding: 1.5rem 0 0.5rem; color:
  var(--body2, var(--text)); font-size: 14px; line-height: 1.7; }
.pw-wait i { display: block; font-size: 30px; color: var(--purple-l);
  margin-bottom: 0.7rem; }
@media (max-width: 640px) {
  .pw-inv { flex-direction: column; align-items: center; }
  .pw-nets { grid-template-columns: 1fr; }
}

/* ── B3-DESIGN: поиск в шапке · бегущая строка заголовка · точки-буллеты ── */
/* FR-UXI-67 / US-UX25 (владелец 2026-09-01: «поиск должен быть в самом вверху
   где дорожная карта и тд - на всех формах»): строка поиска живёт в .header-row
   между заголовком экрана и кнопками (#header-cab-actions), поэтому она есть
   на кабинете, процессе, дорожной карте и любом другом экране кабинета —
   показ/скрытие решает gsSync() в showScreen. Сама шапка pointer-events:none —
   блоку возвращаем клики. Пилюля в тон круглых кнопок (var(--ctrl-bg)). */
.gs-wrap[hidden] { display: none !important; }
/* FR-UXI-67 ред. 2 (батч 4, владелец 2026-09-02: «поиск побольше и там иконка
   поиска и просто написано "Поиск"»): названия в строке шапки больше нет
   (заголовок ушёл под шапку, FR-UXI-101), поэтому поле стоит ПО ЦЕНТРУ
   строки. Флекс с auto-полями центрирует блок лишь между соседями, а группы
   слева (лого/стрелка) и справа (кнопки кабинета) разной ширины — поэтому
   поле вынесено из потока: absolute внутри .header-row, а left/width ставит
   gsFit() (app.js): центр поля = центр строки, пока кнопки оставляют центру
   ≥12rem; иначе — центр свободной части между группами. До первого замера —
   CSS-подстраховка: 40% ширины по центру. Не уже 8rem, не шире 40rem. */
.header-row { position: relative; }
.header-row .gs-wrap { pointer-events: auto; position: absolute; top: 50%;
  transform: translateY(-50%); left: 27%; width: 46%; min-width: 8rem;
  max-width: 44rem; margin: 0; }   /* B5 (FR-UXI-67 ред. 3): чуть длиннее */
.header-row .gs-input { height: 3rem; min-height: 3rem; padding: 0 1rem 0 2.6rem;
  font-size: 15px; border-radius: 999px; background: var(--ctrl-bg);
  border-color: var(--ctrl-border); }
.header-row .gs-input:focus { border-color: var(--purple); }
/* подсказка поля — токеном --dim в обеих темах: общий .input::placeholder
   (светло-серый 40%) на светлой теме сливался с #f1f5f9 и поле стояло «пустым» */
.header-row .gs-input::placeholder { color: var(--dim); opacity: 1; }
/* лупа внутри поля слева — заметнее (15px), в тон подсказки */
.header-row .gs-ico { left: 1rem; font-size: 15px; pointer-events: none; }
/* выдача — под полем, по его центру: не уже 22rem (шире сжатого поля),
   на телефоне — от края до края шапки (правило в блоке B4-HEADER) */
.header-row .gs-results { border-radius: 1rem; left: 50%; right: auto;
  transform: translateX(-50%); width: max(100%, 22rem); min-width: 22rem; }
/* FR-UXI-67 ред. 2 (батч 4): лупы-тумблера #gs-toggle и режима body.gs-open
   больше нет — поле стоит на всех ширинах (в строке шапки нет названия) */
/* Кабинет на узком экране (FR-UXI-67 + приём FR-W50m): «Дорожная карта»
   остаётся кнопкой, скачивание · поделиться · тема — в kebab «⋯»; ряд
   .proc-acts-wide прячет общее правило ≤640px. Кнопки и зазоры ужаты, чтобы
   названию компании оставалась читаемая ширина. */
@media (max-width: 640px) {
  #header-cab-actions .proc-acts-narrow { display: flex; align-items: center; gap: 0.3rem; }
}
/* Ноутбук 1024–1439px с открытым сайдбаром: контенту остаётся ~1000px, а в
   шапке название компании + поле поиска + четыре кнопки. Вторичное «Скачать
   ИИ-стратегию» сворачивается в круглую иконку (подпись — в aria-label/title,
   app.js), и название компании остаётся целым, без бегущей строки. */
@media (min-width: 1024px) and (max-width: 1439px) {
  body.side-open #header-cab-actions .proc-acts-wide [data-action="download-strategy"] .rl-txt { display: none; }
  body.side-open #header-cab-actions .proc-acts-wide [data-action="download-strategy"] {
    padding: 0; width: 2.6rem; height: 2.6rem; border-radius: 999px; gap: 0; }
}
@media (max-width: 480px) {
  .header-cab-actions { gap: 0.25rem; }
  .header-cab-actions .rl-btn,
  .header-cab-actions .ctrl-round { width: 2.35rem; height: 2.35rem; }
  .header-right { gap: 0.35rem; }
}

/* FR-UXI-66 / US-UX24 (владелец 2026-09-01: «чтобы название процесса не
   обрезалось - оно в одну строчку движущийся строкой красиво и элегантно»):
   заголовок шапки в одну строку без многоточия. Короткое имя стоит на месте;
   если fitHeaderTitle() (app.js) намерил переполнение, он ставит .is-overflow и
   --mq-shift/--mq-dur — текст неспешно едет влево до конца, замирает и едет
   обратно (alternate), с паузами на краях (0–15% / 85–100%). Края смягчены
   маской: полоска 0.5rem слева/справа растворяется, а сам текст стартует
   ПОСЛЕ маски (padding + отрицательный margin — позиция первой буквы не
   меняется относительно короткого заголовка). Ховер — пауза; при
   prefers-reduced-motion анимации нет, только мягкий срез справа. */
.hdr-marquee { display: inline-block; white-space: nowrap; vertical-align: top; }
.hdr-title-text.is-overflow { margin-left: -0.5rem;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 0.5rem,
    #000 calc(100% - 0.5rem), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 0.5rem,
    #000 calc(100% - 0.5rem), transparent 100%); }
.hdr-title-text.is-overflow .hdr-marquee { padding: 0 0.5rem;
  will-change: transform;
  animation: hdr-marquee var(--mq-dur, 9s) ease-in-out infinite alternate; }
@keyframes hdr-marquee {
  0%, 15% { transform: translateX(0); }
  85%, 100% { transform: translateX(var(--mq-shift, 0px)); }
}
@media (hover: hover) {
  .hdr-title-text.is-overflow:hover .hdr-marquee { animation-play-state: paused; }
}
@media (prefers-reduced-motion: reduce) {
  .hdr-title-text.is-overflow .hdr-marquee { animation: none; }
  .hdr-title-text.is-overflow {
    -webkit-mask-image: linear-gradient(90deg, #000 85%, transparent 100%);
    mask-image: linear-gradient(90deg, #000 85%, transparent 100%); }
}

/* FR-UXI-65 (владелец 2026-09-01: «артефакты просто точками перед названиями
   булеты // системы тоже точки булеты»): у артефактов и систем — в сайдбаре,
   в настройках, в папках артефактов — перед названием одна серая точка, без
   значков типа (fa-file-lines / fa-server сняты в app.js). */
#side-sec-body-artifacts .nav-item .nav-name::before,
.side-sys-row .nav-name::before { content: "\2022\00a0\00a0"; color: var(--dim); }
/* строка системы в сайдбаре — тем же кеглем и тоном, что строка артефакта
   (.nav-item): один список, одни буллеты, а не два разных шрифта */
.side-sys-row { font-size: 14px; font-weight: 500; color: var(--dim);
  padding: 0.6rem 0.9rem; }
.ux-sys-row::before,
.art-file::before,
ul.dots > li::before,
.dot-item::before { content: "\2022"; color: var(--dim); flex: none;
  width: 1.1rem; text-align: center; line-height: 1; font-size: 15px; }
ul.dots { list-style: none; margin: 0; padding: 0; }
ul.dots > li, .dot-item { display: flex; align-items: center; gap: 0.5rem; }
/* ── B3-SUPPORT: экран «Поддержка» (FR-UXI-51, FR-UXI-52, NFR-UXI-18) ──
   Два поля и кнопка, без слова о почте; после отправки — галочка и одна
   фраза «Запрос отправлен» по центру. Монохром, воздух, без рамок. */
.sup-form { display: flex; flex-direction: column; gap: 0.55rem; max-width: 40rem;
  margin-top: 1.25rem; }
.sup-label { font-size: 12px; color: var(--dim); text-transform: uppercase;
  letter-spacing: 0.04em; margin-top: 0.6rem; }
.sup-textarea { min-height: 9rem; }
.sup-actions { display: flex; align-items: center; justify-content: center; gap: 1rem;
  flex-wrap: wrap; margin-top: 0.8rem; }   /* B5: «Отправить» по центру */
.sup-send { min-height: 44px; }
.sup-done { display: flex; flex-direction: column; align-items: center;
  justify-content: center; text-align: center; gap: 1rem; padding: 3.5rem 1rem 2rem;
  max-width: 40rem; }
.sup-done-icon { font-size: 2.4rem; color: var(--text); }
.sup-done-text { margin: 0; font-size: 1.15rem; font-weight: 600; color: var(--text); }
.sup-done-btn { min-height: 44px; min-width: 9rem; }
@media (max-width: 640px) {
  .sup-form, .sup-done { max-width: none; }
  .sup-done { padding-left: 0; padding-right: 0; }
  .sup-actions { flex-direction: column; align-items: stretch; }
  .sup-send, .sup-done-btn { width: 100%; }
}

/* ── B3-RECORD: запись экрана (FR-OB13…FR-OB20, NFR-OB7…NFR-OB9) ──
   Кнопка-видео — того же размера и тона, что микрофон (FR-OB13, NFR-OB7:
   монохром, без рамок и пульсации). Пока идёт голосовая запись, кнопки нет. */
.composer-screen { background: var(--ctrl-bg); color: var(--dim); }
@media (hover: hover) { .composer-screen:hover { color: var(--heading); } }
.composer.recording .composer-screen { display: none; }
/* панель ВМЕСТО поля ввода: одна строка, flex:1 занимает место textarea; сама
   пилюля композера остаётся (FR-OB15). Скрытие — правилами [hidden], потому
   что элементы flex/grid без них остаются в раскладке */
.sr-panel { flex: 1; min-width: 0; display: flex; align-items: center; min-height: 2.7rem; }
.sr-panel[hidden] { display: none; }
.composer.sr-on .composer-input, .composer.sr-on .composer-mic,
.composer.sr-on .composer-send, .composer.sr-on .composer-screen,
.composer.sr-on .composer-wave, .composer.sr-on .composer-cancel,
.composer.sr-on .composer-confirm { display: none; }
.composer.sr-on { border-color: var(--ctrl-border); }
.sr-count-wrap, .sr-rec-wrap { display: none; align-items: center; gap: 0.7rem;
  width: 100%; min-width: 0; }
.sr-panel[data-state="count"] .sr-count-wrap { display: flex; }
.sr-panel[data-state="rec"] .sr-rec-wrap,
.sr-panel[data-state="paused"] .sr-rec-wrap { display: flex; }
/* отсчёт 5-4-3-2-1 (FR-OB14): крупная цифра, подсказка «проговаривайте», крестик */
.sr-count { font-size: 26px; font-weight: 800; color: var(--heading); min-width: 1.4rem;
  text-align: center; font-variant-numeric: tabular-nums; line-height: 1; }
.sr-hints { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.1rem;
  color: var(--dim); font-size: 12.5px; line-height: 1.35; }
.sr-hint { color: var(--text); }
.sr-hint2 { font-size: 11.5px; }
.sr-cancel { background: var(--ctrl-bg); color: var(--dim); margin-left: auto; }
@media (hover: hover) { .sr-cancel:hover { color: var(--heading); } }
/* идёт запись (FR-OB15/FR-OB16): точка · что снимаем · остаток времени · Стоп */
.sr-dot { margin-right: 0; flex-shrink: 0; }
.sr-panel[data-state="paused"] .sr-dot { animation: none; opacity: 0.5; }
.sr-surface { flex: 1; min-width: 0; color: var(--dim); font-size: 12.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sr-surface[hidden] { display: none; }
.sr-left { color: var(--heading); font-size: 15px; font-weight: 700; margin-left: auto;
  font-variant-numeric: tabular-nums; flex-shrink: 0; }
.sr-left.sr-warn { color: var(--orange); }
.sr-stop { height: 2.7rem; padding: 0 1rem 0 0.85rem; border-radius: 999px; border: 0;
  display: flex; align-items: center; gap: 0.5rem; cursor: pointer; flex-shrink: 0;
  background: var(--ctrl-bg); color: var(--heading); font: inherit; font-size: 13px;
  font-weight: 600; transition: background 0.2s ease; }
.sr-stop i { font-size: 13px; }
@media (hover: hover) { .sr-stop:hover { background: var(--ctrl-border); } }
/* на телефоне — только квадрат, без слова «Стоп» (FR-OB15, NFR-OB9) */
@media (max-width: 600px) {
  .sr-stop-txt { display: none; }
  .sr-stop { padding: 0; width: 2.7rem; justify-content: center; }
  .sr-hint2 { display: none; }
}
/* окно «Лимит времени исчерпан» (FR-OB17): поверх всего (выше пейволла 150 и
   типсов 152), иконка часов сверху по центру, без подзаголовка, три кнопки
   столбиком с иконками */
.sr-limit { position: fixed; inset: 0; z-index: 160; display: flex; align-items: center;
  justify-content: center; background: rgba(0,0,0,0.6); padding: 1rem; }
.sr-limit[hidden] { display: none; }
.sr-limit-card { background: var(--surface); border: 1px solid var(--border);
  border-radius: 1.2rem; padding: 1.6rem 1.4rem 1.3rem; width: 100%; max-width: 22rem;
  text-align: center; }
.sr-limit-ico { font-size: 30px; line-height: 30px; width: 30px; height: 30px; color: var(--dim); display: block; margin: 0 auto 0.7rem; }
.sr-limit-title { margin: 0 0 1.1rem; font-size: 17px; font-weight: 700; color: var(--heading); }
.sr-limit-btns { display: flex; flex-direction: column; gap: 0.5rem; }
.sr-lim-btn { display: flex; align-items: center; justify-content: center; gap: 0.55rem;
  width: 100%; padding: 0.7rem 1rem; border-radius: 999px; border: 1px solid var(--border);
  background: var(--ctrl-bg); color: var(--heading); font: inherit; font-size: 14px;
  font-weight: 600; cursor: pointer; transition: background 0.2s ease; }
.sr-lim-btn[hidden] { display: none; }
.sr-lim-btn i { color: var(--dim); font-size: 14px; }
.sr-lim-btn b { font-weight: 700; font-variant-numeric: tabular-nums; }
@media (hover: hover) { .sr-lim-btn:not(.sr-lim-primary):hover { background: var(--ctrl-border); }
  .sr-lim-primary:hover { background: var(--purple-l); border-color: var(--purple-l); } }
.sr-lim-primary { background: var(--purple); border-color: var(--purple); color: #fff; }
.sr-lim-primary i { color: #fff; }
/* FR-OB18: браузер закрыл всплывающее окно оплаты — ссылка в окне тарифов */
.pw-open-link { color: var(--purple-l); text-decoration: underline; font-weight: 600; }

/* ── B3-CANVAS: полотно процесса в кабинете (FR-UXI-68/69, NFR-UXI-20) ── */
/* обёртка табов и врезок; .fs — полноэкранный режим врезки (значок внутри
   полотна / kebab / Esc). Слой 110: под оверлеем дровера (115) и самим
   дровером (120), над шапкой (30) и сайдбаром (70) */
.dg-wrap { position: relative; box-sizing: border-box; }
.dg-wrap.fs { position: fixed; inset: 0; z-index: 110; background: var(--bg);
  display: flex; flex-direction: column; margin: 0; }
.dg-wrap.fs .dg-tabs-row { flex: 0 0 auto; padding: 8px 12px; }
.dg-wrap.fs .dg-tabs-row:empty { display: none; }
.dg-wrap.fs .proc-canvas { flex: 1 1 auto; min-height: 0; margin: 0; display: flex; }
.dg-wrap.fs .canvas-frame:not([hidden]) { flex: 1 1 auto; height: auto; min-height: 0;
  border: 0; border-radius: 0; }
body.canvas-fs { overflow: hidden; }
/* на телефоне .content-layer (fixed, z 10) и .panel в app-режиме (relative,
   z 10) — свои контексты наложения, и шапка (z 30) перекрывала полный экран;
   на время полного экрана слой поднимаем над шапкой и сайдбаром (70), но
   ниже дровера (120) и его подложки (115) — разбор узла открывается ПОВЕРХ */
body.canvas-fs .content-layer, body.mode-app.canvas-fs .panel { z-index: 111; }
/* дровер элемента полотна — те же секции, что у карточки агента */
.cv-row { display: flex; gap: 0.7rem; align-items: baseline; padding: 0.35rem 0;
  border-bottom: 1px solid var(--border); font-size: 14px; line-height: 1.5; }
.cv-row:last-of-type { border-bottom: 0; }
/* B5 (FR-UXI-68 ред. 3): дровер операции — подписи секций только иконками */
.drawer-sec.sec-icon { display: flex; align-items: center; gap: 0.5rem; margin: 1.3rem 0 0.6rem; }
.drawer-sec.sec-icon i { font-size: 15px; margin: 0; }
.drawer-sec.sec-icon::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.op-rows { display: flex; flex-direction: column; gap: 0.35rem; }
.op-rows.op-inline { flex-direction: row; flex-wrap: wrap; gap: 0; align-items: baseline; }
.op-link { background: transparent; border: 0; padding: 0.25rem 0; color: var(--text); font: inherit;
  font-size: 14px; text-align: left; cursor: pointer; text-decoration: underline;
  text-decoration-color: var(--dim); text-underline-offset: 3px; }
@media (hover: hover) { .op-link:hover { text-decoration-color: var(--text); } }
.op-link i { font-size: 11px; color: var(--dim); margin-left: 0.2rem; }
.op-plain, .op-sep { font-size: 14px; color: var(--text); }
/* FR-UXI-170 (B16, аудит: «Редактор документов,Работа с Markdown…» слипались):
   разделитель «, » — отдельный флекс-элемент, и его хвостовой пробел браузер
   схлопывает; зазор после запятой задаётся явно, а не пробелом */
.op-rows.op-inline .op-sep { margin-right: 0.3rem; }
.op-metrics { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; }
.op-metric-add { display: inline-flex; align-items: center; gap: 0.35rem; flex: 1 1 12rem; min-width: 0; }
.op-metric-input { flex: 1 1 auto; min-width: 0; min-height: 2.4rem; padding: 0.35rem 0.7rem; font-size: 13.5px; }
.op-metric-plus { width: 2.4rem; height: 2.4rem; flex: none; }
/* FR-UXI-169 (свежие глаза #25; владелец: «надо чтобы был»): у каждой метрики
   бара операции — текущее значение KPI («· сейчас 4 мин»), введённое в
   панели роли (FR-UXI-86); клик по значению раскрывает ТОТ ЖЕ ряд ввода с
   ✓/✗, что в панели роли (kpiRowHtml без имени метрики), сохраняет тем же
   POST …/kpi. Ряд метрики занимает всю строку, чип остаётся чипом. */
.op-metric-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem;
  flex: 1 1 100%; min-width: 0; }
.op-kpi-now { background: transparent; border: 0; padding: 0.15rem 0.3rem; margin: 0;
  color: var(--dim); font: inherit; font-size: 12.5px; line-height: 1.4; cursor: pointer;
  border-radius: 0.4rem; white-space: nowrap; }
.op-kpi-now b { color: var(--text); font-weight: 600; }
@media (hover: hover) { .op-kpi-now:hover { color: var(--text); background: var(--hover); } }
.op-kpi-now:focus-visible { outline: 1px solid var(--dim); outline-offset: 2px; }
.op-metric-row .org-kpi-row { flex: 1 1 100%; margin: 0; }
.op-metric-row .org-kpi-row[hidden] { display: none; }
.op-role-kpi { margin: 0.35rem 0 0; font-size: 12.5px; line-height: 1.5; color: var(--dim); }
.op-role-kpi b { color: var(--text); font-weight: 600; }
.op-logic { width: 100%; font-size: 14px; line-height: 1.5; resize: vertical; }
.cv-k { flex: 0 0 38%; color: var(--dim); font-size: 12.5px; }
.cv-v { flex: 1 1 auto; min-width: 0; color: var(--text); overflow-wrap: anywhere; }
.cv-list { margin: 0; padding-left: 1.1rem; }
.cv-list li { margin: 0.1rem 0; }
.cv-pre { margin: 0; padding: 0.7rem 0.8rem; border-radius: 0.6rem; background: var(--surface);
  font: 12.5px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  white-space: pre-wrap; overflow-wrap: anywhere; color: var(--text); }
.cv-link { width: 100%; margin-top: 0.45rem; text-align: left; }
.cv-link .cv-lbl { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.cv-link .cv-mark { flex: 0 0 auto; font-size: 11px; color: var(--dim); text-transform: uppercase;
  letter-spacing: 0.06em; }
.cv-link i:last-child { color: var(--dim); }
.cv-chips { margin-top: 0.5rem; }
.cv-doc { display: inline-flex; align-items: center; gap: 0.5rem; margin: 0.3rem 0.6rem 0 0;
  font-size: 13.5px; color: var(--text); text-decoration: none; }
@media (hover: hover) { .cv-doc:hover { color: var(--purple-l); } }
.drawer.canvas-mode .drawer-badge { background: var(--hover); color: var(--dim); }

/* ── B3-ORG: оргсхема уровнями и панель роли (FR-UXI-78…86, NFR-UXI-24) ── */
/* схема: панорамируемый холст (FR-UXI-80) — скролл внутри, страница не
   расползается; touch-action pan-x pan-y — палец двигает схему нативно */
.org-tree { display: block; position: relative; overflow: auto; cursor: grab;
  touch-action: pan-x pan-y; padding: 0.4rem 0 1rem; margin-top: 0.6rem;
  -webkit-overflow-scrolling: touch; scrollbar-width: thin;
  /* FR-UXI-80 ред. 2 (свежие глаза #24; владелец: «прокручивать ок»):
     схема из 10+ ролей ограничена по ВЫСОТЕ — обе оси прокручиваются
     внутри самой схемы (мышью, колесом, пальцем и перетаскиванием), а не
     растягивают страницу; 15rem — шапка, заголовок раздела, вкладки и
     поле снизу (замер 1280×720: при 14rem низ схемы уходил за окно на 6px).
     NFR-FE8: dvh с vh-фолбэком. */
  max-height: calc(100vh - 15rem); max-height: calc(100dvh - 15rem);
  min-height: 12rem; scrollbar-color: var(--ctrl-border) transparent; }
.org-tree::-webkit-scrollbar { width: 8px; height: 8px; }
.org-tree::-webkit-scrollbar-thumb { background: var(--ctrl-border); border-radius: 999px; }
.org-tree::-webkit-scrollbar-track { background: transparent; }
.org-tree.panning { cursor: grabbing; user-select: none; -webkit-user-select: none; }
.org-pan { position: relative; display: inline-block; min-width: 100%;
  white-space: nowrap; vertical-align: top; }
.org-lines { position: absolute; left: 0; top: 0; pointer-events: none;
  overflow: visible; }
.org-lines path { fill: none; stroke: var(--org-line); stroke-width: 1.5; }
/* ряд корней (и нижний ряд «Без руководителя») центрирован — CEO по
   середине (FR-UXI-79) */
.org-level { display: flex; justify-content: center; align-items: flex-start;
  gap: 0.75rem; white-space: nowrap; }
/* узел = колонка «карточка над рядом СВОИХ детей» (ред. 2 FR-UXI-79):
   руководитель по центру над своими подчинёнными, братья в одну линию,
   поддеревья соседей не накладываются — шины линий не сливаются */
.org-node { display: inline-flex; flex-direction: column; align-items: center;
  flex: none; }
.org-kids { display: flex; align-items: flex-start; gap: 0.75rem;
  margin-top: 2.6rem; }
.org-level-label { text-align: center; font-size: 12px; margin-top: 2.2rem;
  letter-spacing: 0.04em; text-transform: uppercase; }
.org-level-label + .org-level { margin-top: 0.7rem; }
.org-cards { display: flex; flex-wrap: wrap; gap: 0.6rem; }
/* FR-UXI-80 ред. 3: ряд ролей без руководителя не имеет линий связи —
   он переносится по ширине панели (иначе 55 ролей шаблона = 12 экранов
   вправо). Ряды с подчинением остаются одной строкой и панорамируются */
.org-level.org-level-loose { flex-wrap: wrap; justify-content: flex-start;
  white-space: normal; max-width: 100%; }
.org-pan.org-pan-flat { display: block; }
/* карточка: значок + имя + шеврон, графит, без рамок (FR-UXI-78) */
.org-card { display: inline-flex; align-items: center; gap: 0.55rem; width: auto;
  min-width: 160px; max-width: 240px; min-height: 44px; padding: 0.6rem 0.7rem 0.6rem 0.75rem;
  background: var(--surface); border: 1px solid transparent; border-radius: 0.8rem;
  color: var(--text); font: inherit; font-size: 14px; text-align: left; cursor: pointer;
  flex: none; position: relative; white-space: nowrap; transition: background 0.15s ease; }
.org-card > i:first-child { color: var(--dim); font-size: 15px; width: 1.1rem;
  text-align: center; flex: none; }
.org-card-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* FR-UXI-80 ред. 4 (B16, владелец: «имена должны читаться»): в ПЛОСКОЙ сетке
   ролей без руководителя карточка не обязана быть одной строкой — линий
   связи у неё нет, и имя переносится на вторую строку (не больше двух,
   дальше «…»); предел ширины поднят до 20rem, чтобы имя до ~40 знаков
   помещалось целиком. В рядах с подчинением (.org-level/.org-kids)
   карточка прежняя — nowrap и 240px, иначе поедут шины линий FR-UXI-79. */
.org-level-loose .org-card { white-space: normal; max-width: 20rem; }
.org-level-loose .org-card-name { white-space: normal; display: -webkit-box;
  -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
  text-overflow: clip; line-height: 1.25; overflow-wrap: anywhere; }
.org-card-chev { color: var(--dim); font-size: 11px; flex: none; }
.org-card:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; }
.org-empty { margin: 1rem 0; }
/* ховер — токен --hover (DESIGN, FR-UXI-61): белый 8 % в тёмной теме, тёмный
   6 % в светлой; без запасных значений — токен объявлен в обеих темах (NFR-FE10) */
@media (hover: hover) {
  .org-card:hover { background-image: linear-gradient(var(--hover),
    var(--hover)); }
  .org-title-btn:hover .org-title-pen { opacity: 1; }
  .org-boss-item:hover, .org-op-row:hover, .org-map-head:hover,
  .org-sys-add:hover, .org-kpi-btn:hover, .org-sys-x:hover {
    background: var(--hover); }
  .org-boss-btn:hover { background-image: linear-gradient(var(--hover),
    var(--hover)); }
}
/* панель роли: имя = кнопка переименования (FR-UXI-82) */
.org-title-btn { display: inline-flex; align-items: center; gap: 0.5rem; max-width: 100%;
  background: transparent; border: 0; padding: 0; margin: 0; color: inherit; font: inherit;
  text-transform: inherit; letter-spacing: inherit; text-align: left; cursor: text; }
.org-title-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.org-title-pen { color: var(--dim); font-size: 13px; opacity: 0; flex: none;
  transition: opacity 0.15s ease; }
.org-title-btn:focus-visible .org-title-pen { opacity: 1; }
.org-title-input { font-size: 15px; padding: 0.55rem 0.75rem; text-transform: none; }
.org-title-err { margin-top: 0.3rem; }
/* руководитель: поле со списком и поиском (FR-UXI-83) */
.org-boss { position: relative; }
.org-boss-btn { display: flex; align-items: center; gap: 0.6rem; width: 100%;
  min-height: 44px; padding: 0.55rem 0.8rem; background: var(--surface);
  border: 1px solid var(--border); border-radius: 0.7rem; color: var(--text);
  font: inherit; font-size: 14px; text-align: left; cursor: pointer;
  transition: background 0.15s ease; }
.org-boss-val { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.org-boss-chev { color: var(--dim); font-size: 12px; flex: none;
  transition: transform 0.2s ease; }
.org-boss-btn[aria-expanded="true"] .org-boss-chev { transform: rotate(180deg); }
.org-boss-list { position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 5;
  background: var(--surface); border: 1px solid var(--border); border-radius: 0.7rem;
  padding: 0.45rem; max-height: 16rem; overflow: auto; }
.org-boss-search { width: 100%; font-size: 14px; padding: 0.55rem 0.75rem;
  border-radius: 0.55rem; margin-bottom: 0.35rem; }
.org-boss-items { display: flex; flex-direction: column; gap: 2px; }
.org-boss-item { display: flex; align-items: center; gap: 0.5rem; width: 100%;
  min-height: 40px; padding: 0.45rem 0.65rem; background: transparent; border: 0;
  border-radius: 0.5rem; color: var(--text); font: inherit; font-size: 14px;
  text-align: left; cursor: pointer; }
.org-boss-item.current { color: var(--heading); font-weight: 600; }
.org-boss-item.current::after { content: "\f00c"; font-family: "Font Awesome 6 Free";
  font-weight: 900; margin-left: auto; font-size: 11px; color: var(--purple-l); }
.org-boss-none { padding: 0.5rem 0.65rem; }
/* системы: иконка + имя, ручные — с крестиком (FR-UXI-84) */
.org-sys-list { display: flex; flex-wrap: wrap; gap: 0.45rem; align-items: center; }
.org-sys-chip { display: inline-flex; align-items: center; gap: 0.45rem; min-height: 32px;
  padding: 0.3rem 0.65rem; background: var(--surface); border-radius: 0.6rem;
  font-size: 13px; color: var(--text); }
.org-sys-chip > i { color: var(--dim); font-size: 13px; }
.org-sys-x, .org-sys-add, .org-kpi-btn { position: relative; display: inline-flex;
  align-items: center; justify-content: center; width: 26px; height: 26px;
  border-radius: 999px; border: 0; background: transparent; color: var(--dim);
  font-size: 12px; cursor: pointer; flex: none; padding: 0; }
.org-sys-x::after, .org-sys-add::after, .org-kpi-btn::after { content: ""; position: absolute;
  left: 50%; top: 50%; width: 44px; height: 44px; transform: translate(-50%, -50%); }
.org-sys-x { margin: 0 -0.3rem 0 -0.1rem; }
.org-sys-add { width: 32px; height: 32px; background: var(--surface); }
.org-sys-add[aria-expanded="true"] { color: var(--heading); }
.org-sys-pick { display: flex; flex-direction: column; gap: 2px; margin-top: 0.5rem;
  padding: 0.35rem; background: var(--surface); border-radius: 0.6rem; }
.org-sys-empty { margin: 0; }
/* карта процессов: аккордеон процесс → операции (FR-UXI-85) */
.org-map-proc + .org-map-proc { margin-top: 0.25rem; }
.org-map-head { display: flex; align-items: center; gap: 0.55rem; width: 100%;
  min-height: 40px; padding: 0.4rem 0.5rem; background: transparent; border: 0;
  border-radius: 0.5rem; color: var(--heading); font: inherit; font-size: 14px;
  font-weight: 600; text-align: left; cursor: pointer; }
.org-map-chev { color: var(--dim); font-size: 11px; flex: none; transition: transform 0.2s ease; }
.org-map-proc:not(.open) .org-map-chev { transform: rotate(-90deg); }
.org-map-proc:not(.open) .org-map-ops { display: none; }
.org-map-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.org-map-ops { margin: 0.1rem 0 0.4rem 0.95rem; padding-left: 0.7rem;
  border-left: 1px solid var(--border); }
.org-op-row { display: flex; align-items: center; gap: 0.5rem; width: 100%;
  min-height: 40px; padding: 0.4rem 0.5rem; background: transparent; border: 0;
  border-radius: 0.5rem; color: var(--text); font: inherit; font-size: 14px;
  text-align: left; cursor: pointer; }
.org-op-row > i:first-child { color: var(--dim); font-size: 12px; flex: none; }
.org-op-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.org-op-arrow { color: var(--dim); font-size: 11px; flex: none; }
.org-map-wait { margin: 0; }
/* KPI операции: значение + галочка/крестик (FR-UXI-86) */
.org-kpi-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem;
  padding: 0.15rem 0 0.15rem 1.6rem; }
.org-kpi-name { flex: 1 1 8rem; min-width: 0; color: var(--dim); font-size: 13px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.org-kpi-input { width: 7.5rem; min-height: 32px; padding: 0.3rem 0.55rem;
  background: var(--surface); border: 1px solid transparent; border-radius: 0.5rem;
  color: var(--text); font: inherit; font-size: 13px; }
.org-kpi-input:focus { outline: none; border-color: var(--purple); }
.org-kpi-btn { display: none; }
.org-kpi-row.dirty .org-kpi-btn { display: inline-flex; }
.org-kpi-btn.ok { color: var(--heading); }
.org-kpi-btn[disabled] { opacity: 0.5; cursor: default; }
.org-kpi-err { flex-basis: 100%; font-size: 12px; margin: 0; }
@media (max-width: 767px) {
  .org-card { min-width: 150px; max-width: 220px; }
  .org-level, .org-kids { gap: 0.55rem; }
  /* FR-UXI-80 ред. 4: на телефоне роли плоской сетки идут «столбиком друг за
     другом» — одна карточка в ряд на всю ширину (раньше 220px из 361 и 40 %
     ширины справа пустовали); ряды с подчинением по-прежнему панорамируются */
  .org-level-loose .org-card { width: 100%; max-width: none; }
  .org-tree { margin-left: -0.5rem; margin-right: -0.5rem; padding-left: 0.5rem;
    padding-right: 0.5rem; }
}

/* ── B3-ROADMAP: «Обновить карту», меню целей/приоритетов, группы по процессам,
   галочка «внедрён» (SPEC-UX-INTERVIEW §14.5, FR-UXI-87…93, NFR-UXI-26).
   Поверхности — var(--surface), ховер — var(--hover) (токен потока DESIGN,
   объявлен в обеих темах — без запасных значений, NFR-FE10), иконки
   монохромные; единственное цветное место —
   заливка статуса «внедрён». ── */
.road-toast { position: fixed; left: 50%; bottom: 1.5rem; transform: translateX(-50%);
  z-index: 170; background: var(--surface); border: 1px solid var(--border);
  color: var(--text); border-radius: 999px; padding: 0.6rem 1.1rem; font-size: 13px;
  max-width: min(90vw, 32rem); text-align: center; }
.road-notice { margin: 0 0 0.6rem; padding: 0.55rem 0.8rem; border-radius: 0.7rem;
  border: 1px solid var(--border); color: var(--text); font-size: 12.5px; }
.road-offline { margin: 0.4rem 0 0; }
.road-offline i { margin-right: 0.35rem; }
/* меню (десктоп — карточка справа под шапкой) */
.road-menu-veil { position: fixed; inset: 0; z-index: 150; background: rgba(0,0,0,0.45); }
.road-menu { position: fixed; top: 4.4rem; right: 1rem; width: min(31rem, calc(100vw - 2rem));
  max-height: calc(100vh - 6rem); overflow: auto; background: var(--surface);
  border: 1px solid var(--border); border-radius: 1.1rem; padding: 1rem 1.1rem 1.1rem;
  z-index: 151; color: var(--text); }
.road-menu-head { display: flex; align-items: center; justify-content: space-between; }
.road-menu-head b { font-size: 15px; color: var(--heading); display: inline-flex;
  align-items: center; gap: 0.5rem; }
.road-menu-head b i { color: var(--dim); font-size: 13px; }
.road-menu-x { width: 44px; height: 44px; border: 0; background: transparent; color: var(--dim);
  font-size: 18px; cursor: pointer; border-radius: 50%; margin-right: -0.6rem; }
@media (hover: hover) { .road-menu-x:hover { background: var(--hover); } }
.road-menu-label { font-size: 10px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--dim); margin: 0.9rem 0 0.4rem; }
.road-menu-note { margin: 0.3rem 0 0; }
/* строки целей: галочка · метрика · цель · сейчас · ✕ */
.road-goal-head, .road-goal-row { display: grid; align-items: center; gap: 0.5rem;
  grid-template-columns: 2rem minmax(0, 1fr) 5.6rem 5.6rem 1.8rem; }
.road-goal-head { font-size: 10.5px; color: var(--dim); text-transform: uppercase;
  letter-spacing: 0.06em; padding: 0 0.1rem 0.3rem; }
.road-goal-row { padding: 0.5rem 0.1rem; border-top: 1px solid var(--border); }
.road-goal-check { width: 2rem; height: 2rem; border-radius: 0.5rem; border: 1px solid var(--border);
  background: transparent; color: transparent; cursor: pointer; display: inline-flex;
  align-items: center; justify-content: center; position: relative; font-size: 12px; padding: 0; }
.road-goal-check::after { content: ''; position: absolute; inset: -6px; }
.road-goal-check.on { border-color: var(--purple); background: var(--purple); color: #fff; }
.road-goal-name { font-size: 13.5px; color: var(--heading); overflow-wrap: anywhere; }
.road-goal-sub { font-size: 11.5px; color: var(--dim); margin-top: 0.1rem; }
.road-goal-op { background: none; border: 0; padding: 0; color: var(--dim); font: inherit;
  font-size: 11.5px; cursor: pointer; text-align: left; overflow-wrap: anywhere; }
@media (hover: hover) { .road-goal-op:hover { color: var(--heading); } }
.road-goal-op .sep { margin: 0 0.35rem; opacity: 0.6; }
.road-goal-custom { font-style: italic; }
.road-goal-val { min-width: 0; }
.road-val { width: 100%; min-height: 2.2rem; border: 1px solid var(--border); border-radius: 0.6rem;
  background: transparent; color: var(--text); font: inherit; font-size: 13px; cursor: pointer;
  padding: 0.3rem 0.55rem; text-align: left; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
@media (hover: hover) { .road-val:hover { background: var(--hover); } }
.road-val.empty { color: var(--dim); }
.road-val-edit { display: flex; align-items: center; gap: 0.15rem; min-width: 0; }
.road-input { width: 100%; min-width: 0; height: 2.2rem; border: 1px solid var(--purple);
  border-radius: 0.6rem; background: var(--input-bg); color: var(--text);
  font: inherit; font-size: 13px; padding: 0 0.5rem; }
.road-goal-add .road-input { border-color: var(--border); }
.road-val-ok, .road-val-x, .road-goal-del { width: 1.8rem; height: 1.8rem; flex: 0 0 auto; border: 0;
  border-radius: 50%; background: transparent; color: var(--dim); cursor: pointer; font-size: 12px;
  display: inline-flex; align-items: center; justify-content: center; padding: 0; position: relative; }
.road-val-ok::after, .road-val-x::after, .road-goal-del::after { content: ''; position: absolute; inset: -8px; }
.road-val-ok { color: var(--heading); }
@media (hover: hover) { .road-val-ok:hover, .road-val-x:hover, .road-goal-del:hover {
  background: var(--hover); } }
.road-goal-addbtn { margin-top: 0.6rem; background: none; border: 1px dashed var(--border);
  border-radius: 0.7rem; color: var(--dim); font: inherit; font-size: 13px; padding: 0.55rem 0.8rem;
  cursor: pointer; width: 100%; text-align: left; min-height: 44px; }
@media (hover: hover) { .road-goal-addbtn:hover { color: var(--heading); border-color: var(--heading); } }
.road-menu .prio-list { gap: 0.4rem; }
.road-menu .prio-item { padding: 0.6rem 0.8rem; font-size: 13.5px; min-height: 44px; }
.road-menu-cta { margin-top: 1rem; }
/* карта: группы по процессам */
.road-groups { margin-top: 0.8rem; display: flex; flex-direction: column; gap: 0.8rem; }
.road-proc { background: var(--surface); border: 1px solid var(--border); border-radius: 1.1rem;
  overflow: hidden; }
.road-proc-head { display: flex; align-items: center; gap: 0.7rem; width: 100%; padding: 0.9rem 1.1rem;
  min-height: 52px; background: none; border: 0; color: var(--heading); font: inherit;
  font-size: 15px; font-weight: 700; text-align: left; cursor: pointer; }
@media (hover: hover) { .road-proc-head:hover { background: var(--hover); } }
.road-proc-ico { color: var(--dim); width: 1.2rem; text-align: center; font-size: 14px; }
.road-proc-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.road-proc-count { font-size: 12px; font-weight: 600; color: var(--dim); display: inline-flex;
  gap: 0.3rem; align-items: center; white-space: nowrap; }
.road-proc-chev { color: var(--dim); font-size: 12px; transition: transform 0.2s ease; }
.road-proc.collapsed .road-proc-chev { transform: rotate(-90deg); }
.road-proc-body { border-top: 1px solid var(--border); }
.road-agent { display: flex; align-items: center; gap: 0.9rem; padding: 0.85rem 1.1rem; cursor: pointer;
  border-top: 1px solid var(--border); }
.road-agent:first-child { border-top: 0; }
@media (hover: hover) { .road-agent:hover { background: var(--hover); } }
.road-agent-main { flex: 1 1 auto; min-width: 0; }
.road-agent-title b { font-size: 14px; color: var(--heading); }
.road-agent-metrics { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.4rem; }
.road-chip { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 11.5px;
  padding: 0.2rem 0.6rem; border-radius: 999px; border: 1px solid var(--border); color: var(--dim); }
.road-chip i { font-size: 10px; }
.road-chip.hit { color: var(--heading); border-color: var(--heading); font-weight: 600; }
.road-agent-ops { font-size: 12px; color: var(--dim); margin-top: 0.4rem; }
.road-agent-ops i { margin-right: 0.3rem; font-size: 11px; }
.road-dev { padding: 0.5rem 0.9rem; font-size: 12px; min-height: 2.4rem; }
.road-dev:disabled { opacity: 0.5; cursor: default; }
/* FR-UXI-143 ред. 4: обёртка закрытой кнопки несёт подсказку «почему закрыто»
   — она получает наведение и там, где disabled-кнопка события не отдаёт */
.road-dev-wrap { display: inline-flex; align-items: center; }
.road-done { width: 2.6rem; height: 2.6rem; color: var(--dim); }
.road-done.on { color: #fff; border-color: transparent;
  background: linear-gradient(135deg, var(--purple), var(--orange)); }
/* мобилка: меню — нижний лист, строки — в одну колонку (NFR-UXI-26) */
@media (max-width: 640px) {
  /* ред. 2 (батч 4, FR-UXI-113): нижний лист снят — меню по центру и на
     телефоне, правило живёт в блоке B4-PANELS в конце файла */
  .road-goal-head { display: none; }
  .road-goal-row { grid-template-columns: 2rem minmax(0, 1fr) 1.8rem; row-gap: 0.35rem;
    grid-template-areas: "chk name del" ". target target" ". current current"; }
  .road-goal-check { grid-area: chk; }
  .road-goal-main { grid-area: name; }
  .road-goal-del, .road-goal-del-ph { grid-area: del; }
  .road-goal-val[data-col="target"] { grid-area: target; }
  .road-goal-val[data-col="current"] { grid-area: current; }
  .road-goal-val { display: flex; align-items: center; gap: 0.5rem; }
  .road-goal-val::before { content: attr(data-lbl); font-size: 10.5px; color: var(--dim);
    text-transform: uppercase; letter-spacing: 0.06em; flex: 0 0 3.6rem; }
  .road-goal-val .road-val, .road-goal-val .road-val-edit, .road-goal-val .road-input { flex: 1 1 auto; min-width: 0; }
  .road-agent { flex-direction: column; align-items: stretch; gap: 0.6rem; }
}

/* ── B3-PROGRESS: кружки прогресса внедрения и обучения ── */
/* FR-UXI-95/97/100, NFR-UXI-29. Кольцо 1em (= кегль строки сайдбара): доля
   --p (0..1) заливается градиентом фиолетовый → оранжевый по часовой стрелке,
   остаток — тонкий серый трек (var(--track)); отверстие вырезано маской, так что
   подсветка строки на ховере видна сквозь него. Цифр рядом нет — подпись
   «3 из 5 агентов внедрено» живёт в title/aria-label. */
.prog-ring { --p: 0; flex: 0 0 auto; width: 1em; height: 1em; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  vertical-align: -0.125em; box-sizing: border-box; pointer-events: none;
  background: conic-gradient(var(--purple) 0deg,
    var(--orange) calc(var(--p) * 360deg), var(--track) calc(var(--p) * 360deg));
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2.6px),
    #000 calc(100% - 1.6px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 2.6px),
    #000 calc(100% - 1.6px)); }
/* всё внедрено / курс пройден: диск залит целиком, внутри белая галочка */
.prog-ring.done { -webkit-mask: none; mask: none;
  background: linear-gradient(135deg, var(--purple), var(--orange)); }
/* галочка рисуется бордерами самого <i> — не зависит от загрузки webfont
   Font Awesome (офлайн рендер-чеки его не видят, а галочка обязана быть);
   класс fa-check остаётся семантикой разметки */
.prog-ring.done i { display: block; width: 0.3em; height: 0.55em; margin-top: -0.14em;
  box-sizing: border-box; border: solid #fff; border-width: 0 0.14em 0.14em 0;
  transform: rotate(45deg); font-size: inherit; line-height: 0; color: #fff; }
.prog-ring.done i::before { content: none; }
.nav-item.course-nav .prog-ring { margin-right: 0.15rem; }
.course-name .prog-ring { font-size: 15px; margin-right: 0.15rem; }
/* рейка (FR-UXI-20): списки скрыты — сводный кружок у иконки секции */
.rail-ring { display: none; }
body.side-rail .side-sec { position: relative; }
body.side-rail .rail-ring { display: inline-flex; position: absolute;
  font-size: 9px; right: 11px; top: 9px; }

/* ── B4-IV2 ── интервью: подсказки виджетов и поле метрики (батч 4) ── */
/* FR-UXI-135: одноразовая подсказка виджета — строка серым В ПОТОКЕ виджета
   (не оверлей, поля не перекрывает по построению), без цветных плашек и
   рамок, только токены темы; крестик — настоящая тач-цель 44px
   (NFR-UXI-11), визуально компактная за счёт отрицательных полей */
.ux-tip { display: flex; align-items: flex-start; gap: 0.55rem;
  margin: 0.2rem 0 0.7rem; color: var(--dim); font-size: 12.5px;
  line-height: 1.5; }
.ux-tip > i { flex: 0 0 auto; margin-top: 0.22rem; font-size: 12px;
  color: var(--dim); }
.ux-tip-text { flex: 1 1 auto; min-width: 0; overflow-wrap: break-word; }
.ux-tip-x { flex: 0 0 auto; width: 2.75rem; height: 2.75rem;
  margin: -0.7rem -0.75rem -0.7rem 0; border: 0; background: transparent;
  color: var(--dim); cursor: pointer; font-size: 13px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  transition: color 0.2s ease; }
@media (hover: hover) { .ux-tip-x:hover { color: var(--text); } }
/* FR-UXI-131: секция метрики — та же .ux-sec, иконка fa-chart-simple
   монохромом (NFR-UXI-2 ред. 3), ничего цветного */
.ux-sec .ux-sec-ico .fa-chart-simple { color: inherit; }

/* ── B4-AGENT: паспорт агента — системы, артефакты, «что умеет», «как пользоваться» ── */
/* FR-PRC57 (владелец 2026-09-02: «какие системы используются… какие артефакты
   используют и создают… что они умеют и как ими пользоваться»). Чипы систем —
   те же .org-sys-chip, что у роли (FR-UXI-84); артефакты и умения — ul.dots
   (FR-UXI-65); текст «как пользоваться» — .dr-text. Элементы не интерактивны,
   ховеров нет; на экране «Агенты» — строка систем под именем, иконка + имя. */
.agent-arts { display: flex; flex-direction: column; gap: 0.35rem; }
.agent-art-lbl { margin: 0.3rem 0 0; font-size: 12px; letter-spacing: 0.04em;
  color: var(--dim); }
.agent-art-list, .agent-can { font-size: 14px; line-height: 1.6; color: var(--text); }
.agent-art-list > li, .agent-can > li { align-items: flex-start; }
.agent-howto { white-space: pre-line; }
.agent-sys-line { margin: 0.45rem 0 0; display: flex; flex-wrap: wrap;
  gap: 0.3rem 0.75rem; font-size: 12.5px; line-height: 1.5; color: var(--dim); }
.agent-sys-line > span { display: inline-flex; align-items: center; gap: 0.3rem;
  min-width: 0; }
.agent-sys-line i { color: var(--dim); font-size: 12px; }

/* ── B4-PANELS: панель роли (артефакты, ИИ-агенты), дорожная карта (значок
   «внедрён» в строке, ряд «Разработать» + галочка в карточке), попапы по
   центру («Обновить карту», «Поддержка») — SPEC-UX-INTERVIEW §15.2,
   FR-UXI-111…119, NFR-UXI-34/35; ARCH §4.7b. Владелец 2026-09-02: «когда
   открываешь обновить карту, то по центру попап открывается / поддержка
   также попапом открывается», «не надо писать "Внедрен"». Токены темы,
   ховеры только под @media (hover: hover), тач-цели ≥44px. ── */
/* панель роли: артефакты — точки (FR-UXI-65), имя и мелко «операция · процесс» */
.org-art-list > li { align-items: baseline; flex-wrap: wrap; padding: 0.2rem 0; font-size: 14px;
  color: var(--text); }
.org-art-name { min-width: 0; overflow-wrap: anywhere; }
.org-art-sub { font-size: 11.5px; color: var(--dim); margin-left: 0.15rem; overflow-wrap: anywhere; }
/* панель роли: ИИ-агенты — строки-кнопки, как операции карты (FR-UXI-116) */
.org-agent-list { display: flex; flex-direction: column; }
.org-agent-row { display: flex; align-items: center; gap: 0.55rem; width: 100%;
  min-height: 44px; padding: 0.45rem 0.5rem; background: transparent; border: 0;
  border-radius: 0.5rem; color: var(--text); font: inherit; font-size: 14px;
  text-align: left; cursor: pointer; }
@media (hover: hover) { .org-agent-row:hover { background: var(--hover); } }
.org-agent-ico { color: var(--dim); font-size: 12px; flex: none; width: 1.1rem; text-align: center; }
.org-agent-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.org-agent-role { font-weight: 600; color: var(--heading); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.org-agent-sub { font-size: 11.5px; color: var(--dim); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.org-agent-done { color: var(--dim); font-size: 12px; flex: none; }
/* карточка агента: значки робота/человека — монохром вместо эмодзи (NFR-UXI-35) */
.dr-title-ico { font-size: 0.8em; color: var(--dim); margin-right: 0.1em; }
.dr-human-ico { color: var(--dim); font-size: 12px; margin-right: 0.15rem; }
/* дорожная карта: строка агента — значок робота и маленькая галочка справа
   (только у .road-agent.on; кнопок в строке больше нет — FR-UXI-112) */
.road-agent-ico { color: var(--dim); font-size: 12px; margin-right: 0.25rem; }
.road-agent-done { display: none; flex: 0 0 auto; color: var(--dim); font-size: 13px;
  width: 1.4rem; height: 1.4rem; line-height: 1.4rem; text-align: center; }
.road-agent.on .road-agent-done { display: inline-block; }
/* карточка агента: ряд «Разработать» (закрыто) + галочка «внедрён» (FR-UXI-117) */
.drawer-dev-row { margin-top: 1.6rem; align-items: center; gap: 0.8rem; }
/* чипы метрик: значок подтянут к тексту (FR-UXI-118) */
.road-chip { gap: 0; }
.road-chip i { vertical-align: -1px; margin-right: 0.35rem; }
/* B5 (FR-UXI-91 ред. 3): метрики и операции агента — ссылки, стрелка справа */
.road-link { cursor: pointer; font: inherit; }
/* NFR-UXI-16 ред. 2 / FR-UXI-91 ред. 4 (B16, аудит: чипы метрик «серым по
   серому»): чип стал кнопкой (B5), и у него проступала системная заливка
   кнопки (ButtonFace, rgb(107,107,107)) под текстом --dim — 1.9:1. Заливку
   снимаем, текст — тем же токеном, что у соседних ссылок операций (--text);
   «попадание в цель» (.hit) по-прежнему --heading. Токены обеих тем дают
   ≥4.5:1 на --surface. */
button.road-chip { border-style: solid; background: transparent; color: var(--text); }
.road-op-link { background: transparent; border: 0; padding: 0; color: var(--text); font-size: inherit;
  text-decoration: underline; text-decoration-color: var(--dim); text-underline-offset: 3px; }
@media (hover: hover) { .road-op-link:hover, button.road-chip:hover { text-decoration-color: var(--text); } }
.road-agent-go { flex: none; margin-left: 0.5rem; align-self: center; }
/* меню «Обновить карту» — попап по центру на всех ширинах (FR-UXI-113,
   ред. 2 FR-UXI-88): перекрывает карточку справа и нижний лист B3 */
.road-menu { top: 50%; left: 50%; right: auto; bottom: auto; transform: translate(-50%, -50%);
  width: min(34rem, calc(100vw - 2rem)); max-height: calc(100vh - 3rem); }
/* строка заголовка «Цели» с круглой кнопкой «+» справа (FR-UXI-118) */
.road-menu-row { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem;
  margin: 0.6rem 0 0.2rem; }
.road-menu-row .road-menu-label { margin: 0; }
.ctrl-round.road-goal-addbtn { width: 44px; height: 44px; min-height: 44px; margin: 0; padding: 0;
  border: 1px solid var(--ctrl-border); border-radius: 999px; color: var(--heading);
  text-align: center; font-size: 15px; }
@media (hover: hover) { .ctrl-round.road-goal-addbtn:hover { color: var(--heading);
  border-color: var(--ctrl-border); background-image: linear-gradient(var(--hover), var(--hover)); } }
/* строка цели: выравнивание по верху, галочка к линии имени, воздух между
   именем и подписью «операция | процесс» (FR-UXI-118) */
.road-goal-row { align-items: start; }
.road-goal-row .road-goal-check { margin-top: 0.1rem; }
.road-goal-sub { margin-top: 0.3rem; }
/* попап «Поддержка» (FR-UXI-114, ред. 2 FR-UXI-51): та же .modal-card, шире */
.sup-card { position: relative; width: min(36rem, 100%); max-height: calc(100vh - 2rem);
  overflow: auto; background: var(--surface); padding: 1.3rem 1.6rem 1.6rem; }
/* B5 (FR-UXI-114 ред. 2): заголовок «Поддержка» по центру, крестик — в углу */
.sup-head { display: flex; align-items: center; justify-content: center; gap: 0.6rem; position: relative; }
.sup-head .sup-close { position: absolute; right: 0; top: 50%; transform: translateY(-50%); }
.sup-title { margin: 0; font-size: clamp(1.05rem, 1.5vw, 1.35rem); font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--heading); }
.sup-close { width: 44px; height: 44px; border: 0; background: transparent; color: var(--dim);
  font-size: 18px; cursor: pointer; border-radius: 50%; margin-right: -0.6rem; flex: none;
  display: inline-flex; align-items: center; justify-content: center; }
@media (hover: hover) { .sup-close:hover { background: var(--hover); color: var(--heading); } }
.sup-card .sup-form { max-width: none; margin-top: 0.9rem; }
.sup-card .sup-done { max-width: none; padding: 2rem 0 0.5rem; }
@media (max-width: 640px) {
  .road-menu { top: 50%; left: 50%; right: auto; bottom: auto; width: min(34rem, calc(100vw - 1rem));
    max-height: calc(100vh - 2rem); border-radius: 1.1rem; padding-bottom: 1.1rem; }
  .sup-overlay { padding: 0.5rem; }
  .sup-card { width: 100%; max-height: calc(100vh - 1rem); padding: 1.1rem 1.1rem 1.3rem; }
}

/* ── B4-HEADER (батч 4, владелец 2026-09-02): заголовок под шапкой · поиск по
   центру · факты в карточке · страница процесса (FR-UXI-101…104, FR-UXI-66
   ред. 2, FR-UXI-67 ред. 2, NFR-UXI-30) ── */
/* В строке шапки от заголовка осталась стрелка «назад»: слот больше не
   растягивается (иначе он делил бы свободное место с полем поиска, и поле
   уезжало бы от центра); стрелка стоит у лого с прежним зазором FR-W28. */
.header-row .header-title { flex: 0 0 auto; }
/* FR-UXI-101: заголовок экрана ПОД шапкой — первый ребёнок .scroll, по центру
   панели, в одну строку; тот же кегль/капс, что был в шапке; переполнение —
   бегущей строкой (.hdr-title-text.is-overflow из блока B3-DESIGN). */
.screen-title { display: flex; justify-content: center; align-items: center;
  width: 100%; max-width: 62rem; min-width: 0; padding: 0.1rem 0 0;
  text-align: center; }
.screen-title .hdr-title-text { display: inline-block; max-width: 100%;
  font-size: clamp(1.05rem, 1.5vw, 1.5rem); font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--heading);
  white-space: nowrap; overflow: hidden; line-height: 1.3; min-width: 0; }
/* FR-UXI-171 (B16, аудит 14-op-drawer: заголовок «ПРИЁМ КЛИЕНТА И СБОР КОН…»
   уходил под открытый бар операции). Пока открыт бар с полотна
   (body.canvas-drawer, ставит openCanvasDrawer), заголовок раздела получает
   справа тот же отступ, что полотно от canvasInset(): ширина бара
   (min(460px, 100vw)) минус то, что от правого края заголовка до края окна.
   Считается чистым CSS от геометрии колонки: правый край заголовка =
   центр колонки + половина его ширины (min(62rem, ширина экрана − 2·1.2rem),
   экран ≤68rem по центру области справа от сайдбара 280px). Порог 780px —
   тот же, что у canvasInset: уже него бар накрывает всё поле, и отступ
   бессмыслен. На планшете (780–1023px) колонка = окно минус поля панели. */
@media (min-width: 780px) and (max-width: 1023px) {
  body.canvas-drawer .screen-title { padding-right: calc(460px - 1.2rem); }
}
@media (min-width: 1024px) {
  body.canvas-drawer .screen-title { padding-right:
    max(0px, calc(460px - 50vw + min(31rem, 50vw - 1.2rem))); }
  body.canvas-drawer.side-open .screen-title { padding-right:
    max(0px, calc(600px - 50vw + min(31rem, 50vw - 140px - 1.2rem))); }
  /* сайдбар свёрнут в рейку 64px (FR-UXI-20) — колонка сдвинута на её ширину */
  body.canvas-drawer.side-open.side-rail .screen-title { padding-right:
    max(0px, calc(492px - 50vw + min(31rem, 50vw - 32px - 1.2rem))); }
}
/* FR-UXI-102: табы AS-IS/TO-BE стоят сразу за заголовком — без лишнего воздуха */
.screen.active[data-screen="process"] #proc-detail .dg-tabs-row { margin-top: 0; }
/* FR-UXI-104 / FR-W50n ред. 3: цель · метрика · триггер — три строки карточки
   процесса, каждая в ОДНУ строку; значок монохромный (--dim, FR-UXI-63);
   переполнение едет бегущей строкой (.mq-slot.is-overflow, fitMarquee) */
.tile-facts { display: flex; flex-direction: column; gap: 0.3rem; margin-top: -0.1rem;
  min-width: 0; }
.tile-fact { display: flex; align-items: center; gap: 0.5rem; min-width: 0;
  font-size: 12.5px; line-height: 1.5; color: var(--text); }
.tile-fact i { color: var(--dim); font-size: 11.5px; flex: none; width: 1rem;
  text-align: center; }
.tile-fact-link { cursor: pointer; }
/* FR-ORG7 ред. 2 (аудит S22): подпись автора у чужого процесса — той же
   строкой, что и факты плитки, но приглушённой: это метка, не факт */
.proc-tile-author { display: flex; align-items: center; gap: 0.5rem; min-width: 0;
  font-size: 12px; line-height: 1.5; color: var(--dim); }
.proc-tile-author i { font-size: 11px; flex: none; width: 1rem; text-align: center; }
.tile-fact-link .mq-text { text-decoration: underline; text-decoration-color: var(--dim);
  text-underline-offset: 3px; }
@media (hover: hover) { .tile-fact-link:hover .mq-text { text-decoration-color: var(--text); } }
.mq-slot { flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; }
.mq-text { display: inline-block; white-space: nowrap; vertical-align: top; }
/* FR-UXI-104 ред. 4 (B16, аудит mobile/01-m-cabinet: средний факт плитки
   «отстоял» от значка, а первый и третий «прижимались»). Бегущая строка
   начиналась на 0.5rem ЛЕВЕЕ статичной (margin-left −0.5rem под затухание
   левого края + набивка текста), и посреди анимации видимое начало текста
   оказывалось в зоне затухания — у самого значка, тогда как строка без
   бега стояла на своём месте. Теперь у всех трёх строк один зазор от значка:
   слот бегущей строки стоит там же, где статичный, левый край режется по
   краю слота, затухает только правый (как и в reduced-motion ниже). */
.mq-slot.is-overflow {
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 0.5rem), transparent 100%);
  mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 0.5rem), transparent 100%); }
.mq-slot.is-overflow .mq-text { padding: 0 0.5rem 0 0; will-change: transform;
  animation: hdr-marquee var(--mq-dur, 9s) ease-in-out infinite alternate; }
@media (hover: hover) {
  .proc-tile:hover .mq-slot.is-overflow .mq-text { animation-play-state: paused; }
}
@media (prefers-reduced-motion: reduce) {
  .mq-slot.is-overflow .mq-text { animation: none; }
  .mq-slot.is-overflow {
    -webkit-mask-image: linear-gradient(90deg, #000 85%, transparent 100%);
    mask-image: linear-gradient(90deg, #000 85%, transparent 100%); }
}
/* телефон: поле поиска сжимается между группами (не уже 8rem), выдача — от
   края до края шапки (якорь — сама строка шапки, а не сжатое поле) */
@media (max-width: 640px) {
  .header-row .gs-input { height: 2.75rem; min-height: 2.75rem; font-size: 16px; }
  .header-row .gs-ico { left: 0.85rem; }
  /* left/width выставляет gsPlaceResults() по рамке .header-row (поле уже
     строки, а выдача должна лечь от края до края) */
  .header-row .gs-results { right: auto; width: auto; min-width: 0;
    transform: none; top: calc(100% + 6px); }
  .screen-title .hdr-title-text { font-size: 1.05rem; }
}

/* владелец 2026-09-10: значки ⓘ и пузыри подсказок сняты целиком */
.tip-i, .ux-tip, .hint-bubble, [data-hint-bubble] { display: none !important; }

/* владелец 2026-09-10: дорожная карта — плоский список карточек; верхние
   карточки зрелости и обучения — того же вида, что карточки агентов */
.road-flat, .road-top { display: flex; flex-direction: column; gap: 10px; }
.road-top { margin-bottom: 10px; }
.road-card, .road-top-card { width: 100%; text-align: left; cursor: pointer;
  border: 1px solid var(--card-border); background: var(--card); border-radius: 14px;
  padding: 14px 16px; display: flex; align-items: center; gap: 12px; font: inherit; color: inherit; }
.road-card .road-agent-main, .road-top-card .road-agent-main { flex: 1 1 auto; min-width: 0; }
/* владелец 2026-09-10 (скрин): описание выводится целиком (2–3 строки на
   мобиле), без обрезки «…»; стрелка — всегда справа (см. медиа ниже) */
.road-agent-desc { margin-top: 4px; font-size: 13px; line-height: 1.35; }
.road-top-chev { flex: 0 0 auto; color: var(--dim); }
@media (max-width: 640px) {
  .road-card, .road-top-card { flex-direction: row; align-items: center; }
}
@media (hover: hover) { .road-card:hover, .road-top-card:hover { background-image: linear-gradient(var(--hover), var(--hover)); } }
/* полотно внутри шага интервью */
.step-canvas { margin: 8px 0 12px; }
.step-canvas .canvas-frame { width: 100%; min-height: 320px; border: 1px solid var(--card-border); border-radius: 12px; }

/* владелец 2026-09-10: папки в сайдбаре — шеврон, процессы правее, карандаш;
   бегущая строка едет только при наведении */
#side-processes .nav-folder { display: flex; align-items: center; gap: 6px; cursor: pointer; }
#side-processes .nav-folder .nav-fold-chev { font-size: 11px; transition: transform .15s; flex: 0 0 auto; }
#side-processes .nav-folder.closed .nav-fold-chev { transform: rotate(-90deg); }
#side-processes .nav-folder .nav-fold-pen { margin-left: auto; border: 0; background: none; color: var(--dim);
  cursor: pointer; padding: 2px 4px; font-size: 12px; opacity: 0; flex: 0 0 auto; }
#side-processes .nav-sub { padding-left: 1.9rem; }
#side-processes .nav-name .mq-slot { display: block; }
#side-processes .mq-slot.is-overflow .mq-text { animation-play-state: paused; }
/* NFR-FE10: :hover только под (hover: hover) — на таче карандаш виден всегда */
@media (hover: hover) {
  #side-processes .nav-folder:hover .nav-fold-pen { opacity: 1; }
  #side-processes .nav-item:hover .mq-slot.is-overflow .mq-text { animation-play-state: running; }
}
@media (hover: none) {
  #side-processes .nav-folder .nav-fold-pen { opacity: 1; }
  #side-processes .mq-slot.is-overflow .mq-text { animation-play-state: running; }
}
#side-processes .nav-folder .fname-input { width: 100%; font: inherit; padding: 2px 6px; }

/* ── B4-TIPS (батч 4, владелец 2026-09-02: «типсы проверь чтобы везде всё было
   понятно указано»): пузырь подсказки #tipbox, значок ⓘ .tip-i, коуч-строка
   экрана .coach. FR-UXI-141…146, NFR-UXI-40/41: только токены темы, без
   цветных плашек и теней, тач-цели ≥44px, ховеры лишь в @media (hover: hover),
   pointer-events: none у пузыря — клики сквозь него не перехватываются. ── */
.tipbox { position: fixed; z-index: 1100; max-width: 18rem; padding: 0.45rem 0.7rem;
  border-radius: 0.6rem; background: var(--card); color: var(--text);
  border: 1px solid var(--ctrl-border); font-size: 12.5px; line-height: 1.5;
  pointer-events: none; overflow-wrap: break-word; }
.tipbox[hidden] { display: none; }
.tip-i { position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 1.4rem; height: 1.4rem; margin-left: 0.15rem; padding: 0; border: 0;
  border-radius: 50%; background: transparent; color: var(--dim); font-size: 12px;
  line-height: 1; cursor: pointer; vertical-align: middle; font-family: inherit; }
/* тач-цель 3rem × 3rem (≥44px) поверх компактного значка */
.tip-i::after { content: ""; position: absolute; inset: -0.8rem; }
.tip-i:focus-visible { outline: 1px solid var(--dim); outline-offset: 2px; }
@media (hover: hover) { .tip-i:hover { color: var(--text); } }
/* ⓘ за парой табов AS-IS/TO-BE не сдвигает центровку табов (FR-UXI-102:
   табы по центру панели): значок висит справа, не занимая места в раскладке */
.dg-tabs-row > .tip-i { margin-right: -1.55rem; }

/* ── B16-MERGE (FR-UXI-181, владелец 2026-09-08: «спрашиваем у юзера —
   схлопнуть ли в одну сущность»): окно «Такая роль уже есть» на каркасе
   .modal-overlay > .modal-card (NFR-UXI-34) — только заголовок и имена,
   цвета токенами темы, без теней и рамок. ── */
.merge-card { width: min(26rem, 100%); }
.merge-title { margin: 0 0 0.55rem; font-size: 1.05rem; font-weight: 600; line-height: 1.35;
  color: var(--heading); }
.merge-text .merge-name { font-weight: 600; color: var(--heading); }

/* владелец 2026-09-10: между формами предыдущая форма остаётся на экране
   погашенной, крутится только её кнопка — пузыря со спиннером нет */
.log-row.log-busy .log-widget { opacity: .55; pointer-events: none; }
.log-row.log-busy .drawer-cta .btn-white { opacity: 1; }

/* причина гейта 402 под заголовком окна тарифов (чат-ленты нет — объяснение
   живёт в самом окне, FR-PAY4a ред. 2, 2026-09-10) */
.pw-gate { color: var(--dim); font-size: 14px; margin: 0.4rem 0 0; }

/* владелец 2026-09-10: генерируется TO-BE — крутилка в полотне, без слов */
.canvas-wait { min-height: 320px; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--card-border); border-radius: 12px; }
/* выбранная карточка роли подсвечена, текст остаётся */
.role-pick.on { border-color: var(--purple); background-image: linear-gradient(var(--hover), var(--hover)); }
/* гиперссылки в панелях: операции, системы, роли, артефакты — без стрелок и точек */
.fact-link { background: none; border: 0; padding: 0; margin: 0; font: inherit; color: var(--purple);
  cursor: pointer; text-align: left; }
@media (hover: hover) { .fact-link:hover { text-decoration: underline; } }
.fact-link.op-link { font-weight: inherit; }
.org-sys-chip.fact-chip { cursor: pointer; font: inherit; }

/* FR-PAY7 (2026-09-11): переключатель валюты в окне тарифов — $ / € */
.pw-cur-row { text-align: center; margin: -0.6rem 0 1.2rem; }
.pw-cur { display: inline-flex; gap: 0; margin: 0 auto; border: 1px solid var(--card-border);
  border-radius: 999px; padding: 3px; }
.pw-cur-btn { background: none; border: 0; border-radius: 999px; padding: 0.35rem 0.9rem;
  font: inherit; font-size: 13px; font-weight: 600; color: var(--dim); cursor: pointer; }
.pw-cur-btn.active { background: var(--purple); color: white; }
@media (hover: hover) { .pw-cur-btn:not(.active):hover { color: var(--text); } }
.pw-rate { color: var(--dim); font-size: 12.5px; margin: 0.5rem 0 0; }
