/* ============================================================================
   Каркас приложения: шапка, навигация, сетки страниц, правая панель.
   Здесь только расположение. Внешний вид элементов внутри — в components.css.
   ============================================================================ */

/* ================================================================== оболочка */
.shell {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.shell__main {
  flex: 1;
  padding: var(--space-6) 0 var(--space-12);
}

/* Страница внутри iframe (карточка в попапе списка лидов): каркас приложения
   прячется — шапка, полоса дня и крошки уже есть у родителя. */
.is-embedded .topbar,
.is-embedded #daybar,
.is-embedded .crumbs,
.is-embedded .skip-link { display: none; }
.is-embedded .shell__main { padding-top: var(--space-5); }
/* В попапе карточка едет ОДНИМ куском: правый столбец (ЛПР, план, каналы) не
   прилипает к верху, иначе при прокрутке он «отставал» от остальной карточки.
   На отдельной странице прилипание остаётся — там оно помогает держать контакты
   и следующий шаг перед глазами, пока правишь письмо. */
.is-embedded .record__rail--sticky { position: static; top: auto; }

/* Общая рабочая ширина. Разжата до 1600px, потому что главный экран —
   таблица лидов на десяток столбцов: на 1180px она либо ужимается до
   нечитаемого, либо уезжает в горизонтальную прокрутку. */
.wrap {
  width: 100%;
  max-width: var(--shell-max);
  margin: 0 auto;
  padding: 0 var(--space-7);
}

/* ==================================================================== шапка
   Прилипает: навигация и поиск нужны в любой момент, а не только наверху
   страницы. Полупрозрачность с размытием — чтобы уехавшее под шапку
   содержимое читалось как «уехало», а не обрывалось. */
.topbar {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: color-mix(in srgb, var(--bg-surface) 88%, transparent);
  backdrop-filter: saturate(1.6) blur(10px);
  border-bottom: 1px solid var(--line);
}
.topbar__inner {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  height: var(--shell-header);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--fg);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight);
  flex: none;
}
.brand:hover { color: var(--fg); }
.brand__mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--radius-md);
  background: var(--accent);
  color: var(--accent-on);
}

/* Поиск занимает свободное место между логотипом и навигацией, но не
   растягивается бесконечно: поле в 700px выглядит ошибкой вёрстки. */
.topbar__search { flex: 1 1 auto; max-width: 380px; }

.nav {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
}
.nav__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 34px;
  padding: 0 var(--space-4);
  border-radius: var(--radius-md);
  color: var(--fg-muted);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  white-space: nowrap;
  transition:
    color var(--motion-fast) var(--ease-out),
    background-color var(--motion-fast) var(--ease-out);
}
.nav__link:hover { color: var(--fg); background: var(--bg-hover); }
/* Текущий раздел — цветом И жирностью. Одного цвета мало: раздел должен
   считываться боковым зрением, не вчитываясь. */
.nav__link[aria-current="page"] {
  color: var(--accent-fg);
  font-weight: var(--weight-semi);
  background: var(--accent-soft);
}
/* Метка «есть новое» у раздела. Точка, а не число: точное количество здесь
   не нужно, а число заставляет его прочитать. */
.nav__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

.topbar__user { flex: none; }

/* ============================================================== хлебные крошки
   Отвечают на «где я и как вернуться». Последний элемент — текущая страница,
   не ссылка. */
.crumbs {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-5) 0 0;
  color: var(--fg-muted);
  font-size: var(--text-xs);
  flex-wrap: wrap;
}
.crumbs__sep { color: var(--line-strong); }
.crumbs a { color: var(--fg-muted); }
.crumbs a:hover { color: var(--accent-fg); }
.crumbs__current { color: var(--fg-soft); font-weight: var(--weight-medium); }

/* ============================================================ шапка страницы */
.page-head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-6);
  flex-wrap: wrap;
  margin: var(--space-5) 0 var(--space-6);
}
.page-head__body { min-width: 0; display: grid; gap: var(--space-3); }
.page-head__title {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight);
}
.page-head__sub { color: var(--fg-muted); font-size: var(--text-sm); }
/* Плотный вариант — для рабочих экранов, которые открывают десятки раз в день
   и на которых важна не витрина, а сколько строк поместилось. */
