/*
  style.css — визуальный язык «Зачёт» (этап 3 «Веб-скелет», волна 2б).
  Источники канона:
    - docs/zachet/юикс-требования.md, §3 «Адаптивность», §4 «Визуальный язык»
      (палитра §4.1/4.2, подсветка расхождений §4.3, типографика §4.4).
    - Палитра/акцент унаследованы у scripts/wb_cs_flow/index.html (синий
      #3B5BDB, светлый фон #EEF1F5) — чтобы два внутренних инструмента
      одного бизнеса не выглядели продуктами разных компаний.

  ПРАВИЛО (юикс-требования.md §4, критерий приёмки №12): хардкод цвета,
  размера шрифта или отступа МИМО токена --zc-* в шаблонах/компонентах
  запрещён — весь дизайн идёт через custom properties этого файла.

  Брейкпоинты — mobile-first (базовые правила без media query — для S,
  затем min-width для M/L). Причина порядка объяснена в юикс-требования.md
  §3.1: при обратном порядке любое незакрытое переопределение ломает именно
  телефон, то есть главного пользователя (Эльвира).
    S — 320-767px  (базовые правила, без media query)
    M — 768-1199px (min-width: 768px)
    L — >=1200px   (min-width: 1200px)
  Доп. точка 480px — «сверхкомпактный» режим внутри S (подписи нижней
  навигации скрываются).
*/

/* ============================================================ ТОКЕНЫ === */
:root{
  /* поверхности */
  --zc-bg:          #EEF1F5;
  --zc-surface:     #FFFFFF;
  --zc-surface-2:   #F6F8FB;
  --zc-surface-3:   #E8ECF2;

  /* текст */
  --zc-ink:         #1B2432;
  --zc-ink-muted:   #5B6472;
  --zc-ink-faint:   #8A93A2;
  --zc-ink-invert:  #FFFFFF;

  /* линии */
  --zc-line:        #CED5DF;
  --zc-line-soft:   #E2E7EE;
  --zc-line-strong: #A9B2BF;

  /* акцент */
  --zc-accent:        #3B5BDB;
  --zc-accent-hover:  #314CC0;
  --zc-accent-active: #2A42A6;
  --zc-accent-soft:   #E5EAFB;
  --zc-focus:         #1B4DFF;

  /* семантика действий / расхождений */
  --zc-success:      #0B7A54;  --zc-success-bg:  #E6F4EE;  --zc-success-line: #0B7A54;
  --zc-warning:      #8A5300;  --zc-warning-bg:  #FCF2DC;  --zc-warning-line: #C98A0E;
  --zc-danger:       #A3231B;  --zc-danger-bg:   #FBE9E7;  --zc-danger-line:  #C7362B;
  --zc-neutral:      #5B6472;  --zc-neutral-bg:  #F2F4F7;  --zc-neutral-line: #A9B2BF;
  --zc-info:         #1C4E9C;  --zc-info-bg:     #E7EFFA;  --zc-info-line:    #3B5BDB;

  /* типографика — системный стек, без веб-шрифтов (юикс-требования §4.4) */
  --zc-font-ui:   system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --zc-font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;

  --zc-t-display-size: 34px; --zc-t-display-lh: 40px; --zc-t-display-w: 600;
  --zc-t-h1-size:      22px; --zc-t-h1-lh:      28px; --zc-t-h1-w:      600;
  --zc-t-h2-size:      18px; --zc-t-h2-lh:      24px; --zc-t-h2-w:      600;
  --zc-t-body-size:    16px; --zc-t-body-lh:    24px; --zc-t-body-w:    400;
  --zc-t-small-size:   14px; --zc-t-small-lh:   20px; --zc-t-small-w:   400;
  --zc-t-caption-size: 13px; --zc-t-caption-lh: 18px; --zc-t-caption-w: 400;
  --zc-t-micro-size:   12px; --zc-t-micro-lh:   16px; --zc-t-micro-w:   500;

  /* раскладка — поля страницы/промежуток по точкам (юикс-требования §3.1) */
  --zc-page-pad:  16px;
  --zc-gap:       12px;
  --zc-radius:    10px;
  --zc-radius-lg: 16px;

  --zc-topnav-h:    64px;
  --zc-bottomnav-h: 56px;
  --zc-safe-bottom: env(safe-area-inset-bottom, 0px);
}

@media (min-width: 768px){
  :root{ --zc-page-pad: 24px; --zc-gap: 16px; }
}
@media (min-width: 1200px){
  :root{ --zc-page-pad: 32px; --zc-gap: 24px; }
}

/* тёмная тема НЕ реализуется в MVP (юикс-требования §4.1/§9) — токены уже
   объявлены так, что её добавление — одна секция ниже без правки компонентов. */
