:root {
  --bg: #f6f8fb;
  --panel: #ffffff;
  --text: #16233f;
  --muted: #647085;
  --line: #e1e6ee;
  --accent: #2f5fcb;
  --accent-dark: #24499e;
  --accent-soft: #c3d3f3;
  --negative: #cf6a34;
  --positive: #2f8f5b;
  --row-hover: #eef2f8;
  /* Уложились в бюджет / вышли за него. Держим отдельно от основных
     цветов: эти два значат состояние, а не просто «ещё один оттенок». */
  --ok-bg: #e7f4ec;
  --ok-text: #1f6b45;
  --over: #c0392b;
  --over-bg: #fbeae8;
  --over-text: #9c2f23;
}

* { box-sizing: border-box; }

html, body { margin: 0; padding: 0; }

body {
  font-family: 'Montserrat', Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* Каркас страницы: список разделов слева, содержимое справа. */
.layout { display: flex; align-items: flex-start; }

.sidebar {
  width: 232px;
  flex: none;
  /* Список остаётся на месте, когда содержимое справа прокручивается. */
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  padding: 18px 12px;
  background: var(--panel);
  border-right: 1px solid var(--line);
}

.sidebar-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 8px 18px;
}

.sidebar-logo {
  width: 30px;
  height: 30px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  color: #fff;
  font-size: 16px;
  font-weight: 700;
}

.sidebar-title { font-size: 15px; font-weight: 700; letter-spacing: 0.02em; }

.tabs {
  display: flex;
  flex-direction: column;
  gap: 2px;
  /* Если разделов станет больше, чем помещается, список прокрутится
     сам, не утаскивая за собой всю страницу. */
  overflow-y: auto;
}

.tab-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: none;
  border: none;
  padding: 9px 10px;
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--muted);
  text-align: left;
}

.tab-btn:hover { background: var(--row-hover); color: var(--text); }

.tab-btn.active {
  background: var(--accent-soft);
  color: var(--accent-dark);
  font-weight: 600;
}

.tab-icon {
  width: 16px;
  height: 16px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.3;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* У значка Главной доли закрашены, а не обведены — так он читается
   лучше, чем четыре пустых квадратика. */
.tab-btn[data-tab="dashboard"] .tab-icon { fill: currentColor; stroke: none; }

.sidebar-foot {
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-start;
}
.sidebar-user { font-size: 12px; color: var(--muted); padding: 0 8px; }
.sidebar-foot button { width: 100%; }

#app { flex: 1; min-width: 0; padding: 24px 28px 60px; max-width: 1280px; }

@media (max-width: 860px) {
  /* Узкий экран: список разделов превращается в полосу сверху. */
  .layout { flex-direction: column; align-items: stretch; }
  .sidebar {
    width: auto;
    position: static;
    height: auto;
    flex-direction: row;
    align-items: center;
    gap: 12px;
    padding: 10px 16px;
    border-right: none;
    border-bottom: 1px solid var(--line);
  }
  .sidebar-head { padding: 0; }
  .sidebar-title { display: none; }
  .tabs { flex-direction: row; overflow-x: auto; }
  .tab-btn { width: auto; white-space: nowrap; }
  .sidebar-foot {
    margin-top: 0;
    margin-left: auto;
    padding-top: 0;
    border-top: none;
    flex-direction: row;
    align-items: center;
  }
  .sidebar-foot button { width: auto; }
}

.tab-panel { display: none; }
.tab-panel.active { display: block; animation: fade-up 0.35s ease; }

@keyframes fade-up {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: center;
  padding: 0 0 16px;
  margin-bottom: 20px;
  border-bottom: 1px solid var(--line);
}

.toolbar label { display: flex; gap: 8px; align-items: center; font-size: 12px; color: var(--muted); }

.period-controls { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); }

input, select {
  font-family: inherit;
  font-size: 13px;
  padding: 6px 8px;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--text);
}

input:focus, select:focus { outline: none; border-color: var(--accent); }

button {
  font-family: inherit;
  font-size: 13px;
  padding: 7px 16px;
  cursor: pointer;
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #fff;
}

button:hover { background: var(--accent-dark); border-color: var(--accent-dark); }

button.secondary { background: none; color: var(--accent); border: 1px solid var(--line); }
button.secondary:hover { border-color: var(--accent); background: none; color: var(--accent-dark); }

/* Кнопка-значок (корзина). Спокойная серая, пока на неё не навели, —
   чтобы ряды таблиц не пестрели; под мышкой краснеет, подсказывая, что
   будет удаление. */
.icon-btn {
  background: none;
  border: 1px solid transparent;
  color: var(--muted);
  padding: 4px 6px;
  line-height: 0;
  display: inline-flex;
  align-items: center;
}
.icon-btn:hover {
  background: var(--over-bg);
  border-color: var(--over-bg);
  color: var(--over);
}
.icon-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.icon-trash { width: 15px; height: 15px; display: block; }

