/* =============================================================
   XERP2 — карточный layout.
   Topbar сверху (компакт), под ним — широкий контейнер с
   карточками/гридами. Sidebar убран по требованию: интерфейс
   полностью карточный.
   ============================================================= */

/* ---------- Topbar ---------- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--kz-sidebar-bg);
  color: var(--kz-text-on-dark);
  box-shadow: 0 2px 8px rgba(0,0,0,0.18);
}
.topbar__row {
  display: flex;
  align-items: center;
  gap: 14px;
  height: 56px;
  padding: 0 20px;
  max-width: 1400px;
  margin: 0 auto;
}
.topbar__brand {
  display: flex; align-items: center; gap: 10px;
  text-decoration: none;
  color: var(--kz-text-on-dark);
}
/* Лого в шапке — лёгкая вертикальная растяжка (1:1.07), как на login. */
.topbar__brand img { width: 38px; height: 40px; object-fit: fill; }
/* Имя в две строки: «KZHS» / «GROUP», ≈ высота лого. */
.topbar__brand-name {
  font-size: 14px;
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: .04em;
  white-space: nowrap;
}
.topbar__brand-sub  { font-size: 12px; opacity: .65; letter-spacing: .04em; white-space: nowrap; }

.topbar__nav {
  display: flex; gap: 4px;
  scroll-snap-type: x proximity;
  align-items: center;
  /* На узких экранах items не переносятся (flex-wrap:nowrap), вместо
     этого — горизонтальный скролл колесом / свайпом. ВАЖНО: НЕ ставим
     mask-image / filter / transform на этот контейнер — они создают
     containing block для position:fixed потомков, и dropdown «Финансы»
     /« Справочники» не выходят за пределы nav. */
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: visible;
  scrollbar-width: none;
  flex: 1; min-width: 0;
}
.topbar__nav::-webkit-scrollbar { display: none; }

/* Обёртка навигации + кнопки прокрутки (‹ ›). Показываются только когда меню
   переполнено (классы can-left/can-right ставит JS). ВАЖНО: на .topbar__nav-wrap
   только position:relative — без transform/filter, иначе fixed-дропдауны групп
   будут позиционироваться относительно обёртки, а не окна. */
.topbar__nav-wrap {
  position: relative;
  flex: 1; min-width: 0;
  display: flex; align-items: center;
  margin-left: 16px;
}
.topbar__nav-scroll {
  position: absolute; top: 0; bottom: 0; z-index: 6;
  width: 36px; padding: 0; border: none; cursor: pointer;
  display: none; align-items: center; justify-content: center;
  color: var(--kz-text-on-dark);
}
.topbar__nav-scroll i { font-size: 24px; }
.topbar__nav-scroll:hover i { color: var(--kz-sidebar-accent); }
/* Градиент-фейд к фону шапки — подсказка, что под кнопкой есть ещё пункты. */
.topbar__nav-scroll--left {
  left: 0; justify-content: flex-start;
  background: linear-gradient(to right, var(--kz-sidebar-bg) 60%, transparent);
}
.topbar__nav-scroll--right {
  right: 0; justify-content: flex-end;
  background: linear-gradient(to left, var(--kz-sidebar-bg) 60%, transparent);
}
.topbar__nav-wrap.can-left  .topbar__nav-scroll--left  { display: flex; }
.topbar__nav-wrap.can-right .topbar__nav-scroll--right { display: flex; }
.topbar__nav > a, .topbar__nav > .topbar__group { scroll-snap-align: start; }
.topbar__nav a {
  color: var(--kz-text-on-dark);
  /* W4: на 1280px пункты шире зоны (~1156px против ~792px) — прокрутка
     осознанная (стрелки+фейд). Паддинг ужат 12->10px + scroll-snap, чтобы
     видимые пункты не резались посередине. */
  padding: 8px 10px;
  border-radius: 8px;
  font-size: 14px;
  white-space: nowrap;
  flex-shrink: 0;
  opacity: .85;
  /* Лёгкая подложка у неактивных пунктов — чтобы кнопки были
     визуально различимы на тёмной шапке. */
  background: rgba(255, 255, 255, .07);
  transition: background-color .15s ease, opacity .15s ease;
}
.topbar__nav a:hover { background: var(--kz-sidebar-accent); opacity: 1; }
.topbar__nav a.is-active { background: var(--kz-sidebar-accent); opacity: 1; }

/* ---------- Apple-style notification badge ----------
   Красный кружок с белым числом в правом-верхнем углу пункта меню.
   Используется на «Задачи» / «Снабжение» — счётчики приходят из
   core.context_processors.nav_badges. Inline-flex на самой ссылке
   позволяет позиционировать .nav-badge относительно неё. */
.topbar__link-with-badge {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  /* Резерв справа под бейдж, чтобы он сидел в правом-верхнем углу
     внутри кнопки и не налезал на соседний активный пункт. */
  padding-right: 28px !important;
}
.nav-badge {
  /* iOS-style: ярко-красный круг с белой жирной цифрой. Сидит в
     ВЕРХНЕМ-ПРАВОМ углу кнопки. Не вылазит за границу пункта —
     поэтому соседний .is-active его никогда не перекрывает. */
  position: absolute;
  top: 3px;
  right: 4px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: #ff3b30;             /* iOS systemRed */
  color: #ffffff;
  font-size: 11px;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
  letter-spacing: -0.2px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .35);
  pointer-events: none;
}

/* ---------- Группы в шапке (раскрываемое подменю) ----------
   Чистый CSS-hover dropdown. Заголовок группы — обычная <a>,
   ведёт на индекс раздела (Финансы → главная финансов и т.д.).
   Подменю появляется при наведении ИЛИ при keyboard-focus. */
.topbar__group {
  position: relative;
  /* inline-flex держит .topbar__group-toggle на одной базовой
     линии с обычными ссылками-сёстрами. Без этого <div>-обёртка
     сдвигала «Финансы»/«Справочники» по вертикали. */
  display: inline-flex;
  align-items: center;
}
.topbar__group-toggle { /* стиль наследует от .topbar__nav a */ }
.topbar__caret { font-size: 10px; opacity: .7; margin-left: 2px; }

