/* КРУСТ ПУЛЬТ — токены обеих тем и оболочка: сайдбар, шапка, контент, меню, вход, адаптив каркаса.
   Компоненты — components.css, экраны — screens.css. Тёмная тема (macет modern-style-dark) — по умолчанию,
   светлая — modern-style-light. Переходы 150–200 мс, prefers-reduced-motion выключает всё. Контраст текста ≥ 4.5:1 в обеих темах
   (в светлой ok/warn/purple затемнены под пилюли на «soft»-фоне). Отступы — шкала 2/4/6/8/12/16/20/24/32/48. */

:root {
  --bg: #0b1118;
  --bg-2: #0d131d;
  --surface: #0d131d;
  --surface-2: #0e161e;
  --surface-3: #141c26;
  --surface-hover: #131b25;
  --line: #1f2731;
  --line-strong: #2b3441;

  --ink: #ffffff;
  --ink-2: #c3cad4;
  --muted: #9aa2ad;
  --disabled: #7d8692;

  --accent: #5b57eb;
  --accent-hover: #6764f0;
  --accent-2: #4b47d6;
  --accent-soft: #192030;
  --accent-text: #8a92f6;
  --accent-line: rgba(138, 146, 246, 0.45);
  --accent-glow: 0 0 0 3px rgba(91, 87, 235, 0.28);
  --on-accent: #ffffff;

  --ok: #4ecb60;
  --ok-soft: rgba(78, 203, 96, 0.12);
  --ok-line: rgba(78, 203, 96, 0.45);
  --warn: #eab445;
  --warn-soft: rgba(234, 180, 69, 0.13);
  --warn-line: rgba(234, 180, 69, 0.45);
  --danger: #f4655f;
  --danger-soft: rgba(240, 80, 74, 0.13);
  --danger-line: rgba(240, 80, 74, 0.45);
  --info: #6b96f0;
  --info-soft: rgba(92, 139, 238, 0.13);
  --info-line: rgba(92, 139, 238, 0.4);
  --purple: #7a76df;
  --purple-soft: rgba(122, 118, 223, 0.14);

  /* Приветствие консультанта (screens.css, этап 13г): кольцо логотипа — четыре тона акцентной палитры, градиент заголовка — на токенах темы */
  --hero-grad-1: #5b57eb;
  --hero-grad-2: #6b96f0;
  --hero-grad-3: #8a92f6;
  --hero-grad-4: #7a76df;
  --hero-text-grad: linear-gradient(90deg, var(--accent-text), var(--info));

  --row-hover: rgba(138, 146, 246, 0.05);
  --shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  --shadow-card: none;
  --shadow-strong: 0 30px 80px rgba(0, 0, 0, 0.6);
  --backdrop: rgba(4, 8, 14, 0.7);
  --field-bg: #0b1118;
  --thead-bg: transparent;

  --mono: "JetBrains Mono", "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  --sans: Inter, "Segoe UI", Roboto, system-ui, -apple-system, "Helvetica Neue", sans-serif;

  --sidebar-w: 222px;
  --topbar-h: 60px;
  --content-max: 1440px;
  --content-pad: 24px;
  --radius-lg: 12px;
  --radius: 10px;
  --radius-sm: 8px;
  --radius-xs: 6px;
  --control-h: 40px;
  --row-control-h: 34px;
  --touch: 44px;

  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  /* Пружина для отклика нажатия (Motion AI Kit, generate-css-easing: spring, ощущаемые 0,22 с,
     упругость 0,25 — хвост кривой это доводка, не задержка). Библиотек не добавляем: чистый CSS */
  --spring-press: linear(0, 0.2093, 0.5494, 0.8103, 0.956, 1.0157, 1.0284, 1.0223, 1.0127, 1.0053, 1.0012, 0.9995, 1);
  --dur-spring: 400ms;
  --dur-fast: 150ms;
  --dur: 200ms;
}

