/* Карточка магазина — вёрстка по макету `docs/designe/SellSaver Admin —
   Магазин`. Две колонки, боковая липнет к верху при прокрутке.

   Токены (`--panel`, `--sunken`, `--rowline`, `--ozon` и прочие) и шрифты
   (`InterPanel`, `PTSerifPanel`) объявлены в `admin.css` — здесь только
   геометрия и композиция карточки, своих цветов файл не заводит. */

.shopcard { display: flex; flex-direction: column; gap: var(--sp-gutter); }

/* ── Шапка ─────────────────────────────────────────────────────────────── */

.shopcard__head { display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-gutter); flex-wrap: wrap; }
.shopcard__title { flex: 1; min-width: 340px; display: flex; flex-direction: column; gap: var(--sp-item); }
.shopcard__name { display: flex; align-items: center; gap: var(--sp-block); flex-wrap: wrap; }

/* Плитка маркетплейса — квадрат в фирменном цвете площадки, а не подпись
   мышиного цвета: магазин опознаётся по ней раньше, чем прочитано название.
   Цвет приходит модификатором (`--ozon`/`--wb`/`--yandex`), потому что
   `Marketplace` — закрытый список из трёх значений. */
.shopcard__mp { width: var(--mp-tile); height: var(--mp-tile); flex: 0 0 var(--mp-tile);
  border-radius: 13px;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-hint); font-weight: 700; letter-spacing: .02em; color: #fff;
  background: var(--faint); text-transform: uppercase; }
.shopcard__mp--ozon { background: var(--ozon); }
.shopcard__mp--wb { background: var(--wb); }
/* Жёлтый Яндекса — единственный из трёх, на котором белый текст не читается;
   и код у него вдвое длиннее прочих, поэтому кегль мельче. */
.shopcard__mp--yandex { background: var(--yandex); color: #1A1A1A; font-size: var(--fs-tag); }

/* Имя магазина — общий `h1` панели (`admin.css`): засечный, `--fs-display`,
   700. Своей копии правила здесь больше нет — она и была тем образцом, по
   которому общее правило переписано. */

/* Статус — уже готовый `.adm-badge` из `status_html` (его же рисует колонка
   списка и подменяет поллинг `live.js`). Своей пилюли у обёртки нет: рамка
   поверх рамки бейджа давала вложенную «двойную» пилюлю. */
.shopcard__status { display: inline-flex; }
.shopcard__status .adm-badge::before { content: ""; width: 6px; height: 6px;
  border-radius: 50%; background: currentColor; flex: 0 0 6px; }
/* Магазин в работе — пульсация точки; остальные статусы статичны, иначе
   мигает вся страница разом и перестаёт что-либо значить. */
.shopcard[data-busy="1"] .shopcard__status .adm-badge::before {
  animation: shopcardPulse 1.6s ease-in-out infinite; }
@keyframes shopcardPulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

/* Отступ ровно под плиткой маркетплейса и её зазором до имени — метаданные
   выстраиваются по левому краю названия, а не по краю плитки. */
.shopcard__meta { display: flex; align-items: center; gap: var(--sp-item); flex-wrap: wrap;
  font-size: var(--fs-body); color: var(--muted2);
  padding-left: calc(var(--mp-tile) + var(--sp-block)); }

/* ── Предупреждение о приостановке ─────────────────────────────────────── */

.shopcard__alert { display: flex; align-items: flex-start; gap: var(--sp-row);
  padding: var(--sp-row) var(--sp-block); border-radius: 14px; font-size: var(--fs-row);
  color: var(--warn); background: rgba(241, 163, 59, .08);
  border: 1px solid rgba(241, 163, 59, .24); }
.shopcard__alert > div { flex: 1; min-width: 0; font-weight: 600; }
.shopcard__alert a { flex: 0 0 auto; color: inherit; font-size: var(--fs-body); font-weight: 500;
  white-space: nowrap; text-decoration: underline; text-underline-offset: 2px; }

/* ── Верхние KPI ───────────────────────────────────────────────────────── */

.shopcard__kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-gutter); }
.shopcard__kpi { padding: var(--sp-block) var(--sp-block); background: var(--panel);
  border: 1px solid var(--border); border-radius: 14px; min-width: 0; }
.shopcard__kpi-label { font-size: var(--fs-micro); letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted4); font-weight: 600; margin-bottom: var(--sp-item);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.shopcard__kpi-value { font-size: var(--fs-metric); font-weight: 600; letter-spacing: -.03em;
  line-height: 1; color: var(--text); font-variant-numeric: tabular-nums; }
.shopcard__kpi-note { font-size: var(--fs-hint); color: var(--muted3); margin-top: var(--sp-snug);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.shopcard__kpi--warn .shopcard__kpi-value,
.shopcard__kpi--warn .shopcard__kpi-note { color: var(--warn); }

/* ── Сетка карточки ────────────────────────────────────────────────────── */

.shopcard__grid { display: grid; grid-template-columns: minmax(0, 1fr) 344px;
  gap: var(--sp-gutter); align-items: start; }
.shopcard__main { display: flex; flex-direction: column; gap: var(--sp-gutter); min-width: 0; }
.shopcard__side { display: flex; flex-direction: column; gap: var(--sp-gutter);
  position: sticky; top: calc(var(--header-h) + var(--sp-gutter)); }

/* ── Панель ────────────────────────────────────────────────────────────── */

/* Радиус — общий токен панели, а не своё число: 16 против 18 у соседних
   экранов не читается как разница смысла, только как разнобой. */
.shopcard__panel { background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius-card); overflow: hidden; }
/* Шапка панели утоплена фоном — иначе заголовок и содержимое сливаются в
   одно полотно и панели перестают читаться как отдельные блоки. Отступы и
   фон здесь те же, что у общей `.adm-card__head` в `admin.css`: обе шапки
   описывают одно и то же место интерфейса.

   Правила для `h2` тут больше нет: гарнитуру и кегль заголовка блока задаёт
   общий `h2` в `admin.css`. Раньше возврат к шрифту интерфейса жил только на
   этом экране, из-за чего заголовки блоков на всех остальных оставались
   засечными и размером «по умолчанию». */