.topbar__group-menu {
  display: none;
  position: fixed;
  top: 56px;
  left: 0;
  min-width: 240px;
  margin-top: 0;
  background: #272444;
  color: #ffffff;
  border-radius: 10px;
  box-shadow: 0 12px 30px rgba(0, 0, 0, .45);
  /* padding-top больше обычного — невидимая «зона касания» сверху,
     чтобы курсор мог перейти с .topbar__group-toggle вниз без отрыва
     от hover-области. Раньше тут был 2px gap → меню исчезало. */
  padding: 12px 6px 6px;
  flex-direction: column;
  gap: 2px;
  z-index: 300;
  /* Длинные меню (Финансы) — прокрутка вместо вылезания за экран. */
  max-height: calc(100vh - 64px);
  overflow-y: auto;
}
.topbar__group:hover > .topbar__group-menu,
.topbar__group:focus-within > .topbar__group-menu {
  display: flex;
}
.topbar__group-menu a {
  color: #ffffff;
  text-decoration: none;
  padding: 8px 12px;
  border-radius: 6px;
  font-size: 13px;
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
  /* Лёгкая подложка у неактивных пунктов — чтобы строки меню были
     визуально отделены друг от друга на тёмном фоне панели. */
  background: rgba(255, 255, 255, .06);
  transition: background-color .15s ease;
}
.topbar__group-menu a i { color: #ffffff; opacity: .85; }
.topbar__group-menu a:hover { background: #605aa1; }
/* Под-заголовок секции внутри выпадающего меню (Операции/Зарплата/…). */
.topbar__group-section {
  color: rgba(255, 255, 255, .5);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .04em;
  padding: 8px 12px 2px;
  margin-top: 4px;
}
.topbar__group-section:first-child { margin-top: 0; }

/* ---------- ⚙ Настройки (язык, тема, …) ---------- */
.settings-menu { position: relative; }
.settings-menu__btn { cursor: pointer; background: none; border: none; }
.settings-menu__panel {
  display: none;
  position: absolute;
  top: 100%;
  right: 0;
  min-width: 220px;
  margin-top: 2px;
  background: var(--kz-card-bg);
  color: var(--kz-text);
  border-radius: 10px;
  box-shadow: 0 12px 30px rgba(0, 0, 0, .25);
  padding: 10px;
  z-index: 200;
}
.settings-menu:hover > .settings-menu__panel,
.settings-menu:focus-within > .settings-menu__panel {
  display: block;
}
.settings-menu__section-label {
  color: var(--kz-text-muted);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .04em;
  margin: 6px 0 4px;
}
.settings-menu__section-label:first-child { margin-top: 0; }
.settings-menu__row { padding: 4px 0; }

/* Раньше — `flex: 1`, толкало topbar__actions вправо. Теперь
   `.topbar__nav` сам имеет `flex: 1; overflow-x: auto`, так что
   spacer больше не нужен — оставляем нулевую ширину для совместимости. */
.topbar__spacer { flex: 0 0 auto; }

.topbar__actions {
  display: flex; align-items: center; gap: 8px;
}
.topbar__icon-btn {
  position: relative;
  width: 38px; height: 38px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px;
  color: var(--kz-text-on-dark);
  text-decoration: none;
}
.topbar__icon-btn:hover { background: var(--kz-sidebar-accent); }
.topbar__icon-btn i { font-size: 22px; }
.badge-dot {
  position: absolute; top: 4px; right: 4px;
  min-width: 18px; height: 18px; padding: 0 5px;
  font-size: 11px; line-height: 18px; text-align: center;
  background: var(--kz-danger); color: white;
  border-radius: 10px;
}

/* User menu dropdown */
.user-menu { position: relative; }
.user-menu__btn {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 12px;
  background: rgba(255,255,255,0.08);
  color: var(--kz-text-on-dark);
  border-radius: 8px;
}
.user-menu__btn:hover { background: var(--kz-sidebar-accent); }
.user-menu__avatar {
  width: 28px; height: 28px;
  border-radius: 50%;
  background: var(--kz-sidebar-accent);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: bold;
}
/* Когда аватар — реальное фото из Person.photo. Сохраняем размер 28×28,
   обрезаем по кругу, прячем фон. */
.user-menu__avatar--img {
  object-fit: cover;
  background: transparent;
  display: block;
}
.user-menu__panel {
  position: absolute; right: 0; top: 100%; margin-top: 6px;
  min-width: 220px;
  background: var(--kz-card-bg);
  color: var(--kz-text);
  border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0,0,0,0.18);
  padding: 8px;
  z-index: 200;
}
.user-menu__panel a, .user-menu__panel button {
  display: flex; align-items: center; gap: 10px;
  width: 100%; text-align: left;
  padding: 9px 12px;
  border-radius: 8px;
  font-size: 14px;
  color: var(--kz-text);
  /* Тонкая подложка у неактивных пунктов — отделяет строки на
     светлом фоне панели. На dark — лёгкая белая alpha-подложка. */
  background: rgba(0, 0, 0, .03);
  transition: background-color .15s ease;
}
[data-theme="dark"] .user-menu__panel a,
[data-theme="dark"] .user-menu__panel button { background: rgba(255, 255, 255, .04); }
.user-menu__panel a:hover, .user-menu__panel button:hover { background: var(--kz-bg); }
.user-menu__divider {
  height: 1px; background: var(--kz-border); margin: 6px 4px;
}


/* Language pills (и тогглер темы) — внутри settings-menu panel.
   Раньше использовалось `color: var(--kz-text-on-dark)` + opacity 0.55,
   но панель стоит на светлом фоне var(--kz-card-bg) — белый текст
   на белом фоне был нечитаем. Делаем pill-кнопки с границей и
   фоновым контрастом, как обычные .btn--ghost. */
.lang-pills { display: flex; gap: 4px; flex-wrap: wrap; }
.lang-pills form { display: inline; }
/* Селектор языка теперь — обычные ссылки (<a>), но раньше тут были
   <button>'ы. Стилизуем и то и другое одинаково, чтобы при возможной
   обратной миграции стиль остался. */
.lang-pills button,
.lang-pills > a {
  padding: 6px 12px;
  border-radius: 8px;
  background: var(--kz-bg);
  color: var(--kz-text);
  border: 1px solid var(--kz-border);
  font-size: 13px;
  letter-spacing: .04em;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  text-decoration: none;
  transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.lang-pills button:hover,
.lang-pills > a:hover { background: var(--kz-border); }
.lang-pills button.is-active,
.lang-pills > a.is-active {
  background: var(--kz-sidebar-accent);
  color: var(--kz-text-on-dark);
  border-color: var(--kz-sidebar-accent);
}

/* ---------- Container / page ---------- */
.page {
  max-width: 1400px;
  margin: 0 auto;
  padding: 24px 20px 80px;
}
.page__header {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  margin-bottom: 20px;
}
.page__title { font-size: 24px; }
.page__sub  { color: var(--kz-text-muted); font-size: 14px; }

/* ---------- Cards & grid ---------- */
.card {
  position: relative;        /* для absolute .tile__footer и оверлеев */
  background: var(--kz-card-bg);
  border-radius: var(--kz-radius);
  box-shadow: var(--kz-shadow-card);
  padding: 18px;
  margin-bottom: 16px;
}
/* Резерв под footer в любой карточке. Высота — на 2 ряда chip'ов
   (см. комментарий у .tile:has(.tile__footer) ниже). */
.card:has(.tile__footer) { padding-bottom: 100px; }
.card__title  { font-size: 16px; margin-bottom: 12px; }

.grid {
  display: grid;
  gap: 16px;
}
/* Все ячейки в строке грида растягиваются на одну высоту (под самую
   высокую). Без absolute-чипов и без min-height — просто height: 100%. */
.grid > .card,
.grid > .tile,
.grid > .tile-wrap { height: 100%; margin-bottom: 0; }
.grid > .tile-wrap > .tile { height: 100%; }
/* Минимум колонки. 320px / 220px — чтобы суммы (1 234 567 KZT) и
   подписи помещались в одну строку без переноса и троеточия. */
.grid--cards    { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
.grid--stats    { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
.grid--two      { grid-template-columns: 1fr 1fr; }

@media (max-width: 720px) {
  .grid--two { grid-template-columns: 1fr; }
}

/* Card with hover affordance for clickable tiles.
   align-items: stretch — items растягиваются по вертикали; .tile__icon
   с фиксированными размерами остаётся 46×46, а контент-блок стретчится
   на всю высоту, чтобы margin-top: auto на chip-row работал. */
.tile {
  display: flex; gap: 14px; align-items: stretch;
  position: relative;            /* для absolute .tile__footer */
  background: var(--kz-card-bg);
  border-radius: var(--kz-radius);
  box-shadow: var(--kz-shadow-card);
  padding: 18px;
  text-decoration: none;
  color: inherit;
  transition: transform .12s ease, box-shadow .12s ease;
}
.tile:hover { transform: translateY(-2px); box-shadow: 0 10px 24px rgba(39,36,68,.12); }
.tile__icon {
  width: 46px; height: 46px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 10px;
  background: rgba(96,90,161,0.12);
  color: var(--kz-sidebar-accent);
  font-size: 26px;
  flex-shrink: 0;
  /* align-self: flex-start — иконка не растягивается с stretch на родителе. */
  align-self: flex-start;
}
.tile__title { font-weight: 600; }
.tile__sub   { color: var(--kz-text-muted); font-size: 13px; margin-top: 2px; }

/* Контент-блок стандартной row-плитки: <div> сразу после .tile__icon.
   Растягивается на всю высоту, flex-column'ом распределяет содержимое. */
.tile > .tile__icon + div {
  flex: 1;
  min-width: 0;
  align-self: stretch;
  display: flex;
  flex-direction: column;
}

/* Чип-зона как ОТДЕЛЬНЫЙ контейнер. Любая плитка ставит чипы внутри
   `<div class="tile__footer">` — она абсолютно позиционируется внизу
   карточки на полную ширину. Контент карточки получает padding-bottom
   через правило .tile.has-footer ниже. */
.tile__footer {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 14px 18px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  background: var(--kz-card-bg);
  border-radius: 0 0 var(--kz-radius) var(--kz-radius);
  z-index: 1;
}
/* Резерв под footer в любой плитке, где он есть.
   Учитываем, что chip-ы могут перенестись на ВТОРУЮ строку — иначе
   при длинных подписях (например, «На согласовании») второй ряд
   чипов лезет на текст карточки сверху. 100px = padding 14×2 + 2 ряда
   chip'ов высотой ~28px + gap. */
.tile:has(.tile__footer) { padding-bottom: 100px; }
.tile__footer { min-height: 44px; }

/* В flex-строке chip-ов денежный чип всегда первый. */
.chip--money { order: -1; }


/* Stat box */
.stat {
  background: var(--kz-card-bg);
  border-radius: var(--kz-radius);
  box-shadow: var(--kz-shadow-card);
  padding: 14px 18px;
}
.stat__label { color: var(--kz-text-muted); font-size: 13px; }
/* Число + валюта всегда в одну строку (NBSP'ы внутри числа +
   достаточная ширина .grid--stats не дают вывалиться). */
.stat__value { font-size: 26px; margin-top: 4px; white-space: nowrap; }
.stat--success .stat__value { color: var(--kz-success); }
.stat--warning .stat__value { color: var(--kz-warning); }
.stat--danger  .stat__value { color: var(--kz-danger); }

/* ---------- Accordion (карточный аккордеон) ---------- */
.accordion__item {
  background: var(--kz-card-bg);
  border-radius: var(--kz-radius);
  box-shadow: var(--kz-shadow-card);
  margin-bottom: 10px;
  overflow: hidden;
}
.accordion__header {
  display: flex; justify-content: space-between; align-items: center;
  padding: 14px 18px;
  cursor: pointer; user-select: none;
}
.accordion__header i { transition: transform .2s ease; }
.accordion__item[aria-expanded="true"] .accordion__header i { transform: rotate(90deg); }
.accordion__body { padding: 0 18px 16px; display: none; }
.accordion__item[aria-expanded="true"] .accordion__body { display: block; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 16px;
  border-radius: 8px;
  font-size: 14px;
  text-decoration: none;
  cursor: pointer;
  border: 1px solid transparent;
  transition: background .12s ease, transform .05s ease;
}
.btn:active { transform: translateY(1px); }
/* Компактная кнопка — для плотных таблиц/строк (редактор шаблонов и т.п.). */
.btn--sm { padding: 4px 8px; font-size: 12px; gap: 4px; }
.btn--primary { background: var(--kz-sidebar-bg);    color: white; }
.btn--primary:hover { background: var(--kz-sidebar-accent); }
.btn--accent  { background: var(--kz-sidebar-accent);color: white; }
.btn--success { background: var(--kz-success);       color: white; }
.btn--warning { background: var(--kz-warning);       color: white; }
.btn--danger  { background: var(--kz-danger);        color: white; }
.btn--ghost   { background: var(--kz-bg);            color: var(--kz-text); }
.btn--ghost:hover { background: var(--kz-border); }

/* ---------- Inputs ---------- */
.input, .select {
  /* Фиксированная высота, чтобы соседние input/select/date в форме
     выравнивались по одной линии (иначе number/date спиннер
     добавляет миллиметры, выглядит неровно). */
  width: 100%;
  height: 38px;
  box-sizing: border-box;
  padding: 0 12px;
  border-radius: 8px;
  border: 1px solid var(--kz-border);
  background: var(--kz-card-bg);
  color: var(--kz-text);
  font-size: 14px;
  line-height: 36px;
}
.textarea {
  width: 100%;
  box-sizing: border-box;
  padding: 9px 12px;
  border-radius: 8px;
  border: 1px solid var(--kz-border);
  background: var(--kz-card-bg);
  color: var(--kz-text);
  font-size: 14px;
  font-family: inherit;
  line-height: 1.4;
}
.input:focus, .select:focus, .textarea:focus {
  outline: 2px solid var(--kz-sidebar-accent);
  outline-offset: -1px;
  border-color: var(--kz-sidebar-accent);
}
.label  { display: block; color: var(--kz-text-muted); font-size: 13px; margin-bottom: 4px; }
.field  { margin-bottom: 14px; }
/* Чекбокс-поле в той же сетке что обычные input-поля — выравниваем
   по верху контрола (label + input = 17 + 4 + 38 = 59px). */
.field--checkbox {
  display: flex;
  align-items: center;
  min-height: 59px;
  margin-bottom: 14px;
}
.field--checkbox > label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}

/* ---------- Percent input (number + range slider) ---------- */
.percent-input {
  display: flex;
  align-items: center;
  gap: 10px;
}
.percent-input__num {
  width: 80px;
  flex: 0 0 80px;
  text-align: right;
}
.percent-input__range {
  flex: 1;
  height: 6px;
  -webkit-appearance: none;
  appearance: none;
  background: var(--kz-bg);
  border-radius: 3px;
  outline: none;
}
.percent-input__range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--kz-sidebar-accent);
  cursor: pointer;
  border: 2px solid var(--kz-card-bg);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .2);
}
.percent-input__range::-moz-range-thumb {
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--kz-sidebar-accent);
  cursor: pointer;
  border: 2px solid var(--kz-card-bg);
}

