@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(6px)
  }

  to {
    opacity: 1;
    transform: translateY(0)
  }
}

/* ── FOUC shield для styled-select / styled-date-picker ────────────────
   Скрипты загружаются через defer, поэтому DOM рендерится с native
   <select>/<input type="date"> до запуска JS — на медленных рефрешах
   проскакивает «дд.мм.гггг» и неоформленные селекты.
   Прячем native-контролы пока styled-* JS не пометит их dataset-init.
   Использовать .no-styled на самом элементе чтобы opt-out (для случаев
   когда нужно показать сырой контрол). После init JS прячет native сам,
   а .ss-btn / .sdp-btn остаются видимыми. */
select.form-control:not([data-styled-select-init]):not(.no-styled):not([multiple]),
input[type="date"].form-control:not([data-sdp-init]):not(.no-styled),
input[type="month"].form-control:not([data-sdp-init]):not(.no-styled),
/* Универсальная страховка: ЛЮБОЙ input[type="date"]/type="month" без класса
   form-control тоже скрываем до hydration (например, .sal-period > input
   на /admin/salary, .td-period на team_detail — там input без form-control).
   Используем .no-styled чтобы opt-out. */
input[type="date"]:not([data-sdp-init]):not(.no-styled),
input[type="month"]:not([data-sdp-init]):not(.no-styled) {
  opacity: 0 !important;
  pointer-events: none;
  /* Сохраняем layout, чтобы кнопки не "прыгали" когда JS заменяет. */
}

.toggle-switch {
  position: relative;
  width: 36px;
  height: 20px;
  flex-shrink: 0;
  display: inline-block
}

.toggle-switch input {
  opacity: 0;
  width: 0;
  height: 0;
  position: absolute
}

.toggle-track {
  position: absolute;
  inset: 0;
  background: rgba(148, 163, 184, .25);
  border-radius: 20px;
  cursor: pointer;
  transition: background .2s
}

.toggle-track::after {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 14px;
  height: 14px;
  background: #fff;
  border-radius: 50%;
  transition: transform .2s;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .15)
}

.toggle-switch input:checked+.toggle-track {
  background: var(--primary-gradient)
}

.toggle-switch input:checked+.toggle-track::after {
  transform: translateX(16px)
}

/* ══════════════════════════════════════════════════════════════════════════
 * INTER (self-hosted, Google Fonts v20)
 *
 * Жалоба пользователя: «шрифты вечно слетают и неполностью прогружаются».
 *
 * Корень проблемы (до этого фикса):
 *   • 5 @font-face блоков указывали на ОДИН WOFF2 файл (Inter v18) на
 *     fonts.gstatic.com — каждый weight делал свой request. Если CDN
 *     возвращал 503 на любом из них → fallback на system Arial.
 *   • Параллельно в layout.html подключался отдельный CSS-файл
 *     fonts.googleapis.com/css2?family=Inter:wght@... → ещё 7 subset'ов
 *     v20 файлов. Получался dual-load v18 + v20, race + 503 шанс.
 *   • display=optional на layout-CSS — после ~100мс fallback навсегда.
 *
 * Фикс:
 *   • Self-host 3 файла в /static/fonts/inter/ (cyrillic + latin + latin-ext).
 *     Google Fonts v20 разбит на unicode-range subsets — каждый subset это
 *     variable-axis WOFF2 (один файл на ВСЕ weight'ы 400-700).
 *   • Один файл-источник на subset, никаких race-condition'ов на CDN.
 *   • font-display: swap — текст виден сразу с fallback, потом swap на Inter
 *     (минимум FOIT, контролируемый FOUT).
 *   • Алиасы SF Pro Display/Text/SF Pro теперь резолвятся на ту же self-hosted
 *     Inter — никаких внешних HTTP. */

/* — Inter (variable, weight 400-700) — латиница, кириллица, лат-ext — */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/static/fonts/inter/inter-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/static/fonts/inter/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/static/fonts/inter/inter-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* — Aliases: «SF Pro Display», «SF Pro Text», «SF Pro» → ту же Inter.
 *   `local()` сначала ищет системный SF Pro (macOS) — иначе берёт нашу Inter
 *   (которая теперь self-hosted, без CDN-fallback risks).                  */
