/*
 * Stockshop UI — Utility classes (badge / chip / toolbar / empty state)
 * ----------------------------------------------------------------------------
 *   <link rel="stylesheet" href="/shared/design/tokens.css">
 *   <link rel="stylesheet" href="/shared/design/utilities.css">
 *
 * Кнопки и поля — в design/controls.css (с 2026-09-11). Он подключается
 * отдельным <link> ДО utilities.css; @import убран (аудит 2026-09-13 §3.7:
 * блокирующий запрос-дубль при том, что макет уже линкует controls.css).
 */

/* ═══ Значок состояния ══════════════════════════════════════════════════
   Значок СООБЩАЕТ состояние и не кликается. Если по нему можно щёлкнуть —
   это чип или кнопка, а не значок. */
.ui-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 7px;
    border-radius: var(--ui-radius-sm);
    background: var(--ui-surface-muted);
    color: var(--ui-color-text-secondary);
    font-size: var(--ui-font-size-xs);
    font-weight: var(--ui-weight-bold);
    letter-spacing: var(--ui-tracking-label);
    line-height: 1.5;
    text-transform: uppercase;
    white-space: nowrap;
}
.ui-badge-primary { background: var(--ui-color-primary-soft); color: var(--ui-color-primary-hover); }
.ui-badge-success { background: var(--ui-color-success-soft); color: var(--ui-color-success-strong); }
.ui-badge-warning { background: var(--ui-color-warning-soft); color: var(--ui-color-warning-strong); }
.ui-badge-danger  { background: var(--ui-color-danger-soft);  color: var(--ui-color-danger-strong); }
.ui-badge-violet  { background: var(--ui-color-violet-soft);  color: var(--ui-color-violet-strong); }
.ui-badge-ghost   { background: transparent; color: var(--ui-color-text-muted); box-shadow: inset 0 0 0 1px var(--ui-border-color); }
.ui-badge-sm      { padding: 1px 5px; font-size: 10px; }

/* ═══ Чип ═══════════════════════════════════════════════════════════════
   Чип — это ВЫБОР, который можно снять; поэтому у него скруглённая форма
   и, как правило, крестик. */
.ui-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: var(--ui-control-h-sm);
    padding: 0 10px;
    border: 1px solid var(--ui-border-color);
    border-radius: var(--ui-radius-full);
    background: var(--ui-surface);
    color: var(--ui-color-text-secondary);
    font-size: var(--ui-font-size-sm);
    white-space: nowrap;
}
.ui-chip-primary { background: var(--ui-color-primary-soft); border-color: var(--ui-color-primary-border); color: var(--ui-color-primary-hover); }
.ui-chip-success { background: var(--ui-color-success-soft); border-color: var(--ui-color-success-border); color: var(--ui-color-success-strong); }
.ui-chip-warning { background: var(--ui-color-warning-soft); border-color: var(--ui-color-warning-border); color: var(--ui-color-warning-strong); }
.ui-chip-danger  { background: var(--ui-color-danger-soft);  border-color: var(--ui-color-danger-border); color: var(--ui-color-danger-strong); }
.ui-chip-violet  { background: var(--ui-color-violet-soft);  border-color: var(--ui-color-violet-border); color: var(--ui-color-violet-strong); }
.ui-chip-ghost   { background: var(--ui-surface-muted); border-color: transparent; color: var(--ui-color-text-muted); }
.ui-chip-sm      { height: 22px; padding: 0 8px; font-size: var(--ui-font-size-xs); }
.ui-chip button {
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font-size: 14px;
    line-height: 1;
    opacity: .55;
    cursor: pointer;
}
.ui-chip button:hover { opacity: 1; }

/* ═══ Индикатор живости ═════════════════════════════════════════════════
   По умолчанию статичный: на странице с несколькими десятками сервисов
   мигание превращается в рябь. Пульс — осознанный выбор через -pulse. */