.shopcard__panel-head { display: flex; align-items: center; gap: var(--sp-item);
  padding: var(--sp-row) var(--sp-gutter); background: var(--sunken); border-bottom: 1px solid var(--line);
  flex-wrap: wrap; }
.shopcard__panel-head .shopcard__hint { margin-left: auto; }
/* Подпись, поясняющая сам заголовок («журнал списаний по этому магазину»),
   стоит вплотную к нему: отжатая к правому краю она читается как отдельная
   колонка шапки, а не как пояснение. Вправо уходят только подписи-ремарки
   вроде «списываются с владельца» в «Действиях». */
.shopcard__panel-head .shopcard__hint--inline { margin-left: 0; }
.shopcard__panel-head > button,
.shopcard__panel-head > .adm-btn { margin-left: auto; }
/* Заголовок «Действия» несёт и подсказку, и кнопку-справку — второй
   auto-отступ не нужен, кнопка идёт вплотную за подсказкой. */
.shopcard__panel-head .shopcard__hint + button { margin-left: var(--sp-tight); }
.shopcard__panel > div, .shopcard__panel > ul, .shopcard__panel > table,
.shopcard__panel > form { margin: 0; }

.shopcard__hint { font-size: var(--fs-hint); color: var(--muted3); }

/* ── Финансовая конфигурация ───────────────────────────────────────────── */

.shopcard__config { display: grid; grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-block) var(--sp-section); padding: var(--sp-block) var(--sp-gutter); }
.shopcard__config-label { font-size: var(--fs-micro); letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted4); font-weight: 600; margin-bottom: var(--sp-tight); }
.shopcard__config-value { font-size: var(--fs-lead); color: var(--text); font-weight: 600; }
/* Пояснение к значению — обычным текстом: моноширинный шрифт стоял здесь
   ради имён полей модели (`tax_mode`), которых в подписях больше нет. */
.shopcard__config-note { font-size: var(--fs-hint); color: var(--muted4); margin-top: var(--sp-tight); }

/* ── Данные магазина ───────────────────────────────────────────────────── */

/* Строки, а не `<table>`: у пары «поле — значение» третьей колонкой идёт
   состояние, и таблица здесь ничего не выигрывает, зато мешает значению
   ужиматься многоточием. */
.shopcard__cred { display: grid; grid-template-columns: minmax(190px, 1fr) minmax(0, 1.4fr);
  gap: var(--sp-block); align-items: center; padding: var(--sp-row) var(--sp-gutter); border-bottom: 1px solid var(--rowline); }
.shopcard__cred:last-child { border-bottom: none; }
/* Та же зебра и теми же токенами, что в журнале: два списка строк в одной
   карточке обязаны чередоваться одинаково. Шапка блока — первый ребёнок
   секции, поэтому полоса приходится на нечётные позиции. */
.shopcard__cred:nth-child(odd) { background: var(--stripe); }
.shopcard__cred-label { font-size: var(--fs-row); color: var(--text); min-width: 0; }
.shopcard__cred-value { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--fs-row); color: var(--text2); white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }

/* ── Последние операции ────────────────────────────────────────────────── */

.shopcard__ops { display: grid;
  grid-template-columns: 46px 66px minmax(120px, 1fr) minmax(150px, 1fr) 68px 58px minmax(140px, 1.1fr);
  gap: var(--sp-item); align-items: center; padding: var(--sp-item) var(--sp-gutter);
  border-bottom: 1px solid var(--rowline); transition: background .14s ease; }
/* Цвета — общие табличные токены панели (`.adm-table` в `admin.css`), а не
   снятые с макета: журнал операций — такая же таблица, как списки разделов,
   и две разные зебры в одном интерфейсе читаются как разные сущности.
   Зебра `--stripe` по чётным строкам данных, наведение `--hover2` (для
   строк; `--hover` в панели закреплён за пунктами меню).

   Шапка — первый ребёнок контейнера, поэтому чётные строки данных попадают
   на НЕЧЁТНЫЕ позиции среди всех детей; из чередования шапка исключена явно. */
.shopcard__ops:hover { background: var(--hover2); }
.shopcard__ops:nth-child(odd):not(.shopcard__ops--head) { background: var(--stripe); }
.shopcard__ops:nth-child(odd):not(.shopcard__ops--head):hover { background: var(--hover2); }
.shopcard__ops:last-child { border-bottom: none; }
.shopcard__ops--head { padding: var(--sp-row) var(--sp-gutter); font-size: var(--fs-eyebrow); letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted4); font-weight: 600;
  background: var(--sunken); border-bottom: 1px solid var(--border2); }
.shopcard__ops--head:hover { background: var(--sunken); }
.shopcard__ops > .adm-num { text-align: right; }
.shopcard__ops-date { font-size: var(--fs-body); color: var(--muted4); font-variant-numeric: tabular-nums; }
.shopcard__ops-time { font-size: var(--fs-body); color: var(--muted3); font-variant-numeric: tabular-nums; }
.shopcard__ops-kind { display: flex; align-items: center; gap: var(--sp-item); min-width: 0;
  font-size: var(--fs-row); color: var(--text2); }