@font-face {
  font-family: 'SF Pro Display';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: local('SF Pro Display'), local('SFProDisplay-Regular'),
       local('Inter'), local('Inter-Regular'),
       url('/static/fonts/inter/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153;
}
@font-face {
  font-family: 'SF Pro Display';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: local('SF Pro Display'), local('SFProDisplay-Regular'),
       local('Inter'), local('Inter-Regular'),
       url('/static/fonts/inter/inter-cyrillic.woff2') format('woff2');
  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'SF Pro Text';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: local('SF Pro Text'), local('SFProText-Regular'),
       local('Inter'), local('Inter-Regular'),
       url('/static/fonts/inter/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153;
}
@font-face {
  font-family: 'SF Pro Text';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: local('SF Pro Text'), local('SFProText-Regular'),
       local('Inter'), local('Inter-Regular'),
       url('/static/fonts/inter/inter-cyrillic.woff2') format('woff2');
  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'SF Pro';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: local('SF Pro'), local('SFPro-Regular'),
       local('Inter'), local('Inter-Regular'),
       url('/static/fonts/inter/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153;
}
@font-face {
  font-family: 'SF Pro';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: local('SF Pro'), local('SFPro-Regular'),
       local('Inter'), local('Inter-Regular'),
       url('/static/fonts/inter/inter-cyrillic.woff2') format('woff2');
  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

:root {
  /* ── Бренд-палитра CRM ────────────────────────────────────────────────
   * Главный визуальный якорь — градиент blue-500 → indigo-500
   * (совпадает с .chat-bubble.own и кнопкой email «Написать»).
   *
   *   --primary-gradient   — для backgrounds (кнопки, бейджи, бабблы,
   *                          шапки виджетов, активные чипы, иконки-кружки).
   *   --primary-grad-hover — на 1 шаг темнее, для hover-состояний.
   *   --primary             — solid mid-tone из того же градиента (≈ #4f6ae8),
   *                          используется для ссылок, иконок, текста-акцента,
   *                          бордеров. Раньше был жёсткий blue-700 (#1d4ed8) —
   *                          выпадал из синей-индиго гаммы интерфейса.
   *   --primary-hover       — для активных/hover-text. */
  --primary-gradient: linear-gradient(135deg, #3b82f6 0%, #6366f1 100%);
  --primary-grad-hover: linear-gradient(135deg, #2563eb 0%, #4f46e5 100%);
  --primary: #4f6ae8;
  --primary-hover: #3b4fc6;
  --primary-light: #eef2ff;
  --primary-border: #c7d2fe;
  --dark: #1e293b;
  --dark-2: #0f172a;
  --gray: #64748b;
  --gray-light: rgba(148, 163, 184, .18);
  --light: #f0f4ff;
  --white: #fff;
  --sidebar-bg: #0f172a;
  --sidebar-hover: rgba(59, 130, 246, .1);
  --sidebar-active: rgba(59, 130, 246, .18);
  --sidebar-text: #94a3b8;
  --sidebar-width: 238px;
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .03);
  --shadow: 0 4px 16px rgba(59, 130, 246, .06), 0 2px 6px rgba(0, 0, 0, .04);
  --shadow-lg: 0 12px 40px rgba(59, 130, 246, .08), 0 4px 12px rgba(0, 0, 0, .06);
  --radius-sm: 8px;
  --radius: 14px;
  --radius-lg: 20px;
  /* SF Pro как основной шрифт CRM.
   * На Mac/iOS возьмётся системный SF Pro (через -apple-system /
   *   BlinkMacSystemFont).
   * На Windows / Linux Apple SF Pro не предустановлен, и без подмены
   *   браузер сваливался на `system-ui` → Segoe UI → визуально совсем
   *   другой шрифт, чем у дизайнера на Mac. Inter (Rasmus Andersson)
   *   делался как идеологический клон SF Pro и в большинстве рендеров
   *   неотличим — поэтому ставим его ДО `system-ui` в стеке.
   * Inter подключается web-шрифтом из Google Fonts (см. layout.html
   *   роли admin/manager/client/partner: <link rel="stylesheet"
   *   href="https://fonts.googleapis.com/css2?family=Inter...">),
   *   плюс ниже идёт @font-face для классов «SF Pro Display/Text»,
   *   который алиасит их на тот же Inter — если где-то в template
   *   зашит явный font-family:'SF Pro Display', оно подтянется. */
  --font: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'SF Pro Text', 'SF Pro', 'Inter', system-ui, 'Segoe UI', Roboto, Arial, sans-serif;
  --glass-bg: rgba(255, 255, 255, .95);
  --glass-border: rgba(255, 255, 255, .45);
  --glass-blur: blur(16px)
}

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

html {
  font-size: 14px;
  scrollbar-gutter: stable
}

body {
  font-family: var(--font);
  background: linear-gradient(135deg, #eef2ff 0, #f0f4ff 40%, #f8fafc 100%);
  background-attachment: fixed;
  color: var(--dark);
  line-height: 1.6;
  min-height: 100vh;
  /* Глобальная страховка от horizontal scroll при slide-in модалках
     (profile-modal, notif-panel и т.п.) — даже если у них transform:translateX,
     любой forgotten element с right:-Npx больше не будет двигать layout. */
  overflow-x: hidden;
}
/* Глобальный scrollbar-gutter — резервируем место под вертикальный
   scrollbar, чтобы при появлении/исчезновении контента layout не прыгал.
   overflow-x:hidden на html — двойная страховка к body, т.к. некоторые
   элементы с position:fixed transform могут давать viewport overflow
   на уровне html. */
html { scrollbar-gutter: stable; overflow-x: hidden; }
/* Изоляция layout-контейнера: изменения внутри не reflow-ят родителя.
   Резко уменьшает CLS на страницах с динамическим контентом (cb-benef-grid,
   sal-*, td-*). */
.main-content { contain: layout style; }

/* ВАЖНО: contain: layout style создаёт containing block для position:fixed
   потомков. Любая .modal-overlay внутри .main-content анкорилась к нему
   (offset от topbar), а не к viewport → визуально модалка «уезжала вниз».
   Снимаем contain только пока модалка реально открыта (.open) — :has()
   динамически реагирует на изменение класса. CLS-выигрыш в нормальном
   состоянии сохраняется; во время модалки CLS не важен (она перекрывает
   layout). История: «Окна подтверждений должны отображаться посредине».
   Также покрывает .crm-confirm-overlay (мини-confirm) и dropdowns
   (.bank-dropdown / .integ-dropdown / .change-bank-dropdown — JS-positioned
   через getBoundingClientRect viewport-coords; сборщик их закрепил бы
   к .main-content и они уезжали бы вправо на величину margin-left).
   Жалоба: «дропдаун добавить банк вызывается не возле кнопки». */
.main-content:has(.modal-overlay.open),
.main-content:has(.crm-confirm-overlay),
.main-content:has(.bank-dropdown.open),
.main-content:has(#propose-list-overlay.is-open) {
  contain: none;
}

/* Защита от bubble'инга wheel-scroll внутри overlay'ев — без неё страница
   под модалкой могла прокручиваться, когда юзер крутил wheel над панелью.
   body.style.overflow=hidden блокирует scroll-bar, но wheel-events всё
   равно бубл'ились на main-content (у неё свой scrollable содержит).
   overscroll-behavior:contain останавливает inertial scroll на границе. */
#propose-list-overlay,
#propose-choice-overlay,
.modal-overlay,
.crm-confirm-overlay {
  overscroll-behavior: contain;
}

/* ── Late-injected fab'ы (calc-widget.js, reminder-stickers.js, chat-widget):
   создаются через JS-инжекцию после DOMContentLoaded. Раньше визуально
   «выезжали» справа в случайные моменты → выглядело как дёрганье.
   Теперь все они изначально opacity:0, плавно fade-in за 180ms через
   transition. Заодно крпеит «появление» dock'а единственным анимирующим
   событием — без отвлекающих jumps. */
#calc-fab, #chat-fab, .rsn-fab, .ctb-tail {
  transition: opacity .22s ease-out, transform .22s ease-out;
}
html:not(.app-hydrated) #calc-fab,
html:not(.app-hydrated) #chat-fab,
html:not(.app-hydrated) .rsn-fab {
  opacity: 0 !important;
  pointer-events: none !important;
}

/* Reveal-when-ready блока заявок (см. applications.html). Контейнеры списка/
   канбана рендерятся с инлайн opacity:0; JS-reveal плавно показывает их после
   гидрации. Этот CSS — FAILSAFE: если JS-reveal не отработал (сбой / pjax без
   перезапуска скриптов), анимация принудительно покажет элемент через 1.8с.
   Анимация перекрывает инлайн opacity:0 (CSS-animations > inline). После
   JS-reveal атрибут снимается → правило перестаёт матчиться, держится inline
   opacity:1. */
@keyframes appsPrehideReveal { to { opacity: 1; } }
[data-apps-prehide] { animation: appsPrehideReveal 0.01s linear 1.8s forwards; }

a {
  color: var(--primary);
  text-decoration: none
}

a:hover {
  color: var(--primary-hover)
}

img {
  max-width: 100%
}

::-webkit-scrollbar {
  width: 5px;
  height: 5px
}

::-webkit-scrollbar-track {
  background: transparent
}

::-webkit-scrollbar-thumb {
  background: rgba(100, 116, 139, .2);
  border-radius: 10px
}

::-webkit-scrollbar-thumb:hover {
  background: rgba(100, 116, 139, .35)
}

.app-layout {
  display: flex;
  min-height: 100vh
}

.sidebar {
  /* По UX-запросу «сайдбар уж слишком широкий, сделай на 15% уже» —
     280 → 238px (–15%). main-content имеет flex:1 → автоматически забирает
     освободившиеся 42px (больше места под таблицы/формы). Mobile-overlay
     остаётся 280px (см. mobile.css) — там это off-canvas drawer ширина,
     другой контекст. */
  width: 238px;
  background: linear-gradient(180deg, #0f172a 0%, #111827 50%, #1a1f3d 100%);
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  z-index: 100;
  /* НЕ добавлять width сюда! Анимацию ширины (238↔66) даёт ТОЛЬКО
     `.sidebar.sb-animated { transition: width .25s }` (sb-animated ставится
     +300мс после загрузки). Width в БАЗОВОМ правиле → ширина анимируется и во
     время load-осадки (до sb-animated) → сайдбар «скачет» на refresh. transform
     остаётся для мобильного off-canvas. */
  transition: transform .3s ease;
  border-right: none;
  box-shadow: 4px 0 24px rgba(0, 0, 0, .15)
}

.sidebar-logo {
  padding: 24px 16px 20px;
  border-bottom: 1px solid rgba(255, 255, 255, .08);
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 12px
}

.sidebar-logo-icon {
  display: none
}

.sidebar-logo-img {
  width: 32px;
  height: 32px;
  border-radius: 10px;
  flex-shrink: 0;
  object-fit: contain
}

.sidebar-logo-text {
  color: var(--white);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.2
}

.sidebar-logo-sub {
  color: var(--sidebar-text);
  font-size: 11px;
  font-weight: 400
}

.sidebar-nav {
  flex: 1;
  padding: 16px 12px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-start
}

.nav-section {
  display: none
}

.nav-item {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  padding: 11px 16px;
  color: var(--sidebar-text);
  font-size: 13.5px;
  font-weight: 400;
  cursor: pointer;
  transition: all .25s;
  border-radius: 10px;
  position: relative;
  text-decoration: none;
  margin: 2px 0
}

button.nav-item {
  font-family: inherit;
  font-size: 13.5px;
  color: var(--sidebar-text);
  width: auto;
  text-align: left;
  background: none;
  border: none
}

.nav-item:hover {
  background: rgba(255, 255, 255, .1);
  color: #e2e8f0;
  transform: translateX(2px)
}

.nav-item.active {
  background: linear-gradient(90deg, rgba(59, 130, 246, .28) 0%, rgba(99, 102, 241, .15) 100%);
  color: #fff;
  font-weight: 600;
  border-radius: 10px;
  box-shadow: 0 2px 12px rgba(59, 130, 246, .18), inset 0 0 0 1px rgba(99, 102, 241, .25)
}

.nav-item.active::before {
  display: none
}

/* ═══════════ SIDEBAR CRM-GRADIENT REBRAND ════════════════════════════════
   Перекрашивает сайдбар в основной градиент CRM (#3b82f6 → #6366f1).
   ОТКАТ К ПРЕЖНЕЙ ТЁМНОЙ ГАММЕ: удалить весь этот блок (от «SIDEBAR CRM-
   GRADIENT REBRAND» до «/SIDEBAR CRM-GRADIENT REBRAND»). Оригинальные правила
   (.sidebar bg на ~строке 386, --sidebar-* на ~219, .nav-item:hover/.active
   выше) НЕ изменены → прежняя тёмная гамма вернётся автоматически.
   Бэкап значений также продублирован в static/css/sidebar-color-backup.txt. */
.sidebar {
  background: linear-gradient(180deg, #3b82f6 0%, #6366f1 100%) !important;
}
:root {
  /* --sidebar-bg под градиент → flyout «Сервисы» (background:var(--sidebar-bg)) перекрасится тоже */
  --sidebar-bg: linear-gradient(180deg, #3b82f6 0%, #6366f1 100%);
  --sidebar-text: rgba(255, 255, 255, .84);
  --sidebar-hover: rgba(255, 255, 255, .14);
  --sidebar-active: rgba(255, 255, 255, .22);
}
.nav-item:hover  { background: rgba(255, 255, 255, .14); color: #fff; }
.nav-item.active {
  background: rgba(255, 255, 255, .20);
  color: #fff;
  box-shadow: 0 2px 12px rgba(0, 0, 0, .10), inset 0 0 0 1px rgba(255, 255, 255, .30);
}
.sidebar-logo-sub, .sidebar-user-role { color: rgba(255, 255, 255, .68) !important; }
/* Иконки навигации — белые (на градиенте они currentColor=.84 белый, выглядели тускло). */
.sidebar .nav-item .nav-icon { color: #fff !important; }
.sidebar .nav-item svg.nav-icon[stroke="currentColor"] { stroke: #fff !important; }
.sidebar .nav-item svg.nav-icon[fill="currentColor"]   { fill:   #fff !important; }
/* Иконка вкладки «Заявки» — это PNG-логотип (синий каркасный глобус).
   Перекрашиваем в белый фильтром, чтобы совпадал с белыми line-иконками
   остальных вкладок. brightness(0) → чёрный (альфа сохр.), invert(1) → белый. */
.sidebar .nav-item .nav-icon[src*="logo"] { filter: brightness(0) invert(1) !important; }
/* Бейджи непрочитанных (почта/сообщения) — КРАСНЫЙ с лёгкой прозрачностью
   («красный с прозрачным оверлеем») + белый счётчик + тонкая светлая окантовка.
   Белый бейдж на синем градиенте был незаметен (жалоба). Действует и в
   свёрнутом сайдбаре (там бейдж — угловой dot на иконке; тёмный border
   #0f172a у свёрнутого правила ниже тоже заменён на светлый). */
.sidebar .nav-badge {
  background: rgba(239, 68, 68, .42) !important;   /* прозрачный красный оверлей — не вычурно */
  color: #fff !important;
  border: 1.5px solid rgba(239, 68, 68, .85) !important;   /* красная окантовка */
  box-sizing: border-box;
}
/* Лого — белая закруглённая подложка (обводка). Glow убран по запросу. */
.sidebar-logo-img {
  background: #fff !important;
  padding: 4px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .12);
}
/* Активная вкладка (напр. Заявки) — мягкий левый акцент-бар вместо навязчивой
   полной обводки. Один и тот же box-shadow в покое И при наведении → акцент
   не «пропадает» на hover (жалоба). На hover чуть ярче фон. */
.nav-item.active,
.nav-item.active:hover {
  box-shadow: inset 3px 0 0 0 #fff, 0 2px 10px rgba(0, 0, 0, .10) !important;
}
.nav-item.active:hover { background: rgba(255, 255, 255, .24) !important; }
/* Кнопка «Выйти» убрана из сайдбара (дублирует профиль) — её оверрайды удалены. */
/* Flyout «Сервисы»: фон под градиент (через --sidebar-bg выше) + белые иконки
   (раньше иконки были сине-градиентные — на синем фоне исчезли бы). */
.nav-tools-flyout-global svg.nav-icon,
.nav-tools-flyout-global svg.nav-icon[stroke="currentColor"] { stroke: #fff !important; color: #fff !important; }
.nav-tools-flyout-global svg.nav-icon[fill="currentColor"] { fill: #fff !important; }
/* ═══════════ /SIDEBAR CRM-GRADIENT REBRAND ═══════════════════════════════ */

.nav-item .nav-icon {
  display: block
}

.nav-badge {
  /* Раньше центровка через text-align + line-height — двузначные числа
     (10+, 99+) выглядели вертикально смещённо из-за descender'а шрифта.
     Перешли на inline-flex: центрируется по обеим осям, независимо от
     количества цифр. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: auto;
  background: var(--primary-gradient);
  color: white;
  font-size: 10px;
  font-weight: 700;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  padding: 0;
  line-height: 1;
  box-sizing: border-box
}

/* «Скрыть бейджи-счётчики» — глобальный тоггл из настроек уведомлений.
   Прячем все числовые индикаторы: бейджи навигации, fab-msg-badge у
   чат-FAB'а, ctb-badge'и таскбара, нотиф-стек-бейдж в панели уведомлений.
   Класс ставится на <html>: pre-init из localStorage (см. layout.html
   <head>), окончательное состояние подтверждается из server prefs при
   loadAllNavCounts. Сами уведомления продолжают приходить и
   сохраняться — пользователь видит их в Центре уведомлений. */
html.crm-badges-hidden .nav-badge,
html.crm-badges-hidden #notif-badge,
html.crm-badges-hidden #topbar-notif-badge,
html.crm-badges-hidden #msg-badge,
html.crm-badges-hidden #news-badge,
html.crm-badges-hidden #email-badge,
html.crm-badges-hidden #tasks-badge,
html.crm-badges-hidden #fab-msg-badge,
html.crm-badges-hidden .ctb-badge,
html.crm-badges-hidden .notif-stack-badge,
html.crm-badges-hidden .notif-section-count,
html.crm-badges-hidden .notif-section-unread-dot,
html.crm-badges-hidden .notif-tab-badge,
html.crm-badges-hidden .notif-tab-content-count,
html.crm-badges-hidden .rsn-fab-badge {
  display: none !important;
}

/* ── Плавное появление поповеров правого стека (Калькулятор / Чат / Звонилка)
   + новых стикеров. Жалоба: «Калькулятор, чат, Звонок открываются резко —
   надо плавно, как у стикера». Composite-only (opacity + transform) → GPU,
   не триггерит layout. Калькулятор анимируется через #calc-popup.open
   (он сам display:none↔block), чат/звонилка — через класс .crm-widget-popin
   с reflow-retrigger в их toggle-open ветке (на restore не вешается → нет
   «попа» при каждой загрузке страницы). */
@keyframes crmWidgetPopIn {
  from { opacity: 0; transform: scale(.96) translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.crm-widget-popin { animation: crmWidgetPopIn .19s cubic-bezier(.18,.74,.3,1.06); }
#calc-popup.open  { animation: crmWidgetPopIn .19s cubic-bezier(.18,.74,.3,1.06); }
@media (prefers-reduced-motion: reduce) {
  .crm-widget-popin, #calc-popup.open { animation: none !important; }
}

/* (Reveal-when-ready списка заявок уже реализован через [data-apps-prehide]
   в самом applications.html — инлайн opacity:0 + JS-reveal на DCL+2rAF +
   CSS-фолбэк 1.8s. Отдельный apps-booting слой убран как дублирующий.) */

/* ── Apps-list: липкая шапка таблицы при скролле ───────────────────────────
   Жалоба: «при скролле списка заявок шапка должна оставаться видна».
   Тулбар (поиск/фильтры/вид) уже ВЫШЕ обёртки #apps-table-wrapper → остаётся
   на месте. Обёртке даём max-height → она скроллит строки ВНУТРИ себя по
   вертикали (overflow-y у неё уже auto, т.к. overflow-x:auto принудительно
   делает overflow-y:auto), а thead пиним sticky к её верху → заголовки
   колонок видны при прокрутке. По горизонтали thead скроллит вместе с
   таблицей (top задан, left — нет). 210px ≈ topbar 64 + паддинги + тулбар. */
#apps-table-wrapper { max-height: calc(100vh - 210px); }
#apps-table thead th {
  position: sticky;
  top: 0;
  z-index: 6;
  /* фон уже #f1f5f9 (см. #apps-table th выше) — строки не просвечивают */
}

/* ── Apps-страница статична (без прокрутки страницы) ────────────────────────
   Поднимаем контент выше и убираем лишний скролл (~40px переполнения):
   уменьшаем верх/низ отступы page-content и нижний margin строки продуктов так,
   чтобы (top таблицы + нижний отступ) совпали с резервом max-height (210px) →
   ровно под вьюпорт. Жалоба: «промежуток небольшой, смысла в скролле нет —
   пусть будет статичная страница». Скоуп строго на apps. */
body.page-applications .page-content {
  padding-top: 12px !important;
  padding-bottom: 12px !important;
}
body.page-applications .prod-tabs { margin-bottom: 12px !important; }

/* ── Smooth fade-in/out для badge-индикаторов ─────────────────────────────
   Composite-only анимация (opacity + transform): полностью GPU, не
   триггерит layout/paint. <0.1мс на кадр — для 60fps бюджета (16.6мс)
   практически бесплатно. На perf-mode (слабые GPU) — отключается ниже.
   Жалоба: «всё не дёргано появлялось, а плавно». */
.nav-badge,
#notif-badge,
#topbar-notif-badge,
#msg-badge,
#news-badge,
#email-badge,
#tasks-badge,
#fab-msg-badge,
.rsn-fab-badge,
.ctb-badge {
  transition: opacity .18s ease-out, transform .18s ease-out;
  will-change: opacity;
}
html.perf-mode .nav-badge,
html.perf-mode #notif-badge,
html.perf-mode #topbar-notif-badge,
html.perf-mode #msg-badge,
html.perf-mode #news-badge,
html.perf-mode #email-badge,
html.perf-mode #tasks-badge,
html.perf-mode #fab-msg-badge,
html.perf-mode .rsn-fab-badge,
html.perf-mode .ctb-badge {
  transition: none !important;
  will-change: auto;
}

/* Этап Б: smooth-appear для late-injected элементов (presence-аватары,
   crm-tag'и, status-badge'и, реакции в чатах). Transition объявляется
   глобально — fade-in срабатывает автоматически когда JS меняет
   opacity/transform. Если элемент рендерится сразу видимым — никаких
   side-effects. */
.app-presence-stack,
.reaction-badge,
.chat-bubble .reaction-badge,
.ic-reactions > *,
.crm-tag,
.prow-kb-row,
.lbg-stage-badge,
.lbg-prow-bank-icon,
.user-avatar-mini {
  transition: opacity .18s ease-out, transform .18s ease-out;
}
html.perf-mode .app-presence-stack,
html.perf-mode .reaction-badge,
html.perf-mode .chat-bubble .reaction-badge,
html.perf-mode .ic-reactions > *,
html.perf-mode .crm-tag,
html.perf-mode .prow-kb-row,
html.perf-mode .lbg-stage-badge,
html.perf-mode .lbg-prow-bank-icon,
html.perf-mode .user-avatar-mini {
  transition: none !important;
}

.sidebar-footer {
  /* По UX-запросу «криво реализован сайдбар» — footer сделан более
     компактным/анкоред: padding 16→10px, чётче border-top (.08→.14
     alpha), глубже background-затемнение (.1→.18). Визуально feels
     как intentional bottom-bar, а не оторванный «бокс». */
  padding: 10px 12px;
  border-top: 1px solid rgba(255, 255, 255, .14);
  background: rgba(0, 0, 0, .18)
}

/* ── Hamburger button — СПРЯТАНА ВСЕГДА ─────────────────────────────────
   КРИТИЧНО: правило живёт в main.css (а НЕ в mobile.css). Mobile.css
   подключается через media="(max-width: 1024px)" → на десктопе >1024px
   файл вообще не парсится браузером → правила из него не работают.
   Жалоба: «Всё так же вижу гамбургер» — после предыдущего фикса в
   mobile.css на десктопе ничего не изменилось.
   По UX «надо убрать» — глобально, на всех viewport'ах, !important
   перебивает старое @media показывание в mobile.css. */
.hamburger-btn {
  display: none !important;
}

.sidebar-user {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 6px
}

.sidebar-avatar {
  width: 38px;
  height: 38px;
  background: linear-gradient(135deg, #3b82f6, #8b5cf6);
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-weight: 600;
  font-size: 14px;
  flex-shrink: 0;
  box-shadow: 0 2px 8px rgba(59, 130, 246, .2)
}

.sidebar-user-info {
  flex: 1;
  min-width: 0
}

.sidebar-user-name {
  color: var(--white);
  font-size: 13px;
  font-weight: 500;
  word-break: break-word;
  line-height: 1.3
}

.sidebar-user-role {
  color: var(--sidebar-text);
  font-size: 11px
}

.btn-logout {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  color: #fca5a5;
  font-size: 13px;
  font-weight: 500;
  padding: 9px 14px;
  margin-top: 10px;
  transition: all .2s;
  background: rgba(239, 68, 68, .06);
  border: 1px solid rgba(239, 68, 68, .1);
  border-radius: 10px;
  cursor: pointer;
  font-family: var(--font);
  text-decoration: none;
  width: 100%
}

.btn-logout:hover {
  background: rgba(239, 68, 68, .15);
  color: #f87171;
  border-color: rgba(239, 68, 68, .25);
  transform: translateY(-1px)
}

#push-bell {
  font-size: 16px;
  cursor: pointer;
  opacity: .6;
  background: 0;
  border: 0;
  padding: 4px;
  border-radius: 6px;
  transition: opacity .2s, background .2s;
  line-height: 1
}

#push-bell:hover {
  opacity: 1;
  background: rgba(255, 255, 255, .08)
}

#push-bell.push-active {
  opacity: .9
}

.main-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-width: 0;
  overflow: hidden;
  /* margin-left анимируется синхронно с шириной сайдбара (238↔66) при сворачивании. */
  transition: margin-left .3s ease
}

.topbar {
  background: rgba(255, 255, 255, .7);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom: 1px solid rgba(148, 163, 184, .12);
  padding: 0 28px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: sticky;
  top: 0;
  z-index: 50
}

.topbar-title {
  font-size: 17px;
  font-weight: 600;
  color: var(--dark-2)
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  /* margin-left:auto прижимает actions к правому краю topbar'а независимо
     от того, есть ли в шапке title или нет (раньше title с flex:1 толкал
     actions вправо; после удаления title actions съехали влево). */
  margin-left: auto;
}

.page-content {
  padding: 28px;
  flex: 1
}

.card {
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  border: 1px solid var(--glass-border)
}

.card-header {
  /* Компактная macOS-like шапка карточки — по аналогии с .modal-header.
     Раньше 18px 22px 14px (~50px высоты) — громоздкая полоса заголовка
     над контентом. Теперь 8px 18px + min-height 40px (~40px высоты),
     соответствует визуально модалкам. Внутри ещё помещаются бейджи,
     toolbar, presence-stack — align-items:center выравнивает их по
     центру. */
  padding: 8px 18px;
  min-height: 40px;
  border-bottom: 1px solid rgba(148, 163, 184, .12);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px
}

.card-title {
  /* 13px / letter-spacing -.01em — единый стиль с .modal-title. Раньше
     14px без letter-spacing'а — заголовок выпирал визуально. */
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--dark-2)
}

.card-body {
  padding: 20px 22px
}

.stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin-bottom: 24px
}

.stat-card {
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border-radius: var(--radius);
  padding: 20px 22px;
  box-shadow: var(--shadow);
  border: 1px solid var(--glass-border);
  display: flex;
  align-items: center;
  gap: 16px;
  transition: transform .2s, box-shadow .2s
}

.stat-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg)
}

.stat-icon {
  width: 48px;
  height: 48px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  flex-shrink: 0
}

.stat-icon.orange {
  background: linear-gradient(135deg, #eff6ff, #dbeafe)
}

.stat-icon.blue {
  background: linear-gradient(135deg, #eff6ff, #dbeafe)
}

.stat-icon.green {
  background: linear-gradient(135deg, #ecfdf5, #d1fae5)
}

.stat-icon.purple {
  background: linear-gradient(135deg, #f5f3ff, #ede9fe)
}

.stat-value {
  font-size: 26px;
  font-weight: 700;
  color: var(--dark-2);
  line-height: 1
}

.stat-label {
  font-size: 12px;
  color: var(--gray);
  margin-top: 3px
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 34px;
  padding: 0 14px;
  border-radius: 10px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: -.01em;
  cursor: pointer;
  transition: border-color .18s ease, box-shadow .18s ease, background .18s ease, color .18s ease, transform .1s ease;
  border: 1px solid #e2e8f0;
  background: linear-gradient(180deg, #fff 0%, #f8fafc 100%);
  color: #334155;
  font-family: var(--font);
  text-decoration: none;
  white-space: nowrap;
  line-height: 1.2;
  box-shadow: 0 1px 2px rgba(15, 23, 42, .05);
  box-sizing: border-box
}

/* Primary — единый бренд-градиент CRM (blue-500 → indigo-500).
   Совпадает с .chat-bubble.own, .email-compose-btn, шапкой виджетов
   и кнопками действий — везде один и тот же визуальный акцент. */
.btn-primary {
  border: none;
  background: var(--primary-gradient);
  color: #fff;
  box-shadow: 0 2px 10px rgba(99, 102, 241, .28)
}

.btn-primary:hover {
  background: var(--primary-grad-hover);
  color: #fff;
  box-shadow: 0 4px 16px rgba(99, 102, 241, .36);
  transform: translateY(-1px)
}

/* ── Кнопки — палитра как у уведомления .ic-public-warn ────────────────────
   Полупрозрачный градиент в цвете акцента (blue/red/green) + тонкий бордер
   того же оттенка + насыщенный текст. Пример «Это чат с клиентом» —
   эталон. Исходный вид сохранён в memory/ui_buttons_original.md. */
.btn-secondary {
  background: linear-gradient(135deg, rgba(59, 130, 246, .08), rgba(99, 102, 241, .08));
  color: #1d4ed8;
  border: 1px solid rgba(59, 130, 246, .22);
  box-shadow: none
}

.btn-secondary:hover {
  background: linear-gradient(135deg, rgba(59, 130, 246, .14), rgba(99, 102, 241, .14));
  border-color: rgba(59, 130, 246, .35);
  color: #1e40af;
  box-shadow: 0 1px 4px rgba(59, 130, 246, .12)
}

.btn-danger {
  background: linear-gradient(135deg, rgba(239, 68, 68, .08), rgba(244, 63, 94, .08));
  color: #b91c1c;
  border: 1px solid rgba(239, 68, 68, .22);
  box-shadow: none
}

.btn-danger:hover {
  background: linear-gradient(135deg, rgba(239, 68, 68, .14), rgba(244, 63, 94, .14));
  border-color: rgba(239, 68, 68, .35);
  color: #991b1b;
  box-shadow: 0 1px 4px rgba(239, 68, 68, .12)
}

.btn-success {
  background: linear-gradient(135deg, rgba(16, 185, 129, .08), rgba(34, 197, 94, .08));
  color: #047857;
  border: 1px solid rgba(16, 185, 129, .22);
  box-shadow: none
}

.btn-success:hover {
  background: linear-gradient(135deg, rgba(16, 185, 129, .14), rgba(34, 197, 94, .14));
  border-color: rgba(16, 185, 129, .35);
  color: #065f46;
  box-shadow: 0 1px 4px rgba(16, 185, 129, .12)
}

.btn-sm {
  min-height: 32px;
  padding: 0 12px;
  font-size: 12px;
  border-radius: 9px;
  gap: 5px
}

.btn-icon {
  padding: 7px;
  border-radius: var(--radius-sm)
}

.form-group {
  margin-bottom: 16px
}

.form-label {
  display: block;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--dark);
  margin-bottom: 6px
}

.form-control {
  width: 100%;
  padding: 10px 14px;
  border: 1px solid rgba(148, 163, 184, .22);
  border-radius: 10px;
  font-size: 13.5px;
  font-family: var(--font);
  color: var(--dark);
  background: #fff;
  transition: border-color .2s, box-shadow .2s;
  outline: 0
}

.form-control:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(59, 130, 246, .12);
  background: rgba(255, 255, 255, .95)
}

.form-control::placeholder {
  color: #94a3b8
}

select.form-control {
  cursor: pointer;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  padding-right: 34px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 12px;
  transition: border-color .2s, box-shadow .2s, background-color .15s
}

select.form-control:hover {
  border-color: rgba(59, 130, 246, .35);
  background-color: rgba(255, 255, 255, .92)
}

select.form-control:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(59, 130, 246, .12);
  background-color: rgba(255, 255, 255, .98);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%233b82f6' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E")
}

select.form-control option {
  padding: 8px 12px;
  background: #fff;
  color: var(--dark);
  font-family: var(--font);
  font-size: 13px
}

textarea.form-control {
  resize: vertical;
  min-height: 80px
}

.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px
}

.form-hint {
  font-size: 11.5px;
  color: var(--gray);
  margin-top: 4px
}

.table-wrapper {
  overflow-x: auto;
  max-width: 100%
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13.5px
}

thead th {
  background: #f1f5f9;
  padding: 10px 14px;
  text-align: left;
  font-weight: 600;
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--gray);
  border-bottom: 1px solid rgba(148, 163, 184, .15);
  white-space: nowrap
}

tbody tr {
  border-bottom: 1px solid rgba(148, 163, 184, .08);
  transition: background .15s
}

tbody tr:hover {
  background: rgba(59, 130, 246, .03)
}

tbody tr:last-child {
  border-bottom: 0
}

td {
  padding: 12px 14px;
  color: var(--dark);
  vertical-align: middle
}

.td-muted {
  color: var(--gray);
  font-size: 12.5px
}

.table-empty {
  text-align: center;
  padding: 48px 20px;
  color: var(--gray)
}

.table-empty-icon {
  font-size: 36px;
  margin-bottom: 8px
}

.badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 8px;
  font-size: 11.5px;
  font-weight: 500;
  white-space: nowrap;
  backdrop-filter: blur(4px)
}

.badge-new {
  background: rgba(37, 99, 235, .1);
  color: #2563eb
}

.badge-progress {
  background: rgba(217, 119, 6, .1);
  color: #d97706
}

.badge-docs {
  background: rgba(124, 58, 237, .1);
  color: #7c3aed
}

.badge-review {
  background: rgba(2, 132, 199, .1);
  color: #0284c7
}

.badge-approved {
  background: rgba(22, 163, 74, .1);
  color: #16a34a
}

/* on_issue («На выдаче») — между approved и completed. Чуть ярче, чем
   completed (mint emerald), чтобы менеджер сразу видел: банк одобрил,
   проект на финишной прямой, идёт выпуск БГ. */
.badge-on_issue {
  background: rgba(52, 211, 153, .18);
  color: #059669
}

.badge-rejected {
  background: rgba(220, 38, 38, .1);
  color: #dc2626
}

.badge-completed {
  background: rgba(100, 116, 139, .1);
  color: #64748b
}

.priority-low {
  color: #16a34a
}

.priority-medium {
  color: #d97706
}

.priority-high {
  color: #dc2626
}

.modal-overlay {
  /* Viewport-relative центрирование. Раньше использовали `inset:0`, но из-за
   * `contain:layout style` на `.main-content` (CLS-isolation) position:fixed
   * потомки внутри main-content анчорились к нему, а не к viewport. На
   * длинных страницах модалка центрировалась в МИДДЛ main-content (намного
   * больше viewport'а) → визуально оказывалась «внизу» экрана.
   * Жалоба: «модалка должна вызываться посредине экрана». Явные vw/vh
   * единицы → viewport-relative независимо от containing block. */
  position: fixed;
  inset: 0;
  top: 0; left: 0; right: 0; bottom: 0;
  width: 100vw; min-height: 100vh; min-height: 100dvh;
  background: rgba(15, 23, 42, .45);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  place-items: center;
  overflow-y: auto;
  padding: 20px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s
}

.modal-overlay.open {
  opacity: 1;
  pointer-events: all
}

.modal {
  background: rgba(255, 255, 255, .97);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg), 0 0 0 1px rgba(255, 255, 255, .5);
  width: 100%;
  max-width: 520px;
  max-height: 90vh;
  /* `overflow:hidden` (вместо `overflow-y:auto`) убирает subpixel-«проплешины»
     по верхним углам модалок: при overflow-y:auto background-цвет родителя
     просвечивал сквозь border-radius на половину пикселя по краям градиентной
     шапки. Длинный контент должен скроллиться внутри .modal-body, который
     задаёт свой max-height/overflow при необходимости. */
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transform: translateY(16px);
  /* delay .25s — критично для close-анимации: при удалении .open класса
     transform возвращается с 0 в 16px. Без delay юзер видит как модалка
     медленно опускается ВНИЗ ПАРАЛЛЕЛЬНО с fade-out overlay'я (.25s) —
     визуально воспринимается как баг «сначала опускается, потом закрывается».
     С delay:.25s transform начинает анимироваться ПОСЛЕ того как overlay
     уже невидим (opacity:0) → slide-down не виден. На open же
     `.modal-overlay.open .modal` override'ит до 0s delay → плавное появление
     работает как раньше. Жалоба: «не просто закрывается, а сначала
     опускается вниз и уже потом закрывается». */
  transition: transform .25s .25s
}
/* Дочерний .modal-body теперь сам решает проблему скролла для длинного
   контента. Если body не задан — fallback на overflow:auto на .modal. */
.modal > .modal-body {
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
}

.modal-overlay.open .modal {
  transform: translateY(0);
  transition: transform .25s 0s
}

/* Плавное угасание модалки ПЕРЕД reload. Сохраняет класс .open (scroll-lock
   observer в app.js не снимает overflow → фон под модалкой не «прыгает»),
   но визуально overlay+modal угасают за .2s обычным ease (не bouncy — иначе
   диалог «перелетал вниз»). Используется _hideModalForReload. Specificity
   .open.crm-fading (0,3,1 для .modal) перебивает .open .modal (0,2,1). */
.modal-overlay.open.crm-fading {
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s ease;
}
.modal-overlay.open.crm-fading .modal {
  transform: translateY(8px) scale(.99);
  transition: transform .2s ease;
}

.modal-header {
  /* Компактная macOS-like шапка: меньше padding, чтобы контент сразу
     был виден без громоздкой верхней полосы. Раньше 22px 24px 16px —
     шапка занимала ~60px высоты, выглядела громоздко. */
  padding: 10px 16px;
  border-bottom: 1px solid rgba(148, 163, 184, .12);
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 38px;
}

.modal-title {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--dark-2)
}

.modal-close {
  width: 22px;
  height: 22px;
  border: 0;
  background: rgba(148, 163, 184, .1);
  border-radius: 50%;
  cursor: pointer;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background .15s;
  color: var(--gray);
  padding: 0;
}

.modal-close:hover {
  background: rgba(148, 163, 184, .22);
  color: var(--dark)
}

.modal-body {
  padding: 22px 24px
}

.modal-footer {
  padding: 14px 24px 20px;
  display: flex;
  gap: 10px;
  justify-content: flex-end
}

.login-page {
  min-height: 100vh;
  background: linear-gradient(135deg, #0f172a 0, #1e3a5f 50%, #312e81 100%);
  background-size: 200% 200%;
  animation: loginGradient 12s ease infinite;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px
}

@keyframes loginGradient {
  0% {
    background-position: 0 50%
  }

  50% {
    background-position: 100% 50%
  }

  100% {
    background-position: 0 50%
  }
}

.login-card {
  background: rgba(255, 255, 255, .12);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border-radius: var(--radius-lg);
  box-shadow: 0 16px 48px rgba(0, 0, 0, .2), 0 0 0 1px rgba(255, 255, 255, .15);
  width: 100%;
  max-width: 400px;
  padding: 40px;
  border: 1px solid rgba(255, 255, 255, .18);
  color: #e2e8f0
}

.login-card .form-control {
  background: rgba(255, 255, 255, .08);
  border-color: rgba(255, 255, 255, .15);
  color: #f1f5f9
}

.login-card .form-control::placeholder {
  color: rgba(148, 163, 184, .6)
}

.login-card .form-control:focus {
  border-color: #60a5fa;
  box-shadow: 0 0 0 3px rgba(96, 165, 250, .2);
  background: rgba(255, 255, 255, .12)
}

.login-card select.form-control {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E")
}

.login-card select.form-control:focus {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2360a5fa' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E")
}

.login-card .form-label {
  color: #cbd5e1
}

.login-card .btn-primary {
  width: 100%;
  padding: 12px;
  font-size: 14px;
  justify-content: center
}

.login-logo {
  text-align: center;
  margin-bottom: 32px
}

.login-logo-icon {
  width: 54px;
  height: 54px;
  background: var(--primary-gradient);
  border-radius: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 26px;
  margin-bottom: 12px;
  box-shadow: 0 8px 24px rgba(59, 130, 246, .3)
}

.login-logo-title {
  font-size: 20px;
  font-weight: 700;
  color: #f1f5f9
}

.login-logo-sub {
  font-size: 12.5px;
  color: #94a3b8;
  margin-top: 2px
}

.login-error {
  background: rgba(239, 68, 68, .12);
  border: 1px solid rgba(239, 68, 68, .25);
  color: #fca5a5;
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  font-size: 13px;
  margin-bottom: 16px
}

.grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px
}

.grid-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 20px
}

.task-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid rgba(148, 163, 184, .1)
}

.task-item:last-child {
  border-bottom: 0
}

.task-check {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid rgba(148, 163, 184, .3);
  flex-shrink: 0;
  margin-top: 2px;
  cursor: pointer;
  transition: all .2s;
  display: flex;
  align-items: center;
  justify-content: center
}

.task-check:hover {
  border-color: var(--primary)
}

.task-check.done {
  background: var(--primary-gradient);
  border-color: transparent
}

.task-title {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--dark)
}

.task-title.done {
  text-decoration: line-through;
  color: var(--gray)
}

.task-meta {
  font-size: 11.5px;
  color: var(--gray);
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 2px
}

.task-priority {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase
}

.filters-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap
}

.filters-bar .form-control {
  width: auto;
  min-width: 140px
}

.filters-bar select.form-control {
  padding: 8px 32px 8px 12px;
  font-size: 12.5px;
  font-weight: 500;
  border-radius: 10px;
  background-color: rgba(255, 255, 255, .85);
  border-color: rgba(148, 163, 184, .18)
}

.filters-bar select.form-control:hover {
  background-color: rgba(255, 255, 255, .95);
  border-color: rgba(59, 130, 246, .3);
  box-shadow: 0 1px 4px rgba(59, 130, 246, .08)
}

.search-input-wrap {
  position: relative;
  flex: 1;
  max-width: 480px
}

.search-input-wrap .search-icon {
  position: absolute;
  left: 8px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--gray);
  font-size: 14px
}

