@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap');

/*
 * Основа дизайна. Значения перенесены из макета (theme/AlloMaster - UI Kit)
 * без округления: если в макете 219,218,222 — здесь #dbdade, а не «почти
 * серый». Подгонка на глаз — то, из-за чего потом никто не может ответить,
 * почему в одном месте одна рамка, а в соседнем другая.
 *
 * Два цвета вместо одного, и это не украшение. --primary зовёт нажать:
 * кнопки, ссылки, активный пункт меню, фокус в поле. --navy — цвет марки:
 * логотип, заголовки, боковое меню. Раньше они совпадали, и «сохранить»
 * выглядело так же, как заголовок страницы.
 */
:root {
  --bg: #f8f7fa;
  --surface: #ffffff;
  --border: #dbdade;
  --text: #4b465c;
  --text-muted: #5d596c;
  --text-disabled: #a8aaae;

  /* Действие */
  --primary: #7367f0;
  --primary-dark: #675cd8;
  --primary-light: rgba(115, 103, 240, .16);

  /* Марка. Тот самый #131747 — он никуда не делся, но теперь отвечает
     за принадлежность, а не за действие. */
  --navy: #131747;
  --navy-soft: #8692d0;

  --secondary: #a8aaae;
  --secondary-light: rgba(168, 170, 174, .16);
  --success: #28c76f;
  --success-light: rgba(40, 199, 111, .16);
  --danger: #ea5455;
  --danger-light: rgba(234, 84, 85, .16);
  --warning: #ff9f43;
  --warning-light: rgba(255, 159, 67, .16);
  --info: #00cfe8;
  --info-light: rgba(0, 207, 232, .16);

  /* Фирменный красный из знака. Намеренно отличается от --danger: тот
     означает ошибку и необратимое действие, этот — просто марку. Если бы
     они совпали, «удалить» и «наше» выглядели бы одинаково. */
  --accent: #e20613;
  --accent-light: #fdeaeb;

  /* Скругления. Шкала из макета и ровно из трёх ступеней: чем меньше
     элемент, тем меньше радиус, иначе мелкий бейдж превращается в каплю.
     Четвёртая ступень — только для круглых: аватар, счётчик, переключатель.

     Значения совпадают с noneerp-theme.css намеренно. Тот файл грузится
     после и перебил бы их в любом случае; расхождение здесь означало бы,
     что страница без внешнего слоя выглядит иначе, чем с ним. */
  --radius-sm: 6px;
  --radius: 8px;
  --radius-lg: 12px;
  --radius-pill: 999px;

  /* Высоты элементов управления: малый, обычный, крупный. Совпадают у
     кнопки, поля и выпадающего списка — иначе они не встают в одну строку. */
  --control-h-sm: 32px;
  --control-h: 38px;
  --control-h-lg: 48px;

  --shadow: 0 2px 4px rgba(165, 163, 174, .3);
  /* Всплывающий слой лежит поверх содержимого — ему нужна тень заметнее,
     иначе панель читается как часть страницы под ней. */
  --shadow-lg: 0 4px 18px rgba(75, 70, 92, .1);
  --sidebar-w: 250px;
}

/*
 * Тёмная тема — по выбору человека, а не по настройке его системы.
 *
 * Умышленно не через prefers-color-scheme. Настройка операционной системы
 * говорит о вкусах в телефоне вечером, а не о том, как удобнее смотреть на
 * таблицу с суммами в рабочий день. Продукт открывается светлым всегда, а
 * переключить — отдельное осознанное действие, и выбор запоминается.
 */
:root[data-theme="dark"] {
  --bg: #25293c;
  --surface: #2f3349;
  --border: #434968;
  --text: #b6bee3;
  --text-muted: #8692d0;
  --text-disabled: #6a7192;
  --shadow: 0 2px 4px rgba(15, 20, 34, .3);
  --shadow-lg: 0 4px 18px rgba(15, 20, 34, .4);
}

/* Переключатель темы в шапке. Иконка одна, меняется по теме: рисовать две
   кнопки рядом — значит заставлять человека думать, какая из них нажата. */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  padding: 0;
}
.theme-toggle:hover { border-color: var(--primary); color: var(--primary); }
.theme-toggle:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--primary-light); }
/* Показываем ту иконку, которая обещает результат нажатия: в светлой теме
   луна («станет темно»), в тёмной — солнце. */
