/* Кассовый контур — оформление.

   Палитра заказчика: серый (база, ~60%), оранжевый (действия, ~30%),
   зелёный (успех и подтверждение, ~10%). Композиция по правилу 60-30-10:
   серые поверхности не спорят с акцентом, зелёный показывает только
   «всё сошлось».

   Движение: короткие микроанимации (hover 150–200 мс, нажатие <100 мс),
   анимируются только transform и opacity, уважается prefers-reduced-motion.

   ── Обновление 29.09.2026 (у клиента новый ноутбук) ──────────────────────
   Раньше файл был рассчитан на Windows 7 и слабый Celeron: узкая колонка
   1020 px, минимум эффектов, потолок браузера Chrome 109. Теперь у клиента
   Windows Pro и i7-1355U / 16 ГБ, потолок снят, поэтому:
     • колонка контента шире (1180–1320 px) — таблицы на 7–9 колонок
       перестали тесниться, широкие таблицы прокручиваются в .table-scroll;
     • плавная типографика (clamp) и лишние брейкпоинты;
     • тёмная тема (переключатель в шапке, выбор помнится в localStorage);
     • переходы между страницами (View Transitions), современные тени,
       градиенты и «появление» элементов (@starting-style).
   Всё новое по-прежнему подчиняется prefers-reduced-motion, а вся
   бухгалтерская логика (документы, суммы, номера) не затронута.
   Цвета для тёмной темы вынесены в переменные — по коду не должно остаться
   «случайных» #fff и rgba(...) мимо переменных. */

:root {
  /* --- серая база */
  --bg: #f6f6f4;
  --surface: #ffffff;
  --surface-2: #fbfbfa;
  --surface-3: #f0f0ec;
  --border: #e4e4e0;
  --border-strong: #cfcfc9;
  --border-hover: #b3b3ac;
  --placeholder: #a3a39c;
  --text: #1c1c1a;
  --muted: #6b6b66;
  --topbar-bg: rgba(255, 255, 255, 0.88);
  --glow: rgba(226, 96, 15, 0.07);
  /* блик, пробегающий по главной кнопке при наведении (см. блок «кнопки») */
  --sheen: rgba(255, 255, 255, 0.5);
  /* волна от нажатия: цвет берётся из currentColor кнопки */
  --ripple: 0.3;

  /* --- оранжевый: действия, активная вкладка */
  --accent: #e2600f;
  --accent-hover: #c24f08;
  --accent-active: #a34307;
  --accent-soft: #fef3ea;
  --accent-border: #f3d4bc;
  --accent-ring: rgba(226, 96, 15, 0.3);
  --accent-bright: #f59e0b;

  /* --- зелёный: успех, подтверждение */
  --ok: #2e7d4f;
  --ok-soft: #edf7f1;
  --ok-border: #bcdcc9;
  /* заливка строки, отмеченной галочкой «проверено» (нежно-салатовый) */
  --checked-bg: #e9f8e0;
  --checked-border: #b9e2a4;

  /* --- состояния */
  --bad: #c0392b;
  --bad-soft: #fdeeec;
  --bad-soft-2: #fadfdb;
  --bad-border: #e8b7b0;
  --bad-text: #8e2b20;
  --warn: #b7791f;
  --warn-soft: #fdf6e7;
  --warn-border: #ecd9a7;

  /* --- служебное: тени, скелетон, спиннер */
  --shadow-rgb: 28 28 26;
  --shadow-sm: 0 1px 2px rgb(var(--shadow-rgb) / 0.06);
  --shadow-md:
    0 6px 16px -4px rgb(var(--shadow-rgb) / 0.1),
    0 2px 6px -2px rgb(var(--shadow-rgb) / 0.06);
  --shadow-lg: 0 14px 30px -8px rgb(var(--shadow-rgb) / 0.16);
  --skeleton-1: #efefec;
  --skeleton-2: #f8f8f6;
  --spinner-track: rgba(255, 255, 255, 0.45);
  --spinner-track-quiet: rgba(28, 28, 26, 0.25);

  --r-field: 10px;
  --r-card: 18px;
  --r-pill: 9999px;

  --ease: cubic-bezier(0.25, 0.8, 0.5, 1);

  color-scheme: light;
}

/* ---------------------------------------------------------------- тёмная тема

   Переключатель в шапке (static/theme.js) ставит на <html> атрибут
   data-theme="dark" и помнит выбор в localStorage. Пока выбора нет — тему
   задаёт система (значение "auto"), это решает маленький скрипт в base.html
   ДО первой отрисовки, поэтому вспышки светлого фона не бывает.

   Меняются только переменные: разметка и логика темы не касаются. */
:root[data-theme="dark"] {
  color-scheme: dark;

  --bg: #151513;
  --surface: #1e1e1b;
  --surface-2: #232320;
  --surface-3: #2b2b26;
  --border: #34342e;
  --border-strong: #46463f;
  --border-hover: #57574e;
  --placeholder: #7b7b71;
  --text: #f2f2ee;
  --muted: #a8a89f;
  --topbar-bg: rgba(21, 21, 19, 0.86);
  --glow: rgba(240, 122, 44, 0.1);
  --sheen: rgba(255, 255, 255, 0.26);
  --ripple: 0.26;

  --accent: #f07a2c;
  --accent-hover: #f78d43;
  --accent-active: #d9681f;
  --accent-soft: #2b1f14;
  --accent-border: #54301c;
  --accent-ring: rgba(240, 122, 44, 0.35);
  --accent-bright: #f7a54a;

  --ok: #6cc08d;
  --ok-soft: #16261c;
  --ok-border: #2e5238;
  --checked-bg: #1b2a16;
  --checked-border: #33512a;

  --bad: #ef6b5c;
  --bad-soft: #2a1614;
  --bad-soft-2: #3a1d19;
  --bad-border: #5a2b25;
  --bad-text: #f4a79c;
  --warn: #e0b256;
  --warn-soft: #2a2415;
  --warn-border: #4d4225;

  --shadow-rgb: 0 0 0;
  --shadow-sm: 0 1px 2px rgb(var(--shadow-rgb) / 0.4);
  --shadow-md:
    0 6px 18px -4px rgb(var(--shadow-rgb) / 0.55),
    0 2px 6px -2px rgb(var(--shadow-rgb) / 0.4);
  --shadow-lg: 0 16px 34px -8px rgb(var(--shadow-rgb) / 0.7);
  --skeleton-1: #262623;
  --skeleton-2: #313130;
  --spinner-track: rgba(255, 255, 255, 0.35);
  --spinner-track-quiet: rgba(242, 242, 238, 0.3);
}

/* Смена темы: плавно переводим всю страницу (View Transitions API).
   В браузере без поддержки тема просто переключается без анимации —
   это нормально; CSS-хаков с !important не нужно. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.26s;
  animation-timing-function: var(--ease);
}

/* Кнопка переключения темы в шапке: тихая, не спорит с основными действиями. */
.theme-toggle {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  min-width: 40px;
  height: 40px;
  min-height: 40px;
  padding: 0;
  border-radius: var(--r-pill);
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-sm);
  transition:
    color 0.15s var(--ease),
    border-color 0.15s var(--ease),
    background-color 0.15s var(--ease),
    transform 0.12s var(--ease);
}

.theme-toggle:hover {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: var(--accent);
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm);
}

.theme-toggle:active {
  transform: translateY(0);
}

.theme-toggle svg {
  width: 18px;
  height: 18px;
}

/* Иконка показывает, КУДА переключим: в светлой теме — луна (станет тёмной),
   в тёмной — солнце. */
.theme-toggle .icon-sun {
  display: none;
}