.search-input-wrap .form-control {
  padding-left: 28px
}

.app-status-bar {
  display: flex;
  align-items: center;
  gap: 0;
  margin: 24px 0;
  flex-wrap: wrap
}

.app-status-step {
  display: flex;
  align-items: center;
  font-size: 12px;
  font-weight: 500
}

.app-status-step .step-dot {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid rgba(148, 163, 184, .25);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  background: rgba(255, 255, 255, .6);
  color: var(--gray);
  z-index: 1
}

.app-status-step.active .step-dot {
  background: var(--primary-gradient);
  border-color: transparent;
  color: white;
  box-shadow: 0 2px 8px rgba(59, 130, 246, .3)
}

.app-status-step.done .step-dot {
  background: rgba(16, 185, 129, .1);
  border-color: #10b981;
  color: #10b981
}

.app-status-step .step-label {
  margin: 0 6px;
  color: var(--gray);
  font-size: 11.5px
}

.app-status-step.active .step-label {
  color: var(--primary);
  font-weight: 600
}

.step-line {
  flex: 1;
  height: 2px;
  background: rgba(148, 163, 184, .2);
  min-width: 20px
}

.info-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px
}

.info-item label {
  display: block;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--gray);
  font-weight: 600;
  margin-bottom: 3px
}