.page-head--tight { margin: var(--space-4) 0 var(--space-4); }
.page-head__actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

/* ==================================================================== сетки */

/* Вертикальная стопка блоков страницы — самый частый случай.

   minmax(0, 1fr), а не 1fr: у элемента сетки минимальная ширина по умолчанию
   равна ширине содержимого, и он ОТКАЗЫВАЕТСЯ сжиматься. Широкая таблица внутри
   карточки тогда распирает карточку, карточка — страницу, и весь документ
   уезжает в горизонтальную прокрутку вместе с шапкой. Полоса прокрутки при этом
   появляется не у таблицы, где ей место, а у всей страницы. */
.stack {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
}
.stack--tight { gap: var(--space-4); }
.stack--loose { gap: var(--space-7); }

/* Ряд KPI-плиток. auto-fit, а не фиксированные четыре колонки: на узком
   экране плитки перестраиваются сами, без отдельного медиазапроса. */
.kpi-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: var(--space-5);
}

/* Сводка по срезу одной полосой — вместо четырёх плиток на 105px. Цифры
   в течение дня почти не меняются, а список читают постоянно: место отдано
   списку. Полоса переносится на узком экране сама. */
.summary-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-6);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--line);
  font-size: var(--text-sm);
  color: var(--fg-soft);
}
.summary-strip__item { display: inline-flex; align-items: center; gap: var(--space-2); }
.summary-strip__item b { color: var(--fg); font-variant-numeric: tabular-nums; }
.summary-strip__icon { color: var(--fg-muted); flex: none; }
.summary-strip__item--link { color: inherit; }
.summary-strip__item--link:hover { color: var(--accent-fg); }
.summary-strip__item--link:hover .summary-strip__icon { color: var(--accent); }

/* Строка фильтров списка лидов: поиск и кнопки всегда на виду, остальные поля
   свёрнуты. Развёрнутая панель занимала 181px и отодвигала первого лида. */
.filterbar__form { display: grid; gap: var(--space-4); }
.filterbar__top {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}
.filterbar__search { flex: 1 1 320px; min-width: 0; }
.filterbar__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--radius-full);
  background: var(--accent);
  color: var(--accent-on);
  font-size: var(--text-2xs);
  font-variant-numeric: tabular-nums;
}
/* Свёрнуто по умолчанию. Правило нужно явно: .filters ниже задаёт display: grid
   тем же весом, и один [hidden] ему проигрывал бы по порядку. */
.filterbar__fields[hidden] { display: none; }
.filterbar__chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
/* Плашка применённого фильтра. Нажатие снимает его — поэтому крестик виден
   всегда, а не только при наведении: скрытое действие всё равно что нет его. */
.filterchip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 3px var(--space-3);
  border: 1px solid var(--accent-softer);
  border-radius: var(--radius-full);
  background: var(--accent-soft);
  color: var(--accent-fg);
  font-size: var(--text-xs);
  text-decoration: none;
}
.filterchip:hover { border-color: var(--accent); background: var(--accent-softer); }
.filterchip__label { color: var(--fg-muted); }
.filterchip__value { font-weight: var(--weight-semi); max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.filterchip__x { opacity: 0.7; flex: none; }
.filterchip:hover .filterchip__x { opacity: 1; }

/* Панель фильтров: поля разной ширины, переносятся по мере надобности.
   align-items: start — поля выравниваются по ВЕРХУ: у всех подпись в одну
   строку одной высоты, поэтому сами контролы встают на одну линию, а подсказка
   под полем (hint) свисает вниз и не толкает соседей вверх (была причина
   «съезжающей» разметки: end-выравнивание поднимало поля с подсказкой). */
.filters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--space-4);
  align-items: start;
}
.filters__wide { grid-column: span 2; }
.filters__actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  grid-column: 1 / -1;
}
.filters__actions--end { justify-content: flex-end; }
@media (max-width: 720px) {
  .filters__wide { grid-column: auto; }
}

/* Применённый фильтр подсвечен — сразу видно, что он активен. Активен = выбран
   не-пустой вариант (не «Любой…») или в поиске набран текст. Определяем по
   разметке, отрисованной сервером после применения (:has), без классов в шаблоне.
   background-color, а не background, — чтобы не затереть стрелку <select>. */
