/* ═══════════════════════════════════════════════════════════════════════════
   PRODUCT-UI — нарисованный интерфейс продукта, общий для страниц сайта

   Не «стили страницы», а маленькая библиотека: те же компоненты рисуют и
   кандидат главной (/test2), и страница про контроль производства (/test3),
   и всё, что появится дальше — хаб функций, тарифы, блог.

   ПОЧЕМУ ОТДЕЛЬНЫМ ФАЙЛОМ. Пока компоненты лежали внутри test2.css, у второй
   страницы был ровно один способ их получить — скопировать. Две копии
   расходятся на первой же правке данных: номер заказа поменяли в одном
   месте, в другом остался прежний, и никто об этом не узнает.

   ИМЕНА ВЗЯТЫ ИЗ test2.css НАМЕРЕННО. Макет второй страницы называет то же
   самое иначе (hero-app, process-board, queue-screen, chart-screen), но
   переименовывать проверенную страницу ради новой — платить отзывом её
   мобильной вёрстки. Словарь принимает новая страница, а не наоборот.

   ОДНО ПЕРЕИМЕНОВАНИЕ: .pill → .ui-pill. Единственное имя нарисованного
   интерфейса, которое уже занято сайтом (landing.css: .pill, .pill.orange,
   .pill.dot::before). Общая библиотека не может носить имя, которое сайт
   вправе поменять под себя.

   ПОРЯДОК ПОДКЛЮЧЕНИЯ: после landing.css, до файла страницы. Тогда страница
   может доопределить компонент под себя, а сайт — не может его сломать.

   ПОРЯДОК ПРАВИЛ ВНУТРИ сохранён из test2.css как есть, включая медиазапросы
   в двух написаниях. Это не небрежность: при равной специфичности выигрывает
   то, что ниже, и перестановка правил здесь молча поменяла бы вид страницы,
   которая уже проверена на пяти ширинах.

   РАЗМЕТКА НЕ ЗДЕСЬ. Она в страницах: обе показывают РАЗНЫЕ операции, и общий
   партиал без параметров навязал бы одной странице данные другой (build.js
   параметров не умеет). Исключение — карточка заказа с зафиксированным
   набором (26-031 · Монтаж-Сервис · 243 000 ₽): она в partials/ui-order-card.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Токены — из candidate.css (.p-cand на <body>). Свои имена компонент не
   объявляет: он пришёл из test2.css вместе с её словарём, и пока тот словарь
   жил в :root страницы, ссылки разрешались молча. Проверка var() в build.js
   поймала их в тот момент, когда :root страницы удалили. */


