    /* ═══ Epic 85 (84.7) — CSS-канон ═══ */
    [v-cloak] { display: none; }

    :root {
      /* ═══ Дизайн-токены v2 (раунд 10.25/F2; палитра §8, ADR-1025-9 D1) ═══
         Имена потребителей сохранены (surface/text/teal/purple/status/grad/glass) —
         меняются значения; OD4/Relume-палитра SUPERSEDE. */
      /* surfaces (§8: Background #090D17 / Surface #151B2A / Elevated #1C2537) */
      --surface-0:#090D17; --surface-1:#151B2A; --surface-2:#1C2537; --surface-3:#232E45;
      --surface-border:rgba(170,182,200,.14);
      /* --surface-glass: legacy-алиас (стекло = --glass-bg ниже). */
      --surface-glass:rgba(21,27,42,.5);
      /* HOTFIX10 (ADR-1025-18 D2, T-2852): единая подложка рабочей поверхности
         Main — согласована с --surface-0, полупрозрачна (фон Dark Aurora Flow
         остаётся виден, но нет яркой вертикальной полосы в зазоре у sidebar).
         Слой 3 порядка: фон → графит sidebar/header → рабочая поверхность. */
      --work-surface-bg: rgba(9, 13, 23, 0.62);
      /* text (§8: Primary #F4F7FB / Secondary #AAB6C8). --text-3 скорректирован
         (D4 «ради контраста») так, чтобы даже на САМОМ СВЕТЛОМ эффективном фоне
         стекла (--glass-bg alpha .5 поверх анимированного wash) ratio ≥4.5:1
         для .75rem: #94A3B8→#A2B0C6 (5.25 на стекле, 8.84 на surface-0). */
      --text-1:#F4F7FB; --text-2:#AAB6C8; --text-3:#A2B0C6;
      /* brand/base palette (§8: Teal #42D6C4 / Violet #A78BFA / Blue #77A8FF) */
      --teal-500:#42D6C4; --teal-600:#2FB9A8; --purple-500:#A78BFA; --purple-400:#8B6FE8;
      --magenta-600:#E05A8A; --magenta-400:#F08BB0; --lilac-200:#CFC4F5; --indigo-300:#77A8FF;
      /* status (§8: warning #F6C56F / danger #F07178; ok согласован с палитрой) */
      --ok:#3DD68C; --warn:#F6C56F; --err:#F07178;
      /* D-1/@Reviewer: danger-ТЕКСТ на стекле (12px) — светлее --err ради AA
         (--err на эффективном стекле-B = 4.03 < 4.5; #FCA5A5 = 6.07). */
      --err-text:#FCA5A5;
      --ok-bg:rgba(61,214,140,.14); --warn-bg:rgba(246,197,111,.14); --err-bg:rgba(240,113,120,.14);
      /* animated gradient tokens (§10: бирюза/синий/фиолет/приглушённый синий) */
      --grad-angle:135deg; --grad-a:#42D6C4; --grad-b:#77A8FF; --grad-c:#A78BFA;
      --grad-d:#5C7CFA;   /* §10/T-2545: приглушённый синий вместо оранжевого */
      --grad-speed:75s;      /* §10/T-2544: основной цикл 60–90 c (было 6s) */
      --grad-speed-slow:105s;/* §10/T-2544: вторичные слои 90–120 c */
      --grad-ease:cubic-bezier(0,0,.2,1);
      /* typography (значения эталона) */
      --font-body:'Inter',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;
      --h1:3.5rem;--h2:3rem;--h3:2.5rem;--h4:2rem;--h5:1.5rem;--h6:1.25rem;
      --heading-weight:600;--heading-ls:-.03em;
      --tx-large:1.25rem;--tx-med:1.125rem;--tx-reg:1rem;--tx-small:.875rem;--tx-tiny:.75rem;
      /* radius / shadow / spacing / motion (эталон) */
      --radius-sm:4px;--radius-md:8px;--radius-lg:12px;--radius-full:9999px;
      --shadow-sm:0 1px 2px rgba(0,0,0,.05);--shadow-md:0 4px 6px -1px rgba(0,0,0,.07);
      --shadow-lg:0 10px 25px -3px rgba(0,0,0,.08);--shadow-xl:0 20px 50px -12px rgba(0,0,0,.12);
      --dur-fast:.15s;--dur-normal:.3s;--dur-slow:.5s;--ease-out:cubic-bezier(0,0,.2,1);
      --page-padding:2.5rem;--navbar-height:4.5rem;
      /* Liquid Glass v2 → v6.3 U08 (REQ-U08-*; SUPERSEDE ADR-1025-12 D1) — уровни A/B/C.
         B (default, glass-set): blur + светлая кромка + блик + тень.
         A (opt-in [data-glass="a"]): НАСТОЯЩАЯ рефракция подложки —
         backdrop-filter url(#lg-lens) ТОЛЬКО при probe-подтверждённом
         [data-glass-tier="a"] (render-probe glass-probe.js); до probe —
         честный Tier B frost. WebKit/WebKit-like → probe fail → Tier B
         (bug 245510). ::before — rim/specular/tint, БЕЗ фильтра на тексте.
         C ([data-glass="c"]/deny-list/без blur): непрозрачный fallback.
         Токены — единый источник для панелей/карточек/модалок/sticky. */
      --glass-bg: rgba(21, 27, 42, 0.5);
      --glass-bg-strong: rgba(21, 27, 42, 0.85);
      --glass-blur: blur(16px);
      --glass-border-color: rgba(170, 182, 200, 0.16);
      --glass-border: 1px solid var(--glass-border-color);
      --glass-highlight: rgba(255, 255, 255, 0.16);
      --glass-highlight-soft: rgba(255, 255, 255, 0.05);
      /* D3.5/ADR-1025-13: «грязь» убрана — alpha .75 → .55; карточкам даётся
         отдельная лёгкая --card-shadow (ниже), модалки/тултипы остаются на
         --glass-shadow (сохранён для них). */
      --glass-shadow: 0 18px 40px -18px rgba(3, 7, 18, 0.55);
      /* ═══ W2-GLASS (U08.2/U08.3): токены материала Liquid Glass ═══
         Новые ключи --lg-* (существующие --glass-* не переименовываются —
         их читают другие секции). Значения — по таблице параметров ТЗ U08.2
         (Frost blur 6–12/saturate 1.25–1.55, Tint alpha 0.05–0.12 light +
         0.12–0.28 dark, Rim 1px 0.40–0.75, Specular 1–3px, bend 2–8px,
         fringe 0.3–1.2px edge-only, corners 16–22). Калибровка — по
         скриншотам стенда (w2-evidence-glass/). */
      --lg-frost: blur(8px) saturate(130%);
      --lg-frost-hero: blur(5px) saturate(140%);
      --lg-tint-hero: linear-gradient(150deg,
          rgba(190, 225, 255, 0.10) 0%, rgba(21, 27, 42, 0.18) 46%,
          rgba(100, 155, 235, 0.07) 100%);
      --lg-tint-soft: linear-gradient(160deg,
          rgba(190, 225, 255, 0.07) 0%, rgba(21, 27, 42, 0.14) 55%,
          rgba(100, 155, 235, 0.05) 100%);
      --lg-rim: linear-gradient(115deg,
          rgba(248, 254, 255, 0.62) 0%, rgba(210, 238, 255, 0.16) 34%,
          rgba(105, 153, 220, 0.10) 69%, rgba(236, 249, 255, 0.42) 100%);
      --lg-specular-arc: radial-gradient(120% 70% at 14% 0%,
          rgba(245, 252, 255, 0.34) 0%, rgba(245, 252, 255, 0) 46%);
      --lg-specular-soft: radial-gradient(90% 60% at 88% 6%,
          rgba(210, 238, 255, 0.12) 0%, rgba(210, 238, 255, 0) 52%);
      --lg-fringe: linear-gradient(170deg,
          rgba(120, 235, 255, 0.30) 0%, rgba(120, 235, 255, 0) 12%,
          rgba(120, 235, 255, 0) 74%, rgba(167, 139, 250, 0.26) 100%);
      --lg-ring-mask: linear-gradient(#fff 0 0) content-box,
          linear-gradient(#fff 0 0);
      --lg-shadow: 0 12px 32px rgba(0, 6, 22, 0.28),
          inset 0 1px rgba(245, 252, 255, 0.23),
          inset 0 -1px rgba(160, 206, 255, 0.08);
      --lg-radius: 20px;
      --lg-radius-hero: 22px;
      --lg-radius-solid: 16px;
      --sticky-save-h: 4.5rem;
      /* F9 (ADR-1025-22 D5): keyboard-offset от visualViewport (app.js
         `_syncKeyboardOffset`). Отдельно от safe-area — НЕ складывается с ним
         (§64 D3: safe-area учтён ровно один раз в `.sticky-save`). */
      --kb-offset: 0px;
      /* ═══ HOTFIX9 (ADR-1025-17 D1): ЕДИНЫЙ источник высоты shell ═══
         ВАЖНО: значения custom properties НЕ валидируются при разборе — браузер
         хранит почти любое значение и лишь при var()-подстановке объявляет
         результат invalid at computed-value time. Поэтому базовое значение —
         всегда валидный `100vh`; прогрессивное улучшение до `100dvh` включается
         отдельной @supports-веткой ниже. В TMA `telegram-init.js` задаёт
         `--app-usable-height = innerHeight − computeBottomOffset(...)` inline на
         documentElement (формула ADR-1025-12 D3 не меняется). `--shell-h` —
         ТОЛЬКО алиас (совместимость маркеров/тестов), второго источника нет. */
      --app-usable-height: 100vh;
      --shell-h: var(--app-usable-height);
      /* ═══ HOTFIX9 (ADR-1025-17 D4): shell v3.1 — ГРАФИТОВЫЙ §8 ═══
         Значения строго по UPD3 §8 (не derived из карточных --glass-*).
         Shell — визуально отдельный слой (плотнее/серее карточек), без цветной
         линзы/ореола и БЕЗ диагональной текстуры `--shell-texture` (удалена
         полностью — UPD3 §7). Мягкий откат рецепта при UI_SHELL_GRAPHITE_V3=OFF
         → значения hotfix8 (см. .app-shell.shell-v3-off); текстура НЕ
         возвращается (её удаление — часть исправления). */
      --shell-bg: rgba(27, 29, 34, 0.94);
      --shell-bg-mobile: rgba(27, 29, 34, 0.96);
      --shell-bg-strong: rgba(27, 29, 34, 0.98);
      --shell-border-color: rgba(255, 255, 255, 0.09);
      --shell-border: 1px solid var(--shell-border-color);
      --shell-highlight: rgba(255, 255, 255, 0.055);
      --shell-highlight-soft: rgba(255, 255, 255, 0.03);
      --shell-shadow: 0 4px 16px rgba(0, 0, 0, 0.16);
      --shell-blur: blur(14px) saturate(105%);
      --shell-specular: linear-gradient(160deg, rgba(255,255,255,.05), rgba(255,255,255,.015) 44%, transparent 74%);
      --shell-sheen-opacity: .05;
      --card-shadow: 0 8px 20px -14px rgba(3, 7, 18, 0.45);
      /* compat-алиасы (хардкод прежней фиолетово-синей палитры удалён, §4.5) */
      --card-bg: var(--glass-bg);
      --card-border: 1px solid var(--surface-border);
      --accent-grad: linear-gradient(135deg, var(--purple-500), var(--grad-d), var(--teal-500));
    }
    /* Реальный фолбэк высоты shell (ADR-1025-17 D1): апгрейд
       `--app-usable-height` до `100dvh` разрешён ТОЛЬКО при доказанной
       поддержке dvh; иначе остаётся базовый валидный `100vh` (см. комментарий
       выше). В TMA inline-значение из `telegram-init.js` имеет приоритет.
       `--shell-h` — алиас, отдельного апгрейда у него нет. */
    @supports (height: 100dvh) {
      :root {
        --app-usable-height: 100dvh;
      }
    }
    /* @property + inherits:false — быстрое (не)наследуемое вычисление и
       плавная интерполяция угла градиента (OD4/§4.3) */
    @property --grad-angle { syntax: "<angle>"; inherits: false; initial-value: 135deg; }

    /* ═══ Material Symbols Rounded — self-host субсет (T-1147/§15.4) ═══
       В git только субсет ~18 КБ; источник 5.11 МиБ — .gitignore (OD18).
       Лигатур в субсете НЕТ ⟹ иконки рендерим PUA-кодпоинтом (ICONS в app.js),
       unicode-range не объявляем (google/fonts#10599).
       10.8 (R10.8-5): `?v=2.58.141` cache-bust — .woff2 отдаётся с
       max-age=86400, поэтому при пересборке субсета клиент обязан запросить
       новый URL, иначе до 24ч рисует старый 10.7-набор (tofu). */
    @font-face {
      font-family: 'Material Symbols Rounded';
      font-style: normal;
      font-weight: 100 700;
      font-display: block;
      src: url('/static/fonts/material-symbols-rounded.woff2?v=2.58.141') format('woff2-variations');
    }
    .msr {
      font-family: 'Material Symbols Rounded';
      font-weight: normal; font-style: normal;
      line-height: 1; display: inline-block; font-size: 24px;
      text-transform: none; letter-spacing: normal; white-space: nowrap;
      direction: ltr;
      font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
    }
    .msr.is-active {
      font-variation-settings: 'FILL' 1, 'wght' 500, 'GRAD' 0, 'opsz' 24;
    }

    /* ═══ Анимированные градиенты (OD4/T-1091): только ограниченные
       поверхности; текст/иконки — всегда на плотных подложках (WCAG AA) ═══ */
    @keyframes grad-spin { from { --grad-angle: 0deg; } to { --grad-angle: 360deg; } }
    @keyframes grad-drift { from { background-position: 0% 50%; } to { background-position: 100% 50%; } }
    .grad-band, .btn-accent, .tab-btn.active {
      background-image: conic-gradient(from var(--grad-angle),
        var(--grad-a), var(--grad-b), var(--grad-d), var(--grad-c), var(--grad-a));
      animation: grad-spin var(--grad-speed) linear infinite;
    }
    .grad-band { contain: paint; }

    * { box-sizing: border-box; }

    html, body {
      margin: 0;
      min-height: 100vh;
      font-family: var(--font-body);
      color: var(--text-1);
    }

    html { background-color: var(--surface-0); }
    body {
      background: transparent;
      position: relative;
    }
    /* ═══ HOTFIX8 (ADR-1025-16 D3): живой aurora/mesh фон (CSS-first) ═══
       Заменяет «мёртвый» conic page-wash (§10/F2: 75 c, opacity .30). Слой —
       отдельный задний (body::before/body::after/.aurora-bg, z-index:0 < #app),
       палитра §8/§10 (teal/blue/violet/indigo, без оранжевого), 5 blob-слоёв,
       разные фазы/длительности, лёгкий morph, слабый grain. Механика
       `@property --grad-angle` + grad-spin/grad-drift СОХРАНЕНА для
       .grad-band/.btn-accent/.tab-btn.active и как legacy-фолбэк фона
       (UI_AURORA_BG_ENABLED=OFF → класс html.bg-wash-legacy ниже).
       Blur viewport НЕ анимируется (T-2541): движемся transform/opacity/
       background-position, но НЕ filter. */
    body::before {
      content: '';
      position: fixed;
      inset: -12%;
      z-index: 0;
      pointer-events: none;
      /* Медленный атмосферный mesh (3 blob) — не статичен, не «психоделика»:
         основной цикл 60–90 c, вторичный morph 90–120 c (токены §10). */
      background:
        radial-gradient(42% 55% at 18% 22%, rgba(66, 214, 196, .30), transparent 64%),
        radial-gradient(48% 54% at 82% 24%, rgba(119, 168, 255, .26), transparent 66%),
        radial-gradient(46% 58% at 70% 84%, rgba(167, 139, 250, .30), transparent 66%),
        var(--surface-0);
      background-size: 180% 180%, 180% 180%, 180% 180%, 100% 100%;
      animation: aurora-flow var(--grad-speed) ease-in-out infinite alternate,
                 aurora-morph var(--grad-speed-slow) var(--grad-ease) infinite alternate;
    }
    /* Второй слой: ещё 2 blob + очень слабый grain (едва заметен). */
    body::after {
      content: '';
      position: fixed;
      inset: -12%;
      z-index: 0;
      pointer-events: none;
      background:
        repeating-linear-gradient(0deg, rgba(255,255,255,.012) 0 1px, transparent 1px 2px),
        repeating-linear-gradient(90deg, rgba(0,0,0,.020) 0 1px, transparent 1px 2px),
        radial-gradient(40% 50% at 30% 74%, rgba(92, 124, 250, .24), transparent 64%),
        radial-gradient(34% 42% at 62% 40%, rgba(66, 214, 196, .18), transparent 68%);
      animation: aurora-flow-rev var(--grad-speed-slow) ease-in-out infinite alternate;
      animation-delay: -21s;
      opacity: .9;
    }
    /* Быстрые (но плавные) blob-слои 26–58 c: разные фазы через отрицательные
       задержки — «медленно, но заметно», не «заморожено». */
    .aurora-bg {
      position: fixed; inset: -14%; z-index: 0;
      pointer-events: none; overflow: hidden;
    }
    .aurora-bg .aurora-blob {
      position: absolute; display: block;
      width: 52vmax; height: 52vmax; border-radius: 50%;
      filter: blur(64px); opacity: .5; will-change: transform;
    }
    .aurora-bg .aurora-blob.b1 {
      left: -8%; top: -12%;
      background: radial-gradient(circle at 42% 42%, rgba(66, 214, 196, .60), transparent 68%);
      animation: aurora-blob-1 34s ease-in-out infinite alternate;
    }
    .aurora-bg .aurora-blob.b2 {
      right: -10%; top: -6%;
      background: radial-gradient(circle at 50% 50%, rgba(119, 168, 255, .55), transparent 68%);
      animation: aurora-blob-2 46s ease-in-out -12s infinite alternate;
    }
    .aurora-bg .aurora-blob.b3 {
      left: 6%; bottom: -18%;
      background: radial-gradient(circle at 50% 50%, rgba(167, 139, 250, .55), transparent 68%);
      animation: aurora-blob-3 40s ease-in-out -22s infinite alternate;
    }
    .aurora-bg .aurora-blob.b4 {
      right: 2%; bottom: -14%;
      background: radial-gradient(circle at 50% 50%, rgba(92, 124, 250, .50), transparent 68%);
      animation: aurora-blob-4 52s ease-in-out -30s infinite alternate;
    }
    .aurora-bg .aurora-blob.b5 {
      left: 38%; top: 26%; width: 40vmax; height: 40vmax;
      background: radial-gradient(circle at 50% 50%, rgba(66, 214, 196, .30), transparent 70%);
      animation: aurora-blob-1 58s ease-in-out -40s infinite alternate;
    }
    .aurora-bg .aurora-grain {
      position: absolute; inset: 0; opacity: .5;
      background-image:
        repeating-linear-gradient(0deg, rgba(255,255,255,.014) 0 1px, transparent 1px 2px),
        repeating-linear-gradient(90deg, rgba(0,0,0,.022) 0 1px, transparent 1px 2px);
    }
    /* ═══ HOTFIX9 (ADR-1025-17 D6): Dark Aurora Flow — ОДИН фоновый canvas ═══
       Широкие световые ленты (OGL fragment shader; Canvas2D-фолбэк внутри
       модуля). Слой — позади #app (z-index:0), pointer-events:none. Прежние
       слои (.aurora-bg / body::before/::after) выводятся из активного пути —
       никаких «пятен поверх пятен». Пауза/статика — `lg-bg-paused` +
       `prefers-reduced-motion` внутри модуля. */
    .aurora-flow-canvas {
      position: fixed; inset: 0; z-index: 0; pointer-events: none;
      display: block; width: 100%; height: 100%;
    }
    html.aurora-flow-v2 .aurora-bg { display: none !important; }
    html.aurora-flow-v2 body::before,
    html.aurora-flow-v2 body::after { content: none; }
    /* ═══ round 10.26 (ADR-1026-3 D1/D4/D5): Polygonal Luminescence — ОДИН
       фоновый canvas на Canvas 2D (Delaunator 5.0.0). Прямой потомок body,
       вне max-width/scroll-контейнеров, z-index:0 (НЕ отрицательный), позади
       #app. `html.polygon-bg` (ставит app.js::_syncBgLayer) выводит из
       активного пути Aurora (OGL-канвас) и legacy-слои — ровно один фон.
       Только при UI_POLYGON_BG_ENABLED=ON. Откат — OFF → `.aurora-flow-v2`. */
    .polygon-background-canvas {
      position: fixed; inset: 0; z-index: 0; pointer-events: none;
      display: block; width: 100%; height: 100%;
    }
    html.polygon-bg .aurora-bg { display: none !important; }
    html.polygon-bg .aurora-flow-canvas { display: none !important; }
    html.polygon-bg body::before,
    html.polygon-bg body::after { content: none; }
    @keyframes aurora-flow {
      from { background-position: 0% 0%, 100% 0%, 60% 100%, 50% 50%; }
      to   { background-position: 12% 14%, 84% 16%, 44% 82%, 50% 50%; }
    }
    @keyframes aurora-flow-rev {
      from { background-position: 50% 50%, 50% 50%, 30% 74%, 62% 40%; }
      to   { background-position: 50% 50%, 50% 50%, 40% 62%, 52% 44%; }
    }
    @keyframes aurora-morph {
      from { transform: scale(1); }
      to   { transform: scale(1.06); }
    }
    @keyframes aurora-blob-1 {
      0%   { transform: translate3d(0, 0, 0) scale(1); border-radius: 50% 50% 50% 50%; }
      50%  { transform: translate3d(7%, 5%, 0) scale(1.14); border-radius: 58% 42% 52% 48%; }
      100% { transform: translate3d(-3%, 9%, 0) scale(.98); border-radius: 46% 54% 44% 56%; }
    }
    @keyframes aurora-blob-2 {
      0%   { transform: translate3d(0, 0, 0) scale(1.06); border-radius: 50% 50% 50% 50%; }
      50%  { transform: translate3d(-6%, 7%, 0) scale(.94); border-radius: 44% 56% 50% 50%; }
      100% { transform: translate3d(4%, -5%, 0) scale(1.1); border-radius: 54% 46% 56% 44%; }
    }
    @keyframes aurora-blob-3 {
      0%   { transform: translate3d(0, 0, 0) scale(1); border-radius: 50% 50% 50% 50%; }
      50%  { transform: translate3d(5%, -6%, 0) scale(1.12); border-radius: 60% 40% 48% 52%; }
      100% { transform: translate3d(-5%, 4%, 0) scale(.96); border-radius: 42% 58% 54% 46%; }
    }
    @keyframes aurora-blob-4 {
      0%   { transform: translate3d(0, 0, 0) scale(1.04); border-radius: 50% 50% 50% 50%; }
      50%  { transform: translate3d(-7%, -4%, 0) scale(.92); border-radius: 46% 54% 42% 58%; }
      100% { transform: translate3d(3%, 6%, 0) scale(1.08); border-radius: 56% 44% 52% 48%; }
    }
    /* UI_AURORA_BG_ENABLED=OFF (класс ставит app.js): прежний conic page-wash
       §10/F2 — механика/цвета/длительности 60–90 c / 90–120 c, opacity .30. */
    html.bg-wash-legacy .aurora-bg { display: none !important; }
    html.bg-wash-legacy body::after { content: none; }
    html.bg-wash-legacy body::before {
      content: '';
      position: fixed;
      inset: -10%;
      z-index: 0;
      pointer-events: none;
      background: conic-gradient(from var(--grad-angle) at 50% 50%,
        var(--grad-a), var(--grad-b), var(--grad-d), var(--grad-c), var(--grad-a));
      background-size: 200% 200%;
      animation: grad-spin var(--grad-speed) linear infinite,
                 grad-drift var(--grad-speed-slow) var(--grad-ease) infinite alternate;
      opacity: .30;
    }
    /* §10/T-2547: пауза дорогих эффектов при скрытии TMA (класс ставит
       onVisibilityChange в app.js — единый обработчик, без второго listener'а). */
    html.lg-bg-paused body::before,
    html.lg-bg-paused body::after,
    html.lg-bg-paused .aurora-blob,
    html.lg-bg-paused .grad-band,
    html.lg-bg-paused .btn-accent,
    html.lg-bg-paused .tab-btn.active {
      animation-play-state: paused;
    }
    #app { position: relative; z-index: 1; }
    @media (prefers-reduced-motion: reduce) {
      .grad-band, .btn-accent, .tab-btn.active { animation: none !important; }
      body::before {
        animation: none !important;
        background: linear-gradient(135deg, var(--grad-a), var(--grad-b), var(--grad-c));
      }
      body::after { animation: none !important; }
      .aurora-bg .aurora-blob { animation: none !important; }
      :root { --grad-angle: 135deg; }
      /* T-2548/W2-GLASS: при reduced-motion гасим тяжёлое преломление
         уровня A (остаётся честный frost — U08.3e, стекло не убиваем). */
      [data-glass="a"] {
        -webkit-backdrop-filter: var(--lg-frost-hero) !important;
        backdrop-filter: var(--lg-frost-hero) !important;
      }
    }
    @media (prefers-contrast: more) {
      .grad-band, .btn-accent, .tab-btn.active, body::before, body::after {
        animation: none !important; background-image: none !important;
        background-color: var(--surface-3) !important; opacity: 1;
      }
      .aurora-bg { display: none !important; }
    }

    /* Glass-карточки (84.7/UPD3): полупрозрачные — фон просвечивает */
    .card {
      background-color: var(--glass-bg);
      -webkit-backdrop-filter: var(--glass-blur) saturate(140%);
      backdrop-filter: var(--glass-blur) saturate(140%);
      border: var(--glass-border);
      border-radius: 1rem;
      box-shadow: var(--shadow-lg);
    }
    /* G1.3: card-solid — плотная подложка только header-sticky/scope-panel. */
    .card-solid {
      background: var(--glass-bg-strong);
    }

    /* F6 (10.14): рендер Markdown-гайда в «Справке» — читаемая типографика */
    .guide-markdown { color: var(--text-1); line-height: 1.65; }
    .guide-markdown h1 { font-size: 1.35rem; font-weight: 700; margin: 0 0 .6rem; }
    .guide-markdown h2 { font-size: 1.15rem; font-weight: 700; margin: 1.3rem 0 .5rem; }
    .guide-markdown h3 { font-size: 1rem; font-weight: 600; margin: 1.1rem 0 .4rem; }
    .guide-markdown h4, .guide-markdown h5, .guide-markdown h6 {
      font-size: .95rem; font-weight: 600; margin: 1rem 0 .35rem;
    }
    .guide-markdown h1:first-child, .guide-markdown h2:first-child { margin-top: 0; }
    .guide-markdown p { margin: .5rem 0; }
    .guide-markdown ul { margin: .5rem 0 .5rem 1.25rem; list-style: disc; }
    .guide-markdown li { margin: .2rem 0; }
    .guide-markdown code {
      font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
      font-size: .85em; background: rgba(255, 255, 255, .08);
      padding: .1rem .35rem; border-radius: .35rem;
    }
    .guide-markdown a { color: var(--teal-500); text-decoration: underline; }
    .guide-markdown b { font-weight: 700; }
    .guide-markdown i { font-style: italic; }

    /* F7 10.22 (ADR-1022-7): rich-Справка v4 — заголовки h1/h2 (Tailwind
       preflight их обнуляет) + команды-вызовы как выделенная цитата/код.
       DOMPurify (default) пропускает h1/h2/blockquote — отдельный allowlist
       не нужен, но без этих стилей теги визуально неотличимы от текста. */
    .info-html { color: var(--text-1); line-height: 1.65; }
    .info-html h1 { font-size: 1.3rem; font-weight: 700; margin: 0 0 .7rem; }
    .info-html h2 { font-size: 1.08rem; font-weight: 700; margin: 1.25rem 0 .5rem; }
    .info-html h1:first-child, .info-html h2:first-child { margin-top: 0; }
    .info-html p { margin: .5rem 0; }
    .info-html blockquote {
      margin: .4rem 0; padding: .45rem .8rem;
      border-left: 3px solid var(--teal-500);
      background: rgba(255, 255, 255, .06);
      border-radius: 0 .5rem .5rem 0;
      font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
      font-size: .85em; color: var(--text-2);
    }
    .info-html blockquote b { font-weight: 700; }
    .info-html a { color: var(--teal-500); text-decoration: underline; }

    /* §8/T-2535: primary — акцентный градиент; тёмный текст на светлых стопах
       (белый давал ~2:1 и проваливал AA). */
    .btn-accent {
      color: #081018;
      border: none;
      border-radius: 0.75rem;
      padding: 0.55rem 1rem;
      font-weight: 600;
      cursor: pointer;
      transition: transform 0.12s ease, opacity 0.12s ease;
    }
    .btn-accent:hover:not(:disabled) { transform: translateY(-1px); }
    .btn-accent:disabled { opacity: 0.45; cursor: not-allowed; }

    /* §8/T-2535: secondary — приглушённая заливка + бордер (не «ярче primary»). */
    .btn-ghost {
      background: rgba(170, 182, 200, 0.10);
      border: var(--card-border);
      border-radius: 0.75rem;
      padding: 0.5rem 0.9rem;
      color: var(--text-2);
      cursor: pointer;
      transition: background 0.12s ease, border-color 0.12s ease;
    }
    .btn-ghost:hover:not(:disabled) {
      background: rgba(170, 182, 200, 0.18); border-color: var(--glass-border-color);
    }
    .btn-ghost:disabled { opacity: 0.4; cursor: not-allowed; }
    /* S7 (ADR-1026-9 D4, §110): активный чип «Саммари» в существующем log
       viewer — тот же btn-ghost, только подсветка состояния (viewer не
       переписывается; CSP/zero-build). */
    .btn-ghost.log-chip.active {
      color: var(--teal-500);
      border-color: rgba(66, 214, 196, 0.55);
      background: rgba(66, 214, 196, 0.12);
    }
    /* §8/T-2535: danger — семантический красный, отличим от primary/secondary. */
    .btn-danger {
      background: linear-gradient(135deg, var(--err), #C24A52);
      color: #1B0B0E;
      border: none;
      border-radius: 0.75rem;
      padding: 0.5rem 0.9rem;
      cursor: pointer;
      font-weight: 600;
    }
    .btn-danger:hover:not(:disabled) { transform: translateY(-1px); }
    .btn-danger:disabled { opacity: 0.45; cursor: not-allowed; }

    .tab-btn {
      display: flex;
      align-items: center;
      gap: 0.6rem;
      width: 100%;
      text-align: left;
      padding: 0.65rem 0.9rem;
      border-radius: 0.75rem;
      color: var(--text-2);
      background: transparent;
      border: none;
      cursor: pointer;
      font-size: 0.92rem;
      transition: background 0.12s ease, color 0.12s ease;
    }
    .tab-btn:hover { background: rgba(170, 182, 200, 0.10); color: var(--text-1); }
    .tab-btn.active {
      color: #081018;
      font-weight: 600;
      box-shadow: 0 4px 18px rgba(66, 214, 196, 0.35);
    }

    /* T-1100/раунд 10.6 (A1): navbar-полоса (6 пунктов эталона) + hub */
    .navbar-band {
      display: flex; align-items: stretch; gap: .15rem; width: 100%;
      overflow-x: auto;
    }
    .nav-link {
      display: flex; flex-direction: column; align-items: center;
      justify-content: flex-start; gap: 1px; flex: 1 1 0; min-width: 0;
      padding: .15rem 0; white-space: normal;
      background: transparent; border: none; cursor: pointer;
      color: var(--text-2); font-size: var(--tx-small);
    }
    .nav-link .nav-icon { font-size: 22px; line-height: 1; }
    /* 10.7 (1d): подписи навбара — без разрыва внутри слова (keep-all),
       перенос по словам, максимум 2 строки с ellipsis; едино mobile+desktop. */
    .nav-label {
      font-size: 0.625rem; line-height: 1.05; letter-spacing: -0.01em;
      text-align: center; word-break: keep-all; overflow-wrap: break-word;
      hyphens: none; display: -webkit-box; -webkit-line-clamp: 2;
      -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis;
    }
    .nav-link:hover { background: rgba(255,255,255,.06); color: var(--text-1); }
    .nav-link.active {
      background: var(--surface-3); color: var(--text-1); font-weight: 600;
    }
    .nav-link.active .msr { font-variation-settings: 'FILL' 1; }
    @media (min-width: 992px) { .nav-link { min-width: 60px; } }

    /* Раунд 10.6 (A2): список 11 модулей + карточки */
    .module-list {
      grid-column: 1 / -1; display: grid; gap: .75rem;
      /* 10.20 (БЛОК 3.5/T-1899): auto-fit + minmax(300px) + строгая центровка;
         треки не разъезжаются к левому краю на широких экранах. */
      grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
      justify-content: center; width: 100%; max-width: 1100px;
      justify-self: center; margin-inline: auto;
    }
    .module-card { display: flex; flex-direction: column; align-items: stretch; gap: .5rem; }
    /* F4 §33: верхняя строка карточки — иконка + название + тумблер. */
    .module-card-head { display: flex; align-items: center; gap: .75rem; }
    .module-card .module-icon { color: var(--teal-500); font-size: 24px; flex-shrink: 0; }
    .module-meta { flex: 1 1 auto; min-width: 0; }
    /* Раунд 10.6 (A9) / 10.8 (§4): эксклюзивный аккордеон «Доступы» заменён
       route-driven модалками (ADR-001) — CSS аккордеона удалён; используются
       существующие .hub-card/.modal-*. */
    /* Раунд 10.6 (A4): блоки провайдеров */
    .prov-block { border: var(--card-border); border-radius: var(--radius-lg); }
    .prov-test-btn:disabled { opacity: .5; cursor: not-allowed; }
    /* ═══ P0 Vision (§4 / P0V-UI-OVERFLOW): контракт раскладки форм
       провайдеров — первопричина, не симптом. ═══
       Раньше `.prov-row/.prov-label/.prov-head` жили ТОЛЬКО на Tailwind-
       утилитах (хрупкость: пересборка tailwind без w-36/min-w-0 молча ломает
       подписи). Здесь — устойчивый минимум, чтобы сетка/строка ужимались, а
       не выпихивали документ:
       * grid-элементы могут сжиматься ниже своего min-content (`min-width:0`);
       * `.prov-row` не создаёт min-content-пола, подпись переносится
         (`overflow-wrap:anywhere` — перенос по словам, БЕЗ разрыва слов
         по буквам);
       * поле ввода — `min-width:0` (нативный <input> имеет intrinsic width
         по size-атрибуту и иначе раздувает строку);
       * заголовок карточки переносится, статус-badge не распирает header. */
    .prov-grid > * { min-width: 0; }
    .prov-row { min-width: 0; }
    .prov-row > .prov-label { overflow-wrap: anywhere; }
    .prov-row .field,
    .prov-row .secret-field__input { min-width: 0; }
    .prov-head { flex-wrap: wrap; min-width: 0; }
    .prov-head .badge { flex: 0 0 auto; }
    /* Узкий контейнер формы (телефоны 320–430 + крупный системный шрифт
       Android, который масштабирует rem-подписи `w-36` до 180–216px):
       подпись — НАД полем (стек), иначе на 320px ключу остаётся 55px.
       Порог — ширина КОНТЕЙНЕРА (container-type задан на `.prov-grid`),
       viewport ни при чём: в ландшафте при 844px контейнер может быть 398px.
       Скоуп — только `.prov-grid` (имя контейнера): другие секции, где
       `.prov-row` используется вне формы провайдеров, не затрагиваются. */
    @container prov-grid (max-width: 479px) {
      .prov-row {
        flex-direction: column;
        align-items: stretch;
        gap: .25rem;
      }
      .prov-row > .prov-label {
        width: auto;
        max-width: 100%;
        padding-top: 0;
      }
      .prov-row > .flex-1 { width: 100%; }
    }
    /* 10.11 (2.1): карточки центрируются и ограничены по ширине
       (fullscreen не растягивает на всю ширину; mobile — 1 колонка). */
    .hub-head {
      grid-column: 1 / -1; width: 100%; max-width: 64rem;
      justify-self: center;
    }
    .hub-head .hub-title { font-size: var(--tx-large); font-weight: 600; }
    .hub-head .hub-sub { font-size: var(--tx-small); color: var(--text-3); }
    .hub-grid {
      grid-column: 1 / -1; display: grid; gap: .75rem;
      width: 100%; max-width: 64rem; justify-self: center;
      /* 10.20 (БЛОК 3.5/T-1899): auto-fit + minmax(300px) + центровка. */
      grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
      justify-content: center; margin-inline: auto;
    }
    .hub-card {
      display: flex; align-items: flex-start; gap: .75rem; text-align: left;
      background-color: var(--glass-bg); border: var(--glass-border);
      border-radius: var(--radius-lg); padding: .9rem; cursor: pointer;
      color: var(--text-1); transition: transform .12s ease, border-color .12s ease;
    }
    .hub-card:hover { transform: translateY(-1px); border-color: var(--teal-500); }
    .hub-card .msr { color: var(--teal-500); font-size: 28px; flex-shrink: 0; }
    .hub-card .hub-card-title { font-weight: 600; font-size: var(--tx-med); }
    .hub-card .hub-card-sub { font-size: var(--tx-small); color: var(--text-3); }

    /* T-1127: кастомный scope-dropdown (a11y listbox) */
    .scope-wrap { position: relative; }
    .scope-trigger {
      display: inline-flex; align-items: center; gap: .4rem; cursor: pointer;
      max-width: 260px;
      /* HOTFIX8 (ADR-1025-16 D2 §4): selector/pill-floating — 16 px. */
      border-radius: 16px;
    }
    .scope-initial {
      width: 20px; height: 20px; border-radius: 50%;
      background: var(--surface-3); color: var(--text-1);
      display: inline-flex; align-items: center; justify-content: center;
      font-size: 10px; font-weight: 600; flex-shrink: 0; text-transform: uppercase;
    }
    .scope-panel {
      position: absolute; right: 0; top: calc(100% + 4px); z-index: 50;
      min-width: 260px; max-height: 60vh; overflow-y: auto; padding: .4rem;
      border: var(--card-border); border-radius: var(--radius-lg);
      box-shadow: var(--shadow-xl);
    }
    .scope-option {
      display: flex; align-items: center; gap: .5rem; width: 100%;
      text-align: left; padding: .4rem .5rem; border-radius: var(--radius-md);
      background: transparent; border: none; color: var(--text-1);
      cursor: pointer; font-size: var(--tx-small);
    }
    .scope-option:hover, .scope-option.active { background: rgba(255,255,255,.08); }
    /* ═══ F3 round 10.25 (§5): селектор области — постоянно доступный ═══ */
    /* Полный chat_id — только в «технических подробностях» (не в основном UI). */
    /* Reviewer Critical: кнопка возврата к глобальному не должна давать
       горизонтальный overflow на узких экранах — снимаем Tailwind
       `shrink-0`, разрешаем сжатие/перенос (видимая подпись сокращена
       до «↪ Глобальное», полный смысл — в aria-label/title).
       Селектор — стабильный класс (не зависит от текста aria-label). */
    .btn-reset-global {
      flex-shrink: 1; min-width: 0; max-width: 100%; white-space: normal;
    }
    .scope-tech { position: relative; }
    .scope-tech > summary { cursor: pointer; list-style: none; }
    .scope-tech > summary::-webkit-details-marker { display: none; }
    .scope-tech-body {
      position: absolute; right: 0; top: calc(100% + 4px); z-index: 50;
      padding: .3rem .5rem; border: var(--card-border);
      border-radius: var(--radius-md); background: var(--glass-bg-strong);
      font-size: 10px; color: var(--text-3); white-space: nowrap;
      box-shadow: var(--shadow-xl);
    }
    /* ADS: §70/§5 mobile (<768) — селектор области ОТДЕЛЬНОЙ строкой ПОД
       названием страницы (в шапке остаётся заголовок); тач-цель ≥44px;
       не перекрывает нижнюю навигацию (та — fixed с offset). */
    @media (max-width: 767px) {
      .scope-wrap { flex: 1 1 100%; order: 5; max-width: 100%; }
      .scope-trigger {
        width: 100%; max-width: 100%; min-height: 44px;
        justify-content: flex-start;
      }
      .scope-panel { min-width: 0; width: 100%; }
    }
    .matrix-group summary { color: var(--text-2); }
    .matrix-group summary:hover { color: var(--text-1); }

    /* T-1112: адаптив ≤991 / ≤479 */
    @media (max-width: 991px) {
      :root { --page-padding: 1.25rem; }
    }
    @media (max-width: 479px) {
      .hub-grid { grid-template-columns: 1fr; }
      .nav-link { padding: .3rem .1rem; }
      .avail-list th:nth-child(2), .avail-list td:nth-child(2) { display: none; }
      .log-logger { display: none; }
    }

    .field {
      width: 100%;
      background: rgba(255, 255, 255, 0.06);
      border: var(--card-border);
      border-radius: 0.6rem;
      padding: 0.5rem 0.7rem;
      color: var(--text-1);
      outline: none;
      font-size: 0.9rem;
    }
    .field:focus { border-color: var(--teal-500); }
    /* KV-редактор (3.5.2): дубль/пустое поле пары */
    .field.kv-bad { border-color: rgba(239, 68, 68, 0.75); }
    textarea.field { font-family: ui-monospace, Consolas, monospace; }
    /* ФИКС 2026-09-03: native <select> игнорирует полупрозрачный фон/.field →
       открывался БЕЛЫМ (UA-стиль); жёсткий тёмный фон (--surface-3) +
       светлый текст согласован с карточками. */
    select.field {
      background-color: var(--surface-3);
      color: var(--text-1);
    }
    select.field option {
      background-color: var(--surface-3);
      color: var(--text-1);
    }
    /* F-13 (AC-1, ремедиация ревью): .chat-select min/max-ширины УДАЛЕНЫ —
       unlayered CSS перебивал Tailwind-утилиты (w-44 max-w-[280px]) и
       компактность селектора не работала; ширина — только утилитами. */

    .badge {
      display: inline-block;
      padding: 0.15rem 0.5rem;
      border-radius: 999px;
      font-size: 0.72rem;
      font-weight: 600;
    }
    .badge-ok    { background: var(--ok-bg);   color: var(--ok); }
    .badge-warn  { background: var(--warn-bg); color: var(--warn); }
    .badge-err   { background: var(--err-bg);  color: var(--err); }
    .badge-info  { background: rgba(59, 130, 246, 0.18); color: #93c5fd; }
    .badge-muted { background: rgba(255, 255, 255, 0.08); color: #9ca3af; }

    /* ═══ D-1/@Reviewer: Tailwind-утилиты текста → токены §8 ═══
       Дефолтные Tailwind-цвета не из §8: на эффективном стекле (--glass-bg
       alpha .5 поверх wash §10) .text-gray-500 давал 2.38:1, .text-red-400 —
       4.17:1 (<4.5:1 для .75rem). app.css грузится ПОСЛЕ tailwind.css →
       равная специфичность, это правило выигрывает и покрывает стекло+фон. */
    .text-gray-600,
    .text-gray-500 { color: var(--text-3); }
    .text-gray-400 { color: var(--text-2); }
    .text-red-400 { color: var(--err-text); }

    /* B1/OD8 (T-1128): плотный список доступности ключей (мелкий шрифт,
       плотный line-height, без «карточечных» отступов) */
    .avail-list { width: 100%; border-collapse: collapse; }
    .avail-list th {
      font-size: var(--tx-tiny); text-transform: uppercase; color: var(--text-3);
      text-align: left; font-weight: 600; padding: 2px 8px; letter-spacing: .02em;
    }
    .avail-list td {
      font-size: var(--tx-tiny); line-height: 1.25; padding: 3px 8px;
      border-top: 1px solid var(--surface-border); white-space: nowrap;
    }
    .avail-list td.mono { font-family: ui-monospace, Consolas, monospace;
      color: var(--text-1); overflow: hidden; text-overflow: ellipsis; }
    .avail-dot { display: inline-block; width: 8px; height: 8px;
      border-radius: 50%; background: var(--text-3); vertical-align: middle; }
    .avail-dot.ok { background: var(--ok); }
    .avail-dot.warn { background: var(--warn); }
    .avail-dot.err { background: var(--err); }
    .avail-code.ok { color: var(--ok); }
    .avail-code.warn { color: var(--warn); }
    .avail-code.err { color: var(--err); }
    .avail-code.none { color: var(--text-3); }

    /* 10.9 (п.7.1): строки блока «Доступность ключей» — имя/провайдер,
       маска ключа, задержка, health. */
    .llm-row {
      display: grid; gap: .5rem; align-items: center;
      grid-template-columns: minmax(0,1fr) auto auto auto;
      padding: .35rem .25rem; border-top: 1px solid var(--surface-border);
    }
    @media (max-width: 640px) {
      .llm-row { grid-template-columns: minmax(0,1fr) auto; }
    }
    /* 10.9 (п.1): owner-блоки PERMsoc — нативный <summary> без маркера. */
    .owner-block > summary { list-style: none; }
    .owner-block > summary::-webkit-details-marker { display: none; }

    /* 10.7 (2a): ТОЛЬКО таблица ключей (.keys-avail) — фиксированная
       раскладка + ellipsis, чтобы whisper-large-v3 не ломал карточку.
       Матрица ролей и прочие .avail-list не затрагиваются. */
    .keys-avail .avail-list { table-layout: fixed; }
    .keys-avail .avail-list th:nth-child(1),
    .keys-avail .avail-list td:nth-child(1) { width: 34%; }
    .keys-avail .avail-list th:nth-child(2),
    .keys-avail .avail-list td:nth-child(2) { width: 18%; }
    .keys-avail .avail-list th:nth-child(3),
    .keys-avail .avail-list td:nth-child(3) { width: 30%; }
    .keys-avail .avail-list th:nth-child(4),
    .keys-avail .avail-list td:nth-child(4) { width: 8%; }
    .keys-avail .avail-list th:nth-child(5),
    .keys-avail .avail-list td:nth-child(5) { width: 10%; }
    .keys-avail .avail-list td {
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }

    .progress {
      height: 8px;
      border-radius: 999px;
      background: rgba(255, 255, 255, 0.08);
      overflow: hidden;
    }
    .progress > div {
      height: 100%;
      background: linear-gradient(90deg, var(--teal-600), var(--teal-500));
      transition: width 0.4s ease;
    }

    /* Логи */
    /* Hotfix-R10: fontSize снижен (0.78 → 0.7rem) — длинные строки
       «Running job …» на мобилках не разлетались на 5+ строк и не
       вылезали из контейнера */
    .log-row { font-family: ui-monospace, Consolas, monospace; font-size: 0.7rem; }
    .log-row:hover { background: rgba(255, 255, 255, 0.04); }
    /* expander стека в логах (Hotfix-R10; 10.8 §3.4): компактная
       Material-иконка, НЕ выглядит полем ввода; spacer сохраняет ширину. */
    .log-toggle, .log-toggle-spacer {
      flex: 0 0 1.25rem;
      width: 1.25rem;
      height: 1.25rem;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: 0;
      background: none;
      border: 0;
    }
    .log-toggle {
      color: rgba(156, 163, 175, 0.9);
      cursor: pointer;
      user-select: none;
    }
    .log-toggle .msr { font-size: 1rem; }
    .log-toggle:hover { color: #e5e7eb; }
    /* Раунд 10 (F-8 T-871): компактные логи — pre code, thin-scroll, fixed height */
    .log-panel {
      max-height: 320px;
      overflow-y: auto;
    }
    /* Hotfix-R10 (мобилки/TMA): не выше половины экрана */
    @media (max-width: 768px) {
      .log-panel { max-height: 50dvh; }
    }
    .log-code {
      font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
      font-size: 0.7rem;
      white-space: normal;
      word-break: normal;
      line-height: 1.25;
    }
    .log-code .log-row { display: block; padding: 2px 4px; }
    /* 10.8 (§3.2/§3.4): шапка строки — flex с переносом (на Android
       level/ts/logger уходят на вторую строку, сообщение не схлопывается). */
    .log-head {
      display: flex; flex-wrap: wrap; align-items: baseline;
      gap: .25rem .5rem; min-width: 0;
    }
    /* 10.8 (§3.4): жёсткие min-width/width/max-width колонок УДАЛЕНЫ —
       на 360px-экране они оставляли сообщению ~1 символ. */
    .log-level { text-align: center; }
    .log-level .badge { display: inline-block; }
    .log-ts {
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
    }
    .log-msg {
      display: block; width: 100%; margin-top: 2px;
      word-break: break-word; overflow-wrap: anywhere; white-space: pre-wrap;
    }
    /* 10.7 (3c): transient-подсветка скопированной строки. */
    .log-copied { background: rgba(66, 214, 196, .18); transition: background .15s ease; }
    /* Раунд 10 (F-8 T-874): чип «авто» вместо «— авто» */
    .chip-auto {
      background: rgba(245, 158, 11, 0.18);
      color: #fcd34d;
    }
    .log-exc {
      display: block; margin: 0;
      font-family: ui-monospace, Consolas, monospace;
      font-size: 0.72rem;
      white-space: pre-wrap;
      color: #fca5a5;
    }
    /* Раунд 10 (BUG-7): ghost-textarea копирования — за экраном
       (fixed left:-9999px), opacity:0, без раскладки-эффекта в Telegram
       WebView; временный узел (10.7, удаляется после клипа). ВАЖНО:
       НЕ visibility:hidden — иначе элемент не фокусируется и
       execCommand('copy')-fallback ломается (Telegram WebView). */
    .clipboard-ghost {
      position: fixed;
      left: -9999px;
      top: 0;
      width: 1px;
      height: 1px;
      opacity: 0;
      contain: strict;
      pointer-events: none;
      border: 0;
      padding: 0;
      background: transparent !important;
    }

    /* Тосты */
    .toast-wrap {
      position: fixed;
      /* F0.4 (ADR-1025-4 D3): safe area — max(env, --tg-content-safe-area-*,
         --tg-safe-area-*) (образец .fullscreen-mode header ниже). Не
         перекрываем header/навигацию/селектор области. */
      top: calc(1rem + max(env(safe-area-inset-top, 0px), var(--tg-content-safe-area-inset-top, 0px), var(--tg-safe-area-inset-top, 0px)));
      right: calc(1rem + max(env(safe-area-inset-right, 0px), var(--tg-content-safe-area-inset-right, 0px), var(--tg-safe-area-inset-right, 0px)));
      z-index: 60;
      display: flex;
      flex-direction: column;
      gap: 0.5rem;
      max-width: min(340px, calc(100vw - 2rem));
    }
    .toast {
      padding: 0.7rem 1rem;
      border-radius: 0.75rem;
      font-size: 0.85rem;
      animation: toast-in 0.25s ease;
      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
      border: var(--card-border);
    }
    /* F0.4 (ADR-1025-4 D2): длинная ошибка не «заливает» мобильную страницу —
       показываем компактно + «Подробнее» (раскрытие). */
    .toast-text--long {
      display: -webkit-box;
      -webkit-line-clamp: 3;
      -webkit-box-orient: vertical;
      overflow: hidden;
    }
    .toast-text--long.is-open {
      -webkit-line-clamp: unset;
      overflow: auto;
      max-height: 40vh;
    }
    .toast-more {
      margin-top: 0.35rem;
      padding: 0;
      background: transparent;
      border: none;
      color: inherit;
      font: inherit;
      text-decoration: underline;
      cursor: pointer;
    }
    @keyframes toast-in {
      from { opacity: 0; transform: translateY(-8px); }
      to   { opacity: 1; transform: translateY(0); }
    }
    .toast-ok    { background: rgba(22, 101, 52, 0.9);   color: #dcfce7; }
    .toast-err   { background: rgba(127, 29, 29, 0.92);  color: #fee2e2; }
    .toast-warn  { background: rgba(113, 63, 18, 0.92);  color: #fef3c7; }

    /* Модалка */
    .modal-backdrop {
      position: fixed;
      inset: 0;
      background: rgba(0, 0, 0, 0.55);
      backdrop-filter: blur(4px);
      z-index: 50;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 1rem;
    }

    /* Лор чатов (round 7, spec §3.10/E2): read-only авто-лор и инфо-строка */
    .lore-auto-area {
      background: rgba(120, 53, 15, 0.16);
      border-color: rgba(245, 158, 11, 0.35);
      color: #f3e2b8;
    }
    .lore-memory {
      background: rgba(0, 0, 0, 0.22);
    }
    .lore-diff-line {
      display: block;
      white-space: pre-wrap;
      word-break: break-word;
      font-family: ui-monospace, Consolas, monospace;
      font-size: 11px;
      line-height: 1.45;
    }

    /* Дерево чекбоксов */
    .tree-child { padding-left: 1.25rem; border-left: 1px solid rgba(255,255,255,0.1); margin-left: 0.4rem; }
    .tree-node label { display: flex; align-items: center; gap: 0.45rem; padding: 0.14rem 0; cursor: pointer; font-size: 0.85rem; }
    .tree-node input[type='checkbox'] { accent-color: var(--teal-500); width: 15px; height: 15px; cursor: pointer; }

    .spinner {
      width: 28px; height: 28px;
      border: 3px solid rgba(255,255,255,0.15);
      border-top-color: var(--teal-500);
      border-radius: 50%;
      animation: spin 0.8s linear infinite;
      margin: 0 auto;
    }
    @keyframes spin { to { transform: rotate(360deg); } }

    .scroll-thin::-webkit-scrollbar { width: 6px; height: 6px; }
    .scroll-thin::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.15); border-radius: 3px; }

    /* UI-полировка TMA: прилипающая шапка (непрозрачнее обычной card-solid,
       чтобы контент не просвечивал сквозь неё при скролле).
       10.7 (1b): горизонтальные safe-area (Telegram-кнопки/вырезы) —
       правые элементы шапки не уходят под нативные кнопки WebView.
       U07.2 (asap8-v6.3): формула max(env, --tg-content-safe-area-inset-*,
       --tg-safe-area-inset-*) обязательна и для ГОРИЗОНТАЛЬНЫХ инсетов —
       env(safe-area-inset-*) в Telegram Android часто = 0, а значения SDK
       лежат в --tg-*-переменных (иначе inline-⛶ в landscape уходит под
       нативную ✕/⋮ зону). Образец: .fullscreen-mode header ниже (10.10). */
    header.header-sticky {
      position: sticky;
      top: 0;
      z-index: 40;
      /* HOTFIX8 (ADR-1025-16 D2): шапка — отдельный серо-графитовый shell-слой
         §4 (--shell-bg, glass), не карточный --glass-bg. Ширину рамки даёт
         `[data-glass="shell"]`; сверху/сбоку рамка снята (full-bleed шапка). */
      background-color: var(--shell-bg);
      border-bottom: var(--shell-border);
      border-top: 0;
      border-right: 0;
      border-left: 0;
      box-shadow: var(--shell-shadow),
                  inset 0 1px 0 var(--shell-highlight),
                  inset 0 -1px 0 var(--shell-highlight-soft);
      /* A2/T-2589 (ADR-1025-12 D2; AMEND ADR-1025-13 D3): стекляннее карточек. */
      -webkit-backdrop-filter: var(--shell-blur);
      backdrop-filter: var(--shell-blur);
      padding-right: calc(1rem + max(env(safe-area-inset-right, 0px), var(--tg-content-safe-area-inset-right, 0px), var(--tg-safe-area-inset-right, 0px)));
      padding-left: calc(1rem + max(env(safe-area-inset-left, 0px), var(--tg-content-safe-area-inset-left, 0px), var(--tg-safe-area-inset-left, 0px)));
    }

    /* D (ADR-1025-12 D5, T-2606…T-2610): компактная двухстрочная шапка.
       Строка 1 — навигация/заголовок/⛶ (правый верхний угол, безопасная зона);
       строка 2 — селектор области/бейдж/аватар/роль. Без горизонтального скролла.
       `--header-h` задаёт резерв контента (ResizeObserver, app.js). */
    header.header-sticky.header-compact-v2 {
      flex-wrap: wrap;
      gap: .4rem;
      /* FS-HOTFIX 18.10: нативная зона клиента = СУММА системной и
         Telegram-части: contentSafeAreaInset отсчитывается от области,
         свободной от системных элементов (docs.telegram-mini-apps.com:
         «safe area — free from device elements, content safe area — free
         from Telegram UI elements»; рекомендация к сумме — tma.js#695).
         При --tg-content-safe-area-inset-top: 0 формула байт-в-байт равна
         прежней max(env, --tg-content, --tg-safe) — фикс d9b7f389 сохранён. */
      padding-top: calc(.6rem + max(env(safe-area-inset-top, 0px),
                    var(--tg-safe-area-inset-top, 0px))
                    + var(--tg-content-safe-area-inset-top, 0px));
      padding-bottom: .6rem;
    }
    /* Legacy (не compact): обёртка прозрачна для flex; CSS `order`
       восстанавливает прежний однорядный вид [scope][tech][tools][⛶][navbar]
       при той же единственной разметке (без дублирования селектора). */
    .header-scope-row { display: contents; }
    header.header-sticky:not(.header-compact-v2) .header-scope-row .ml-auto {
      order: 90;
    }
    header.header-sticky:not(.header-compact-v2) .header-fs-btn { order: 99; }
    header.header-sticky:not(.header-compact-v2) .navbar-band { order: 100; }
    /* Compact (IA v2 + UI_HEADER_COMPACT_V2): строка 1 — навигация/заголовок/⛶
       (правый верхний угол, безопасная зона); строка 2 — область/бейдж/аватар. */
    header.header-sticky.header-compact-v2 .header-title-wrap {
      flex: 1 1 auto; min-width: 0;
    }
    header.header-sticky.header-compact-v2 .header-fs-btn {
      order: 5; margin-left: auto;
      min-width: 44px; min-height: 44px;
      display: inline-flex; align-items: center; justify-content: center;
    }
    header.header-sticky.header-compact-v2 .header-scope-row {
      order: 10; flex: 1 1 100%;
      display: flex; align-items: center; flex-wrap: wrap;
      gap: .5rem; min-width: 0;
    }
    .header-compact-v2 .header-scope-row .scope-trigger { max-width: 60vw; }
    @media (max-width: 479px) {
      .header-compact-v2 .header-scope-row .header-user span { max-width: 4.5rem; }
    }

    /* Раунд 10.6 (A1/T-1161/T-1162): модель скролла без боковой панели.
       HOTFIX9 (ADR-1025-17 D1): .app-shell — flex-КОЛОНКА
       [header / main.scroll-area]; нормальный режим desktop —
       нативный скролл страницы, header sticky. Высота — из ЕДИНОГО источника
       `--app-usable-height` (алиас `--shell-h`); конкурирующих источников нет. */
    .app-shell {
      display: flex; flex-direction: column;
      min-height: var(--shell-h);
      height: auto;
      overflow: visible;
    }
    /* ASAP-speech-arch U-06 (§8): на desktop скроллится ДОКУМЕНТ, поэтому
       scroll-padding-top нужен и корневому скроллеру — иначе scrollIntoView
       к якорю/фокус ставит верх контента ПОД липкую шапку. `--header-h`
       измеряется ResizeObserver'ом (app.js::_initHeaderHeight) на :root. */
    html { scroll-padding-top: calc(var(--header-h, 0px) + 1rem); }
    /* HOTFIX9 D1: mobile (и любой fullscreen) — фиксированная flex-колонка
       ровно по доступной области; скроллится ТОЛЬКО центральная зона. */
    .app-shell.shell-mobile:not(.shell-layout-legacy),
    .app-shell.fullscreen-mode:not(.shell-layout-legacy) {
      height: var(--app-usable-height, 100vh);
      max-height: var(--app-usable-height, 100vh);
      min-height: 0;
      overflow: hidden;
    }
    .scroll-area {
      flex: 1 1 auto; min-height: 0; padding: 1rem;
      /* D3/T-2609 (ADR-1025-12 D5): резерв под sticky-шапку. `--header-h`
         измеряется ResizeObserver'ом (реальная высота строк 1+2), а не
         брейкпоинт-константой — верх контента не подлезает под панель и
         якорная прокрутка учитывает её высоту. */
      scroll-padding-top: calc(var(--header-h, 0px) + 1rem);
    }
    /* HOTFIX9 D1 (T-2795): единственный скроллер внутри flex-колонки —
       `main.scroll-area`; header/nav неподвижны. */
    .app-shell.shell-mobile:not(.shell-layout-legacy) > main.scroll-area,
    .app-shell.fullscreen-mode:not(.shell-layout-legacy) > main.scroll-area {
      flex: 1 1 auto; min-height: 0;
      overflow-y: auto; overflow-x: hidden;
      -webkit-overflow-scrolling: touch;
      overscroll-behavior: contain;
    }
    /* D2 (T-2802): header — flex:0 0 auto ⇒ контент структурно НЕ может
       оказаться под шапкой (никаких absolute-сдвигов). */
    header.header-sticky { flex: 0 0 auto; }
    /* HOTFIX7 D1.2 (ADR-1025-13): fullscreen — shell ровно по видимой области,
       единственный скроллер внутри `.scroll-area`. Никаких смешанных
       min-height/height с разными значениями (P4 устранён). */
    .fullscreen-mode {
      overflow: hidden;
    }
    .fullscreen-mode .scroll-area {
      overflow-y: auto;
      -webkit-overflow-scrolling: touch;
      overscroll-behavior: contain;
      /* HOTFIX10 (ADR-1025-18 D3, T-2853/T-2854): нижний safe-area учитывается
         РОВНО ОДИН РАЗ — в `--app-usable-height` (telegram-init.js). Второй
         вычет `env(safe-area-inset-bottom)` здесь давал двойной учёт и обрезал
         нижнюю навигацию. Оставлен только базовый отступ. */
      padding-bottom: 1rem;
    }
    /* HOTFIX7 D4.4 (ADR-1025-13): UI_SHELL_LAYOUT_V2=OFF → прежняя геометрия
       высот (откат самого рискованного, не воспроизводимого headless изменения):
       конкурирующий min-height(stable) + height:100dvh в fullscreen. */
    .app-shell.shell-layout-legacy {
      min-height: var(--tg-viewport-stable-height, 100vh);
      height: auto;
      overflow: visible;
    }
    .app-shell.shell-layout-legacy.fullscreen-mode {
      height: 100dvh;
      max-height: none;
      min-height: var(--tg-viewport-stable-height, 100vh);
      overflow: hidden;
    }
    /* Нет скролл-чейнинга у вложенных скроллеров (T-1163) */
    .log-panel, .scope-panel, .modal-body { overscroll-behavior: contain; }

    @media (max-width: 768px) {
      header.header-sticky {
        padding-top: calc(0.75rem + env(safe-area-inset-top, 0px));
      }
    }

    /* Раунд 10.10 (п.1, ADR-1010): в TMA-fullscreen нативные кнопки
       (Свернуть/Ещё/Закрыть) лежат поверх верхней полосы WebView, а
       env(safe-area-inset-*) внутри Telegram на Android часто = 0. Берём
       max(env, --tg-content-safe-area-inset-*, --tg-safe-area-inset-*):
       Telegram отдаёт точные значения в этих CSS-переменных (Bot API 8.0).
       Специфичность (0,2,1) > базового (0,1,1) — перекрывает и @media, и
       базовое правило, НЕ уменьшая текущие отступы (10.7 по ширине,
       10.9 scroll-area — не тронуты). */
    .fullscreen-mode header.header-sticky {
      /* FS-HOTFIX 18.10: сумма системной и Telegram-части (нативные кнопки
         клиента рисуются ПОВЕРХ WebView — их зону шапка обязана обходить
         целиком; формула совпадает с .header-compact-v2 выше). */
      padding-top: calc(0.75rem + max(env(safe-area-inset-top, 0px), var(--tg-safe-area-inset-top, 0px)) + var(--tg-content-safe-area-inset-top, 0px));
      padding-right: calc(1rem + max(env(safe-area-inset-right, 0px), var(--tg-content-safe-area-inset-right, 0px), var(--tg-safe-area-inset-right, 0px)));
      padding-left: calc(1rem + max(env(safe-area-inset-left, 0px), var(--tg-content-safe-area-inset-left, 0px), var(--tg-safe-area-inset-left, 0px)));
    }

    /* Раунд 10.10 (п.2): обёртка графика истории ключей — относительное
       позиционирование + реактивная высота (maintainAspectRatio:false). */
    .keys-chart { position: relative; width: 100%; }

    /* F6 (T-1460, ТЗ §8): SVG-EKG «Сердцебиение» — свой inline-SVG +
       CSS-анимация (Chart.js key-history не трогаем). Период задаётся
       переменной --ekg-period из computed heartbeat; цвет — классом
       .ekg-calm/.ekg-elev/.ekg-high. */
    .ekg-wrap { position: relative; width: 100%; max-width: 100%; }
    .ekg { display: block; width: 100%; max-width: 100%; height: 56px; overflow: hidden; }
    .ekg-base {
      fill: none; stroke: currentColor; stroke-width: 1.5;
      stroke-linejoin: round; stroke-linecap: round; opacity: .18;
    }
    .ekg-trace {
      fill: none; stroke: currentColor; stroke-width: 2.5;
      stroke-linejoin: round; stroke-linecap: round;
      stroke-dasharray: 70 330; stroke-dashoffset: 70;
      animation: ekg-sweep var(--ekg-period, 2.4s) linear infinite;
      filter: drop-shadow(0 0 4px currentColor);
    }
    @keyframes ekg-sweep {
      from { stroke-dashoffset: 70; }
      to   { stroke-dashoffset: -330; }
    }
    .ekg-calm { color: #34d399; }   /* норма → спокойный зелёный */
    .ekg-elev { color: #f59e0b; }   /* 0.5..0.8 → учащённый оранжевый */
    .ekg-high { color: #ef4444; }   /* >0.8 → частый красный */
    @media (prefers-reduced-motion: reduce) {
      .ekg-trace { animation: none !important; stroke-dashoffset: 0; }
      .hb-canvas { animation: none !important; }
    }

    /* §15/C1 (ADR-1025-12 D4): контейнер сердебиения не выходит за экран.
       `.status-block` ограничен по ширине/overflow; canvas/линза — width:100%. */
    .status-block { max-width: 100%; overflow: hidden; }
    .status-block__pulse { min-width: 0; max-width: 100%; }
    /* HOTFIX10 H-1 (round1025, T-2855): grid-контейнер `main.scroll-area` с
       ОПРЕДЕЛЁННОЙ высотой сжимал auto-строку с элементом, у которого
       `overflow:hidden` (`.status-block`, §15/C1), до padding+border (34px):
       карточка «Статус» обрезала сердцебиение/метрики, а следующая карточка
       наезжала поверх (mobile и desktop fullscreen). `max-content` возвращает
       строке реальную высоту контента. Дизайн сердцебиения и flex/графит §63
       не затрагиваются — меняется только трек grid. */
    main.scroll-area { grid-auto-rows: max-content; }
    .hb-wrap { position: relative; width: 100%; max-width: 100%; min-height: 56px; }
    .hb-canvas { display: block; width: 100%; max-width: 100%; height: 56px;
                 cursor: pointer; }
    .hb-tip {
      position: absolute; left: 0; right: 0; top: calc(100% + 4px);
      z-index: 5; margin: 0 auto; max-width: 320px;
      background: var(--glass-bg-strong); border: var(--glass-border);
      border-radius: var(--radius-md); padding: .5rem .6rem;
      font-size: .72rem; line-height: 1.45; color: var(--text-2);
      -webkit-backdrop-filter: var(--glass-blur);
      backdrop-filter: var(--glass-blur);
      box-shadow: var(--glass-shadow);
    }
    .hb-tip b { color: var(--text-1); }
    /* Состояния §15: различимы цветом/интенсивностью (и характером в canvas). */
    .hb-healthy  { color: var(--ok); }
    .hb-warning  { color: var(--warn); }
    .hb-critical { color: var(--err); }
    .hb-unknown  { color: var(--text-3); }
    @media (max-width: 767px) {
      /* §15/C1: на мобильном сердебиение — отдельная полноширинная область
         под системными метриками (grid уже одноколоночный). */
      .status-block__pulse { width: 100%; }
      /* HOTFIX7 D1.6: канвас/обёртка не схлопываются (в т.ч. в fullscreen). */
      .hb-canvas { height: 52px; }
      .hb-wrap { min-height: 52px; }
    }

    /* F5 (T-1450..T-1456, ТЗ §5/§7): дашборд «Осмысление» — бегущие строки
       (opacity-50 по краям → 100 в центре) + граф + виджет «Интеллект и
       Память». Только фронт-классы (каталог-Δ=0). */
    .cognition-ribbons { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; }
    @media (max-width: 640px) { .cognition-ribbons { grid-template-columns: 1fr; } }
    /* F5 (T-1588, round1015, ТЗ §5): шапка «Мониторинга Интеллекта» —
       десктоп горизонтально (растягивается), мобильно жёстко в столбик:
       заголовок → бейдж Сна → бейдж Глубокого сна (кнопка ⟳ в конец). */
    .intel-header { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }
    @media (max-width: 640px) {
      .intel-header { flex-direction: column; align-items: flex-start; }
      .intel-header .intel-title { width: 100%; }
    }
    .ribbon {
      border: 1px solid rgba(255,255,255,.08); border-radius: 10px;
      padding: 8px; overflow: hidden; min-width: 0;
    }
    .ribbon-title { font-size: .72rem; font-weight: 700; margin-bottom: 6px; }
    .ribbon-viewport {
      position: relative; height: 156px; overflow: hidden;
      -webkit-mask-image: linear-gradient(to bottom, transparent, #000 20%,
        #000 80%, transparent);
      mask-image: linear-gradient(to bottom, transparent, #000 20%,
        #000 80%, transparent);
    }
    .ribbon-track { animation: ribbon-scroll 22s linear infinite; }
    @keyframes ribbon-scroll {
      from { transform: translateY(0); }
      to   { transform: translateY(-50%); }
    }
    .ribbon-item {
      display: flex; gap: 6px; align-items: baseline; font-size: .78rem;
      padding: 3px 4px; transition: opacity .6s ease; min-width: 0;
    }
    .ribbon-ts { color: #94a3b8; font-size: .68rem; flex: none; }
    .ribbon-op-100 { opacity: 1; }
    .ribbon-op-75 { opacity: .75; }
    .ribbon-op-50 { opacity: .5; }
    /* F8 (ADR-1024-5 D3/UPD3 №4): пояснительный Empty State в лентах
       «Парадигмы»/«Эволюция характера» — причины и как работает эволюция. */
    .ribbon-empty { height: 100%; overflow-y: auto; padding: 4px 4px 2px; }
    .ribbon-empty__title {
      font-size: .76rem; font-weight: 600; color: #94a3b8; margin-bottom: 4px;
    }
    .ribbon-empty__text {
      font-size: .68rem; color: #94a3b8; line-height: 1.35;
    }
    .ribbon-empty__reason {
      font-size: .66rem; color: #64748b; margin-top: 5px;
    }
    .cognition-graph {
      height: 320px; width: 100%; border: 1px solid rgba(255,255,255,.08);
      border-radius: 10px; background: rgba(0,0,0,.18);
    }
    /* F2 (graph-frontend-physics-search-round1015): «Поиск по графу» —
       flex-wrap; на узких экранах переносится в столбик.
       F5 (T-1821, ТЗ п.4): мобила — компактный input (высота+шрифт),
       десктоп — ОГРАНИЧЕННАЯ ширина (не «на всю ширину»). */
    .graph-search {
      display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
      margin-top: 8px;
    }
    .graph-search .graph-search__input { flex: 1 1 140px; min-width: 0; }
    @media (max-width: 479px) {
      .graph-search { flex-direction: column; align-items: stretch; }
      .graph-search .graph-search__input {
        flex: none; width: 100%; padding: 0.3rem 0.5rem; font-size: 0.8rem;
      }
      .graph-search .btn-ghost { font-size: 0.7rem; padding: 0.25rem 0.45rem; }
    }
    @media (min-width: 768px) {
      .graph-search { max-width: 460px; }        /* не на всю ширину */
      .graph-search .graph-search__input { flex: 1 1 220px; }
    }
    /* F5 (T-1819, ТЗ п.5): объединённый блок «Статус» —
       Сердцебиение + Бот + Сервер (мобила — столбик, десктоп — рядом). */
    .status-block { grid-column: 1 / -1; }
    .status-block__grid { display: grid; grid-template-columns: 1fr; gap: 12px; }
    @media (min-width: 768px) {
      .status-block__grid {
        grid-template-columns: 1.4fr 1fr 1.2fr; align-items: start;
      }
    }

    /* ═══ F11 (10.25, ADR-1025-23 D1): композиция витрины «Статус» ═══
       Единый 12-колоночный контейнер внутри ветки `activeTab === 'status'`;
       `main.scroll-area` и прочие вкладки НЕ меняются. Адаптив §70:
       ≥992 — 12 колонок; 768–991 — 6 (карточки span 6); ≤767 — 1 колонка
       (тот же DOM-порядок §12). Анти-overflow: minmax(0,1fr) + min-width:0. */
    .status-grid {
      grid-column: 1 / -1;
      display: grid;
      grid-template-columns: repeat(12, minmax(0, 1fr));
      gap: 1rem;
      align-content: start;
      min-width: 0;
    }
    .status-grid > * { min-width: 0; }
    /* База: всё на всю ширину (legacy-безопасность). */
    .status-grid > .sg { grid-column: 1 / -1; }
    /* Спаны §12 (12-кол. база). */
    .status-grid > .sg-5 { grid-column: span 5; }
    .status-grid > .sg-7 { grid-column: span 7; }
    .status-grid > .sg-8 { grid-column: span 8; }
    .status-grid > .sg-4 { grid-column: span 4; }
    .status-grid > .sg-12 { grid-column: 1 / -1; }
    /* §14: метрики+heartbeat — 7 колонок (класс `.status-block` сохранён
       байт-в-байт для hotfix6/10-контракта; спаны задаются селектором). */
    .status-grid > .status-block { grid-column: span 7; }
    .status-grid > .glass-surface { grid-column: 1 / -1; }
    @media (max-width: 991px) {
      .status-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); }
      .status-grid > .sg-5,
      .status-grid > .sg-7,
      .status-grid > .sg-8,
      .status-grid > .sg-4,
      .status-grid > .status-block { grid-column: span 6; }
    }
    @media (max-width: 767px) {
      .status-grid { grid-template-columns: minmax(0, 1fr); }
      .status-grid > .sg-5,
      .status-grid > .sg-7,
      .status-grid > .sg-8,
      .status-grid > .sg-4,
      .status-grid > .sg-12,
      .status-grid > .status-block { grid-column: 1 / -1; }
    }
    /* Kill-switch UI_STATUS_GRID_V2=OFF → одноколоночный безопасный режим
       (НЕ byte-identical legacy-DOM; M-F11S-1) без редеплоя. */
    .status-grid--legacy { grid-template-columns: minmax(0, 1fr) !important; }
    .status-grid--legacy > * { grid-column: 1 / -1 !important; }

    /* L-F11S-3: тач-цели ≥44px — быстрый переход §20 и контролы/чипы-соседи
       полноэкранного графа. */
    .status-counts .btn-ghost { min-height: 44px; }
    .status-graph-full .btn-ghost { min-height: 44px; }

    /* ═══ Wave 2 UX: суб-вкладки «Аналитики» (#/oversight) ═══
       Desktop: горизонтальный ряд табов; mobile/narrow: горизонтальный
       скролл (свайп), тач-цели ≥44px, без переноса строк. Активная вкладка —
       заливка + рамка; цвет НЕ единственный носитель (aria-selected +
       is-active + вес шрифта). */
    .oversight-tabs__row {
      display: flex;
      flex-wrap: wrap;
      gap: 4px;
      min-width: 0;
    }
    .oversight-tab {
      appearance: none;
      border: 1px solid transparent;
      background: transparent;
      color: var(--text-2, #AAB6C8);
      font-size: .8rem;
      line-height: 1;
      padding: 8px 12px;
      border-radius: 999px;
      cursor: pointer;
      white-space: nowrap;
      min-height: 36px;
      min-width: 0;
    }
    .oversight-tab:hover { background: rgba(255, 255, 255, .06); }
    .oversight-tab.is-active {
      background: rgba(139, 92, 246, .18);
      border-color: rgba(139, 92, 246, .5);
      color: var(--text-1, #F4F7FB);
      font-weight: 600;
    }
    .oversight-tab:focus-visible {
      outline: 2px solid rgba(139, 92, 246, .7);
      outline-offset: 2px;
    }
    /* ═══ W2-SHELL (U02): mobile <768 — лента обрезанных pills ЗАМЕНЕНА
       компактным полноширинным dropdown «Раздел: [текущая ▾]» (стили —
       в блоке W2-SHELL ниже). Горизонтальный скролл табов больше не канон:
       на 320px не должно быть невидимых крайних вкладок. Desktop ≥768 —
       прежняя горизонтальная панель (правила выше без изменений). ═══ */
    @media (max-width: 767px) {
      .oversight-tabs__row { display: none; }
      .oversight-tab { min-height: 44px; }
    }
    /* Открытый mobile-dropdown поднимает карточку над соседями (grid-item
       z-index; панель не должна перекрываться следующими карточками).
       WIN-GLASS-P0 2.58.85 (регресс, DROPDOWN-WG): glass-refraction.js
       инлайнит `overflow: clip` на карточки-поверхности — открытая панель
       уходит НИЖЕ края карточки и обрезается: elementFromPoint на опции =
       соседняя карточка, тап не доходит. Пока список открыт, клип снят
       (`!important` — единственный способ перебить inline); при закрытии
       правило не действует и клип возвращается сам. Рефракция/Tier/бюджеты
       не тронуты (слой живёт, обрезание только у открытого списка). */
    .oversight-tabs.oversight-dd-open { position: relative; z-index: 45; }
    .oversight-tabs.oversight-dd-open { overflow: visible !important; }
    .status-graph-full .badge {
      min-height: 44px; display: inline-flex; align-items: center;
    }
    /* FIX-logs-anchor: логи — физический блок внизу «Аналитики» (вне
       таб-гвардов); вкладка «Логи» и карточка «Логи → Аналитика» — якоря:
       скролл к блоку + короткая вспышка контура (~1с). Цвет не единственный
       носитель — движение и позиция скролла. */
    .status-logs--flash {
      animation: status-logs-flash 1s ease-out 1;
    }
    @keyframes status-logs-flash {
      0% { box-shadow: 0 0 0 2px rgba(139, 92, 246, .8); }
      100% { box-shadow: 0 0 0 2px rgba(139, 92, 246, 0); }
    }
    @media (prefers-reduced-motion: reduce) {
      .status-logs--flash { animation: none; }
    }

    /* §13 Hero: компактная карточка состояния бота (Liquid Glass, без
       длинной таблицы/постоянной пульсации). */
    .status-hero__title { font-size: .95rem; font-weight: 700; }
    /* §20: быстрый переход «Ошибки/Предупреждения» (вверху Статуса). */
    .status-counts { display: flex; align-items: center; gap: .5rem;
      flex-wrap: wrap; }
    /* §17: виджет сна — бейджи + последнее выполнение; свечение активных
       — существующий `.badge.glow`. */
    .status-sleep .sleep-phase { border-top: 1px solid rgba(255,255,255,.08);
      padding-top: .5rem; margin-top: .5rem; }
    .status-sleep .sleep-phase:first-of-type { border-top: none;
      padding-top: 0; margin-top: 0; }
    /* §19 «Новые факты» — ТОЛЬКО вертикальный пользовательский скролл;
       позиция не сбрасывается (список не пересоздаётся, без автопрокрутки). */
    .status-facts .facts-list { max-height: 260px; overflow-y: auto;
      display: flex; flex-direction: column; gap: .4rem; }
    .status-facts .facts-item { border: 1px solid rgba(255,255,255,.08);
      border-radius: var(--radius-md); padding: .4rem .55rem; }
    .status-facts .facts-item b { color: var(--text-1); }
    /* §19 «Бюджеты интеллекта». */
    .status-budgets .budget-row { margin-bottom: .6rem; }
    .status-budgets .budget-row:last-child { margin-bottom: 0; }
    /* §16/D4: mobile — отдельный экран полного исследования графа
       (fallback-шторка при IA_V2_ENABLED=false/нет hash-навигации). */
    .status-graph-full { position: fixed; inset: 0; z-index: 60;
      display: flex; flex-direction: column; gap: .5rem;
      padding: .75rem; background: var(--glass-bg-strong);
      -webkit-backdrop-filter: var(--glass-blur);
      backdrop-filter: var(--glass-blur); min-width: 0; }
    .status-graph-full .cognition-graph--full { flex: 1 1 auto;
      height: auto; min-height: 240px; }
    /* HOTFIX10 (ADR-1025-18 D1, T-2848/T-2849): КОНТРАКТ GlassSurface.
       Контейнер задаёт геометрию заранее; декоративные слои библиотеки
       (`absolute; inset:0; pointer-events:none` из vendored CSS) лежат НИЖЕ
       контента; `isolation:isolate` не даёт микшировать слои с фоном;
       `contain:layout paint` не выпускает декор за пределы блока. Стекло — на
       ОДНОМ изолированном декоративном элементе (без данных/контролов). */
    .glass-surface {
      grid-column: 1 / -1;
      position: relative;
      height: 44px;
      border-radius: var(--radius-lg);
      overflow: hidden;
      isolation: isolate;
      contain: layout paint;
      pointer-events: none;
      /* Тёмная «бумага» frost-слоя (не белая) — честный frosted, не рефракция. */
      --glass-paper: var(--surface-1);
      --glass-ink: #000;
    }
    /* Контент (если появится) — строго ВЫШЕ декоративных слоёв библиотеки. */
    .glass-surface > .glass-surface__content {
      position: relative; z-index: 1;
    }
    .badge.glow {
      box-shadow: 0 0 10px currentColor;
      animation: badge-pulse 1.6s ease-in-out infinite;
    }
    @keyframes badge-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .6; } }
    .progress > .bar-red { background: #ef4444 !important; }
    .timeline-list {
      display: flex; flex-direction: column; gap: 2px;
      max-height: 140px; overflow-y: auto;
    }
    .timeline-row {
      display: flex; gap: 6px; font-size: .76rem; align-items: baseline;
      min-width: 0;
    }
    @media (prefers-reduced-motion: reduce) {
      .badge.glow { animation: none !important; }
      .ribbon-track { animation: none !important; }
      .ribbon-viewport {
        -webkit-mask-image: none !important; mask-image: none !important;
      }
      .ribbon-item { opacity: 1 !important; }
    }

    /* ═══════════════════════════════════════════════════════════════════
       Раунд 10.20 — рефакторинг UX/UI мини-аппа (БЛОК 3). МЕНЮ НЕ МЕНЯЕТСЯ.
       ═══════════════════════════════════════════════════════════════════ */

    /* §9/F2 (ADR-1025-9 D2): Liquid Glass уровень B (default) — карточки/панели/
       модалки/модальные блоки: backdrop blur + светлая кромка + внутренний блик +
       мягкая тень. RC-A: `.card` (94 узла) обязан входить в glass-set; alpha .5. */
    .card,
    .modal-card,
    .module-card,
    .hub-card,
    .prov-block,
    details.advanced,
    .scope-panel,
    .glass-panel,
    .oversight-panel {
      background-color: var(--glass-bg);
      -webkit-backdrop-filter: var(--glass-blur) saturate(140%);
      backdrop-filter: var(--glass-blur) saturate(140%);
      border: var(--glass-border);
      /* D3.4/ADR-1025-13: карточки — тоньше и ближе к фону (низкая «высота»),
         отдельная --card-shadow; модалки/тултипы возвращаются на --glass-shadow
         ниже — сохраняется глубина «фон → карточки → shell → модалки». */
      box-shadow: var(--card-shadow),
                  inset 0 1px 0 var(--glass-highlight);
    }
    /* D3.4: модалки — над shell, сохраняют плотную --glass-shadow. */
    .modal-card {
      box-shadow: var(--glass-shadow),
                  inset 0 1px 0 var(--glass-highlight);
    }
    /* ═══ W2-GLASS (U08.2/U08.3): Tier A hero — реальная edge-рефракция ═══
       Слоистая семантика .lg-panel на атрибутивном пути (псевдослои, ТЗ U08.2
       допускает при той же z-order-семантике):
         root            = .lg-panel__backdrop  (pixels/refraction ЗА панелью:
                           backdrop-filter; url(#lg-lens) — ТОЛЬКО при
                           data-glass-tier="a" (render-probe + Chromium;
                           WebKit игнорирует url() — bug 245510 → честный B))
         ::before        = .lg-panel__tint      (tint + мягкий направленный
                           sheen; z-index:-1, под контентом)
         ::after         = .lg-panel__rim       (masked ring: rim-градиент +
                           specular-дуга + chromatic fringe 0.3–1.2px,
                           всё edge-only)
       content-слой — сами дочерние узлы (in-flow, поверх z:-1-псевдо);
       фильтр НИКОГДА не вешается на корень с текстом/на текст (U08.2).
       До первого успешного probe узел живёт как Tier B (frost) — честный
       дефолт без ожидания JS. */
    [data-glass="a"] {
      position: relative;
      isolation: isolate;
      border-radius: var(--lg-radius-hero);
      background-color: var(--glass-bg);
      border: var(--glass-border);
      box-shadow: var(--lg-shadow),
                  inset 0 1px 0 var(--glass-highlight);
    }
    [data-glass="a"]:not([data-glass-tier="a"]) {
      -webkit-backdrop-filter: var(--lg-frost-hero);
      backdrop-filter: var(--lg-frost-hero);
    }
    [data-glass="a"][data-glass-tier="a"] {
      -webkit-backdrop-filter: var(--lg-frost-hero) url(#lg-lens);
      backdrop-filter: var(--lg-frost-hero) url(#lg-lens);
    }
    /* ═══ WIN-GLASS-P0 (18.10.2026): носитель оптики — слой преломления ═══
       Клиент не рендерит `url()` внутри backdrop-filter (Android WebView/
       WebKit, bug 245510): оптику даёт decorative-слой `.lg-refract`
       (glass-refraction.js — полигональный фон production + SVG-карта линзы,
       маска-рамка у кромок). У поверхности остаётся только frost без url():
       двойное преломление и двойной blur исключены, контраст/прозрачность
       сохраняются, текст/контролы не искажаются (слой под контентом,
       pointer-events:none). */
    [data-refract-layer="on"][data-glass-tier="a"],
    [data-refract-layer="on"][data-glass-tier="a"] .lg-panel__backdrop,
    /* выше по специфичности, чем `.lg-panel--hero[data-glass-tier="a"]
       .lg-panel__backdrop` (секция lg-panel ниже по файлу) */
    [data-refract-layer="on"][data-glass-tier="a"].lg-panel--hero
      .lg-panel__backdrop,
    [data-refract-layer="on"][data-glass-tier="a"].lg-panel .lg-panel__backdrop {
      -webkit-backdrop-filter: var(--lg-frost-hero);
      backdrop-filter: var(--lg-frost-hero);
    }
    [data-glass="a"]::before {
      content: "";
      position: absolute; inset: 0; z-index: -1;
      pointer-events: none; border-radius: inherit;
      background:
        radial-gradient(90% 60% at 88% 6%,
          rgba(210, 238, 255, 0.10) 0%, rgba(210, 238, 255, 0) 52%),
        var(--lg-tint-hero);
    }
    [data-glass="a"]::after {
      content: "";
      position: absolute; inset: 0; z-index: -1;
      pointer-events: none; border-radius: inherit; padding: 1.5px;
      background:
        var(--lg-specular-arc),
        var(--lg-fringe),
        var(--lg-rim);
    }
    @supports ((mask-composite: exclude) or (-webkit-mask-composite: xor)) {
      [data-glass="a"]::after {
        -webkit-mask: var(--lg-ring-mask);
        mask: var(--lg-ring-mask);
        -webkit-mask-composite: xor;
        mask-composite: exclude;
      }
    }
    /* mask-composite НЕ поддерживается → rim по box-shadow/overlay
       (U08.5.3: ВСЕ контролы видимы и кликабельны, скриншот fallback). */
    @supports not ((mask-composite: exclude) or (-webkit-mask-composite: xor)) {
      [data-glass="a"]::after {
        background: none;
        box-shadow: inset 0 0 0 1px rgba(210, 235, 255, 0.45),
                    inset 0 1px 0 rgba(248, 254, 255, 0.55),
                    inset 0 -1px 0 rgba(150, 190, 240, 0.25);
      }
    }
    /* ═══ HOTFIX8 (ADR-1025-16 D2): shell v3 — нейтральный графитовый glass ═══
       Панели (sidebar/header/drawer/bottom-nav/more-sheet) больше НЕ несут
       `data-glass="a"` → цветная teal/blue/violet линза-ореол
       `[data-glass="a"]::before` к shell не применяется. Рецепт §4: `--shell-bg`
       + тонкая обводка + мягкий inner highlight + subtle specular/текстура +
       БЕСЦВЕТНЫЙ sheen ПОД контентом. Без внешнего glow/виньетки. */
    [data-glass="shell"] {
      position: relative;
      isolation: isolate;
      background-color: var(--shell-bg);
      background-image: var(--shell-specular);
      border: var(--shell-border);
      box-shadow: var(--shell-shadow),
                  inset 0 1px 0 var(--shell-highlight);
      -webkit-backdrop-filter: var(--shell-blur);
      backdrop-filter: var(--shell-blur);
    }
    /* Очень слабый нейтральный specular (бесцветный, opacity ≤ .05, z-index:-1
       в изолированном контексте → под контентом). W2-GLASS: filter:url(#lg-lens)
       снят — это displacement-фильтр реальной рефракции ЗАДНЕГО плана (Tier A
       hero) и на sheen-градиенте shell не имеет смысла (U08.1: фильтр на
       собственном градиенте = декорация, не рефракция). Shell — Tier B. */
    [data-glass="shell"]::after {
      content: "";
      position: absolute; inset: 0; z-index: -1;
      pointer-events: none; border-radius: inherit;
      background: linear-gradient(135deg,
                  rgba(255, 255, 255, .06), transparent 68%);
      opacity: var(--shell-sheen-opacity, .05);
    }
    /* §9/F2 (AMEND ADR-1025-12 D1): обратимое понижение A → B (нет
       поддержки рендера url-фильтра (probe) / перф-кап / reduced-motion /
       low-end): JS ставит `data-glass-downgraded` + `data-glass-tier="b"`.
       W2-GLASS (U08.3e): понижение НЕ убивает стекло — статичные rim/tint/
       specular (::before/::after выше) остаются; снимается только тяжёлая
       рефракция (url(#lg-lens) не применяется без tier="a"). opt-in
       `data-glass` (декларация) НЕ переписывается — b→a обратимо. */
    [data-glass="a"][data-glass-downgraded="1"] {
      -webkit-backdrop-filter: var(--lg-frost-hero);
      backdrop-filter: var(--lg-frost-hero);
    }
    /* §9/F2 (T-2538): явный уровень B — frost без преломления. W2-GLASS:
       blur снижен 16→8px (перф mid-range Android, U08.3e), кромка/блик —
       в appended-секции W2-GLASS. */
    [data-glass="b"] {
      background-color: var(--glass-bg);
      -webkit-backdrop-filter: var(--lg-frost);
      backdrop-filter: var(--lg-frost);
      border: var(--glass-border);
      box-shadow: var(--card-shadow),
                  inset 0 1px 0 var(--glass-highlight);
    }
    /* §9/F2 (T-2539): deny-list — уровень C. textarea/таблицы прав/логи/длинные
       формы/редакторы промптов: никакого преломления и blur, плотная подложка. */
    [data-glass="c"],
    .keys-avail,
    .avail-list,
    .matrix-table,
    .log-panel,
    .log-code,
    textarea,
    textarea.field,
    .prompt-editor {
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
    }
    [data-glass="c"] {
      background-color: var(--glass-bg-strong);
      box-shadow: var(--glass-shadow);
    }
    /* G1.6/UPD3 (T-1935): grid-контейнеры — ТОЛЬКО раскладка, без фона/
       бордера/blur (раньше фон висел на обёртке «панель-слэб»). */
    .prov-grid,
    .module-list,
    .hub-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
      gap: 1rem;
      width: 100%;
      align-content: start;
      border: 0;
      background: transparent;
      -webkit-backdrop-filter: none;
      backdrop-filter: none;
      /* F1 (T-2405/§70): раскладки, зависящие от ширины КОМПОНЕНТА. */
      container-type: inline-size;
    }
    /* G1.5: вложенные карточки не складывают alpha в «кирпич». */
    .card .card,
    .modal-body .card {
      background-color: rgba(255, 255, 255, .04);
      -webkit-backdrop-filter: none;
      backdrop-filter: none;
    }
    /* G2.4/UPD3: мобильное схлопывание сетки — ПОСЛЕ правила-тройки
       (иначе более позднее auto-fit перебивает 1fr). */
    @media (max-width: 479px) {
      .prov-grid, .module-list, .hub-grid { grid-template-columns: 1fr; }
    }
    /* P0 Vision (P0V-UI-OVERFLOW): трек форм провайдеров — по ширине
       КОНТЕЙНЕРА, не viewport. `minmax(320px,1fr)` держал жёсткий пол 320px:
       если контейнер уже 320px (телефон с крупным системным шрифтом Android,
       узкая рабочая колонка в ландшафте), трек шире контейнера → форма
       обрезается/уезжает по горизонтали. `min(320px,100%)` = прежний пол
       320px на широком контейнере и полный отказ от него на узком (одна
       колонка во всю ширину). Правило тройки и мобильный блок выше не
       меняются (другие секции — прежние). */
    .prov-grid {
      grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
      container-name: prov-grid;
    }
    .modal-backdrop {
      background: rgba(0, 0, 0, 0.5);
      /* HOTFIX-TIERA (SOUL-1, владелец): скрим модалки БОЛЬШЕ НЕ размывает
         страницу. blur(16px) на скриме = двойное размытие (скрим + сам
         `.modal-card`) и конфликт вложенных слоёв: скрим создавал backdrop
         root, из-за чего рефракция карточки модалки была недостижима/мутна.
         Дим (.5) сохранён; blur+рефракция выполняет поверхность модалки
         (Tier A: blur 5px + url(#lg-lens); фолбэк — frost-hero). */
      -webkit-backdrop-filter: none;
      backdrop-filter: none;
    }
    /* webkit-фолбэк: плотный фон (уровень C), если backdrop-filter не поддержан.
       Не полагаемся на backdrop url-фильтр — без поддержки читаемый fallback.
       A2/T-2591: панели (sidebar/drawer/header/bottom-nav/more-sheet) тоже
       уходят на непрозрачную плотную подложку — раскладка/контраст сохранены. */
    @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
      .card, .modal-card, .module-card, .hub-card, .prov-block,
      details.advanced, .scope-panel, .glass-panel, .oversight-panel,
      [data-glass="a"], [data-glass="c"], .lg-panel {
        background-color: var(--glass-bg-strong);
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
      }
      .lg-panel__backdrop,
      .lg-panel__tint, .lg-panel__rim, .lg-panel__specular {
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
      }
      /* HOTFIX8 (ADR-1025-16 D2): shell-панели — плотный серо-графитовый
         фолбэк (раскладка/контраст сохранены, стекло честно исчезает). */
      [data-glass="shell"],
      .app-sidebar, .app-drawer, header.header-sticky {
        background-color: var(--shell-bg-strong);
        background-image: none;
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
      }
      [data-glass="a"]::before {
        content: none; -webkit-filter: none; filter: none;
        -webkit-mask-image: none; mask-image: none;
      }
      [data-glass="shell"]::after {
        content: none; -webkit-filter: none; filter: none;
      }
    }
    /* HOTFIX9 (ADR-1025-17 D4): UI_SHELL_GRAPHITE_V3=OFF → значения `--shell-*`
       hotfix8 (мягкий откат рецепта §8). Диагональная текстура НЕ возвращается —
       её удаление есть часть исправления UPD3 §7. */
    .app-shell.shell-v3-off {
      --shell-bg: rgba(24, 28, 38, 0.72);
      --shell-bg-mobile: rgba(24, 28, 38, 0.78);
      --shell-border-color: rgba(255, 255, 255, 0.08);
      --shell-highlight: rgba(255, 255, 255, 0.06);
      --shell-highlight-soft: rgba(255, 255, 255, 0.05);
      --shell-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
      --shell-blur: blur(18px) saturate(115%);
      --shell-specular: linear-gradient(160deg, rgba(255,255,255,.10), rgba(255,255,255,.02) 42%, transparent 72%);
    }
    /* Мобильный shell плотнее (§4: 0.78) — только для shell v3 (default). */
    @media (max-width: 767px) {
      .app-shell:not(.shell-v3-off) { --shell-bg: var(--shell-bg-mobile); }
    }
    /* HOTFIX7 D3.8 (ADR-1025-13): UI_SHELL_GLASS_V2=OFF → shell-панели
       возвращаются к общим карточным токенам (поведение до HOTFIX7) —
       независимый мягкий откат области D3 без редеплоя. */
    .app-shell.shell-glass-legacy .app-sidebar,
    .app-shell.shell-glass-legacy .app-drawer {
      background-color: var(--glass-bg);
      background-image: none;
      border-color: var(--glass-border-color);
      box-shadow: var(--glass-shadow), inset 0 1px 0 var(--glass-highlight);
      -webkit-backdrop-filter: var(--glass-blur) saturate(140%);
      backdrop-filter: var(--glass-blur) saturate(140%);
    }
    .app-shell.shell-glass-legacy header.header-sticky {
      background-color: var(--glass-bg-strong);
      background-image: none;
      border-color: transparent;
      border-bottom-color: var(--glass-border-color);
      box-shadow: var(--glass-shadow), inset 0 1px 0 var(--glass-highlight);
      -webkit-backdrop-filter: var(--glass-blur) saturate(140%);
      backdrop-filter: var(--glass-blur) saturate(140%);
    }
    .app-shell.shell-glass-legacy [data-glass="shell"]::after { content: none; }

    /* T-1900/UPD3 (T-1938) + D13 (§18I.13): sticky-save — КОМПАКТНАЯ панель
       (pill) внизу скролл-контейнера: монтируется ТОЛЬКО при dirty/saving/
       failed (clean → в DOM отсутствует, reserved spacer убран), не
       full-width (fit-content, прижата вправо). */
    .sticky-save {
      position: sticky;
      /* CFG-04B.2 (source L158): клавиатура. `--kb-offset` (app.js
         `_syncKeyboardOffset`) — фактическая высота экранной клавиатуры в
         layout-viewport; панель поднимается над ней, а не остаётся под
         кнопками. safe-area НЕ складывается с клавиатурой дважды: она
         считается один раз в padding-bottom ниже. */
      bottom: var(--kb-offset, 0px);
      z-index: 5;
      display: flex;
      align-items: center;
      gap: .5rem;
      flex-wrap: wrap;
      width: fit-content;
      max-width: 100%;
      min-width: 0;
      margin-left: auto;
      box-sizing: border-box;
      padding: .45rem .6rem;
      /* CFG-04B.2 (L158) + §64 D3: Telegram Android сообщает нижнюю зону не
         только через env(), но и через --tg-safe-area-inset-bottom /
         --tg-content-safe-area-inset-bottom. Берём максимум РОВНО ОДИН раз. */
      padding-bottom: calc(.45rem + max(env(safe-area-inset-bottom, 0px),
        var(--tg-safe-area-inset-bottom, 0px),
        var(--tg-content-safe-area-inset-bottom, 0px)));
      /* F9 (ADR-1025-22 D5): панель не уезжает под клавиатуру. */
      scroll-margin-bottom: var(--kb-offset, 0px);
      border: var(--glass-border);
      border-radius: .75rem;
      background-color: var(--glass-bg-strong);
      -webkit-backdrop-filter: var(--glass-blur);
      backdrop-filter: var(--glass-blur);
      box-shadow: var(--glass-shadow);
    }
    /* CFG-04C.2 (source L166): touch-зоны основных действий панели ≥44 px. */
    .sticky-save .btn-accent,
    .sticky-save .btn-ghost {
      flex: 0 0 auto;
      max-width: 100%;
      min-height: 44px;
      white-space: normal;
    }
    /* G5.1: панель лежит ВНУТРИ скроллера — это и есть sticky-носитель.
       HOTFIX9 D3 (T-2806) + D13 (§18I.13): в footer.modal-actions панель
       НЕ sticky (position:static), компактная, прижата вправо; сам футер
       рендерится только при dirty (см. v-if в шаблонах) или содержит
       только «Закрыть» (read-only окна). */
    .modal-footer > .sticky-save,
    .modal-actions > .sticky-save {
      position: static;
      flex: 0 1 auto;
      border: 0;
      padding-left: 0;
      padding-right: 0;
      padding-bottom: .45rem;
      /* HOTFIX-TIERA (SOUL-1): сейвбар внутри модалки — НЕ самостоятельное
         стекло (прозрачный футер): !important обязателен, иначе inline
         tier-A линза app.js навесила бы рефракцию на прозрачный футер. */
      background-color: transparent !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      box-shadow: none;
    }
    /* G5: модалка = flex-колонка [head / body / actions]; .modal-body —
       единственный скроллер. HOTFIX9 D3 (T-2806/T-2807): высота — от единого
       `--app-usable-height` (600–700 px окна: последнее поле скроллится,
       footer целиком в экране). */
    /* CFG-04C.4 (source L168): при открытой клавиатуре карточка ужимается на
       её высоту, чтобы футер/кнопки оставались в видимой области (safe-area
       здесь не вычитается — она учтена один раз в панели). */
    .modal-card {
      display: flex;
      flex-direction: column;
      max-height: min(calc(var(--app-usable-height, 100vh) - 24px
        - var(--kb-offset, 0px)), 720px);
      overflow: hidden;
      border-radius: var(--radius-lg);
    }
    .modal-head { flex: 0 0 auto; }
    .modal-body {
      flex: 1 1 auto;
      min-height: 0;
      overflow-y: auto;
      overscroll-behavior: contain;
      /* CFG-04B.3 (L159): запас = ФАКТИЧЕСКАЯ высота панели (app.js пишет
         `--sticky-save-h`) + клавиатура + 4px подстраховки от субпиксельного
         округления; фикс. 4.5rem был меньше панели на 320 px, и последнее
         поле уходило под неё. */
      scroll-padding-bottom: calc(var(--sticky-save-h) + var(--kb-offset, 0px) + 4px);
    }
    .modal-footer { flex: 0 0 auto; margin-top: 0; }
    /* HOTFIX9 D3: отдельная нижняя область модалки (SaveBar) — не sticky,
       не absolute, не поверх полей. */
    .modal-actions {
      flex: 0 0 auto;
      display: flex;
      align-items: flex-end;
      gap: .5rem;
      margin-top: .5rem;
      /* F9 (ADR-1025-22 D5): keyboard-offset (safe-area — в .sticky-save). */
      scroll-margin-bottom: var(--kb-offset, 0px);
      border-top: var(--glass-border);
    }
    /* G5.5 (UPD3-fix/M-1) + D13 (§18I.13): reserved spacer УДАЛЁН — панель
       монтируется только при dirty и не сдвигает контент в clean state.
       Оставлен scroll-padding-bottom (фокус/scrollIntoView не уезжает под
       панель). */
    .scroll-area:has(> .sticky-save) {
      padding-bottom: 0;
      /* CFG-04B.3 (L159): запас под фактическую высоту панели + клавиатуру. */
      scroll-padding-bottom: calc(var(--sticky-save-h) + var(--kb-offset, 0px) + 4px);
    }
    @supports not (selector(:has(*))) {
      /* Без :has() не сужаем content-box (M-1/L-3) — только scroll-padding. */
      .scroll-area {
        scroll-padding-bottom: calc(var(--sticky-save-h) + var(--kb-offset, 0px) + 4px);
      }
    }

    /* D13 (§18I.13) + CFG-04B.1 (source L157): компактный СЧЁТЧИК в шапке —
       только при dirty/saving/failed; показывает число изменённых полей;
       success → исчезает. Это индикатор, а не кнопка: фон/бордер как у
       btn-ghost (не accent), чтобы не конкурировать с единственной CTA
       сохранения — панелью внизу формы. */
    .header-save-chip {
      display: inline-flex;
      align-items: center;
      gap: .3rem;
      padding: .25rem .6rem;
      border-radius: 999px;
      white-space: nowrap;
      min-height: 32px;
      background: rgba(170, 182, 200, 0.10);
      border: var(--card-border);
      color: var(--text-2);
    }
    .header-save-chip__count {
      font-weight: 700;
      font-variant-numeric: tabular-nums;
    }
    .header-save-chip[data-save-state='error'],
    .header-save-chip[data-save-state='conflict'] {
      filter: saturate(1.4);
      outline: 1px solid #f87171;
    }

    /* ═══ CFG-04C.2 (source L166): touch-зоны переключателей ═════════════
       Визуальный трек остаётся 44×24; кликабельная область label в карточке
       параметра — минимум 44×44 CSS px (палец, а не курсор). */
    .card .param-toggle {
      min-width: 44px;
      min-height: 44px;
      justify-content: flex-end;
    }

    /* ═══ CFG-04C.3 (source L167): полный технический ключ ═══════════════
       В карточке ключ сокращается, но полное значение доступно: title,
       раскрытие (--open, перенос строк) и копирование. Русское название,
       описание и значение — отдельные элементы карточки. */
    .tech-key {
      display: flex;
      align-items: center;
      gap: .35rem;
      min-width: 0;
      max-width: 100%;
      margin-top: .1rem;
    }
    .tech-key__value {
      flex: 1 1 auto;
      min-width: 0;
      text-align: left;
      background: transparent;
      border: 0;
      padding: 0;
      color: var(--text-3);
      font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
      font-size: var(--tx-tiny);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      cursor: pointer;
      min-height: 24px;
      /* C.3: скрытая подсказка «ключ кликабелен» без изменения палитры. */
      text-decoration: underline dotted;
      text-decoration-color: rgba(170, 182, 200, 0.35);
      text-underline-offset: 3px;
    }
    .tech-key__value--open {
      white-space: normal;
      overflow-wrap: anywhere;
      overflow: visible;
      text-overflow: clip;
    }
    .tech-key__copy {
      flex: 0 0 auto;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      min-width: 32px;
      min-height: 32px;
      padding: 0 .25rem;
      border-radius: .5rem;
      border: 1px solid transparent;
      background: transparent;
      color: var(--text-3);
      cursor: pointer;
    }
    .tech-key__copy-label {
      font-size: var(--tx-tiny);
      line-height: 1;
      white-space: nowrap;
    }
    .tech-key__copy:hover { color: var(--teal-500); border-color: var(--glass-border-color); }
    .tech-key__copy[data-copied='1'] { color: var(--teal-500); }

    /* ═══ D12 (§18I.11/§18I.12-K): Unified Run Card + outcome funnel ═══ */
    .run-card {
      display: flex;
      flex-direction: column;
      gap: .35rem;
      padding: .5rem .6rem;
      border: 1px solid var(--surface-border);
      border-radius: .6rem;
      background: rgba(255, 255, 255, 0.03);
      min-width: 0;
      max-width: 100%;
    }
    .run-card__head {
      display: flex;
      align-items: center;
      gap: .35rem;
      flex-wrap: wrap;
      min-width: 0;
    }
    .run-card__title { font-weight: 700; font-size: .8rem; color: var(--text-1); }
    .run-card__facts {
      display: flex;
      align-items: center;
      gap: .75rem;
      flex-wrap: wrap;
      font-size: .72rem;
      color: var(--text-2);
    }
    .run-card__reason { font-size: .72rem; color: #fbbf24; }
    .run-card__stages {
      display: flex;
      flex-direction: column;
      gap: .15rem;
      min-width: 0;
    }
    .run-stage {
      display: grid;
      grid-template-columns: minmax(72px, auto) minmax(48px, 1fr) 3ch auto;
      align-items: center;
      gap: .4rem;
      font-size: .72rem;
      color: var(--text-2);
      min-width: 0;
    }
    .run-stage__label { white-space: nowrap; overflow: hidden;
      text-overflow: ellipsis; }
    .run-stage__bar {
      display: block;
      height: 6px;
      border-radius: 3px;
      background: rgba(255, 255, 255, 0.08);
      overflow: hidden;
      min-width: 48px;
    }
    /* Счётчики без процента (не воронка) — вместо пустого трека разрыв. */
    .run-stage__nobar { display: inline-block; }
    .run-stage__fill {
      display: block;
      height: 100%;
      border-radius: 3px;
      background: var(--teal-500, #2dd4bf);
    }
    .run-stage--warn .run-stage__fill { background: #fbbf24; }
    .run-stage--fail .run-stage__fill { background: #f87171; }
    .run-stage--muted .run-stage__fill { background: #6b7280; }
    .run-stage__value { font-variant-numeric: tabular-nums; text-align: right; }
    .run-stage__arrow { color: var(--text-3); }
    .run-card__foot {
      display: flex;
      align-items: center;
      gap: .5rem;
      flex-wrap: wrap;
      font-size: .66rem;
      color: var(--text-3);
    }
    .run-card__links { display: flex; gap: .6rem; flex-wrap: wrap; }
    /* §18I.12-D: компактный sleep-бейдж — кнопка (клик → детальный виджет);
       активная фаза подсвечивается, но смысл не только цветом (текст). */
    .badge-btn {
      cursor: pointer;
      border: 1px solid transparent;
      background: transparent;
      font: inherit;
      font-size: .66rem;
    }
    .badge-btn:hover { border-color: var(--surface-border); }
    .badge-btn.badge--active { box-shadow: 0 0 0 1px currentColor; }
    @media (prefers-reduced-motion: reduce) {
      .run-card, .run-stage__fill { transition: none; animation: none; }
    }
    .sticky-save__count {
      flex: 1 1 auto;
      min-width: 0;
      font-size: var(--tx-tiny);
      color: var(--text-3);
    }
    /* S10.20-6: провалы сохранения не «благословляются» — красная подсветка. */
    .sticky-save__failed {
      flex: 0 1 auto;
      min-width: 0;
      font-size: var(--tx-tiny);
      color: #f87171;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    /* F0.4 (ревью, T-2435): поле с ошибкой сохранения — подсветка рядом с полем
       (per-field error map), а не только в панели. */
    .is-save-failed {
      border-color: #f87171 !important;
      box-shadow: 0 0 0 1px rgba(248, 113, 113, 0.5);
    }
    .sticky-save__state {
      flex: 0 0 auto;
      font-size: var(--tx-tiny);
      color: var(--text-3);
      opacity: 0.85;
    }
    .sticky-save[data-save-state="error"] .sticky-save__state,
    .sticky-save[data-save-state="conflict"] .sticky-save__state {
      color: #f87171;
    }
    /* F9 (ADR-1025-22 D5): клавиатура. `--kb-offset` (app.js
       `_syncKeyboardOffset`) поднимает модалку над экранной клавиатурой; сам
       offset НЕ складывается с safe-area (§64 D3 — safe-area один раз в
       `.sticky-save`). `scroll-margin-bottom` на панелях/полях — фокус и
       последнее поле не уезжают под клавиатуру/панель. */
    .modal-backdrop {
      padding-bottom: calc(1rem + var(--kb-offset, 0px));
    }
    .field,
    .secret-field__input {
      scroll-margin-bottom: calc(var(--sticky-save-h) + var(--kb-offset, 0px) + 4px);
    }

    /* F9 (ADR-1025-22 D1/D4): единый вид секрет-поля (display-индикатор маски
       + пустой ввод + «Заменить»/«Удалить»). Zero-build, без библиотек. */
    .secret-field { min-width: 0; }
    .secret-field__title { font-size: 0.875rem; font-weight: 600; }
    .secret-field__key {
      font-family: ui-monospace, Consolas, monospace;
      font-size: var(--tx-tiny);
      color: var(--text-3);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .secret-field__desc { font-size: var(--tx-tiny); color: var(--text-3); margin-bottom: .35rem; }
    .secret-field__mask { display: inline-block; margin-bottom: .35rem; }
    .secret-field__row { display: flex; gap: .5rem; align-items: center; }
    .secret-field__input { flex: 1 1 auto; min-width: 0; }
    .secret-field__reveal { flex: 0 0 auto; }
    .secret-field__actions {
      display: flex;
      gap: .5rem;
      flex-wrap: wrap;
      margin-top: .35rem;
    }

    /* T-1897: «Живая лента досье» — бегущая строка (CSS, без библиотек).
       F4 (раунд 10.24, ADR-1024-8 D1): ON-режим — вертикальная лента
       (снизу вверх) с масштабируемой скоростью; OFF-флаг оставляет
       прежнюю горизонталь 42s байт-в-байт. */
    .dossier-ticker-wrap { overflow: hidden; }
    .dossier-ticker {
      position: relative;
      overflow: hidden;
      -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
      mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
    }
    .dossier-ticker__track {
      display: inline-flex;
      align-items: center;
      gap: 1.5rem;
      white-space: nowrap;
      will-change: transform;
      animation: dossier-ticker-scroll 42s linear infinite;
    }
    .dossier-ticker__item {
      display: inline-flex;
      align-items: center;
      gap: .4rem;
      font-size: var(--tx-small);
      color: var(--text-2);
    }
    .dossier-ticker__dot { color: var(--teal-500); font-size: 10px; }
    .dossier-ticker:hover .dossier-ticker__track { animation-play-state: paused; }
    @keyframes dossier-ticker-scroll {
      from { transform: translateX(0); }
      to   { transform: translateX(-50%); }
    }

    /* F4 (10.24, ADR-1024-8 D1): вертикальная лента «снизу вверх».
       * фиксированная высота контейнера обязательна (иначе клиппинг/цикл
       не работают), ≤ 40vh на низких экранах;
       * 180deg-маска вместо 90deg;
       * дорожка дублируется (см. dossierFeedLoop), поэтому бесшовный цикл =
       translateY(-50% - gap/2): полкопии мимо окна (gap между flex-копиями);
       * скорость --dossier-speed = max(72s, items×6s), hover/focus — пауза. */
    .dossier-ticker--y {
      --dossier-h: 180px;
      --dossier-gap: .5rem;
      height: min(var(--dossier-h), 40vh);
      -webkit-mask-image: linear-gradient(180deg, transparent, #000 12%, #000 88%, transparent);
      mask-image: linear-gradient(180deg, transparent, #000 12%, #000 88%, transparent);
    }
    .dossier-ticker__track--y {
      display: flex;
      flex-direction: column;
      align-items: stretch;
      gap: var(--dossier-gap);
      white-space: normal;
      will-change: transform;
      animation: dossier-ticker-scroll-y var(--dossier-speed, 72s) linear infinite;
    }
    .dossier-ticker__track--y .dossier-ticker__item {
      display: flex;
      align-items: baseline;
      gap: .4rem;
      font-size: var(--tx-small);
      color: var(--text-2);
      padding: .35rem .5rem;
      border-radius: 8px;
      transition: background var(--dur-fast) var(--ease-out);
    }
    .dossier-ticker__item--click { cursor: pointer; }
    .dossier-ticker__item--click:hover {
      background: rgba(255, 255, 255, .06);
    }
    .dossier-ticker__item--click:focus-visible {
      background: rgba(255, 255, 255, .06);
      outline: none;
      box-shadow: 0 0 0 2px var(--teal-500) inset;
    }
    .dossier-ticker--y:hover .dossier-ticker__track--y,
    .dossier-ticker--y:focus-within .dossier-ticker__track--y {
      animation-play-state: paused;
    }
    @keyframes dossier-ticker-scroll-y {
      from { transform: translateY(0); }
      /* Сдвиг = ровно одна копия + половина межкопийного gap (бесшовный
         цикл). gap берём из переменной — смена --dossier-gap не сломает стык. */
      to   { transform: translateY(calc(-50% - (var(--dossier-gap) / 2))); }
    }

    /* T-1896: карточка авто-досье — плотная подложка для читаемости. */
    .dossier-auto {
      background: rgba(0, 0, 0, 0.24);
      border: var(--glass-border);
      white-space: pre-wrap;
      word-break: break-word;
      font-family: var(--font-body);
    }

    /* T-1902: рестайлинг существующего Advanced-аккордеона (<details>).
       Состав групп НЕ меняется — только оформление полосы раскрытия. */
    details.advanced {
      border: var(--glass-border);
      border-radius: var(--radius-lg);
      background: var(--glass-bg);
      -webkit-backdrop-filter: var(--glass-blur);
      backdrop-filter: var(--glass-blur);
      overflow: hidden;
    }
    details.advanced > summary {
      display: flex;
      align-items: center;
      gap: .5rem;
      padding: .6rem .85rem;
      list-style: none;
      cursor: pointer;
      transition: background var(--dur-fast) var(--ease-out);
    }
    details.advanced > summary::-webkit-details-marker { display: none; }
    details.advanced > summary::before {
      content: '▶';
      display: inline-block;
      font-size: 10px;
      color: var(--teal-500);
      transition: transform var(--dur-normal) var(--ease-out);
    }
    details.advanced[open] > summary::before { transform: rotate(90deg); }
    details.advanced > summary:hover { background: rgba(255, 255, 255, .05); }
    details.advanced > summary .advanced-gear {
      margin-left: auto;
      color: var(--text-3);
      font-size: 18px;
    }
    details.advanced[open] > summary .advanced-gear { color: var(--teal-500); }

    @media (prefers-reduced-motion: reduce) {
      .dossier-ticker__track { animation: none !important; }
      .dossier-ticker {
        -webkit-mask-image: none !important; mask-image: none !important;
      }
      /* F4 (10.24): вертикальная лента без анимации — обычный прокручиваемый
         список (mask снят выше, высота по контенту с разумным потолком).
         Клон-дубль (нужный только для анимации) скрываем — иначе факты
         дублируются в списке (review iter1). */
      .dossier-ticker--y {
        height: auto;
        max-height: var(--dossier-h);
        overflow-y: auto;
      }
      .dossier-ticker__item--dup { display: none !important; }
      details.advanced > summary::before { transition: none !important; }
    }
  

    /* ═══ F3 (раунд 10.24, ADR-1024-7): визуальное дерево вызова (Node Flow) ═══
       Чистый CSS Flexbox: узлы + тонкие коннекторы, без граф-библиотек и CDN
       (инвариант CSP/zero-build). Источник — computed tokenFlowTree (web/app.js). */
    .token-flow {
      display: flex;
      flex-direction: column;
      gap: 0;
    }
    .token-flow__node {
      position: relative;
      border: 1px solid var(--surface-border, rgba(255, 255, 255, .12));
      border-radius: var(--radius-lg, .6rem);
      background: rgba(255, 255, 255, .04);
      padding: .4rem .6rem;
    }
    .token-flow__node--root {
      border-color: rgba(148, 163, 184, .45);
      background: rgba(148, 163, 184, .08);
    }
    .token-flow__node--synthesizer,
    .token-flow__node--verbalizer {
      border-color: rgba(110, 168, 254, .55);
      background: rgba(110, 168, 254, .08);
    }
    .token-flow__node--result {
      border-color: rgba(74, 222, 128, .55);
      background: rgba(74, 222, 128, .08);
    }
    .token-flow__node--tool {
      border-color: rgba(250, 204, 21, .5);
      background: rgba(250, 204, 21, .07);
      border-left-width: 3px;
    }
    /* Ветка: отдельный контейнер под родителем (Синтезатором); tool-под-ноды
       NOT на спине. Рельс + горизонтальный ус — CSS-псевдоэлементы. */
    .token-flow__branch {
      position: relative;
      display: flex;
      flex-direction: column;
      gap: .3rem;
      margin: .2rem 0 .2rem 1.25rem;
    }
    .token-flow__branch::before {
      content: '';
      position: absolute;
      left: -.75rem;
      top: -.2rem;
      bottom: 50%;
      width: 2px;
      background: rgba(250, 204, 21, .45);
    }
    .token-flow__branch::after {
      content: '';
      position: absolute;
      left: -.75rem;
      top: 50%;
      width: .6rem;
      height: 2px;
      background: rgba(250, 204, 21, .45);
    }
    .token-flow__head {
      font-size: .78rem;
      font-weight: 700;
      color: var(--text-1, #e5e7eb);
    }
    .token-flow__note {
      font-size: .68rem;
      color: var(--text-3, #9ca3af);
      margin-top: .1rem;
    }
    .token-flow__metrics {
      display: flex;
      flex-wrap: wrap;
      gap: .3rem .75rem;
      margin-top: .25rem;
      font-size: .72rem;
      color: var(--text-2, #cbd5e1);
    }
    .token-flow__metric { white-space: nowrap; }
    .token-flow__edge {
      text-align: center;
      color: rgba(110, 168, 254, .75);
      font-size: .62rem;
      line-height: 1.1;
    }
    /* узкая TMA: вертикальный стек, отступ ветки убираем, порядок сохраняется */
    @media (max-width: 420px) {
      .token-flow__branch { margin-left: 0; }
      .token-flow__branch::before,
      .token-flow__branch::after { display: none; }
    }
    @media (prefers-reduced-motion: reduce) {
      .token-flow__node { transition: none !important; }
    }
    /* ═══ F6 round1025 (ADR-1025-19 D1/D3): adapter-узлы ExecutionGraph ═══
       Аддитивное расширение .token-flow*: kind-enum llm/algorithm/tool/format/
       publish/other + stage-модификаторы. Рендер — тот же единственный
       компонент (§116, вторая визуализация не создаётся). */
    .token-flow__node--llm {
      border-color: rgba(110, 168, 254, .55);
      background: rgba(110, 168, 254, .08);
    }
    .token-flow__node--algorithm,
    .token-flow__node--format,
    .token-flow__node--publish {
      border-color: rgba(167, 139, 250, .5);
      background: rgba(167, 139, 250, .07);
    }
    .token-flow__node--other {
      border-color: rgba(148, 163, 184, .45);
      background: rgba(148, 163, 184, .06);
    }
    .token-flow__node[role="button"] { cursor: pointer; }
    .token-flow__node[role="button"]:focus-visible {
      outline: 2px solid rgba(110, 168, 254, .8);
      outline-offset: 1px;
    }
    /* ═══ S8 round1026 (ADR-1026-10 D6/§29): mobile-карта вызовов ═══
       Конкретный вызов — вертикальная последовательность этапов (flex-column
       выше); граф не сжимается до 320px, числовые значения переносятся и
       доступны без pinch-zoom. Только аддитивные правила — рендер F6 не
       переписывается (§111/§30). */
    .token-flow { min-width: 0; }
    .token-flow__metrics { overflow-wrap: anywhere; }
    @media (max-width: 360px) {
      .token-flow__node { min-width: 0; }
      .token-flow__metric { white-space: normal; }
    }

    /* §27: детали узла — desktop side-panel справа. */
    /* L-F6S-4: подложка (клик закрывает) + aria-modal на панели. */
    .exec-detail-backdrop {
      position: fixed;
      inset: 0;
      z-index: 59;
      background: rgba(0, 0, 0, .35);
    }
    .exec-detail {
      position: fixed;
      top: 0;
      right: 0;
      bottom: 0;
      width: min(360px, 92vw);
      z-index: 60;
      padding: .75rem .9rem;
      overflow-y: auto;
      background: var(--surface-1, rgba(17, 24, 39, .97));
      border-left: 1px solid var(--surface-border, rgba(255, 255, 255, .12));
      box-shadow: -8px 0 24px rgba(0, 0, 0, .35);
    }
    .exec-detail__head {
      display: flex;
      align-items: center;
      gap: .35rem;
      margin-bottom: .5rem;
    }
    .exec-detail__row {
      display: flex;
      justify-content: space-between;
      gap: .75rem;
      padding: .2rem 0;
      border-bottom: 1px solid rgba(255, 255, 255, .06);
    }
    .exec-preview { min-width: 0; }

    /* §29 mobile: граф/детали — вертикально, без сжатия до 320 px.
       Детали превращаются в bottom-sheet. */
    @media (max-width: 767px) {
      .exec-detail {
        top: auto;
        left: 0;
        right: 0;
        bottom: 0;
        width: auto;
        max-height: 72vh;
        border-left: none;
        border-top: 1px solid var(--surface-border, rgba(255, 255, 255, .12));
        border-radius: var(--radius-lg, .6rem) var(--radius-lg, .6rem) 0 0;
        box-shadow: 0 -8px 24px rgba(0, 0, 0, .4);
      }
    }

    /* ═══════════════════════════════════════════════════════════════════
       F1 round 10.25 (ADR-1025-1 D6/D7): раздельные app shell’ы.
       Диапазоны §70: <768 mobile · 768–991 tablet · 992–1199 compact ·
       ≥1200 desktop (постоянный sidebar СТРОГО с 1200 px).
       ═══════════════════════════════════════════════════════════════════ */
    .header-title-wrap { min-width: 0; flex: 1 1 auto; }

    /* ── Breadcrumb (UPD §8.4): текущий раздел + путь назад ── */
    .breadcrumb {
      display: flex; align-items: center; gap: .3rem; flex-wrap: wrap;
      font-size: .68rem; color: var(--text-3);
    }
    .breadcrumb-link {
      background: transparent; border: none; padding: 0; cursor: pointer;
      color: var(--text-2); font-size: .68rem; text-decoration: underline;
      text-underline-offset: 2px;
    }
    .breadcrumb-link:hover { color: var(--text-1); }
    .breadcrumb-sep { opacity: .5; }
    .breadcrumb-current { color: var(--text-1); font-weight: 600; }

    /* ── Общие элементы shell-навигации ── */
    .sidebar-nav { display: flex; flex-direction: column; gap: .15rem; }
    .sidebar-link, .app-drawer .sidebar-link {
      display: flex; align-items: center; gap: .6rem;
      min-height: 44px; padding: .5rem .65rem;
      background: transparent; border: 1px solid transparent; border-radius: .6rem;
      color: var(--text-2); cursor: pointer; text-align: left;
      font-size: .85rem; width: 100%;
    }
    .sidebar-link:hover {
      background: rgba(255,255,255,.06); color: var(--text-1);
    }
    .sidebar-link.active {
      background: var(--surface-3); color: var(--text-1); font-weight: 600;
      border-color: var(--surface-border);
    }
    .sidebar-link.active .msr,
    .mobile-topnav-link.active .msr { font-variation-settings: 'FILL' 1; }
    .sidebar-label { min-width: 0; overflow: hidden; text-overflow: ellipsis;
      white-space: nowrap; }
    .sidebar-sep { height: 1px; margin: .35rem .15rem;
      background: var(--surface-border); }
    .sidebar-brand {
      display: flex; align-items: center; gap: .5rem;
      padding: .75rem .5rem; font-weight: 700; color: var(--text-1);
    }
    .sidebar-brand .msr { color: var(--teal-500); }
    .sidebar-brand-title { font-size: .95rem; letter-spacing: .01em; }

    /* Desktop sidebar (≥1200): фикс. панель 216 px (§4: 208–224), sticky-контент. */
    .app-sidebar { display: none; }
    @media (min-width: 1200px) {
      .app-shell.ia-v2 { padding-left: 216px; }
      .app-shell.ia-v2 .app-sidebar {
        display: flex; flex-direction: column;
        position: fixed; top: 0; left: 0; bottom: 0; width: 216px;
        padding: .5rem .5rem calc(.5rem + max(env(safe-area-inset-bottom, 0px), var(--tg-safe-area-inset-bottom, 0px), var(--tg-content-safe-area-inset-bottom, 0px)));
        /* HOTFIX8 (ADR-1025-16 D2/D4): shell-панель — §4 base + backdrop blur +
           мягкая внутренняя подсветка + subtle specular/текстура; тон/глубина
           отличны от карточек; радиус 0 (стык к main content). */
        background-color: var(--shell-bg);
        background-image: var(--shell-specular);
        border-right: var(--shell-border);
        border-radius: 0;
        box-shadow: var(--shell-shadow),
                    inset 0 1px 0 var(--shell-highlight),
                    inset 0 -1px 0 var(--shell-highlight-soft);
        -webkit-backdrop-filter: var(--shell-blur);
        backdrop-filter: var(--shell-blur);
        overflow-y: auto; z-index: 30;
      }
      /* header ≈64 px (§6) */
      .app-shell.ia-v2 header.main-header { min-height: 64px; }
      /* HOTFIX10 (ADR-1025-18 D2, T-2852): единая рабочая поверхность Main.
         `max-width:1440px; margin-inline:auto` сняты — контент более не
         центрируется внутри широкой области, поэтому между sidebar (x=216) и
         рабочей областью НЕТ яркой вертикальной полосы. Подложка — на самой
         `main.scroll-area` (начинается ровно за sidebar, тянется до правого
         края), а не на `.app-shell`: canvas не обрезается. Лимит карточек
         1100px сохранён на `.module-list`/`.module-quick-wrap`/`.module-toolbar`. */
      .app-shell.ia-v2 main.scroll-area {
        width: 100%; max-width: none; margin-inline: 0;
        background: var(--work-surface-bg);
      }
      .app-shell.ia-v2 .app-drawer,
      .app-shell.ia-v2 .drawer-backdrop { display: none !important; }
    }

    /* Drawer (768–1199): без постоянного sidebar — временная панель. */
    .app-drawer {
      position: fixed; top: 0; left: 0; bottom: 0; width: min(280px, 84vw);
      padding: .75rem .5rem calc(.75rem + max(env(safe-area-inset-bottom, 0px), var(--tg-safe-area-inset-bottom, 0px), var(--tg-content-safe-area-inset-bottom, 0px)));
      /* HOTFIX8 (ADR-1025-16 D2/D4): drawer — тот же §4 shell-слой, что
         sidebar/bottom-nav; скруглён с внутренней стороны (18 px). */
      background-color: var(--shell-bg);
      background-image: var(--shell-specular);
      border-right: var(--shell-border);
      border-radius: 0 18px 18px 0;
      box-shadow: var(--shell-shadow),
                  inset 0 1px 0 var(--shell-highlight),
                  inset 0 -1px 0 var(--shell-highlight-soft);
      -webkit-backdrop-filter: var(--shell-blur);
      backdrop-filter: var(--shell-blur);
      transform: translateX(-105%); transition: transform .2s ease;
      overflow-y: auto; z-index: 40;
    }
    .app-drawer.open { transform: translateX(0); }
    .drawer-backdrop {
      position: fixed; inset: 0; background: rgba(0,0,0,.55); z-index: 35;
    }

    /* Bottom-nav (<768): ≤4 пункта, тач ≥44×44.
       HOTFIX9 (ADR-1025-17 D1/D2, T-2798/T-2800): панель — ПОСЛЕДНИЙ flex-child
       колонки, НЕ отдельный fixed-слой. Нижний safe-area учтён РОВНО ОДИН РАЗ —
       теперь (ASAP-3.1, T-4083, §93) на САМОЙ панели как flex-child:
       shell = фактически видимая высота (без guessed-offset), панель поднимает
       labels над системной зоной собственным padding-bottom. Инварианты §94:
       rect.top ≥ 0; rect.bottom ≤ visible bottom; icon/label видны; main
       (flex-1) структурно не под nav. */
    /* ═══ W2-SHELL (asap8-v6.3, U01.1/U01.3): мобильная row B (<768) —
       ровно 4 сегмента «Статус / Аналитика / Модули / Ещё ▾», равные/
       пропорциональные доли ширины, БЕЗ горизонтальной прокрутки и БЕЗ
       третьей строки. bottom-nav НЕ возвращается. Высота сегмента ~44px. ═══ */
    .mobile-topnav {
      flex: 0 0 auto; width: 100%;
      display: flex; align-items: stretch; gap: .2rem;
      padding: .05rem 0 .15rem;
      min-width: 0;
    }
    .mobile-topnav-link {
      flex: 1 1 0; min-width: 44px; min-height: 44px;
      display: flex; flex-direction: column; align-items: center;
      justify-content: center; gap: 1px; padding: .25rem .25rem;
      background: transparent; border: none; cursor: pointer;
      color: var(--text-2); font-size: .625rem; border-radius: .5rem;
      white-space: nowrap; overflow: hidden;
    }
    .mobile-topnav-link.active { color: var(--text-1); font-weight: 600;
      background: rgba(255, 255, 255, 0.07); }
    .mobile-topnav-link .msr { font-size: 20px; line-height: 1; }
    .mobile-topnav-label { font-size: .625rem; line-height: 1.05;
      max-width: 100%; overflow: hidden; text-overflow: ellipsis;
      white-space: nowrap; }
    /* U01.1: триггер «Ещё» — активный раздел из меню отражается подписью
       «Ещё • …» (ellipsis по доступной ширине). */
    .mobile-topnav-more { font-weight: 500; }
    /* Ландшафт/низкое окно: row B компактнее — контент остаётся большинством
       экрана (§18I.14: no three simultaneous fixed bars). */
    @media (orientation: landscape) and (max-height: 500px) {
      .mobile-topnav-link { min-height: 32px; padding: .1rem .45rem; }
      .mobile-topnav-link .msr { font-size: 16px; }
      .mobile-topnav-label { font-size: .5625rem; }
    }
    @media (prefers-reduced-motion: reduce) {
      .mobile-topnav { scroll-behavior: auto; }
    }
    /* ═══ D13 (§18I.14): нижняя навигация удалена — компенсация 72px
       (scroll-padding-bottom под bottom-nav) больше не нужна. ═══ */
    /* HOTFIX9 D1 (T-2801): навигация в потоке flex-колонки — отдельный
       padding-bottom компенсации больше НЕ нужен (контент не прячется за
       панелью структурно). Оставлен только базовый паддинг `.scroll-area`. */
    .app-shell.ia-v2.shell-mobile main.scroll-area,
    .app-shell.ia-v2.shell-mobile .scroll-area {
      padding-bottom: 1rem;
    }
    /* §70: на узких mobile — одна колонка без min-width-треков (иначе
       inline `minmax(320px,1fr)` даёт горизонтальный скролл на 320 px).
       ASAP 4.3 (§10.2, T-4850): `1fr` = `minmax(auto,1fr)` с min-content
       полом — широкий контент (Save area) выталкивал трек за вьюпорт и
       `Сохранить изменения` обрезался справа. Структурно: `minmax(0,1fr)`
       (как tailwind `grid-cols-*`), контент обёртывается, а не режется. */
    @media (max-width: 767px) {
      .app-shell.ia-v2 main.scroll-area {
        grid-template-columns: minmax(0, 1fr) !important;
        width: 100%; max-width: 100%;
        padding-left: .5rem; padding-right: .5rem;
      }
      .app-shell.ia-v2 .hub-grid,
      .app-shell.ia-v2 .module-list { grid-template-columns: 1fr; }
      /* P0 Vision (P0V-UI-OVERFLOW): формы провайдеров — без min-content
         пола. `1fr` = `minmax(auto,1fr)`: min-content строки (rem-подпись
         `w-36` + intrinsic <input>) раздувал трек за контейнер при крупном
         системном шрифте Android — тот же класс дефекта, что у
         `main.scroll-area` выше, поэтому то же структурное лечение
         `minmax(0,1fr)`. Остальные grid'ы — прежние. */
      .app-shell.ia-v2 .prov-grid {
        grid-template-columns: minmax(0, 1fr);
      }
      .app-shell.ia-v2 .modal-card { max-width: 100%; }
    }

    /* ═══ D13 (§18I.14): шторка «Ещё» удалена вместе с bottom-nav. ═══ */

    /* Container queries (§70): раскладки, зависящие от ширины КОМПОНЕНТА
       (container-type задан в базовых правилах .module-list/.hub-grid). */
    @container (max-width: 359px) {
      /* F4 §33: карточка модуля уже вертикальная (см. .module-card);
         растягиваем детей по ширине, чтобы верхняя строка не сжималась. */
      .module-card { flex-direction: column; align-items: stretch; }
    }
    @container (max-width: 420px) {
      .hub-card { width: 100%; }
    }
    .navbar-band { max-width: 100%; }
    @media (prefers-reduced-motion: reduce) {
      .app-drawer { transition: none; }
    }

    /* ── T-2400 «Справка»: desktop оглавление+контент, mobile стек ── */
    .help-layout { display: grid; gap: 1rem; grid-template-columns: 1fr;
      width: 100%; max-width: 100%; }
    .help-toc-list { display: flex; flex-direction: column; gap: .1rem;
      max-height: 60vh; overflow-y: auto; }
    .help-toc-link {
      display: block; width: 100%; text-align: left; min-height: 32px;
      background: transparent; border: none; cursor: pointer;
      color: var(--text-2); font-size: .78rem; padding: .25rem .3rem;
      border-radius: .4rem; overflow: hidden; text-overflow: ellipsis;
      white-space: nowrap;
    }
    .help-toc-link:hover { background: rgba(255,255,255,.06); color: var(--text-1); }
    .help-toc-link.lvl-2 { padding-left: .9rem; }
    .help-toc-link.lvl-3 { padding-left: 1.5rem; font-size: .72rem; }
    /* Reviewer (L): touch-цель ≥44×44 на mobile. */
    @media (max-width: 767px) {
      .help-toc-link { min-height: 44px; display: flex; align-items: center;
        padding-top: .5rem; padding-bottom: .5rem; }
    }
    .help-content { min-width: 0; display: flex; flex-direction: column; }
    @media (min-width: 768px) {
      .help-layout { grid-template-columns: 240px minmax(0, 1fr); }
      .help-toc { position: sticky; top: .75rem; align-self: start; }
    }
    /* Якорные заголовки: не уезжают под sticky-header при переходе. */
    .info-html h1, .info-html h2, .info-html h3,
    .guide-markdown h1, .guide-markdown h2, .guide-markdown h3 {
      scroll-margin-top: 4.5rem;
    }

    /* ── T-2401 «Доступы»: mobile — последовательный редактор (без
       горизонтального скролла). Desktop-матрица не меняется. ── */
    @media (max-width: 767px) {
      .matrix-table thead { display: none; }
      .matrix-table, .matrix-table tbody,
      .matrix-table tr, .matrix-table td { display: block; width: 100%; }
      .matrix-table tr {
        border: 1px solid var(--surface-border); border-radius: .6rem;
        padding: .5rem .6rem; margin-bottom: .5rem;
      }
      .matrix-table td { border: none; padding: .2rem 0; }
      .matrix-table td[data-label]::before {
        content: attr(data-label); display: block;
        color: var(--text-3); font-size: .68rem; margin-bottom: .1rem;
      }
      .matrix-table td:last-child { padding-top: .4rem; }
    }

    /* ═══ F4 (10.25, ADR-1025-14 §32–§45): каталог/панель/поиск/фильтры ═══ */
    /* §32/D7: изолированные правила каталога — колонок ≤3 при ЛЮБОЙ ширине
       (устраняет возможность >3 из-за auto-fit). Тиры — по ширине
       контейнера-обёртки. Общие .prov-grid/.hub-grid не изменяются. */
    .module-catalog {
      grid-column: 1 / -1; width: 100%; container-type: inline-size;
    }
    .module-catalog .module-list {
      grid-column: auto; max-width: 1100px; margin-inline: auto;
    }
    @container (max-width: 1023px) {
      .module-catalog .module-list {
        grid-template-columns: repeat(2, minmax(0, 1fr));
      }
    }
    @container (max-width: 479px) {
      .module-catalog .module-list {
        grid-template-columns: repeat(1, minmax(0, 1fr));
      }
    }

    /* §45: общие индикаторы (Всего / Включено / Выключено / Есть проблемы). */
    .module-counters {
      display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .5rem;
    }
    .module-counter {
      display: inline-flex; align-items: baseline; gap: .25rem;
      padding: .15rem .55rem; border-radius: var(--radius-full);
      background: rgba(255,255,255,.05);
      border: 1px solid var(--surface-border);
      color: var(--text-2); font-size: var(--tx-small); white-space: nowrap;
    }
    .module-counter b { color: var(--text-1); font-size: var(--tx-med); }
    .module-counter--on b { color: var(--teal-500); }
    .module-counter--off b { color: var(--text-3); }
    .module-counter--issue b { color: var(--warn); }

    /* §34–§35: панель быстрого управления (≤4/2/2–1). */
    .module-quick-wrap {
      grid-column: 1 / -1; width: 100%; max-width: 1100px;
      justify-self: center; container-type: inline-size;
    }
    .module-quick-head {
      display: flex; align-items: center; gap: .5rem; margin-bottom: .4rem;
    }
    .module-quick {
      display: grid; gap: .5rem;
      grid-template-columns: repeat(4, minmax(0, 1fr));
    }
    @container (max-width: 1023px) {
      .module-quick { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    }
    @container (max-width: 359px) {
      .module-quick { grid-template-columns: repeat(1, minmax(0, 1fr)); }
    }
    .module-quick-item {
      display: flex; align-items: center; gap: .5rem; min-width: 0;
      padding: .5rem .6rem;
    }
    .module-quick-item .module-icon {
      color: var(--teal-500); font-size: 20px; flex-shrink: 0;
    }
    .module-quick-meta { flex: 1 1 auto; min-width: 0; }
    .module-quick-meta .module-title {
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }

    /* §32/§44: поиск + фильтры (представление, ноль мутаций). */
    .module-toolbar {
      grid-column: 1 / -1; width: 100%; max-width: 1100px;
      justify-self: center; display: flex; flex-wrap: wrap;
      gap: .5rem; align-items: center;
    }
    .module-search { flex: 1 1 200px; min-width: 0; }
    .module-filters { display: flex; flex-wrap: wrap; gap: .25rem; }
    .module-filter-btn {
      min-height: 32px; padding: .25rem .6rem;
      border-radius: var(--radius-full);
      background: transparent; border: 1px solid var(--surface-border);
      color: var(--text-2); font-size: var(--tx-small);
      cursor: pointer; white-space: nowrap;
    }
    .module-filter-btn:hover {
      background: rgba(255,255,255,.06); color: var(--text-1);
    }
    .module-filter-btn.active {
      background: var(--surface-3); color: var(--text-1); font-weight: 600;
    }

    /* §33: «карточка ≠ тумблер»; «Настроить» — отдельное действие. */
    .module-card { cursor: default; }
    .module-state { color: var(--text-2); }
    .module-source { color: var(--text-3); }
    .module-problem { color: var(--warn); }
    .module-error { color: var(--err); }
    .module-card-actions {
      display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
    }
    .module-card-actions .module-params-btn { margin-left: auto; }
    .module-empty {
      padding: 1rem; color: var(--text-3); text-align: center;
    }

    /* §33/T-2625: тач-цель тумблера ≥44×44 CSS px (визуальный трек не
       растёт; растёт hit-area метки). Без уменьшения ради 4 колонок §35. */
    .module-toggle {
      min-width: 44px; min-height: 44px; justify-content: flex-end;
      position: relative;
    }
    .module-toggle.is-saving { opacity: .7; }
    .module-toggle.is-saving::after {
      content: ''; position: absolute; right: -4px; top: 50%;
      width: 12px; height: 12px; margin-top: -6px; border-radius: 50%;
      border: 2px solid rgba(255,255,255,.25);
      border-top-color: var(--teal-500);
      animation: module-spin .7s linear infinite;
    }
    @keyframes module-spin { to { transform: rotate(360deg); } }
    @media (prefers-reduced-motion: reduce) {
      .module-toggle.is-saving::after { animation: none; }
    }
    .module-pin-btn { white-space: nowrap; }
    /* Тач-цели фильтров — ≥44×44 на mobile. */
    @media (max-width: 767px) {
      .module-filter-btn { min-height: 44px; }
    }

    /* ═══ F5 (ADR-1025-15 D3/§48): master-detail библиотеки промптов ═══
       desktop: дерево | редактор | описание+параметры; mobile (<768):
       список → полноэкранный редактор; без горизонтального скролла. */
    .workspace-prompt-lib {
      display: grid; gap: 12px;
      grid-template-columns: 220px minmax(0, 1fr) 260px;
      align-items: start;
    }
    .prompt-tree { max-height: 60vh; overflow: auto; }
    .prompt-tree-item {
      display: block; padding: 6px 8px; border-radius: 8px;
      color: var(--text-2, #AAB6C8); background: transparent;
      border: 1px solid transparent; cursor: pointer; font-size: .8rem;
    }
    .prompt-tree-item:hover { background: rgba(255,255,255,.05); }
    .prompt-tree-item.is-active {
      background: rgba(139,92,246,.18); border-color: rgba(139,92,246,.5);
      color: var(--text-1, #F4F7FB);
    }
    .prompt-editor textarea { width: 100%; }
    @media (max-width: 1023px) {
      .workspace-prompt-lib { grid-template-columns: 200px minmax(0, 1fr); }
      .prompt-meta { display: none; }
    }
    @media (max-width: 767px) {
      .workspace-prompt-lib { grid-template-columns: minmax(0, 1fr); }
      .workspace-prompt-lib .prompt-meta { display: none; }
      .workspace-prompt-lib .prompt-editor { display: none; }
      /* ASAP-2.1 (T-3982): is-editing навешивается ТОЛЬКО на валидный фокус
         (workspacePromptFocus), поэтому stale-ключ дерево не скрывает. */
      .workspace-prompt-lib.is-editing .prompt-tree { display: none; }
      .workspace-prompt-lib.is-editing .prompt-editor { display: block; }
      .prompt-tree { max-height: none; }
      .prompt-tree-item { min-height: 44px; }
      /* T-3982: явный back «editor → список» — тач-цель ≥44px. */
      .prompt-back-btn { min-height: 44px; }
      [data-workspace-tabs] button { min-height: 44px; }
      .workspace-head .prov-test-btn,
      .direct-stage-card .prov-test-btn { min-height: 44px; }
    }

    /* ═══ F5 (ADR-1025-15 D4/§49, T-2714): карточка подключения ═══
       название / назначение / основная модель / резервная модель / статус
       + «Проверить» / «Настроить». Без горизонтального скролла; длинные
       значения моделей переносятся, тач-цели ≥44×44 на mobile. */
    .conn-card { min-width: 0; }
    .conn-facts { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
    /* flex-wrap: длинное значение уходит на свою строку, короткие факты
       остаются в одну строку (P0 Vision D12: причина проверки — длинный
       текст даже на телефоне). */
    .conn-fact { display: flex; flex-wrap: wrap; gap: 6px; min-width: 0; overflow-wrap: anywhere; }
    .conn-fact-label { flex: 0 0 auto; color: var(--text-3, #8A94A6); }
    /* P0 Vision (D12): значение факта — отдельный flex-item с min-width:0:
       длинный текст причины переносится с левого края своей колонки, а не
       сжимается анонимным flex-item'ом. База 14em: если после подписи
       остаётся уже — значение уходит на свою строку (узкий Android). */
    .conn-fact-value { flex: 1 1 14em; min-width: 0; }
    .conn-settings { border-top: 1px solid rgba(255, 255, 255, .08); }
    @media (max-width: 767px) {
      [data-conn-test],
      [data-conn-configure],
      [data-connection-settings] button { min-height: 44px; }
    }
    /* Тач-цели workspace (табы/карточки) — ≥44×44 на всех ширинах §70:
       это управляющие кнопки, размер выровнен независимо от вьюпорта. */
    [data-workspace-tabs] button,
    [data-conn-test],
    [data-conn-configure],
    [data-connection-settings] button { min-height: 44px; }


    /* ── ASAP-3.2 (ADR-1028-5 D14, ТЗ §106–§114): Cover Styles editor —
       dedicated full-screen surface. Кастомные классы вместо отсутствующих
       в прекомпилированном tailwind утилит (zero-build, CSP). */
    .cover-overlay {
      position: fixed;
      inset: 0;
      background: rgba(0, 0, 0, 0.7);
      z-index: 50;
      display: flex;
      align-items: stretch;
      justify-content: center;
    }
    @media (min-width: 640px) {
      .cover-overlay { align-items: center; padding: 1.5rem 1rem; }
    }
    .cover-editor {
      background: #111827;
      width: 100%;
      max-width: 100%;
      min-width: 0;
      display: flex;
      flex-direction: column;
      overflow: hidden;
    }
    /* ASAP 4.3 (§10.3, T-4851): header/footer — несжимаемые части layout;
       body — ЕДИНСТВЕННЫЙ скроллер (`min-height:0` иначе flex-item не
       скроллится и весь редактор уезжает). */
    .cover-editor-head { flex: 0 0 auto; max-width: 100%; min-width: 0; }
    .cover-editor-body {
      flex: 1 1 auto;
      min-height: 0;
      overflow-y: auto;
      overflow-x: hidden;
      overscroll-behavior: contain;
    }
    .cover-editor-foot {
      flex: 0 0 auto;
      max-width: 100%;
      /* safe-area ровно один раз (та же формула, что у shell/nav). */
      padding-bottom: calc(0.75rem + max(
        env(safe-area-inset-bottom, 0px),
        var(--tg-safe-area-inset-bottom, 0px),
        var(--tg-content-safe-area-inset-bottom, 0px)));
    }
    @media (max-width: 639.98px) {
      .cover-editor { height: 100%; }
    }
    @media (min-width: 640px) {
      .cover-editor {
        max-width: 60rem;
        max-height: calc(100vh - 3rem);
        border-radius: 1rem;
      }
    }
    .cover-menu {
      position: absolute;
      right: 0;
      margin-top: 0.25rem;
      z-index: 10;
      display: flex;
      flex-direction: column;
      gap: 0.25rem;
      border-radius: 0.5rem;
      border: 1px solid rgba(255, 255, 255, 0.1);
      background: #111827;
      padding: 0.5rem;
      min-width: 9rem;
    }
    .cover-preview {
      width: 100%;
      max-width: 11rem;
      max-height: 11rem;
      aspect-ratio: 1 / 1;
      object-fit: cover;
      border-radius: 0.75rem;
      min-width: 0;
    }
    .cover-preview-empty {
      width: 100%;
      max-width: 11rem;
      max-height: 11rem;
      aspect-ratio: 1 / 1;
      border-radius: 0.75rem;
      background: rgba(255, 255, 255, 0.05);
      display: flex;
      align-items: center;
      justify-content: center;
      color: rgba(156, 163, 175, 1);
      font-size: 0.75rem;
    }
    /* ASAP 4.3 (§10.4, T-4852): `До → После` — одна горизонтальная группа,
       картинки масштабируются от доступной ширины (не vertical wall). */
    .cover-preview-group {
      display: flex;
      align-items: flex-end;
      gap: 0.5rem;
      flex-wrap: nowrap;
      max-width: 100%;
      min-width: 0;
    }
    .cover-preview-group > div { min-width: 0; }
    @media (max-width: 639.98px) {
      .cover-preview, .cover-preview-empty {
        max-width: 6.5rem;
        max-height: 8.5rem;
      }
    }
    .cover-preview-arrow { color: rgba(156, 163, 175, 1); font-size: 1.4rem; }
    /* ASAP 4.2 (D5.4, T-4826): компактные before/after mini в списке стилей
       (НЕ giant image wall). Стрелка — Material Symbol `.msr`. */
    .cover-card-previews { width: 5.75rem; }
    .cover-mini {
      width: 2.25rem;
      height: 2.25rem;
      object-fit: cover;
      border-radius: 0.4rem;
      flex: none;
    }
    .cover-mini--empty {
      display: flex;
      align-items: center;
      justify-content: center;
      background: rgba(255, 255, 255, 0.05);
      color: rgba(156, 163, 175, 1);
      font-size: 0.85rem;
    }
    .cover-mini-arrow {
      color: rgba(156, 163, 175, 1);
      font-size: 1rem;
      flex: none;
    }

    /* ═══ ASAP-4 волна E (§61.1–§61.14): Run Inspector «Пайплайн саммари».
       Вертикальный timeline (mobile-first, §61.14); статусы — значок +
       текстовый label (цвет НЕ единственный носитель, §61.2); ветка
       обложки — отдельный блок (§61.8). Чистый CSS, без библиотек. ═══ */
    .pipe-timeline {
      display: flex;
      flex-direction: column;
      gap: 0;
      min-width: 0;
    }
    .pipe-node {
      border: 1px solid var(--surface-border, rgba(255, 255, 255, .12));
      border-radius: var(--radius-lg, .6rem);
      background: rgba(255, 255, 255, .04);
      padding: .35rem .6rem;
      cursor: pointer;
      min-width: 0;
    }
    .pipe-node:focus-visible {
      outline: 2px solid rgba(110, 168, 254, .7);
    }
    .pipe-node__row {
      display: flex;
      flex-wrap: wrap;
      align-items: baseline;
      gap: .35rem;
      font-size: .75rem;
      line-height: 1.3;
    }
    .pipe-node__icon {
      font-weight: 700;
      flex: none;
    }
    /* Цвет дополняет значок/текст, не единственный носитель (§61.2). */
    .pipe-node__icon--success  { color: #4ade80; }
    .pipe-node__icon--repaired,
    .pipe-node__icon--fallback { color: #fbbf24; }
    .pipe-node__icon--failed   { color: #f87171; }
    .pipe-node__icon--skipped,
    .pipe-node__icon--pending  { color: #9ca3af; }
    .pipe-node__icon--running  { color: #93c5fd; }
    .pipe-node__label {
      font-weight: 700;
      color: rgba(229, 231, 235, 1);
    }
    .pipe-node__status {
      color: rgba(156, 163, 175, 1);
    }
    .pipe-node__reason {
      color: rgba(252, 211, 77, .9);
    }
    .pipe-node__latency {
      flex: none;
    }
    .pipe-node__explain {
      margin-top: .3rem;
      padding-top: .3rem;
      border-top: 1px dashed rgba(255, 255, 255, .1);
      color: rgba(156, 163, 175, 1);
      font-size: .72rem;
      display: flex;
      flex-direction: column;
      gap: .1rem;
    }
    /* Коннектор вертикального timeline (§61.14). */
    .pipe-edge {
      color: rgba(156, 163, 175, .6);
      font-size: .7rem;
      line-height: 1;
      padding: .1rem 0 .1rem .9rem;
      user-select: none;
    }
    /* MCA-23 (P2-B, §36 current_task): причины planned-узлов «Ответ
       (Pipeline)» — информационные (шаблон из плана), НЕ предупреждения:
       нейтральный тон; amber `.pipe-node__reason` остаётся за реальными
       причинами падений Run Inspector (цвет не единственный носитель). */
    .pipe-plan__reason {
      color: rgba(156, 163, 175, 1);
      font-size: .72rem;
    }
    /* Агрегатные карточки per-stage (§61.5): сетка ≤3/2/1 колонки. */
    .pipe-grid {
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: .5rem;
    }
    @media (max-width: 640px) {
      .pipe-grid { grid-template-columns: 1fr; }
    }
    @media (min-width: 641px) and (max-width: 1024px) {
      .pipe-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    }
    /* Список последних запусков (§61.10): строки-кнопки, тач ≥44px. */
    .pipe-runs {
      display: flex;
      flex-direction: column;
      gap: .25rem;
    }
    .pipe-run-row {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: .5rem;
      font-size: .75rem;
      padding: .45rem .5rem;
      border: 1px solid var(--surface-border, rgba(255, 255, 255, .1));
      border-radius: .5rem;
      cursor: pointer;
      min-height: 44px;
      min-width: 0;
    }
    .pipe-run-row:focus-visible {
      outline: 2px solid rgba(110, 168, 254, .7);
    }

/* ══ Раунд 10.46 (MCA-12, ADR-1028-21 D3/D4): блок «Истории чата» ═════════
   Аддитивные стили витрины (Liquid Glass: карточка, не админ-таблица;
   палитра/радиусы — существующие токены). Лента — вертикальный
   пользовательский скролл с bounded-высотой (прецедент facts-list);
   reduced-motion — без анимаций (prepend мгновенный). */
.stories-feed {
  max-height: 22rem;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: .375rem;
  overscroll-behavior: contain;
}
.stories-item {
  border: 1px solid rgba(255, 255, 255, .06);
}
.stories-item--stale {
  opacity: .75;
}
@media (prefers-reduced-motion: reduce) {
  .stories-feed {
    scroll-behavior: auto;
  }
}

/* ═══ ASAP 8 F4 / REV-F3 tail: gap-утилиты ═══
   Prebuilt vendor/tailwind.css отстал от разметки: классы gap-x-4/gap-y-1
   используются (index.html: спаны заголовков Embeddings/Response-панелей),
   но в билде отсутствуют — спаны слипаются. Ровно 2 утилиты (значения
   Tailwind-канона); канонический путь — rebuild (tailwind.config.js). */
.gap-x-4 { column-gap: 1rem; }
.gap-y-1 { row-gap: 0.25rem; }

/* ═══════════════════════════════════════════════════════════════════════
   ═══ W2-SHELL (asap8-v6.3 live-correction): U01 mobile-шапка + U02 ═══
   Владелец секции: лейн W2-L1 SHELL. Геометрия шапки/row A/row B,
   меню «Ещё» (popover), мобильный dropdown суб-вкладок Аналитики.
   Материал (background/backdrop-filter/box-shadow/токены --glass-*) —
   НЕ здесь (лейн GLASS, property-split w2-contract §3.1/HS-3).
   ═══════════════════════════════════════════════════════════════════════ */

/* ── U01 row A: мобильная геометрия (<768, shell-mobile, IA v2) ─────────
   [чат-селектор + GLOBAL/CHAT + профиль] [⛶] — логотип AdminBot НЕ
   рендерится (см. ниже). Заголовок/крошки из шапки убраны (U01.5: нет
   второго заголовка, контент начинается сразу под row B); chat_id/роль —
   в меню «Ещё». */
.mobile-brand {
  display: none;
  align-items: center; gap: .3rem;
  color: var(--text-1);
  min-width: 0;
}
.mobile-brand .msr { font-size: 20px; line-height: 1; color: var(--teal-500, #2dd4bf); }
.mobile-brand-name { font-size: .8rem; font-weight: 700; letter-spacing: .01em; }
/* FS-HOTFIX FOLLOW-UP (директива владельца 18.10, §4.1.2/§5.5/§7 №8/§10):
   «Главный визуальный приоритет — убрать логотип AdminBot и занять
   освободившееся место функциональной кнопкой». Логотип — декоративный,
   кнопка ⛶ — функциональная: в мобильном shell логотип скрыт, его место
   отдано функциональной компоновке row A (селектор чата получает ширину,
   ⛶ остаётся у правого края внутри ТОЙ ЖЕ строки — без новой строки и без
   роста шапки). Desktop/compact shell (sidebar/drawer) не затронут: там
   логотип и не рендерится (v-if isMobileShell), а правила .mobile-brand
   остаются для узкого окна Telegram Desktop (<768 → mobile shell). */
.app-shell.shell-mobile .mobile-brand { display: none; }
/* Заголовок/крошки — только desktop/compact shell; на mobile row A без
   второго заголовка (раздел виден в row B / «Ещё • …»). */
.app-shell.shell-mobile header.header-sticky.header-compact-v2 .header-title-wrap {
  display: none;
}
/* row A: селектор области — гибкий, с ellipsis (не полная строка названия);
   ширина по flex/clamp, полное имя — в title/aria-label триггера. */
.app-shell.shell-mobile header.header-sticky.header-compact-v2 .header-scope-row {
  order: 1;
  /* flex-basis 0% (не auto): строка A занимает одну линию, селектор
     сжимается с ellipsis — без этого max-content переносит её на 2-ю линию. */
  flex: 1 1 0%;
  flex-wrap: nowrap;
  min-width: 0;
}
.app-shell.shell-mobile .scope-wrap {
  flex: 1 1 auto;
  order: 0;
  max-width: 100%;
  min-width: 0;
}
.app-shell.shell-mobile .scope-trigger {
  width: 100%;
  max-width: clamp(96px, 100%, 280px);
  min-height: 40px;
}
/* U01.2: ID области — НЕ в постоянной шапке (доступен в меню «Ещё»,
   блок профиля); на desktop <details class="scope-tech"> сохранён. */
.app-shell.shell-mobile .scope-tech { display: none; }
/* U01.2: профиль в row A — компактно (аватар); имя/роль — в «Ещё»
   (без третьей строки, всё влезает на 320px). */
.app-shell.shell-mobile .header-user { gap: .25rem; }
.app-shell.shell-mobile .header-user span { display: none; }
/* mobile: ровно 2 flex-линии — row A (бренд/селектор/профиль/⛶) и row B.
   Явный order у row B: без него (order auto = 0) topnav упаковывается
   РАНЬШЕ scope-row(order 1) и шапка разваливается на 3–4 строки. */
.app-shell.shell-mobile header.header-sticky.header-compact-v2 .mobile-topnav {
  order: 10;
}
.app-shell.shell-mobile header.header-sticky.header-compact-v2 {
  row-gap: .3rem;
}

/* ── FS-HOTFIX FOLLOW-UP §8 (18.10): временная админ-диагностика геометрии ⛶
   Панель открывается только из меню «Ещё» (admin-гейт), закрыта по
   умолчанию — в обычном UI места не занимает. Нейтральный solid-материал
   (это dev-инструмент, не продуктовая карточка); z-index 57 — выше меню
   «Ещё» (55/56), ниже модалок (59). Временная: удалить после приёмки. */
.fs-geom-diag-root { position: fixed; inset: 0; z-index: 57; }
.fs-geom-diag-backdrop {
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, .45);
}
.fs-geom-diag-panel {
  position: absolute;
  left: max(8px, env(safe-area-inset-left, 0px));
  right: max(8px, env(safe-area-inset-right, 0px));
  top: calc(var(--header-h, 96px) + env(safe-area-inset-top, 0px) + 4px);
  max-height: calc(100dvh - var(--header-h, 96px)
             - env(safe-area-inset-top, 0px)
             - max(env(safe-area-inset-bottom, 0px), 12px) - 8px);
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: .4rem;
  padding: .5rem;
  background-color: var(--surface-1, #11151c);
  border: var(--card-border, 1px solid rgba(255, 255, 255, .12));
  box-shadow: var(--shadow-xl);
  border-radius: 14px;
  outline: none;
}
.fs-geom-diag-pre {
  margin: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .6875rem; line-height: 1.3;
  white-space: pre-wrap; word-break: break-word;
  color: var(--text-2, #C7D0DD);
}
.fs-geom-diag-actions { display: flex; flex-wrap: wrap; gap: .4rem; }
/* Админ-инструмент в подвале меню «Ещё»: НЕ пункт навигации (отдельный класс,
   чтобы RBAC-счётчик разделов меню не менялся), доступен только админу */
.more-menu-admin-tool {
  display: flex; align-items: center; gap: .6rem;
  min-height: 44px;
  margin-top: .2rem;
  padding: .5rem .6rem;
  border: 1px dashed rgba(255, 255, 255, .18);
  border-radius: 10px;
  background: transparent;
  color: var(--text-2, #C7D0DD);
  font-size: .8125rem;
  text-align: left;
  cursor: pointer;
  width: 100%;
}
.more-menu-admin-tool:hover { background: rgba(255, 255, 255, .07); }
.more-menu-admin-tool .msr { font-size: 18px; color: var(--text-3, #8B96A5); flex-shrink: 0; }
.more-menu-admin-tool:focus-visible {
  outline: 2px solid rgba(139, 92, 246, .7);
  outline-offset: 2px;
}
/* Оверлей вычисленных границ safe area: сверка с реальной нативной панелью
   (§8). pointer-events:none — тапы и скролл не перехватываются. */
.fs-safe-overlay { position: fixed; inset: 0; z-index: 56; pointer-events: none; }
.fs-safe-overlay__band {
  position: absolute; left: 0; right: 0; top: 0;
  height: 0;
  background: rgba(255, 138, 128, .10);
  border-bottom: 1px dashed rgba(255, 138, 128, .85);
}
.fs-safe-overlay__left {
  position: absolute; top: 0; bottom: 0; left: 0; width: 0;
  border-right: 1px dashed rgba(255, 138, 128, .55);
}
.fs-safe-overlay__right {
  position: absolute; top: 0; bottom: 0; right: 0; width: 0;
  border-left: 1px dashed rgba(255, 138, 128, .55);
}
.fs-safe-overlay__label {
  position: absolute; right: 6px; bottom: 2px;
  font: 10px/1.2 ui-monospace, SFMono-Regular, Menlo, monospace;
  color: rgba(255, 205, 200, .92);
  background: rgba(24, 10, 10, .6);
  padding: 1px 4px; border-radius: 4px;
  white-space: nowrap;
}

/* ── U01.4: меню «Ещё» — popover/sheet поверх контента ──────────────────
   Overlay + панель под шапкой; z-index: header=40, drawer=40, dropdowns=50,
   модалки=59/60 → меню 55/56 (выше шапки, ниже модалок). */
.more-menu-root { position: fixed; inset: 0; z-index: 55; }
.more-menu-backdrop {
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, .45);
}
.more-menu-panel {
  position: absolute;
  left: max(8px, env(safe-area-inset-left, 0px));
  right: max(8px, env(safe-area-inset-right, 0px));
  top: calc(var(--header-h, 96px) + env(safe-area-inset-top, 0px) + 4px);
  max-height: calc(100dvh - var(--header-h, 96px)
             - env(safe-area-inset-top, 0px)
             - max(env(safe-area-inset-bottom, 0px), 12px) - 8px);
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 2px;
  padding: .4rem;
  /* SHELL-baseline читаемости (popover поверх контента, U01.4): solid.
     GLASS вправе перетюсить материал через [data-glass="c"] (§3.2). */
  background-color: var(--surface-1, #11151c);
  border: var(--card-border, 1px solid rgba(255, 255, 255, .12));
  box-shadow: var(--shadow-xl);
  border-radius: 14px;
  outline: none;
}
.more-menu-item {
  display: flex; align-items: center; gap: .6rem;
  min-height: 44px;
  padding: .5rem .6rem;
  border: none; border-radius: 10px;
  background: transparent; color: var(--text-1);
  font-size: .875rem; text-align: left; cursor: pointer;
  width: 100%;
}
.more-menu-item:hover { background: rgba(255, 255, 255, .07); }
.more-menu-item.active { font-weight: 600; background: rgba(139, 92, 246, .18); }
.more-menu-item .msr { font-size: 22px; color: var(--teal-500, #2dd4bf); flex-shrink: 0; }
.more-menu-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.more-menu-item:focus-visible, .mobile-topnav-link:focus-visible,
.oversight-mobile-trigger:focus-visible, .oversight-mobile-option:focus-visible {
  outline: 2px solid rgba(139, 92, 246, .7);
  outline-offset: 2px;
}
.more-menu-profile {
  display: flex; align-items: center; gap: .5rem;
  margin-top: .3rem; padding: .5rem .6rem;
  border-top: 1px solid rgba(255, 255, 255, .12);
}
.more-menu-profile-main { display: flex; flex-direction: column; min-width: 0; }
.more-menu-profile-name {
  font-size: .8rem; font-weight: 600; color: var(--text-1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.more-menu-profile-meta {
  font-size: .7rem; color: var(--text-3, #8B96A5);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* U01.4 body-scroll-lock без прыжков: единственный скроллер mobile-shell
   (main.scroll-area) блокируется на время открытого меню. */
.app-shell.more-menu-open.shell-mobile main.scroll-area { overflow: hidden; }

/* ── U02: мобильный dropdown суб-вкладок Аналитики (<768) ───────────────
   Один полноширинный триггер «Раздел: [текущая ▾]»; полный список в
   панели; длинные метки — до 2 строк в меню, ellipsis на триггере. */
.oversight-mobile-dd { position: relative; }
.oversight-mobile-trigger {
  display: flex; align-items: center; gap: .4rem;
  width: 100%; min-height: 44px;
  padding: .4rem .6rem;
  border-radius: 12px;
  background: rgba(255, 255, 255, .05);
  color: var(--text-1); font-size: .85rem;
  cursor: pointer; text-align: left;
}
.oversight-mobile-dd__label { color: var(--text-3, #8B96A5); flex-shrink: 0; }
.oversight-mobile-dd__current {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-weight: 600;
}
.oversight-mobile-dd__caret { flex-shrink: 0; color: var(--text-3, #8B96A5); }
.oversight-mobile-panel {
  position: absolute; left: 0; right: 0;
  top: calc(100% + 4px);
  z-index: 46;
  display: flex; flex-direction: column; gap: 2px;
  padding: .35rem;
  /* SHELL-baseline читаемости; GLASS перетюсит через [data-glass="c"]. */
  background-color: var(--surface-1, #11151c);
  border: var(--card-border, 1px solid rgba(255, 255, 255, .12));
  box-shadow: var(--shadow-xl);
  border-radius: 12px;
  max-height: 60vh;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.oversight-mobile-option {
  min-height: 44px;
  padding: .45rem .6rem;
  border: none; border-radius: 9px;
  background: transparent; color: var(--text-1);
  font-size: .85rem; text-align: left; cursor: pointer;
  white-space: normal;           /* длинные метки — до 2 строк в меню */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.oversight-mobile-option:hover { background: rgba(255, 255, 255, .07); }
.oversight-mobile-option.is-active { font-weight: 600; background: rgba(139, 92, 246, .18); }
@media (min-width: 768px) {
  .oversight-mobile-dd { display: none; }
}

/* Ландшафт: шапка МАКСИМАЛЬНО компактна — контент остаётся большинством
   экрана (FS-HOTFIX 18.10: Android landscape «верхняя панель занимает
   непропорционально много высоты»). Вертикальные отступы срезаны до
   минимума (row A остаётся hit-целью ⛶ 44px, row B — компактной лентой).
   Sum-формула нативной зоны сохранена — перекрытия с native-кнопками нет.
   Архитектура row B (Статус/Аналитика/Модули/Ещё) не меняется.
   Логотип не скрывается: измеренная ширина 667 даёт запас, а «скрывать
   логотип» директива разрешает только при реальной нехватке ширины —
   измерений нехватки нет (shell-e2e 320/390/667: overflow=0). */
@media (orientation: landscape) and (max-height: 500px) {
  .app-shell.shell-mobile header.header-sticky.header-compact-v2 {
    row-gap: .1rem;
    padding-top: calc(.15rem + max(env(safe-area-inset-top, 0px),
                  var(--tg-safe-area-inset-top, 0px))
                  + var(--tg-content-safe-area-inset-top, 0px));
    padding-bottom: .15rem;
  }
  .app-shell.shell-mobile .scope-trigger { min-height: 32px; }
}
@media (prefers-reduced-motion: reduce) {
  .more-menu-root, .oversight-mobile-panel { scroll-behavior: auto; }
}

/* ═══ W2-FULLSCREEN (asap8-v6.3, U07.2a/2b, REQ-U07-2) + FS-HOTFIX 18.10 ═══
   Один DOM-узел .header-fs-btn; единственный видимый слот — inline (в потоке
   row A). Писатели html.fs-hidden / data-fs-reason — ТОЛЬКО
   fullscreen-policy.js (контракт §2.3); --tg-* переменные пишет
   telegram-init.js, здесь они только читаются.
     inline  — кнопка стоит вплотную под нативной панелью клиента: низ
               нативной зоны задаёт safe-area-формула шапки
               max(env, --tg-safe) + --tg-content-safe-area (см. padding-top
               выше). Fixed-координат нет: реальных координат нативных
               кнопок клиента WebView не знает — официального API для них
               не существует (Telegram-Mini-Apps/issues#62, открыт.
               Text: «Provide a way to understand offsets and sizes of
               Close and Menu buttons», 10.01.2025);
     hidden  — html.fs-hidden: кнопка не рендерится (v-if в index.html);
               data-fs-reason на <html> — dev-маркер причины, НЕ UI.

   Геометрия FS-HOTFIX (18.10): иконка 18px (норма 16–18px), сам узел
   остаётся hit-целью ≥44×44 (U07.2/U01). Материал (21.10, U08.4d/U08.5.1,
   REV-W2-N1 закрыт биндингом): Tier B мини-линза .lg-mini-lens (W2-GLASS
   ниже; rim + один блик, НЕ «64px затемнённый квадрат») — правила
   .header-fs-btn больше не красят фон/рамку и не добавляют своё стекло,
   материал приходит ТОЛЬКО из .lg-mini-lens. */
.header-fs-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  transition: filter 0.12s ease;
}
.header-fs-btn .fs-ic { display: block; }
/* U08.4d: hover/active НЕ перекрашивают материал линзы плоским фоном
   (стирали бы градиент) — обратная связь яркостью. */
.header-fs-btn:hover { filter: brightness(1.12); }
.header-fs-btn:active { filter: brightness(.92); }
.header-fs-btn:focus-visible {
  outline: 2px solid rgba(139, 92, 246, .7);
  outline-offset: 2px;
}
/* ═══ /W2-FULLSCREEN ═══ */

/* ═════════════════════════════════════════════════════════════════════
   ═══ W2-GLASS (U08): слоистая модель Liquid Glass — lg-panel ═══
   Каноническая структура (ТЗ U08.2, имена заморожены w2-contract §3.4):
     .lg-panel                     position:relative; isolate; radius 16–22
       ├ .lg-panel__backdrop       pixels/refraction/blur ЗА панелью
       ├ .lg-panel__tint           tint + полупрозрачная толща
       ├ .lg-panel__rim            1–2 градиентные кромки (masked ring)
       ├ .lg-panel__specular       локальный направленный блик
       └ .lg-panel__content        контент; z поверх оптики; не искажается
   Инварианты: декоративные слои pointer-events:none (hit-тест REQ-U08-2);
   filter:url() НИКОГДА не на корне карточки/тексте/.lg-panel__content;
   контент не затуманивается; слои не перекрывают scroll/native hit-зоны.
   Модификаторы: --hero (Tier A линза), --soft (Tier B), --solid (Tier C).
   ═════════════════════════════════════════════════════════════════════ */
.lg-panel {
  position: relative;
  isolation: isolate;
  border-radius: var(--lg-radius);
  background: transparent;
}
.lg-panel--hero { border-radius: var(--lg-radius-hero); }
.lg-panel--soft { border-radius: var(--lg-radius); }
.lg-panel--solid {
  border-radius: var(--lg-radius-solid);
  background-color: var(--glass-bg-strong);
  border: 1px solid var(--glass-border-color);
  box-shadow: var(--glass-shadow);
}
/* Декоративные слои: рисуют оптику, никогда не перехватывают pointer. */
.lg-panel__backdrop,
.lg-panel__tint,
.lg-panel__rim,
.lg-panel__specular {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  border-radius: inherit;
}
/* backdrop: единственный слой, трогающий задние пиксели.
   hero: Tier A — реальная edge-рефракция url(#lg-lens) (Chromium, probe);
   без tier="a" — честный frost (WebKit/эконом-режим/reduced-motion). */
.lg-panel__backdrop {
  -webkit-backdrop-filter: var(--lg-frost-hero);
  backdrop-filter: var(--lg-frost-hero);
}
.lg-panel--hero .lg-panel__backdrop { -webkit-backdrop-filter: var(--lg-frost-hero); backdrop-filter: var(--lg-frost-hero); }
.lg-panel--hero[data-glass-tier="a"] .lg-panel__backdrop {
  -webkit-backdrop-filter: var(--lg-frost-hero) url(#lg-lens);
  backdrop-filter: var(--lg-frost-hero) url(#lg-lens);
}
.lg-panel__tint { background: var(--lg-tint-soft); }
.lg-panel--hero .lg-panel__tint { background: var(--lg-tint-hero); }
/* rim: 1–2 полосы градиентной кромки через masked ring (padding 1.5px). */
.lg-panel__rim {
  padding: 1.5px;
  background:
    linear-gradient(170deg,
      rgba(120, 235, 255, 0.22) 0%, rgba(120, 235, 255, 0) 10%,
      rgba(120, 235, 255, 0) 78%, rgba(167, 139, 250, 0.20) 100%),
    var(--lg-rim);
}
.lg-panel--solid .lg-panel__rim { background: none; }
@supports ((mask-composite: exclude) or (-webkit-mask-composite: xor)) {
  .lg-panel__rim {
    -webkit-mask: var(--lg-ring-mask);
    mask: var(--lg-ring-mask);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
  }
}
/* U08.5.3 fallback: mask-composite нет → rim по box-shadow,
   контролы видимы и кликабельны (скриншот fallback в evidence). */
@supports not ((mask-composite: exclude) or (-webkit-mask-composite: xor)) {
  .lg-panel__rim {
    background: none;
    box-shadow: inset 0 0 0 1px rgba(210, 235, 255, 0.40),
                inset 0 1px 0 rgba(248, 254, 255, 0.50),
                inset 0 -1px 0 rgba(150, 190, 240, 0.22);
  }
}
/* specular: ЛОКАЛЬНЫЙ верхне-левый блик + второй мягкий по боковине
   (не равномерная заливка — направленный свет, ТЗ U08.2). */
.lg-panel__specular {
  background:
    radial-gradient(130% 65% at 12% -2%,
      rgba(248, 254, 255, 0.30) 0%, rgba(248, 254, 255, 0) 42%),
    radial-gradient(60% 34% at 88% 4%,
      rgba(210, 238, 255, 0.14) 0%, rgba(210, 238, 255, 0) 55%);
  opacity: .9;
}
.lg-panel--soft .lg-panel__specular { opacity: .55; }
.lg-panel--solid .lg-panel__specular { display: none; }
.lg-panel__content {
  position: relative;
  z-index: 2;
}

/* ═══ W2-GLASS (U08.4b): массовые карточки — Tier B материал ═══
   blur снижен 16→8px + saturate(130%) (ТЗ-таблица U08.2; перф mid-range
   Android, U08.3e). Кромка/объём — inset-полосы box-shadow (без псевдо —
   не трогаем stacking 94 узлов .card). Поверхность материальная, не
   «однотипные тёмные прямоугольники». */
.card,
.module-card,
.hub-card,
.prov-block,
.glass-panel,
.oversight-panel {
  -webkit-backdrop-filter: var(--lg-frost);
  backdrop-filter: var(--lg-frost);
  box-shadow: var(--card-shadow),
              inset 0 1px 0 rgba(240, 248, 255, 0.26),
              inset 1px 0 0 rgba(210, 235, 255, 0.10),
              inset -1px 0 0 rgba(140, 180, 230, 0.08),
              inset 0 -1px 0 rgba(150, 190, 240, 0.12);
}
/* hover-specular на desktop (U08.4b): только фон-градиент, без layout. */
@media (hover: hover) {
  .module-card:hover {
    background-image:
      radial-gradient(120% 90% at 18% 0%,
        rgba(215, 240, 255, 0.10) 0%, rgba(215, 240, 255, 0) 55%);
  }
}

/* ═══ HOTFIX-TIERA (SOUL-1, приказ владельца): Tier A — основной материал
   ВСЕХ стеклянных поверхностей реальной админки ═══
   app.js ставит tier-атрибуты не только на `[data-glass]`, но и на классовые
   поверхности (`.card/.module-card/.hub-card/.prov-block/.glass-panel/
   .modal-card/details.advanced/.lg-panel/.lg-mini-lens/.sticky-save`) и
   выдаёт каждой подтверждённой (probe) поверхности линзу `url(#lg-lens …)`
   inline (пул фильтров по размеру узла). Здесь снято то, что ГАСИЛО
   рефракцию: избыточное затемнение подложки, двойной blur и конфликт
   вложенных слоёв. Ложной рефракции нет: без подтверждённой пробы узел
   остаётся честным Tier B (frost) — см. `data-glass-reason`. */
/* 1) Shell-панели (sidebar/шапка/drawer): плотная графитовая подложка §8
   (alpha .94/.96) физически скрывала преломление (видно 6% фона) — в
   ПОДТВЕРЖДЁННОМ Tier A она светлеет настолько, чтобы фон просвечивал и
   рефракция читалась на кромках. Не подтверждено (WebKit/эконом-режим/
   reduced-motion) — плотный §8-вид и честный отказ от рефракции. */
[data-glass="shell"][data-glass-tier="a"],
.app-shell [data-glass="shell"][data-glass-tier="a"] {
  background-color: rgba(27, 29, 34, 0.72);
}
@media (max-width: 767px) {
  [data-glass="shell"][data-glass-tier="a"],
  .app-shell [data-glass="shell"][data-glass-tier="a"] {
    background-color: rgba(27, 29, 34, 0.78);
  }
}
/* 2) Панель сохранения (pill над скроллом) — тоже стекло: плотный
   --glass-bg-strong (.85) скрывал линзу; в Tier A подложка светлее, кромка/
   кнопки сохраняют свою подложку и контраст. */
.sticky-save[data-glass-tier="a"] {
  background-color: rgba(21, 27, 42, 0.62);
}
/* Сейвбар ВНУТРИ модалки — не самостоятельное стекло (прозрачный футер
   `.modal-actions`): исключение объявлено в самом правиле футера
   (`!important` там же) — отдельного правила здесь нет. */
/* 3) «Стекло в стекле» (`data-glass-nested="1"` ставит app.js): ближайший
   предок уже несёт backdrop-filter → создан backdrop root, рефракция
   СТРАНИЦЫ там физически недостижима, а второй blur давал двойное размытие
   и «кирпич» от суммы alpha (U08.4b/G1.5). Плоская лёгкая подложка — тот же
   приём, что и прежний `.card .card`; ложной рефракции не имитируем. */
[data-glass-nested="1"] {
  background-color: rgba(255, 255, 255, .04);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
/* ═══ /HOTFIX-TIERA ═══ */

/* ═══ W2-GLASS (U08.4d): lg-mini-lens — круглый Tier B-контрол ⛶ ═══
   Материал для кнопки U07 (класс применён в разметке ⛶ index.html,
   21.10, U08.4d/U08.5.1 — REV-W2-N1; геометрия — за fullscreen-лейном,
   здесь только визуал: круглая мини-линза с rim и одним бликом, НЕ
   «64px затемнённый квадрат»). */
.lg-mini-lens {
  position: relative;
  isolation: isolate;
  border-radius: 50%;
  background:
    radial-gradient(90% 90% at 30% 22%,
      rgba(220, 240, 255, 0.22) 0%, rgba(220, 240, 255, 0) 55%),
    rgba(21, 27, 42, 0.55);
  border: 1px solid rgba(210, 235, 255, 0.35);
  box-shadow: 0 4px 14px rgba(0, 6, 22, 0.30),
              inset 0 1px 0 rgba(248, 254, 255, 0.45),
              inset 0 -1px 0 rgba(150, 190, 240, 0.18);
  -webkit-backdrop-filter: var(--lg-frost-hero);
  backdrop-filter: var(--lg-frost-hero);
  color: #eaf2ff;
}
.lg-mini-lens::after {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  pointer-events: none; border-radius: inherit; padding: 1px;
  background: var(--lg-rim);
}
@supports ((mask-composite: exclude) or (-webkit-mask-composite: xor)) {
  .lg-mini-lens::after {
    -webkit-mask: var(--lg-ring-mask);
    mask: var(--lg-ring-mask);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
  }
}

/* ═══ W2-GLASS (U08.3e): pause/деградация ═══
   Скрытая вкладка/TMA (html.lg-bg-paused из app.js::setBgPaused):
   стеклянные слои статичны по дизайну (нет rAF/анимаций в оптике),
   правило фиксирует отсутствие анимаций и будущие регрессии ловит. */
html.lg-bg-paused .lg-panel__specular,
html.lg-bg-paused .lg-panel__rim,
html.lg-bg-paused .lg-mini-lens::after {
  animation: none !important;
  transition: none !important;
}
/* prefers-reduced-motion: само стекло НЕ убивать — статичный rim/tint
   остаётся (U08.3e); анимаций в оптике нет и не должно появляться. */
@media (prefers-reduced-motion: reduce) {
  .lg-panel__specular,
  .lg-panel__rim,
  .lg-panel__backdrop,
  .lg-mini-lens::after {
    animation: none !important;
    transition: none !important;
  }
}
/* ═══ /W2-GLASS ═══ */

/* ═══ W3-EDITOR (asap8-v6-3 B05/U06): Style editor — стабильный solid
   инструмент (Tier C по U08.4; стабильность B05 важнее декоративности).
   CORR-1: полигональный фон production ЗАМОРОЖЕН — редактор получает
   неподвижный НЕПРОЗРАЧНЫЙ фон ЛОКАЛЬНОЙ поверхностью контейнера
   (дизайн-токены --surface-*), глобальный фон не меняется. ═══ */

/* B05.1: редактор — непрозрачная поверхность поверх оверлея; живой
   polygon/canvas сквозь текст не виден. Декоративный фон остаётся только
   ВНЕ рабочей области (за rgba-оверлеем). */
.cover-editor {
  background: var(--surface-1, #151B2A);
}

/* B05.3: overlay — 100dvh внутри Telegram WebView (dvh с vh-fallback);
   сам оверлей не скроллится и не перепускает скролл наружу. */
@media (max-width: 639.98px) {
  .cover-overlay {
    height: 100vh;
    height: 100dvh;
  }
}
.cover-overlay { overscroll-behavior: contain; }

/* B05.3: no behind-overlay scroll — пока открыт редактор, скролл app
   позади заблокирован (класс ставит watch coverStyles.editorOpen).
   Оверлей fixed, документ не скроллится — layout app не сдвигается. */
html.cover-editor-open { overflow: hidden; }

/* U06.1: секции рабочего инструмента — solid-карточки Tier C (читаемый
   текст без стекла/рефракции на textarea и selection). */
.cover-editor-sec {
  border: 1px solid var(--surface-border);
  background: var(--surface-0, #090D17);
  border-radius: 0.75rem;
  padding: 0.75rem;
}
.cover-sec-title {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: rgba(156, 163, 175, 1);
  margin-bottom: 0.5rem;
}

/* U06.2: «Фактическая сборка» — одна строка; цвет ТОЛЬКО при превышении
   (никакого постоянного зелёного «успеха»). */
[data-cover-compile-summary] {
  font-weight: 600;
  color: rgba(229, 231, 235, 1);
}
.cover-limit-over {
  color: #f87171 !important;
}

/* U06.2: точный промпт — моноширинный pre со скроллом и копированием;
   длинный prompt читается без подсвечиваемой сетки за текстом
   (непрозрачная подложка секции). */
.cover-prompt-pre {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas,
    "Liberation Mono", monospace;
  font-size: 0.72rem;
  line-height: 1.45;
  max-height: 16rem;
  overflow: auto;
  overscroll-behavior: contain;
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0;
  padding: 0.5rem;
  border-radius: 0.5rem;
  background: var(--surface-1, #151B2A);
  color: rgba(209, 213, 219, 1);
  border: 1px solid var(--surface-border);
}

/* B05.3: guard закрытия — модальный слой ВНУТРИ оверлея редактора. */
.cover-guard-backdrop {
  position: absolute;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.6);
  padding: 1rem;
}
.cover-guard {
  background: var(--surface-2, #1C2537);
  border: 1px solid var(--surface-border);
  border-radius: 0.75rem;
  padding: 1rem;
  max-width: 22rem;
  width: 100%;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5);
}

/* B05.1: prefers-reduced-motion — внутри редактора движения нет
   (редактор и так без анимаций; правило страхует будущие декорации). */
@media (prefers-reduced-motion: reduce) {
  .cover-editor *,
  .cover-guard * {
    animation: none !important;
    transition: none !important;
  }
}
/* ═══ /W3-EDITOR ═══ */
/* ═══ W3-STATUS (asap8-v6-3-live-correction: U03/U04/B03) ═══
   Правки только status-слоёв; полигональный фон ЗАМОРОЖЕН (CORR-1):
   читаемость достигается ПОДЛОЖКАМИ карточек/ячеек (opacity/pointer-events),
   НЕ правкой background-stack. */

/* U03.1: каноническая панель «Сон / Глубокий сон» — фазы читаемыми
   строками; подложка фазы — плотная (контент не просвечивает через
   анимацию/фон), это слой карточки, не фона. */
.status-sleep .sleep-phase b { color: var(--text-1, #F4F7FB); }

/* U03.3: «Здоровье памяти» — смысловые результаты и технические счётчики
   раздельно; раскладка строками «имя → значение» (не разноцветные pills
   одной строкой на мобиле). */
.mem-kv {
  border: 1px solid rgba(255, 255, 255, .08);
  border-radius: 10px;
  padding: .5rem .6rem;
  margin-top: .5rem;
  background: rgba(10, 14, 22, .55);  /* подложка над фоном, не фон */
}
.mem-kv--semantic { border-color: rgba(139, 92, 246, .25); }
.mem-kv__title { font-weight: 700; color: var(--text-1, #F4F7FB);
  margin-bottom: .25rem; font-size: .78rem; }
.mem-kv__row {
  display: flex; justify-content: space-between; gap: .75rem;
  padding: .12rem 0; font-size: .72rem; color: #AAB6C8; min-width: 0;
}
.mem-kv__row b { color: var(--text-1, #F4F7FB); font-weight: 600;
  white-space: nowrap; }
.mem-kv__empty { font-size: .72rem; color: #94a3b8; padding: .15rem 0; }

/* U03.3: ленты «Мониторинга Интеллекта» — контент не просвечивает через
   анимацию: плотная подложка ленты и элементов (слои карточек). */
.intel-card .ribbon { background: rgba(10, 14, 22, .55); }
.ribbon-item {
  background: rgba(10, 14, 22, .45);
  border-radius: 6px;
}

/* U03.4: independent-воронка «Инициативы» — сетка ячеек стадий;
   desktop 4 колонки, tablet 4→2, mobile — 2 колонки (читаемо на 320). */
.funnel-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: .4rem;
}
@media (max-width: 991px) { .funnel-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.funnel-cell {
  border: 1px solid rgba(255, 255, 255, .08);
  border-radius: 8px;
  padding: .35rem .5rem;
  min-width: 0;
  background: rgba(10, 14, 22, .55);
}
.funnel-cell__label { font-size: .66rem; color: #AAB6C8; }
.funnel-cell__value { font-size: .95rem; font-weight: 700;
  color: var(--text-1, #F4F7FB); line-height: 1.2; }
.funnel-cell__sub { font-size: .62rem; color: #8b98ab; }
.funnel-cell--ok { border-color: rgba(255, 255, 255, .08); }
.funnel-cell--warn { border-color: rgba(251, 191, 36, .45); }
.funnel-cell--warn .funnel-cell__value { color: #fbbf24; }

/* U03.4: окна 24ч/7д «Опыта» — две карточки рядом, mobile — столбик. */
.exp-windows {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .5rem;
}
@media (max-width: 640px) { .exp-windows { grid-template-columns: 1fr; } }
.exp-window {
  border: 1px solid rgba(255, 255, 255, .08);
  border-radius: 8px;
  padding: .4rem .55rem;
  min-width: 0;
  background: rgba(10, 14, 22, .55);
}
.exp-window__title { font-weight: 700; color: var(--text-1, #F4F7FB);
  margin-bottom: .2rem; font-size: .74rem; }
.exp-window__row {
  display: flex; justify-content: space-between; gap: .5rem;
  font-size: .7rem; color: #AAB6C8; padding: .08rem 0; min-width: 0;
}
.exp-window__row b { color: var(--text-1, #F4F7FB); font-weight: 600; }

/* U04: якорный скролл к блоку логов — гарантированный резерв под
   sticky-шапку (JS считает offset измерением; scroll-margin страхует
   нативный anchor-переход). */
#status-logs { scroll-margin-top: calc(var(--header-h, 4.5rem) + 1rem); }
/* В mobile-скроллере scroll-padding-top уже резервирует шапку — не
   удваиваем отступ. */
.app-shell.shell-mobile:not(.shell-layout-legacy) .scroll-area #status-logs,
.app-shell.fullscreen-mode:not(.shell-layout-legacy) .scroll-area #status-logs {
  scroll-margin-top: 0;
}
/* Внутри .status-grid карточка логов — полная ширина строки на всех
   брейкпоинтах (эквивалент sg-12 задан классом; правило страхует
   kill-switch UI_STATUS_GRID_V2=OFF, где каждая ячейка и так 1/-1). */
.status-grid > .status-logs { grid-column: 1 / -1; }

/* U04: тач-цели контролов viewer логов в Статусе (чип «Саммари»/Обновить
   в один ряд с селектором — ≥36px, на таче 44px через существующие
   btn-ghost паддинги; прямого сужения нет). */
.status-logs .log-chip.active {
  border-color: rgba(139, 92, 246, .5);
  background: rgba(139, 92, 246, .18);
}
@media (max-width: 767px) {
  .status-logs .log-chip, .status-logs .btn-ghost { min-height: 44px; }
}
/* Visual Neighborhood Sweep (U04): .field { width:100% } перебивал
   Tailwind w-32/w-40 — селектор уровня и trace-фильтры растягивались на
   всю карточку и переносились по одному в ряд. На ≥768 возвращаем
   компактные ширины (утилиты w-* применяются), на мобиле — полноширинные
   (тач-дружелюбно), как было. */
@media (min-width: 768px) {
  .status-logs select.field { width: auto; }
  .status-logs #mca-log-filters .field { width: auto; flex: 0 1 auto; }
}
/* ═══ /W3-STATUS ═══ */

/* ═══ W3-MODULES-UI (ASAP 8 v6.3: B06/B07/B01.4) ═══ */
/* B06.2: read-only мастер-тумблер global-only карточки на области чата.
   Хитбокс НЕ меняется (тот же w-11 h-6 peer, U08.4): только курсор и
   приглушение активного цвета — состояние остаётся читаемым. */
.module-toggle.is-readonly { cursor: default; opacity: .72; }
.module-toggle.is-readonly .peer { cursor: default; }
/* Подпись причины read-only на карточке каталога (вместо ⚠-проблемы:
   это не сбой, а честная природа master-флага). */
.module-global-hint { color: rgba(156, 163, 175, .9); margin-top: 2px; }
/* «Настроить глобально» — существующий btn-ghost; компактная тач-цель. */
.module-card-actions .module-global-btn { min-height: 32px; }
/* B07: строка детализации проверок во времени на Обзоре Фактчека —
   усечение длинных заголовков без роста ширины карточки. */
[data-factcheck-temporal] .btn-ghost { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* ═══ /W3-MODULES-UI ═══ */

/* ═══ W3-ANALYTICS ═══ */
/* U05 (v6.3): прогрессивная Аналитика + 7 визуализаций D12 §18I.12
   на реальных durable-данных. Тёмная палитра AdminBot; читаемый
   контраст (текст ≥ rgba(244,247,251,…)); текст не лежит на графике;
   мобильные 320/390 + landscape 667×375 без переполнения;
   prefers-reduced-motion: блоки статичны (анимаций нет). */

/* ── Viz 4: heatmap активности (день × час) ── */
.viz-heat { overflow-x: auto; }
.viz-heat__select { width: 88px; min-width: 88px; }
.viz-heat__hours,
.viz-heat__row {
  display: grid;
  grid-template-columns: 38px repeat(24, minmax(10px, 1fr));
  gap: 2px;
  align-items: center;
  min-width: 340px;
}
.viz-heat__hour,
.viz-heat__day {
  font-size: 9px;
  color: rgba(178, 192, 212, .85);
  text-align: center;
  line-height: 1.1;
}
.viz-heat__day { text-align: left; white-space: nowrap; }
.viz-heat__hours .viz-heat__day { min-height: 12px; }
.viz-heat__row .viz-heat__cell {
  width: 100%;
  aspect-ratio: 1 / 1;
  max-height: 16px;
  border-radius: 3px;
  background: rgba(255, 255, 255, .05);
  position: relative;
}
.viz-heat__cell--l1 { background: rgba(66, 214, 196, .18); }
.viz-heat__cell--l2 { background: rgba(66, 214, 196, .38); }
.viz-heat__cell--l3 { background: rgba(66, 214, 196, .62); }
.viz-heat__cell--l4 { background: rgba(139, 111, 232, .75); }
.viz-heat__cell--err::after {
  content: "";
  position: absolute;
  inset: auto 2px 2px auto;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: #F87171;
}

/* ── Viz 2: маршрут обработки (Sankey-lite) ── */
.viz-route__root,
.viz-route__branch {
  display: grid;
  grid-template-columns: minmax(120px, 180px) 1fr 48px;
  gap: 8px;
  align-items: center;
  padding: 2px 0;
}
.viz-route__label {
  font-size: 11px;
  color: var(--text-1, #F4F7FB);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.viz-route__label--branch { padding-left: 12px; color: rgba(220, 230, 244, .92); }
.viz-route__track { position: relative; height: 10px; }
.viz-route__bar {
  height: 100%;
  min-width: 2px;
  border-radius: 5px;
  background: linear-gradient(90deg, rgba(66, 214, 196, .85), rgba(139, 111, 232, .85));
}
.viz-route__bar--root {
  background: linear-gradient(90deg, rgba(66, 214, 196, .95), rgba(47, 185, 168, .75));
}
.viz-route__bar--zero { background: rgba(255, 255, 255, .10); }
.viz-route__bar--err { box-shadow: inset 0 0 0 1.5px rgba(248, 113, 113, .8); }
.viz-route__num {
  font-size: 11px;
  color: var(--text-1, #F4F7FB);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* ── Viz 1: цикл памяти (flow) ── */
.viz-flow {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: stretch;
}
.viz-flow__node {
  flex: 1 1 150px;
  min-width: 140px;
  max-width: 240px;
  border: 1px solid rgba(255, 255, 255, .10);
  border-radius: 10px;
  background: rgba(10, 14, 22, .55);
  padding: 8px 10px;
}
.viz-flow__node--err { border-color: rgba(248, 113, 113, .55); }
.viz-flow__node--zero { opacity: .78; }
.viz-flow__label { font-size: 11px; color: rgba(220, 230, 244, .92); }
.viz-flow__num { font-size: 18px; font-weight: 700;
  color: var(--text-1, #F4F7FB); font-variant-numeric: tabular-nums; }
.viz-flow__caption { font-size: 10px; color: rgba(178, 192, 212, .9); }

/* ── Viz 3: waterfall задержек ── */
.viz-wf__row {
  display: grid;
  grid-template-columns: minmax(110px, 160px) 1fr 64px;
  gap: 8px;
  align-items: center;
  padding: 2px 0;
}
.viz-wf__label {
  font-size: 11px;
  color: var(--text-1, #F4F7FB);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.viz-wf__track {
  position: relative;
  display: flex;
  height: 12px;
  min-width: 0;
}
.viz-wf__spacer { flex: none; }
.viz-wf__bar { height: 100%; border-radius: 4px; min-width: 2px; }
.viz-wf__bar--ok { background: rgba(66, 214, 196, .75); }
.viz-wf__bar--warn { background: rgba(251, 191, 36, .75); }
.viz-wf__bar--err { background: rgba(248, 113, 113, .85); }
.viz-wf__bar--muted { background: rgba(255, 255, 255, .18); }
.viz-wf__num {
  font-size: 11px;
  color: rgba(220, 230, 244, .92);
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ── Viz 5: карта зависимостей ── */
.viz-deps {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding-bottom: 4px;
}
.viz-deps__col {
  flex: 1 1 180px;
  min-width: 170px;
  border: 1px solid rgba(255, 255, 255, .08);
  border-radius: 10px;
  padding: 6px 8px;
  background: rgba(10, 14, 22, .45);
}
.viz-deps__title {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-1, #F4F7FB);
  margin-bottom: 4px;
  white-space: nowrap;
}
.viz-deps__chips { display: flex; flex-wrap: wrap; gap: 4px; }
.viz-deps__chip { font-size: 10px; max-width: 100%; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }

/* ── Viz 6: timeline дат источников фактчека ── */
.viz-factdates__row {
  display: grid;
  grid-template-columns: 96px 1fr minmax(140px, auto);
  gap: 8px;
  align-items: center;
  padding: 2px 0;
}
.viz-factdates__track { position: relative; height: 8px;
  background: rgba(255, 255, 255, .05); border-radius: 4px; }
.viz-factdates__bar {
  height: 100%;
  min-width: 2px;
  border-radius: 4px;
  background: rgba(139, 111, 232, .65);
}
.viz-factdates__bar--nodate { background: rgba(255, 255, 255, .16); }

/* ── Viz 7: popover overrides чата ── */
.viz-ovpop {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  z-index: 40;
  width: min(320px, 86vw);
  background: var(--surface-2, #1C2537);
  border: 1px solid var(--surface-border);
  border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0, 6, 22, .45);
  padding: 8px 10px;
  color: var(--text-2, #D7DFEC);
  text-align: left;
}

/* ── B08: карточка истории ── */
/* Секция историй не должна наследовать широкий grid-трек воркспейса
   (предсуществующие min-w-max/таблицы в той же вкладке): на 320px
   карточка обязана читаться (B08 mobile), поэтому секция ограничена
   шириной вьюпорта, а её фильтры сжимаются. */
[data-stories-manage] { max-width: 100vw; overflow-x: hidden; }
[data-stories-filters] .field { max-width: 100%; }
.story-card {
  background: rgba(10, 14, 22, .55);
  border-color: rgba(66, 214, 196, .30);
}
.story-card--insufficient {
  border-color: rgba(170, 182, 200, .22);
  background: rgba(15, 19, 28, .6);
}
.story-card__synopsis {
  color: var(--text-1, #F4F7FB);
  line-height: 1.45;
  overflow-wrap: anywhere;
}
.story-card__dates {
  margin-top: 6px;
  display: grid;
  gap: 2px;
}
.story-card__date-row { color: rgba(215, 223, 236, .95); }
.story-card__date-label {
  color: rgba(178, 192, 212, .9);
  margin-right: 4px;
}
.story-card__questions {
  border-left: 3px solid rgba(251, 191, 36, .55);
  padding-left: 8px;
  color: rgba(253, 230, 138, .95);
}
.story-card__timeline {
  margin-top: 4px;
  display: grid;
  gap: 4px;
}
.story-card__tl-item {
  display: flex;
  gap: 8px;
  align-items: baseline;
  border-left: 2px solid rgba(139, 111, 232, .35);
  padding-left: 8px;
  flex-wrap: wrap;
}
.story-card__tl-text {
  color: var(--text-1, #F4F7FB);
  flex: 1 1 200px;
  overflow-wrap: anywhere;
}
.story-card__tl-refs { flex: none; }

/* ── Мобильная адаптация (U05/V05: 320/390, landscape 667×375) ── */
@media (max-width: 640px) {
  .viz-route__root,
  .viz-route__branch { grid-template-columns: minmax(96px, 1fr) 64px 40px; }
  .viz-route__label--branch { padding-left: 6px; }
  .viz-wf__row { grid-template-columns: minmax(84px, 1fr) 72px 56px; }
  .viz-factdates__row { grid-template-columns: 72px 1fr minmax(110px, auto); }
  .viz-flow__node { flex-basis: 100%; max-width: none; }
  .viz-deps__col { flex-basis: 62%; }
  .viz-heat__hours,
  .viz-heat__row { grid-template-columns: 30px repeat(24, minmax(8px, 1fr)); min-width: 280px; }
}
@media (max-width: 380px) {
  .viz-route__root,
  .viz-route__branch { grid-template-columns: minmax(80px, 1fr) 48px 36px; }
  .viz-wf__row { grid-template-columns: minmax(72px, 1fr) 56px 48px; }
  .viz-wf__num, .viz-route__num { font-size: 10px; }
}
/* landscape-телефон: высота ограничена — панели компактны и без новых
   фиксированных высот; горизонтальный overflow исключён min-width'ами
   внутренних скролл-контейнеров (.viz-heat/.viz-deps). */
@media (max-height: 480px) and (orientation: landscape) {
  .viz-flow__node { padding: 4px 8px; }
  .viz-flow__num { font-size: 14px; }
}
/* ═══ /W3-ANALYTICS ═══ */

/* ═══════════════════════════════════════════════════════════════════════════
   SOUL-1 W6 — «Речь и характер» (#/ai/speech).
   Материалы НЕ новые: карточки/панели используют существующий tier A
   (`.card` + линза масштаба 32 из committed контракта), редакторы, таблицы и
   dense-текст сидят на opaque/tinted подложке (tier C) — иначе выбор и каретка
   не выживают перерисовку. Токены/линза/полигональный фон не затрагиваются.
   Правила раскладки: 1 колонка ≤599px; 600–1023 адаптивно; ≥1024 две колонки
   только там, где это правда полезно (редактор + предпросмотр). Тач-цели
   ≥44×44, паддинги ≥12px, длинные строки скроллятся ВНУТРИ компонента.
   ═══════════════════════════════════════════════════════════════════════════ */
.speech-screen {
  display: grid;
  gap: 12px;
  padding: 12px;
  max-width: 1180px;
  min-width: 0;
}
.speech-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 12px;
  min-height: 56px;
}
.speech-title { font-size: 14px; font-weight: 700; display: flex; align-items: center; gap: 6px; }
.speech-back,
.speech-refresh { min-height: 44px; min-width: 44px; }
.speech-entry .btn-accent { min-height: 44px; }

/* Тач-цели: все интерактивные контролы раздела ≥44×44 (SOUL-10.P2). */
.speech-screen button,
.speech-screen select,
.speech-screen .field,
.speech-screen summary { min-height: 44px; }
.speech-screen input[type="checkbox"],
.speech-screen input[type="radio"] { width: 22px; height: 22px; flex: none; }
.speech-screen label.flex { min-height: 44px; }

/* Кнопки-действия внутри раздела: прозрачность материала сохранена, но текст
   читается и на светлых участках tier A (блики линзы у кромки карточки). */
.speech-screen .btn-ghost {
  background-color: rgba(12, 18, 30, .72);
  color: var(--text-1, #F4F7FB);
}
.speech-screen .btn-ghost:hover:not(:disabled) {
  background-color: rgba(18, 26, 42, .86);
}
.speech-screen .btn-accent { color: #081018; }

/* Витрина: карточки-кнопки (§2/§4-C1: 4 группы). ADD-TR.1 (19.10.2026):
   число колонок решает КОНТЕЙНЕР (auto-fill + минимум содержимого), а не
   viewport. Порог 220px = минимум содержимого карточки: padding 10+10 +
   иконка 18 + 2×gap 8 + badge ≤72 + читаемое тело ≥84 («Попробовать»/
   «Возможности» при 13px/700 — самое длинное неразрывное слово) ≈ 210.
   Прежнее правило «ровно 2 колонки на 360–599px» давало на телефоне
   карточку 156px и тело 30–66px: заголовок уходил под badge (≈20px
   у «Характер», до 40px у «Возможности бота»), подписи рвались по
   2–5 букв (регрессия ADD-TR.1, evidence/render и evidence/grid-fix).
   Поэтому на узком экране колонка ОДНА и во всю ширину, а две
   появляются только когда каждая ≥220px. */
.speech-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr)); gap: 8px; }
.speech-group-title {
  grid-column: 1 / -1;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-3, #7C8798);
  margin-top: 4px;
}
.speech-group-note { grid-column: 1 / -1; }
/* Плотный вариант той же витрины: минимум колонки тот же (220px), иначе
   при подключении класса вернулась бы та же теснота, что в ADD-TR.1. */
.speech-grid-tight { grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr)); }
.speech-card {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 10px;
  min-height: 64px;
  text-align: left;
  cursor: pointer;
  color: inherit;
  min-width: 0;
}
.speech-card-tight { min-height: 64px; }
.speech-card[disabled] { cursor: default; opacity: .7; }
.speech-card-icon { font-size: 18px; line-height: 1; flex: none; }
.speech-card-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
/* ADD-TR.1: заголовок переносится, а не вылезает из своего бокса в зону
   badge (overflow-wrap:anywhere — без разрыва слов по буквам: рвём слово
   только когда оно реально не влезает). */
.speech-card-title { font-size: 13px; font-weight: 700; min-width: 0; overflow-wrap: anywhere; }
/* badge — несжимаемый элемент строки карточки: ужимается тело
   (.speech-card-body, min-width:0), статус остаётся целиком читаемым. */
.speech-card > .badge { flex: none; }
.speech-card-sub { font-size: 11px; color: var(--text-2, #A9B4C4); overflow-wrap: anywhere; }
.speech-card-detail {
  font-size: 11px;
  color: var(--text-3, #7C8798);
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.speech-adv-title {
  grid-column: 1 / -1;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-3, #7C8798);
  margin-top: 4px;
}
.speech-card-adv { min-height: 64px; }
.speech-adv-note { grid-column: 1 / -1; }

/* ═ SOUL-14.1: диаграмма «Как рождается ответ» (витрина «Речи и характера»).
   Статичная карта слоёв Core → SelfModel → L1 → (lessons, examples, humor)
   → Writer; НЕ журнал событий. Верстка одной колонкой без горизонтального
   скролла: перенос — overflow-wrap:anywhere, коннектор — линия CSS в желобе
   иконки (без зависимости от шрифта). Поверхность строк — конвенция
   .speech-tab (плотная тёмная подложка внутри стеклянной карточки). ═ */
.speech-layers {
  grid-column: 1 / -1;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}
.speech-layers-head { display: flex; align-items: flex-start; gap: 8px; min-width: 0; }
.speech-layers-glyph { color: var(--teal-500, #42D6C4); font-size: 20px; flex: none; }
.speech-layers-headtext { min-width: 0; }
.speech-layers-title { font-size: 13px; font-weight: 700; overflow-wrap: anywhere; }
.speech-layers-sub { font-size: 11px; color: var(--text-3, #A2B0C6); overflow-wrap: anywhere; }
.speech-layers-flow { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; min-width: 0; }
.speech-layer { display: flex; flex-direction: column; min-width: 0; }
.speech-layer:not(:last-child) { padding-bottom: 10px; }
.speech-layer:not(:last-child)::after {
  content: '';
  width: 0;
  height: 10px;
  margin-left: 19px; /* центр желоба иконки: 10px padding + 9px половина */
  border-left: 2px solid rgba(148, 163, 184, .24);
}
.speech-layer-card {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  width: 100%;
  min-height: 44px;
  padding: 8px 10px;
  text-align: left;
  color: inherit;
  background: rgba(9, 14, 25, .72);
  border: 1px solid rgba(148, 163, 184, .24);
  border-radius: 10px;
  min-width: 0;
}
.speech-layer-card-btn { cursor: pointer; }
.speech-layer-icon { font-size: 18px; line-height: 1; flex: none; color: var(--teal-500, #42D6C4); padding-top: 1px; }
.speech-layer-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.speech-layer-top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.speech-layer-title { font-size: 13px; font-weight: 700; min-width: 0; overflow-wrap: anywhere; }
.speech-layer-top > .badge { flex: none; }
.speech-layer-desc { font-size: 11px; color: var(--text-2, #AAB6C8); overflow-wrap: anywhere; }
.speech-layer-detail { font-size: 11px; color: var(--text-3, #A2B0C6); overflow-wrap: anywhere; }
.speech-layer-go { flex: none; font-size: 18px; color: var(--text-3, #A2B0C6); align-self: center; }
.speech-layers-note { font-size: 11px; color: var(--text-3, #A2B0C6); line-height: 1.35; overflow-wrap: anywhere; }

/* Раздел: панели/ряды/действия */
.speech-section {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
  min-width: 0;
}
.speech-section > *,
.speech-pad > *,
.speech-table > * { min-width: 0; }
.speech-pad { padding: 12px; display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.speech-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
.speech-note { font-size: 12px; line-height: 1.35; }
.speech-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.speech-actions .btn-accent,
.speech-actions .btn-ghost { min-height: 44px; padding-left: 12px; padding-right: 12px; }
.speech-select { min-height: 44px; max-width: 100%; }
.speech-search { min-height: 44px; flex: 1 1 180px; min-width: 0; }
.speech-warn {
  font-size: 12px;
  padding: 8px 10px;
  border-radius: 10px;
  background: rgba(250, 204, 21, .10);
  border: 1px solid rgba(250, 204, 21, .28);
  overflow-wrap: anywhere;
}

/* ASAP3 §1.3: ограничения подсказки — в существующей дизайн-системе. */
.speech-limits {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px;
  border-radius: 10px;
  background: rgba(9, 14, 25, .78);
  border: 1px solid rgba(148, 163, 184, .18);
  min-width: 0;
  overflow-wrap: anywhere;
}
.speech-limit-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  min-width: 0;
}
.speech-limit-row .badge {
  flex: 0 0 auto;
  white-space: nowrap;
}
.speech-limit-value {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  min-width: 0;
}
.speech-limit-input {
  width: 120px;
  max-width: 100%;
  min-height: 44px;
}

/* Редактор (tier C): непрозрачная подложка — выбор/каретка и черновик живут
   независимо от перерисовок и поллинга других разделов. §4-C6: автовысота
   от 3 строк (JS autoGrowEditor), максимум 40vh, resize выключен. */
.speech-editor {
  min-height: 96px;
  max-height: 40vh;
  resize: none;
  overflow: auto;
  background: var(--editor-bg, rgba(9, 14, 25, .96));
  border: 1px solid rgba(148, 163, 184, .28);
  color: var(--text-1, #F4F7FB);
  padding: 10px 12px;
  line-height: 1.45;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
  font-variant-ligatures: none;
}
.speech-editor.dirty { border-color: rgba(250, 204, 21, .55); }

/* Длинные строки/JSON/prompt — скролл ВНУТРИ компонента.
   ASAP-speech-arch U-04 (§8): режим ПРОСМОТРА переносит строки — на 320–430 px
   русский текст, URL и токены читаются целиком, без обрезания справа и без
   второй горизонтальной прокрутки страницы. Горизонтальный скролл остаётся
   только у явно кодовых блоков (`.speech-code`, diff), где строка значима. */
.speech-pre,
.speech-scrollable {
  margin: 0;
  padding: 10px 12px;
  max-height: 40vh;
  overflow: auto;
  background: rgba(9, 14, 25, .96);
  border: 1px solid rgba(148, 163, 184, .22);
  border-radius: 10px;
  font-size: 11px;
  line-height: 1.4;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  word-break: break-word;
  max-width: 100%;
  min-width: 0;
}
.speech-scrollable { white-space: pre-wrap; overflow-wrap: anywhere; }
/* Исключение: реальный код/diff — строку сохраняем, скроллим по горизонтали. */
.speech-pre.speech-code {
  white-space: pre;
  overflow-wrap: normal;
  word-break: normal;
  overflow-x: auto;
}

/* Плотные таблицы/ряды (tier C) */
.speech-table { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.speech-rule,
.speech-soft,
.speech-hist,
.speech-lesson,
.speech-entity-row,
.speech-layer-row,
.speech-cap-row,
.speech-trace-row,
.speech-block-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 10px;
  border-radius: 10px;
  background: rgba(9, 14, 25, .78);
  border: 1px solid rgba(148, 163, 184, .18);
  min-width: 0;
  overflow-wrap: anywhere;
}
.speech-soft, .speech-hist, .speech-entity-row, .speech-layer-row,
.speech-cap-row, .speech-trace-row {
  flex-direction: row;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}
.speech-rule-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* INS-SKIPREASON / INS-HIERARCHY / INS-CONFLICT (ASAP inspector §6) */
.speech-skip-row,
.speech-conflict-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 10px;
  border-radius: 10px;
  background: rgba(9, 14, 25, .78);
  border: 1px solid rgba(148, 163, 184, .18);
  min-width: 0;
  overflow-wrap: anywhere;
}
.speech-skip-row .text-xs,
.speech-conflict-row .text-xs { min-width: 0; overflow-wrap: anywhere; }
.speech-hier-group { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.speech-hier-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px 10px;
  border-radius: 10px;
  background: rgba(9, 14, 25, .78);
  border: 1px solid rgba(148, 163, 184, .18);
  cursor: pointer;
  min-width: 0;
  min-height: 44px;
  overflow-wrap: anywhere;
}
.speech-hier-row.is-open { border-color: rgba(96, 165, 250, .55); }
.speech-hier-row .text-xs { min-width: 0; overflow-wrap: anywhere; }
.speech-hier-detail {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 2px 4px 6px;
  min-width: 0;
}
.speech-hash {
  display: inline-block;
  max-width: 100%;
  overflow-wrap: anywhere;
  word-break: break-all;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10px;
  color: var(--text-2, #AEB6C4);
}
.speech-block-row { cursor: pointer; text-align: left; color: inherit; min-height: 44px; }
.speech-block-row .text-xs:last-child { color: var(--text-3, #7C8798); }

/* Diff/предпросмотр формы */
.speech-diff, .speech-preview { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.speech-diff-line, .speech-preview-line {
  font-size: 11px;
  padding: 6px 8px;
  border-radius: 8px;
  background: rgba(9, 14, 25, .9);
  border: 1px solid rgba(148, 163, 184, .18);
  overflow: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.speech-diff-line.before { border-color: rgba(248, 113, 113, .35); }
.speech-diff-line.after, .speech-preview-line.after { border-color: rgba(52, 211, 153, .35); }

/* Редактор редакций характера */
.speech-tabs { display: flex; gap: 6px; flex-wrap: wrap; }
.speech-tab {
  min-height: 44px;
  padding: 0 12px;
  border-radius: 10px;
  border: 1px solid rgba(148, 163, 184, .24);
  background: rgba(9, 14, 25, .72);
  color: inherit;
  font-size: 12px;
}
.speech-tab.active { border-color: rgba(56, 189, 248, .55); background: rgba(56, 189, 248, .12); }
.speech-adv summary { min-height: 44px; display: flex; align-items: center; cursor: pointer; }

/* Редактор + предпросмотр: две колонки ТОЛЬКО там, где это правда полезно */
.speech-split { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; min-width: 0; }

@media (max-width: 599px) {
  .speech-screen { padding: 12px; }
  .speech-editor { min-height: 110px; max-height: 42vh; }
  .speech-pre, .speech-scrollable { max-height: 34vh; }
}
/* ADD-TR.1 (19.10.2026, регрессия §4-C1): здесь было
   @media (min-width:360px) and (max-width:599px) { .speech-grid,
   .speech-grid-tight { repeat(2, minmax(0,1fr)) } } — «ровно 2 колонки по
   viewport». На 360px карточка сжималась до 156px, .speech-card-body до
   30–66px, ink заголовка «Характер» перекрывал badge на 21px, подписи
   рвались по 2–5 букв (замеры: evidence/render/measure.json; до/после —
   evidence/grid-fix). Правило удалено: сетка витрины снова управляется
   контейнером (.speech-grid, порог 220px), узкий экран = одна колонка
   во всю ширину. Тач-цели, разворот редактора и compaction-правила ниже
   не затронуты. */
/* §4-C1/§4-C2 (P0A-UX): компактная шапка и подблоки вместо «матрёшки»;
   группа=подпись, действие=кнопка, техдетали=details. Тач-цели не трогаем.
   Базовые правила идут ДО медиа-запросов ниже (иначе display:none перекрыл
   бы мобильные/landscape-правила при равной специфичности). */
.speech-refresh { display: inline-flex; align-items: center; gap: 6px; }
.speech-subblock {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  border-left: 2px solid rgba(148, 163, 184, .18);
  padding-left: 10px;
  border-radius: 0;
}
.speech-editor-tools { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.speech-expand-btn { display: none; }
/* C4: кнопка ⋯ — самостоятельная цель 44×44 (§4). */
.speech-menu-btn { min-width: 44px; justify-content: center; }
.speech-saved { color: #34d399; }
.speech-screen { padding-bottom: calc(12px + max(env(safe-area-inset-bottom), var(--tg-safe-area-inset-bottom, 0px)) + var(--kb-offset, 0px)); }
.speech-savebar { justify-content: flex-end; }
.speech-fullscreen {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  padding-top: calc(12px + env(safe-area-inset-top, 0px));
  padding-bottom: calc(12px + max(env(safe-area-inset-bottom),
    var(--tg-safe-area-inset-bottom, 0px)) + var(--kb-offset, 0px));
  background: rgba(9, 14, 25, .98);
  overflow: auto;
}
.speech-fullscreen .speech-editor { flex: 1 1 auto; max-height: none; }
/* ⋯-меню раздела: локальный popover по паттерну .more-menu-* (§4-C4):
   z-index 55 (ниже тостов 60), закрытие — backdrop/Esc/пункт. */
.speech-menu-root { position: fixed; inset: 0; z-index: 55; outline: none; }
.speech-menu-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, .45); }
.speech-menu-panel {
  position: absolute;
  left: max(8px, env(safe-area-inset-left, 0px));
  right: max(8px, env(safe-area-inset-right, 0px));
  top: calc(var(--header-h, 96px) + env(safe-area-inset-top, 0px) + 4px);
  max-height: calc(100dvh - var(--header-h, 96px)
    - env(safe-area-inset-top, 0px)
    - max(env(safe-area-inset-bottom, 0px), 12px) - 8px);
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: .4rem;
  background-color: var(--surface-1, #11151c);
  border: var(--card-border, 1px solid rgba(255, 255, 255, .12));
  box-shadow: var(--shadow-xl);
  border-radius: 14px;
}
@media (max-width: 599px) {
  .speech-tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
  .speech-tab { width: 100%; padding: 0 8px; }
  .speech-refresh-label { display: none; }
  .speech-expand-btn { display: inline-flex; }
}
/* §4-C2: имя активного чата дублирует верхний селектор области — на узком
   экране не показываем. */
@media (max-width: 480px) {
  .speech-head-chat { display: none; }
}
@media (min-width: 1024px) {
  .speech-split { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }
}
/* landscape-телефон: без высоких панелей */
@media (max-height: 480px) and (orientation: landscape) {
  .speech-editor { min-height: 120px; max-height: 40vh; }
  .speech-pre, .speech-scrollable { max-height: 30vh; }
  .speech-expand-btn { display: inline-flex; }
}
/* ═══ /SOUL-1 W6 ═══ */

/* ═══════════════════════════════════════════════════════════════════════════
   ADD-SAMPLES-UX §4 (20.10.2026): экран «Примеры» — вкладки категорий одной
   строкой, одна колонка карточек, отдельный экран редактора. Только токены
   и flex/grid с min-width:0; никаких фиксированных координат/высот/DPI.
   ═══════════════════════════════════════════════════════════════════════════ */
.speech-examples-tabs {
  display: flex;
  flex-wrap: nowrap;            /* §4.1.2: три вкладки одной строкой */
  gap: 6px;
  min-width: 0;
}
.speech-examples-tabs .speech-tab {
  flex: 1 1 0;
  min-width: 0;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.speech-examples-counters { display: flex; gap: 12px; flex-wrap: wrap; min-width: 0; }
.speech-examples-toolbar { flex-wrap: nowrap; min-width: 0; }
.speech-examples-toolbar .speech-examples-search { flex: 1 1 auto; min-width: 0; }
.speech-examples-adv { min-width: 0; }
.speech-sample-card { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.speech-sample-title {
  display: flex; align-items: center; gap: 8px; min-width: 0;
  cursor: pointer;
  /* REV-SAMPLES-UX b.2: бейдж статуса («Используется») не переносится
     по буквам; при нехватке места уходит на отдельную строку карточки. */
  flex-wrap: wrap;
}
.speech-sample-title .badge { flex: 0 0 auto; white-space: nowrap; }
.speech-sample-title .text-sm { min-width: 0; overflow-wrap: anywhere; }
.speech-sample-lines { cursor: pointer; min-width: 0; }
.speech-sample-lines > div {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
  min-width: 0;
}
.speech-sample-lines .speech-sample-input { -webkit-line-clamp: 2; color: inherit; }
.speech-sample-lines .speech-sample-reply { -webkit-line-clamp: 3; }
.speech-sample-caption { overflow-wrap: anywhere; min-width: 0; }
.speech-why-btn { min-height: 36px; }
.speech-field-full { display: block; min-width: 0; }
.speech-field-full .speech-select,
.speech-field-full .speech-editor { width: 100%; max-width: 100%; }
@media (max-width: 599px) {
  /* §4.3: на мобильном поля 100% ширины; тач-цели через .speech-screen */
  .speech-examples-adv .speech-select { width: 100%; }
}
@media (min-width: 1024px) {
  /* §4.3: desktop — ограниченный max-width читаемого контента
     (только экран «Примеры»; другие разделы не затронуты). */
  .speech-examples-screen { max-width: 720px; }
}
/* ═══ /ADD-SAMPLES-UX §4 ═══ */

/* ═══════════════════════════════════════════════════════════════════════════
   FIX-SPEECH-MOBILE (18.10, директива владельца §6.3) — явная строка-вход
   «Речь и характер» на хабе «ИИ» (мобильный путь «Ещё» → «ИИ»).
   Это НЕ карточка хаба: состав 5 страниц «ИИ» и навигация не меняются;
   это дверь к существующему special-screen'у #/ai/speech. Поверхность
   намеренно НЕ стеклянная (не входит в glass-селектор поверхностей) и не
   трогает фон/линзу/шапку: акцентная рамка + подложка из существующих
   токенов. Тач-цель ≥ 56px, длинные строки переносятся (320px-экран).
   ═══════════════════════════════════════════════════════════════════════════ */
.speech-hub-entry {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 10px; text-align: left;
  width: 100%; min-height: 56px; padding: 10px 12px;
  border-radius: var(--radius-lg);
  border: 1px solid rgba(56, 189, 248, .45);
  background: rgba(56, 189, 248, .10);
  color: var(--text-1); cursor: pointer;
}
.speech-hub-entry:hover { border-color: var(--teal-500); }
.speech-hub-entry__icon { color: var(--teal-500); font-size: 22px; flex: none; }
.speech-hub-entry__body {
  display: flex; flex-direction: column; gap: 1px;
  min-width: 0; flex: 1 1 auto;
}
.speech-hub-entry__title { font-size: var(--tx-med); font-weight: 600; }
.speech-hub-entry__sub {
  font-size: var(--tx-small); color: var(--text-3); overflow-wrap: anywhere;
}
.speech-hub-entry__cta {
  flex: none; font-size: var(--tx-small); color: var(--teal-500);
  font-weight: 600; white-space: nowrap;
}
/* ═══ /FIX-SPEECH-MOBILE ═══ */

/* ═══════════════════════════════════════════════════════════════════════════
   ASAP-speech-arch W4 (§8, U-01…U-09): точечные UI-исправления по скриншотам.
   Только раскладка, читаемость и аффордансы: базовые цвета, токены и
   полигональный рисунок не меняются; новых оверлеев/стекла не добавляется
   (материал — существующие `.card`/`lg-*`).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── U-03 (§8): «Библиотека промптов» — одна адаптивная сетка ─────────────
   Было: flex-wrap с карточками по содержимому → рваные вертикальные области
   (3 широкие, затем 5 узких) и «гуляющие» отступы. Теперь одна grid-система:
   равные колонки, одинаковые отступы, одинаковая внутренняя сетка кнопок. */
.prompt-module-grid {
  display: grid;
  gap: .75rem;
  grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
  align-items: stretch;
}
.prompt-module-card {
  display: flex;
  flex-direction: column;
  gap: .35rem;
  min-width: 0;
  height: 100%;
}
.prompt-module-card > .flex {
  margin-top: auto;          /* кнопки прижаты к низу — один ритм у всех карточек */
  row-gap: .25rem;
}

/* ── U-05 (§8): переключатель редакций и «Развернуть» ─────────────────────
   Подписи не съедают место соседних контролов и не ломают их размеры:
   табы переносятся/сжимаются, на 320–359 px — по одному в строке. */
.speech-tabs { flex-wrap: wrap; }
.speech-tab {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 100%;
  white-space: normal;
  overflow-wrap: anywhere;
  text-align: center;
}
@media (max-width: 359px) {
  .speech-tabs { grid-template-columns: minmax(0, 1fr); }
  .speech-tab { width: 100%; }
}
/* Крупный редактор (U-05): собственная прокрутка внутри, фон не «уезжает». */
.speech-fullscreen { overscroll-behavior: contain; }
.speech-fullscreen .speech-actions { flex: 0 0 auto; flex-wrap: wrap; }

/* ── U-04 (§8): кодовые поля/Inspector — перенос строк вместо обрезания ────
   На 320–430 px текст не упирается в правый край: pre-wrap + anywhere.
   Горизонтальный скролл — только у явного кода (`.speech-code`/diff). */
.speech-pre,
.speech-scrollable,
.speech-diff-line,
.speech-preview-line {
  max-width: 100%;
  min-width: 0;
}
.speech-pre { overflow-x: hidden; }
.speech-editor {
  max-width: 100%;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

/* ── U-02 (§8): честные аффордансы строк карты сборки ─────────────────────
   Ряд без адреса редактирования не притворяется кнопкой: нет hover, курсор
   обычный, явная пометка «только чтение» в разметке. */
.speech-layer-card-ro { cursor: default; }
.speech-layer-card-btn:focus-visible {
  outline: 2px solid rgba(66, 214, 196, .75);
  outline-offset: 2px;
}

/* ── U-06 (§8): шапка — заголовок и путь не дублируют друг друга ──────────
   Крошка показывает только путь (родители), имя раздела — единственный
   заголовок `.header-title`; он не перекрывается липкой шапкой, потому что
   живёт в её flex-строке (структурно над контентом). */
.header-title { line-height: 1.25; }
.breadcrumb { line-height: 1.2; }

/* ── U-07 (§8): один CTA сохранения ───────────────────────────────────────
   Панель `.speech-savebar` держит единственную активную кнопку (появляется
   только при dirty/ошибке); «Сохранено» — статус без кнопки. */
.speech-savebar[data-speech-savebar] .btn-accent[data-speech-save-primary] {
  flex: 0 0 auto;
}
.speech-savebar > .text-xs { min-width: 0; overflow-wrap: anywhere; }

/* ── U-08 (§8): читаемость вторичного текста на стекле ────────────────────
   Токен `--text-3` (#7C8798) и Tailwind `text-gray-500` на полупрозрачных
   карточках поверх яркого участка фона давали < 4.5:1 для 11–12 px. Поднимаем
   ТОЛЬКО вторичный текст внутри «Речи и характера» и подписи карточек хаба —
   базовые цвета/фон/полигоны не меняются. Контраст измеряется в evidence
   (`plans/features/asap-speech-arch/evidence/w4/ui-acceptance.md`). */
.speech-screen {
  --text-2: #C3CDDC;
  --text-3: #AAB6C8;
}
.speech-screen .text-gray-500,
.speech-screen .text-gray-400 { color: #AAB6C8; }
.speech-screen .text-\[10px\].text-gray-500 { color: #A7B3C6; }
.speech-card-sub,
.speech-card-detail,
.speech-layers-sub,
.speech-layer-desc,
.speech-layer-detail,
.speech-layers-note,
.speech-group-title { color: #AAB6C8; }
.hub-card .hub-card-sub { color: #AEBACB; }
.speech-hub-entry__sub { color: #AEBACB; }
/* ═══ /ASAP-speech-arch W4 ═══ */