.theme-toggle .icon-dark { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-light { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-dark { display: block; }

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: 'Montserrat', -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
}

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

/* ---- Auth pages ---- */
.auth-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  /* Фон входа — цвет марки, а не действия: это ещё не работа, это порог. */
  background: var(--navy);
  background: radial-gradient(circle at top left, #1c2160 0%, var(--navy) 55%, #0b0e30 100%);
}
.auth-card {
  width: 380px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 32px;
  box-shadow: var(--shadow-lg);
}
.auth-card h1 { font-size: 20px; margin: 0 0 4px; color: var(--navy); }
.auth-card p.subtitle { color: var(--text-muted); margin: 0 0 20px; }

/* ---- App shell ---- */
.app-shell { display: flex; min-height: 100vh; }
.sidebar {
  width: var(--sidebar-w);
  flex-shrink: 0;
  /* Меню — цвет марки. В макете оно тоже navy: фиолетовая панель во всю
     высоту перетягивает внимание с того, что на ней написано. */
  background: var(--navy);
  color: rgba(255, 255, 255, .78);
  padding: 18px 0;
  display: flex;
  flex-direction: column;
}
.sidebar .brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  font-size: 18px;
  letter-spacing: .01em;
  color: #fff;
  padding: 4px 22px 22px;
}
.sidebar nav { flex: 1; display: flex; flex-direction: column; }
.sidebar nav a {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 11px 22px;
  color: rgba(255, 255, 255, .78);
  border-left: 3px solid transparent;
  font-size: 14px;
  font-weight: 500;
  transition: background .12s ease, color .12s ease;
}
.sidebar nav a:hover { background: rgba(255, 255, 255, .07); color: #fff; text-decoration: none; }
.sidebar nav a.active {
  background: rgba(255, 255, 255, .12);
  color: #fff;
  border-left-color: #fff;
  font-weight: 600;
}
.sidebar nav a svg { opacity: .85; }
.sidebar nav a.active svg { opacity: 1; }
.sidebar nav a.sub-link { padding-left: 44px; font-size: 13.5px; }

.sidebar .nav-group-toggle {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  border: none;
  background: none;
  cursor: pointer;
  padding: 11px 22px;
  color: rgba(255, 255, 255, .78);
  font-size: 14px;
  font-weight: 500;
  font-family: inherit;
  border-left: 3px solid transparent;
}
.sidebar .nav-group-toggle:hover { background: rgba(255, 255, 255, .07); color: #fff; }
.sidebar .nav-group-toggle .label { flex: 1; text-align: left; }
.sidebar .nav-group-toggle svg.chevron { transition: transform .18s ease; opacity: .6; }
.sidebar .nav-group-toggle[aria-expanded="true"] svg.chevron { transform: rotate(180deg); }
/* Раскрытие группы анимируется через grid-template-rows 0fr → 1fr.
   display: grid здесь обязателен: без него подпункты видны всегда. */
.sidebar .nav-group { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .2s ease; }
.sidebar .nav-group-inner { overflow: hidden; }
.sidebar .nav-group-toggle.active { color: #fff; border-left-color: #fff; font-weight: 600; }

.sidebar .group-title {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: rgba(255, 255, 255, .4);
  padding: 18px 22px 6px;
  font-weight: 600;
}

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 28px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.topbar h1 { font-size: 19px; margin: 0; font-weight: 700; color: var(--text); }
.topbar .user-chip { color: var(--text-muted); font-size: 13px; display: flex; align-items: center; gap: 12px; }

/* Счётчик непрочитанного поверх угла кнопки.

   Кнопке нужен position:relative — иначе счётчик уедет в угол ближайшего
   позиционированного предка, то есть куда-то в шапку. */
.btn-badged, .chat-launcher { position: relative; }
.btn-badge {
  position: absolute;
  top: -7px;
  right: -7px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  background: var(--danger);
  color: #fff;
  font-size: 11px;
  line-height: 18px;
  font-weight: 600;
  text-align: center;
}

/* Выпадающая панель под кнопкой в шапке: уведомления, меню профиля.

   Оболочка — .popover-anchor: без неё панель считает координаты от
   страницы, а не от своей кнопки. */
.popover-anchor { position: relative; display: inline-block; }
.popover {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  width: 340px;
  max-height: 400px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  z-index: 50;
  text-align: left;
}
.popover-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
}
.popover-item {
  display: block;
  width: 100%;
  text-align: left;
  border: none;
  border-bottom: 1px solid var(--border);
  padding: 10px 12px;
  background: transparent;
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
}
.popover-item.is-unread { background: var(--primary-light); }
.popover-item .when { color: var(--text-muted); font-size: 11px; margin-top: 2px; }

/* На телефоне панель шириной 340px, привязанная к правому краю своей
   кнопки, уезжает за левый край экрана. Отвязываем её от кнопки и
   растягиваем по ширине окна — привязка к кнопке нужна там, где рядом
   есть место, а на 375px его нет. */
@media (max-width: 760px) {
  .popover {
    position: fixed;
    top: 60px;
    left: 8px;
    right: 8px;
    width: auto;
    max-height: calc(100vh - 76px);
  }
}

.rates-strip { display: flex; align-items: center; gap: 6px; }
.rate-pill {
  background: var(--primary-light);
  color: var(--primary);
  padding: 3px 8px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

/* min-width:0 обязателен: без него дочерний элемент шире экрана
   растягивает саму колонку, и вбок уезжает вся страница вместе с меню,
   а не только широкий блок. */
.content { padding: 26px 28px; flex: 1; min-width: 0; }

/* ---- Building blocks ---- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 22px;
  box-shadow: var(--shadow);
  /* Широкая таблица прокручивается внутри карточки, а не тянет вбок всю
     страницу: иначе меню уезжает, а последние колонки просто обрезаются. */
  overflow-x: auto;
}
.card + .card { margin-top: 16px; }

.toolbar { display: flex; gap: 10px; align-items: center; margin-bottom: 18px; flex-wrap: wrap; }
.toolbar .spacer { flex: 1; }

/* Иконка-кнопка: по умолчанию только значок, при наведении раскрывается подпись. */
.btn-icon { padding: 8px 10px; overflow: hidden; }
.btn-icon .btn-label {
  display: inline-block;
  max-width: 0;
  overflow: hidden;
  white-space: nowrap;
  opacity: 0;
  transition: max-width .22s ease, opacity .15s ease, margin-left .22s ease;
}
.btn-icon:hover .btn-label,
.btn-icon:focus-visible .btn-label {
  max-width: 220px;
  opacity: 1;
  margin-left: 7px;
}

.btn {
  display: inline-flex;
  align-items: center;
  /* По центру и по горизонтали тоже. Пока стояло только align-items,
     кнопка с заданной шириной — в форме, в карточке реестра, в модалке —
     прижимала подпись к левому краю, и рядом с ней зияла пустота. */
  justify-content: center;
  gap: 6px;
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.3;
  /* Плавность только на цвете и тени. Анимировать размеры нельзя: кнопка,
     которая «дышит» при наведении, сдвигает соседние и промахивается мимо
     пальца на телефоне. */
  transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.btn:hover { background: var(--bg); text-decoration: none; }
/* Фокус с клавиатуры виден отдельно от наведения мышью: человек, идущий
   по форме табом, должен понимать, где он находится. */
.btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--primary-light); }
.btn-primary {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
  box-shadow: 0 2px 4px rgba(115, 103, 240, .35);
}
.btn-primary:hover { background: var(--primary-dark); border-color: var(--primary-dark); }
.btn-danger { color: var(--danger); border-color: var(--danger-light); background: var(--danger-light); }
.btn-danger:hover { background: rgba(234, 84, 85, .24); }
.btn-sm { padding: 5px 11px; font-size: 13px; border-radius: var(--radius-sm); }
/* Заблокированная кнопка обязана выглядеть заблокированной. Без этого
   человек жмёт её и решает, что система зависла. */
.btn[disabled], .btn:disabled {
  opacity: .55;
  cursor: not-allowed;
  box-shadow: none;
}

.form-group { margin-bottom: 14px; }
.form-group label { display: block; font-size: 13px; color: var(--text-muted); margin-bottom: 5px; font-weight: 500; }
.form-control, select.form-control, textarea.form-control {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 14px;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.form-control:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-light); }
/* Поле с ошибкой обведено красным до того, как человек полез читать
   подпись под ним: цвет замечают, текст — читают. */
.form-control[aria-invalid="true"], .form-control.is-invalid {
  border-color: var(--danger);
}
.form-control[aria-invalid="true"]:focus, .form-control.is-invalid:focus {
  box-shadow: 0 0 0 3px var(--danger-light);
}
.form-control[disabled], .form-control:disabled {
  background: var(--secondary-light);
  color: var(--text-disabled);
  cursor: not-allowed;
}
.form-error { color: var(--danger); font-size: 12px; margin-top: 4px; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
/* Форма в несколько колонок: число колонок подбирается по ширине экрана,
   поле на всю строку помечается утилитой .u-span-all. */
.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0 14px;
}