.info-item span {
  font-size: 14px;
  color: var(--dark);
  font-weight: 400
}

.alert {
  padding: 12px 16px;
  border-radius: 10px;
  font-size: 13px;
  margin-bottom: 16px;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  backdrop-filter: blur(8px)
}

.alert-success {
  background: rgba(16, 185, 129, .08);
  border: 1px solid rgba(16, 185, 129, .2);
  color: #059669
}

.alert-info {
  background: rgba(59, 130, 246, .08);
  border: 1px solid rgba(59, 130, 246, .2);
  color: #2563eb
}

.alert-warning {
  background: rgba(245, 158, 11, .08);
  border: 1px solid rgba(245, 158, 11, .2);
  color: #d97706
}

.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 22px;
  flex-wrap: wrap;
  gap: 12px
}

.page-header h1 {
  font-size: 20px;
  font-weight: 600;
  color: var(--dark-2)
}

.breadcrumb {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  color: var(--gray);
  margin-bottom: 8px
}

.breadcrumb a {
  color: var(--gray)
}

.breadcrumb a:hover {
  color: var(--primary)
}

.breadcrumb .sep {
  color: rgba(148, 163, 184, .4)
}

.breadcrumb .current {
  color: var(--dark);
  font-weight: 500
}

.password-box {
  background: var(--primary-light);
  border: 1px solid var(--primary-border);
  border-radius: var(--radius);
  padding: 18px 22px;
  margin-bottom: 20px
}