@media (prefers-color-scheme: dark){
  :root{ /* зарезервировано — намеренно пусто на этом этапе */ }
}

/* ============================================================= RESET === */
*, *::before, *::after{ box-sizing: border-box; }
html, body{
  margin: 0; padding: 0;
  max-width: 100%;
  overflow-x: hidden;               /* критерий приёмки: НЕТ горизонтальной прокрутки страницы */
}
body{
  background: var(--zc-bg);
  color: var(--zc-ink);
  font-family: var(--zc-font-ui);
  font-size: var(--zc-t-body-size);
  line-height: var(--zc-t-body-lh);
  font-weight: var(--zc-t-body-w);
  -webkit-text-size-adjust: 100%;
  padding-bottom: calc(var(--zc-bottomnav-h) + var(--zc-safe-bottom));
}
@media (min-width: 1200px){
  body{ padding-bottom: 0; }
}
img, svg{ max-width: 100%; height: auto; }
a{ color: var(--zc-accent); text-decoration: none; }
a:hover{ text-decoration: underline; }
h1, h2, h3, p, ul, ol{ margin: 0 0 var(--zc-gap) 0; }
ul, ol{ padding-left: 1.25em; }
button{ font-family: inherit; }

/* «Перейти к содержимому» — первая цель Tab на КАЖДОЙ странице, то есть
   единственный элемент интерфейса, который человек на клавиатуре встречает
   раньше всего остального. Раньше высота была 40px (24px строки + 8+8
   padding) — ниже минимума 44px (юикс-требования §3.5/§10.1 №2). Минимум
   задан явно через min-height + inline-flex, а не подгонкой padding: padding
   зависит от line-height темы, min-height — нет. */
.zc-skip-link{
  position: absolute; left: -9999px; top: 0;
  display: inline-flex; align-items: center;
  min-height: 44px;
  background: var(--zc-accent); color: var(--zc-ink-invert);
  padding: 8px 12px; border-radius: var(--zc-radius);
  z-index: 100;
}
.zc-skip-link:focus{ left: 8px; top: 8px; }

:focus-visible{ outline: 2px solid var(--zc-focus); outline-offset: 2px; }

/* Базовый тач-таргет для ЛЮБОГО <details>/<summary> в системе — без стилей
   браузер рисует inline-block ~20-24px, ниже минимума (юикс-требования
   §3.5/§10.1 №2). Более специфичные правила (.zc-confirm, .zc-bottomnav__item,
   .gd-filters) переопределяют это по мере надобности — селектор здесь
   намеренно низкой специфичности. */
details > summary{
  min-height: 44px;
  display: flex; align-items: center;
  padding: 8px 4px;
  cursor: pointer;
  list-style: none;
}
details > summary::-webkit-details-marker{ display: none; }

/* =========================================================== LAYOUT ==== */
.zc-container{
  max-width: 1200px;
  margin: 0 auto;
  padding: var(--zc-gap) var(--zc-page-pad);
  width: 100%;
}

/* ======================================================= TOPNAV (L) ==== */
.zc-topnav{
  display: none;                    /* показывается только на L (см. media ниже) */
  background: var(--zc-surface);
  border-bottom: 1px solid var(--zc-line-soft);
}
.zc-topnav__inner{
  max-width: 1200px; margin: 0 auto;
  height: var(--zc-topnav-h);
  padding: 0 var(--zc-page-pad);
  display: flex; align-items: center; gap: 24px;
}
.zc-topnav__brand{
  font-size: var(--zc-t-h2-size); font-weight: var(--zc-t-h2-w);
  color: var(--zc-ink);
}
.zc-topnav__brand:hover{ text-decoration: none; }
.zc-topnav__links{ display: flex; align-items: center; gap: 8px; flex: 1; }
.zc-topnav__link{
  color: var(--zc-ink-muted);
  font-weight: 600;
  font-size: var(--zc-t-small-size);
  padding: 0 4px;
  height: var(--zc-topnav-h);
  display: inline-flex; align-items: center;
  border-top: 2px solid transparent;   /* активный пункт — не только цветом */
}
.zc-topnav__link:hover{ color: var(--zc-ink); text-decoration: none; }
.zc-topnav__link.is-active{
  color: var(--zc-accent);
  border-top-color: var(--zc-accent);
}
.zc-topnav__profile{ display: flex; align-items: center; gap: 12px; }
.zc-topnav__user{ font-size: var(--zc-t-small-size); color: var(--zc-ink-muted); }
.zc-topnav__logout-form{ display: inline; }

@media (min-width: 1200px){
  .zc-topnav{ display: block; }
}