table.table { width: 100%; border-collapse: collapse; }
table.table th, table.table td {
  text-align: left;
  padding: 11px 12px;
  border-bottom: 1px solid var(--border);
  font-size: 13.5px;
}
table.table th { color: var(--text-muted); font-weight: 600; font-size: 12.5px; text-transform: uppercase; letter-spacing: .03em; }
table.table tbody tr:hover { background: var(--bg); }

.badge {
  display: inline-block;
  padding: 3px 9px;
  border-radius: var(--radius-sm);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .02em;
  color: #fff;
  white-space: nowrap;
  background: var(--text-muted);
}

.empty-state { text-align: center; color: var(--text-muted); padding: 40px 0; }
.empty-state-title { font-weight: 600; margin-bottom: 4px; color: var(--text); }

/* Страницы ошибок: 404, 403, 419, 429, 500, 503.

   Свой маленький набор правил, потому что у этих страниц нет ни бокового
   меню, ни шапки — они открываются и без входа в систему, и в момент,
   когда сломано всё остальное. Внутри — тот же блок .empty-state, что и
   в пустых списках: человек узнаёт карточку и понимает, что он всё ещё
   в системе, а не провалился в чужую страницу. */
.error-shell {
  max-width: 520px;
  margin: 0 auto;
  padding: 72px 20px;
  text-align: center;
}
.error-brand { display: inline-block; margin-bottom: 40px; }
/* Номер ошибки крупный, но приглушённый: он нужен поддержке, а не
   человеку, и не должен перебивать фразу под ним. */
.error-code {
  font-size: 44px;
  font-weight: 700;
  line-height: 1;
  color: var(--border);
  margin-bottom: 12px;
}
.error-shell .empty-state { padding: 0; }
.error-actions {
  display: flex;
  gap: 10px;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 28px;
}

.form-label { display: block; font-size: 13px; color: var(--text-muted); margin-bottom: 5px; font-weight: 500; }

/* Пустая подпись-распорка: держит высоту строки, чтобы кнопка в конце
   ряда фильтров встала вровень с полями. Пустой элемент схлопнулся бы,
   поэтому высота задаётся явно. */
.form-label-spacer { height: 18px; }
.form-hint { color: var(--text-muted); font-size: 12px; margin-top: 4px; }

/* Поле пароля с глазиком.

   Кнопка лежит поверх поля, а не рядом: рядом она отняла бы ширину
   у самого поля, а на телефоне там и так тесно. Полю добавлен отступ
   справа, чтобы длинный пароль не заезжал под кнопку. */
.password-field { position: relative; }
.password-field .form-control { padding-right: 42px; }

.password-eye {
  position: absolute;
  top: 0;
  right: 0;
  width: 40px;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}

.password-eye:hover { color: var(--primary); }

/* Показан открытый глаз, пока пароль скрыт: значок обещает действие,
   а не докладывает о состоянии. Перечёркнутый — когда пароль виден. */
.password-eye .eye-closed { display: none; }
.password-eye.is-shown .eye-open { display: none; }
.password-eye.is-shown .eye-closed { display: block; }

.alert { padding: 11px 14px; border-radius: var(--radius); margin-bottom: 16px; font-size: 13.5px; }
.alert-error { background: var(--danger-light); color: #b3151a; border: 1px solid #ffc9cb; }
.alert-success { background: var(--success-light); color: #157347; border: 1px solid #b8ecd0; }
/* Предупреждение: не ошибка, но требует внимания — незакрытый остаток,
   приближающийся срок, неполные данные. */
.alert-warning { background: var(--warning-light); color: #8a5300; border: 1px solid #ffe0a3; }

/* ---- Kanban board ---- */
.board { display: flex; gap: 14px; overflow-x: auto; padding-bottom: 8px; }
/* Граница у колонки видимая: одного фона мало — на светлой теме колонка
   сливается со страницей, и глазу не за что зацепиться, где кончается
   «В работе» и начинается «Проверка». */
.board-col { flex: 0 0 270px; background: var(--bg); padding: 10px; border: 1px solid var(--border); }
.board-col-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: -10px -10px 10px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  font-weight: 600;
}
.board-col-head .count { color: var(--text-muted); font-weight: 400; }
.board-card {
  background: var(--surface);
  padding: 10px 12px;
  margin-bottom: 8px;
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  display: block;
}
.board-card:hover { border-color: var(--primary); text-decoration: none; }
.board-card[draggable="true"] { cursor: grab; }
.board-card.dragging { opacity: 0.4; }
.board-card .num { font-weight: 600; font-size: 13px; display: flex; align-items: center; gap: 6px; }
.board-card .device { color: var(--text); font-size: 13.5px; margin: 3px 0; }
.board-card .customer { color: var(--text-muted); font-size: 12.5px; }

.board-col.drag-over { background: var(--primary-light); outline: 2px dashed var(--primary); outline-offset: -2px; }

.badge-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; }
.badge-dot-term { background: var(--warning); }
.badge-dot-overdue { background: var(--danger); }
.badge-dot-debt { background: var(--info); }

.filter-tabs { display: flex; gap: 6px; flex-wrap: wrap; }
.filter-tab {
  border: 1px solid var(--border);
  background: var(--surface);
  padding: 6px 12px;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-muted);
  cursor: pointer;
}
.filter-tab:hover { border-color: var(--primary); color: var(--text); }
.filter-tab.active { background: var(--primary); border-color: var(--primary); color: #fff; }
.filter-tab-term.active { background: var(--warning); border-color: var(--warning); }
.filter-tab-overdue.active { background: var(--danger); border-color: var(--danger); }
.filter-tab-debt.active { background: var(--info); border-color: var(--info); }

.status-dot { display: inline-block; width: 9px; height: 9px; margin-right: 6px; }

/* ================================================================
   Библиотека компонентов
   Всё оформление живёт здесь, а не в инлайновых style="" шаблонов:
   так экраны выглядят одинаково и правятся в одном месте.
   ================================================================ */

/* --- Заголовок карточки и секции --- */
.card-title {
  margin: 0 0 14px;
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}
.card-title .sub {
  font-weight: 400;
  font-size: 12.5px;
  color: var(--text-muted);
  margin-left: 8px;
}
.card-tight { padding: 14px 16px; }

/* --- Плитка показателя (дашборд, отчёты) --- */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
}
.stat {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--primary);
  padding: 16px 18px;
}
.stat .stat-label {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-muted);
  font-weight: 600;
}
.stat .stat-value {
  font-size: 24px;
  font-weight: 700;
  color: var(--text);
  margin-top: 6px;
  line-height: 1.15;
}
.stat .stat-hint { font-size: 12.5px; color: var(--text-muted); margin-top: 4px; }
.stat-success { border-left-color: var(--success); }
.stat-danger { border-left-color: var(--danger); }
.stat-warning { border-left-color: var(--warning); }
.stat-info { border-left-color: var(--info); }