/* ---------- Pills / chips ---------- */
.chip {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 12px;
  font-size: 12px;
  background: var(--kz-bg);
}
.chip--success { background: rgba(43,189,126,.15);  color: var(--kz-success); }
.chip--warning { background: rgba(245,166,35,.18);  color: var(--kz-warning); }
.chip--danger  { background: rgba(231,76,60,.15);   color: var(--kz-danger); }
.chip--info    { background: rgba(96,90,161,.15);   color: var(--kz-sidebar-accent); }
/* Денежный чип — число (с NBSP в разрядах) + код валюты в одну строку.
   Ширина колонки grid--cards (320px+) гарантирует, что типичные суммы
   помещаются без троеточия. */
.chip--money { white-space: nowrap; }

/* Тёмная тема: дефолтный .chip и .chip--info переопределяем явно.
   `var(--kz-sidebar-accent)` в dark = #4a4280 (тёмно-фиолетовый), и текст
   таким цветом на тёмном фоне читался плохо — особенно денежный чип
   .chip chip--info. Делаем поярче. */
[data-theme="dark"] .chip       { background: rgba(255,255,255,0.06); color: var(--kz-text); }
[data-theme="dark"] .chip--info { background: rgba(138,130,208,0.18); color: #b8b0e8; }

/* ---------- Table ---------- */
.table {
  width: 100%;
  border-collapse: collapse;
}
.table thead th {
  text-align: left;
  padding: 10px 12px;
  color: var(--kz-text-muted);
  font-weight: 500;
  font-size: 13px;
  border-bottom: 1px solid var(--kz-border);
}
.table tbody td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--kz-border);
}
.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr:hover { background: var(--kz-bg); }