/* =================================================== BOTTOMNAV (S/M) === */
.zc-bottomnav{
  position: fixed; left: 0; right: 0; bottom: 0;
  height: calc(var(--zc-bottomnav-h) + var(--zc-safe-bottom));
  padding-bottom: var(--zc-safe-bottom);
  background: var(--zc-surface);
  border-top: 1px solid var(--zc-line-soft);
  /* 4 слота (Главная/Товары/Склады/Ещё) — акцентная «+» запрещена в этом
     этапе (создание документа появится в Этапе 4), см. base.html. Пятый
     слот и .zc-bottomnav__plus вернутся вместе с формой документа. */
  display: grid; grid-template-columns: repeat(4, 1fr);
  align-items: stretch;
  z-index: 30;
}
.zc-bottomnav__item{
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px;
  color: var(--zc-ink-muted);
  height: var(--zc-bottomnav-h);
  border-top: 2px solid transparent;
  min-height: 44px;
  list-style: none;
  cursor: pointer;
}
.zc-bottomnav__item:hover{ text-decoration: none; }
.zc-bottomnav__item.is-active{ color: var(--zc-accent); border-top-color: var(--zc-accent); }
.zc-bottomnav__icon{ font-size: 20px; line-height: 1; }
.zc-bottomnav__label{ font-size: var(--zc-t-micro-size); font-weight: var(--zc-t-micro-w); }
/* .zc-bottomnav__item--accent / .zc-bottomnav__plus (акцентная «+», 5-й слот)
   удалены вместе с кнопкой в base.html — план прямо запрещает «создать
   документ» на этом этапе (ложное ожидание у Эльвиры, что документ можно
   завести уже сейчас). Вернутся вместе с формой документа в Этапе 4. */

/* «Ещё» — нативный <details>/<summary>, работает БЕЗ единой строки JS */
.zc-bottomnav__more{ display: contents; }
.zc-bottomnav__more > summary{
  list-style: none;
}
.zc-bottomnav__more > summary::-webkit-details-marker{ display: none; }
.zc-bottomnav__sheet{
  position: fixed; left: 0; right: 0; bottom: 0;
  display: none;
  background: var(--zc-surface);
  border-top-left-radius: var(--zc-radius-lg);
  border-top-right-radius: var(--zc-radius-lg);
  box-shadow: 0 -4px 24px rgba(20, 30, 45, .18);
  padding: 12px 16px calc(16px + var(--zc-bottomnav-h) + var(--zc-safe-bottom));
  z-index: 40;
}
.zc-bottomnav__more[open] .zc-bottomnav__sheet{ display: flex; flex-direction: column; }
.zc-bottomnav__more[open]::before{
  content: ""; position: fixed; inset: 0;
  background: rgba(20, 30, 45, .35);
  z-index: 35;
}
.zc-bottomnav__sheet-link{
  display: block; padding: 14px 8px;
  font-size: var(--zc-t-body-size);
  color: var(--zc-ink);
  border-bottom: 1px solid var(--zc-line-soft);
  min-height: 44px;
  text-align: left; background: none; border-left: 0; border-right: 0; border-top: 0;
  width: 100%;
}
.zc-bottomnav__sheet-link:hover{ text-decoration: none; background: var(--zc-surface-2); }
.zc-bottomnav__sheet-link:last-child{ border-bottom: 0; }
.zc-bottomnav__sheet-form{ margin: 0; }
.zc-bottomnav__sheet-link--btn{ font: inherit; cursor: pointer; }

@media (max-width: 479px){
  .zc-bottomnav__label{ display: none; }   /* сверхкомпактный режим: только глифы */
}
@media (min-width: 1200px){
  .zc-bottomnav{ display: none; }
}

/* ============================================================ FOOTER === */
.zc-footer{
  border-top: 1px solid var(--zc-line-soft);
  color: var(--zc-ink-faint);
  font-size: var(--zc-t-caption-size);
}
.zc-footer__inner{ padding-top: var(--zc-gap); padding-bottom: var(--zc-gap); }