:root[data-theme="dark"] .theme-toggle .icon-sun {
  display: inline;
}

:root[data-theme="dark"] .theme-toggle .icon-moon {
  display: none;
}

/* Переходы между страницами кабинета (Chrome 126+). В остальных браузерах
   правило просто игнорируется — страницы открываются как обычно. */
@view-transition {
  navigation: auto;
}

.topbar {
  view-transition-name: kassa-topbar;
}

::view-transition-old(kassa-topbar),
::view-transition-new(kassa-topbar) {
  animation-duration: 0.22s;
}

main.wrap {
  view-transition-name: kassa-main;
}

::view-transition-old(kassa-main) {
  animation: 0.16s var(--ease) both fade-out;
}

::view-transition-new(kassa-main) {
  animation: 0.22s var(--ease) both fade-in;
}

@keyframes fade-out {
  to {
    opacity: 0;
  }
}

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

* {
  box-sizing: border-box;
}

/* Атрибут hidden должен прятать всегда: у кнопок задан display: inline-flex,
   и он перебивал стандартное правило браузера — из-за этого кнопка
   «пересчитать» в подсказке висела даже когда расхождений нет. */
[hidden] {
  display: none !important;
}

body {
  margin: 0;
  font-family:
    "Golos Text", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 16px;
  line-height: 1.55;
  color: var(--text);
  /* Мягкое тёплое свечение сверху — «воздух» на большом экране.
     На слабом железе это просто градиент, тяжёлых эффектов здесь нет. */
  background:
    radial-gradient(1100px 520px at 12% -12%, var(--glow), transparent 62%),
    var(--bg);
  background-attachment: fixed;
  -webkit-text-size-adjust: 100%;
}

/* Колонка контента.
   Было 1020 px — на ноутбуке 15,6" (FHD при масштабе 125–150 %) это две трети
   экрана, а таблицы отчётов идут на 7–9 колонок. Теперь 1180 px, а на широких
   мониторах — 1320 px. */
.wrap {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 20px;
}

@media (min-width: 1500px) {
  .wrap {
    max-width: 1320px;
  }
}

/* --------------------------------------------------- появление контента */

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

main.wrap > * {
  animation: rise 0.28s var(--ease) both;
}

main.wrap > *:nth-child(2) {
  animation-delay: 0.04s;
}

main.wrap > *:nth-child(3) {
  animation-delay: 0.08s;
}

/* ------------------------------------------------------------- шапка */

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--topbar-bg);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--border);
}

.topbar .wrap {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 16px;
  min-height: 60px;
  padding-top: 10px;
  padding-bottom: 10px;
}

/* Шапка в две строки: сверху знак и кнопки, ниже — разделы.
   Почему не в одну: разделов девять, и на 1280–1536 px (ноутбук при
   масштабе 125–150 %) кнопка темы «сваливалась» на отдельную строку —
   получалось неровно. Теперь строка разделов всегда своя. */
.topbar nav {
  order: 3;
  flex: 1 1 100%;
}

.menu-button,
.theme-toggle {
  order: 2;
}

.brand {
  order: 1;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  font-size: 17px;
  letter-spacing: -0.02em;
  text-decoration: none;
  color: var(--text);
  white-space: nowrap;
}

/* Фирменный знак — «чек с галочкой» (static/logo.svg) */
.brand-mark {
  width: 30px;
  height: 30px;
  border-radius: 9px;
  box-shadow: 0 2px 6px var(--accent-ring);
}

/* --- навигация */

.menu-toggle {
  display: none;
}

.menu-button {
  display: none;
  margin-left: auto;
  padding: 10px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-field);
  background: var(--surface);
  cursor: pointer;
}

.menu-button span,
.menu-button span::before,
.menu-button span::after {
  display: block;
  width: 20px;
  height: 2px;
  border-radius: 2px;
  background: var(--text);
  transition:
    transform 0.2s var(--ease),
    opacity 0.2s var(--ease);
}

.menu-button span::before,
.menu-button span::after {
  content: "";
  position: relative;
}

.menu-button span::before {
  top: -6px;
}

.menu-button span::after {
  top: 4px;
}

.topbar nav {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
}

.topbar nav a {
  position: relative;
  padding: 8px 13px;
  border-radius: var(--r-field);
  color: var(--muted);
  text-decoration: none;
  font-size: 15px;
  font-weight: 500;
  white-space: nowrap;
  transition:
    color 0.15s var(--ease),
    background-color 0.15s var(--ease);
}

.topbar nav a:hover {
  color: var(--text);
  background: var(--surface-2);
}

.topbar nav a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* активная вкладка — «таблетка» цвета действия */
.topbar nav a.active {
  color: #ffffff;
  background: linear-gradient(135deg, var(--accent), var(--accent-bright));
  box-shadow: 0 6px 16px -6px var(--accent-ring);
}

.topbar nav a.active:hover {
  color: #ffffff;
  background: var(--accent-hover);
}

/* ------------------------------------------------------------- текст */

/* Заголовки тянется вместе с экраном: на ноутбуке читаются крупнее,
   на телефоне остаются компактными (было жёстко 28 и 23 px). */
h1 {
  font-size: clamp(26px, 0.7vw + 20px, 34px);
  line-height: 1.18;
  letter-spacing: -0.02em;
  margin: 0 0 8px;
  text-wrap: balance;
}

h2 {
  font-size: clamp(17px, 0.3vw + 15px, 20px);
  line-height: 1.25;
  letter-spacing: -0.015em;
  margin: 0 0 16px;
  text-wrap: balance;
}

h3 {
  font-size: 16px;
  margin: 0 0 8px;
}

p {
  margin: 0 0 16px;
}

a {
  color: var(--accent-active);
}

.muted {
  color: var(--muted);
}

.small {
  font-size: 13px;
}

.ok {
  color: var(--ok);
  font-weight: 600;
}

.bad {
  color: var(--bad);
  font-weight: 600;
}

/* Полоса сверки в авансовом отчёте: та же проверка, что и в блоке «Сверка»
   внизу страницы, но **липкая** — расхождение с суммой изъятия видно, пока
   листаешь чеки, а не только после прокрутки в самый низ (просьба владелицы,
   02.10.2026). Стоит под липкой шапкой: её высоту page считает в `--topbar-h`
   (static/ui.js). */
.sverka-bar {
  position: sticky;
  top: calc(var(--topbar-h, 84px) + 4px);
  z-index: 15;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 18px;
  padding: 10px 16px;
  margin-bottom: 20px;
  border: 1px solid var(--border);
  border-left-width: 4px;
  border-radius: var(--r-field);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  font-size: 14px;
}

.sverka-bar .sb-cell {
  white-space: nowrap;
}

.sverka-bar .sb-cell b {
  font-variant-numeric: tabular-nums;
}

.sverka-bar .sb-note {
  margin-left: auto;
  font-weight: 600;
}

.sverka-bar.ok {
  border-left-color: var(--ok-border);
  background: var(--ok-soft);
}

.sverka-bar.ok .sb-note {
  color: var(--ok);
}

.sverka-bar.bad {
  border-left-color: var(--bad-border);
  background: var(--bad-soft);
  color: var(--bad-text);
}

.sverka-bar.bad .sb-note {
  color: var(--bad-text);
}

@media (max-width: 720px) {
  .sverka-bar .sb-note {
    margin-left: 0;
  }
}

/* ------------------------------------------------------------- карточки */

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 16px;
  margin-bottom: 32px;
}

.card {
  position: relative;
  display: block;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  padding: 20px;
  text-decoration: none;
  color: var(--text);
  box-shadow: var(--shadow-sm);
  transition:
    transform 0.2s var(--ease),
    box-shadow 0.2s var(--ease),
    border-color 0.2s var(--ease);
}