.app-top{height:48px;border-bottom:1px solid var(--c-line);display:flex;align-items:center;padding:0 16px}
.top-chip{height:34px;padding:0 12px;border-radius:999px;background:#f5f1ed;color:#5b5550;font-size:var(--c-fs-small);font-weight:600;display:grid;place-items:center}
.app-layout{display:grid;grid-template-columns:264px 1fr;min-height:630px}
.app-side{border-right:1px solid var(--c-line);padding:18px 14px 16px;background:#fcfbfa}
.app-brand{display:flex;align-items:center;gap:10px;font-size:19px;font-weight:600;padding:6px 10px 14px}
.app-brand .mark{width:24px;height:24px;background:var(--c-accent);border-radius:50%;color:#fff;display:grid;place-items:center;font-size:11px}
.side-section{padding:10px 10px 8px;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:#a29b93}
.side-nav{display:grid;gap:4px}
.side-item{height:40px;padding:0 12px;border-radius:10px;display:flex;align-items:center;gap:11px;color:#635e57;font-size:15px}
.side-item.on{background:#fff1ea;color:var(--c-accent);font-weight:600}
.side-icon{width:16px;height:16px;color:currentColor;flex:0 0 auto}
.side-btn{margin:16px 0 14px;height:46px;border:2px solid var(--c-accent);border-radius:12px;color:var(--c-accent);font-weight:600;display:grid;place-items:center}
.app-main{background:#faf8f6;padding:12px 18px 18px}
.dashboard-title{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;padding:4px 2px 12px}
.dashboard-title h3{margin:0;font-size:var(--c-fs-h3);letter-spacing:-.04em;font-weight:var(--c-fw-head);line-height:1.05}
.dashboard-title p{margin:4px 0 0;font-size:15px;color:var(--c-muted-2)}
.attention{display:flex;justify-content:space-between;align-items:center;gap:12px;border:1px solid var(--c-line);background:#fff;border-radius:14px;padding:10px 14px}
.attention-left{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.warn-icon{width:16px;height:16px;color:var(--c-red)}
.ui-pill{display:inline-flex;align-items:center;justify-content:center;height:28px;padding:0 11px;border-radius:999px;font-size:13px;font-weight:600;white-space:nowrap}
.attention-link{font-size:15px;color:#6d6760}
.kpis-wide{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-top:12px}
.wide-kpi,.mini-kpi{background:#fff;border:1px solid var(--c-line);border-radius:14px;padding:14px}
.wide-kpi small,.mini-kpi small{display:block;font-size:13px;color:var(--c-muted-2)}
.wide-kpi b,.mini-kpi b{display:block;font-size:24px;line-height:1.05;margin-top:4px;font-weight:var(--c-fw-head);letter-spacing:-.03em}
.wide-kpi b.green-t{color:var(--c-green)}
.wide-kpi b.red-t{color:var(--c-red)}
.wide-kpi b.orange-t{color:#c96d18}
.kpis-mini{display:grid;grid-template-columns:repeat(5,1fr);gap:10px;margin-top:10px}
.mini-kpi b{font-size:20px}
.mini-kpi .sub{font-size:13px;color:var(--c-muted-2);margin-top:3px}
.mini-kpi .sub.red-t{color:var(--c-red)}
.mini-kpi .sub.green-t{color:var(--c-green)}
.mini-kpi .sub.orange-t{color:#c96d18}
.order-table .row{display:grid;grid-template-columns:1.1fr 1.1fr .85fr .56fr .6fr .65fr;gap:10px;padding:11px 14px;border-bottom:1px solid var(--c-line);align-items:center;font-size:13px}
.order-table .row.head{font-size:12px;color:#8b847d;font-weight:600;background:#fcfbfa}
.order-table .row:last-child{border-bottom:0}
.order-table b{font-size:14px;font-weight:600}
.order-code{position:relative;padding-left:12px}
.order-code:before{content:"";position:absolute;left:0;top:8px;width:7px;height:7px;border-radius:50%;background:currentColor}
.table-progress{height:6px;background:#ece9e4;border-radius:999px;overflow:hidden}
.table-progress i{display:block;height:100%;background:var(--c-accent);border-radius:999px}
.table-progress.green i{background:#28b27f}
.table-progress.gray i{background:#d8d2cb}
.table-progress.yellow i{background:#f0a100}
.metric-card{background:#fff;border:1px solid var(--c-line);border-radius:18px;padding:22px;box-shadow:var(--c-shadow)}
.metric-top{display:flex;justify-content:space-between;gap:24px;align-items:flex-start}
.metric-top small{display:block;font-size:16px;color:var(--c-muted-2);line-height:1.2}
.metric-top b{display:block;font-size:var(--c-fs-h2);line-height:1;margin-top:8px;font-weight:var(--c-fw-head);letter-spacing:-.04em}
.spark{height:152px;margin-top:22px;position:relative;background:linear-gradient(to bottom,transparent 24%,#ece7e1 25%,transparent 26%,transparent 49%,#ece7e1 50%,transparent 51%,transparent 74%,#ece7e1 75%,transparent 76%)}
.spark svg{position:absolute;inset:0;width:100%;height:100%}
.kanban{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;height:100%}
.kanban-col{border-radius:14px;background:#ecebe8;padding:12px}
.kanban-head{display:flex;justify-content:space-between;align-items:center;font-size:14px;font-weight:600;margin-bottom:10px}
.k-card{background:#fff;border:1px solid var(--c-line);border-radius:12px;padding:12px 12px 11px;margin-bottom:8px}
.k-card small{display:block;font-size:12px;color:var(--c-muted-2)}
.k-card b{display:block;font-size:15px;font-weight:600;margin:5px 0;line-height:1.2}
.k-card span{display:block;font-size:12px;color:#c47710}
.k-card.done{opacity:.78}
.k-card.done b{text-decoration:none}
.k-card.done span{color:#27aa79}
.stock-list{display:grid;gap:12px;align-content:center;height:100%;max-width:none;width:100%;margin:0;padding:12px 10px}
.stock-item{background:#fff;border:1px solid var(--c-line);border-radius:16px;padding:14px 16px;box-shadow:0 6px 18px rgba(0,0,0,.03)}
.stock-head{display:flex;justify-content:space-between;align-items:flex-start;gap:14px}
.stock-meta{display:flex;flex-direction:column;gap:6px;min-width:0}
.stock-meta b{font-size:18px;line-height:1.16;font-weight:var(--c-fw-head)}
.stock-meta small{font-size:14px;color:var(--c-muted-2);line-height:1.2}
.stock-bar{height:7px;background:#ece9e5;border-radius:999px;overflow:hidden;margin-top:12px}
.stock-bar i{display:block;height:100%;border-radius:999px}
.stock-item.warn i{width:46%;background:#eca500}
.stock-item.ok i{width:82%;background:#19b38b}
.finance-box{background:#fff;border:1px solid var(--c-line);border-radius:18px;padding:18px 28px;box-shadow:var(--c-shadow)}
.finance-box small{display:block;font-size:14px;color:var(--c-muted-2)}
.finance-box .sum{font-size:40px;line-height:1.04;font-weight:var(--c-fw-head);letter-spacing:-.04em;margin:6px 0 12px;white-space:nowrap}
.finance-row{display:flex;justify-content:space-between;gap:16px;padding:9px 0;border-top:1px solid var(--c-line);font-size:15px;line-height:1.25}
.finance-row b{font-weight:600;white-space:nowrap}
.finance-row span{white-space:nowrap}
.finance-row .green-t{color:var(--c-green)}
.orders-ui{background:#fff;border:1px solid var(--c-line);border-radius:18px;overflow:hidden;box-shadow:var(--c-shadow)}
.orders-head{display:flex;gap:10px;flex-wrap:wrap;padding:14px 16px;border-bottom:1px solid var(--c-line)}
.orders-chip{font-size:13px;color:#6a655e}
.orders-chip.on{height:30px;padding:0 10px;border-radius:999px;background:#171717;color:#fff;display:grid;place-items:center;font-weight:600}
.orders-row{display:grid;grid-template-columns:.72fr 1.42fr 1fr .78fr .52fr;gap:12px;padding:14px 16px;border-bottom:1px solid var(--c-line);align-items:center;font-size:13px}
.orders-row:last-child{border-bottom:0}
.orders-row b{font-size:14px;font-weight:600}
.order-finance{display:grid;grid-template-columns:1.2fr .8fr;gap:10px}
.order-main{background:#fff;border:1px solid var(--c-line);border-radius:18px;padding:22px 18px 18px 22px}
.order-title{font-size:20px;font-weight:var(--c-fw-head);letter-spacing:-.03em;margin-bottom:12px}
.order-sub{font-size:13px;color:var(--c-muted-2);margin-top:5px}
.order-step{display:grid;grid-template-columns:1.05fr .9fr .65fr;gap:8px;padding:12px 0;border-top:1px solid var(--c-line);align-items:center;font-size:13px}
.order-step:first-of-type{border-top:0}
.order-step b{font-size:14px;font-weight:600}
.order-side{display:grid;gap:8px}

@media(max-width:1180px) {
  .kpis-mini{grid-template-columns:repeat(3,1fr)}
}

@media(max-width:880px) {
  .app-layout{grid-template-columns:1fr}
  .app-side{display:none}
  .kpis-wide{grid-template-columns:1fr}
  .kpis-mini{grid-template-columns:1fr 1fr}
  .order-table .row{grid-template-columns:1fr 1.1fr .8fr .56fr}
  .order-table .row span:nth-child(5),.order-table .row span:nth-child(6),.order-table .row div:nth-child(5),.order-table .row div:nth-child(6){display:none}
}

@media(max-width:640px) {
  .app-main{padding:10px}
  .attention,.app-top{padding-inline:10px}
  .kpis-mini{grid-template-columns:1fr}
  .order-finance{grid-template-columns:1fr}
  .order-side{grid-template-columns:1fr}
}
.app-layout>*{min-width:0}
.app-main{min-width:0;overflow:hidden}
.dashboard-title h3,.dashboard-title p,.attention,.wide-kpi,.mini-kpi,.ui-pill,.top-chip,.side-item,.side-btn{white-space:nowrap}
.attention-left{flex-wrap:nowrap;min-width:0;overflow:hidden}
.attention-left>span{flex:0 0 auto}
.attention-link{white-space:nowrap;flex:0 0 auto}
.kpis-wide>*,.kpis-mini>*{min-width:0}
.wide-kpi small,.mini-kpi small{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.order-table .row>*{min-width:0;overflow:hidden;text-overflow:ellipsis}
.order-table .row>*>div{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.order-table .row>div,.order-table .row>span,.order-table .row>b{white-space:nowrap}
.order-table .row .ui-pill{max-width:100%;overflow:hidden;text-overflow:ellipsis}
.kanban-col,.k-card,.stock-item,.stock-meta{min-width:0}
.k-card small,.k-card b,.k-card span{overflow:hidden;text-overflow:ellipsis}
.k-card small,.k-card span{white-space:nowrap}
.k-card b{display:block;white-space:nowrap}
.stock-head{min-width:0}
.stock-meta b,.stock-meta small{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.orders-ui{min-width:0}
.orders-head{flex-wrap:nowrap;overflow:hidden}
.orders-chip{white-space:nowrap;flex:0 0 auto}
.orders-row>*{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.orders-row .ui-pill{max-width:100%;height:28px;padding:0 10px;font-size:12px;justify-self:start}
.order-main,.order-side,.order-step>*{min-width:0}
.order-step>*{overflow:hidden;text-overflow:ellipsis}
.order-step b,.order-step span{white-space:nowrap}

/* min-width жил здесь и обрезал /test3 на 321px: тот же компонент лежит там
   в колонке 737px. Это свойство МЕСТА, а не компонента, поэтому уехало на
   страницу, которая его задаёт (см. .p-t2 .app-layout в test2.css). */
.stock-list,.finance-box{display:grid;gap:22px}
.stock-item,.finance-row{margin:0}
.finance-box{padding:24px 28px}
.finance-row{padding:12px 0}

@media (min-width: 881px) and (max-width: 1159px) {
  .app-layout { min-width: 0; grid-template-columns: 1fr; }
  .app-side   { display: none; }
}

@media (max-width: 640px) {
  /* [1] СТРОКА «ТРЕБУЕТ ВНИМАНИЯ» — В СТОЛБИК.
     Была flex-строкой с nowrap + overflow:hidden на левой части: при 100px
     ширины против 451px нужных обрезались ОБЕ плашки с числами, то есть
     ровно то, ради чего компонент существует. Остаётся подпись и ссылка. */
  .attention      { flex-direction: column; align-items: flex-start; gap: 8px; }
  .attention-left { flex-wrap: wrap; overflow: visible; }
  .attention-left > span { flex: 0 1 auto; }
  /* [2] ТАБЛИЦА ЗАКАЗОВ — КАРТОЧКАМИ.
     Четыре колонки на 375 не живут: плашка статуса резалась с обеих сторон
     («Просрочено» → «Іросроче»), названия клиентов обрывались, а сумма
     переносилась на вторую строку, из-за чего шапка переставала совпадать
     со своими же данными. Шапку убираем — подписи столбцов без столбцов
     смысла не имеют, — а строку раскладываем в карточку. */
  .order-table .row.head { display: none; }
  .order-table .row {
    grid-template-columns: 1fr auto;
    gap: 6px 10px;
    padding: 12px 14px;
  }
  .order-table .row > *            { overflow: visible; text-overflow: clip;
                                     white-space: normal; min-width: 0; }
  .order-table .row > *:nth-child(1) { grid-column: 1; }
  /* номер   */
  .order-table .row > *:nth-child(3) { grid-column: 2; justify-self: end; }
  /* статус */
  .order-table .row > *:nth-child(2) { grid-column: 1 / -1; }
  /* название */
  .order-table .row > *:nth-child(4) { grid-column: 1; }
  /* срок    */
  .order-table .row > *:nth-child(6) { grid-column: 2; justify-self: end;
                                       display: block; }
  /* сумма   */
  .order-table .row > *:nth-child(5) { grid-column: 1 / -1; }
  /* готовность */
  .order-table .row .ui-pill { white-space: nowrap; }
  .stock-list     { height: auto; align-content: start; }
  /* Две из четырёх иллюстраций свёрстаны как ВНУТРЕННОСТЬ фиксированной рамки:
     .metric-card центрируется через top:50%+translate, .finance-box растянут
     через inset. От абсолютного потока рамка с height:auto схлопывается в
     46px — замерено, стало ХУЖЕ, чем было. Поэтому на узком экране они
     возвращаются в обычный поток и рамка растёт под них. */
  /* [6] Лента фильтров доски — та же болезнь, что у строки внимания:
     flex-wrap:nowrap + overflow:hidden. Плашки «Просрочено · 2» и «Готово · 4»
     обрезались целиком. */
  .orders-head  { flex-wrap: wrap; overflow: visible; }
  .single-canvas > .orders-ui,
  .single-canvas > .order-finance { position: static; inset: auto; transform: none; }
}

/* ─── РАЗМЕЩЕНИЕ — НЕ ДЕЛО КОМПОНЕНТА ──────────────────────────────────────
   У четырёх компонентов (.metric-card, .finance-box, .orders-ui,
   .order-finance) здесь стояло `position:absolute` с `inset`. Это было не
   их свойство, а способ, которым /test2 кладёт их в рамку фиксированной
   высоты. Вторая страница показала это сразу: в обычном потоке список
   заказов растянулся на 1404px внутри карточки шириной 620.

   Компонент отвечает за то, КАК он выглядит; за то, ГДЕ он лежит, отвечает
   страница. Размещение переехало в test2.css под собственные рамки. */