/* --- Индикатор выполнения --- */
.progress {
  background: var(--border);
  overflow: hidden;
  height: 8px;
  width: 100%;
}
.progress-bar { height: 100%; background: var(--primary); }
.progress-lg { height: 14px; }
.progress-sm { height: 6px; }
.progress-success .progress-bar { background: var(--success); }
.progress-danger .progress-bar { background: var(--danger); }
.progress-warning .progress-bar { background: var(--warning); }
.progress-wrap { display: flex; align-items: center; gap: 8px; }
.progress-wrap .progress { flex: 1; min-width: 60px; }
.progress-value { font-size: 12.5px; color: var(--text-muted); white-space: nowrap; font-variant-numeric: tabular-nums; }

/* --- Вложенная панель (списки выбора, блоки внутри форм) --- */
.panel {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px;
  background: var(--surface);
}
.panel + .panel { margin-top: 8px; }
.panel-scroll { max-height: 180px; overflow-y: auto; }
.panel-muted { background: var(--bg); }

/* Тон панели: цветом отмечена только левая кромка. Заливать весь блок
   тревожным цветом — значит кричать там, где достаточно указать. */
.panel-warning { border-left: 3px solid var(--warning); }
.panel-danger { border-left: 3px solid var(--danger); }
.panel-success { border-left: 3px solid var(--success); }

/* --- Пары «подпись — значение» на карточках --- */
.def-list { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; font-size: 13.5px; }
.def-list dt { color: var(--text-muted); }
.def-list dd { margin: 0; }

/* --- Бейджи по смыслу состояния --- */
.badge-success { background: var(--success); }
.badge-danger { background: var(--danger); }
.badge-warning { background: var(--warning); }
.badge-info { background: var(--info); }
.badge-primary { background: var(--primary); }
.badge-muted { background: var(--text-muted); }
.badge-outline {
  background: transparent;
  color: var(--text-muted);
  border: 1px solid var(--border);
}
/* Приглушённый вариант для «спокойных» отметок: имя ответственного, метка. */
.badge-soft { background: var(--primary-light); color: var(--primary); }
.badge-inline { display: inline-flex; align-items: center; gap: 6px; }

/* Подпись поля на карточке: «Адрес», «Ответственный», «Срок». */
.meta-label { font-size: 12px; color: var(--text-muted); margin-bottom: 2px; }
.meta-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 14px;
  margin-bottom: 14px;
}

/* --- Модальное окно --- */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(19, 23, 71, .45);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 60px 20px 20px;
  z-index: 100;
  overflow-y: auto;
}
.modal {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-width: 560px;
}
.modal-wide { max-width: 860px; }
.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
}
.modal-head h3 { margin: 0; font-size: 15px; font-weight: 600; }
.modal-close {
  border: none;
  background: none;
  cursor: pointer;
  font-size: 20px;
  line-height: 1;
  color: var(--text-muted);
  padding: 0 4px;
  font-family: inherit;
}
.modal-close:hover { color: var(--text); }
.modal-body { padding: 20px; }
.modal-foot {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  padding: 14px 20px;
  border-top: 1px solid var(--border);
  background: var(--bg);
}

/* --- Слитная группа кнопок-переключателей (разрезы списков) --- */
.btn-group { display: inline-flex; }
.btn-group .btn + .btn { margin-left: -1px; }
.btn-group .btn.btn-primary { position: relative; z-index: 1; }

/* --- Вкладки внутри страницы --- */
.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border); margin-bottom: 18px; }
.tab {
  border: 1px solid transparent;
  border-bottom: none;
  background: none;
  padding: 9px 16px;
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--text-muted);
  cursor: pointer;
  margin-bottom: -1px;
}
.tab:hover { color: var(--text); }
.tab.active {
  background: var(--surface);
  border-color: var(--border);
  border-bottom: 1px solid var(--surface);
  color: var(--primary);
  font-weight: 600;
}

/* --- Строка фильтров --- */
/* Строка полей: и фильтры над списком, и форма в несколько колонок.

   Выравнивание по верху, а не по низу. По низу поле с подсказкой
   приподнималось на её высоту, и в одном ряду поля стояли лесенкой —
   форма выглядела съехавшей. Кнопке в конце строки фильтров ровняться
   помогает пустая подпись (x-field spacer), а не выравнивание всей
   сетки. */
.filters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  align-items: start;
  margin-bottom: 16px;
}

/* Подпись всегда занимает строку, даже когда её нет: иначе поле без
   подписи встаёт выше соседей. */
.filters .form-group > label,
.form-grid .form-group > label,
.filters .form-label,
.form-grid .form-label { min-height: 18px; }
.filters .form-group { margin-bottom: 0; }

/* ================================================================
   Диаграмма Ганта
   Полосы позиционируются в пикселях от левого края полотна: так
   масштабирование и прокрутка работают предсказуемо, а перетаскивание
   пересчитывается в дни делением на ширину дня.
   ================================================================ */
.gantt { display: flex; border: 1px solid var(--border); overflow: hidden; }

.gantt-legend { display: flex; gap: 16px; flex-wrap: wrap; font-size: 12px; color: var(--text-muted); align-items: center; }
.gantt-swatch { display: inline-block; width: 14px; height: 10px; vertical-align: middle; margin-right: 4px; }
.gantt-swatch-normal { background: var(--primary); }
.gantt-swatch-critical { background: var(--danger); }
.gantt-swatch-done { background: var(--success); }
.gantt-swatch-baseline { background: transparent; border: 1px dashed var(--text-muted); }

/* Левая колонка с названиями не уезжает при горизонтальной прокрутке. */
.gantt-labels {
  flex: 0 0 260px;
  border-right: 1px solid var(--border);
  background: var(--surface);
  z-index: 2;
}
.gantt-label {
  height: 30px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding-right: 8px;
  font-size: 12.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border-bottom: 1px solid var(--border);
}
.gantt-label a { color: var(--text); overflow: hidden; text-overflow: ellipsis; }
.gantt-toggle {
  border: none;
  background: none;
  cursor: pointer;
  font-size: 11px;
  color: var(--text-muted);
  padding: 0 2px;
  font-family: inherit;
}