.password-box h4 {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--dark-2);
  margin-bottom: 4px
}

.password-box p {
  font-size: 12.5px;
  color: var(--gray);
  margin-bottom: 10px
}

.password-value {
  font-family: 'Courier New', monospace;
  font-size: 20px;
  font-weight: 700;
  color: var(--primary);
  letter-spacing: 2px
}

.timeline {
  position: relative;
  padding-left: 24px
}

.timeline::before {
  content: '';
  position: absolute;
  left: 6px;
  top: 6px;
  bottom: 6px;
  width: 2px;
  background: rgba(148, 163, 184, .2)
}

.timeline-item {
  position: relative;
  padding-bottom: 20px
}

.timeline-dot {
  position: absolute;
  left: -20px;
  top: 4px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: rgba(148, 163, 184, .3);
  border: 2px solid var(--white)
}

.timeline-dot.active {
  background: var(--primary);
  box-shadow: 0 0 0 3px rgba(59, 130, 246, .15)
}

.timeline-dot.done {
  background: #10b981
}

.timeline-label {
  font-size: 13px;
  font-weight: 500;
  color: var(--dark)
}

.timeline-date {
  font-size: 11.5px;
  color: var(--gray)
}

.text-muted {
  color: var(--gray)
}

.text-primary {
  color: var(--primary)
}

.text-sm {
  font-size: 12.5px
}

.fw-600 {
  font-weight: 600
}

.mt-4 {
  margin-top: 4px
}

.mt-8 {
  margin-top: 8px
}

.mt-16 {
  margin-top: 16px
}

.mt-24 {
  margin-top: 24px
}

.mb-16 {
  margin-bottom: 16px
}

.mb-24 {
  margin-bottom: 24px
}

.flex {
  display: flex
}

.flex-center {
  display: flex;
  align-items: center
}

.gap-8 {
  gap: 8px
}

.gap-12 {
  gap: 12px
}

.ml-auto {
  margin-left: auto
}

.chat-layout {
  display: flex;
  height: calc(100vh - 64px);
  overflow: hidden;
  margin: -28px
}

.chat-sidebar {
  width: 300px;
  flex-shrink: 0;
  border-right: 1px solid rgba(0, 0, 0, .08);
  background: #F9F9F9;
  backdrop-filter: none;
  display: flex;
  flex-direction: column;
  overflow: hidden
}

.chat-sidebar-header {
  padding: 18px 16px 12px;
  border-bottom: 1px solid rgba(148, 163, 184, .12);
  font-size: 14px;
  font-weight: 600;
  color: var(--dark-2);
  display: flex;
  align-items: center;
  justify-content: space-between
}

.chat-search {
  padding: 10px 12px;
  border-bottom: 1px solid rgba(148, 163, 184, .1)
}

.chat-search input {
  width: 100%;
  padding: 7px 12px;
  border: 1px solid rgba(148, 163, 184, .2);
  border-radius: 20px;
  font-size: 13px;
  font-family: var(--font);
  outline: 0;
  background: rgba(248, 250, 252, .7)
}

.chat-search input:focus {
  border-color: var(--primary);
  background: white
}

.chat-user-list {
  flex: 1;
  overflow-y: auto
}

.chat-section-label {
  padding: 8px 14px 4px;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: #94a3b8;
  background: rgba(248, 250, 252, .5)
}

.chat-user-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  cursor: pointer;
  transition: background .15s;
  border-bottom: 1px solid rgba(148, 163, 184, .06);
  text-decoration: none
}

.chat-user-item:hover {
  background: rgba(59, 130, 246, .04)
}

.chat-user-item.active {
  background: rgba(0, 122, 255, .08);
  border-left: 3px solid #007AFF
}

.chat-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 15px;
  flex-shrink: 0;
  position: relative
}

.chat-avatar.manager-av {
  background: linear-gradient(135deg, #ede9fe, #ddd6fe);
  color: #7c3aed
}

.chat-avatar.client-av {
  background: linear-gradient(135deg, #dbeafe, #bfdbfe);
  color: #2563eb
}

.chat-avatar.admin-av {
  background: linear-gradient(135deg, #fce7f3, #fbcfe8);
  color: #be185d
}

.online-dot {
  position: absolute;
  bottom: 1px;
  right: 1px;
  width: 10px;
  height: 10px;
  background: #22c55e;
  border-radius: 50%;
  border: 2px solid white
}

.chat-user-info {
  flex: 1;
  min-width: 0
}

.chat-user-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--dark);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis
}

.chat-user-preview {
  font-size: 11.5px;
  color: var(--gray);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 2px
}

.chat-unread {
  background: #007AFF;
  color: white;
  font-size: 10px;
  font-weight: 700;
  min-width: 18px;
  height: 18px;
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 5px;
  flex-shrink: 0
}

.chat-window {
  flex: 1;
  display: flex;
  flex-direction: column;
  background: #FFFFFF;
  min-width: 0
}

.chat-window-header {
  background: #FFFFFF;
  backdrop-filter: none;
  border-bottom: 1px solid rgba(0, 0, 0, .08);
  padding: 14px 20px;
  display: flex;
  align-items: center;
  gap: 12px
}

.chat-window-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--dark-2)
}

.chat-window-status {
  font-size: 11.5px;
  color: var(--gray);
  margin-top: 1px
}

.chat-online {
  color: #16a34a
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 20px 20px 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: #FFFFFF
}

.chat-date-sep {
  font-size: 11px;
  color: #8E8E93;
  margin: 16px auto 12px;
  position: relative;
  background: rgba(0, 0, 0, .06);
  width: fit-content;
  padding: 4px 14px;
  border-radius: 12px;
  font-weight: 500;
  text-align: center
}

.chat-date-sep::before,
.chat-date-sep::after {
  display: none
}

.chat-bubble-wrap {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  margin: 2px 0
}

.chat-bubble-wrap.own {
  flex-direction: row-reverse
}

.bubble-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 600;
  flex-shrink: 0;
  background: rgba(0, 122, 255, .1);
  color: #007AFF;
  transition: box-shadow .15s
}

.bubble-avatar:hover {
  box-shadow: 0 0 0 2px rgba(0, 122, 255, .2)
}

.chat-bubble {
  max-width: 75%;
  padding: 10px 16px;
  border-radius: 18px;
  font-size: 14px;
  line-height: 1.45;
  word-break: break-word;
  position: relative;
  transition: transform .15s ease
}

.chat-bubble:hover {
  transform: scale(1.008)
}

.chat-bubble.other {
  background: #E9E9EB;
  color: var(--dark);
  border-radius: 18px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .06);
  border: none;
  backdrop-filter: none
}

.chat-bubble.own {
  /* Градиент совпадает с .btn-primary в hover-состоянии и кнопкой
   * .email-compose-btn («Написать»). Раньше тут стоял плоский iOS-blue
   * #007AFF — на фоне градиентных кнопок «Новая заявка» / «Написать»
   * чат смотрелся «бедно» и не из одной палитры. Сейчас:
   *   blue-500 → indigo-500 — те же стопы, что и у акцентных кнопок CRM. */
  background: var(--primary-gradient);
  color: white;
  border-radius: 18px;
  box-shadow: 0 2px 10px rgba(99, 102, 241, .22);
}

.bubble-time {
  font-size: 10px;
  margin-top: 4px;
  text-align: right
}

.chat-bubble.own .bubble-time {
  color: rgba(255, 255, 255, .7)
}

.chat-bubble.other .bubble-time {
  color: #8E8E93
}

.chat-input-bar {
  background: #FFFFFF;
  backdrop-filter: none;
  border-top: 1px solid rgba(0, 0, 0, .08);
  padding: 14px 16px;
  display: flex;
  align-items: flex-end;
  gap: 10px
}

.chat-input {
  flex: 1;
  padding: 12px 18px;
  border: 1px solid rgba(148, 163, 184, .15);
  border-radius: 20px;
  font-size: 14px;
  font-family: var(--font);
  outline: 0;
  resize: none;
  max-height: 120px;
  overflow-y: auto;
  transition: border-color .2s;
  line-height: 1.5;
  background: #F2F2F7
}

.chat-input:focus {
  border-color: #007AFF;
  background: #FFFFFF
}

.chat-send-btn {
  position: relative;
  width: 42px;
  height: 42px;
  border: 0;
  border-radius: 50%;
  background: linear-gradient(135deg, #3b82f6 0%, #2563eb 52%, #1d4ed8 100%);
  color: #fff;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: 18px;
  box-shadow: 0 2px 10px rgba(37, 99, 235, .28), inset 0 1px 0 rgba(255, 255, 255, .2);
  transition: transform .18s ease, box-shadow .18s ease, filter .18s ease, background .18s ease;
  overflow: hidden
}

.chat-send-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: linear-gradient(135deg, rgba(255, 255, 255, .18), rgba(255, 255, 255, 0) 55%);
  pointer-events: none
}

.chat-send-btn svg {
  position: relative;
  z-index: 1;
  transform: translate(-1px, 1px);
  filter: drop-shadow(0 1px 1px rgba(15, 23, 42, .18))
}

.chat-send-btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 18px rgba(37, 99, 235, .42), inset 0 1px 0 rgba(255, 255, 255, .26);
  filter: brightness(1.06);
  background: linear-gradient(135deg, #60a5fa 0%, #3b82f6 45%, #2563eb 100%)
}

.chat-send-btn:active {
  transform: translateY(0);
  box-shadow: 0 2px 8px rgba(37, 99, 235, .28)
}

.chat-send-btn:focus-visible {
  outline: 2px solid rgba(59, 130, 246, .55);
  outline-offset: 2px
}

.chat-send-btn:disabled {
  background: rgba(148, 163, 184, .25);
  color: rgba(100, 116, 139, .65);
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
  filter: none
}

.chat-send-btn:disabled::before {
  display: none
}

.chat-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: var(--gray);
  gap: 12px
}

.chat-empty-icon {
  font-size: 48px
}

.chat-empty-text {
  font-size: 14px
}

#crm-toast-container {
  position: fixed;
  top: 20px;
  right: 20px;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  gap: 10px;
  pointer-events: none
}

.crm-toast {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  background: #fff;
  backdrop-filter: blur(20px);
  color: #1c1c1e;
  padding: 14px 16px;
  border-radius: 16px;
  max-width: 360px;
  min-width: 260px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06);
  pointer-events: all;
  transform: translateY(-120%);
  /* По UX «отмечаю прочитанным — подглючивает» — добавлены transition
     для max-height/opacity/margin/padding, чтобы при закрытии toast'а
     соседи в flex-container не прыгали вверх скачком, а плавно сдвигались. */
  transition: transform .35s cubic-bezier(.4, 0, .2, 1),
              max-height .28s ease,
              opacity .22s ease,
              margin .28s ease,
              padding .28s ease;
  border: none
}

.crm-toast.toast-show {
  transform: translateY(0)
}

.toast-icon {
  width: 36px;
  height: 36px;
  border-radius: 12px;
  background: #007AFF;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  flex-shrink: 0
}

.toast-content {
  flex: 1;
  min-width: 0
}

.toast-title {
  font-weight: 600;
  font-size: 13.5px;
  margin-bottom: 2px;
  color: #1c1c1e
}

.toast-body {
  font-size: 12.5px;
  color: #8E8E93;
  white-space: normal;
  word-break: break-word;
  line-height: 1.4
}

.toast-close {
  background: none;
  border: none;
  color: #C7C7CC;
  cursor: pointer;
  font-size: 16px;
  padding: 4px;
  flex-shrink: 0;
  line-height: 1;
  border-radius: 50%;
  transition: all .15s
}

.toast-close:hover {
  color: #8E8E93;
  background: rgba(0, 0, 0, .05)
}

/* ── Универсальный spinner для кнопок (.is-loading) ──────────────────
   Использование: button.disabled = true; button.classList.add('is-loading').
   Заменяет уродливые "Загрузка..." / "Привязка..." text-changes на
   нормальный visual indicator. По UX-запросу: «добавь нормальный спиннер
   внутри кнопки, а не "привязка..."». */
button.is-loading {
  position: relative;
  pointer-events: none;
  /* Резервируем место под спиннер слева — текст не должен прыгать */
  padding-left: calc(1em + 18px);
}
button.is-loading::before {
  content: '';
  position: absolute;
  left: 12px;
  top: 50%;
  width: 13px;
  height: 13px;
  margin-top: -7px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: crm-btn-spin .7s linear infinite;
  opacity: .85;
}
@keyframes crm-btn-spin {
  to { transform: rotate(360deg); }
}