/* ========================================================= TYPOGRAPHY == */
.zc-h1{ font-size: var(--zc-t-h1-size); line-height: var(--zc-t-h1-lh); font-weight: var(--zc-t-h1-w); margin: 0 0 var(--zc-gap); }
.zc-h2{ font-size: var(--zc-t-h2-size); line-height: var(--zc-t-h2-lh); font-weight: var(--zc-t-h2-w); margin: 0 0 8px; }
.zc-display{ font-size: var(--zc-t-display-size); line-height: var(--zc-t-display-lh); font-weight: var(--zc-t-display-w); }
.zc-small{ font-size: var(--zc-t-small-size); line-height: var(--zc-t-small-lh); }
.zc-caption{ font-size: var(--zc-t-caption-size); line-height: var(--zc-t-caption-lh); color: var(--zc-ink-muted); }
.zc-micro{ font-size: var(--zc-t-micro-size); line-height: var(--zc-t-micro-lh); font-weight: var(--zc-t-micro-w); letter-spacing: .04em; text-transform: uppercase; }
.zc-ink-muted{ color: var(--zc-ink-muted); }
.zc-ink-faint{ color: var(--zc-ink-faint); }
.zc-mono{
  font-family: var(--zc-font-mono);
  font-variant-numeric: tabular-nums;
  /* длинные непрерывные строки без пробелов (пути файлов, sku_id с
     подчёркиваниями, id локаций WB:CENTRAL/KOLEDINO) иначе не находят точку
     разрыва и на 375px вылезают за край, обрезанные body{overflow-x:hidden}
     — это НЕ горизонтальная прокрутка страницы (тело её не даёт), но
     реальная визуальная порча текста; overflow-wrap:anywhere разрешает
     разрыв в любом месте токена, когда естественных пробелов не хватает. */
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* ============================================================= CARD ==== */
.zc-card{
  background: var(--zc-surface);
  border: 1px solid var(--zc-line-soft);
  border-radius: var(--zc-radius);
  padding: var(--zc-gap);
  margin-bottom: var(--zc-gap);
}

/* ============================================================ BUTTONS == */
.zc-btn{
  display: inline-flex; align-items: center; justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 16px;
  border-radius: var(--zc-radius);
  border: 1px solid transparent;
  font-size: var(--zc-t-body-size);
  font-weight: 600;
  cursor: pointer;
  background: var(--zc-accent);
  color: var(--zc-ink-invert);
}
.zc-btn:hover{ background: var(--zc-accent-hover); text-decoration: none; color: var(--zc-ink-invert); }
.zc-btn:active{ background: var(--zc-accent-active); }
.zc-btn--ghost{
  background: transparent; color: var(--zc-accent);
  border-color: var(--zc-line);
}
.zc-btn--ghost:hover{ background: var(--zc-accent-soft); color: var(--zc-accent-hover); }
/* «Кнопка (вторичная, в ряду)» — юикс-требования §4.5, таблица высот: 44px на S/M
   (тач), 36px только на L (курсор). Раньше было плоских 36px везде — это и давало
   промахи на пагинации, «Применить» на карточке склада и т.д. на телефоне. */
.zc-btn--small{ min-height: 44px; padding: 0 12px; font-size: var(--zc-t-small-size); }
@media (min-width: 1200px){
  .zc-btn--small{ min-height: 36px; }
}
.zc-btn--block{ width: 100%; }
/* Модификаторы кнопки живут РЯДОМ с базовым .zc-btn и только здесь. До
   03.08.2026 три из них (--secondary/--danger/--danger-confirm) были объявлены
   инлайном в templates/users_extra_head.html: разметка `class="zc-btn
   zc-btn--secondary"` на любом другом экране давала обычную синюю кнопку —
   класс есть, стилей нет. Ровно этот дефект приёмка нашла на плитках отчётов;
   семейство кнопок закрыто здесь, чтобы он не повторился на формах этапа 4. */
.zc-btn--secondary{
  background: var(--zc-surface); color: var(--zc-ink); border: 1px solid var(--zc-line);
}
.zc-btn--secondary:hover{ background: var(--zc-surface-2); color: var(--zc-ink); }
.zc-btn--danger{
  background: var(--zc-surface); color: var(--zc-danger); border: 1px solid var(--zc-danger-line);
}
.zc-btn--danger:hover{ background: var(--zc-danger-bg); color: var(--zc-danger); }
.zc-btn--danger-confirm{
  background: var(--zc-danger-line); color: var(--zc-ink-invert); border-color: var(--zc-danger-line);
}
.zc-btn--danger-confirm:hover{ background: var(--zc-danger); color: var(--zc-ink-invert); }

/* Ссылка «← Назад» (zc-caption, под шапкой раздела) — сама по себе это 13/18
   текст без отступов, кликабельная область 15-19px. Класс расширяет тач-таргет
   до 44px по высоте, не трогая типографику (юикс-требования §3.5). */
.zc-back-link{
  display: inline-flex; align-items: center;
  min-height: 44px;
  padding: 4px 0;
}

/* Инлайн-текстовая ссылка с безопасным тач-таргетом — тот же приём, что и
   .zc-back-link (текстовая ссылка, не блочная кнопка), но без семантики
   «назад»: используется там, где ссылка не «шапка раздела», а часть текста
   или ячейки таблицы (баннер дублей контрагента, столбец «Наименование» в
   таблице контрагентов, «Отменить и вернуться к списку» в форме).
   Найдено 03.08.2026 мобильным сьютом: класс стоял в разметке четырёх мест,
   но НИ ОДНОГО правила для него в стилях не было — ссылка «Отменить и
   вернуться к списку» рисовалась 15px вместо честных 44px (юикс-требования
   §10.1, критерий №2). */
.zc-link{
  display: inline-flex; align-items: center;
  min-height: 44px;
  padding: 4px 0;
}

/* ================================================== ИНЛАЙН-ПОДТВЕРЖДЕНИЕ === */
/* Необратимое действие раскрывается на месте, без модалки (юикс-требования
   §5.7: «модалка — не место для формы») — нативный <details>/<summary>, без
   единой строчки JS.
   Переехал сюда из templates/users_extra_head.html 03.08.2026. Раньше здесь
   стоял только КОММЕНТАРИЙ «класс определён в шаблоне раздела» — то есть
   общий файл стилей ссылался на правила, которых в нём нет: ровно та связь,
   из-за которой на этапе 4 удаление документа получило бы <summary> без
   тач-таргета. */
.zc-confirm{
  margin-top: 8px;
  padding: var(--zc-gap);
  border-radius: var(--zc-radius);
  background: var(--zc-surface-2);
  border: 1px solid var(--zc-line-soft);
}
/* <summary> без явных размеров — нативный inline ~24px высотой, вдвое ниже
   минимального тач-таргета (юикс-требования §10.1, критерий №2) — и это на
   необратимых действиях (сброс пароля, деактивация), где промах на телефоне
   дорого стоит. display:flex + min-height дают честные 44px, не трогая
   типографику/окраску блока. */
.zc-confirm > summary{
  display: flex; align-items: center; gap: 6px;
  min-height: 44px;
  padding: 10px 4px;
  cursor: pointer;
  font-weight: 600;
  list-style: none;
}
.zc-confirm > summary::-webkit-details-marker{ display: none; }
.zc-confirm > summary::before{ content: "▸"; font-size: 12px; color: var(--zc-ink-muted); }
.zc-confirm[open] > summary::before{ content: "▾"; }
.zc-confirm__text{ color: var(--zc-ink-muted); margin: 8px 0; }

/* ============================================== ФЛАЖОК В СТРОКЕ (44px) === */
/* «Показать деактивированных / архивные / служебные» — один и тот же по смыслу
   переключатель на четырёх экранах, и до 03.08.2026 он был сделан ЧЕТЫРЬМЯ
   разными способами: .gd-check с честными 44px на /goods/list, голый <label>
   на складах (флажок растягивался на всю ширину правилом input{width:100%}) и
   <label> с инлайновым style="width:auto;min-height:auto" на контрагентах —
   там тач-таргет схлопывался до 24px.

   Общий компонент: <label class="zc-check"><input type="checkbox" …> Текст
   </label>. Высота строки 44px берёт на себя ЛЕЙБЛ (кликабельна вся строка, а
   не 16px квадратика), а сам <input> освобождается от общего правила формы
   input{width:100%; min-height:44px}, которое флажку не подходит. */
.zc-check{
  display: flex; align-items: center; gap: 8px;
  min-height: 44px;
  cursor: pointer;
}
.zc-check input{
  width: auto; min-height: auto;
  flex: 0 0 auto;
  margin: 0;
}

/* ================================================== ИНЛАЙН-ФОРМА В РЯД === */
/* Ряд полей + кнопка, переносится на узком экране. Поля тянутся, кнопка
   прижата к их нижнему краю. Переехал сюда из users_extra_head.html, потому
   что класс с общим префиксом `zc-` использован на двух экранах раздела и
   заведомо понадобится формам этапа 4.
   Близкие по смыслу .gc-inline-form (goods_categories), .zcw-filters-row и
   .zcw-goods-filters (склады) ОСТАВЛЕНЫ инлайн сознательно: каждый из них
   живёт ровно на одном экране и отличается базисом поля. Новую форму писать
   на .zc-inline-form, а не копировать их. */
.zc-inline-form{ display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-end; }
.zc-inline-form .zc-field{ flex: 1 1 200px; margin-bottom: 0; }

/* Мелкая поясняющая строка под полем/блоком. */
.zc-muted-note{ color: var(--zc-ink-muted); font-size: var(--zc-t-caption-size); margin: 4px 0 0; }

/* ============================================================= FORMS === */
/* Минимальный размер шрифта в полях ввода — 16px на ЛЮБОМ размере экрана.
   Требование безусловное (юикс-требования §4.4): меньший шрифт заставляет
   Safari iOS зумить страницу при фокусе и ломает липкую вёрстку. */
input, select, textarea{
  font-family: var(--zc-font-ui);
  font-size: var(--zc-t-body-size);
  line-height: var(--zc-t-body-lh);
  color: var(--zc-ink);
  background: var(--zc-surface);
  border: 1px solid var(--zc-line);
  border-radius: var(--zc-radius);
  padding: 10px 12px;
  min-height: 44px;
  width: 100%;
}
input:focus, select:focus, textarea:focus{
  border-color: var(--zc-line-strong);
  outline: 2px solid var(--zc-focus);
  outline-offset: 1px;
}
label{ display: block; font-size: var(--zc-t-caption-size); color: var(--zc-ink-muted); margin-bottom: 4px; }
.zc-field{ margin-bottom: var(--zc-gap); }

/* ============================================================= BADGES == */
/* Подсветка расхождений — юикс-требования §4.3. ЧЕТЫРЕ независимых носителя
   признака на каждое состояние: оттенок, глиф, знак числа, стиль левой
   границы — цвет НИКОГДА единственный носитель смысла (критично для
   дейтеранопии/протанопии и ч/б печати). */
.zc-badge{
  display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--zc-font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--zc-t-small-size);
  padding: 2px 8px;
  border-radius: 999px;
  border-left: 4px solid;
}
.zc-badge--ok{       color: var(--zc-success); background: var(--zc-success-bg); border-left-style: solid;   border-left-color: var(--zc-success-line); }
.zc-badge--surplus{  color: var(--zc-warning); background: var(--zc-warning-bg); border-left-style: dashed;  border-left-color: var(--zc-warning-line); }
.zc-badge--shortage{ color: var(--zc-danger);  background: var(--zc-danger-bg);  border-left-style: double;  border-left-width: 5px; border-left-color: var(--zc-danger-line); }
.zc-badge--unknown{  color: var(--zc-neutral); background: var(--zc-neutral-bg); border-left-style: dotted; border-left-color: var(--zc-neutral-line); }
/* Активность записи (пользователь/контрагент/склад — везде одна пара
   состояний). Переехали из templates/users_extra_head.html 03.08.2026:
   модификатор семейства обязан лежать там же, где базовый .zc-badge. */