/* В строке операции корзина прижата к правому краю. */
.op-delete { margin-left: auto; }

/* Кнопки «Загрузить выписку» и «Загрузить эксель». Сделаны подписью
   (label), а не кнопкой, — иначе файл не выбрать. Из-за этого их красило
   общее правило для подписей фильтров, и белый текст превращался в
   серый на синем. Поэтому цвет и размер задаём здесь построже — так,
   чтобы правило для подписей их уже не перебивало. */
.file-btn,
.toolbar label.file-btn {
  cursor: pointer;
  background: var(--accent);
  color: #fff;
  padding: 7px 16px;
  font-size: 13px;
  font-weight: 500;
  display: inline-flex;
  align-items: center;
}
.file-btn:hover,
.toolbar label.file-btn:hover { background: var(--accent-dark); color: #fff; }

.panel {
  border: 1px solid var(--line);
  padding: 20px 24px;
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

.data-table th, .data-table td {
  padding: 9px 10px;
  border-bottom: 1px solid var(--line);
  text-align: left;
}

.data-table thead th {
  font-weight: 500;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

.data-table td.num, .data-table th.num { text-align: right; font-variant-numeric: tabular-nums; }

.data-table tbody tr:hover { background: var(--row-hover); }

.data-table input, .data-table select, .data-table textarea { width: 100%; }

/* Поле для длинных названий: текст переносится и виден целиком, а поле
   подрастает под него.
   Высоту задаёт невидимая копия текста (::after) — она и поле лежат в
   одной клетке сетки, поэтому поле всегда ровно по тексту. Никаких
   замеров из кода: они не работают, пока поле спрятано на закрытой
   подвкладке, и сбиваются при смене ширины окна. */
.growing-input {
  display: grid;
  width: 100%;
}

.growing-input::after {
  content: attr(data-value) " ";
  visibility: hidden;
  white-space: pre-wrap;
}

.growing-input > textarea,
.growing-input::after {
  /* Обе части должны считаться совершенно одинаково, иначе высота
     разъедется — поэтому все размеры перечислены здесь вместе. */
  grid-area: 1 / 1 / 2 / 2;
  font-family: inherit;
  font-size: 13px;
  line-height: 1.4;
  padding: 6px 8px;
  border: 1px solid transparent;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.growing-input > textarea {
  border-color: var(--line);
  background: #fff;
  color: var(--text);
  resize: none;
  overflow: hidden;
}
.growing-input > textarea:focus { outline: none; border-color: var(--accent); }
.growing-input > textarea:disabled { background: var(--bg); color: var(--muted); }

/* Названиям «ООО …» нужно больше места, чем остальным колонкам. */
#ref-counterparties .data-table th:first-child,
#ref-counterparties .data-table td:first-child { width: 46%; }
#ref-companies .data-table th:first-child,
#ref-companies .data-table td:first-child { width: 70%; }

/* Плотный вариант таблицы: строки ниже, длинные названия обрезаются
   многоточием — так на экран помещается сразу много строк. Полное
   название всё равно видно при наведении. */
.data-table--compact { table-layout: fixed; }
.data-table--compact th, .data-table--compact td {
  padding: 5px 8px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.data-table--compact tbody td { font-size: 12.5px; }

/* Список прокручивается внутри рамки, а шапка таблицы остаётся на месте —
   фильтры и названия колонок не уезжают наверх. */
.table-scroll { max-height: calc(100vh - 300px); overflow: auto; }
.table-scroll thead th {
  position: sticky;
  top: 0;
  background: var(--panel);
  z-index: 1;
}

/* Сводка по руководителям: два блока рядом, под ними общий итог.
   На узком экране блоки встают друг под друга. */
.managers-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px 28px;
  align-items: start;
}

.managers-table { font-size: 12.5px; }
.managers-table thead th { padding-top: 0; }

.managers-total {
  grid-column: 1 / -1;
  display: flex;
  gap: 20px;
  justify-content: flex-end;
  padding-top: 10px;
  margin-top: 4px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.managers-total span:first-child { margin-right: auto; font-weight: 500; color: var(--muted); }

@media (max-width: 760px) {
  .managers-row { grid-template-columns: 1fr; }
}

/* Строка с итогами над списком. Пустой она тоже занимает место — чтобы
   список не подпрыгивал, когда итоги появляются и пропадают. */
.summary-line {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 24px;
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 12px;
  min-height: 20px;
}

/* Поиск делаем заметно шире обычного поля: в него вводят и названия
   целиком, а не только пару букв. */
.search-field input { width: 260px; }

/* Счётчик рядом с поиском: сколько нашлось и сколько всего. */
.toolbar-count { font-size: 12px; color: var(--muted); white-space: nowrap; }

/* Полоска «работает старая версия». Нарочно заметная и во всю ширину:
   пока она висит, всему остальному на экране верить нельзя. */
.stale-banner {
  background: var(--over-bg);
  color: var(--over-text);
  border-bottom: 1px solid var(--over);
  padding: 12px 28px;
  font-size: 13px;
  line-height: 1.6;
}

.muted { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 10px; }

/* Когда по счёту в последний раз появлялись данные. */
.muted-cell { color: var(--muted); }
.update-main { white-space: nowrap; }

/* --- Бюджет: строка «кому и за что», компании колонками --- */

/* Плотные строки — но без обрезки содержимого: в ячейках выпадающие
   списки, и обрезка срезала бы их вместе с вариантами выбора. */
.budget-table th,
.budget-table td {
  padding: 5px 8px;
  overflow: visible;
}
.budget-table tbody td { font-size: 12.5px; }

/* Названия компаний в шапке переносятся по словам: иначе длинное название
   растягивало бы всю колонку. */
.budget-table thead th { white-space: normal; }

/* Поля правятся прямо в таблице, поэтому выглядят как обычный текст и
   обводятся только под мышкой — иначе рябило бы от рамок. */
.budget-table input,
.budget-table .search-select input {
  border-color: transparent;
  background: transparent;
  padding: 3px 5px;
}
.budget-table input:hover,
.budget-table input:focus,
.budget-table .search-select input:hover,
.budget-table .search-select input:focus {
  border-color: var(--line);
  background: #fff;
}

.budget-table .search-select { width: 100%; }
.budget-table td { vertical-align: middle; }

/* Суммы по компаниям — узкими колонками, цифры в столбик. */
.budget-amount {
  width: 100%;
  min-width: 86px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
/* Стрелочки у числового поля съедают место и в таблице не нужны. */
.budget-amount::-webkit-outer-spin-button,
.budget-amount::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.budget-amount { -moz-appearance: textfield; }

/* Итоги под таблицей. Прилипают к низу, чтобы при длинном бюджете их было
   видно, не прокручивая до конца. */
.budget-total td {
  position: sticky;
  bottom: 0;
  background: var(--row-hover);
  border-top: 1px solid var(--line);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.budget-total--income td { color: var(--positive); }

/* --- Остатки: счета сгруппированы по компаниям --- */

/* Строка-заголовок компании: стрелка, название, число счетов и итог
   справа. По всей строке можно щёлкнуть, чтобы свернуть или развернуть. */
.group-row { cursor: pointer; background: var(--row-hover); }
.group-row:hover { background: var(--accent-soft); }
.group-row td { border-bottom: 1px solid var(--line); }

/* Ручка для перетаскивания. Бледная, пока на строку не навели, —
   чтобы список не рябил точками. */
.group-grip {
  display: inline-block;
  width: 14px;
  margin-right: 2px;
  color: transparent;
  cursor: grab;
  font-size: 12px;
  user-select: none;
}
.group-row:hover .group-grip { color: var(--muted); }
.group-row--dragging { opacity: 0.45; }

/* Черта показывает, куда встанет компания, если отпустить здесь. */
.drop-above td { box-shadow: inset 0 2px 0 var(--accent); }
.drop-below td { box-shadow: inset 0 -2px 0 var(--accent); }

.group-chevron {
  display: inline-block;
  width: 14px;
  color: var(--muted);
  font-size: 11px;
}
.group-name { font-weight: 600; }
.group-chip {
  margin-left: 8px;
  padding: 1px 7px;
  font-size: 11px;
  color: var(--muted);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 9px;
}
.group-total { font-weight: 600; white-space: nowrap; }

/* Счёт внутри компании — с отступом, чтобы вложенность читалась. */
.account-row .account-name { padding-left: 32px; }
.account-own { font-size: 11px; color: var(--muted); white-space: nowrap; }

.balances-table tbody tr.group-row + .account-row td { border-top: none; }

.total-line { font-size: 26px; font-weight: 600; letter-spacing: -0.01em; margin-bottom: 20px; }

.negative { color: var(--negative); }
.income { color: var(--positive); }

.subtabs {
  display: flex;
  gap: 4px;
  margin-bottom: 20px;
  border-bottom: 1px solid var(--line);
}

.subtab-btn {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 8px 14px;
  cursor: pointer;
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
}

.subtab-btn.active { color: var(--text); border-bottom-color: var(--accent); }

.subtab-panel { display: none; }
.subtab-panel.active { display: block; animation: fade-up 0.3s ease; }

.modal-backdrop {
  position: fixed; inset: 0; background: rgba(22, 35, 63, 0.45);
  display: flex; align-items: center; justify-content: center;
}

.modal-backdrop[hidden] { display: none; }

.modal {
  background: #fff; border: 1px solid var(--line);
  padding: 24px; min-width: 340px; max-width: 90vw; max-height: 85vh; overflow: auto;
}

.modal h2 { margin-top: 0; font-size: 15px; font-weight: 600; }

.modal-field { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.modal-field label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.03em; }
.modal-field input, .modal-field select { padding: 7px 9px; }
.modal-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 16px; }

.mapping-table { width: 100%; border-collapse: collapse; margin-top: 12px; font-size: 12px; }
.mapping-table td, .mapping-table th { border-bottom: 1px solid var(--line); padding: 6px 8px; }
.mapping-table th { color: var(--muted); font-weight: 500; text-transform: uppercase; font-size: 10px; }

/* Выпадающий фильтр с чекбоксами */
.filter-dropdown { position: relative; display: inline-block; }

.filter-btn {
  padding: 6px 12px;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--text);
}
.filter-btn:hover { background: var(--row-hover); border-color: var(--line); }

.filter-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  background: #fff;
  border: 1px solid var(--line);
  width: 240px;
  padding: 10px 0;
  z-index: 30;
  display: none;
}

.filter-panel.open { display: block; }

.filter-actions {
  display: flex;
  justify-content: space-between;
  padding: 0 14px 8px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--line);
}

.filter-actions button {
  background: none;
  border: none;
  padding: 0;
  font-size: 12px;
  color: var(--accent);
}
.filter-actions button:hover { background: none; color: var(--accent-dark); }

.filter-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  cursor: pointer;
  font-size: 13px;
}

.filter-option:hover { background: var(--row-hover); }

/* Выпадающий список с беглым поиском по названию */
.search-select { position: relative; width: 100%; }
.search-select input { width: 100%; }

.search-select-panel {
  position: absolute;
  top: calc(100% + 2px);
  left: 0;
  right: 0;
  background: #fff;
  border: 1px solid var(--line);
  max-height: 220px;
  overflow-y: auto;
  z-index: 40;
  display: none;
}

.search-select-panel.open { display: block; }

.search-select-option {
  padding: 6px 10px;
  cursor: pointer;
  font-size: 13px;
  white-space: nowrap;
}

.search-select-option:hover { background: var(--row-hover); }

.search-select-empty { padding: 6px 10px; font-size: 12px; color: var(--muted); }

/* Список транзакций: компактная строка на операцию (две строки), вместо
   широкой таблицы на десять колонок. */
.list-panel {
  border: 1px solid var(--line);
  background: var(--panel);
}

.op-row {
  padding: 10px 16px;
  border-top: 1px solid var(--line);
}
.op-row:first-child { border-top: none; }
.op-row:hover { background: var(--row-hover); }

.op-primary {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.op-date { font-size: 12px; color: var(--muted); white-space: nowrap; width: 78px; flex: none; }
.op-counterparty { flex: 1 1 220px; min-width: 0; }
.op-counterparty input { font-weight: 600; border-color: transparent; padding-left: 0; background: transparent; }
.op-counterparty input:hover, .op-counterparty input:focus { border-color: var(--line); padding-left: 7px; background: #fff; }
.op-desc { font-size: 12px; color: var(--muted); flex: 2 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.op-amount { font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap; flex: none; }

.op-secondary {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 6px;
  padding-left: 88px;
  flex-wrap: wrap;
}
.op-place { font-size: 12px; color: var(--muted); }

.field-chip { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; }
.field-chip > span { color: var(--muted); white-space: nowrap; }
.field-chip .search-select { width: 170px; }
.field-chip input { font-size: 12.5px; padding: 4px 6px; }

@media (max-width: 480px) {
  .op-secondary { padding-left: 0; flex-direction: column; align-items: flex-start; gap: 6px; }
  .op-desc { display: none; }
  .field-chip .search-select { width: 140px; }
}

/* Постраничный вывод */
.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 16px;
  flex-wrap: wrap;
}

.pager-size { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); }

.pager-pages { display: flex; align-items: center; gap: 4px; }
.pager-pages button {
  font-family: inherit;
  font-size: 12.5px;
  padding: 6px 11px;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--text);
  cursor: pointer;
}
.pager-pages button:hover { background: var(--row-hover); }
.pager-pages button.current {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  cursor: default;
}
.pager-pages button:disabled { color: var(--muted); cursor: default; }
.pager-pages button:disabled:hover { background: #fff; }
.pager-pages .pager-ellipsis { color: var(--muted); padding: 6px 4px; }

/* KPI-карточки */
.kpi-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border: 1px solid var(--line);
  border-left: none;
  margin: 20px 0;
}

.kpi-col { padding: 16px 20px; border-left: 1px solid var(--line); }

.kpi-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  margin-bottom: 6px;
}

.kpi-value { font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
.kpi-value.negative { color: var(--negative); }

.chart-svg { width: 100%; height: 240px; display: block; }

.panel-title {
  margin: 0 0 14px;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* --- Кольцевые диаграммы структуры доходов и расходов --- */
.donut-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  margin-top: 20px;
}

.donut-panel { padding: 20px 24px; }

.donut-body { display: flex; align-items: center; gap: 20px; }

.donut-svg { width: 180px; height: 180px; flex: none; }

.donut-center-value {
  font-size: 22px;
  font-weight: 600;
  fill: var(--text);
  font-family: inherit;
}
.donut-center-caption {
  font-size: 11px;
  fill: var(--muted);
  font-family: inherit;
}

.donut-legend { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 9px; }

.donut-legend-row {
  display: grid;
  grid-template-columns: 10px 1fr auto auto;
  align-items: center;
  gap: 10px;
  font-size: 13px;
}

/* Кружок цвета доли. Он только помогает найти долю на кольце — название
   и процент рядом написаны словами, поэтому по одному цвету угадывать
   ничего не нужно. */
.donut-dot { width: 10px; height: 10px; border-radius: 50%; }

.donut-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.donut-sum { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.donut-pct { font-weight: 600; font-variant-numeric: tabular-nums; min-width: 34px; text-align: right; }

/* --- Расходы против бюджета --- */
.dev-row {
  display: grid;
  /* minmax(0, 1fr) — чтобы средняя колонка со столбиками умела сжиматься,
     а не распирала строку и не выталкивала метку на соседей. */
  grid-template-columns: 170px minmax(0, 1fr) 250px;
  align-items: center;
  gap: 16px;
  padding: 10px 0;
  border-top: 1px solid var(--line);
  font-size: 13px;
}
.dev-row:first-child { border-top: none; }

.dev-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }

.dev-bars { display: flex; flex-direction: column; gap: 4px; min-width: 0; }

.dev-bar-line { display: grid; grid-template-columns: 34px minmax(0, 1fr) 88px; align-items: center; gap: 8px; }
.dev-bar-label { font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.dev-bar-value { font-size: 12px; text-align: right; color: var(--muted); font-variant-numeric: tabular-nums; }

.dev-track { height: 7px; background: var(--row-hover); }
.dev-fill { height: 100%; }
.dev-fill--ok { background: var(--positive); }
.dev-fill--over { background: var(--over); }
.dev-fill--none { background: var(--muted); }
.dev-fill--plan { background: var(--accent-soft); }

/* Итог по строке. Цвет тут не единственный признак: рядом стоит значок
   и написано словами, уложились или нет и на сколько. */
.dev-badge {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  justify-self: end;
  /* Метка не должна вылезать за свою колонку: иначе она наползала бы
     на суммы слева. Если текст не помещается — переносится на вторую
     строку, а не залезает на соседей. */
  max-width: 100%;
  padding: 5px 10px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.4;
  text-align: right;
}
.dev-badge-mark { font-size: 10px; flex: none; }
.dev-badge--ok { background: var(--ok-bg); color: var(--ok-text); }
.dev-badge--over { background: var(--over-bg); color: var(--over-text); }
.dev-badge--none { background: var(--row-hover); color: var(--muted); }

@media (max-width: 900px) {
  .donut-row { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  .kpi-row { grid-template-columns: 1fr; }
  .kpi-col { border-left: none; border-top: 1px solid var(--line); }
  .kpi-col:first-child { border-top: none; }
  .donut-body { flex-direction: column; align-items: stretch; }
  .donut-svg { align-self: center; }
  .dev-row { grid-template-columns: 1fr; gap: 8px; }
  .dev-badge { justify-self: start; }
}

@media (max-width: 480px) {
  .sidebar { padding: 10px 12px; }
  #app { padding: 16px; }
  .toolbar { flex-direction: column; align-items: stretch; }
  .panel { padding: 14px; }
  .data-table { display: block; overflow-x: auto; }
}

/* Элементы, скрытые по умолчанию (снимает JS для admin/viewer) */
.admin-only[hidden] { display: none; }

body.role-viewer .edit-only { display: none !important; }

/* Страница входа */
.login-body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}

.login-box {
  width: 280px;
  padding: 28px 24px;
  border: 1px solid var(--line);
  background: var(--panel);
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.login-box h1 {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin: 0 0 16px;
  text-align: center;
}

.login-box button { margin-top: 8px; }

.login-error {
  color: var(--negative);
  font-size: 12px;
  margin: 4px 0;
}

/* Вкладка «Почта» */
.mail-status {
  margin-left: auto;
  font-size: 13px;
  padding: 2px 8px;
  border-radius: 10px;
  background: #eef1f5;
  color: #445;
}
.mail-status--imported { background: #e6f5ea; color: #256b3a; }
.mail-status--needs_account,
.mail-status--empty { background: #fdf0d5; color: #8a5a00; }
.mail-status--duplicate,
.mail-status--importing,
.mail-status--unsupported { background: #eef1f5; color: #667; }
.mail-status--error { background: #fbe6e6; color: #8a2222; }

.mail-assign {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  margin-top: 8px;
}
.mail-remember { display: flex; align-items: center; gap: 4px; font-size: 13px; }

/* Значок с числом непросмотренных писем — у правого края своей строки
   в списке разделов. */
.badge {
  display: inline-block;
  margin-left: auto;
  min-width: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: #d94b4b;
  color: #fff;
  font-size: 12px;
  line-height: 18px;
  text-align: center;
}

.op-row--new { background: #fbf7e8; }

/* Операция без статьи. Бледно-красным, потому что она не попадёт ни в
   диаграмму расходов, ни в сравнение с бюджетом, пока статью не выберут.
   Правило стоит после «нового», чтобы у непросмотренной операции без
   статьи была видна именно эта пометка — она важнее. */
.op-row--no-article { background: var(--over-bg); }
.op-row--no-article:hover { background: #f6dcd8; }

.tx-new-mark {
  margin-left: 8px;
  font-size: 12px;
  padding: 1px 6px;
  border-radius: 8px;
  background: #d94b4b;
  color: #fff;
}

/* --- Разбивка операции по статьям, проектам и практикам --- */

/* Красная точка в начале строки: операция ещё не разобрана. */
.unsplit-dot {
  border: none;
  padding: 0;
  cursor: pointer;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--over);
  flex: none;
  align-self: center;
}


/* Окно разбивки: по строке на каждое разнесение. */
.split-header {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-bottom: 12px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
}
.split-header .muted { margin-bottom: 0; }

/* Окно подбирает ширину по содержимому, и пяти столбцам в строке
   разбивки места не хватало. Задаём ширину явно, но не шире экрана. */
.split-lines { display: flex; flex-direction: column; gap: 10px; min-width: min(900px, 78vw); }

/* Строка разбивки: каждой клетке своё место, без «пусть встанет само».
   Пока клеток было четыре, самостоятельная расстановка работала, но с
   появлением счёта на оплату и документов клетки начали налезать друг
   на друга — поэтому места теперь названы и расписаны. */
.split-line {
  display: grid;
  grid-template-columns: 110px 1fr 1fr 1fr 150px;
  grid-template-areas:
    "amount  article project practice trash"
    "comment comment comment vat      vat"
    "invoice invoice invoice files    files";
  gap: 8px 10px;
  align-items: end;
  padding: 10px;
  background: var(--bg);
}

.split-cell--amount { grid-area: amount; }
.split-cell--article { grid-area: article; }
.split-cell--project { grid-area: project; }
.split-cell--practice { grid-area: practice; }
.split-line .icon-btn { grid-area: trash; justify-self: end; align-self: end; }

.split-cell { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.split-cell label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.split-cell--wide { grid-area: comment; }
.split-cell input, .split-cell .search-select { width: 100%; }

.split-amount { text-align: right; font-variant-numeric: tabular-nums; }

.split-vat-row { display: flex; align-items: center; gap: 8px; }
.split-vat-check { display: flex; align-items: center; gap: 4px; font-size: 12px; color: var(--text); text-transform: none; letter-spacing: 0; }
.split-vat { width: 70px; }

/* Сколько разнесено и сколько осталось — чтобы не считать в уме. */
.split-total {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  font-weight: 600;
}
.split-left--ok { color: var(--positive); }
.split-left--off { color: var(--over-text); }

/* Практика, доставшаяся от руководителя, а не выбранная руками. */
.inherited-value input { color: var(--muted); font-style: italic; }

/* --- Файлы, приложенные к операции --- */
.files-box {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.files-title { font-size: 13px; font-weight: 600; margin-bottom: 8px; }
.files-list { display: flex; flex-direction: column; gap: 4px; margin-bottom: 8px; }

.file-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 6px;
  font-size: 13px;
  background: var(--bg);
}
.file-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--accent); }
.file-name:hover { color: var(--accent-dark); }
.file-size { font-size: 12px; color: var(--muted); white-space: nowrap; }
.files-box .file-btn { margin-top: 4px; }

/* Клетка НДС в разбивке: галочка, ставка и сумма вручную — в одну строку,
   под ними подсказка, сколько попадёт в экономику проектов. */
.split-cell--vat { grid-area: vat; }
.split-vat-row { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; }
.split-vat-check {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--text);
  text-transform: none;
  letter-spacing: 0;
  white-space: nowrap;
}
.split-vat { width: 76px; flex: none; }
.split-vat-amount { width: 104px; flex: none; text-align: right; font-variant-numeric: tabular-nums; }

/* Когда сумма НДС вписана руками, галочка и ставка уже ни на что не
   влияют — показываем это бледностью. */
.split-vat-muted { opacity: 0.45; }

.split-net { font-size: 11px; color: var(--muted); margin-top: 3px; white-space: nowrap; }

/* Красная точка — кнопка: одним щелчком открывает разбивку. */
.unsplit-dot {
  border: none;
  padding: 0;
  cursor: pointer;
}
.unsplit-dot:hover { background: var(--over-text); }

/* Видимая кнопка разбивки в строке операции. */
.op-split-btn {
  background: none;
  border: 1px solid var(--line);
  color: var(--accent);
  font-size: 12px;
  padding: 3px 10px;
  cursor: pointer;
  white-space: nowrap;
}
.op-split-btn:hover { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-dark); }

/* --- Экономика проектов: дерево проект → практика → строки --- */

.pnl-row {
  display: grid;
  grid-template-columns: 18px 1fr auto 130px 130px 140px;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  cursor: pointer;
  font-size: 13px;
  border-top: 1px solid var(--line);
}
.pnl-row:hover { background: var(--row-hover); }

.pnl-row--project { background: var(--row-hover); font-weight: 600; }
.pnl-row--project:hover { background: var(--accent-soft); }
.pnl-row--practice { padding-left: 28px; background: none; }

.pnl-chevron { color: var(--muted); font-size: 11px; }
.pnl-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pnl-sub { font-size: 12px; color: var(--muted); font-weight: 400; white-space: nowrap; }

/* Практика, которую позвали на помощь, — не та, что у самого проекта. */
.pnl-helper {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 1px 6px;
  border-radius: 8px;
  background: var(--accent-soft);
  color: var(--accent-dark);
  font-weight: 500;
}

.pnl-income, .pnl-expense, .pnl-profit {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.pnl-income { color: var(--positive); }
.pnl-expense { color: var(--negative); }
.pnl-profit { font-weight: 600; }

/* Сами доходы и расходы — таблицей внутри практики. */
.pnl-rows { margin: 4px 0 12px 46px; width: calc(100% - 46px); font-size: 12.5px; }
.pnl-rows th, .pnl-rows td { padding: 5px 8px; }
.pnl-comment { max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); }
.pnl-actions { width: 1%; white-space: nowrap; }

/* Строка, заведённая руками, а не пришедшая из выписки. */
.pnl-manual td:first-child { box-shadow: inset 3px 0 0 var(--accent); }

/* Предложение завести запись, которой в справочнике ещё нет. Отделено
   чертой и подписано действием — чтобы его не приняли за готовый вариант
   из списка. */
.search-select-create {
  padding: 7px 10px;
  cursor: pointer;
  font-size: 13px;
  color: var(--accent);
  border-top: 1px solid var(--line);
  background: var(--bg);
}
.search-select-create:hover { background: var(--accent-soft); color: var(--accent-dark); }
.search-select-create:first-child { border-top: none; }

/* --- Предпросмотр загрузки выписки --- */

/* Показывает не колонки файла, а то, что из них получится. Неверно
   угаданный формат чисел или дат виден здесь сразу. */
.import-preview {
  border: 1px solid var(--line);
  padding: 10px 12px;
  margin-bottom: 12px;
  background: var(--bg);
}

.import-preview-head {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 6px;
}

.import-preview-total {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  margin-bottom: 4px;
}

.import-preview .mapping-table { margin-top: 8px; background: #fff; }

/* Переключатель сторон на Главной: российские компании и иностранные
   считаются отдельно и между собой не смешиваются. */
.region-switch {
  display: flex;
  gap: 4px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--line);
}
.region-btn {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 8px 18px;
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--muted);
}
.region-btn:hover { background: var(--row-hover); color: var(--text); }
.region-btn.active {
  color: var(--text);
  border-bottom-color: var(--accent);
  background: none;
}

/* Замечание в строке операции: разнесена не вся сумма. Само замечание
   открывает разбивку — это и способ исправить, и повод туда зайти. */
.op-remainder {
  margin-left: auto;
  background: var(--over-bg);
  border: 1px solid transparent;
  color: var(--over-text);
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  padding: 3px 10px;
  cursor: pointer;
  white-space: nowrap;
}
.op-remainder:hover { border-color: var(--over); }

/* Когда замечание есть, корзина уже не прижимается к краю сама. */
.op-remainder + .op-delete { margin-left: 8px; }

/* Счётчики над списком операций: не разобрано, без статьи, разобрано
   частично. Каждый — кнопка: щелчок оставляет в списке только такие
   операции, повторный возвращает весь список.
   Выглядят текстом, а не обычными кнопками, чтобы не спорить с
   «Показать» в полосе фильтров. */
.tx-mark {
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--muted);
  background: none;
  border: 1px solid transparent;
  padding: 2px 8px;
  cursor: pointer;
  white-space: nowrap;
}
.tx-mark:hover { background: var(--row-hover); border-color: var(--line); }
.tx-mark:disabled { cursor: default; }
.tx-mark:disabled:hover { background: none; border-color: transparent; }

/* Есть что доработать — видно цветом. */
.tx-mark--some { color: var(--over-text); font-weight: 600; }
.tx-mark--some:hover { background: var(--over-bg); border-color: var(--over-bg); }

/* Отбор включён — видно, что список сейчас урезан. */
.tx-mark--active {
  color: #fff;
  font-weight: 600;
  background: var(--over);
  border-color: var(--over);
}
.tx-mark--active:hover { background: var(--over-text); border-color: var(--over-text); }

/* Выбор разделов, открытых сотруднику. Устроен как выпадающий список с
   галочками: разделов восемь, и в строку они бы не поместились. */
.tab-picker { position: relative; display: inline-block; }

.tab-picker-btn {
  font-family: inherit;
  font-size: 13px;
  padding: 6px 12px;
  background: none;
  border: 1px solid var(--line);
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
}
.tab-picker-btn:hover { border-color: var(--accent); color: var(--accent-dark); background: none; }

.tab-picker-panel {
  position: absolute;
  top: calc(100% + 2px);
  left: 0;
  min-width: 200px;
  background: #fff;
  border: 1px solid var(--line);
  padding: 6px;
  z-index: 40;
  display: none;
}
.tab-picker-panel.open { display: block; }

/* --- Сводная ведомость расчётов --- */

/* Переключатель разрезов. Выглядит как подвкладки справочников, но это
   отдельный класс: общий обработчик подвкладок сюда лезть не должен. */
.settle-view-btn {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 8px 14px;
  cursor: pointer;
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
}
.settle-view-btn.active { color: var(--text); border-bottom-color: var(--accent); }

/* Вторая строка отборов — та, что меняется от разреза к разрезу. */
.toolbar--thin { margin-top: -8px; }

.check-inline {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--muted);
  cursor: pointer;
}

.kpi-row--four { grid-template-columns: repeat(4, 1fr); }
.kpi-hint { font-size: 11px; color: var(--muted); margin-top: 4px; }
.kpi-value.positive { color: var(--positive); }

.settle-table { font-size: 13px; }
.settle-table td, .settle-table th { padding: 8px 10px; }
.settle-name { font-weight: 600; }

/* Строка-ссылка: по щелчку открывается карточка расчётов. */
.settle-row { cursor: pointer; }
.settle-row:hover .settle-name { color: var(--accent); }

.settle-days { display: block; font-size: 11px; color: var(--muted); font-weight: 400; }

.settle-total td { font-weight: 600; border-top: 2px solid var(--line); }
.settle-hint { margin-top: 12px; font-size: 12px; }

.settle-actions { white-space: nowrap; text-align: right; }
.settle-actions .icon-btn { vertical-align: middle; }

.link-btn {
  background: none;
  border: none;
  padding: 2px 6px;
  color: var(--accent);
  cursor: pointer;
  font-family: inherit;
  font-size: 12px;
}
.link-btn:hover { color: var(--accent-dark); text-decoration: underline; }

/* Чем дольше долг ждёт оплаты, тем заметнее клетка. */
.aging-d30 { background: #fdf6e8; }
.aging-d60 { background: #fbecd9; }
.aging-d90 { background: var(--over-bg); }
.aging-over90 { background: var(--over-bg); color: var(--over-text); font-weight: 600; }

/* Карточка расчётов с контрагентом — акт сверки. */
.settle-card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 20px;
  margin-bottom: 14px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
}
.settle-card-name { font-size: 15px; font-weight: 600; }
.settle-card-closing { margin-left: auto; font-weight: 600; }

.settle-doc-invoice td { background: var(--panel); }
.settle-doc-payment td { background: var(--bg); }

/* --- Счёт на оплату в карточке операции и в строках разбивки --- */

/* Номер и дата счёта у самой операции: отдельной полоской над
   разбивкой, чтобы было видно, что это про весь платёж целиком. */
.tx-invoice {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 10px 16px;
  margin: 14px 0;
  padding: 10px 12px;
  background: var(--bg);
}
.tx-invoice-title { font-size: 13px; font-weight: 600; width: 100%; }
.tx-invoice-field { display: flex; flex-direction: column; gap: 3px; }
.tx-invoice-field label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.tx-invoice-number { width: 180px; }
.tx-invoice-hint { font-size: 11px; color: var(--muted); flex: 1; min-width: 160px; }

/* Номер счёта в строке разбивки — и файлы к этому самому счёту. */
.split-cell--invoice { grid-area: invoice; }
.split-invoice-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.split-invoice-row > * { min-width: 0; }
.split-invoice-number { flex: 1; min-width: 0; }
.split-invoice-date { width: 130px; flex: none; }

.split-cell--files { grid-area: files; }
.split-files { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.split-file {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: 100%;
  padding: 2px 6px;
  background: var(--panel);
  border: 1px solid var(--line);
  font-size: 11px;
}
.split-file a { color: var(--accent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 140px; }
.split-file .icon-btn { padding: 0; }
.split-file-add { font-size: 11px; padding: 2px 8px; }

@media (max-width: 900px) {
  .kpi-row--four { grid-template-columns: 1fr 1fr; }
}

/* Номер счёта на оплату в строке операции. */
.op-invoice {
  font-size: 11px;
  color: var(--muted);
  padding: 2px 8px;
  background: var(--bg);
  border: 1px solid var(--line);
  white-space: nowrap;
}

/* Строка о спрятанных контрагентах — тех, по которым счетов ещё нет. */
.settle-folded {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
  margin-bottom: 12px;
  padding: 8px 10px;
  background: var(--bg);
  font-size: 12px;
  color: var(--muted);
}

/* Кнопка «Завести счёт» в полоске счёта у операции. */
.tx-invoice .split-file-add { margin-left: auto; }