.gantt-scroll { flex: 1; overflow-x: auto; overflow-y: hidden; }
.gantt-canvas { position: relative; }

.gantt-head {
  height: 40px;
  position: relative;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
}
.gantt-months { position: relative; height: 20px; }
.gantt-month {
  position: absolute;
  top: 0;
  height: 20px;
  line-height: 20px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text);
  border-left: 1px solid var(--border);
  padding-left: 5px;
  overflow: hidden;
  white-space: nowrap;
  text-transform: capitalize;
}
.gantt-ticks { position: relative; height: 20px; }
.gantt-tick {
  position: absolute;
  top: 0;
  font-size: 10.5px;
  color: var(--text-muted);
  border-left: 1px solid var(--border);
  padding-left: 3px;
  line-height: 20px;
  white-space: nowrap;
}
.gantt-tick-weekend { color: var(--danger); }

.gantt-body { position: relative; }
.gantt-grid-line { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--border); opacity: .5; }
.gantt-today { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--warning); z-index: 3; }
.gantt-arrows { position: absolute; top: 0; left: 0; pointer-events: none; z-index: 1; }

.gantt-row { position: absolute; left: 0; right: 0; border-bottom: 1px solid var(--border); }
.gantt-nodate { position: absolute; left: 8px; top: 8px; font-size: 11px; color: var(--text-muted); }

.gantt-bar {
  position: absolute;
  top: 5px;
  height: 20px;
  background: var(--primary-light);
  border: 1px solid var(--primary);
  overflow: hidden;
  z-index: 2;
}
.gantt-fill { height: 100%; background: var(--primary); opacity: .75; }
.gantt-bar-text {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  padding-left: 5px;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--text);
  pointer-events: none;
}
.gantt-bar-critical { background: var(--danger-light); border-color: var(--danger); }
.gantt-bar-critical .gantt-fill { background: var(--danger); }
.gantt-bar-done { background: var(--success-light); border-color: var(--success); }
.gantt-bar-done .gantt-fill { background: var(--success); }

.gantt-bar-group { top: 9px; height: 12px; background: var(--text-muted); border-color: var(--text); }
.gantt-bar-group .gantt-fill { background: var(--text); }

/* Базовый план — полупрозрачная полоса под фактической. */
.gantt-bar-baseline {
  top: 22px;
  height: 5px;
  background: transparent;
  border: 1px dashed var(--text-muted);
  z-index: 1;
}

.gantt-draggable { cursor: grab; }
.gantt-draggable:active { cursor: grabbing; }
.gantt-handle {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: 6px;
  cursor: ew-resize;
  background: rgba(19, 23, 71, .25);
}

/* ================================================================
   Утилиты раскладки
   Небольшой набор для повторяющихся мелочей: отступы, выравнивание,
   приглушённый текст. Нужен, чтобы не плодить одинаковые style=""
   в шаблонах. Всё сложнее пары свойств — оформляем компонентом.
   ================================================================ */
.u-muted { color: var(--text-muted); }
.u-danger { color: var(--danger); }
.u-sm { font-size: 12px; }
.u-md { font-size: 13px; }
.u-lg { font-size: 18px; }
.u-bold { font-weight: 600; }
.u-note { color: var(--text-muted); font-size: 12px; }
/* Отпечаток документа — цепочка из шестидесяти четырёх знаков. Её
   сверяют глазами, а в пропорциональном шрифте единица и буква l
   выглядят одинаково. */
.u-mono { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; word-break: break-all; }
.u-metric { font-size: 18px; font-weight: 600; }
.u-right { text-align: right; }
.u-right-bold { text-align: right; font-weight: 600; }

.u-m-0 { margin: 0; }
.u-mb-0 { margin-bottom: 0; }
.u-mb-8 { margin-bottom: 8px; }
.u-mb-10 { margin-bottom: 10px; }
.u-mb-16 { margin-bottom: 16px; }
.u-mt-8 { margin-top: 8px; }
.u-mt-12 { margin-top: 12px; }
.u-mt-14 { margin-top: 14px; }
.u-mt-16 { margin-top: 16px; }

.u-span-all { grid-column: 1 / -1; }
.u-split { display: grid; grid-template-columns: 2fr 1fr; gap: 14px; align-items: start; }

@media print {
  .no-print { display: none !important; }
}

/* --- Обсуждение на карточке --- */
.comment-thread {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-height: 420px;
  overflow-y: auto;
}

.comment {
  border: 1px solid var(--border);
  border-left: 3px solid var(--primary);
  padding: 10px 12px;
  background: var(--bg);
}

.comment-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
  font-size: 13px;
}

.comment-time { color: var(--text-muted); font-size: 12px; }

.comment-delete {
  border: none;
  background: none;
  cursor: pointer;
  color: var(--text-muted);
  font-size: 18px;
  line-height: 1;
  padding: 0 2px;
}

.comment-delete:hover { color: var(--danger); }

.comment-body { font-size: 14px; line-height: 1.5; word-break: break-word; }

.mention {
  background: var(--primary-light);
  color: var(--primary);
  font-weight: 600;
  padding: 0 3px;
}

.mention-file { text-decoration: underline; }

.picker-row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  text-align: left;
  border: none;
  background: none;
  cursor: pointer;
  padding: 8px;
  border-bottom: 1px solid var(--border);
  font-family: inherit;
  font-size: 14px;
}

.picker-row:hover { background: var(--primary-light); }

.picker-group {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-muted);
  padding: 8px 8px 4px;
  border-bottom: 1px solid var(--border);
}

.mention-ref { text-decoration: underline; }
.mention-gone { text-decoration: line-through; opacity: .65; }

.u-danger-row { background: var(--danger-light); }

/* --- Кликабельная плитка показателя --- */
.stat-link { display: block; text-decoration: none; color: inherit; }
.stat-link:hover { border-color: var(--primary); }
.stat-link .stat-value { text-decoration: none; }

.stat-bar {
  height: 4px;
  background: var(--border);
  margin: 6px 0 4px;
}

.stat-bar-fill { height: 100%; background: var(--primary); }

/* --- Столбчатая диаграмма --- */
.bar-chart {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 150px;
  overflow-x: auto;
}

.bar-col {
  flex: 1;
  min-width: 34px;
  display: flex;
  flex-direction: column;
  height: 100%;
}

.bar-slot { flex: 1; display: flex; flex-direction: column; }

.bar-chart:not(.bar-chart-signed) .bar-slot { justify-content: flex-end; }

.bar-half { flex: 1; display: flex; }
.bar-half-up { align-items: flex-end; }
.bar-half-down { align-items: flex-start; }

.bar-zero { height: 1px; background: var(--text-muted); }