.zc-badge--active{
  color: var(--zc-success); background: var(--zc-success-bg);
  border-left-style: solid; border-left-color: var(--zc-success-line);
}
.zc-badge--inactive{
  color: var(--zc-neutral); background: var(--zc-neutral-bg);
  border-left-style: dotted; border-left-color: var(--zc-neutral-line);
}

/* ============================================================= ALERTS === */
/* Баннер результата/ошибки над содержимым страницы. Четыре тона —
   info/success/warning/error, каждый несёт признак не только цветом, но и
   глифом в разметке (юикс-требования §4.3).
   Переехал сюда 03.08.2026 из templates/users_extra_head.html; заодно
   поглотил .zc-login__error из login.html — это была ПОБУКВЕННАЯ копия
   .zc-alert + .zc-alert--error под другим именем. Две копии одного баннера в
   двух шаблонах — то же самое, что плитки отчётов без стилей, только
   наоборот: стили есть, но каждый экран носит свои. */
.zc-alert{
  display: flex; gap: 10px; align-items: flex-start;
  border-left: 4px solid;
  border-radius: var(--zc-radius);
  padding: 12px var(--zc-gap);
  margin-bottom: var(--zc-gap);
  font-size: var(--zc-t-small-size);
}
.zc-alert__glyph{ font-size: 18px; line-height: var(--zc-t-body-lh); }
.zc-alert__body{ min-width: 0; }
.zc-alert__title{
  font-size: var(--zc-t-h2-size); font-weight: 600; margin: 0 0 4px;
}
.zc-alert--info{
  color: var(--zc-info); background: var(--zc-info-bg); border-color: var(--zc-info-line);
}
.zc-alert--success{
  color: var(--zc-success); background: var(--zc-success-bg); border-color: var(--zc-success-line);
}
.zc-alert--warning{
  color: var(--zc-warning); background: var(--zc-warning-bg); border-color: var(--zc-warning-line);
}
.zc-alert--error{
  color: var(--zc-danger); background: var(--zc-danger-bg); border-color: var(--zc-danger-line);
}