/* Светлая тема — макет modern-style-light: белые карточки на #f7f9fc, индиго-акцент, тёмный текст */
:root[data-theme="light"] {
  --bg: #f7f9fc;
  --bg-2: #ffffff;
  --surface: #ffffff;
  --surface-2: #f9fafc;
  --surface-3: #f1f3f7;
  --surface-hover: #f3f5f9;
  --line: #e9ebef;
  --line-strong: #d9dde5;

  --ink: #0e121e;
  --ink-2: #2e3846;
  --muted: #5f6572;
  --disabled: #767c87;

  --accent: #3d38d1;
  --accent-hover: #312dc0;
  --accent-2: #2a26ad;
  --accent-soft: #ecebfb;
  --accent-text: #312dc0;
  --accent-line: rgba(61, 56, 209, 0.35);
  --accent-glow: 0 0 0 3px rgba(61, 56, 209, 0.18);
  --on-accent: #ffffff;

  --ok: #146f2b;
  --ok-soft: #e7f5ea;
  --ok-line: rgba(20, 111, 43, 0.35);
  --warn: #9c5408;
  --warn-soft: #fcf1e3;
  --warn-line: rgba(156, 84, 8, 0.35);
  --danger: #c22a2e;
  --danger-soft: #fbe9e8;
  --danger-line: rgba(194, 42, 46, 0.35);
  --info: #1f5fd6;
  --info-soft: #e8f1fc;
  --info-line: rgba(31, 95, 214, 0.35);
  --purple: #5d58d4;
  --purple-soft: #ededfb;
  /* --hero-grad-*: кольцо логотипа консультанта в светлой теме не переопределяется — те же тона читаются акцентом на белом;
     --hero-text-grad собирается из --accent-text и --info этой темы */

  --row-hover: rgba(61, 56, 209, 0.04);
  --shadow: 0 10px 30px rgba(14, 18, 30, 0.12);
  --shadow-card: 0 1px 2px rgba(14, 18, 30, 0.04);
  --shadow-strong: 0 30px 80px rgba(14, 18, 30, 0.2);
  --backdrop: rgba(14, 18, 30, 0.4);
  --field-bg: #ffffff;
  --thead-bg: #f9fafc;
}

*, *::before, *::after { box-sizing: border-box; }

html { background: var(--bg); color-scheme: dark; }
html[data-theme="light"] { color-scheme: light; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink-2);
  font: 400 14px/1.45 var(--sans);
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  font-variant-numeric: tabular-nums;
}

[hidden] { display: none !important; }

h1, h2, h3 { font-family: var(--sans); font-weight: 600; }

/* Кольцо фокуса повторяет форму самого элемента: у круглых и «таблеточных» контролов (переключатель темы,
   кнопки-иконки, пилюли) прямоугольная рамка 4 px выглядела приклеенной поверх */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: inherit; }

a.link, .link { color: var(--accent-text); text-decoration: none; font-weight: 500; transition: color var(--dur-fast) var(--ease); }
a.link:hover, .link:hover { color: var(--accent-hover); text-decoration: underline; text-underline-offset: 3px; }

.icon { display: block; width: 20px; height: 20px; flex: none; }
.icon-16 { width: 16px; height: 16px; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: 12px; top: -60px; z-index: 30;
  padding: 8px 16px; border-radius: var(--radius-sm);
  background: var(--accent); color: var(--on-accent); font-weight: 600; text-decoration: none;
}
.skip-link:focus { top: 12px; }

/* ── Каркас: сайдбар на всю высоту + колонка «шапка + контент» ──── */

.shell { display: flex; align-items: stretch; min-height: 100vh; }
.frame { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.sidebar {
  position: sticky; top: 0; align-self: flex-start;
  flex: none; width: var(--sidebar-w); height: 100vh;
  display: flex; flex-direction: column;
  padding: 16px 8px 12px;
  background: var(--bg-2);
  border-right: 1px solid var(--line);
}
.sidebar__scroll { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 8px; padding-bottom: 8px; overscroll-behavior: contain; }
/* Группа проекта крупнее и светлее подгрупп («Наблюдение», «Устройства»): раньше оба уровня были одинаковыми 11 px капсом */
.sidebar__group { margin: 12px 0 4px; padding: 0 16px; font-size: 12px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-2); }
.nav-group { display: flex; flex-direction: column; gap: 8px; }
/* Подгруппы «Проекта YODA»: заголовок капсом 11 px, сворачиваются (details), активный пункт подсвечивает и группу */
.nav-sub { margin: 0; }
.nav-sub__title {
  display: flex; align-items: center; gap: 8px; list-style: none; cursor: pointer; user-select: none;
  margin: 4px 0 2px; padding: 6px 16px; border-radius: var(--radius-sm);
  font-size: 11px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted);
  transition: color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.nav-sub__title::-webkit-details-marker { display: none; }
.nav-sub__title > span { flex: 1; min-width: 0; }
.nav-sub__title:hover { color: var(--ink); background: var(--surface-hover); }
.nav-sub__chevron { width: 16px; height: 16px; flex: none; transition: transform var(--dur-fast) var(--ease); }
.nav-sub:not([open]) .nav-sub__chevron { transform: rotate(-90deg); }
.nav-sub--current .nav-sub__title { color: var(--accent-text); }
.nav-sub__items { display: flex; flex-direction: column; gap: 2px; }
.nav-sub .nav-item { min-height: 38px; }
.nav-sub__title:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.nav-group--enter { animation: nav-group-in var(--dur) var(--ease); }
@keyframes nav-group-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