.bar { width: 100%; }
.bar-positive { background: var(--primary); }
.bar-negative { background: var(--danger); }

.bar-label {
  font-size: 10px;
  color: var(--text-muted);
  text-align: center;
  padding-top: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ================================================================
   Адаптив: планшет и телефон
   ================================================================

   Раскладка на широком экране — боковое меню плюс рабочая область.
   На телефоне колонка в 240 px съедает две трети ширины, поэтому меню
   становится выезжающим, а всё остальное — в одну колонку.

   Гриды (form-grid, stat-grid, filters, meta-grid) построены на
   auto-fit/minmax и перестраиваются сами — им правила не нужны.
   Отдельно поджимаются только отступы и то, что задано жёстко.
   ================================================================ */

.menu-toggle {
  display: none;
  background: none;
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 18px;
  line-height: 1;
  /* Палец — не курсор: меньше 44 px в него не попадают. */
  min-width: 44px;
  min-height: 44px;
  margin-right: 12px;
  cursor: pointer;
}

.menu-scrim {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(19, 23, 71, .45);
  border: 0;
  z-index: 40;
}

[x-cloak] { display: none !important; }

@media (max-width: 900px) {
  .topbar { padding: 12px 14px; }
  .topbar h1 { font-size: 16px; }
  .content { padding: 14px; }
  .card { padding: 14px; }

  /* Название компании и имя пользователя в шапке телефона не помещаются,
     а кнопка выхода нужна всегда — прячем текст, оставляем действия. */
  .topbar .user-chip { font-size: 0; gap: 6px; }
  .topbar .user-chip * { font-size: 13px; }

  .menu-toggle { display: inline-flex; align-items: center; justify-content: center; }
  .menu-scrim { display: block; }

  .sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 50;
    /* Меню уезжает за край, а не скрывается display:none — так оно
       возвращается плавно и не перестраивает раскладку рывком. */
    transform: translateX(-100%);
    transition: transform .18s ease-out;
    overflow-y: auto;
  }

  .menu-open .sidebar { transform: translateX(0); }

  /* Кнопки в панели действий на телефоне встают в строку и переносятся,
     а не выстраиваются в узкий столбец. */
  .toolbar { gap: 8px; }
  .toolbar .btn { min-height: 40px; }

  /* Таблицы шире экрана прокручиваются внутри карточки. Ломать их в
     карточки-строки нельзя: в журналах и ведомостях смысл именно
     в сопоставлении колонок по строке. */
  table.table { min-width: 640px; }

  /* Палец тянет таблицу вбок, и ссылка под ним не должна принимать это
     за нажатие. pan-x/pan-y отдаёт жест прокрутке: браузер перестаёт
     ждать, тап это или протяжка, и промахов не случается. */
  .u-scroll-x, .card { -webkit-overflow-scrolling: touch; touch-action: pan-x pan-y; }

  /* Ссылка в таблице на телефоне — цель для пальца, а не для курсора. */
  table.table a { display: inline-block; padding: 2px 0; }
}

@media (max-width: 600px) {
  .topbar .user-chip form { margin-left: 0; }
  .stat-grid { gap: 10px; }

  /* Поля ввода не меньше 16 px: иначе Safari на iPhone зумит страницу
     при фокусе и пользователь оказывается в увеличенной вёрстке. */
  .form-control, .btn { font-size: 16px; }
}

/* --- Плавающий чат ---

   Кнопка в правом нижнем углу и панель над ней. Панель перекрывает край
   содержимого намеренно: разговор — это второй план поверх работы, а не
   ещё одна колонка, отнимающая ширину у таблиц.

   Скруглений нет и здесь: круглая кнопка чата — привычка внешних
   виджетов, но в системе, где ни один угол не скруглён, она читалась бы
   как чужеродная вставка. */
.chat-widget {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
}