.card::after {
  content: "";
  position: absolute;
  inset: auto 20px 0 20px;
  height: 3px;
  border-radius: 3px 3px 0 0;
  background: linear-gradient(90deg, var(--accent), var(--accent-bright));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.24s var(--ease);
}

.card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
  border-color: var(--border-strong);
}

.card:hover::after {
  transform: scaleX(1);
}

.card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.card-label {
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.card-title {
  font-size: 17px;
  font-weight: 600;
  margin-top: 8px;
}

.card-value {
  font-size: 30px;
  font-weight: 700;
  line-height: 1.1;
  margin-top: 8px;
  font-variant-numeric: tabular-nums;
}

.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  padding: 26px;
  margin-bottom: 24px;
  box-shadow: var(--shadow-sm);
}

/* Плитки быстрого перехода ведут к разделам по #id — оставляем запас сверху,
   чтобы заголовок не прятался под шапкой страницы. Отступ считаем от
   настоящей высоты шапки (`--topbar-h` ставит static/ui.js): шапка бывает
   в одну и в две строки. */
.panel[id] {
  scroll-margin-top: calc(var(--topbar-h, 84px) + 10px);
}

.row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 0;
  border-top: 1px solid var(--border);
}

.row:first-of-type {
  border-top: none;
}

table.kv {
  width: 100%;
  border-collapse: collapse;
}

table.kv td {
  padding: 10px 0;
  border-top: 1px solid var(--border);
  vertical-align: top;
}

table.kv td:first-child {
  color: var(--muted);
  width: 34%;
}

/* ------------------------------------------------------------- формы */

label {
  display: block;
  margin-bottom: 16px;
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
}

input[type="text"],
input:not([type]),
input[type="password"],
input[type="date"],
input[type="file"],
select {
  display: block;
  width: 100%;
  min-height: 46px;
  margin-top: 6px;
  padding: 11px 13px;
  font-family: inherit;
  font-size: 15px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-field);
  transition:
    border-color 0.15s var(--ease),
    box-shadow 0.15s var(--ease);
}

input[readonly] {
  background: var(--surface-2);
  color: var(--muted);
}

input:hover:not([readonly]),
select:hover {
  border-color: var(--border-hover);
}

input:focus,
select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

input::placeholder {
  color: var(--placeholder);
}

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

.three {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

.item {
  border-top: 1px solid var(--border);
  padding-top: 20px;
  margin-top: 20px;
}

/* Счётчик «Отработано дней» рядом с датами приёма и увольнения.
   Стоит в той же сетке, что и поля, поэтому низ выравниваем по низу полей. */
.days-counter {
  display: flex;
  flex-direction: column;
  gap: 4px;
  justify-content: flex-end;
}

.days-counter .dc-label {
  font-size: 12px;
  line-height: 1.3;
  color: var(--muted);
}

.days-counter .dc-value {
  min-height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--accent-soft);
  border-color: var(--accent-border);
  color: var(--accent-active);
  /* Стаж пишется словами («1 год 9 месяцев 24 дня») — крупным шрифтом он
     не влезал в треть строки, поэтому 15 px и перенос по словам. */
  font-size: 15px;
  line-height: 1.25;
  font-weight: 600;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* Управление счётчиком дней: общая дата счёта и галочка «Скрыть уволенных».
   Отдельная строка над списком работников — чтобы было видно, ЧТО именно
   пересчитывается. */
.days-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 10px 18px;
  padding: 12px 16px;
  margin: 4px 0 6px;
  border: 1px solid var(--accent-border);
  border-radius: 10px;
  background: var(--accent-soft);
}

.days-controls label {
  margin: 0;
}

.days-controls .check {
  padding-bottom: 10px;
}

.days-controls button {
  margin-bottom: 2px;
}

.actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.check {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 400;
}

.check input {
  width: auto;
  min-height: 0;
  margin: 0;
}

/* ------------------------------------------------------------- кнопки */

button {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 46px;
  padding: 11px 20px;
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  color: #ffffff;
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: var(--r-field);
  box-shadow: 0 2px 6px -2px var(--accent-ring);
  cursor: pointer;
  transition:
    background-color 0.18s var(--ease),
    border-color 0.18s var(--ease),
    box-shadow 0.18s var(--ease),
    transform 0.12s var(--ease);
}

button:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  box-shadow: 0 10px 20px -6px var(--accent-ring);
  transform: translateY(-2px);
}

/* нажатие: кнопка чуть «вдавливается» (в современных интерфейсах это
   главный сигнал «клик принят» — важнее общей анимации) */
button:active {
  background: var(--accent-active);
  border-color: var(--accent-active);
  transform: translateY(0) scale(0.985);
  box-shadow: 0 2px 6px -2px var(--accent-ring);
}

button:focus-visible {
  outline: 2px solid var(--accent-active);
  outline-offset: 2px;
}

/* ---------- зелёный градиентный ореол при наведении ----------
   По просьбе владелицы: вокруг вкладок меню и кнопок при наведении курсора
   появляется медленно пульсирующий ореол в оттенках зелёного. Нарисован
   внешними тенями (не layout — дёшево для слабого ноутбука клиентки):
   внутреннее зелёное свечение у края + расходящаяся градиентная дымка.
   Пульс медленный (2,6 с), чтобы не рябило в глазах; при системной настройке
   «меньше анимаций» отключается целиком. */
:root {
  --halo-green-soft: rgba(34, 168, 96, 0.35);
  --halo-green-mid: rgba(52, 199, 123, 0.28);
  --halo-green-bright: rgba(110, 231, 168, 0.5);
}

.topbar nav a:hover,
.topbar nav a:focus-visible,
button:hover:not(:disabled),
button:focus-visible:not(:disabled) {
  animation: halo-green 2.6s ease-in-out infinite;
}

@keyframes halo-green {
  0%,
  100% {
    box-shadow:
      0 0 0 1px var(--halo-green-bright),
      0 0 10px 2px var(--halo-green-mid),
      0 0 22px 6px var(--halo-green-soft),
      0 0 44px 12px rgba(34, 168, 96, 0.16);
  }
  50% {
    box-shadow:
      0 0 0 1px var(--halo-green-bright),
      0 0 14px 4px var(--halo-green-mid),
      0 0 34px 10px var(--halo-green-soft),
      0 0 70px 20px rgba(34, 168, 96, 0.22);
  }
}

@media (prefers-reduced-motion: reduce) {
  .topbar nav a:hover,
  .topbar nav a:focus-visible,
  button:hover:not(:disabled),
  button:focus-visible:not(:disabled) {
    animation: none;
  }
}

/* ---------- перелив: по главной кнопке при наведении пробегает блик ----------
   Полоса нарисована как фон псевдоэлемента (background-size шире кнопки),
   поэтому её не нужно обрезать через overflow:hidden — а он бы срезал
   пульсирующее кольцо у кнопки .attention и не влез в обычные кнопки.
   Двигаем только background-position: дешёвая отрисовка, без layout.
   Вторичная (.ghost) и опасная (.danger) остаются спокойными — иначе
   переливы начинают рябить в глазах на длинных страницах. */
button:not(.ghost):not(.danger)::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-image: linear-gradient(
    105deg,
    transparent 42%,
    var(--sheen) 50%,
    transparent 58%
  );
  background-size: 240% 100%;
  background-position: 135% 0;
  background-repeat: no-repeat;
  opacity: 0;
  pointer-events: none;
  transition:
    background-position 0.62s var(--ease),
    opacity 0.2s var(--ease);
}

button:not(.ghost):not(.danger):hover::before,
button:not(.ghost):not(.danger):focus-visible::before {
  background-position: -35% 0;
  opacity: 1;
}