/* Логотип: знак из brand/logo.svg + «КРУСТ ПУЛЬТ» и мелкая подпись «CONTROL NODE 01 · INTERNAL» */
.brand { display: flex; align-items: center; gap: 8px; margin: 0 6px 16px 8px; text-decoration: none; color: inherit; }
.brand__mark { width: 34px; height: 34px; flex: none; }
.brand__text { display: flex; flex-direction: column; min-width: 0; }
.brand__title { font-size: 17px; font-weight: 700; letter-spacing: 0; color: var(--ink); line-height: 1.1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.brand__sub { margin-top: 3px; font-family: var(--mono); font-size: 7px; letter-spacing: 0.14em; color: var(--muted); white-space: nowrap; overflow: hidden; }

/* Переключатель проекта: «Все проекты ▾» */
.project-switch {
  display: flex; align-items: center; gap: 8px; width: 100%; min-height: 40px; margin: 0 0 12px; padding: 0 12px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--surface); color: var(--ink);
  font: 500 14px/1.2 var(--sans); text-align: left; cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.project-switch:hover, .project-switch[aria-expanded='true'] { border-color: var(--accent-line); background: var(--surface-hover); }
.project-switch__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.project-switch .icon { color: var(--muted); }
.project-switch__chevron { width: 16px; height: 16px; }

.nav-item {
  display: flex; align-items: center; gap: 12px;
  width: 100%; min-height: 44px; padding: 0 16px;
  border: 0; border-radius: var(--radius-sm);
  background: transparent; color: var(--ink-2);
  font: 500 14px/1.2 var(--sans); text-align: left; cursor: pointer; text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.nav-item .icon { color: var(--muted); transition: color var(--dur-fast) var(--ease); }
.nav-item:hover { background: var(--surface-hover); color: var(--ink); }
.nav-item:hover .icon { color: var(--ink-2); }
.nav-item[aria-current='page'] { background: var(--accent-soft); color: var(--accent-text); }
.nav-item[aria-current='page'] .icon { color: var(--accent-text); }
.nav-item__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-item__tag { font-size: 9px; font-weight: 600; letter-spacing: 0.06em; color: var(--muted); padding: 1px 4px; border: 1px solid var(--line-strong); border-radius: 4px; flex: none; }
.nav-item__badge {
  display: inline-flex; align-items: center; justify-content: center; min-width: 22px; height: 20px; padding: 0 6px;
  border-radius: 999px; background: var(--warn-soft); border: 1px solid var(--warn-line); color: var(--warn);
  font-size: 11px; font-weight: 600;
}
.nav-item__badge--danger { background: var(--danger-soft); border-color: var(--danger-line); color: var(--danger); }
.nav-item__badge:empty { display: none; }

/* ── Шапка: заголовок слева, часы · Обновить · Справка · тема · пользователь (учётная запись, безопасность, настройки, выход) ─── */

.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 6px;
  height: var(--topbar-h); padding: 0 var(--content-pad);
  background: var(--bg);
}
.topbar__title { font-size: 14px; font-weight: 500; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar__title b { font-weight: 500; color: var(--ink-2); }
.topbar__spacer { flex: 1; }
.topbar__clock { display: inline-flex; align-items: center; gap: 8px; margin-right: 12px; font-size: 14px; color: var(--ink-2); white-space: nowrap; }
.topbar__clock .icon { color: var(--muted); }
.topbar__tool {
  display: inline-flex; align-items: center; gap: 8px; min-height: var(--control-h); padding: 0 12px;
  border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--ink-2);
  font: 400 14px/1.2 var(--sans); text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.topbar__tool .icon { color: var(--muted); transition: color var(--dur-fast) var(--ease); }
.topbar__tool:hover { background: var(--surface-hover); color: var(--ink); }
.topbar__tool:hover .icon { color: var(--accent-text); }
.topbar__sep { width: 1px; height: 22px; margin: 0 8px; background: var(--line-strong); }
/* На узком десктопе (≤1100) часы уходят первыми: они наименее нужны, а без них шапка со всеми
   инструментами и переключателем темы перестаёт распирать документ вбок */
@media (max-width: 1100px) {
  .topbar__clock, .topbar__tool .topbar__tool-text { display: none; }
  /* 901–1100: «Обновить» и «Справка» — значками (подсказка в title): их текст съедал место заголовка («Проект YODA / Монито…») */
  .topbar__tool { padding: 0 10px; }
}
.topbar__user { max-width: 320px; }
.topbar__user .topbar__user-text { overflow: hidden; text-overflow: ellipsis; }
.topbar__user .topbar__chevron { width: 16px; height: 16px; }

/* ── «Смотреть как роль» (этап 22): плашка под шапкой ─────────────
   Липнет сразу под шапкой (та сама липнет к top: 0 с z-index 20): выше контента, но ниже шапки, шторки (29–30),
   тоста (40), меню (45) и диалогов (верхний слой). Фон обёртки непрозрачный (--bg): полупрозрачная «warn-soft»
   плашка иначе просвечивала бы прокручиваемым под ней контентом. Движение — по Motion AI Kit (MCP motion и motion-plus,
   24.09.2026), чистым CSS: только opacity и transform (композитор; у CSS animation слой выделяется сам — will-change
   не нужен), без перелёта — интерфейс рабочий, не игровой:
     * вход — 180 мс по --ease (замедление без перелёта), один раз на загрузку страницы;
     * смена состояния «идёт → закончился» — узел плашки тот же: фон и рамка перетекают transition'ом (--dur),
       содержимое проявляется за 200 мс (linear) и досаживается на 4 px пружиной без отскока — generate-css-easing
       {kind: spring, duration: 0.2, bounce: 0} → 400 мс linear(…) (перцептивно 0,2 с, хвост — дотяжка);
   prefers-reduced-motion гасит всё это (конец файла). */
#preview-banner {
  position: sticky; top: var(--topbar-h); z-index: 19;
  padding: 4px var(--content-pad) 8px;
  background: var(--bg);
}
#preview-banner .banner { margin: 0; transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease); }
/* Значок — рядом с текстом и на 320: у общей плашки основа текста 260 px, и значок уезжал на отдельную строку */
#preview-banner .banner__text { flex-basis: 200px; }
#preview-banner .banner--row { animation: preview-in 180ms var(--ease); }
#preview-banner .banner__hint { font-variant-numeric: tabular-nums; }
/* Заголовок: «Вы смотрите как: Оператор» — жирным, область и окно — тем же цветом, но легче: глаз цепляется за роль */
#preview-banner .preview-banner__facts { font-weight: 500; }
/* Полный список проектов — в подсказке заголовка (title), когда в нём «… и ещё N» */
#preview-banner .banner__title[title] { cursor: help; }
#preview-banner .banner--ended > * {
  animation:
    preview-swap-fade 200ms linear both,
    preview-swap-settle 400ms linear(0, 0.2175, 0.5207, 0.7361, 0.8631, 0.9317, 0.9668, 0.9842, 0.9926, 0.9966, 0.9984, 0.9993, 1) both;
}
@keyframes preview-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
@keyframes preview-swap-fade { from { opacity: 0; } }
@keyframes preview-swap-settle { from { transform: translateY(-4px); } }
/* Липкая плашка не закрывает цели прокрутки и фокуса: документ отступает сверху на её высоту (--preview-h ставит admin.js
   через ResizeObserver; без плашки — 0). Шапку правило не учитывает, как и прежде: у целей под неё свой scroll-margin-top */