.shopcard__ops-kind span:last-child { white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
/* Точка операции — по статусу списания (`ChargeStatus`). Общих модификаторов
   `.adm-dot` для них нет: там своя ось (живость процесса), а здесь — исход
   тарификации, и совпадение имён было бы случайным. */
.shopcard__ops-kind .adm-dot--charged { background: var(--brand); }
.shopcard__ops-kind .adm-dot--free { background: var(--info); }
.shopcard__ops-kind .adm-dot--insufficient { background: var(--err); }
.shopcard__ops-kind .adm-dot--released { background: var(--muted4); }
.shopcard__ops-src { font-size: var(--fs-body); color: var(--muted3); min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.shopcard__ops-num { font-size: var(--fs-body); color: var(--text2);
  font-variant-numeric: tabular-nums; text-align: right; }
.shopcard__ops-result { font-size: var(--fs-body); color: var(--muted3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Отказ по деньгам — единственный исход, который оператор ищет в журнале
   глазами: он красный, остальные исходы рассказывает точка слева. */
.shopcard__ops-result.is-refused { color: var(--err); }
.shopcard__ops-empty { padding: var(--sp-page) var(--sp-gutter); text-align: center;
  font-size: var(--fs-body); color: var(--muted3); }
/* Страховка на случай, когда семь колонок всё же не помещаются (очень
   длинный адрес оператора, узкий экран): журнал уезжает в горизонтальную
   прокрутку целиком, а не сплющивает колонки до нечитаемых. Минимумы в
   `grid-template-columns` подобраны так, чтобы на штатной ширине панели
   прокрутки не появлялось. */
.shopcard__ops-scroll { overflow-x: auto; }

.shopcard__badge { font-size: var(--fs-hint); color: var(--muted3);
  background: var(--chip); border-radius: 999px; padding: var(--sp-hair) var(--sp-item); }

.shopcard__pager { display: flex; align-items: center; gap: var(--sp-row);
  padding: var(--sp-row) var(--sp-gutter); font-size: var(--fs-body); color: var(--muted3); }
.shopcard__pager-nav { margin-left: auto; display: flex; align-items: center; gap: var(--sp-snug); }
.shopcard__pager-nav a, .shopcard__pager-state { height: 28px; border-radius: 8px;
  border: 1px solid var(--border2); display: flex; align-items: center;
  justify-content: center; color: var(--text2); font-variant-numeric: tabular-nums; }
.shopcard__pager-nav a { width: 28px; }
.shopcard__pager-nav a:hover { border-color: var(--border4); color: var(--text); }
.shopcard__pager-state { padding: 0 var(--sp-row); color: var(--muted3); }

/* ── Владелец ──────────────────────────────────────────────────────────── */

.shopcard__owner { display: flex; align-items: center; gap: var(--sp-row);
  padding: var(--sp-block) var(--sp-gutter); border-bottom: 1px solid var(--rowline); }
/* Обе строки ужимаются многоточием: длинный адрес иначе распирает боковую
   колонку и выдавливает из неё кружок с инициалами. Полный адрес — в
   подсказке ссылки. */
.shopcard__owner-body { min-width: 0; }
.shopcard__owner a { display: block; font-weight: 500; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.shopcard__owner .shopcard__hint { margin-top: var(--sp-hair); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.shopcard__wallet { display: flex; flex-direction: column; gap: var(--sp-item);
  padding: var(--sp-row) var(--sp-gutter); margin: 0; }
/* `gap`, а не только `space-between`: у длинного числа подпись и значение
   иначе сходятся вплотную и читаются как одна строка символов. */
.shopcard__wallet > div { display: flex; align-items: baseline; gap: var(--sp-block);
  justify-content: space-between; font-size: var(--fs-body); }
.shopcard__wallet dt { color: var(--muted2); white-space: nowrap; }
.shopcard__wallet dd { margin: 0; color: var(--text2); font-weight: 500;
  white-space: nowrap; font-variant-numeric: tabular-nums; }
/* Отрицательный баланс — не просто красная цифра: полоса показывает, какую
   долю овердрафта магазин уже проел. */
.shopcard__wallet dd.is-debt { color: var(--err); font-weight: 600; }

/* ── Действия ──────────────────────────────────────────────────────────── */

/* Список действий — форма: тариф и кнопка запуска в одной строке. */
.shopcard__tariffs { margin: 0; padding: 0; }
.shopcard__act { position: relative; display: flex; align-items: center; gap: var(--sp-row);
  padding: var(--sp-row) var(--sp-gutter); border-bottom: 1px solid var(--rowline);
  transition: background .14s ease; }
.shopcard__act:last-child { border-bottom: none; }
.shopcard__act:hover { background: var(--hover); }
/* Полоса слева — ПРЕПЯТСТВИЕ, а не платность. Появляется ровно в двух
   случаях: владельцу не хватает токенов (янтарь) и маркетплейс операцию не
   умеет (серая). У обычной строки полосы нет вовсе — иначе весь список
   расчерчен и цвет перестаёт что-либо значить. */
.shopcard__act::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0;
  width: 2.5px; background: transparent; }
.shopcard__act.is-short::before { background: var(--warn); }
.shopcard__act.is-unsupported::before { background: var(--faint); }
/* Зебры в списке действий НЕТ (в отличие от журнала и данных магазина):
   подсветка здесь занята смыслом — залита та строка, на которую владельцу
   не хватает токенов. Чередование поверх неё сделало бы половину списка
   похожей на предупреждение. */
.shopcard__act.is-short { background: rgba(241, 163, 59, .05); }
.shopcard__act.is-short:hover { background: rgba(241, 163, 59, .10); }

.shopcard__act-body { flex: 1; min-width: 0; }
.shopcard__act-line { display: flex; align-items: baseline; gap: var(--sp-item); min-width: 0; }
.shopcard__act-line + .shopcard__act-line { margin-top: var(--sp-tight); }
/* Строка держит ровно две линии: длинное название ужимается многоточием, а
   не переносится. Семь строк одинаковой высоты сравниваются взглядом, а
   «прыгающая» высота превращает список в лестницу. Полное название — в
   подсказке строки. */
.shopcard__act-label { font-size: var(--fs-row); font-weight: 500; color: var(--text);
  min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.shopcard__act-total { margin-left: auto; flex: 0 0 auto; font-size: var(--fs-body);
  font-weight: 600; color: var(--muted4); font-variant-numeric: tabular-nums;
  white-space: nowrap; }
.shopcard__act-state { font-size: var(--fs-hint); font-weight: 500; color: var(--green);
  min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.shopcard__act-cost { margin-left: auto; flex: 0 0 auto; font-size: var(--fs-eyebrow);
  color: var(--muted4); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Кнопка запуска: цвет — это ПЛАТНОСТЬ операции. Сплошная зелёная у
   бесплатной, янтарный контур у платной. Своя, а не `.adm-btn`: тому
   пришлось бы заводить вариант «янтарный контур» ради одного места. */
.shopcard__act-run { flex: 0 0 auto; font: inherit; font-size: var(--fs-body); font-weight: 600;
  padding: var(--sp-snug) var(--sp-row); border-radius: 9px; cursor: pointer; white-space: nowrap;
  background: var(--brand); border: 1px solid var(--brand); color: var(--on-brand);
  transition: filter .16s ease, background .16s ease; }
.shopcard__act-run:hover { filter: brightness(1.08); }
.shopcard__act.is-paid .shopcard__act-run { background: rgba(241, 163, 59, .12);
  border-color: rgba(241, 163, 59, .30); color: var(--warn); }
.shopcard__act.is-paid .shopcard__act-run:hover { background: rgba(241, 163, 59, .18); }
.shopcard__act-run:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.shopcard__act-run[disabled] { opacity: .45; cursor: not-allowed; filter: none; }

/* Платная операция: сумма справа тоже янтарная — та же ось, что и кнопка. */
.shopcard__act.is-paid .shopcard__act-total { color: var(--warn); }
/* Не хватает токенов: янтарь переезжает на состояние. Кнопка остаётся
   активной — операцию можно провести за счёт сервиса. */
.shopcard__act.is-short .shopcard__act-state { color: var(--warn); }
/* Маркетплейс операции не умеет: строка тускнеет целиком, а состояние вместо
   описания называет причину — иначе она читается как «доступна». */
.shopcard__act.is-unsupported .shopcard__act-label { color: var(--muted3); font-weight: 400; }
.shopcard__act.is-unsupported .shopcard__act-total,
.shopcard__act.is-unsupported .shopcard__act-state { color: var(--muted4); }

.shopcard__info-btn { width: 22px; height: 22px; border-radius: 999px; font-size: var(--fs-body); }

/* ── Автоматизация ─────────────────────────────────────────────────────── */

.shopcard__toggle { display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--sp-row); padding: var(--sp-row) var(--sp-gutter); border-bottom: 1px solid var(--rowline);
  cursor: pointer; transition: background .14s ease; }
.shopcard__toggle:hover { background: var(--hover); }
.shopcard__toggle > div > div:first-child { font-size: var(--fs-row); font-weight: 500; color: var(--text); }
.shopcard__toggle .shopcard__hint { margin-top: var(--sp-tight); line-height: 1.45; }
/* Сам тумблер (нативный флажок, перерисованный в переключатель) описан в
   `admin.css` рядом с `.adm-switch`: правила общие с экраном создания
   магазина и живут одним блоком, а не двумя копиями. */

/* Правило разбора заявок. Приглушается при выключенной авто-модерации, но
   остаётся рабочим: типовой порядок — настроить правило, а включить уже
   настроенное, и заблокированные поля заставляли бы делать это в два захода. */
.shopcard__automation-rule { padding: 0 var(--sp-gutter) var(--sp-row); border-bottom: 1px solid var(--rowline);
  transition: opacity .18s ease; }
.shopcard__automation-rule.is-off { opacity: .5; }
.shopcard__automation-rule > .shopcard__hint { display: block; padding-top: var(--sp-item);
  line-height: 1.4; }
/* Сегмент режима — во всю ширину блока, а не по содержимому: два варианта
   выбора одного правила читаются как переключатель только равными половинами. */
.shopcard__automation-modes { display: grid; grid-template-columns: 1fr 1fr;
  width: 100%; margin-top: var(--sp-row); }
/* Настоящие радиокнопки под подписями: сегмент обязан оставаться полем формы —
   он уезжает в POST вместе с порогом и работает с клавиатуры. */
.shopcard__automation-modes input { position: absolute; width: 1px; height: 1px;
  opacity: 0; pointer-events: none; }
.shopcard__automation-modes input:focus-visible + span { outline: 2px solid var(--brand);
  outline-offset: 3px; border-radius: 4px; }

/* Пресеты процента — сетка равных ячеек, а не разнокалиберные пилюли:
   проценты сравниваются глазом только при одинаковой ширине. */
.shopcard__presets { display: grid; grid-template-columns: repeat(auto-fit, minmax(56px, 1fr));
  gap: var(--sp-tight); padding: var(--sp-row) var(--sp-gutter) 0; }
/* Внутренние отступы и радиус заданы всегда, а не вместе с подсветкой
   изменения: появившийся padding сдвигал бы ячейки в момент правки. */
.shopcard__automation-rule .shopcard__presets { grid-template-columns: repeat(5, 1fr);
  padding: var(--sp-item) var(--sp-snug) var(--sp-snug);
  margin: 0 calc(var(--sp-snug) * -1); border-radius: 11px;
  transition: opacity .16s ease, background .16s ease, box-shadow .16s ease; }
/* Режим «по мин. цене» — порога нет вовсе: ячейки гаснут и перестают
   принимать клики, чтобы выбранный процент не выглядел действующим. */
.shopcard__automation-rule .shopcard__presets.is-off { opacity: .4; pointer-events: none; }
/* Своя ячейка ввода в том же ряду, что и пресеты: произвольный порог — такой
   же вариант выбора, а не отдельная форма ниже. */
.shopcard__presets-own { display: flex; align-items: center; justify-content: center;
  gap: var(--sp-hair); height: 32px; border-radius: 8px; background: var(--sunken);
  border: 1px solid var(--border2); }
.shopcard__presets-own:focus-within { border-color: var(--brand); }
.shopcard__presets-own input { width: 26px; padding: 0; border: 0; outline: none;
  background: transparent; color: var(--text); font: inherit; font-size: var(--fs-body);
  font-weight: 600; font-variant-numeric: tabular-nums; text-align: right;
  -moz-appearance: textfield; appearance: textfield; }
/* Стрелки числового поля съели бы всю ширину ячейки — ввод здесь с клавиатуры. */
.shopcard__presets-own input::-webkit-outer-spin-button,
.shopcard__presets-own input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.shopcard__presets-own span { font-size: var(--fs-hint); color: var(--muted3); }

/* Несохранённое изменение показано на самом поле — янтарём, той же осью
   «требует решения», что и платные действия карточки выше. Цветом, а не
   перечислением имён под формой: список называл словами ровно то, что и так
   видно на полях, и рос вместе с числом настроек. */
form[data-automation] .shopcard__toggle.is-changed { background: rgba(241, 163, 59, .06);
  box-shadow: inset 2.5px 0 0 var(--warn); }
/* Свой hover: общий (`--hover`) перекрывался бы подсветкой, и изменённая
   строка переставала бы отзываться на курсор. */
form[data-automation] .shopcard__toggle.is-changed:hover { background: rgba(241, 163, 59, .11); }
form[data-automation] .shopcard__automation-modes.is-changed {
  background: rgba(241, 163, 59, .07); border-color: rgba(241, 163, 59, .45); }
form[data-automation] .shopcard__presets.is-changed { background: rgba(241, 163, 59, .07);
  box-shadow: inset 0 0 0 1px rgba(241, 163, 59, .40); }

/* Текст для скринридера: подсветку он не читает, а знать о несохранённом
   изменении обязан — иначе кнопка «Применить» оживает молча. */
.shopcard__sr-only { position: absolute; width: 1px; height: 1px; padding: 0;
  margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* Подвал формы: применение справа. Кнопка заблокирована, пока изменений нет:
   активная кнопка без работы обещает действие, которого не будет. */
.shopcard__automation-foot { display: flex; align-items: center; gap: var(--sp-item);
  justify-content: flex-end; padding: var(--sp-row) var(--sp-gutter); }
.shopcard__automation-foot .adm-btn { flex: 0 0 auto; }
.shopcard__presets button { display: flex; align-items: center; justify-content: center;
  height: 32px; padding: 0 var(--sp-tight); border-radius: 8px; font-size: var(--fs-body);
  font-variant-numeric: tabular-nums; background: var(--sunken);
  border: 1px solid var(--border2); color: var(--muted2); cursor: pointer;
  font-family: inherit; transition: background .16s ease, color .16s ease,
  border-color .16s ease; }
.shopcard__presets button:hover { color: var(--text); border-color: var(--border4); }
.shopcard__presets button.is-active { background: var(--brand); border-color: var(--brand);
  color: var(--on-brand); font-weight: 600; }
.shopcard__panel > .shopcard__hint { display: block; padding: var(--sp-item) var(--sp-gutter) var(--sp-row); line-height: 1.4; }

/* ── Опасная зона ──────────────────────────────────────────────────────── */

/* Общая часть (рамка, шапка, строка «что произойдёт», каскад счётчиков)
   переехала в `admin.css` под именами `.adm-danger*`/`.adm-cascade*`: та же
   зона стоит на карточке клиента, и две её копии разъехались бы при первой
   же правке. Здесь остаётся только привязка к панели карточки магазина —
   у неё своя шапка (`.shopcard__panel-head`), а не общая `.adm-card__head`. */
.shopcard__panel--danger .shopcard__panel-head { background: rgba(241, 98, 111, .05); }
.shopcard__panel--danger .shopcard__panel-head h2 { color: var(--err); }
.shopcard__panel--danger .shopcard__hint { margin-top: var(--sp-hair); line-height: 1.45; }

/* ── Финансовый блок ───────────────────────────────────────────────────── */

/* Выпадашка периода и подсказка точки графика описаны в `admin.css`
   (`.adm-period*`, `.adm-charttip`): тот же контрол стоит у графика расхода
   на карточке клиента, и вторая копия геометрии разъехалась бы с первой.
   Разметка финансового блока пока носит имена `.shopcard__period*` /
   `.shopcard__chart-tip` — они перечислены там псевдонимами. */

/* Пока фрагмент в пути — блок глушится, но остаётся на месте: исчезающий
   график дёргал бы высоту страницы на каждом переключении. */
[data-swap-src].is-loading { opacity: .5; pointer-events: none; }

.shopcard__periods { margin-left: auto; }
/* Оговорки о полноте: сколько магазинов вошло в сумму, сколько дней
   материализовано. Строкой под шапкой, а не подписью в легенде графика: без
   графика (пустой период) легенды нет, а оговорка нужнее всего именно там. */
.shopcard__fin-notes { display: flex; gap: var(--sp-block); flex-wrap: wrap;
  padding: var(--sp-item) var(--sp-gutter); border-bottom: 1px solid var(--line); }
/* Янтарный — «в этих цифрах есть чего-то не хватает», а не «сломано»:
   красный тут читался бы как ошибка расчёта. */
.shopcard__hint--warn { color: var(--warn); }
/* Нечего показать — объясняем словами на месте графика. Высота примерно
   равна графику, чтобы блок не схлопывался в полоску: пропавший корпус
   читается как «блок не загрузился», а не «данных нет». */
.shopcard__fin-empty { padding: var(--sp-page) var(--sp-gutter); text-align: center; }
.shopcard__fin-kpis { display: grid; grid-template-columns: repeat(4, 1fr);
  border-bottom: 1px solid var(--line); }
.shopcard__fin-kpis > div { padding: var(--sp-block) var(--sp-gutter); border-right: 1px solid var(--line); min-width: 0; }
.shopcard__fin-kpis > div:last-child { border-right: none; }
.shopcard__fin-kpis span { display: block; font-size: var(--fs-micro); letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted4); font-weight: 600; margin-bottom: var(--sp-item);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.shopcard__fin-kpis strong { display: block; font-size: var(--fs-metric); font-weight: 600;
  letter-spacing: -.03em; line-height: 1; color: var(--text);
  font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
/* Смысловая окраска чисел: расход — трата, маржа — прибыль или убыток.
   Только на `strong`: на подписи цвет не несёт информации, а размывает её. */
.shopcard__fin-kpis strong.is-loss { color: var(--err); }
.shopcard__fin-kpis strong.is-profit { color: var(--ok); }
.shopcard__fin-kpis em { display: block; font-style: normal; font-size: var(--fs-hint);
  color: var(--muted3); margin-top: var(--sp-snug); white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }

.shopcard__fin-body { display: grid; grid-template-columns: minmax(0, 1fr) 268px; }
.shopcard__chart { padding: var(--sp-block) var(--sp-item) var(--sp-block) var(--sp-gutter); min-width: 0;
  display: flex; flex-direction: column; }
/* Переключатель графика — в шапке блока, справа (по макету), иконками 30×24
   в обойме `.adm-seg--icons`. Сам модификатор объявлен вместе с компонентом
   (`admin.css`, раздел «Переключатели»): здесь остаётся только место на
   экране — правила самого переключателя ни в одном экранном файле не живут,
   иначе они снова разойдутся с общими. */
.shopcard__chart-modes { margin-left: auto; }
/* График с подписями осей: колонка значений слева, даты снизу, легенда под
   ними. Без них полилиния — просто узор: масштаб и знак не прочитать. */
/* Сетка графика: ось и холст в первой строке, даты с легендой — во второй.
   Строка холста тянется (`1fr`), поэтому график занимает всю высоту, что
   осталась от соседней колонки детализации, а ось растёт вместе с ним —
   при выкладке флексом её высоту пришлось бы дублировать числом. */
.shopcard__chart-plot { display: grid; gap: 0 var(--sp-item); flex: 1; min-height: 0;
  grid-template-columns: 52px minmax(0, 1fr);
  grid-template-rows: minmax(190px, 1fr) auto; }
/* Оба режима графика лежат в разметке одновременно — данные для них сервер и
   так считает вместе (см. `panel_finance._chart`), — а показывается тот, что
   назван в `data-fin-chart` секции. Так переключение режима сводится к смене
   одного атрибута на клиенте: без запроса и без перерисовки KPI с
   детализацией, которые от режима не зависят. */
[data-fin-chart="lines"] [data-chart-for="net"],
[data-fin-chart="net"] [data-chart-for="lines"] { display: none; }
.shopcard__chart-axis { position: relative; font-size: var(--fs-hint); color: var(--muted4);
  font-variant-numeric: tabular-nums; text-align: right; }
.shopcard__chart-axis span { position: absolute; right: 0; transform: translateY(-50%); }
/* 5% / 50% / 95% — ровно те доли высоты, на которых лежат максимум, ноль и
   минимум холста при амплитуде 135 из 150 (см. `panel_finance._AMPLITUDE`). */
.shopcard__chart-axis .is-top { top: 5%; }
.shopcard__chart-axis .is-zero { top: 50%; }
.shopcard__chart-axis .is-bottom { top: 95%; }
.shopcard__chart-area { position: relative; min-width: 0; }
.shopcard__chart-foot { grid-column: 2; min-width: 0; }
/* Слой наведения — по невидимой ячейке на день поверх холста, во всю его
   площадь. Курсор оставляем обычный: что график читается по вертикали,
   показывает направляющая под курсором, а не подменённый указатель. */
.shopcard__chart-hover { position: absolute; inset: 0; display: flex; }
.shopcard__chart-hover > div { flex: 1; }
/* Указатель дня. Координаты приходят с сервера в системе холста (1000×300) и
   пересчитываются в проценты — при `preserveAspectRatio="none"` доли по обеим
   осям совпадают с долями внутри слоя, какой бы ширины он ни оказался.

   Слой без своего `z-index` намеренно: он создал бы контекст наложения, и
   подложка внутри него не смогла бы уйти под холст (см. `--band` ниже). */
.shopcard__chart-cursor { position: absolute; inset: 0; pointer-events: none; }
.shopcard__chart-cursor[hidden] { display: none; }
.shopcard__chart-rule { position: absolute; top: 0; bottom: 0; width: 1px;
  margin-left: -.5px; background: var(--border4); }
/* Точка на линии: обводка цветом панели отделяет её от самой линии — без неё
   маркер сливается с ней и наведение читается только по подсказке. */
.shopcard__chart-dot { --dot: 9px; position: absolute; width: var(--dot); height: var(--dot);
  border-radius: 50%; margin: calc(var(--dot) / -2) 0 0 calc(var(--dot) / -2);
  background: currentColor; z-index: 2;
  box-shadow: 0 0 0 2px var(--panel); }
.shopcard__chart-dot.is-income { color: var(--ok); }
.shopcard__chart-dot.is-expense { color: var(--info); }
/* Режим маржи: у столбцов точке взяться неоткуда — день выделяется подложкой
   во всю высоту слота (она же показывает слот пустого дня) и приглушением
   остальных столбцов. Приглушением, а не подсветкой активного: осветление
   работает только на тёмной теме, а прозрачность читается на обеих.
   Подложка и направляющая лежат ПОД холстом (у него `z-index: 1`): поверх
   непрозрачная заливка закрывала бы сам столбец — то есть ровно то, на что
   она должна указывать. Над холстом остаются только точки. */
.shopcard__chart-band { position: absolute; top: 0; bottom: 0; border-radius: 7px;
  background: var(--track); }
.shopcard__chart svg.is-hovered rect { opacity: .38; transition: opacity .12s ease; }
.shopcard__chart svg.is-hovered rect.is-hot { opacity: 1; }
/* Коробка подсказки — общая (`.adm-charttip` в `admin.css`); здесь остаются
   только строки, которых нет у других графиков: приход, расход и маржа со
   своими цветами. */
.shopcard__chart-tip .is-income { color: var(--ok); }
.shopcard__chart-tip .is-expense { color: var(--info); }
.shopcard__chart-tip-net.is-loss span:last-child { color: var(--err); }
.shopcard__chart-tip-net.is-profit span:last-child { color: var(--ok); }

/* Пункт «Настроить диапазон» — такая же строка меню, как пресеты; описан
   вместе с остальным меню в `admin.css`. */
/* Холст поднят над подложкой указателя (`z-index: 1`), а события пропускает
   насквозь — под ним лежит слой наведения, и без `pointer-events: none`
   поднятый холст перехватывал бы наведение на дни. */
.shopcard__chart-area > svg { position: absolute; inset: 0; width: 100%; height: 100%;
  display: block; z-index: 1; pointer-events: none; }
.shopcard__chart-dates { display: flex; justify-content: space-between; font-size: var(--fs-hint);
  color: var(--muted4); padding-top: var(--sp-snug); font-variant-numeric: tabular-nums; }
.shopcard__chart-legend { display: flex; align-items: center; gap: var(--sp-block); padding-top: var(--sp-row);
  flex-wrap: wrap; }
.shopcard__chart-legend > span { display: inline-flex; align-items: center; gap: var(--sp-snug);
  font-size: var(--fs-body); color: var(--text2); }
.shopcard__chart-legend i { width: 14px; height: 3px; border-radius: 2px; background: currentColor; }
.shopcard__chart-legend .is-income { color: var(--ok); }
.shopcard__chart-legend .is-expense { color: var(--info); }
.shopcard__chart-legend .is-loss { color: var(--err); }
/* В режиме «маржа по дням» ряды — столбцы, а не линии: засечка легенды
   должна повторять форму того, что она объясняет. */
[data-fin-chart="net"] .shopcard__chart-legend i { height: 8px; }
.shopcard__chart-legend .shopcard__hint { margin-left: auto; }

.shopcard__breakdown { padding: var(--sp-block) var(--sp-gutter); border-left: 1px solid var(--line);
  display: flex; flex-direction: column; }
/* Та же причина, что и у заголовка панели: подпись колонки — интерфейсный
   шрифт, не засечный. */
.shopcard__breakdown h3 { font-family: inherit; font-size: var(--fs-row); font-weight: 600;
  letter-spacing: normal; line-height: 1.3; color: var(--text); margin: 0 0 var(--sp-item); }
.shopcard__breakdown-row { padding: var(--sp-tight) 0; }
.shopcard__breakdown-line { display: flex; align-items: baseline; gap: var(--sp-item); font-size: var(--fs-body); }
.shopcard__breakdown-line > span:first-child { color: var(--muted); white-space: nowrap; }
/* Пунктирная выноска между подписью и суммой — глаз ведёт по ней от строки
   к числу; без неё в узкой колонке подпись и сумма перестают связываться. */
.shopcard__breakdown-line i { flex: 1; border-bottom: 1px dotted var(--border2); }
.shopcard__breakdown-value { font-variant-numeric: tabular-nums; font-weight: 500;
  color: var(--text2); white-space: nowrap; }
.shopcard__breakdown-bar { height: 3px; border-radius: 2px; background: var(--track);
  margin-top: var(--sp-tight); overflow: hidden; }
.shopcard__breakdown-bar > i { display: block; height: 100%; border-radius: 2px;
  background: var(--info); transform-origin: left; }
.shopcard__breakdown-bar > i.is-income { background: var(--ok); }
.shopcard__breakdown-total { margin-top: var(--sp-item); padding-top: var(--sp-row);
  border-top: 1px solid var(--border); display: flex; align-items: baseline;
  justify-content: space-between; gap: var(--sp-item); }
.shopcard__breakdown-total span { font-size: var(--fs-body); font-weight: 600; color: var(--text); }
.shopcard__breakdown-total strong { font-size: var(--fs-lead); font-weight: 600; color: var(--ok);
  font-variant-numeric: tabular-nums; }
.shopcard__breakdown-total strong.is-loss { color: var(--err); }
/* Предупреждение о незаполненном закупе — под итогом, потому что говорит именно
   о нём: маржа завышена ровно на непокрытую себестоимость. Отступ — `--sp-gutter`,
   зазор между блоками: у предупреждения своя рамка и свой фон, поэтому оно
   читается самостоятельным блоком, а не строкой детализации, и на `--sp-row`
   прижималось к итогу вплотную. Свой нижний отступ снят — он бы сложился с
   полем блока. */
.shopcard__breakdown .adm-alert { margin: var(--sp-gutter) 0 0; }

/* ── Модалки ───────────────────────────────────────────────────────────── */

/* Оболочка — существующий `.adm-modal`; здесь только вариант пошире под
   формы в несколько полей. */
/* Вариант пошире под формы в несколько полей переехал в `admin.css`
   (`.adm-modal--wide`): такие диалоги есть и у карточки клиента.
   `.shopcard__modal` осталось прежним именем того же места. */
/* Пара границ диапазона переехала в `admin.css` (`.adm-modal__range`): тот же
   диалог открывают два блока — финансы и расход токенов. */

/* Результат проверки доступа — в самом диалоге токенов, между полями и
   кнопками: он относится к тому, что оператор только что ввёл, и тост поверх
   окна отвечал бы на вопрос в стороне от него. */
.shopcard__cred-check { padding: var(--sp-item) var(--sp-row); border-radius: 10px; font-size: var(--fs-body);
  line-height: 1.4; color: var(--muted2); background: var(--sunken);
  border: 1px solid var(--border2); }
.shopcard__cred-check[hidden] { display: none; }
.shopcard__cred-check.is-ok { color: var(--ok); background: rgba(47, 203, 116, .09);
  border-color: rgba(47, 203, 116, .28); }
.shopcard__cred-check.is-fail { color: var(--err); background: rgba(241, 98, 111, .09);
  border-color: rgba(241, 98, 111, .30); }

/* Диалог подтверждения действия (`admin/_action_modal.html`). Своя шапка с
   подзаголовком: оператор пришёл сюда из строки списка и должен видеть, над
   каким магазином действие, не закрывая окно. */
#action-modal { padding: 0; }
.adm-actmodal { display: flex; flex-direction: column; gap: 0; }
.adm-actmodal__head { padding: var(--sp-gutter) var(--sp-section) var(--sp-block); }
.adm-actmodal__hint { font-size: var(--fs-body); color: var(--muted3); margin-top: var(--sp-tight); }
.adm-actmodal__body { padding: 0 var(--sp-section); display: flex; flex-direction: column; gap: var(--sp-row); }
.adm-actmodal__actions { padding: var(--sp-block) var(--sp-section) var(--sp-gutter); display: flex;
  justify-content: flex-end; align-items: center; gap: var(--sp-item); }

/* Диалог удаления (`admin/_delete_modal.html`). Каскад — список без маркеров:
   строки вида «отчёты: 12» сами себя перечисляют, а точки перед ними в узком
   окне только сдвигают текст. */
.adm-delmodal__label { font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted4); }
.adm-delmodal__list { margin: calc(var(--sp-snug) * -1) 0 0; padding: 0; list-style: none;
  display: flex; flex-direction: column; gap: var(--sp-hair); }
.adm-delmodal__list li { font-size: var(--fs-body); color: var(--text2);
  font-variant-numeric: tabular-nums; }

/* Выбор режима оплаты — карточки-переключатели. */
.adm-choice { display: flex; flex-direction: column; gap: var(--sp-item); }
.adm-choice__card { position: relative; display: flex; align-items: center; gap: var(--sp-row);
  padding: var(--sp-row) var(--sp-block); border: 1px solid var(--border2); border-radius: 13px;
  background: var(--sunken); cursor: pointer;
  transition: border-color .16s ease, background .16s ease; }
.adm-choice__card:hover { border-color: var(--border4); }
/* Нативный radio спрятан, но не выключен: он остаётся тем, что отправляется
   формой и что читает скринридер, — поэтому увести его за `display:none`
   нельзя, иначе поле выпадает из последовательности фокуса. */
.adm-choice__card input[type="radio"] { position: absolute; opacity: 0;
  width: 0; height: 0; margin: 0; pointer-events: none; }
.adm-choice__mark { flex: 0 0 16px; width: 16px; height: 16px; border-radius: 50%;
  border: 1.5px solid var(--border4); display: flex; align-items: center;
  justify-content: center; transition: border-color .16s ease; }
.adm-choice__mark::after { content: ""; width: 8px; height: 8px; border-radius: 50%;
  background: transparent; transition: background .16s ease; }
.adm-choice__card:has(input:checked) { border-color: var(--brand);
  background: rgba(47, 203, 116, .06); }
.adm-choice__card:has(input:checked) .adm-choice__mark { border-color: var(--brand); }
.adm-choice__card:has(input:checked) .adm-choice__mark::after { background: var(--brand); }
.adm-choice__card:has(input:focus-visible) { outline: 2px solid var(--brand);
  outline-offset: 2px; }
.adm-choice__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--sp-hair); }
.adm-choice__title { font-size: var(--fs-row); font-weight: 600; color: var(--text); }
.adm-choice__hint { font-size: var(--fs-hint); color: var(--muted3); line-height: 1.4; }
.adm-choice__total { flex: 0 0 auto; font-size: var(--fs-row); font-weight: 600;
  color: var(--muted3); font-variant-numeric: tabular-nums; white-space: nowrap; }
.adm-choice__total.is-paid { color: var(--warn); }
.adm-choice__note { margin: 0; font-size: var(--fs-body); line-height: 1.5; color: var(--warn); }

/* Разбивка итога по магазинам выборки (массовый запуск). Список прокручивается
   внутри себя: полсотни строк иначе уводят кнопку подтверждения за сгиб, и
   оператор подтверждает, не видя, что подтверждает. */
.adm-choice__rows { margin-top: var(--sp-item); max-height: 232px; overflow-y: auto;
  border: 1px solid var(--border2); border-radius: var(--radius-control); }
.adm-choice__row { display: flex; align-items: baseline; gap: var(--sp-item);
  padding: var(--sp-snug) var(--sp-row); border-bottom: 1px solid var(--rowline); font-size: var(--fs-body); }
.adm-choice__row:last-child { border-bottom: 0; }
.adm-choice__row-name { flex: 1; min-width: 0; color: var(--text2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.adm-choice__row-note { flex: 0 0 auto; font-size: var(--fs-hint); color: var(--warn); }
.adm-choice__row-total { flex: 0 0 auto; color: var(--muted3);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Строка, которая до маркетплейса не дойдёт: не ошибка оператора, а факт про
   магазин — приглушаем, а не красим тревожно. */
.adm-choice__row.is-off { color: var(--muted4); }
.adm-choice__row.is-off .adm-choice__row-name,
.adm-choice__row.is-off .adm-choice__row-total { color: var(--muted4); }
.adm-choice__row.is-off .adm-choice__row-note { color: var(--muted4); }
.adm-choice__row.is-short { background: rgba(241, 163, 59, .05); }

/* ── Узкий экран ───────────────────────────────────────────────────────── */

@media (max-width: 1100px) {
  .shopcard__grid, .shopcard__fin-body { grid-template-columns: minmax(0, 1fr); }
  .shopcard__side { position: static; }
  .shopcard__kpis, .shopcard__fin-kpis, .shopcard__config { grid-template-columns: repeat(2, 1fr); }
  .shopcard__fin-kpis > div:nth-child(2n) { border-right: none; }
  .shopcard__breakdown { border-left: none; border-top: 1px solid var(--line); }
  /* Журнал операций в одну колонку не влезает — уводим в горизонтальную
     прокрутку целиком, чтобы строки не рвались по-разному. */
  .shopcard__ops { min-width: 760px; }
  .shopcard__ops-scroll { overflow-x: auto; }
}

@media (max-width: 720px) {
  .shopcard__kpis, .shopcard__fin-kpis, .shopcard__config { grid-template-columns: 1fr; }
  .shopcard__fin-kpis > div { border-right: none; border-bottom: 1px solid var(--line); }
  .shopcard__name h1 { font-size: var(--fs-metric); }
  .shopcard__meta { padding-left: 0; }
}