/* ---------- волна от нажатия (ripple) ----------
   Элемент <span class="ripple"> создаёт ui.js в точке клика и убирает
   после анимации (или при отключённой анимации — не создаёт вообще).
   Клип делаем классом .has-ripple на время волны: постоянный overflow:hidden
   на кнопках срезал бы кольцо у .attention. */
button.has-ripple {
  overflow: hidden;
}

.ripple {
  position: absolute;
  border-radius: 50%;
  background: currentColor;
  opacity: var(--ripple);
  transform: scale(0);
  pointer-events: none;
  animation: ripple-wave 0.42s var(--ease) forwards;
}

@keyframes ripple-wave {
  to {
    transform: scale(1);
    opacity: 0;
  }
}

button:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* вторичная */
button.ghost {
  color: var(--text);
  background: var(--surface);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-sm);
}

button.ghost:hover {
  background: var(--surface-2);
  border-color: var(--border-hover);
  box-shadow: var(--shadow-md);
}

button.ghost:active {
  background: var(--surface-3);
}

/* опасная */
button.danger {
  color: var(--bad);
  background: var(--surface);
  border-color: var(--bad-border);
  box-shadow: var(--shadow-sm);
}

button.danger:hover {
  background: var(--bad-soft);
  border-color: var(--bad);
}

button.danger:active {
  background: var(--bad-soft-2);
}

/* Кнопка, которую нужно заметить: «Взять из авансового отчёта» на экране
   кассы остаётся оранжевой (как основное действие) и получает мягкое
   пульсирующее кольцо — оно притягивает взгляд, но не мешает читать.
   Анимируем только transform и opacity (см. общий комментарий в начале файла). */
button.attention {
  background: var(--accent);
  border-color: var(--accent);
  color: #ffffff;
  box-shadow: 0 4px 12px -4px var(--accent-ring);
}

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

button.attention:active {
  background: var(--accent-active);
  border-color: var(--accent-active);
}

button.attention::after {
  content: "";
  position: absolute;
  inset: -3px;
  border: 2px solid var(--accent);
  border-radius: inherit;
  opacity: 0;
  pointer-events: none;
  animation: attention-pulse 2.4s var(--ease) infinite;
}

@keyframes attention-pulse {
  0% {
    transform: scale(0.97);
    opacity: 0.55;
  }
  70% {
    transform: scale(1.14);
    opacity: 0;
  }
  100% {
    transform: scale(1.14);
    opacity: 0;
  }
}

/* состояние «идёт работа» — со вращающимся индикатором */
button.loading {
  color: transparent;
  pointer-events: none;
}

button.loading::after {
  content: "";
  position: absolute;
  width: 18px;
  height: 18px;
  border: 2px solid var(--spinner-track);
  border-top-color: #ffffff;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}

button.ghost.loading::after,
button.danger.loading::after {
  border-color: var(--spinner-track-quiet);
  border-top-color: var(--text);
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* --------------------------------------------------------- оповещения */

/* Всплывающее сообщение о результате действия.
   Важно: на экранах кассы и отчёта кнопка находится в самом низу длинной
   страницы, а обычная плашка — вверху; человек её просто не видел.
   Поэтому результат показываем там, где он точно попадёт в глаза. */
.toast {
  position: fixed;
  top: 76px;
  right: 20px;
  left: auto;
  z-index: 60;
  max-width: min(460px, calc(100vw - 32px));
  margin: 0;
  box-shadow: var(--shadow-lg);
  cursor: pointer;
  backdrop-filter: saturate(1.2) blur(6px);
}

@media (max-width: 720px) {
  .toast {
    top: 8px;
    left: 12px;
    right: 12px;
    max-width: none;
  }
}

/* Кнопка «Наверх»: появляется после первого экрана (static/ui.js).
   Стоит в правом нижнем углу — там её видно на длинной странице, и она
   не спорит с сообщениями вверху. */
.to-top {
  position: fixed;
  right: 20px;
  bottom: 24px;
  z-index: 55;
  padding: 10px 16px;
  border: 1px solid var(--accent-border);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  box-shadow: var(--shadow-lg);
}

.to-top:hover,
.to-top:focus-visible {
  border-color: var(--accent);
  color: var(--accent-active);
  transform: translateY(-2px);
}

@media (max-width: 720px) {
  .to-top {
    right: 12px;
    bottom: 12px;
    padding: 10px 14px;
  }
}

.alert {
  background: var(--bad-soft);
  border: 1px solid var(--bad-border);
  border-left-width: 4px;
  border-radius: var(--r-field);
  padding: 16px 20px;
  margin-bottom: 24px;
  color: var(--bad-text);
  animation: rise 0.24s var(--ease) both;
}

.alert ul {
  margin: 8px 0 0;
  padding-left: 20px;
}

/* сообщение об успехе — зелёное, чтобы отличалось от ошибок */
.alert.ok {
  background: var(--ok-soft);
  border-color: var(--ok-border);
  color: var(--ok);
}

.alert:empty,
.alert[hidden] {
  display: none;
}

.draft {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: var(--ok-soft);
  border: 1px solid var(--ok-border);
  border-left-width: 4px;
  border-radius: var(--r-field);
  padding: 14px 20px;
  margin-bottom: 24px;
  animation: rise 0.24s var(--ease) both;
}

.draft[hidden] {
  display: none;
}

.draft .actions {
  display: flex;
  gap: 8px;
}

.note {
  background: var(--warn-soft);
  border: 1px solid var(--warn-border);
  border-left-width: 4px;
  border-radius: var(--r-field);
  padding: 14px 18px;
  margin: 0 0 16px;
  font-size: 15px;
}

/* ------------------------------------------------------------- позиции */

/* Подсказка «как подписывать части длинного чека» в блоке «Распознать чеки».
   Порядок позиций в собранном чеке зависит от имён файлов, поэтому правило
   должно быть видно прямо на экране — программа не только для одного
   бухгалтера (просьба владелицы 07.10.2026). */
.ocr-hint {
  background: var(--accent-soft);
  border: 1px solid var(--accent-border);
  border-left-width: 4px;
  border-radius: var(--r-field);
  padding: 12px 16px;
  margin: 0 0 14px;
  font-size: 14.5px;
}

.ocr-hint p {
  margin: 6px 0 0;
}

.ocr-hint .ocr-part {
  display: inline-block;
  padding: 1px 7px;
  margin: 1px 0;
  border-radius: 6px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 13px;
  white-space: nowrap;
}

.positions {
  margin-bottom: 16px;
  overflow: hidden;
  max-height: 9000px;
  transition:
    max-height 0.32s var(--ease),
    opacity 0.22s var(--ease);
}

/* плавное сворачивание списка позиций */
.positions.collapsed {
  max-height: 0;
  opacity: 0;
}

/* ------------------------------------------------- скелетон загрузки */

@keyframes shimmer {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}

.skeleton {
  height: 44px;
  margin-bottom: 8px;
  border-radius: var(--r-field);
  background: linear-gradient(
    90deg,
    var(--skeleton-1) 25%,
    var(--skeleton-2) 50%,
    var(--skeleton-1) 75%
  );
  background-size: 200% 100%;
  animation: shimmer 1.3s linear infinite;
}

.skeleton-note {
  margin: 0 0 8px;
  font-size: 14px;
  color: var(--muted);
}

/* ------------------------------------------------- галочка успеха */

.checkmark {
  display: inline-block;
  width: 18px;
  height: 18px;
  vertical-align: -3px;
  margin-right: 6px;
}

.checkmark path {
  fill: none;
  stroke: var(--ok);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 32;
  stroke-dashoffset: 32;
  animation: draw 0.45s var(--ease) forwards;
}

@keyframes draw {
  to {
    stroke-dashoffset: 0;
  }
}

.cheque-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-field);
  padding: 10px 14px;
  margin-bottom: 16px;
}