html { scroll-padding-top: var(--preview-h, 0px); }
/* Значок учётной записи в шапке — тем же жёлтым: на телефоне подпись «владелец → оператор» скрыта, а плашка уезжает */
body.is-preview #topbar-user > .icon:first-child, body.is-preview #topbar-user:hover > .icon:first-child { color: var(--warn); }
/* Широкий десктоп (от 1101 px): «Степнов К.А. · владелец → оператор» длиннее обычной подписи, и в 320 px роль просмотра
   резалась многоточием — даём 420. На 901–1100 место нужнее заголовку экрана: там 320, полная подпись — в title кнопки */
@media (min-width: 1101px) { body.is-preview .topbar__user { max-width: 420px; } }
/* Меню → «Смотреть как…»: пока грузится список проектов для диалога, кнопка учётной записи занята (busy) — значок мерцает */
.topbar__user.is-busy { cursor: progress; }
.topbar__user.is-busy > .icon:first-child { animation: preview-wait 700ms var(--ease) infinite alternate; }
@keyframes preview-wait { to { opacity: 0.35; } }

.icon-button {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--control-h); height: var(--control-h); flex: none;
  border: 0; border-radius: var(--radius-sm);
  background: transparent; color: var(--muted); cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.icon-button:hover, .icon-button[aria-expanded='true'] { background: var(--surface-hover); color: var(--accent-text); }
.icon-button:active { transform: scale(0.94); transition-duration: 60ms; }
.icon-button--small { width: 32px; height: 32px; }
/* Переключатель темы — дорожка на две остановки: светлая (слева) · тёмная (справа). Режим читается
   по положению бегунка, а не только по глифу. Ход бегунка — 200 мс без перелёта на общих токенах (решение владельца
   10.09: пружина 650 мс с перелётом прохода 07.09 для переключателя была долгой). Глиф въезжает поворотом и затуханием.
   prefers-reduced-motion гасит
   и то, и другое (общее правило в конце файла). Кнопка — один <button>: нажатие переключает светлую и тёмную. */