.toast-read {
  background: rgba(16, 185, 129, .1);
  border: none;
  color: #10b981;
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  line-height: 0;
  border-radius: 9px;
  transition: all .15s;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  align-self: center;
}

.toast-read:hover {
  color: #fff;
  background: #10b981
}

.toast-read svg {
  display: block;
}

.notif-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1100;
  background: rgba(0, 0, 0, .25)
}

.notif-overlay.open {
  display: block
}

.notif-panel {
  /* transform вместо right:-480px — иначе модалка торчит за viewport,
     тригерит horizontal scrollbar и layout-shift при загрузке (CLS). */
  position: fixed;
  top: 0;
  right: 0;
  width: 460px;
  max-width: 95vw;
  height: 100vh;
  transform: translateX(105%);
  z-index: 1101;
  background: #FFFFFF;
  box-shadow: -8px 0 40px rgba(0, 0, 0, .1);
  display: flex;
  flex-direction: column;
  transition: transform .32s cubic-bezier(.32, 0, .67, 0);
  will-change: transform;
}

.notif-panel.open {
  transform: translateX(0);
}

/* Анти-FOUC: пока на <html> нет класса notif-anim-on (его ставит JS при
   ПЕРВОМ реальном открытии панели — openNotifPanel в notify-ws.js), панель
   стоит за вьюпортом БЕЗ transition. Иначе при загрузке/навигации, когда
   этот CSS применяется, активный `transition: transform` (в т.ч. из
   perf-mode.css) проигрывает кадр «выезда» → видно мелькание справа, хотя
   панель не открывалась. После первого открытия класс есть → анимация
   работает. Дублирует head-правило в layout'ах (там оно перебивает даже
   позже-загруженный external CSS за счёт #id-специфичности). Жалоба:
   «видно, как скрывается вкладка уведомлений, хотя она не открывалась». */
html:not(.notif-anim-on) .notif-panel {
  transform: translateX(105%) !important;
  transition: none !important;
}

.notif-panel-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 20px 20px 16px;
  border-bottom: 1px solid rgba(0, 0, 0, .06);
  flex-shrink: 0
}

.notif-panel-header h3 {
  flex: 1;
  margin: 0;
  font-size: 20px;
  font-weight: 700;
  color: #1c1c1e;
  letter-spacing: -.02em
}

.notif-panel-body {
  flex: 1;
  overflow-y: auto;
  padding: 4px 0
}

.notif-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 20px;
  cursor: pointer;
  border-bottom: 1px solid rgba(0, 0, 0, .04);
  transition: background .15s
}

.notif-item:hover {
  background: rgba(0, 0, 0, .02)
}

.notif-item.unread {
  background: rgba(0, 122, 255, .04)
}

.notif-item.unread:hover {
  background: rgba(0, 122, 255, .07)
}

.notif-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #007AFF;
  flex-shrink: 0;
  margin-top: 6px
}

.notif-item.read .notif-dot {
  background: transparent
}

.notif-item-content {
  flex: 1;
  min-width: 0
}

.notif-item-title {
  font-size: 13.5px;
  font-weight: 600;
  color: #1c1c1e;
  margin-bottom: 2px
}

.notif-item-body {
  font-size: 12.5px;
  color: #8E8E93;
  white-space: pre-wrap;
  word-break: break-word;
  line-height: 1.45
}

.notif-item-time {
  font-size: 11px;
  color: #AEAEB2;
  margin-top: 4px
}

.notif-empty {
  padding: 48px 20px;
  text-align: center;
  color: var(--gray);
  font-size: 14px
}

.nav-badge {
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  /* Flex-центрирование вместо text-align+line-height — см. коммент выше */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--primary-gradient);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  border-radius: 50%;
  padding: 0;
  width: 22px;
  height: 22px;
  line-height: 1;
  box-sizing: border-box
}

.flash-message {
  transition: opacity .3s, transform .3s
}

.eis-card {
  background: rgba(16, 185, 129, .06);
  border: 1px solid rgba(16, 185, 129, .2);
  border-radius: 12px;
  padding: 12px 14px;
  margin-bottom: 4px;
  font-size: 13px;
  backdrop-filter: blur(8px)
}

.eis-card.eis-error {
  background: rgba(239, 68, 68, .06);
  border-color: rgba(239, 68, 68, .2);
  color: #b91c1c
}

.eis-card-header {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  color: #059669;
  margin-bottom: 8px;
  font-size: 13px
}

.eis-card-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px 16px
}

.eis-row label {
  color: var(--gray);
  font-size: 11px;
  display: block
}

.eis-row span {
  color: var(--dark);
  font-weight: 500
}

.nav-divider {
  display: none
}

.nav-section-label {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: rgba(148, 163, 184, .35);
  padding: 16px 16px 5px;
  user-select: none;
  cursor: default
}

.nav-icon {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
}

/* Утончённые иконки в сайдбаре — зеркалят refined-стиль таскбара
   (size 22→18, stroke-width 2→1.6). По UX «иконки сайдбара такие же
   уточнённые как в таскбаре». Применяется только в самом сайдбаре —
   nav-tools-flyout-global и topbar остаются как есть. */
.sidebar .nav-item .nav-icon {
  width: 18px !important;
  height: 18px !important;
}
.sidebar .nav-item svg.nav-icon {
  stroke-width: 1.6 !important;
}
/* btn-logout SVG (Выйти) тоже под утончение. */
.sidebar .btn-logout svg.nav-icon {
  width: 18px !important;
  height: 18px !important;
  stroke-width: 1.6 !important;
}

.sidebar.collapsed .nav-label {
  display: none;
}

.sidebar.collapsed .nav-divider {
  margin: 4px auto;
}

.styled-app-table {
  table-layout: fixed
}

.styled-app-table thead {
  background: #f1f5f9
}

.styled-app-table th {
  position: relative;
  background: #f1f5f9;
  border-right: 1px solid #e2e8f0;
  white-space: nowrap
}

.styled-app-table th:last-child {
  border-right: none
}

.styled-app-table td {
  border-right: 1px solid #f1f5f9;
  word-wrap: break-word;
  overflow-wrap: break-word
}

.styled-app-table td:last-child {
  border-right: none
}

.sidebar-toggle {
  position: absolute;
  top: 55px;
  right: -12px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: #fff;
  border: 1px solid rgba(148, 163, 184, .2);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .1);
  transition: transform .2s;
  color: var(--gray);
}

.sidebar-toggle:hover {
  background: #f1f5f9;
  color: var(--primary);
}

.sidebar.collapsed .sidebar-toggle {
  top: 45px;
  transform: rotate(180deg);
}

html.sb-collapsed .sidebar .sidebar-toggle {
  top: 45px;
}

.sidebar {
  /* По UX-запросу «сайдбар всё так же остаётся наверху, надо чтобы при
     прокрутке страницы видел всегда сайдбар на одном месте» —
     position:sticky заменён на position:fixed. sticky прокручивался
     вместе с длинными страницами (overflow на родителе ломал прилипание).
     fixed гарантирует что сайдбар всегда виден на одном месте viewport'а
     независимо от scroll position. height:100vh + top:0 + left:0 →
     полная высота viewport'а, прилипает к левому краю.
     overflow:visible — для tooltip'ов nav-section-label, которые
     выходят за пределы сайдбара. */
  position: fixed;
  top: 0;
  left: 0;
  height: 100vh;
  overflow: visible;
  transition: none;
  flex-shrink: 0;
}

/* ── Компенсация position:fixed sidebar'а на main-content ──────────────
   sidebar теперь вышел из document flow (position:fixed). Без явного
   margin-left на .main-content контент уезжает ПОД сайдбар → overlap.
   Жалоба: «сайдбар теперь перекрывает интерфейс».
   Раньше при position:sticky main-content получала компенсацию
   автоматически через flex-flow (sticky остаётся в потоке). С fixed
   нужно вручную задать margin = sidebar-width. */
.main-content {
  margin-left: 238px;  /* совпадает с .sidebar { width: 238px } */
  transition: margin-left .25s ease;
}
html.sb-collapsed .main-content {
  margin-left: 66px;  /* совпадает с html.sb-collapsed .sidebar { width: 66px } */
}
/* Анти-прыжок сайдбара на refresh: пока JS не выставил sb-anim-ready (через
   +300мс после загрузки, там же где .sb-animated) — НИКАКИХ переходов у
   сайдбара и main-content, чтобы при осадке layout'а ничего не анимировалось.
   Раньше это глушил perf-mode глобально; после его удаления переходы стали
   активны уже с гидрации → сайдбар «скакал». Жалоба: «сайдбар скачет при
   обновлении страницы». */
html:not(.sb-anim-ready) .sidebar,
html:not(.sb-anim-ready) .sidebar *,
html:not(.sb-anim-ready) .main-content {
  transition: none !important;
}
/* Mobile: sidebar off-canvas (position:fixed left:-280px из mobile.css) —
   убираем margin, main-content на полную ширину. */
@media (max-width: 768px) {
  .main-content { margin-left: 0 !important; }
  html.sb-collapsed .main-content { margin-left: 0 !important; }
}
/* Taskbar-режим: sidebar display:none → main-content без margin. */
body.nav-taskbar .main-content { margin-left: 0 !important; }

.sidebar.sb-animated {
  transition: width .25s ease;
}

.sidebar-nav {
  overflow-y: auto;
  overflow-x: hidden;
}

.sidebar.collapsed {
  width: 66px !important;
  min-width: 66px !important;
}

.sidebar.collapsed .sidebar-logo-text,
.sidebar.collapsed .sidebar-logo-sub {
  display: none;
}

.sidebar.collapsed .sidebar-logo {
  justify-content: center !important;
  align-items: center !important;
  padding: 12px 0 !important;
  gap: 0 !important;
}

.sidebar.collapsed .sidebar-logo>div {
  display: none;
}

.sidebar.collapsed .sidebar-logo-img {
  width: 32px !important;
  height: 32px !important;
  margin: 0 auto !important;
}

.sidebar.collapsed .nav-item,
.sidebar.collapsed button.nav-item {
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  text-align: center !important;
  padding: 10px 0 !important;
  font-size: 0;
  margin: 2px 6px;
  width: auto;
}

.sidebar.collapsed .nav-item .nav-icon {
  margin: 0 !important;
  align-self: center;
  flex-shrink: 0;
}

.sidebar.collapsed .sidebar-footer {
  padding: 8px 4px;
}

.sidebar.collapsed .sidebar-user-info {
  display: none;
}

.sidebar.collapsed .sidebar-user {
  justify-content: center;
}

.sidebar.collapsed .btn-logout {
  font-size: 0;
  padding: 6px;
  justify-content: center;
}

.sidebar.collapsed .btn-logout svg {
  display: block;
}


/* ── Жёсткая центровка nav-item в свёрнутом виде (button.nav-item имеет text-align:left по умолчанию) ── */
html.sb-collapsed .sidebar .nav-item,
html.sb-collapsed .sidebar button.nav-item {
  position: relative !important;
  overflow: visible !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  text-align: center !important;
  padding: 10px 0 !important;
  width: auto !important;
  box-sizing: border-box;
}

html.sb-collapsed .sidebar .nav-item .nav-icon {
  display: block !important;
  margin: 0 !important;
  align-self: center !important;
  flex-shrink: 0 !important;
}

/* Бейджи уведомлений в свёрнутом виде: висят на нижнем-правом углу иконки, чуть её задевая.
   ВАЖНО: display НЕ ставим через !important — чтобы inline style="display:none" сохранял скрытие при count=0.
   JS ставит style.display='inline-flex' при count>0. */
html.sb-collapsed .sidebar .nav-item .nav-badge {
  position: absolute !important;
  top: auto !important;
  left: auto !important;
  right: 4px !important;
  bottom: 2px !important;
  transform: none !important;
  font-size: 10px !important;
  font-weight: 700 !important;
  padding: 0 4px !important;
  min-width: 18px !important;
  width: auto !important;
  max-width: none !important;
  height: 18px !important;
  min-height: 18px !important;
  max-height: 18px !important;
  line-height: 1 !important;
  border-radius: 9px !important;
  border: 1.5px solid rgba(239, 68, 68, .85) !important;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .35);
  align-items: center !important;
  justify-content: center !important;
  z-index: 2;
  white-space: nowrap;
  margin: 0 !important;
  text-align: center;
  box-sizing: border-box !important;
}

/* Когда бейдж реально видим (JS выставил display:inline-flex) — делаем его flex-контейнером */
html.sb-collapsed .sidebar .nav-item .nav-badge[style*="display:inline-flex"],
html.sb-collapsed .sidebar .nav-item .nav-badge[style*="display: inline-flex"] {
  display: flex !important;
}