.cheque-summary .cs-toggle {
  min-height: 36px;
  padding: 6px 14px;
  font-size: 14px;
}

/* Итоги по чеку — внизу позиций: без скидки, скидка, к оплате.
   Нужны, чтобы сразу видеть, какой чек не сходится с суммой изъятия. */
.cheque-totals {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
  margin: 4px 0 14px;
  padding: 10px 14px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent);
  border-radius: var(--r-field);
}

/* Цвет текста по умолчанию — --muted. Раньше здесь стоял несуществующий
   --muted-text: цвет молча не применялся, и приглушённые числа выглядели
   как обычный текст. */
.cheque-totals .ct-cell {
  font-size: 14px;
  color: var(--muted);
}

.cheque-totals .ct-cell b {
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.cheque-totals .ct-paid {
  color: var(--ok);
}

/* Дата чека, которую не удалось распознать — сразу видно, что нужно вписать */
.c-date.warn {
  border-color: var(--bad);
  background: var(--bad-soft);
}

/* Выбор файла накопления: выбран один раз — используется и обновляется сам */
.accum {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin: 8px 0 6px;
}

.accum button {
  min-height: 38px;
  padding: 8px 16px;
  font-size: 14px;
}

.accum span.ok {
  color: var(--ok);
  font-weight: 500;
}

/* Распознанные документы изъятия за день: суммы складываются, поэтому
   показываем список — видно, что именно вошло в сумму изъятия, и можно
   убрать лишнее (например, случайно распознанный не тот чек). */
.izyatie-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 12px;
}

.izyatie-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 12px;
  background: var(--accent-soft);
  border: 1px solid var(--accent-border);
  border-left: 4px solid var(--accent);
  border-radius: var(--r-field);
  font-size: 15px;
}

.izyatie-row.izyatie-total {
  background: var(--surface);
  border-color: var(--border-strong);
  border-left-color: var(--ok);
  font-weight: 600;
}

/* Изъятие другого дня — в этот отчёт не входит: это отдельный авансовый отчёт */
.izyatie-row.izyatie-other {
  background: var(--bad-soft);
  border-color: var(--bad-border);
  border-left-color: var(--bad);
}

.izyatie-row.izyatie-total .izyatie-sum {
  color: var(--ok);
}

.izyatie-row .izyatie-del {
  min-height: 34px;
  padding: 6px 14px;
  font-size: 13px;
}

.izyatie-sum {
  font-weight: 600;
  white-space: nowrap;
}

/* Строка позиции: наименование — во всю ширину (как в чеке),
   а стоимость, вес/цена, скидка и кнопки — отдельной строкой ниже. */
.pos-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 6px;
  margin-bottom: 12px;
  padding: 8px 10px 12px;
  border-radius: 10px;
  border-bottom: 1px dashed var(--border);
}

/* Строка, которую бухгалтер отметила как проверенную, заливается
   нежно-салатовым — видно, что уже сверено (просьба владелицы 07.10.2026). */
.pos-row.checked {
  background: var(--checked-bg);
  border-bottom-color: var(--checked-border);
}

/* Строка наименования: слева галочка «проверено», справа — название */
.pos-head {
  display: flex;
  align-items: center;
  gap: 8px;
}

.pos-check {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  cursor: pointer;
}

.pos-check input[type="checkbox"] {
  width: 18px;
  height: 18px;
  margin: 0;
  cursor: pointer;
  accent-color: var(--ok);
}

.pos-fields {
  display: grid;
  grid-template-columns: 190px minmax(320px, 1fr) 38px 38px 44px;
  gap: 8px;
  /* по низу: у полей есть подписи сверху, значения должны стоять в одну линию */
  align-items: end;
}

/* Расчёт по позиции — всё в одну строку, каждое поле подписано:
   «Количество × Цена за единицу = Сумма без скидки − Скидка».
   Итог со скидкой не повторяем: он стоит в самой позиции (слева),
   под подписью «Стоимость с учётом скидки». */
.p-hint {
  display: flex;
  align-items: flex-end;
  flex-wrap: nowrap;
  gap: 6px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* Поле с подписью: подпись сверху, значение снизу — ничего не «поедет» */
.p-field {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.p-field .p-caption {
  font-size: 10.5px;
  line-height: 1.2;
  color: var(--muted);
  white-space: normal;
}

/* Знак между полями выравнивается по строке значений, а не по подписям */
.p-op {
  padding-bottom: 11px;
  color: var(--muted);
}

.p-hint input {
  width: 84px;
  min-height: 36px;
  margin-top: 0;
  padding: 6px 8px;
  font-size: 13px;
}

.p-hint .p-discount {
  width: 76px;
}

.p-hint .p-calc {
  display: flex;
  align-items: center;
  min-height: 36px;
  padding: 0 6px;
  font-size: 13px;
  color: var(--text);
}

.p-hint.bad .p-calc {
  color: var(--bad);
}

.p-hint .p-note {
  white-space: nowrap;
}

.p-hint .p-apply {
  min-height: 32px;
  padding: 4px 10px;
  font-size: 13px;
}

.pos-row input {
  margin-top: 0;
}

/* «⧉» — скопировать строку целиком (название, сумма, вес, цена, скидка) */
.pos-row .copy-pos {
  padding: 10px 0;
  min-width: 36px;
  font-size: 17px;
  line-height: 1;
  color: var(--muted);
}

.pos-row .copy-pos:hover {
  color: var(--accent);
}

.pos-row .del-pos {
  padding: 10px 0;
  font-size: 18px;
  line-height: 1;
}

/* «+» — вставить пропущенную позицию ниже этой строки */
.pos-row .ins-pos {
  padding: 10px 0;
  min-width: 36px;
  font-size: 18px;
  line-height: 1;
  color: var(--muted);
}

.pos-row .ins-pos:hover {
  color: var(--accent);
}

.ophead {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
}

.badge {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  color: #ffffff;
}

.badge.in {
  background: var(--ok);
}

.badge.out {
  background: var(--accent);
}

/* Меню и кнопка темы на телефоне: кнопка остаётся справа, бургер — рядом */
@media (max-width: 720px) {
  .theme-toggle {
    margin-left: 0;
  }
}

/* ------------------------------------------------------------- таблицы */

/* Обёртка широких таблиц: на узком окне таблица прокручивается внутри,
   а не растягивает всю страницу.
   Работает вместе с общим .table-scroll */
.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
  margin-bottom: 4px;
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}

.table-scroll::-webkit-scrollbar {
  height: 10px;
}

.table-scroll::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: var(--r-pill);
}

.table-scroll::-webkit-scrollbar-track {
  background: transparent;
}

/* На широком экране в таблицах можно дышать свободнее */
@media (min-width: 1200px) {
  table.data th,
  table.data td {
    padding: 12px 14px;
  }
}

.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

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

table.data th,
table.data td {
  padding: 10px 12px;
  border-top: 1px solid var(--border);
  text-align: left;
  vertical-align: top;
}