.theme-toggle {
  position: relative; flex: none; width: 52px; height: 30px; padding: 0;
  border: 1px solid var(--line-strong); border-radius: 999px;
  background: var(--surface-2); cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.theme-toggle:hover { border-color: var(--accent-line); background: var(--surface-hover); }
.theme-toggle:active { transform: none; }
.theme-toggle__track { position: absolute; inset: 0; display: block; }
.theme-toggle__thumb {
  position: absolute; top: 3px; left: 3px; display: flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--surface); border: 1px solid var(--line-strong); color: var(--ink-2);
  box-shadow: var(--shadow-card);
  transition: transform var(--dur) var(--ease);
}
.theme-toggle[data-mode='light'] .theme-toggle__thumb { transform: translateX(0); }
.theme-toggle[data-mode='dark'] .theme-toggle__thumb { transform: translateX(22px); }
/* Цвет глифа на наведении — без перехода: color в одном transition с transform опускал тир бегунка до C (MotionScore) */
.theme-toggle:hover .theme-toggle__thumb { color: var(--accent-text); border-color: var(--accent-line); }
.theme-toggle .theme-toggle__icon { width: 14px; height: 14px; }
/* Морфинг глифа на каждом нажатии без чтения раскладки: admin.js чередует два одинаковых @keyframes — смена animation-name
   запускает анимацию заново. getAnimations() для перезапуска пересчитывал раскладку (трасса), void offsetWidth у <svg> не делал ничего */
.theme-toggle__icon--swap-a { animation: theme-morph-a var(--dur) var(--ease); }
.theme-toggle__icon--swap-b { animation: theme-morph-b var(--dur) var(--ease); }
@keyframes theme-morph-a { 0% { transform: rotate(-60deg) scale(0.6); opacity: 0; } 100% { transform: rotate(0) scale(1); opacity: 1; } }
@keyframes theme-morph-b { 0% { transform: rotate(-60deg) scale(0.6); opacity: 0; } 100% { transform: rotate(0) scale(1); opacity: 1; } }
/* Смена темы (theme.js): на два кадра переходы цвета выключены — иначе кнопки и пункты меню перекрашивались с задержкой поверх
   мгновенно сменившегося фона. Бегунок переключателя свой переход сохраняет */
.theme-switching *:not(.theme-toggle__thumb), .theme-switching *::before, .theme-switching *::after { transition: none !important; }

.content { flex: 1; min-width: 0; width: 100%; max-width: var(--content-max); padding: 12px var(--content-pad) 48px; }

.screen--enter { animation: screen-enter var(--dur) var(--ease); }
@keyframes screen-enter { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.screen--enter .metric, .screen--enter .kpi, .screen--enter .stat, .screen--enter .project-row { animation: screen-enter var(--dur) var(--ease) both; }
.screen--enter :is(.metric, .kpi, .stat, .project-row):nth-child(2) { animation-delay: 30ms; }
.screen--enter :is(.metric, .kpi, .stat, .project-row):nth-child(3) { animation-delay: 60ms; }
.screen--enter :is(.metric, .kpi, .stat, .project-row):nth-child(4) { animation-delay: 90ms; }
.screen--enter :is(.metric, .kpi, .stat, .project-row):nth-child(5) { animation-delay: 120ms; }
.screen--enter :is(.metric, .kpi, .stat, .project-row):nth-child(n+6) { animation-delay: 150ms; }

.screen__head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 16px; margin-top: 8px; }
.screen__title { margin: 0; font-size: 26px; line-height: 1.2; font-weight: 700; color: var(--ink); letter-spacing: -0.01em; }
.screen__meta { font-size: 13px; color: var(--muted); }
.screen__lead { margin: 4px 0 0; font-size: 14px; color: var(--muted); }
.screen__note { margin: 12px 0 0; font-size: 13px; color: var(--muted); }
.screen__action { margin-left: auto; }
.screen__updated { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; color: var(--muted); }

/* ── Всплывающее меню (⋮, проект, пользователь с группой «Настройки») ─── */