.filters .field:has(select > option:checked:not([value=""])) > .field__label,
.filters .field:has(input[type="search"]:not([value=""])) > .field__label {
  color: var(--accent);
  font-weight: var(--weight-semi);
}
.filters .field:has(select > option:checked:not([value=""])) .select,
.filters .field:has(input[type="search"]:not([value=""])) .input {
  border-color: var(--accent);
  background-color: var(--accent-softer);
}

/* ------------------------------------------------- карточка лида: три колонки
   Слева справка о компании, в центре работа, справа — с кем и когда.
   Средняя колонка — единственная резиновая: расширять надо место для текста
   сообщения, а не для реквизитов. */
.record {
  display: grid;
  grid-template-columns: var(--rail-width) minmax(0, 1fr) var(--rail-width);
  gap: var(--space-5);
  align-items: start;
}
.record__rail { display: grid; gap: var(--space-5); min-width: 0; }
.record__main { display: grid; gap: var(--space-5); min-width: 0; }

/* Боковые колонки едут за экраном: продукт, контакты и следующий шаг нужны,
   пока правишь текст письма. На узком экране прилипание снимается — иначе
   колонка съедает половину высоты. */
@media (min-width: 1280px) {
  .record__rail--sticky {
    position: sticky;
    top: calc(var(--shell-header) + var(--space-5));
  }
}
/* Две колонки: правая (с кем и когда) важнее левой (справка), поэтому левая
   уходит вниз первой. */
@media (max-width: 1279px) {
  .record { grid-template-columns: minmax(0, 1fr) var(--rail-width); }
  .record__rail--left { grid-column: 1 / -1; order: 3; }
}
@media (max-width: 900px) {
  .record { grid-template-columns: minmax(0, 1fr); }
  .record__rail--left, .record__rail--right { grid-column: auto; }
}

/* Список с боковой панелью: таблица лидов + карточка выбранного. */
.with-aside {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--drawer-width);
  gap: var(--space-5);
  align-items: start;
}
@media (max-width: 1200px) {
  .with-aside { grid-template-columns: minmax(0, 1fr); }
}

/* ============================================================= правая панель
   Сводка по выбранному лиду. На широком экране — колонка в потоке (список
   рядом остаётся виден и кликабелен). На узком — накрывающая панель, потому
   что колонка в 380px не оставила бы таблице места.

   Панель — <aside> с aria-label, закрытие по Esc и по клику вне (см. drawer.js). */
.drawer {
  background: var(--bg-surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-xl);
  display: grid;
  gap: var(--space-5);
  padding: var(--space-6);
  align-content: start;
}
@media (min-width: 1201px) {
  .drawer--sticky {
    position: sticky;
    top: calc(var(--shell-header) + var(--space-5));
    max-height: calc(100vh - var(--shell-header) - var(--space-10));
    overflow-y: auto;
  }
}
@media (max-width: 1200px) {
  .drawer {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: var(--z-drawer);
    width: min(var(--drawer-width), 100vw);
    border-radius: 0;
    border-width: 0 0 0 1px;
    overflow-y: auto;
    box-shadow: var(--shadow-xl);
    animation: drawer-in var(--motion-base) var(--ease-out);
  }
}
@keyframes drawer-in {
  from { transform: translateX(16px); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}
.drawer__head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
}
.drawer__title { min-width: 0; display: grid; gap: var(--space-3); }
.drawer__close { margin-left: auto; flex: none; }
.drawer__section { display: grid; gap: var(--space-4); }
.drawer__label {
  color: var(--fg-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-semi);
}
.drawer__actions { display: grid; gap: var(--space-3); }
/* Редкое действие под линией — отдельно от частых кнопок (стоп-лист в сводке лида). */
.drawer__apart {
  display: grid;
  gap: var(--space-3);
  margin-top: var(--space-2);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
}

/* Затемнение под накрывающей панелью. На широком экране панель в потоке —
   затемнять нечего. */
.drawer-backdrop { display: none; }
@media (max-width: 1200px) {
  .drawer-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: calc(var(--z-drawer) - 1);
    background: rgb(15 23 42 / 0.4);
    animation: fade-in var(--motion-fast) var(--ease-out);
  }
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