table.data thead th {
  border-top: none;
  border-bottom: 1px solid var(--border);
  color: var(--muted);
  font-weight: 600;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

table.data tbody tr {
  transition: background-color 0.14s var(--ease);
}

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

table.data .num {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------- вход */

.login-card {
  max-width: 420px;
  margin: 48px auto;
}

.login-card h1 {
  font-size: 24px;
  margin-bottom: 4px;
}

/* ------------------------------------------------------------- помощь */

.shot {
  display: block;
  width: 100%;
  height: auto;
  /* Скриншоты инструкции сняты в 2× и хранятся в WebP: на обычном экране
     не мылятся, а на экране с высоким разрешением остаются резкими.
     Жёсткий потолок ширины нужен, чтобы на широком мониторе снимок
     не растягивался до 1300 px. */
  max-width: 1000px;
  margin: 0 0 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-field);
  box-shadow: var(--shadow-sm);
  background: var(--surface);
}

.shot-caption {
  font-size: 13px;
  color: var(--muted);
  margin: 0 0 20px;
}

.steps {
  counter-reset: step;
  margin: 0;
  padding: 0;
  list-style: none;
}

.steps li {
  position: relative;
  padding: 0 0 20px 48px;
  counter-increment: step;
}

.steps li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 15px;
  color: #ffffff;
  background: linear-gradient(135deg, var(--accent), var(--accent-bright));
  border-radius: var(--r-pill);
  box-shadow: 0 4px 10px -4px var(--accent-ring);
}

.steps li strong {
  display: block;
  margin-bottom: 4px;
}

/* --- Раздел «Помощь»: подсказки и быстрый переход --- */

/* Блок-приглашение спросить Аристарха (вверху инструкции) */
.help-ask {
  display: flex;
  gap: 18px;
  align-items: flex-start;
  border-color: var(--accent-border);
  background: var(--accent-soft);
}

/* Фотография Аристарха — крупная и кликабельная (ведёт в консультанта). */
.help-ask-photo {
  flex: 0 0 auto;
  display: block;
  width: 128px;
  height: 128px;
  border-radius: 50%;
  overflow: hidden;
  border: 3px solid var(--accent-border);
  background: var(--surface);
  box-shadow: 0 10px 22px -12px var(--accent-ring);
  transition:
    transform 160ms ease,
    box-shadow 160ms ease;
}

.help-ask-photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.help-ask-photo:hover,
.help-ask-photo:focus-visible {
  transform: translateY(-2px) scale(1.02);
  box-shadow: 0 16px 28px -12px var(--accent-ring);
}

.help-ask h2 {
  margin: 0 0 6px;
}

.help-ask p {
  margin: 0;
}

@media (max-width: 560px) {
  .help-ask {
    gap: 12px;
  }

  .help-ask-photo {
    width: 88px;
    height: 88px;
  }
}

/* Плитки «что вы хотите сделать» — ссылки на нужный раздел */
.task-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 12px;
}

.task-card {
  display: block;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--r-field);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  text-decoration: none;
  color: var(--text);
  font-weight: 600;
  transition:
    transform 140ms ease,
    border-color 140ms ease,
    box-shadow 140ms ease;
}

.task-card:hover,
.task-card:focus-visible {
  transform: translateY(-2px);
  border-color: var(--accent-border);
  box-shadow: 0 10px 22px -12px var(--accent-ring);
}

/* Счётчик на плитке быстрого перехода («Работники 7», «Уволенные 2»)
   и у заголовка блока внутри «Эталона». */
.count {
  display: inline-block;
  min-width: 22px;
  padding: 1px 8px;
  margin-left: 6px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  border: 1px solid var(--accent-border);
  color: var(--accent-active);
  font-size: 12px;
  font-weight: 700;
  text-align: center;
  vertical-align: middle;
}

/* Заголовок блока внутри раздела (например «Работники» и «Уволенные» в
   «Эталон» → «Работники и стаж»). Плитки ведут на эти заголовки, поэтому
   оставляем запас сверху — иначе он прячется под шапкой страницы. */
.group-head {
  scroll-margin-top: calc(var(--topbar-h, 84px) + 10px);
  margin: 26px 0 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--border);
  font-size: 17px;
  font-weight: 700;
  color: var(--text);
}

/* Пометка «новое» у недавних возможностей */
.badge-new {
  display: inline-block;
  padding: 1px 8px;
  margin-left: 4px;
  border-radius: var(--r-pill);
  background: var(--ok-soft, var(--accent-soft));
  border: 1px solid var(--ok-border, var(--accent-border));
  color: var(--ok, var(--accent-active));
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  vertical-align: middle;
  white-space: nowrap;
}

.toc {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 24px;
}

.toc a {
  padding: 8px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  text-decoration: none;
  font-size: 14px;
  color: var(--text);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  transition:
    transform 0.15s var(--ease),
    box-shadow 0.15s var(--ease),
    border-color 0.15s var(--ease);
}

.toc a:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

/* ------------------------------------------------------------- подвал */

footer {
  padding: 32px 16px 48px;
}

/* ======================================================== мобильная версия */

@media (max-width: 720px) {
  .menu-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* меню раскрывается по флажку — без JavaScript */
  .topbar nav {
    display: none;
    width: 100%;
    flex-direction: column;
    gap: 2px;
    padding-bottom: 12px;
  }

  .menu-toggle:checked ~ nav {
    display: flex;
  }

  .topbar nav a {
    padding: 12px 14px;
    font-size: 16px;
  }

  /* «крестик» у кнопки меню, когда оно открыто */
  .menu-toggle:checked ~ .menu-button span {
    background: transparent;
  }

  .menu-toggle:checked ~ .menu-button span::before {
    transform: rotate(45deg);
    top: -1px;
  }

  .menu-toggle:checked ~ .menu-button span::after {
    transform: rotate(-45deg);
    top: -1px;
  }

  .topbar .wrap {
    min-height: 58px;
    gap: 8px;
  }

  .two,
  .three {
    grid-template-columns: 1fr;
  }

  /* карточки на телефоне — по две в ряд, а не по одной длинной */
  .grid {
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 12px;
  }

  .card {
    padding: 16px;
  }

  .pos-fields {
    grid-template-columns: 1fr 1fr 36px 36px 44px;
    align-items: center;
  }

  /* на телефоне расчёт занимает отдельную строку и может переноситься */
  .p-hint {
    grid-column: 1 / -1;
    flex-wrap: wrap;
    white-space: normal;
    align-items: flex-end;
    row-gap: 10px;
  }

  .p-op {
    padding-bottom: 11px;
  }

  h1 {
    font-size: 23px;
  }

  .panel {
    padding: 18px;
    border-radius: 14px;
  }

  .card-value {
    font-size: 26px;
  }

  button {
    width: 100%;
  }

  button.ghost,
  button.danger {
    width: auto;
    flex: 1 1 auto;
  }

  .actions button {
    width: auto;
  }

  .pos-row .del-pos {
    width: auto;
  }
}

/* Кто просил меньше движения — получит его меньше */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* Кнопка «Поискать в интернете» под ответом, где нормы в базе нет:
   вместо отписки «смотрите ссылку» человек получает действие в один клик. */
.chat-more {
  margin-top: 10px;
  min-height: 38px;
  padding: 7px 14px;
  font-size: 14px;
}

/* ---------- Чат с помощником «Аристарх» ----------
   Окно чата: вопрос справа, ответ помощника слева, под ответом — короткие
   карточки источников со кликабельными ссылками. Задача — читаемость:
   ограниченная ширина строки, спокойные цвета, ничего лишнего. */

.chat-panel {
  padding-bottom: 14px;
}

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

.chat-persona {
  display: flex;
  align-items: center;
  gap: 14px;
}

.chat-persona-text {
  display: flex;
  flex-direction: column;
  line-height: 1.3;
}

.chat-persona-text strong {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.chat-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 96px;
  height: 96px;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  flex: 0 0 auto;
}

.chat-avatar.small {
  width: 50px;
  height: 50px;
  font-size: 13px;
}

.chat-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.chat-mode select {
  padding: 6px 10px;
}