.ui-live-dot {
    display: inline-block;
    width: 7px; height: 7px;
    flex: none;
    border-radius: 50%;
    background: var(--ui-color-success);
    box-shadow: 0 0 0 3px rgba(16, 185, 129, .18);
}
.ui-live-dot-warn, .ui-live-dot.wait { background: var(--ui-color-warning); box-shadow: 0 0 0 3px rgba(245, 158, 11, .18); }
.ui-live-dot-down, .ui-live-dot.down { background: var(--ui-color-danger);  box-shadow: 0 0 0 3px rgba(239, 68, 68, .18); }
.ui-live-dot-idle, .ui-live-dot.idle { background: var(--ui-neutral-400);   box-shadow: 0 0 0 3px rgba(148, 163, 184, .18); }
.ui-live-dot-pulse { animation: uiLiveBlink 1.6s infinite; }
@keyframes uiLiveBlink {
    0%   { box-shadow: 0 0 0 0   rgba(16, 185, 129, .55); }
    70%  { box-shadow: 0 0 0 6px rgba(16, 185, 129, 0);   }
    100% { box-shadow: 0 0 0 0   rgba(16, 185, 129, 0);   }
}

/* ═══ Панель инструментов ═══════════════════════════════════════════════
   Строка над таблицей: поиск, фильтры, действия. `.ui-toolbar-grow`
   отодвигает всё, что после него, к правому краю. */
.ui-toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--ui-spacing-2);
    padding: var(--ui-spacing-2) var(--ui-spacing-3);
    border: 1px solid var(--ui-border-color);
    border-radius: var(--ui-radius-md);
    background: var(--ui-surface-sunken);
}
.ui-toolbar-sep  { width: 1px; height: 20px; background: var(--ui-border-color); flex: none; }
.ui-toolbar-grow { margin-left: auto; }
.ui-toolbar-title {
    font-size: var(--ui-font-size-sm);
    font-weight: var(--ui-weight-semi);
    color: var(--ui-color-text-muted);
}

/* ═══ Пустое состояние ══════════════════════════════════════════════════
   Пустой экран обязан объяснить, ЧТО здесь бывает и что сделать сейчас.
   Поэтому в нём есть действие, а не только фраза «нет данных». */
.ui-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--ui-spacing-3);
    padding: var(--ui-spacing-8);
    border: 1px dashed var(--ui-neutral-300);
    border-radius: var(--ui-radius-md);
    background: var(--ui-surface-sunken);
    text-align: center;
}
.ui-empty-mark { width: 38px; height: 38px; color: var(--ui-color-text-faint); }
.ui-empty-title { font-size: var(--ui-font-size-lg); font-weight: var(--ui-weight-semi); }
.ui-empty-text  { max-width: 46ch; font-size: var(--ui-font-size-sm); color: var(--ui-color-text-muted); }

/* ═══ Плитка со значением ═══════════════════════════════════════════════
   Крупное число оправдано только когда само число — суть экрана. */
.ui-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
    gap: var(--ui-spacing-3);
}
.ui-tile {
    padding: var(--ui-spacing-3) var(--ui-spacing-4);
    border: 1px solid var(--ui-border-color);
    border-radius: var(--ui-radius-md);
    background: var(--ui-surface);
}
.ui-tile-key {
    font-size: var(--ui-font-size-xs);
    font-weight: var(--ui-weight-bold);
    letter-spacing: var(--ui-tracking-label);
    text-transform: uppercase;
    color: var(--ui-color-text-faint);
}
.ui-tile-value {
    margin-top: 3px;
    font-size: var(--ui-font-size-2xl);
    font-weight: var(--ui-weight-bold);
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
}
.ui-tile-note { font-size: var(--ui-font-size-xs); color: var(--ui-color-text-muted); }

/* Плитка-ссылка: быстрое действие на dashboard. Иконка слева (24px, из
   /media/icons), заголовок + заметка справа. Без собственных цветов:
   рамка подсвечивается акцентом при наведении. */
.ui-tile-link {
    display: flex;
    align-items: center;
    gap: var(--ui-spacing-3);
    color: inherit;
    text-decoration: none;
    transition: border-color var(--ui-duration), box-shadow var(--ui-duration);
}
.ui-tile-link:hover,
.ui-tile-link:focus-visible { border-color: var(--ui-color-primary); box-shadow: 0 1px 3px rgba(0, 0, 0, .06); }
.ui-tile-link > img,
.ui-tile-link > svg { width: 24px; height: 24px; flex: none; color: var(--ui-color-text-muted); }
.ui-tile-title { font-weight: var(--ui-weight-semi); }