/* ---------- Mobile ---------- */
@media (max-width: 760px) {
  .topbar__row { padding: 0 12px; gap: 8px; }
  .topbar__brand-sub { display: none; }
  .topbar__nav { display: none; }     /* на mobile меню в user dropdown */
  .page { padding: 16px 12px 80px; }
}

/* ---------- Empty/info ---------- */
.muted { color: var(--kz-text-muted); }
.empty {
  text-align: center;
  padding: 32px 16px;
  color: var(--kz-text-muted);
}
.empty i { font-size: 40px; opacity: .5; }

/* ---------- Popup dialog (HTML5 <dialog>) ----------
   Открывается через JS: document.getElementById('id').showModal().
   Бэкграунд (::backdrop) полупрозрачный, форма прокручивается
   целиком если не помещается по высоте. */
dialog.kz-dialog {
  width: min(920px, 96vw);
  max-height: 92vh;
  /* Явно центрируем — без этого Safari/некоторые сборки браузеров
     прижимают <dialog> в левый верхний угол. */
  position: fixed;
  inset: 0;
  margin: auto;
  padding: 18px 20px;
  border: none;
  border-radius: var(--kz-radius);
  box-shadow: 0 18px 42px rgba(0, 0, 0, .25);
  background: var(--kz-card-bg);
  color: var(--kz-text);
  /* Свой скролл, чтобы длинные формы (лот с 16+ полями) не уезжали
     за viewport, и не пришлось городить flex-внутренности. */
  overflow-y: auto;
}
dialog.kz-dialog::backdrop {
  background: rgba(20, 20, 40, .45);
  backdrop-filter: blur(2px);
}

/* ============================================================
   WhatsApp-style chat (chat/index.html, chat/room.html)
   - .wa-shell — двухпанельный grid (sidebar 320px + pane).
   - .wa-sidebar — список комнат с поиском, аватаром, превью.
   - .wa-pane — открытая комната: шапка, лента, composer.
   - .chat-msg — пузырьки сообщений; mine — справа в акценте.
   ============================================================ */
.wa-shell {
  display: grid;
  grid-template-columns: 320px 1fr;
  gap: 0;
  height: calc(100vh - 56px - 48px);
  min-height: 520px;
  border-radius: var(--kz-radius);
  overflow: hidden;
  box-shadow: var(--kz-shadow-card);
  background: var(--kz-card-bg);
}
@media (max-width: 760px) {
  .wa-shell { grid-template-columns: 1fr; height: calc(100vh - 56px - 24px); }
  .wa-sidebar { display: none; }
}