.chat {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-height: 62vh;
  overflow-y: auto;
  padding: 14px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
}

.chat-msg {
  display: flex;
  gap: 8px;
  align-items: flex-start;
}

.chat-msg-user {
  justify-content: flex-end;
}

.chat-bubble {
  max-width: min(720px, 82%);
  padding: 10px 14px;
  border-radius: 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.chat-msg-user .chat-bubble {
  background: var(--accent-soft);
  border-color: var(--accent-ring);
}

.chat-msg-assistant .chat-bubble {
  max-width: min(760px, 88%);
}

.chat-line + .chat-line {
  margin-top: 6px;
}

.chat-bullet::before {
  content: "• ";
  color: var(--accent);
  font-weight: 700;
}

.chat-sources-title {
  margin-top: 10px;
}

.chat-source-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 6px;
}

.chat-source {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
  font-size: 13px;
  padding: 6px 8px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-field);
}

.chat-source-n {
  color: var(--accent);
  font-weight: 600;
}

.chat-link,
.chat-ref {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.chat-ref {
  font-weight: 600;
  text-decoration: none;
}

.chat-footer {
  margin-top: 8px;
  padding-top: 6px;
  border-top: 1px dashed var(--border);
}

/* Аватар Аристарха — фотография (круглая рамка, фото по центру). */
img.chat-avatar {
  object-fit: cover;
  object-position: center;
  background: var(--accent-soft, #e8eef7);
  border: 2px solid var(--border);
  box-shadow: 0 4px 12px rgba(15, 23, 42, 0.08);
  overflow: hidden;
}

/* Обёртка аватара: принимает фокус и хавер, чтобы показать «лупу»
   (большую копию фото, которую видно с любого места страницы). */
.chat-avatar-wrap {
  position: relative;
  display: inline-flex;
  flex: 0 0 auto;
  border-radius: var(--r-pill);
  cursor: zoom-in;
}

.chat-avatar-wrap:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* Лупа — один на страницу, позицию считает JS (position: fixed, поэтому
   фото не обрезается прокруткой внутри окна чата). */
.avatar-loupe {
  position: fixed;
  z-index: 80;
  width: 280px;
  height: 280px;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 20px;
  background: var(--surface);
  box-shadow: 0 24px 56px rgba(15, 23, 42, 0.35);
  opacity: 0;
  transform: scale(0.82);
  transition:
    opacity 0.22s var(--ease),
    transform 0.22s var(--ease);
  pointer-events: none;
}

.avatar-loupe.on {
  opacity: 1;
  transform: scale(1);
}

.avatar-loupe img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 24%;
}

@media (prefers-reduced-motion: reduce) {
  .avatar-loupe {
    transition: none;
  }
}

/* Кнопка «Прослушать» и переключатель голоса. */
.chat-speak {
  margin-top: 8px;
  min-height: 34px;
  padding: 5px 12px;
  font-size: 13px;
}

.chat-speak.playing {
  border-color: var(--accent);
  color: var(--accent);
}

#voice-toggle.on {
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}

/* Выбор голоса в шапке чата (список приходит с сервера — только проверенные) */
.chat-voice-pick select {
  padding: 6px 10px;
  max-width: 260px;
}

/* Микрофон в строке вопроса */
.mic.recording {
  border-color: #c0392b;
  color: #c0392b;
  font-weight: 600;
  animation: mic-pulse 1.3s ease-in-out infinite;
}

@keyframes mic-pulse {
  0%,
  100% {
    box-shadow: 0 0 0 0 rgba(192, 57, 43, 0.35);
  }
  50% {
    box-shadow: 0 0 0 6px rgba(192, 57, 43, 0);
  }
}

/* ---------- «Аристарх говорит»: большое фото, потом обратно в иконку ----------
   Маленький кружок в шапке издалека не разглядеть, поэтому, пока помощник
   ищет ответ и читает его голосом, на экране — большая карточка с фотографией
   (примерно четверть экрана). Как только речь закончилась, карточка сжимается
   обратно и исчезает — чат не закрыт, читать ответ ничто не мешает. */
.voice-stage {
  position: fixed;
  right: 26px;
  /* По центру правой части экрана: ниже шапки и выше строки вопроса —
     так фото не закрывает ни чат, ни кнопки «Спросить»/«Голосом». */
  top: 50%;
  z-index: 60;
  opacity: 0;
  transform: translateY(-50%) scale(0.55);
  transform-origin: 100% 50%;
  transition:
    opacity 0.3s ease,
    transform 0.34s cubic-bezier(0.2, 0.9, 0.3, 1.18);
  pointer-events: none;
}

.voice-stage.on {
  opacity: 1;
  transform: translateY(-50%);
  pointer-events: auto;
}

.voice-stage[hidden] {
  display: none;
}

.voice-stage-card {
  width: min(30vh, 26vw, 300px);
  padding: 12px 14px 14px;
  text-align: center;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 20px;
  box-shadow: 0 20px 48px rgba(18, 28, 45, 0.28);
  cursor: pointer;
}

.voice-stage-card:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
}

.voice-stage-photo {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  object-position: 50% 24%;
  border-radius: 16px;
}

.voice-stage-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 10px;
}

.voice-stage-info strong {
  font-size: 17px;
}

.voice-stage-status {
  font-size: 13px;
  color: var(--muted, #667);
}

.voice-wave {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 4px;
  height: 20px;
  margin-top: 8px;
}

.voice-wave i {
  display: block;
  width: 4px;
  height: 5px;
  border-radius: 2px;
  background: var(--accent);
  opacity: 0.3;
}

.voice-stage[data-state="speaking"] .voice-wave i {
  opacity: 1;
  animation: voice-bar 0.9s ease-in-out infinite;
}

.voice-wave i:nth-child(2) {
  animation-delay: 0.12s;
}

.voice-wave i:nth-child(3) {
  animation-delay: 0.24s;
}

.voice-wave i:nth-child(4) {
  animation-delay: 0.36s;
}

.voice-wave i:nth-child(5) {
  animation-delay: 0.48s;
}

@keyframes voice-bar {
  0%,
  100% {
    height: 5px;
  }
  50% {
    height: 20px;
  }
}

/* «Ищет ответ» — мягкое дыхание фото, чтобы было видно, что работа идёт */
.voice-stage[data-state="thinking"] .voice-stage-photo {
  animation: voice-think 1.8s ease-in-out infinite;
}

@keyframes voice-think {
  0%,
  100% {
    filter: none;
  }
  50% {
    filter: brightness(1.06) contrast(1.03);
  }
}

@media (max-width: 760px) {
  .voice-stage {
    right: 12px;
    left: 12px;
    top: auto;
    bottom: 150px;
    transform: translateY(14px) scale(0.6);
  }

  .voice-stage.on {
    transform: none;
  }

  .voice-stage-card {
    width: min(56vw, 240px);
    margin-left: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .voice-stage,
  .voice-stage[data-state="speaking"] .voice-wave i,
  .voice-stage[data-state="thinking"] .voice-stage-photo {
    transition: none;
    animation: none;
  }

  .voice-stage {
    transform: translateY(-50%);
  }
}

.chat-input {
  display: flex;
  gap: 10px;
  align-items: flex-end;
  margin-top: 12px;
}

.chat-input textarea {
  flex: 1 1 auto;
  min-height: 44px;
  max-height: 160px;
  resize: vertical;
  font: inherit;
  padding: 10px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-field);
  background: var(--surface);
  color: var(--text);
}

.chat-input textarea:focus-visible {
  outline: 2px solid var(--accent-ring);
  border-color: var(--accent);
}

.chat-hint {
  margin-top: 6px;
}

.chat-typing .chat-bubble {
  opacity: 0.85;
}

#suggestions {
  margin-top: 10px;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px
  ;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

@media (max-width: 720px) {
  .chat-bubble,
  .chat-msg-assistant .chat-bubble {
    max-width: 100%;
  }
  .chat-input {
    flex-direction: column;
    align-items: stretch;
  }
}

/* ------------------------------------------------- показ пароля */

/* «Глазок» внутри поля пароля: маленькая кнопка, которая показывает
   набранное. Появляется сама (static/password-toggle.js) у каждого
   `input[type="password"]`, поэтому шаблоны править не нужно.

   Кнопка вторичная (серая), не спорит с основным действием страницы;
   позиционируется внутри поля, поэтому обёртке нужны свои координаты. */
.pw-field {
  position: relative;
  display: block;
}

.pw-field input {
  /* Место под кнопку, чтобы длинный пароль не заезжал под неё. */
  padding-right: 92px;
}

.pw-field .pw-toggle {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  min-height: 0;
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  box-shadow: none;
}

.pw-field .pw-toggle:hover {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: var(--accent);
  box-shadow: none;
  transform: translateY(-50%);
}

.pw-field .pw-toggle:active {
  transform: translateY(-50%);
  box-shadow: none;
}

.pw-field .pw-toggle:focus-visible {
  outline: 2px solid var(--accent-active);
  outline-offset: 1px;
}

/* ============================================ загрузка фото (pickfiles.js)

   Раньше фото выбирались «голым» input[type=file]: ни перетаскивания,
   ни превью, ни возможности повернуть снимок. На слабом ноутбуке превью
   десяти 15-МБ фотографий было бы тяжело, поэтому их и не делали.
   Теперь у клиента i7 и 16 ГБ — показываем миниатюры, даём повернуть
   и удалить снимок до отправки, а в браузере же уменьшаем очень большие
   фото (это ещё и разгружает сервер и распознавание). */

.dropzone {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 16px;
  margin-top: 6px;
  text-align: center;
  background: var(--surface-2);
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--r-card);
  cursor: pointer;
  transition:
    border-color 0.18s var(--ease),
    background-color 0.18s var(--ease);
}