.menu {
  position: fixed; z-index: 45; min-width: 200px; max-width: 320px; padding: 6px;
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius);
  box-shadow: var(--shadow); animation: menu-in var(--dur-fast) var(--ease);
  display: flex; flex-direction: column; overscroll-behavior: contain;
}
@keyframes menu-in { from { opacity: 0; transform: translateY(-4px) scale(0.98); } to { opacity: 1; transform: none; } }
.menu__item {
  display: flex; align-items: center; gap: 8px; width: 100%; min-height: 36px; padding: 0 8px;
  border: 0; border-radius: var(--radius-xs); background: transparent; color: var(--ink-2);
  font: 400 14px/1.2 var(--sans); text-align: left; cursor: pointer; text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.menu__item:hover, .menu__item:focus-visible { background: var(--surface-hover); color: var(--ink); outline: none; }
.menu__item:disabled { color: var(--disabled); cursor: not-allowed; }
.menu__item:disabled:hover { background: transparent; color: var(--disabled); }
.menu__item--danger { color: var(--danger); }
.menu__item--danger:hover { background: var(--danger-soft); color: var(--danger); }
.menu__item--selected { color: var(--accent-text); }
.menu__icon { color: var(--muted); }
.menu__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.menu__hint { font-size: 12px; color: var(--muted); }
.menu__sep { display: block; height: 1px; margin: 6px 4px; background: var(--line); }
.menu__heading { padding: 6px 8px 2px; font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
/* Заголовок-имя в меню пользователя: «Степнов К.А. · владелец» обычным регистром */
.menu__heading--plain { padding: 8px 8px 6px; font-size: 13px; letter-spacing: 0; text-transform: none; color: var(--ink); }
.menu__swatch { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 6px; font-size: 11px; font-weight: 700; color: #fff; flex: none; }

/* ── Вход: карточка по центру, логотип, три шага ────────────────── */

.login { display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 48px 20px; }
.login__card {
  width: 100%; max-width: 480px; padding: 32px 32px 24px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-strong);
}
/* Брендовая зона входа — часть карточки, а не отдельная плашка. Раньше здесь лежал прямоугольник
   #11130f/#2a2a22 мимо системы токенов: в светлой теме на белой карточке он читался инородным пятном.
   Знак (круг с глифом) несёт собственный тёмный диск и стоит на любом фоне, а темнеет/светлеет только
   надпись — поэтому вместо подложки берём вариант логотипа по теме. Высота фиксирована: при смене шага
   (код 2FA, ошибка, восстановление пароля) зона не подпрыгивает. */
.login__brand { position: relative; display: flex; justify-content: center; align-items: center; min-height: 88px; margin: 0 0 24px; }
.login__logo { width: 250px; max-width: 100%; height: auto; display: block; }
[data-theme='light'] .login__logo--dark, .login__logo--light { display: none; }
[data-theme='light'] .login__logo--light { display: block; }
/* Переключатель темы здесь — ровно тот же, что в шапке приложения: никаких особых цветов */
.login__theme { position: absolute; top: 0; right: 0; }
/* На 320–360 логотип 250 px доходил до бегунка темы и хвост надписи уходил под него — узкий экран получает логотип 200 px */
@media (max-width: 360px) { .login__logo { width: 200px; } }
.login__title { margin: 0; font-size: 24px; color: var(--ink); text-align: center; }
.login__hint { margin: 6px 0 20px; font-size: 13px; color: var(--muted); text-align: center; }
.login__card > form { animation: screen-enter var(--dur) var(--ease); }
/* Отступ между полями — только у собственных форм карточки входа. Не «.login .field-group»: под шлюзом второго фактора
   внутрь карточки попадает чужой блок (карточка «Двухфакторная защита» с экрана «Безопасность»), и общий отступ ломал
   там ряды «поле + кнопка» (.field-row). */
.login__card > form > .field-group { margin-bottom: 12px; }
.login__card > form > .check { margin: 6px 0 8px; }
.login .button--wide + .button--wide { margin-top: 8px; }

.stepper { display: flex; align-items: flex-start; margin: 20px 0 24px; padding: 0; list-style: none; }
.stepper__step { position: relative; flex: 1; display: flex; flex-direction: column; align-items: center; gap: 8px; min-width: 0; text-align: center; }
.stepper__step:not(:last-child)::after {
  content: ''; position: absolute; top: 15px; left: calc(50% + 20px); right: calc(-50% + 20px); height: 2px;
  background: var(--line-strong); transition: background-color var(--dur) var(--ease);
}
.stepper__step--done:not(:last-child)::after { background: var(--ok); }
.stepper__step--last::after { display: none; }
.stepper__dot {
  display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 50%;
  border: 2px solid var(--line-strong); background: var(--surface-2); color: var(--muted);
  font-size: 13px; font-weight: 700;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.stepper__step--current .stepper__dot { border-color: var(--accent); background: var(--accent); color: var(--on-accent); transform: scale(1.06); }
.stepper__step--done .stepper__dot { border-color: var(--ok); background: var(--ok-soft); color: var(--ok); }
.stepper__label { font-size: 12px; color: var(--muted); }
.stepper__step--current .stepper__label { color: var(--ink); font-weight: 500; }
.stepper__step--done .stepper__label { color: var(--ink-2); }
.login__done { display: grid; gap: 1px; margin: 0 0 16px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--line); overflow: hidden; }
.login__done-row { display: flex; align-items: center; gap: 8px; min-width: 0; margin: 0; padding: 8px 12px; background: var(--surface-2); font-size: 13px; color: var(--ink); overflow-wrap: anywhere; }
/* Почта длиной 40–60 знаков на 320 не помещается в строку: без min-width: 0 flex-элемент не сжимается и текст обрезался
   overflow: hidden карточки без многоточия — теперь переносится по любому месту */
.login__done-row > * { min-width: 0; }
.login__step-title { margin: 0 0 4px; font-size: 16px; color: var(--ink); }
.login__links { margin: 12px 0 0; text-align: center; }
.login__links .link-button { margin: 0; }
.field-wrap { position: relative; }
/* Модификаторы полей — с двойным классом: components.css грузится позже и его базовое .field { padding; font; min-height }
   той же специфичности перебивало .field--password и .field--code — отступ под «глаз» и крупный код 2ФА не применялись */
.field.field--password { padding-right: 48px; }
.field-eye {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%); width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center; border: 0; border-radius: var(--radius-xs);
  background: transparent; color: var(--muted); cursor: pointer; transition: color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.field-eye:hover, .field-eye[aria-pressed='true'] { color: var(--accent-text); background: var(--accent-soft); }
/* Автозаполнение менеджера паролей: Chrome красит поле своим светлым фоном — на тёмной карточке входа это белый блок.
   Перекрашиваем только заливку и цвет текста (сама подстановка значения не трогается). */
.login__card .field:-webkit-autofill,
.login__card .field:-webkit-autofill:hover {
  -webkit-text-fill-color: var(--ink);
  -webkit-box-shadow: inset 0 0 0 1000px var(--field-bg);
  caret-color: var(--ink);
}
/* В фокусе заливка не должна съесть штатное свечение .field:focus — держим обе тени */
.login__card .field:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--ink);
  -webkit-box-shadow: var(--accent-glow), inset 0 0 0 1000px var(--field-bg);
  caret-color: var(--ink);
}
.field.field--code { font-size: 24px; letter-spacing: 0.5em; text-align: center; padding-left: calc(12px + 0.5em); min-height: 54px; }
.field.field--code::placeholder { letter-spacing: 0.5em; font-size: 20px; }
.login__card > form > .segment { margin-bottom: 16px; }