/* ---- Sidebar ---- */
.wa-sidebar {
  display: flex; flex-direction: column;
  background: var(--kz-bg);
  border-right: 1px solid var(--kz-border);
  min-height: 0;
}
.wa-sidebar__head {
  padding: 14px 16px 8px;
  border-bottom: 1px solid var(--kz-border);
  display: flex;
  align-items: center;
  gap: 12px;
}
.wa-sidebar__title { font-size: 18px; margin: 0; flex: 1; }
.wa-sidebar__new {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 6px 10px;
  border-radius: 14px;
  background: var(--kz-sidebar-accent);
  color: #fff;
  border: none;
  cursor: pointer;
  font-size: 12px;
  font-weight: 600;
}
.wa-sidebar__new:hover { filter: brightness(1.1); }
.wa-sidebar__new i { font-size: 15px; }
.wa-sidebar__search {
  margin: 10px 12px;
  padding: 8px 12px;
  border-radius: 18px;
  border: 1px solid var(--kz-border);
  background: var(--kz-card-bg);
  color: var(--kz-text);
  font-size: 13px;
  outline: none;
}
.wa-sidebar__search:focus { border-color: var(--kz-sidebar-accent); }
.wa-sidebar__list {
  flex: 1; min-height: 0;
  overflow-y: auto;
  padding: 0 4px 8px;
}
.wa-room {
  display: flex; gap: 12px; align-items: center;
  padding: 10px 12px;
  border-radius: 10px;
  text-decoration: none;
  color: var(--kz-text);
  margin: 2px 0;
}
.wa-room:hover { background: rgba(96, 90, 161, .08); }
.wa-room.is-active {
  background: rgba(96, 90, 161, .15);
}
.wa-room__avatar {
  width: 42px; height: 42px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--kz-sidebar-accent);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 22px;
}
.wa-room__body { flex: 1; min-width: 0; }
.wa-room__row {
  display: flex; align-items: center; gap: 8px;
}
.wa-room__title {
  flex: 1; min-width: 0;
  font-weight: 600;
  font-size: 14px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wa-room__time {
  font-size: 11px;
  color: var(--kz-text-muted);
  flex-shrink: 0;
}
.wa-room__preview {
  flex: 1; min-width: 0;
  font-size: 12px;
  color: var(--kz-text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wa-room__badge {
  background: #25d366;          /* iOS-style WhatsApp green */
  color: #fff;
  font-size: 11px; font-weight: 700;
  min-width: 18px; height: 18px; padding: 0 6px;
  line-height: 18px; text-align: center;
  border-radius: 9px;
  flex-shrink: 0;
}

/* ---- Right pane ---- */
.wa-pane {
  display: flex; flex-direction: column;
  min-height: 0;
  background:
    linear-gradient(rgba(96, 90, 161, .03), rgba(96, 90, 161, .03)),
    var(--kz-card-bg);
}
.wa-pane__empty {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  color: var(--kz-text-muted);
  gap: 10px;
}
.wa-pane__empty i { font-size: 56px; opacity: .4; }
.wa-pane__head {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 16px;
  background: var(--kz-bg);
  border-bottom: 1px solid var(--kz-border);
}
.wa-pane__head-info { display: flex; gap: 10px; align-items: center; flex: 1; min-width: 0; }
.wa-pane__head-avatar {
  width: 38px; height: 38px;
  border-radius: 50%;
  background: var(--kz-sidebar-accent);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 20px;
}
.wa-pane__head-title { font-weight: 600; }
.wa-pane__head-sub { font-size: 11px; color: var(--kz-text-muted); }
.wa-pane__head-actions { display: flex; gap: 6px; }

/* Обёртка ленты: система координат для плашки «новые сообщения» — та висит
   по нижнему краю ЛЕНТЫ, поэтому не зависит от высоты поля ввода. */
.wa-pane__feed-wrap {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex; flex-direction: column;
}

/* Плашка «↓ N новых». Появляется, когда сообщение дописалось в конец, а
   человек читает историю выше (прокрутку в этот момент трогать нельзя). */
.chat-new-pill {
  position: absolute;
  bottom: 12px; left: 50%;
  transform: translateX(-50%);
  z-index: 3;
  display: flex; align-items: center; gap: 6px;
  padding: 7px 14px;
  border: none;
  border-radius: 999px;
  background: var(--kz-accent);
  color: #fff;
  font-family: inherit;
  font-size: 12px; font-weight: 600;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .28);
}
.chat-new-pill:hover { filter: brightness(1.08); }
.chat-new-pill[hidden] { display: none; }

.wa-pane__feed {
  flex: 1;
  overflow-y: auto;
  padding: 12px 16px;
  display: flex; flex-direction: column;
  /* НЕ используем justify-content: flex-end — он ломает scroll и
     каждый swap «дёргает» вниз. Вместо этого ставим margin-top: auto
     на .chat-thread: пустая лента прижимается к низу, заполненная
     ведёт себя как обычный scroll-контейнер. */
}
.wa-pane__feed .chat-thread { margin-top: auto; }
/* В _messages.html уже есть .chat-thread — подменяем чтобы не
   дублировать карточный стиль внутри ленты. */
.wa-pane__feed .chat-thread {
  background: transparent !important;
  box-shadow: none !important;
  padding: 0 !important;
  max-height: none !important;
  overflow: visible !important;
}

.wa-pane__composer {
  display: flex; flex-direction: column;
  gap: 6px;
  padding: 10px 12px;
  background: var(--kz-bg);
  border-top: 1px solid var(--kz-border);
}
.wa-pane__composer form {
  display: flex; gap: 8px; align-items: center;
  background: var(--kz-card-bg);
  border-radius: 22px;
  padding: 4px 6px;
  border: 1px solid var(--kz-border);
}
.wa-pane__input {
  flex: 1;
  border: none;
  background: transparent;
  padding: 8px 6px;
  font-size: 14px;
  color: var(--kz-text);
  outline: none;
}
.wa-pane__icon-btn,
.wa-pane__attach {
  width: 42px; height: 42px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  color: var(--kz-text-muted);
  cursor: pointer;
}
.wa-pane__icon-btn i,
.wa-pane__attach i {
  /* Иконки крупнее, чтобы их было удобно тапать (особенно стоп/корзина
     во время записи голосового). */
  font-size: 22px;
}
.wa-pane__icon-btn:hover,
.wa-pane__attach:hover { background: rgba(96, 90, 161, .08); color: var(--kz-text); }
.wa-pane__icon-btn.is-recording {
  background: var(--kz-danger);
  color: #fff;
}
.wa-pane__send {
  width: 44px; height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--kz-sidebar-accent);
  color: #fff;
  cursor: pointer;
}
.wa-pane__send i { font-size: 22px; }
.wa-pane__send:hover { filter: brightness(1.1); }


/* ---- Chat message bubbles ----
   Сообщения в .chat-thread (внутри .wa-pane__feed). Свои справа
   через align-self: flex-end, чужие — слева. Системные/звонки —
   по центру маленьким серым текстом. */
.chat-thread { display: flex; flex-direction: column; gap: 8px; }
.chat-msg {
  padding: 8px 12px;
  border-radius: 14px;
  background: var(--kz-bg);
  max-width: 70%;
  align-self: flex-start;
  box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
}
.chat-msg--mine {
  background: #d9fdd3;             /* WhatsApp-style salad */
  align-self: flex-end;
}
/* В dark theme — затемнённый зелёный (как у WhatsApp Dark). */
[data-theme="dark"] .chat-msg       { background: rgba(255,255,255,.06); color: var(--kz-text); }
[data-theme="dark"] .chat-msg--mine { background: #1f3a2d; color: var(--kz-text); }

.chat-msg--sys {
  align-self: center;
  background: rgba(0, 0, 0, .04);
  color: var(--kz-text-muted);
  font-size: 12px;
  padding: 4px 12px;
  border-radius: 12px;
  max-width: 80%;
}
/* На тёмной теме black-alpha background → invisible. Используем
   светлую заливку поверх dark bg. */
[data-theme="dark"] .chat-msg--sys { background: rgba(255, 255, 255, .06); }

/* Запись о звонке: значок направления + подпись в одну строку.
   Пропущенный выделяем красным — его надо заметить, это «мне звонили,
   а я не ответил», а не просто отметка в истории. */
.chat-msg--call {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px;
}
.chat-msg--call i { font-size: 16px; }
.chat-msg--call.is-missed { color: var(--kz-danger, #c0392b); }
.chat-msg--call.is-missed i { color: var(--kz-danger, #c0392b); }
.chat-msg__head {
  display: flex; justify-content: space-between; gap: 12px;
  font-size: 11px; color: var(--kz-text-muted);
  margin-bottom: 2px;
}
.chat-msg--mine .chat-msg__head strong { color: #075e54; }   /* WhatsApp teal */


/* ---- Composer states: recording / preview ----
   В .wa-pane__composer одна форма с тремя состояниями. JS скрывает
   неактуальные элементы, CSS их стилизует. */
.wa-pane__rec {
  /* Не растягиваем на всю ширину — таймер должен жаться к стоп-кнопке
     справа. margin-left:auto отодвигает блок от скрепки в конец строки. */
  margin-left: auto;
  display: flex; align-items: center; gap: 8px;
  padding: 0 8px;
  color: var(--kz-text);
  font-variant-numeric: tabular-nums;
  font-size: 14px;
  font-weight: 600;
}
.wa-pane__rec-dot {
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--kz-danger);
  animation: wa-rec-pulse 1s infinite ease-in-out;
}
@keyframes wa-rec-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: .35; }
}
.wa-pane__preview {
  flex: 1;
  height: 36px;
  /* Нативный <audio controls> в Safari/Chrome не растягивается
     красиво без явной высоты; задаём её, чтобы пузырь не «прыгал». */
}
.wa-pane__icon-btn.is-recording {
  background: var(--kz-danger);
  color: #fff;
}


/* HTML `hidden` атрибут перекрывается display: flex/inline-flex
   в правилах выше — приходится возвращать его явно. Без этого
   .wa-pane__rec/.wa-pane__preview/иконки видны даже в idle. */
[hidden] { display: none !important; }


/* ---- Inline-превью картинок в чате ----
   Картинка рендерится как <img class="chat-img"> внутри пузыря
   .chat-msg. Чтобы фото могло занять 50% ширины ленты, а не 50%
   узкого пузыря — расширяем сам пузырь, если в нём только картинка.

   - .chat-msg с .chat-img-wrap получает max-width 50% (вместо
     стандартных 70% для текста) — это и есть «половина горизонтальной
     области чата».
   - max-height 33vh — треть высоты viewport'а; чат-панель занимает
     почти всю высоту экрана, поэтому это близко к 1/3 высоты ленты.
   - width/height auto + max-* даёт contain-поведение: если фото
     горизонтальное и больше cap'а — масштабируется по ширине; если
     вертикальное — по высоте. */
.chat-msg:has(.chat-img-wrap) {
  max-width: 50%;
  background: transparent;
  box-shadow: none;
  padding: 0;
}
.chat-msg--mine:has(.chat-img-wrap) { background: transparent; }
.chat-img {
  display: block;
  max-width: 100%;
  max-height: 33vh;
  width: auto;
  height: auto;
  border-radius: 10px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .12);
  cursor: zoom-in;
}
.chat-img:hover { filter: brightness(1.05); }


/* ---- Image overlay buttons (download + fullscreen) ----
   На hover поверх картинки появляется полупрозрачная панель с двумя
   круглыми кнопками: download и zoom. На touch-устройствах оверлей
   виден всегда (через media-query ниже). */
.chat-img-wrap {
  position: relative;
  display: inline-block;
  line-height: 0;
  border-radius: 10px;
  overflow: hidden;
}
.chat-img-wrap .chat-img {
  display: block;
  cursor: zoom-in;
}
.chat-img__overlay {
  position: absolute;
  top: 6px; right: 6px;
  display: flex;
  gap: 6px;
  opacity: 0;
  transition: opacity .15s ease;
  pointer-events: none;
}
.chat-img-wrap:hover .chat-img__overlay,
.chat-img-wrap:focus-within .chat-img__overlay {
  opacity: 1;
  pointer-events: auto;
}
.chat-img__btn {
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: rgba(0, 0, 0, .55);
  color: #fff;
  cursor: pointer;
  text-decoration: none;
  border: none;
  backdrop-filter: blur(2px);
}
.chat-img__btn:hover { background: rgba(0, 0, 0, .75); }
.chat-img__btn i { font-size: 18px; }
@media (hover: none) {
  /* На touch-устройствах оверлей всегда виден — у пользователя нет hover. */
  .chat-img__overlay { opacity: 1; pointer-events: auto; }
}

/* ---- Fullscreen image modal ----
   Чёрный фон, картинка по центру с object-fit: contain, навигация
   стрелками слева/справа, закрыть/скачать в углах. */
.kz-img-modal {
  border: none;
  padding: 0;
  background: transparent;
  max-width: 100vw;
  max-height: 100vh;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  /* nested flex для центровки <img>. */
  display: none;
  align-items: center;
  justify-content: center;
}
.kz-img-modal[open] { display: flex; }
.kz-img-modal::backdrop {
  background: rgba(0, 0, 0, .92);
  backdrop-filter: blur(2px);
}
.kz-img-modal #img-modal-img {
  max-width: 92vw;
  max-height: 88vh;
  object-fit: contain;
  border-radius: 4px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, .6);
}
.kz-img-modal__close,
.kz-img-modal__download,
.kz-img-modal__nav {
  position: fixed;
  width: 48px; height: 48px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, .14);
  color: #fff;
  cursor: pointer;
  text-decoration: none;
  border: none;
  z-index: 10;
  backdrop-filter: blur(4px);
}
.kz-img-modal__close:hover,
.kz-img-modal__download:hover,
.kz-img-modal__nav:hover { background: rgba(255, 255, 255, .28); }
.kz-img-modal__close i,
.kz-img-modal__download i,
.kz-img-modal__nav i { font-size: 26px; }
.kz-img-modal__close    { top: 18px; right: 18px; }
.kz-img-modal__download { top: 18px; right: 78px; }
.kz-img-modal__nav--left  { left: 18px;  top: 50%; transform: translateY(-50%); }
.kz-img-modal__nav--right { right: 18px; top: 50%; transform: translateY(-50%); }
.kz-img-modal__counter {
  position: fixed;
  bottom: 20px; left: 50%; transform: translateX(-50%);
  color: rgba(255, 255, 255, .75);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  z-index: 10;
}