/* ═══ Врезка ════════════════════════════════════════════════════════════ */
.ui-callout {
    padding: var(--ui-spacing-3) var(--ui-spacing-4);
    border-left: 3px solid var(--ui-color-primary);
    border-radius: 0 var(--ui-radius-md) var(--ui-radius-md) 0;
    background: var(--ui-color-primary-soft);
    font-size: var(--ui-font-size-sm);
}
.ui-callout-warning { border-left-color: var(--ui-color-warning); background: var(--ui-color-warning-soft); }
.ui-callout-danger  { border-left-color: var(--ui-color-danger);  background: var(--ui-color-danger-soft); }
.ui-callout-success { border-left-color: var(--ui-color-success); background: var(--ui-color-success-soft); }
.ui-callout-title   { display: block; margin-bottom: 2px; font-weight: var(--ui-weight-bold); }

/* ═══ Простая таблица ═══════════════════════════════════════════════════
   Статический список без сортировки, ресайза и группировки. Когда нужны они
   — берётся <ui-data-grid>, а не этот класс; здесь нет ни JS, ни состояния.
   Обёртка `.ui-table-wrap` даёт рамку и обрезает содержимое (overflow: clip)
   — сама она никогда не прокручивается. Горизонтальную прокрутку даёт
   вложенный `.ui-table-scroll` (overflow-x: auto); таблица НИКОГДА не
   должна распирать страницу вбок.

   Липкая шапка (`th { position: sticky; top: 0 }`) работает ровно в двух
   формах:
     .ui-table-wrap.ui-fill > .ui-table-scroll.ui-scroll > table.ui-table
       — таблица на остаток высоты, прокрутка внутри самой .ui-table-scroll;
     .ui-table-wrap > table.ui-table (без .ui-fill/.ui-scroll)
       — таблица прокручивается вместе со страницей или внешним .ui-scroll,
         шапка липнет к нему.
   В `.ui-table-wrap > .ui-table-scroll > table` БЕЗ класса `.ui-scroll` на
   `.ui-table-scroll` шапка не липнет — это просто горизонтальный скроллер
   (overflow-x: auto), по вертикали он не прокручивается, и sticky прилипать
   не к чему. */
.ui-table-wrap {
    border: 1px solid var(--ui-border-color);
    border-radius: var(--ui-radius-md);
    /* clip, а не hidden: hidden делал обёртку контейнером прокрутки, и липкая
       шапка th прилипала к коробке, которая никогда не прокручивается.
       Строка ниже — fallback для Safari < 16, где clip не поддерживается
       (там обёртка станет контейнером прокрутки, но это лучше, чем overflow
       без обрезки вовсе). */
    overflow: hidden;
    overflow: clip;
}
.ui-table-scroll { overflow-x: auto; }
/* Таблица на остаток высоты: обёртка передаёт высоту, прокрутка — внутри,
   th липнет к .ui-table-scroll. */
.ui-table-wrap.ui-fill { display: flex; flex-direction: column; }
.ui-table-scroll.ui-scroll { overflow: auto; }

table.ui-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--ui-font-size-md);
}
table.ui-table th {
    position: sticky;
    top: 0;
    z-index: 1;
    padding: 9px 12px;
    background: var(--ui-surface-sunken);
    border-bottom: 1px solid var(--ui-border-color);
    text-align: left;
    white-space: nowrap;
    font-size: var(--ui-font-size-xs);
    font-weight: var(--ui-weight-bold);
    letter-spacing: var(--ui-tracking-label);
    text-transform: uppercase;
    color: var(--ui-color-text-muted);
}
table.ui-table td {
    padding: 9px 12px;
    border-bottom: 1px solid var(--ui-neutral-100);
    vertical-align: middle;
}
table.ui-table tbody tr:last-child td { border-bottom: 0; }
table.ui-table tbody tr:hover td { background: var(--ui-color-primary-soft); }
table.ui-table-compact th,
table.ui-table-compact td { padding: 5px 10px; }

/* Числа выравниваются по правому краю и моноширинно — иначе разряды
   не сопоставить взглядом. */
table.ui-table .ui-td-num {
    text-align: right;
    font-family: var(--ui-font-mono);
    font-size: var(--ui-font-size-sm);
    font-variant-numeric: tabular-nums;
}
table.ui-table .ui-td-mono {
    font-family: var(--ui-font-mono);
    font-size: var(--ui-font-size-sm);
    color: var(--ui-color-text-muted);
}
/* Колонка действий: правая, иконочная, не тянется — общее правило CRUD. */
table.ui-table th.ui-td-actions,
table.ui-table td.ui-td-actions {
    width: 84px;
    text-align: right;
    white-space: nowrap;
}
table.ui-table .ui-td-wrap { white-space: normal; overflow-wrap: anywhere; }