/* ── Права: скрываем элементы записи для ролей «только чтение» ─── */

body:not(.can-content-write) .needs-content-write { display: none !important; }
body:not(.can-user-create) .needs-user-create { display: none !important; }
body:not(.can-devices-write) .needs-devices-write { display: none !important; }
body:not(.can-telemetry-write) .needs-telemetry-write { display: none !important; }
body:not(.can-settings-write) .needs-settings-write { display: none !important; }
body:not(.can-servers-manage) .needs-servers-manage { display: none !important; }
body:not(.can-audit-read) .needs-audit-read { display: none !important; }
body:not(.can-consult-issue) .needs-consult-issue { display: none !important; }
/* Простой режим окна консультанта (auth."user".consult_mode): выбор компонента, «Глубокий разбор» и
   «Разобрать глубже» скрыты — сотрудник выбирает продукт и описывает проблему словами (этап 18) */
body.consult-simple .needs-consult-advanced { display: none !important; }

/* ── Адаптив каркаса: до 900 px сайдбар — шторка слева, шапка со значком меню ─── */

@media (pointer: coarse) {
  .button--row { min-height: var(--control-h); }
  /* 16 px — порог, ниже которого iOS Safari приближает страницу при вводе. Двойной класс — чтобы перебить базовое
     .field { font: 14px } из components.css (грузится позже); код 2ФА крупнее и живёт своим правилом */
  .field:not(.field--code) { font-size: 16px; }
  .field.field--password { padding-right: 52px; }
  .icon-button--small { width: var(--control-h); height: var(--control-h); }
  .field-eye { width: 40px; height: 40px; }
  .link-button, .nav-sub__title, .menu__item { min-height: var(--control-h); }
  /* Ссылки карточки входа («Забыли пароль?», «← Назад», «Выйти») — единственные мелкие цели на экране входа: до --touch */
  .login__links .link-button { min-height: var(--touch); padding: 0 12px; }
  /* Пальцем: логотип, переключатель проекта, кнопки-иконки шапки и шторки — не ниже 44 */
  .brand { min-height: var(--touch); }
  .project-switch { min-height: var(--touch); }
  .icon-button { width: var(--touch); height: var(--touch); }
  /* Переключатель темы остаётся дорожкой 52×30, а зона нажатия дотягивается до 44 невидимым полем */
  .theme-toggle::after { content: ''; position: absolute; inset: -7px -2px; }
  /* Ссылки в заголовках карточек («Все алерты», «Открыть») — строчные, но с высокой зоной нажатия без сдвига макета */
  .card__link { display: inline-flex; align-items: center; min-height: var(--touch); margin-top: -10px; margin-bottom: -10px; }
  .menu__item { min-height: var(--touch); }
  /* Подпункты «Проекта YODA» в шторке: 38 px на десктопе, под палец — 44 */
  .nav-sub .nav-item { min-height: var(--touch); }
  .field-eye { width: var(--touch); height: var(--touch); right: 0; }
}

@media (min-width: 901px) {
  #nav-toggle, .sidebar__close { display: none !important; }
}

/* Широкие экраны (2K и больше): контент растёт вместе с окном, а не упирается в 1440 px —
   иначе на 2560 px справа остаётся ~900 px пустоты. Предел 2240 px оставлен для ультрашироких. */
@media (min-width: 1600px) {
  :root { --content-pad: 32px; }
  /* Владелец 01.09.2026: на 2K любой предел оставляет поле справа — на широких экранах предела нет вовсе */
  .content { max-width: none; }
}
@media (min-width: 2000px) {
  :root { --content-pad: 40px; }
}