/* ---- Full-height layout for chat page ----
   Когда на странице есть .wa-shell — отрубаем скролл body и убираем
   padding у .page, чтобы прокручивалась только лента сообщений
   внутри .wa-pane__feed, а не вся страница. */
body:has(.wa-shell) { overflow: hidden; }
body:has(.wa-shell) .page {
  padding: 0;
  max-width: none;
  height: calc(100vh - 56px);  /* минус topbar */
}
body:has(.wa-shell) .wa-shell {
  height: 100%;
  border-radius: 0;
  box-shadow: none;
}

/* ---- Message actions overlay (reply / forward / delete) ----
   Прячется по умолчанию, появляется при hover на пузыре .chat-msg.
   На touch-устройствах — видна всегда (см. @media ниже). */
.chat-msg { position: relative; }
.chat-msg__actions {
  position: absolute;
  top: 4px; right: 4px;
  display: flex;
  gap: 2px;
  background: rgba(255, 255, 255, .9);
  border-radius: 14px;
  padding: 2px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .12);
  opacity: 0;
  transition: opacity .12s ease;
  pointer-events: none;
}
.chat-msg:hover .chat-msg__actions,
.chat-msg:focus-within .chat-msg__actions {
  opacity: 1;
  pointer-events: auto;
}
.chat-msg__act {
  width: 26px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: transparent;
  color: var(--kz-text-muted);
  border: none;
  cursor: pointer;
}
.chat-msg__act i { font-size: 15px; }
.chat-msg__act:hover { background: rgba(96, 90, 161, .15); color: var(--kz-text); }
.chat-msg__act--danger:hover { background: rgba(255, 59, 48, .15); color: #c4271f; }
@media (hover: none) {
  .chat-msg__actions { opacity: 1; pointer-events: auto; }
}

/* Подсвет «куда отвечают» при клике на цитату. */
.chat-msg.is-flash {
  outline: 2px solid var(--kz-sidebar-accent);
  transition: outline-color .8s ease;
}

/* Цитата parent-сообщения внутри ответа. */
.chat-msg__quote {
  border-left: 3px solid var(--kz-sidebar-accent);
  padding: 4px 8px;
  margin: 4px 0;
  background: rgba(96, 90, 161, .06);
  border-radius: 0 6px 6px 0;
  font-size: 12px;
  cursor: pointer;
}
.chat-msg__quote strong { display: block; font-size: 11px; color: var(--kz-sidebar-accent); }
.chat-msg__quote:hover { background: rgba(96, 90, 161, .12); }

/* Reply-чип в композере (над input'ом). */
.wa-pane__reply {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px;
  background: var(--kz-card-bg);
  border: 1px solid var(--kz-border);
  border-radius: 10px;
  border-left: 3px solid var(--kz-sidebar-accent);
}

/* Чекбокс «архив» в сайдбаре. */
.wa-sidebar__filter {
  display: flex; gap: 6px; align-items: center;
  padding: 0 12px 8px;
  font-size: 12px;
  color: var(--kz-text-muted);
  cursor: pointer;
  user-select: none;
}
.wa-sidebar__filter input { accent-color: var(--kz-sidebar-accent); }

/* ---- Архивные (закрытые/отменённые) чаты в сайдбаре ----
   Затенены, чтобы визуально отделить от активных. Курсор и клик
   работают как обычно — только посмотреть историю. */
.wa-room--archived {
  opacity: 0.55;
}
.wa-room--archived .wa-room__title::after {
  content: " · " attr(data-archived-suffix, "архив");
  color: var(--kz-text-muted);
  font-size: 11px;
  font-weight: normal;
}
.wa-room--archived:hover { opacity: 0.8; }
.wa-room--archived.is-active { opacity: 0.9; }

/* ---- Sidebar room delete overlay ----
   Иконка корзины поверх пункта-комнаты, видна на hover. Кнопка —
   sibling <a>, оба в .wa-room-wrap (relative). */
.wa-room-wrap { position: relative; }
.wa-room__del {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  width: 30px; height: 30px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: rgba(0, 0, 0, .06);
  color: var(--kz-text-muted);
  border: none;
  cursor: pointer;
  opacity: 0;
  transition: opacity .12s ease, background-color .12s ease, color .12s ease;
}
.wa-room-wrap:hover .wa-room__del,
.wa-room-wrap:focus-within .wa-room__del {
  opacity: 1;
}
.wa-room__del:hover {
  background: rgba(255, 59, 48, .15);
  color: #c4271f;
}
.wa-room__del i { font-size: 16px; }
@media (hover: none) {
  .wa-room__del { opacity: 1; }
}

/* ---- Tile delete overlay ----
   Корзина-оверлей в углу плитки. Появляется на hover, идентично
   паттерну с комнатами чата (.wa-room-wrap → .wa-room__del). */
.tile-wrap { position: relative; }
.tile__del {
  /* Кнопка удаления — позиционируется в зоне .tile__footer
     (правый-нижний угол карточки), поверх чипов. Появляется на hover.
     bottom: 14px / right: 14px — внутри padding'а footer'а. */
  position: absolute;
  bottom: 14px;
  right: 14px;
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--kz-card-bg);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .15);
  color: var(--kz-danger);
  border: none;
  cursor: pointer;
  opacity: 0;
  z-index: 3;
  transition: opacity .12s ease, background-color .12s ease, transform .12s ease;
}
.tile__del:hover {
  background: rgba(255, 59, 48, .15);
  color: #c4271f;
  transform: scale(1.05);
}
.tile-wrap:hover .tile__del,
.tile-wrap:focus-within .tile__del,
.supply-item-card:hover .tile__del,
.supply-item-card:focus-within .tile__del { opacity: 1; }
.tile__del i { font-size: 18px; }
@media (hover: none) { .tile__del { opacity: 1; } }