/* ============================================================ узкий контейнер
   Для форм и страниц-сообщений: строка длиной во весь экран не читается. */
.narrow { max-width: 520px; margin: var(--space-10) auto; }
.narrow--wide { max-width: 760px; }

/* ============================================================== адаптивность */
@media (max-width: 1100px) {
  /* Поиск в шапке уступает место навигации: искать можно и со страницы лидов. */
  .topbar__search { display: none; }
}
@media (max-width: 860px) {
  .wrap { padding: 0 var(--space-5); }
  /* Навигация уезжает в прокрутку, а не переносится на вторую строку:
     двухэтажная шапка съедает экран на ноутбуке. */
  .nav {
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  .nav::-webkit-scrollbar { display: none; }
  .page-head__actions { margin-left: 0; width: 100%; }
}

/* ====================================================== ключевые клиенты
   Экран из мессенджера: узкий список слева, разговор в остальном месте.
   Список едет за экраном — по нему щёлкают, пока читают историю справа. */
/* Две колонки на всю оставшуюся высоту. Прилипания больше нет: колонка не
   «догоняет» страницу при прокрутке, а сразу стоит на месте и прокручивается
   сама. Прокрутка не перетекает наружу (overscroll-behavior), поэтому докрутив
   список до конца, вы не утягиваете за собой страницу. */
.keyscreen {
  display: grid;
  grid-template-columns: var(--keylist-width) minmax(0, 1fr);
  gap: var(--space-5);
  align-items: stretch;
  flex: 1;
  min-height: 0;
}
/* Левая колонка — это срез плюс список: срез стоит на месте, прокручивается
   только список под ним. */
.keyside {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  gap: var(--space-3);
  min-width: 0;
  min-height: 0;
}
.keyfilters {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-2);
}
.keylist {
  display: block;
  min-width: 0;
  min-height: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.keylist--empty { overflow: visible; }
.keycard {
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* На узком экране колонки складываются в одну, и прокрутка снова общая:
   два независимых окошка по трети экрана листать невозможно. */
@media (max-width: 899px) {
  body.app-fixed { overflow: auto; }
  .app-fixed .shell { height: auto; }
  .app-fixed .shell__main { overflow: visible; }
  .keyscreen { grid-template-columns: minmax(0, 1fr); }
  .keyside { grid-template-rows: auto auto; }
  .keylist, .keycard { overflow: visible; max-height: none; }
}

.keycard {
  display: grid;
  gap: var(--space-5);
  min-width: 0;
  align-content: start;
}
.keycard__body {
  display: grid;
  grid-template-columns: var(--rail-width) minmax(0, 1fr);
  gap: var(--space-5);
  align-items: start;
}
@media (max-width: 1279px) {
  .keycard__body { grid-template-columns: minmax(0, 1fr); }
}
.keycard__side { display: grid; gap: var(--space-5); min-width: 0; }
.keycard__feed { min-width: 0; }

/* ================================== экран в высоту окна (двухпанельные экраны)
   Страница целиком не прокручивается: прокручиваются колонки, каждая сама.
   Без этого получалось три прокрутки на один жест — сначала уезжала страница,
   потом список, потом снова страница, и колесо «спотыкалось» на каждой границе
   (жалоба владельца 28.08.2026). */
body.app-fixed { overflow: hidden; }
.app-fixed .shell { height: 100dvh; min-height: 0; }
.app-fixed .shell__main {
  display: flex;
  flex-direction: column;
  min-height: 0;
  /* Сверху воздуха почти нет: под полосой дня и так есть отбивка, а каждый
     лишний пиксель здесь отнимается у колонок — они и так в высоту окна.
     Снизу отступ снаружи колонок: рамка списка кончается выше края окна, а не
     упирается в него. Внутрь контейнера этот воздух класть нельзя — он
     уезжает вместе с прокруткой и читается как пустая строка списка. */
  padding-top: var(--space-3);
  padding-bottom: var(--space-6);
  overflow: hidden;
}
/* Заголовок прижат к полосе дня: собственный верхний отступ ему здесь не нужен. */
.app-fixed .page-head { margin-top: 0; }
.app-fixed .shell__main > .wrap {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}