.ui-table-foot {
    display: flex;
    align-items: center;
    gap: var(--ui-spacing-3);
    padding: 8px 12px;
    border-top: 1px solid var(--ui-border-color);
    background: var(--ui-surface-sunken);
    font-size: var(--ui-font-size-sm);
    color: var(--ui-color-text-muted);
}

/* ═══ Статичная раскладка ═══════════════════════════════════════════════
   Цепочка высот: каркас → .ui-fill → .ui-scroll. Страница не прокручивается,
   прокручиваются только .ui-scroll. min-height:0 обязателен: без него flex-
   ребёнок растёт по содержимому и выталкивает прокрутку наружу. */
.ui-fill {
    flex: 1 1 auto;
    min-height: 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
}
.ui-row-fill {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: row;
}
.ui-row-fill > * { min-width: 0; }
.ui-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
}
@media (max-width: 768px) {
    /* На узком экране колонки встают друг под другом и делят высоту. */
    .ui-row-fill { flex-direction: column; }
}

/* ═══ Панель ═════════════════════════════════════════════════════════════
   Простой контейнер без JS и без сворачивания (в отличие от <ui-card>).
   Шапка липнет к верху, только когда сама панель движется внутри ВНЕШНЕГО
   скроллера (например `.ui-panel` как ребёнок `.ui-scroll`); с
   `.ui-panel-body.ui-scroll` шапка просто остаётся на месте, потому что она
   снаружи прокручиваемой области — ей незачем прилипать. Если `.ui-table`
   стоит внутри НЕ прокручивающегося `.ui-panel-body`, а прокручивается
   внешний `.ui-scroll`, `th` этой таблицы нужно явно сдвинуть под шапку
   панели: `th { top: <высота .ui-panel-head> }`. */
.ui-panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    background: var(--ui-surface);
    border: 1px solid var(--ui-border-color);
    border-radius: var(--ui-radius-md);
    /* hidden — fallback для Safari < 16, где overflow:clip не поддерживается. */
    overflow: hidden;
    overflow: clip;
}
.ui-panel-head {
    position: sticky;
    top: 0;
    z-index: 2;
    flex-shrink: 0;
    padding: 10px 14px;
    background: var(--ui-surface-sunken);
    border-bottom: 1px solid var(--ui-border-color);
    font-weight: var(--ui-weight-bold);
}
.ui-panel-body { padding: 12px 14px; }

/* ═══ Мелочи ════════════════════════════════════════════════════════════ */
.ui-mono  { font-family: var(--ui-font-mono); font-size: var(--ui-font-size-sm); }
.ui-muted { color: var(--ui-color-text-muted); }
.ui-faint { color: var(--ui-color-text-faint); }
.ui-label {
    font-size: var(--ui-font-size-xs);
    font-weight: var(--ui-weight-bold);
    letter-spacing: var(--ui-tracking-label);
    text-transform: uppercase;
    color: var(--ui-color-text-faint);
}
.ui-code-inline {
    padding: 1px 5px;
    border-radius: 4px;
    background: var(--ui-surface-muted);
    font-family: var(--ui-font-mono);
    font-size: var(--ui-font-size-sm);
}

/* ═══ Тон иконки роли ═══════════════════════════════════════════════════
   Классы ставит UIRoleIcon (lib/role-icons.js) на inline-SVG; цвет идёт
   через currentColor. `{ noTone: true }` — без класса. */
.ui-role-tone-admin     { color: var(--ui-color-danger); }
.ui-role-tone-manager   { color: var(--ui-color-warning); }
.ui-role-tone-customer  { color: var(--ui-color-success); }
.ui-role-tone-corporate { color: var(--ui-color-primary); }
.ui-role-tone-designer  { color: var(--ui-color-violet); }
.ui-role-tone-sales     { color: var(--ui-color-cyan); }
.ui-role-tone-visitor,
.ui-role-tone-guest,
.ui-role-tone-default   { color: var(--ui-color-text-faint); }