/* ---- Группа hover-action кнопок в углу карточки ----
   Когда в углу карточки нужно несколько кнопок (правка, удаление,
   синхронизация и т.п.) — оборачиваем их в .tile-actions. Группа сама
   позиционируется absolute, плавно появляется при hover родителя
   (.tile-wrap). Кнопки внутри ставим обычными .btn без своего opacity. */
.tile-actions {
  position: absolute;
  bottom: 10px;
  right: 10px;
  display: flex;
  gap: 4px;
  opacity: 0;
  z-index: 3;
  transition: opacity .12s ease;
}
.tile-wrap:hover .tile-actions,
.tile-wrap:focus-within .tile-actions { opacity: 1; }
@media (hover: none) { .tile-actions { opacity: 1; } }
.tile-actions .btn,
.tile-actions button[type="submit"] {
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--kz-card-bg);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .15);
  border: none;
  cursor: pointer;
  color: var(--kz-sidebar-accent);
  padding: 0;
}
.tile-actions .btn:hover,
.tile-actions button[type="submit"]:hover { transform: scale(1.05); }
.tile-actions .btn i,
.tile-actions button i { font-size: 18px; }

/* ---- Transaction card history overlay (finance index) ----
   Кнопка «история изменений» в правом-нижнем углу карточки операции.
   Появляется на hover родителя, поверх любого содержимого. */
.tx-history-overlay {
  position: absolute;
  bottom: 12px;
  right: 12px;
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--kz-card-bg);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .15);
  color: var(--kz-text-muted);
  text-decoration: none;
  opacity: 0;
  z-index: 3;
  transition: opacity .12s ease, transform .12s ease, color .12s ease;
}
.tx-history-overlay:hover {
  color: var(--kz-sidebar-accent);
  transform: scale(1.05);
}
.tx-card:hover .tx-history-overlay,
.tx-card:focus-within .tx-history-overlay { opacity: 1; }
.tx-history-overlay i { font-size: 18px; }
@media (hover: none) { .tx-history-overlay { opacity: 1; } }

/* ---- WebRTC call dialog ----
   Большая модалка с двумя <video>: remote — основное, local — PIP. */
.kz-call-dialog {
  width: min(900px, 95vw);
  max-width: 95vw;
  max-height: 90vh;
  padding: 0;
  border: none;
  background: #111;
  color: #fff;
  border-radius: 12px;
  overflow: hidden;
}
.kz-call-dialog::backdrop {
  background: rgba(0, 0, 0, .85);
  backdrop-filter: blur(4px);
}
.kz-call__head {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 18px;
  background: rgba(0, 0, 0, .55);
}
.kz-call__head .muted { color: rgba(255, 255, 255, .6); }

/* ---- Call controls (mute / hangup) — звонок только аудио ---- */
.kz-call__controls {
  display: flex;
  justify-content: center;
  gap: 14px;
  padding: 18px;
  background: rgba(0, 0, 0, .55);
}
.kz-call__btn {
  width: 52px; height: 52px;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, .15);
  color: #fff;
  border: none;
  cursor: pointer;
  transition: background-color .15s ease, transform .12s ease;
}
.kz-call__btn:hover { background: rgba(255, 255, 255, .25); transform: scale(1.05); }
.kz-call__btn i { font-size: 24px; }
.kz-call__btn.is-off {
  background: rgba(255, 255, 255, .55);
  color: #222;
}
.kz-call__btn--danger {
  background: #ff3b30;
}
.kz-call__btn--danger:hover { background: #d22b22; }

/* ---- Incoming call modal ---- */
.kz-incoming {
  width: min(380px, 90vw);
  padding: 24px;
  text-align: center;
  border: none;
  background: var(--kz-card-bg);
  border-radius: 14px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .25);
}
.kz-incoming::backdrop { background: rgba(0, 0, 0, .35); backdrop-filter: blur(2px); }
.kz-incoming__icon {
  width: 64px; height: 64px;
  margin: 0 auto 12px;
  border-radius: 50%;
  background: var(--kz-sidebar-accent);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 32px;
  animation: kz-ring 1.2s infinite ease-in-out;
}
@keyframes kz-ring {
  0%, 100% { transform: rotate(0); }
  10%, 30% { transform: rotate(-10deg); }
  20%, 40% { transform: rotate(10deg); }
}
.kz-incoming__buttons {
  display: flex; gap: 10px; justify-content: center; margin-top: 18px;
}

/* ---------- Workflow chain (цепочка-таймлайн согласования) ----------
   Горизонтальная цепочка действий: кружок-иконка → линия → следующий кружок.
   На узком экране (≤640px) переходит в вертикальный таймлайн.
   ОК-цвет — фиолетовый (акцент сайдбара); предупреждение — жёлтый; отказ — красный. */