@media (max-width: 1100px) {
  :root { --content-pad: 20px; }
}

@media (max-width: 900px) {
  .shell { display: block; }
  /* Ход шторки — пружина Motion+ без перелёта (generate-css-easing: spring, 0.3 с на глаз, bounce 0; 600 мс вместе
     с успокоением), запасная кривая для браузеров без linear() — строкой выше. Тень живёт на ::after и проявляется
     через opacity: transition box-shadow с размытием 80 px перерисовывал бы полосу 300×100vh каждый кадр (paint),
     а opacity и transform идут на композиторе (MotionScore S). */
  .sidebar {
    /* 100dvh — видимая высота: в iOS Safari и Chrome Android 100vh выше экрана, нижние пункты шторки уходили под панель браузера */
    position: fixed; top: 0; left: 0; bottom: 0; z-index: 30; height: 100vh; height: 100dvh; width: min(300px, 86vw);
    transform: translateX(-104%);
    transition: transform var(--dur) var(--ease);
    transition: transform 600ms linear(0, 0.1061, 0.3018, 0.4922, 0.6466, 0.7613, 0.8422, 0.8975, 0.9342, 0.9582, 0.9737, 0.9836, 0.9898, 0.9937, 0.9961, 0.9976, 0.9985, 0.9991, 1, 1);
  }
  .sidebar::after {
    content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
    box-shadow: var(--shadow-strong); opacity: 0; transition: opacity var(--dur) var(--ease);
  }
  .sidebar--open { transform: none; }
  .sidebar--open::after { opacity: 1; }
  /* Уход шторки короче прихода и с разгоном (ease-in): закрытие не тянется 600 мс пружиной и заканчивается вместе с затемнением */
  .sidebar:not(.sidebar--open) { transition: transform 220ms cubic-bezier(0.4, 0, 1, 1); }
  .sidebar__backdrop { position: fixed; inset: 0; z-index: 29; background: var(--backdrop); animation: backdrop-in var(--dur) var(--ease); transition: opacity var(--dur) var(--ease); }
  .sidebar__backdrop--leaving { opacity: 0; pointer-events: none; }
  .sidebar__close { position: absolute; top: 14px; right: 10px; }
  .topbar { padding: 0 12px; gap: 2px; }
  .topbar__clock, .topbar__tool .topbar__tool-text, .topbar__sep, .topbar__user .topbar__user-text, .topbar__user .topbar__chevron { display: none; }
  .topbar__tool { padding: 0 8px; min-width: var(--touch); justify-content: center; }
  .topbar__title, .topbar__title b { font-size: 15px; color: var(--ink); }
  .topbar__context { color: var(--muted); }
  .content { padding: 8px 12px 48px; }
  #preview-banner { padding: 4px 12px 8px; }
  .screen__title { font-size: 22px; }
  .login { padding: 24px 12px; }
  .login__card { padding: 24px 16px; }
  .stepper__label { font-size: 11px; }
  .stepper__step:not(:last-child)::after { left: calc(50% + 18px); right: calc(-50% + 18px); }
  .field.field--code { font-size: 22px; }
  .menu { max-width: calc(100vw - 16px); }
}
/* Телефон: в шапке — только название экрана, контекст проекта виден в шторке. Прежде «Проект ТИША / …» съедал место,
   и многоточие срезало именно название экрана */
@media (max-width: 640px) { .topbar__context { display: none; } }
/* ≤ 480: «Справка» уходит из шапки (документация остаётся пунктом меню) — 46 px заголовку */
@media (max-width: 480px) { #topbar-help { display: none; } }
/* Телефон и низкий экран (альбомная ориентация, окно в пол-экрана): плашка в 3–4 строки, прилипшая к верху вместе
   с шапкой, съедала бы треть высоты на каждом экране — здесь она стоит в начале страницы и уезжает с прокруткой, а о режиме
   дальше напоминает жёлтый значок учётной записи в шапке. Отступ прокрутки под неё тогда не нужен */
@media (max-width: 640px), (max-height: 520px) {
  #preview-banner { position: static; }
  html { scroll-padding-top: 0; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
  /* Плашка просмотра появляется сразу, без сдвига (общее правило выше её уже гасит — строка закрепляет намерение) */
  #preview-banner .banner, #preview-banner .banner--ended > * { animation: none !important; }
  /* Индикаторы работы — функциональная анимация: застывшая дуга без подписи читалась как сломанная кнопка */
  .button.is-busy::after, .cell-loading::after, .consult-composer__send.is-busy::after { animation: spin 1.4s linear infinite !important; }
  /* Занятая кнопка учётной записи — мерцание без движения, тоже индикатор работы */
  .topbar__user.is-busy > .icon:first-child { animation: preview-wait 700ms linear infinite alternate !important; }
}