.chat-launcher {
  width: 52px;
  height: 52px;
  border: none;
  background: var(--primary);
  color: #fff;
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(19, 23, 71, 0.25);
  display: flex;
  align-items: center;
  justify-content: center;
}
.chat-launcher:hover { background: var(--primary-dark, #0d1035); }

.chat-panel {
  width: 360px;
  max-width: calc(100vw - 40px);
  height: 520px;
  max-height: calc(100vh - 120px);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: 0 6px 28px rgba(19, 23, 71, 0.18);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.chat-head {
  background: var(--primary);
  color: #fff;
  padding: 10px 12px;
  display: flex;
  align-items: flex-start;
  gap: 8px;
}
.chat-title { font-weight: 600; font-size: 14px; }
.chat-sub { font-size: 12px; opacity: 0.8; }
.chat-sub a { color: #fff; text-decoration: underline; }
.chat-close {
  margin-left: auto;
  background: none;
  border: none;
  color: #fff;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}

.chat-channels {
  display: flex;
  gap: 6px;
  padding: 8px 10px;
  overflow-x: auto;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.chat-chip {
  border: 1px solid var(--border);
  background: var(--bg);
  padding: 4px 9px;
  font-size: 12px;
  white-space: nowrap;
  cursor: pointer;
  font-family: inherit;
}
.chat-chip.active { background: var(--primary); color: #fff; border-color: var(--primary); }
/* Сколько ждёт именно в этом канале: без разбивки человек открывает чат,
   видит общую цифру и не знает, где искать. */
.chat-chip-count {
  display: inline-block;
  min-width: 16px;
  margin-left: 5px;
  padding: 0 4px;
  background: var(--danger);
  color: #fff;
  font-size: 10.5px;
  line-height: 16px;
  font-weight: 600;
  text-align: center;
}

.chat-search { padding: 8px 10px; border-bottom: 1px solid var(--border); flex-shrink: 0; }
.chat-found { margin-top: 6px; max-height: 160px; overflow-y: auto; border: 1px solid var(--border); }
.chat-found-row {
  display: block;
  width: 100%;
  text-align: left;
  border: none;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  padding: 7px 9px;
  font-size: 12.5px;
  cursor: pointer;
  font-family: inherit;
}
.chat-found-row:last-child { border-bottom: none; }
.chat-found-row:hover { background: var(--bg); }
.chat-found-kind { color: var(--text-muted); font-size: 11px; display: block; }

.chat-body { flex: 1; overflow-y: auto; padding: 10px; display: flex; flex-direction: column; gap: 8px; }
.chat-empty { color: var(--text-muted); font-size: 12.5px; margin: auto 0; text-align: center; }

.chat-message { border-left: 3px solid var(--border); padding: 2px 0 2px 8px; }
/* Свои сообщения отмечены кромкой, а не выравниванием вправо: в рабочей
   переписке важнее быстро читать колонку, чем видеть «кто где». */
.chat-message.mine { border-left-color: var(--primary); }
.chat-meta { font-size: 11.5px; color: var(--text-muted); display: flex; gap: 6px; align-items: baseline; }
.chat-text { font-size: 13px; word-break: break-word; }

.chat-form { border-top: 1px solid var(--border); padding: 8px 10px; flex-shrink: 0; }
.chat-form textarea { font-size: 13px; resize: none; }
.chat-picker { border: 1px solid var(--border); padding: 8px; margin-top: 6px; max-height: 200px; overflow-y: auto; }
.chat-actions { display: flex; gap: 6px; align-items: center; margin-top: 6px; }
.chat-actions .spacer { flex: 1; }

@media (max-width: 600px) {
  /* На телефоне панель занимает почти весь экран: читать переписку в
     окошке 360 px на экране 360 px невозможно. */
  .chat-widget { right: 12px; bottom: 12px; left: 12px; align-items: stretch; }
  .chat-panel { width: auto; height: calc(100vh - 100px); }
  .chat-launcher { align-self: flex-end; }
}

@media print { .chat-widget { display: none; } }

/* Файл в сообщении чата. */
.chat-file {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 4px;
  padding: 3px 7px;
  border: 1px solid var(--border);
  background: var(--bg);
  font-size: 12.5px;
}
.chat-file:hover { text-decoration: none; background: var(--primary-light); }
/* Срок хранения виден сразу: файл, пропавший без предупреждения, —
   потерянный файл, даже если так и задумано. */
.chat-file-life { color: var(--warning); font-size: 11.5px; }

.chat-pending-files { margin-top: 6px; font-size: 12.5px; }
.chat-pending-files span {
  display: inline-block;
  background: var(--primary-light);
  padding: 2px 7px;
  margin: 0 4px 4px 0;
}

/* --- Конструктор актов: строка поля --- */
.field-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
}
.field-row:last-of-type { border-bottom: none; }
.field-row .form-control { flex: 1; min-width: 0; }
/* Захват для перетаскивания: курсор говорит, что строку можно двигать,
   до того как человек попробует. */
.field-grip { cursor: grab; color: var(--text-muted); user-select: none; font-size: 15px; }
.field-row:active .field-grip { cursor: grabbing; }

@media (max-width: 900px) {
  /* На телефоне перетаскивание не работает, поэтому строка разворачивается
     в столбец: править поля важнее, чем менять их порядок. */
  .field-row { flex-wrap: wrap; }
  .field-row .form-control { flex-basis: 100%; }
  .field-grip { display: none; }
}

/* --- Подпись на объекте ---
   touch-action: none обязателен: без него палец на холсте прокручивает
   страницу вместо того, чтобы рисовать, и подписаться с телефона нельзя. */
.signature-pad {
  width: 100%;
  max-width: 520px;
  height: 180px;
  border: 1px dashed var(--border);
  background: #fff;
  touch-action: none;
  display: block;
}
.signature-image { max-height: 110px; display: block; border: 1px solid var(--border); background: #fff; }

/* Быстрое добавление справочной записи прямо из формы: кнопка живёт под
   выпадающим списком и не должна выглядеть равной ему по весу. */
.quick-add {
    margin-top: 6px;
    font-size: 12px;
}

/* --- Разделы сущности и группы действий ---

   Три вида кнопок на карточке решают три разные задачи, и раньше они
   стояли одним рядом: переходы вглубь, действия над записью и уход со
   страницы. Ряд из девяти одинаковых кнопок читается по одной.

   Теперь: разделы — вкладками, действия — группой справа, разрушительное
   отделено промежутком, «К списку» — слева и вне групп. */

.section-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--border);
}

.section-tab {
  padding: 9px 14px;
  color: var(--text-muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}

.section-tab:hover { color: var(--primary); background: rgba(19, 23, 71, .04); }

.section-tab.is-active {
  color: var(--primary);
  font-weight: 600;
  border-bottom-color: var(--primary);
}

/* Группа однородных действий. Промежуток между группами вдвое больше,
   чем между кнопками внутри, — граница видна без разделительных линий. */
.toolbar-group { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.toolbar-group + .toolbar-group { margin-left: 12px; }

/* Разрушительное действие стоит отдельно: «Удалить» вплотную к
   «Редактировать» нажимают промахом. */
.toolbar-group-danger { margin-left: 20px; }

@media (max-width: 960px) {
  /* Промежутки между группами на узком экране только гонят перенос:
     кнопка, уехавшая на свою строку, выглядит потерянной. */
  .toolbar-group + .toolbar-group,
  .toolbar-group-danger { margin-left: 0; }
}

@media (max-width: 700px) {
  .section-tabs { overflow-x: auto; flex-wrap: nowrap; }
}

/* --- Заголовки широких таблиц ---

   Таблица шире экрана уже прокручивается внутри карточки — это её
   собственная прокрутка, заданная min-width у таблицы и overflow у
   карточки. Второй прокручиваемый слой поверх первого делать нельзя:
   палец попадает то в один, то в другой, и таблица дёргается.

   Здесь только заголовки: перенос слов в шапке делает таблицу выше
   экрана, и читать её становится нечем. */
@media (max-width: 900px) {
  table.table th { white-space: nowrap; }
}

/* --- Канбан на телефоне: как в Trello ---

   Приём оттуда и он же единственный работающий. Колонка занимает почти
   всю ширину экрана, но не всю: соседняя выглядывает краем. Этот край и
   есть подсказка, что доска продолжается вправо, — без него человек
   уверен, что колонка одна.

   Смахивание доводится доводчиком до края следующей колонки, а не
   останавливается посередине: полторы колонки на экране читать нельзя.

   overscroll-behavior-x: contain обязателен. Без него смахивание вправо
   на краю доски уводит браузер назад по истории, и человек вылетает со
   страницы, пытаясь долистать до последней колонки. */
@media (max-width: 760px) {
  .board {
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    /* Отступ по краям, чтобы первая и последняя колонки не липли к
       границе экрана. */
    padding-inline: 2px;
  }

  .board-col {
    flex: 0 0 86vw;
    scroll-snap-align: start;
  }
}

/* Пока карточку тащат, доводчик выключается.

   Он тянет доску к ближайшей колонке, а перетаскивание тянет её к краю
   экрана, чтобы показать соседнюю. Два притяжения одновременно — и
   доска дёргается под пальцем, а карточка падает не туда. */
.board.is-dragging { scroll-snap-type: none; }

/* Кнопки в карточке реестра — палец, а не мышь: 40px это нижняя
   граница, ниже которой промахиваются. */
@media (max-width: 760px) {
  table.table-cards td .btn { min-height: 40px; min-width: 40px; }
}

/* --- Реестр на телефоне: строка становится карточкой ---

   Таблица шириной в пять колонок на экране 375px читается только
   горизонтальной прокруткой, а прокручивать таблицу и одновременно
   помнить, к какой строке относится ячейка, невозможно.

   Поэтому на телефоне строка разворачивается в карточку: значения идут
   сверху вниз, каждое со своей подписью из data-label. Подпись берётся из
   разметки, а не из заголовка таблицы: заголовок в этот момент скрыт.

   Признак .table-cards вешает js/table-cards.js — он же переносит подписи
   из заголовка таблицы в ячейки. Руками расставить их в ста тридцати шести
   реестрах можно, но следующую таблицу забудут, и в карточке останутся
   голые цифры, где не отличить сумму от остатка.

   Исключение помечается классом .table-wide: сверка, план-факт, бюджет,
   табель по дням. Там сравнение по колонкам и есть смысл, и прокрутка
   честнее карточек. */
@media (max-width: 760px) {
  table.table-cards { display: block; overflow-x: visible; }
  table.table-cards thead { display: none; }
  table.table-cards tbody { display: block; }

  table.table-cards tr {
    display: block;
    border: 1px solid var(--border);
    padding: 10px 12px;
    margin-bottom: 10px;
    background: var(--surface);
  }

  table.table-cards td {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    border: none;
    padding: 4px 0;
    text-align: left;
  }

  table.table-cards td::before {
    content: attr(data-label);
    color: var(--text-muted);
    font-size: 12px;
    flex-shrink: 0;
  }

  /* Ячейка без подписи — обычно первая (название) и последняя (кнопки).
     Название занимает всю ширину и набирается крупнее: это заголовок
     карточки. Кнопки прижимаются вправо. */
  /* Снимаем жёсткий min-width, заданный для прокручиваемых таблиц
     выше по файлу. Без этого карточка остаётся шириной 640px внутри
     экрана в 375: подписи видны, а значения уезжают за край, и
     карточка прокручивается вбок ровно так же, как таблица. Это и была
     причина, по которой карточный вид выглядел нерабочим. */
  table.table-cards { min-width: 0; }

  table.table-cards td:not([data-label])::before { content: none; }
  table.table-cards td:first-child { font-weight: 600; font-size: 15px; }
  table.table-cards td:last-child { justify-content: flex-end; padding-top: 8px; }
}

/* --- Многоколоночные формы на телефоне: в одну колонку ---

   Здесь единственное место во всём стиле, где стоит !important, и вот
   почему. Число колонок у .form-row задаётся инлайном прямо в разметке —
   «1fr 1fr auto», «repeat(4, 1fr)», «160px 200px 200px 150px 1fr auto» —
   потому что у каждой формы своё. Инлайн-стиль сильнее любого правила в
   файле, и обычным медиазапросом его не перебить: на телефоне форма из
   шести колонок так и осталась бы шестиколоночной, где каждое поле шире
   экрана вдвое.

   Переписать полсотни таких мест на классы можно, но до тех пор формы
   на телефоне нечитаемы, а правило ниже чинит их все сразу. */
@media (max-width: 760px) {
  .form-row,
  form.form-row {
    grid-template-columns: 1fr !important;
    align-items: stretch !important;
  }

  /* Кнопка в конце такой строки была прижата к нижнему краю ячейки —
     в одну колонку ей ровняться не по чему, и она растягивается. */
  .form-row > .btn { width: 100%; }
}

/* --- Кнопки и поля под палец ---

   На мыши промах стоит движения запястья, на телефоне — попадания
   в соседнюю кнопку. Между «Изменить» и «Удалить» промахнуться особенно
   обидно, поэтому 40px по высоте здесь не про красоту.

   btn-sm на телефоне перестаёт быть маленькой: она задумывалась мелкой,
   чтобы не спорить с содержимым таблицы, а в карточке спорить уже не
   с чем — там она единственное, по чему нажимают. */
@media (max-width: 760px) {
  .btn, .btn-sm {
    min-height: 40px;
    padding: 9px 14px;
    font-size: 14px;
  }

  /* Значок без подписи — квадрат: полоска шириной в иконку под палец
     не попадает. */
  .btn-icon { min-width: 40px; justify-content: center; }

  /* Подпись у иконки раскрывается по наведению, а наведения на телефоне
     нет вовсе — значит подпись не покажется никогда. В карточке место
     есть, и слово рядом со значком снимает всякие догадки. */
  table.table-cards .btn-icon { justify-content: flex-start; }
  table.table-cards .btn-icon .btn-label {
    max-width: none;
    opacity: 1;
    margin-left: 7px;
  }

  /* Группа кнопок в карточке разъезжается по ширине, а не жмётся
     в правый угол: в углу они стоят вплотную и промахи неизбежны. */
  table.table-cards td:last-child { flex-wrap: wrap; gap: 8px; }

  /* Ничто не шире экрана.

     Ширины в разметке заданы под широкий экран — 320px, 480px, встречается
     и 720px. На 375px такой блок выталкивает страницу вбок целиком, и
     горизонтально едет уже всё, включая шапку.

     Таблиц это не касается: у прокручиваемых стоит min-width, он сильнее,
     и прокрутка внутри карточки сохраняется намеренно. */
  .content input,
  .content select,
  .content textarea,
  .content .form-control,
  .content .card > div[style*="width"],
  .content img { max-width: 100%; }
}

/* --- Полоса песочницы --- */
/* Липкая сверху и поверх всего: человек, увлёкшийся заполнением документа,
   обязан видеть счётчик, а не вспомнить о нём на экране «сессия завершена».
   Показывается только на контуре песочницы — на остальных её нет в разметке. */

.sandbox-bar {
  position: sticky;
  top: 0;
  z-index: 60;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 6px 14px;
  padding: 7px 14px;
  background: var(--navy);
  color: #fff;
  font-size: 13px;
  line-height: 1.4;
  text-align: center;
}

/* Последние пять минут — другим цветом. Тот же текст мелким шрифтом человек
   уже не читает: он к нему привык за пятьдесят пять минут. */
.sandbox-bar--soon { background: var(--danger); }

.sandbox-bar strong { font-weight: 700; }

.sandbox-bar a,
.sandbox-bar button {
  color: #fff;
  background: none;
  border: 1px solid rgba(255, 255, 255, .55);
  padding: 2px 10px;
  font: inherit;
  cursor: pointer;
  text-decoration: none;
}

.sandbox-bar a:hover,
.sandbox-bar button:hover { background: rgba(255, 255, 255, .15); }