.workflow-chain {
  list-style: none;
  margin: 0;
  padding: 8px 0;
  display: flex;
  flex-wrap: nowrap;
  gap: 0;
  overflow-x: auto;
}
.workflow-chain__node {
  position: relative;
  flex: 1 0 140px;
  min-width: 140px;
  padding: 0 10px;
  text-align: center;
}
.workflow-chain__node::after {
  /* Линия от кружка к следующему — позиционируется на уровне центра кружка. */
  content: "";
  position: absolute;
  top: 18px;       /* половина высоты кружка (36/2) */
  left: 50%;
  width: 100%;
  height: 2px;
  background: var(--kz-border, #e3e3eb);
  z-index: 0;
}
.workflow-chain__node:last-child::after { display: none; }

.workflow-chain__circle {
  position: relative;
  z-index: 1;
  width: 36px; height: 36px;
  margin: 0 auto 8px;
  border-radius: 50%;
  background: var(--kz-card-bg, #fff);
  border: 2px solid var(--kz-sidebar-accent, #605aa1);
  color: var(--kz-sidebar-accent, #605aa1);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
}
.workflow-chain__node--ok       .workflow-chain__circle { border-color: var(--kz-success, #2bbd7e); color: var(--kz-success, #2bbd7e); }
.workflow-chain__node--warning  .workflow-chain__circle { border-color: var(--kz-warning, #f4a01a); color: var(--kz-warning, #f4a01a); }
.workflow-chain__node--danger   .workflow-chain__circle { border-color: var(--kz-danger,  #e74c3c); color: var(--kz-danger,  #e74c3c); }

.workflow-chain__label { font-weight: 600; font-size: 13px; }
.workflow-chain__meta  { font-size: 11px; margin-top: 2px; line-height: 1.4; }
.workflow-chain__note  {
  font-size: 11px;
  margin-top: 4px;
  padding: 4px 0;
  border-top: 1px dashed var(--kz-border);
  /* Прозрачный фон — кажется органичнее на фоне карточки и в светлой,
     и в тёмной теме (тёмная переопределяла --kz-card-alt-bg, но любая
     заливка под подписями цепочки смотрится как лишний прямоугольник). */
  background: transparent;
  color: var(--kz-text-muted);
  font-style: italic;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Mobile: вертикальный таймлайн. */
@media (max-width: 640px) {
  .workflow-chain { flex-direction: column; gap: 14px; overflow-x: visible; }
  .workflow-chain__node { padding: 0 0 0 56px; min-width: 0; text-align: left; }
  .workflow-chain__node::after {
    /* Вертикальная линия слева вниз. */
    top: 36px;       /* ниже кружка */
    left: 18px;      /* центр кружка слева */
    width: 2px;
    height: calc(100% + 14px); /* до следующего */
  }
  .workflow-chain__circle { position: absolute; top: 0; left: 0; margin: 0; }
}

/* ── Flash-сообщения (messages framework), глобально в base.html ──────
   Один контейнер .kz-flash-area, внутри .kz-flash--<tag> по уровню.
   Раньше каждый шаблон выводил сам — отсюда «всплывание» на Сводке. */
.kz-flash-area { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.kz-flash {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 14px; border-radius: 8px; font-size: 14px;
  border-left: 4px solid var(--kz-info);
  background: color-mix(in srgb, var(--kz-info) 10%, var(--kz-bg));
  color: var(--kz-text);
}
.kz-flash i { font-size: 18px; color: var(--kz-info); flex: 0 0 auto; }
.kz-flash--success { border-left-color: var(--kz-success);
  background: color-mix(in srgb, var(--kz-success) 12%, var(--kz-bg)); }
.kz-flash--success i { color: var(--kz-success); }
.kz-flash--error,
.kz-flash--danger  { border-left-color: var(--kz-danger);
  background: color-mix(in srgb, var(--kz-danger) 12%, var(--kz-bg)); }
.kz-flash--error i,
.kz-flash--danger i { color: var(--kz-danger); }
.kz-flash--warning { border-left-color: var(--kz-warning);
  background: color-mix(in srgb, var(--kz-warning) 14%, var(--kz-bg)); }
.kz-flash--warning i { color: var(--kz-warning); }

/* ─── Прогноз кассового разрыва (E-CASHGAP) ───────────────────────────
   Директор должен считывать смысл за секунду: либо «деньги кончатся через
   N дней» красным, либо «всё в порядке» зелёным. Поэтому крупный заголовок
   и сумма, а детали — мелким. */
.cash-gap {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 16px;
  border-radius: 10px;
  margin-bottom: 12px;
}
.cash-gap > i { font-size: 32px; flex: none; }
.cash-gap--danger {
  background: rgba(220, 53, 69, .10);
  border: 1px solid rgba(220, 53, 69, .35);
}
.cash-gap--danger > i { color: #dc3545; }
.cash-gap--ok {
  background: rgba(25, 135, 84, .10);
  border: 1px solid rgba(25, 135, 84, .30);
}
.cash-gap--ok > i { color: #198754; }
.cash-gap__headline { font-weight: 600; font-size: 15px; }
.cash-gap__amount {
  font-size: 22px; font-weight: 700; color: #dc3545;
  font-variant-numeric: tabular-nums;   /* цифры не «пляшут» при обновлении */
}

/* Четыре числа в ряд; на узком экране переносятся сами. */
.cash-gap__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 12px;
}
.cash-gap__grid strong { font-size: 15px; font-variant-numeric: tabular-nums; }

.cash-gap__note {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--kz-border);
  font-size: 12px;
  color: var(--kz-text-muted);
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}

/* ─── Материалы план/факт на карточке проекта (E1.2-виджет) ──────────
   Пороги смысла: <80% зелёный, 80–100% жёлтый (пора смотреть),
   >100% красный (перерасход). Бар шире 100% не рисуется (bar_pct капится
   во вью) — сумма превышения видна цифрами рядом. */
.matbar {
  height: 10px;
  border-radius: 999px;
  background: var(--kz-border);
  overflow: hidden;
}
.matbar--thin { height: 6px; margin-bottom: 8px; }
.matbar__fill { height: 100%; border-radius: 999px; }
.matbar__fill--success { background: #198754; }
.matbar__fill--warning { background: #f5a623; }
.matbar__fill--danger  { background: #dc3545; }
.matbar__meta {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 13px; margin-bottom: 6px;
}
.matbar__row {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 12px; font-size: 13px; margin-top: 6px;
}
.matbar__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.matbar__nums { flex: none; font-variant-numeric: tabular-nums; }
.matbar__note {
  margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--kz-border);
  font-size: 12px; color: var(--kz-text-muted);
  display: flex; align-items: center; gap: 6px;
}

/* ─── Якоря чата: «Непрочитанные» и подсветка сообщения из уведомления ──
   Разделитель — линия с подписью по центру (как в WhatsApp): открытие
   комнаты сажает ленту сюда, а не в хвост. Подсветка — двухсекундная
   вспышка пузыря, к которому привели по ?msg= из уведомления. */
.chat-unread-sep {
  display: flex; align-items: center; gap: 10px;
  margin: 10px 0;
  font-size: 11px; font-weight: 600;
  color: var(--kz-accent);
  text-transform: uppercase; letter-spacing: .4px;
}
.chat-unread-sep::before,
.chat-unread-sep::after {
  content: ""; flex: 1; height: 1px;
  background: var(--kz-accent); opacity: .45;
}
/* Сентинел подгрузки старых сообщений (E-CHATCACHE CC.1): спиннер по центру
   над лентой, пока тянется предыдущая страница. */
.chat-older-loading {
  display: flex; justify-content: center; align-items: center;
  padding: 10px 0; color: var(--kz-text-muted); font-size: 18px;
  min-height: 20px;
}
.chat-msg--flash { animation: chat-flash 2.4s ease-out; }
@keyframes chat-flash {
  0%, 55% { box-shadow: 0 0 0 3px var(--kz-accent); }
  100%    { box-shadow: 0 0 0 0 transparent; }
}

/* ── Состояния иконок (набор Lucide) ────────────────────────────────────
   Иконки — шрифт (см. lucide.css): цвет наследуется от кнопки через color,
   размер — через font-size, поэтому прежние правила `.kz-call__btn i` и
   `.wa-pane__icon-btn i` продолжают задавать размер.

   Двухсостояточные кнопки держат ОБЕ иконки в разметке, а видимость решает
   CSS по классу на кнопке. Так JS только ставит класс и не подменяет
   разметку (меньше рассинхрона). */
/* Микрофон в звонке: обычный ⇄ перечёркнутый */
#call-mute .lu-mic-off { display: none; }
#call-mute.is-off .lu-mic { display: none; }
#call-mute.is-off .lu-mic-off { display: inline-block; }
/* Кнопка голосового: микрофон ⇄ стоп записи */
#voice-toggle .lu-circle-stop { display: none; }
#voice-toggle.is-recording .lu-mic { display: none; }
#voice-toggle.is-recording .lu-circle-stop { display: inline-block; }

/* Вращение (замена boxicons `bx-spin`): используется у индикаторов загрузки. */
.lu-spin { animation: lu-spin 1.4s linear infinite; }
@keyframes lu-spin { to { transform: rotate(360deg); } }