.task-action-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px;
  border-radius: 6px;
  color: var(--gray);
  transition: all .15s;
  display: flex;
  align-items: center;
  justify-content: center;
}

.task-action-btn:hover {
  background: rgba(59, 130, 246, .08);
  color: var(--primary);
}

.task-dropdown {
  display: none;
  flex-direction: column;
  position: absolute;
  right: 0;
  top: 100%;
  z-index: 100;
  background: rgba(255, 255, 255, .98);
  backdrop-filter: blur(12px);
  border: 1px solid rgba(148, 163, 184, .12);
  border-radius: 10px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .12);
  min-width: 170px;
  padding: 4px 0;
  margin-top: 4px;
}

.task-dd-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border: none;
  background: none;
  cursor: pointer;
  color: var(--dark);
  font-size: 13px;
  font-family: inherit;
  transition: background .1s;
  width: 100%;
  text-align: left;
}

.task-dd-item:hover {
  background: rgba(59, 130, 246, .06);
}

.task-dd-danger {
  color: #ef4444;
}

.task-dd-danger:hover {
  background: rgba(239, 68, 68, .06);
}

.task-dd-sep {
  height: 1px;
  background: rgba(148, 163, 184, .1);
  margin: 3px 0;
}

.mon-del-btn {
  position: absolute;
  top: 2px;
  right: 2px;
  background: none;
  border: none;
  cursor: pointer;
  color: rgba(148, 163, 184, .4);
  font-size: 10px;
  padding: 2px 4px;
  border-radius: 4px;
  transition: all .15s;
  opacity: 0;
}

.chat-bubble-wrap:hover .mon-del-btn {
  opacity: 1;
}

.mon-del-btn:hover {
  color: #ef4444;
  background: rgba(239, 68, 68, .1);
}

.notif-mark-read-btn {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1px solid rgba(0, 122, 255, .2);
  background: rgba(0, 122, 255, .06);
  color: #007AFF;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all .15s;
  align-self: center;
  padding: 0
}

.notif-mark-read-btn:hover {
  background: #007AFF;
  color: #fff;
  border-color: #007AFF
}

.topbar-bell {
  position: relative;
  background: none !important;
  border: 1px solid rgba(148, 163, 184, .2) !important;
  border-radius: 10px !important;
  width: 38px !important;
  height: 38px !important;
  min-height: 38px !important;
  min-width: 38px !important;
  padding: 0 !important;
  cursor: pointer;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  flex-shrink: 0;
  transition: all .2s;
  color: #64748b
}

/* Тултип топбар-кнопок раньше рендерился ЗДЕСЬ через ::after/::before
   (CSS-only attr(data-tip)). Параллельно crm-tips.js конвертит data-tip
   в data-crm-tip и рисует свой стандартный CRM-тултип, поэтому при hover
   появлялись ДВА тултипа сразу (легаси CSS + JS-overlay). Удалили CSS-only
   вариант — остался единый стиль через crm-tips.js (data-tip → автомат). */

.topbar-bell:hover {
  background: rgba(59, 130, 246, .08);
  border-color: rgba(59, 130, 246, .2);
  color: var(--primary)
}

.topbar-bell svg {
  transition: transform .2s
}

.topbar-bell:hover svg {
  transform: rotate(15deg)
}

.topbar-bell-badge {
  position: absolute;
  top: -5px;
  right: -5px;
  background: linear-gradient(135deg, #ef4444, #f97316);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  min-width: 18px;
  height: 18px;
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* line-height:1 + box-sizing — без этого browser default line-height
     (~1.4-1.6) делал цифры выше 14px content-box (height 18 минус 2x2 border),
     визуально текст сдвигался вверх. */
  line-height: 1;
  box-sizing: border-box;
  padding: 0 4px;
  box-shadow: 0 2px 6px rgba(239, 68, 68, .35);
  border: 2px solid #fff
}

.topbar-push-bell {
  width: auto !important;
  height: auto !important;
  min-width: auto !important;
  padding: 4px 10px !important;
  gap: 0;
  border-radius: 6px !important;
  font-size: 11px !important;
  white-space: nowrap;
  font-weight: 600 !important;
  letter-spacing: 0;
  /* Палитра .ic-public-warn (как у кнопок-секондари) */
  background: linear-gradient(135deg, rgba(59, 130, 246, .08), rgba(99, 102, 241, .08)) !important;
  border-color: rgba(59, 130, 246, .22) !important;
  color: #1d4ed8 !important;
}
.topbar-push-bell:hover:not(.push-active) {
  background: linear-gradient(135deg, rgba(59, 130, 246, .14), rgba(99, 102, 241, .14)) !important;
  border-color: rgba(59, 130, 246, .35) !important;
  color: #1e40af !important;
}

select.form-control,
select {
  background-repeat: no-repeat !important;
}

.app-num {
  /* По жалобе «колонка # сжата и номера полностью не влазят, надо под
     контент расширить» — увеличили padding (горизонталь 10px вместо 7px)
     и font-size до 12px. Также `white-space: nowrap` гарантирует что
     номер не порвётся по слогам даже при очень узком родителе. */
  display: inline-block;
  background: rgba(59, 130, 246, .1);
  color: var(--primary);
  font-size: 12px;
  font-weight: 700;
  padding: 2px 10px;
  border-radius: 8px;
  margin-right: 8px;
  vertical-align: middle;
  letter-spacing: .2px;
  font-family: 'SF Mono', Monaco, Consolas, monospace;
  white-space: nowrap;
}

.topbar-app-search {
  display: inline-flex;
  align-items: center;
  gap: 0;
  background: rgba(255, 255, 255, .6);
  border: 1px solid rgba(148, 163, 184, .22);
  border-radius: 10px;
  padding: 0;
  overflow: hidden;
  height: 37.9px;
  transition: border-color .15s, background .15s;
}

.topbar-app-search:focus-within {
  border-color: var(--primary);
  background: #fff;
  box-shadow: 0 0 0 3px rgba(59, 130, 246, .08);
}

.topbar-app-search input {
  width: 170px;
  border: none;
  outline: none;
  background: transparent;
  font-size: 12.5px;
  font-family: var(--font);
  color: #0f172a;
  padding: 0 14px;
  height: 100%;
}

.topbar-app-search input::placeholder {
  color: #94a3b8;
}

.topbar-app-search button {
  border: none;
  background: rgba(59, 130, 246, .1);
  color: var(--primary);
  cursor: pointer;
  padding: 0 12px;
  height: 100%;
  display: flex;
  align-items: center;
  border-radius: 0;
}

.topbar-app-search button:hover {
  background: rgba(59, 130, 246, .18);
}

.topbar-handler-btn {
  width: auto !important;
  height: auto !important;
  min-width: auto !important;
  padding: 4px 10px !important;
  border-radius: 6px !important;
  font-size: 11px !important;
  white-space: nowrap;
  font-weight: 400 !important;
  letter-spacing: 0;
  text-decoration: none !important;
  color: #64748b !important;
  display: inline-flex !important;
  align-items: center !important;
}

.topbar-handler-btn:hover {
  color: var(--primary) !important;
}

.topbar-push-bell.push-active {
  border-color: rgba(34, 197, 94, .3) !important;
  color: #16a34a !important;
  background: rgba(34, 197, 94, .06) !important
}

.topbar-push-bell.push-active:hover {
  background: rgba(34, 197, 94, .12) !important;
  border-color: rgba(34, 197, 94, .4) !important
}

#proposals-table tbody tr[draggable] {
  transition: opacity .15s
}

#proposals-table tbody tr[draggable]:active {
  cursor: grabbing
}

.drag-placeholder td {
  background: var(--primary) !important;
  height: 3px !important;
  padding: 0 !important;
  border: none !important
}

.read-check {
  font-size: 11px;
  margin-left: 3px;
  opacity: .7;
  letter-spacing: -2px
}

/* Proposal row stage colors */
#proposals-table tbody tr.stage-approved {
  background: rgba(34, 197, 94, .06) !important
}

#proposals-table tbody tr.stage-issued {
  background: rgba(22, 163, 74, .12) !important
}

#proposals-table tbody tr.stage-additional_request {
  background: rgba(245, 158, 11, .06) !important
}

#proposals-table tbody tr.stage-rejected {
  background: rgba(239, 68, 68, .06) !important
}

#proposals-table tbody tr.stage-signing {
  background: rgba(139, 92, 246, .06) !important
}

.notif-panel-header {
  justify-content: space-between
}

.notif-panel-header h3 {
  flex: 1;
  min-width: 0
}

.notif-panel-actions {
  display: flex;
  align-items: center;
  /* space-between — левая группа («Прочитать всё»/«Очистить всё») прижимается
     к левому краю, правая (snooze/settings/close) — к правому. Раньше
     justify-content:flex-start + flex:1 spacer работали, но spacer был
     внутри inline-flex'a и иногда схлопывался. space-between — нативный
     и надёжный способ «развести по краям». */
  justify-content: space-between;
  gap: 8px;
  padding: 4px 14px 12px;
  border-bottom: 1px solid rgba(0, 0, 0, .06);
  flex-shrink: 0;
  background: #fff
}

.notif-panel-btn-clear {
  background: #fee2e2 !important;
  color: #dc2626 !important;
  border: none !important
}

.notif-tabs-strip {
  display: grid;
  width: 100%;
  gap: 4px;
  padding: 8px 12px;
  border-bottom: 1px solid #f1f5f9;
  flex-shrink: 0;
  box-sizing: border-box;
  align-items: stretch
}

.notif-tab-btn {
  min-width: 0;
  min-height: 26px;
  max-height: 30px;
  padding: 3px 5px;
  border-radius: 6px;
  font-size: 10.5px;
  font-weight: 600;
  line-height: 1.15;
  border: none;
  cursor: pointer;
  transition: background .15s, color .15s, opacity .15s;
  text-align: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  font-family: var(--font);
  box-sizing: border-box
}

.notif-tab-btn:hover {
  opacity: .92
}

.notif-tab-btn .notif-tab-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap
}

.notif-tab-unread {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 15px;
  height: 15px;
  padding: 0 3px;
  border-radius: 7px;
  font-size: 8.5px;
  font-weight: 700;
  flex-shrink: 0;
  line-height: 1
}

.notif-tab-unread--yellow {
  background: #fcd34d;
  color: #78350f
}

.notif-tab-unread--red {
  background: #fecaca;
  color: #991b1b
}

.notif-panel-gear {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: none;
  border-radius: 10px;
  background: rgba(148, 163, 184, .12);
  color: #64748b;
  cursor: pointer;
  transition: background .15s, color .15s
}

.notif-panel-gear:hover {
  background: rgba(59, 130, 246, .12);
  color: var(--primary)
}

.manager-notif-prefs-scroll {
  display: flex;
  flex-direction: column;
  gap: 0
}

.notif-prefs-section {
  margin-bottom: 16px;
  padding: 14px 16px;
  background: rgba(248, 250, 252, .8);
  border-radius: 12px;
  border: 1px solid rgba(148, 163, 184, .1)
}

.notif-prefs-section:last-child {
  border-bottom: none;
  margin-bottom: 0;
  padding-bottom: 0
}

.notif-prefs-section-title {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--dark-2);
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  gap: 8px
}

.notif-prefs-lead {
  font-size: 12px;
  color: var(--gray);
  margin: 0 0 8px;
  line-height: 1.4
}

.notif-prefs-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  cursor: pointer;
  font-size: 13px;
  color: var(--dark);
  border-bottom: 1px solid rgba(148, 163, 184, .06)
}

.notif-prefs-row--compact {
  padding: 6px 0
}

.notif-prefs-row input[type=checkbox] {
  margin-top: 3px;
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  accent-color: var(--primary)
}

.notif-prefs-label {
  font-weight: 500;
  display: block
}

.notif-prefs-hint {
  display: block;
  font-size: 11.5px;
  color: var(--gray);
  margin-top: 2px;
  line-height: 1.35
}

/* ── Аккордеон-секции в настройках уведомлений ────────────────────────────
   Раньше все секции (Категории, Статусы, Стадии банка, Документы, Дополнительно)
   рендерились развёрнутыми — модалка превращалась в длинную ленту тогглов
   на 30+ позиций, юзер крутил колесо чтобы найти нужное. Теперь каждая
   секция — collapsible <details> с кратким summary: иконка + название +
   бейдж "X заглушено / Y всего" + chevron. По умолчанию все закрыты,
   юзер кликает по нужной — раскрывается только она. */