/* ============================================================== TILES === */
/* Сетка крупных ссылок-плиток: разделы на дашборде, отчёты на /reports.
   Ровно тот компонент, на котором сломалась приёмка 03.08.2026: разметку с
   классами .zc-dash__tile скопировали в reports_placeholder.html, а правила
   остались инлайном в <style> дашборда — и пять плиток отчётов вышли высотой
   19px вплотную друг к другу вместо 88px с промежутком. Класс переименован из
   .zc-dash__tile в .zc-tile: `__dash` в имени говорил «принадлежит дашборду»
   и провоцировал ровно ту копипасту, которая случилась.
   2 колонки на S, 3 на M, 5 на L. */
.zc-tiles{
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--zc-gap);
}
.zc-tile{
  display: flex; align-items: center; justify-content: center;
  min-height: 88px; text-align: center; padding: 8px;
  background: var(--zc-surface); border: 1px solid var(--zc-line-soft);
  border-radius: var(--zc-radius);
  font-weight: 600; color: var(--zc-ink);
}
.zc-tile:hover{ text-decoration: none; background: var(--zc-surface-2); }
@media (min-width: 768px){
  .zc-tiles{ grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 1200px){
  .zc-tiles{ grid-template-columns: repeat(5, 1fr); }
  .zc-tile{ min-height: 104px; }
}

/* ============================================== CARD-LIST (механизм A) == */
/* «Строка становится карточкой» — справочники/списки на S/M (юикс-требования
   §3.3). Роли: заголовок / ключ / значение. Используется будущими разделами
   (Номенклатура, Склады, Контрагенты, Пользователи) — готово заранее. */
.zc-rowcard{
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px;
  padding: 14px 4px;
  border-bottom: 1px solid var(--zc-line-soft);
  min-height: 64px;
}
.zc-rowcard:last-child{ border-bottom: 0; }
.zc-rowcard__main{ min-width: 0; }
.zc-rowcard__title{
  font-size: var(--zc-t-h2-size); font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.zc-rowcard__key{
  font-size: var(--zc-t-caption-size); color: var(--zc-ink-muted);
  font-family: var(--zc-font-mono);
}
.zc-rowcard__value{
  font-size: var(--zc-t-h2-size);
  font-family: var(--zc-font-mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ============================================== ФОТО ТОВАРА (миниатюра) = */
/* Номенклатура WB здесь — семь артикулов подряд, отличающихся одной цифрой
   (`WB_краскопульт_макита_2/3/6`) — фото снижает риск перепутать позицию при
   приёмке. Размер контейнера ФИКСИРОВАН заранее (aspect-ratio, не зависит от
   реального размера файла) — страница не должна прыгать, пока картинки
   догружаются на плохой связи (юикс-требования §3, §9.1 «скелетоны загрузки»
   не делаем, но геометрия резервируется всегда).

   Соотношение сторон 3:4 подобрано под ОБА пресета WB, которые реально
   используются (tm 75x100, c246x328 246x328) — один aspect-ratio годится и
   миниатюре списка, и картинке карточки.

   «Нет фото» и «фото не загрузилось» ВИЗУАЛЬНО ОДИНАКОВЫ и НАМЕРЕННО: глиф
   лежит в разметке всегда, <img> (если ссылка вообще есть) кладётся поверх
   него абсолютным позиционированием. Успешная загрузка перекрывает глиф
   картинкой. Ссылка на WB может протухнуть (смена CDN, потеря карточки) —
   это тоже разновидность «фото нет», а не повод показывать сломанную иконку
   браузера или пустое место: единственный по-настоящему надёжный способ
   узнать, что <img> не загрузился, — браузерное событие `error`, поэтому
   у него один инлайновый обработчик `onerror="this.remove()"` (без
   framework/внешнего файла) — при ошибке загрузки просто убирает <img> из
   DOM, глиф проступает обратно. Иллюстраций тут нет (юикс-требования §9.1) —
   только этот глиф + подпись (у крупного варианта). */
.zc-thumb{
  position: relative;
  flex: 0 0 auto;
  width: 40px; aspect-ratio: 3 / 4;
  border-radius: var(--zc-radius);
  background: var(--zc-surface-2);
  border: 1px solid var(--zc-line-soft);
  overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px;
  color: var(--zc-ink-faint);
}
.zc-thumb svg{ width: 16px; height: 16px; flex: 0 0 auto; }
.zc-thumb img{
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  background: var(--zc-surface-2);
}
.zc-thumb__label{
  display: none;
  font-size: var(--zc-t-micro-size); color: var(--zc-ink-faint); text-align: center;
  padding: 0 4px;
}
.zc-thumb--lg{ width: 128px; }
.zc-thumb--lg svg{ width: 30px; height: 30px; }
.zc-thumb--lg .zc-thumb__label{ display: block; }

/* ==================================================== TABLE (карточки по умолчанию) = */
/* ПЕРЕВЁРНУТО 03.08.2026 (разбор трёх однотипных дефектов за один день:
   карточка товара, четыре заглушки документов, карточка контрагента — во
   всех трёх таблица на телефоне листалась вбок, потому что автор шаблона не
   вспомнил добавить явный класс карточного режима). Тот же принцип, что у
   guard'а маршрутов (routes/__init__.py, zachet_web_guard): новое ЗАКРЫТО по
   умолчанию, разрешение — явное. Здесь роль «маршрута» у любой таблицы:
   безопасное поведение (карточки на S/M) — умолчание для ЛЮБОГО <table>,
   даже вообще без класса .zc-table; горизонтальный скролл — исключение,
   которое теперь нужно включать явно (см. .zc-table--scroll ниже), а не
   помнить включить безопасность.

   Правила ниже разбиты на две части:
   1) .zc-table — чисто косметика (границы, отступы, фон шапки), которая
      не влияет на «скроллится вбок / стала карточкой» и одинакова что для
      обычной таблицы, что для карточной раскладки.
   2) @media (max-width: 1199px) — структурная подмена: ЛЮБАЯ таблица (тег
      <table>, класс не нужен) превращается в список карточек, шапка (thead)
      прячется, её роль берёт на себя атрибут data-th на каждой <td>. */
.zc-table-wrap{ overflow-x: auto; max-width: 100%; }
.zc-table{ border-collapse: collapse; width: 100%; }
.zc-table th, .zc-table td{
  padding: 8px 12px;
  text-align: left;
  border-bottom: 1px solid var(--zc-line-soft);
  font-size: var(--zc-t-small-size);
}
.zc-table th{
  background: var(--zc-surface-2);
  font-weight: 600; color: var(--zc-ink-muted);
}
.zc-table td.zc-mono, .zc-table th.zc-mono{ font-variant-numeric: tabular-nums; }

@media (max-width: 1199px){
  thead{ display: none; }
  table, tbody, tr, td{ display: block; width: 100%; }
  tr{
    border: 1px solid var(--zc-line-soft);
    border-radius: var(--zc-radius);
    padding: 10px 12px;
    margin-bottom: var(--zc-gap);
  }
  tr:last-child{ margin-bottom: 0; }
  td{
    border-bottom: 0;
    padding: 8px 0;
    white-space: normal;
    position: static;
    background: none;
  }
  /* Подпись колонки в карточном режиме — не декоративная мелочь, а
     единственный заголовок, который у ячейки остался (thead выше скрыт).
     Если data-th на <td> ЕСТЬ — подпись выводится как обычно. Если ЗАБЫТА —
     дефект не должен молча слиться с соседними ячейками (как забытая подпись
     схлопывалась бы в пустоту при обычном attr()); вместо неё — заметная
     плашка тревожного цвета: дефект виден на первом же просмотре страницы на
     телефоне, а не только при чтении HTML построчно. */
  td[data-th]::before{
    content: attr(data-th);
    display: block;
    font-size: var(--zc-t-caption-size);
    color: var(--zc-ink-muted);
    margin-bottom: 4px;
  }
  td:not([data-th])::before{
    content: "⚠ нет подписи столбца (забыт data-th)";
    display: block;
    font-size: var(--zc-t-caption-size);
    font-weight: 600;
    color: var(--zc-danger);
    background: var(--zc-danger-bg);
    padding: 2px 6px;
    border-radius: 4px;
    margin-bottom: 4px;
  }
  /* Ссылка внутри свёрнутой в карточку строки (например «Товар» в журнале
     движений) — тот же тач-таргет 44px, что у остального интерфейса на S/M.
     Найдено 03.08.2026: без этого правила ссылка на sku_id рисовалась
     42×16px, вдвое ниже требуемого. */
  td a{
    display: inline-flex; align-items: center;
    min-height: 44px; min-width: 44px;
  }
}

/* ============================================ TABLE SCROLL (явно, только L) = */
/* Горизонтальная прокрутка — законное исключение ТОЛЬКО для таблиц с большим
   числом колонок, которые на широком экране читать построчно (карточками)
   хуже, чем скроллом (отчёты этапа 7, ABC-анализ, длинный журнал). Требование
   безусловно: «горизонтальная прокрутка таблицы допустима только на
   компьютере» (юикс-требования §3.3) — поэтому весь блок целиком внутри
   min-width:1200px и НИЧЕГО не меняет на S/M: там, как у любой другой
   таблицы, работает карточный блок выше. Включается явно:
   <table class="zc-table zc-table--scroll"> внутри <div class="zc-table-wrap">. */
@media (min-width: 1200px){
  .zc-table--scroll{ min-width: 480px; }
  .zc-table--scroll th, .zc-table--scroll td{ white-space: nowrap; }
  .zc-table--scroll th{ position: sticky; top: 0; }
  .zc-table--scroll td:first-child, .zc-table--scroll th:first-child{
    position: sticky; left: 0;
    background: inherit;
  }
}

/* ==================================================== PLACEHOLDER PAGE = */
.zc-placeholder{ padding: 8px 0; }
.zc-placeholder__title{ font-size: var(--zc-t-h1-size); font-weight: var(--zc-t-h1-w); margin: 0 0 8px; }
.zc-placeholder__text{ color: var(--zc-ink-muted); margin: 0 0 var(--zc-gap); }
.zc-placeholder__error{ color: var(--zc-danger); }
.zc-placeholder__routes{ margin: 0; padding-left: 1.1em; }
.zc-placeholder__routes li{ margin-bottom: 4px; font-size: var(--zc-t-small-size); }