.dropzone:hover,
.dropzone:focus-within {
  border-color: var(--accent);
  background: var(--accent-soft);
}

/* Класс ставит pickfiles.js на время перетаскивания файлов */
.dropzone.dragging {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.dropzone input[type="file"] {
  display: none;
}

.dropzone-icon {
  font-size: 20px;
  line-height: 1;
}

.dropzone-hint {
  font-size: 14px;
  color: var(--muted);
}

.dropzone-hint b {
  color: var(--text);
}

.pick-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
  gap: 12px;
  margin-top: 14px;
}

.pick-list:empty {
  display: none;
}

.pick-item {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-field);
  padding: 6px;
  box-shadow: var(--shadow-sm);
  animation: rise 0.2s var(--ease) both;
}

.pick-thumb {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 7px;
  background: var(--surface-3);
}

.pick-name {
  margin-top: 6px;
  font-size: 11px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pick-size {
  font-size: 11px;
  color: var(--muted);
}

.pick-buttons {
  display: flex;
  gap: 4px;
  margin-top: 6px;
}

.pick-buttons button {
  flex: 1 1 auto;
  min-height: 30px;
  min-width: 30px;
  padding: 4px 6px;
  font-size: 14px;
  line-height: 1;
  font-weight: 500;
}

.pick-buttons button.ghost {
  box-shadow: none;
}

.pick-item.pick-warn .pick-size {
  color: var(--bad);
  font-weight: 600;
}

/* Полоска прогресса отправки: показывается, пока файлы уходят на сервер */
.upload-progress {
  height: 6px;
  margin-top: 10px;
  background: var(--surface-3);
  border-radius: var(--r-pill);
  overflow: hidden;
}

.upload-progress[hidden] {
  display: none;
}

.upload-progress > i {
  display: block;
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--accent), var(--accent-bright));
  border-radius: var(--r-pill);
  transition: width 0.18s linear;
}

/* Всплывающее сообщение: плавное появление вместо рывка (Chrome 117+).
   В остальных браузерах работает обычная анимация `rise`. */
@starting-style {
  .toast:not([hidden]) {
    opacity: 0;
    transform: translateY(-6px);
  }
}

.toast {
  transition:
    opacity 0.2s var(--ease),
    transform 0.2s var(--ease);
}

/* «Кто просил меньше движения» — гасим и переходы между страницами */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

/* ------------------------------------------------ диалог подтверждения

   Свой диалог вместо window.confirm (см. ui.js). Системное окно выглядело
   чужеродно и блокировало вкладку целиком. */
.kassa-dialog {
  width: min(440px, calc(100vw - 32px));
  padding: 24px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-lg);
}

.kassa-dialog::backdrop {
  background: rgb(var(--shadow-rgb) / 0.45);
  backdrop-filter: blur(2px);
}

.kassa-dialog-text {
  margin: 0 0 20px;
  font-size: 16px;
  line-height: 1.5;
}

.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.dialog-actions button {
  min-width: 120px;
}

/* --------------------------------------------------- работники (v0.49)
   Раздел «Работники» (§5.102): карточка работника плюс подкарточки
   «Отпуск» и «Больничный». Отпуска и больничные — отдельные формы,
   поэтому визуально собираем их в одну карточку рамкой и фоном. */

.worker-card {
  margin: 18px 0 22px;
  padding: 6px 18px 18px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface, transparent);
}

.subcard {
  margin-top: 18px;
  padding: 12px 14px 14px;
  border: 1px dashed var(--border);
  border-radius: 10px;
  background: var(--accent-soft, transparent);
}

.subcard-head {
  margin: 0 0 6px;
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 8px;
}

.subcard .item {
  border-top: 1px solid var(--border);
  padding-top: 14px;
  margin-top: 14px;
}

.subcard form:first-of-type.item {
  border-top: 0;
  padding-top: 0;
  margin-top: 0;
}

/* Документ и его номер в одной строке: «Приказ [№ ___]». */
.inline-fields {
  display: flex;
  gap: 8px;
}

.inline-fields select {
  flex: 1 1 auto;
  min-width: 0;
}

.inline-fields input {
  flex: 0 0 90px;
  min-width: 0;
}

[readonly] {
  background: var(--accent-soft, transparent);
  color: var(--accent-active);
  font-weight: 600;
}

.children-note {
  border-left: 3px solid var(--accent-border, var(--border));
  padding-left: 10px;
}

/* Свёрнутый список работников под заголовком блока: нажали на фамилию —
   браузер перешёл к её карточке ниже. Работает без JavaScript. */
.worker-index {
  margin: 0 0 12px;
  padding: 0 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--accent-soft, transparent);
}

.worker-index > summary {
  cursor: pointer;
  padding: 10px 0;
  font-weight: 600;
  color: var(--text);
  list-style: none;
}

.worker-index > summary::-webkit-details-marker {
  display: none;
}

.worker-index > summary::before {
  content: "\25B8";
  display: inline-block;
  width: 1.1em;
  color: var(--accent-active);
}

.worker-index[open] > summary::before {
  content: "\25BE";
}

.worker-index-list {
  margin: 0 0 12px;
  padding-left: 24px;
  columns: 2;
}

.worker-index-list li {
  margin: 3px 0;
  break-inside: avoid;
}

.worker-index-list a {
  text-decoration: none;
}

.worker-index-list a:hover {
  text-decoration: underline;
}

/* Якорь карточки не должен прятаться под липкой шапкой страницы. */
.worker-card {
  scroll-margin-top: calc(var(--topbar-h, 84px) + 10px);
}