.notif-prefs-section--accordion {
  padding: 0;
}
.notif-prefs-section--accordion[open] {
  background: rgba(255, 255, 255, .9);
  box-shadow: 0 1px 3px rgba(15, 23, 42, .04);
}
.notif-prefs-section--accordion > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  cursor: pointer;
  list-style: none;
  user-select: none;
  border-radius: 12px;
  transition: background .12s;
}
.notif-prefs-section--accordion > summary::-webkit-details-marker {
  display: none;
}
.notif-prefs-section--accordion > summary:hover {
  background: rgba(241, 245, 249, .8);
}
.notif-prefs-section--accordion[open] > summary {
  border-bottom: 1px solid rgba(148, 163, 184, .12);
  border-radius: 12px 12px 0 0;
}
.notif-prefs-summary-ico {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  color: var(--primary);
  background: rgba(59, 130, 246, .08);
}
.notif-prefs-summary-title {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--dark-2);
}
.notif-prefs-summary-count {
  flex-shrink: 0;
  font-size: 11px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 10px;
  background: rgba(148, 163, 184, .15);
  color: var(--gray);
  letter-spacing: .02em;
}
.notif-prefs-summary-count--active {
  background: rgba(245, 158, 11, .12);
  color: #b45309;
}
.notif-prefs-summary-chevron {
  flex-shrink: 0;
  color: var(--gray);
  transition: transform .15s;
}
.notif-prefs-section--accordion[open] > summary .notif-prefs-summary-chevron {
  transform: rotate(180deg);
}
.notif-prefs-section--accordion > .notif-prefs-section-body {
  padding: 6px 14px 12px;
}
.notif-prefs-section--accordion > .notif-prefs-section-body > .notif-prefs-lead {
  margin-top: 6px;
}

/* Поиск по тогглам — спрятать те, что не подходят под фильтр */
.notif-prefs-row.notif-prefs-row--hidden,
.notif-prefs-section--accordion.notif-prefs-section--hidden {
  display: none !important;
}

/* «Сводка» в шапке модалки: общая кнопка «Включить все», статус всего */
.notif-prefs-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 12px;
  padding: 10px 12px;
  background: linear-gradient(135deg, #eff6ff, #f5f3ff);
  border: 1px solid rgba(99, 102, 241, .18);
  border-radius: 10px;
}
.notif-prefs-toolbar__search {
  flex: 1;
  min-width: 140px;
  padding: 7px 10px;
  border: 1px solid rgba(148, 163, 184, .25);
  border-radius: 8px;
  font-size: 12.5px;
  font-family: inherit;
  background: #fff;
  outline: none;
  transition: border-color .15s, box-shadow .15s;
}
.notif-prefs-toolbar__search:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(59, 130, 246, .12);
}
.notif-prefs-toolbar__btn {
  flex-shrink: 0;
  padding: 7px 12px;
  border: 1px solid rgba(99, 102, 241, .35);
  background: #fff;
  color: #4338ca;
  border-radius: 8px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  transition: background .12s, border-color .12s;
}
.notif-prefs-toolbar__btn:hover {
  background: rgba(99, 102, 241, .08);
  border-color: #6366f1;
}

/* ── Services flyout: «Сервисы» как dropdown ──────────────────────────────
   Триггер `.nav-tools-trigger` (имя класса историческое) — это обычный
   .nav-item внутри сайдбара/таскбара. Сам flyout — отдельный элемент
   `.nav-tools-flyout-global` в <body>, его позицию ставит JS относительно
   триггера через getBoundingClientRect. Это позволяет flyout'у
   «вылезти» из sidebar-nav (у которого overflow-y:auto) и работать
   одинаково в режиме сайдбара и в режиме «панель вкладок».
   Show: hover на триггер ИЛИ click (mobile). Hide: mouseleave на триггер
   и flyout (с задержкой 200мс), click outside, Esc. */
.nav-tools-trigger {
  cursor: pointer;
}

.nav-tools-trigger .nav-tools-arrow {
  /* Стрелочка-индикатор «есть подменю» — вплотную к label-тексту
     (margin-left:6px), не на правом краю пункта. Раньше стояла через
     margin-left:auto → визуально «улетала» в правый-нижний угол при
     длинных названиях и плохо ассоциировалась с текстом вкладки.
     Вертикальное центрирование — через align-items:center у .nav-item. */
  margin-left: 6px;
  align-self: center;
  opacity: .75;
  color: rgba(255, 255, 255, .85);
  transition: transform .15s, opacity .15s, color .15s;
  flex-shrink: 0;
}

.nav-tools-trigger:hover .nav-tools-arrow,
.nav-tools-trigger.is-open .nav-tools-arrow {
  opacity: 1;
  color: #fff;
  transform: translateY(1px);
}

/* ── Sidebar разделитель — тонкая полупрозрачная линия между логическими
   группами пунктов навигации (личные пункты ↔ flyout'ы). ───────────────── */
.sidebar .nav-divider {
  height: 1px;
  margin: 10px 14px 8px;
  background: linear-gradient(90deg,
    rgba(255,255,255,0) 0%,
    rgba(255,255,255,.18) 20%,
    rgba(255,255,255,.18) 80%,
    rgba(255,255,255,0) 100%);
  border: 0;
}
html.sb-collapsed .sidebar .nav-divider {
  margin: 10px 8px 8px;
}

/* В свёрнутом сайдбаре прячем «›»-стрелку и убираем margin-left:auto
   у её псевдо-места — иначе иконка-шестерёнка съезжает влево, освобождая
   место под скрытую стрелку, как видно на скрине пользователя. */
html.sb-collapsed .sidebar .nav-tools-trigger .nav-tools-arrow {
  display: none !important;
}
html.sb-collapsed .sidebar .nav-tools-trigger {
  /* Перебиваем `justify-content:center` из общего правила nav-item —
     там оно уже center, но nav-tools-arrow раньше сдвигал баланс. После
     display:none на arrow центрирование становится корректным. */
  padding-right: 0 !important;
}

.nav-tools-flyout-global {
  position: fixed;
  left: 0;
  top: 0;
  min-width: 230px;
  max-width: 280px;
  /* Раньше было display:none/flex для скрытия — но при первом show'е
     offsetWidth/offsetHeight в скрытом состоянии возвращали 0, а после
     добавления is-visible — реальные размеры. JS позиционировал flyout
     дважды (sync + rAF), и на промежуточном кадре он «прыгал».
     Теперь скрываем через visibility/opacity — размеры читаются всегда,
     позиционирование делается один раз и без подёргивания. */
  display: flex;
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  flex-direction: column;
  gap: 2px;
  padding: 6px;
  background: var(--sidebar-bg, #1e293b);
  border: 1px solid rgba(255, 255, 255, .08);
  border-radius: 10px;
  box-shadow: 0 14px 36px rgba(0, 0, 0, .40), 0 4px 10px rgba(0, 0, 0, .22);
  z-index: 1200;
  /* Плавное появление при наведении на «Сервисы»: лёгкий подъём + scale + fade.
     transform не конфликтует с JS-позиционированием (оно через left/top). */
  transform: translateY(-6px) scale(.97);
  transform-origin: left center;
  transition: opacity .18s ease, transform .18s cubic-bezier(.18, .74, .3, 1.06);
}

.nav-tools-flyout-global.is-visible {
  visibility: visible;
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

.nav-tools-flyout-global .nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 7px;
  color: #fff;
  text-decoration: none;
  font-size: 13px;
  font-weight: 500;
  transition: background .12s, color .12s, transform .12s;
}

/* Hover/active пунктов выпадашки «Сервисы» — как в сайдбаре: светлый
   frosted-фон .14 + белый текст + лёгкий сдвиг вправо. */
.nav-tools-flyout-global .nav-item:hover,
.nav-tools-flyout-global .nav-item.active {
  background: rgba(255, 255, 255, .14);
  color: #fff;
  transform: translateX(2px);
}

.nav-tools-flyout-global .nav-item .nav-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

.nav-tools-flyout-global .nav-item .nav-label {
  font-size: 13px;
  font-weight: 500;
  color: #fff;
  line-height: 1.2;
  /* Override: trigger в sidebar в свернутом режиме скрывает .nav-label,
     но в flyout label всегда видна */
  display: inline !important;
  opacity: 1 !important;
}

/* ── Светлый вариант flyout — для режима «таскбар» (body.nav-taskbar) ─────
   В сайдбар-режиме flyout остаётся тёмным (под цвет тёмного сайдбара),
   а когда панель навигации внизу/сверху как dock — фон страницы вокруг
   светлый, и тёмная плитка на светлом смотрится резко. Меняем подложку
   на белую, текст — тёмный, тень мягче. */
body.nav-taskbar .nav-tools-flyout-global {
  background: #ffffff;
  border-color: rgba(15, 23, 42, .08);
  box-shadow: 0 14px 36px rgba(15, 23, 42, .14),
              0 4px 10px rgba(15, 23, 42, .08);
}
body.nav-taskbar .nav-tools-flyout-global .nav-item {
  color: #1e293b;
}
body.nav-taskbar .nav-tools-flyout-global .nav-item:hover,
body.nav-taskbar .nav-tools-flyout-global .nav-item.active {
  background: rgba(59, 130, 246, .08);
}
body.nav-taskbar .nav-tools-flyout-global .nav-item .nav-label {
  color: #1e293b;
}

/* ── Reply / quote card в чатах (групповой, полноэкранный, виджет) ──────────
   Используется renderChatQuotes (см. manager/chat.html и
   partials/chat_widget.html). Раньше каждый <div> рендерился с огромным
   inline style="..." блоком, сложно было поддерживать визуальную
   консистентность между двумя файлами + хочется hover-state, который inline
   стилем не сделать. Перенесли всю логику в класс .crm-reply-card,
   data-own="0|1" различает входящие/исходящие бабблы. */
.crm-reply-card {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  padding: 8px 11px 8px 10px;
  margin: 0 0 8px;
  border-radius: 10px;
  cursor: pointer;
  transition: background .15s ease, transform .15s ease;
  user-select: none;
}
.crm-reply-card:active { transform: scale(.985); }
.crm-reply-card__icon { flex-shrink: 0; margin-top: 2px; }
.crm-reply-card__body { flex: 1; min-width: 0; }
.crm-reply-card__author {
  font-weight: 600;
  font-size: 12px;
  line-height: 1.25;
  margin-bottom: 2px;
  letter-spacing: -.01em;
}
.crm-reply-card__text {
  font-size: 12px;
  line-height: 1.4;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Входящие баблы (other) — голубой акцент */
.crm-reply-card[data-own="0"] {
  background: rgba(59, 130, 246, .10);
  border-left: 3px solid var(--primary);
}
.crm-reply-card[data-own="0"]:hover { background: rgba(59, 130, 246, .16); }
.crm-reply-card[data-own="0"] .crm-reply-card__icon { color: var(--primary); }
.crm-reply-card[data-own="0"] .crm-reply-card__author { color: var(--primary); }
.crm-reply-card[data-own="0"] .crm-reply-card__text { color: #475569; }
/* Исходящие баблы (own) — белый акцент поверх gradient'а */
.crm-reply-card[data-own="1"] {
  background: rgba(255, 255, 255, .22);
  border-left: 3px solid rgba(255, 255, 255, .9);
}
.crm-reply-card[data-own="1"]:hover { background: rgba(255, 255, 255, .32); }
.crm-reply-card[data-own="1"] .crm-reply-card__icon { color: rgba(255, 255, 255, .9); }
.crm-reply-card[data-own="1"] .crm-reply-card__author { color: #fff; }
.crm-reply-card[data-own="1"] .crm-reply-card__text { color: rgba(255, 255, 255, .88); }

/* Flash-эффект для оригинального сообщения при клике на reply-card */
.crm-msg-flash { animation: crm-msg-flash-kf 1.4s ease; border-radius: inherit; }
@keyframes crm-msg-flash-kf {
  0%   { background: rgba(251, 191, 36, .0); }
  15%  { background: rgba(251, 191, 36, .35); }
  100% { background: rgba(251, 191, 36, .0); }
}

/* Twemoji — эмодзи в чате как <img> (единый вид на всех ОС вместо системного).
   1em → масштаб по контексту (текст сообщения, реакции-чипы). См. crm-twemoji.js. */
img.tw-emoji {
  height: 1em; width: 1em; display: inline-block;
  vertical-align: -0.12em; margin: 0 .05em; object-fit: contain;
}
/* В реакциях-чипах эмодзи центрируется флексом — убираем сдвиг/отступы. */
.rx-chip img.tw-emoji, .reaction-chip img.tw-emoji, .msg-reaction img.tw-emoji,
.react-emoji img.tw-emoji, .emoji-reaction img.tw-emoji {
  vertical-align: middle; margin: 0;
}
