/* ============================================================================
   РАЦИН-портал — тема Orchid «Графит + Янтарь»
   Источник дизайна: docs/40-ui/portal_main_maket.zip (k27-mock, схема GRAPHITE).
   Накладывается поверх precompiled-ассетов Orchid 14 (Bootstrap 5) как
   override-стиль. Подключается через resources/views/vendor/platform/header.blade.php
   (@push('head')). Сборка не требуется — обычный статический CSS.

   Это также seed дизайн-токенов набора ps-ui-orchid (docs/40-ui/spec-ps-ui-orchid-primitives.md):
   токены ниже (--rp-*) — единый источник цветов/радиусов/шрифта для будущих
   компонентов Sandbox.
   Раунд: F · f1 (Фаза 5 Этап 5.2). Палитра вынута из brand.jsx + GRAPHITE-схемы макета.
   ========================================================================= */

/* ---- 1. Дизайн-токены (палитра «Графит + Янтарь») ------------------------- */
:root {
    /* поверхности */
    --rp-bg:            #EFEEEA;  /* фон рабочей области */
    --rp-card:          #FFFFFF;  /* карточки / поля */
    --rp-line:          #E5E4E0;  /* границы */
    --rp-line-2:        #F4F3F0;  /* мягкая граница / зебра */

    /* текст */
    --rp-ink:           #23262B;  /* основной текст / заголовки */
    --rp-sub:           #5E646C;  /* вторичный текст */
    --rp-faint:         #99A0A8;  /* третичный / подсказки */

    /* графит (primary) */
    --rp-primary:       #2C2F36;
    --rp-primary-ink:   #FFFFFF;
    --rp-primary-soft:  #E9EAEC;
    --rp-primary-deep:  #1B1D22;

    /* янтарь (accent) */
    --rp-accent:        #F5B301;
    --rp-accent-deep:   #C98F00;
    --rp-accent-soft:   #FBF1D6;

    /* семантика */
    --rp-green:         #1F9D55;
    --rp-red:           #E2483D;
    /* w377 (решение Владельца 04.08): тот же красный, но пригодный ПОД БЕЛЫЙ ТЕКСТ. Замер: на
       `--rp-red` белое даёт 4.02:1 при пороге 4.5 для мелкого жирного (бейдж — 11px/800), на этом
       оттенке — 4.98:1. Семантика прежняя: «непрочитанное», «опасность» — тот же красный, темнее
       ровно настолько, чтобы надпись на нём читалась. */
    --rp-red-deep:      #D32F2F;
    --rp-blue:          #2C7BE5;
    /* мягкие фоны семантики + янтарь-предупреждение (набор w6, зеркало ps-ui-orchid.jsx) */
    --rp-green-soft:    #DFF3E6;
    --rp-red-soft:      #FBE3E1;
    --rp-blue-soft:     #DEEBFB;
    --rp-amber:         #E5A400;
    --rp-amber-soft:    #FBEFCB;

    /* сайдбар (тёмный графит) */
    --rp-sidebar:        #1F2228;
    --rp-sidebar-line:   #313640;
    --rp-sidebar-ink:    #ECEEF1;
    --rp-sidebar-sub:    #A2A9B2;
    --rp-sidebar-faint:  #6B727C;
    --rp-sidebar-active-bg:  rgba(245, 179, 1, 0.16);
    --rp-sidebar-active-ink: #F5C24A;

    /* геометрия / шрифт */
    --rp-radius:         12px;
    --rp-radius-lg:      16px;
    --rp-font: "Manrope", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

/* ---- 2. Глобальные переменные Bootstrap (Orchid) -------------------------- */
:root {
    --bs-body-bg:           var(--rp-bg);
    --bs-body-color:        var(--rp-ink);
    --bs-body-font-family:  var(--rp-font);
    --bs-emphasis-color:    var(--rp-ink);
    --bs-secondary-color:   var(--rp-sub);
    --bs-tertiary-color:    var(--rp-faint);
    --bs-border-color:      var(--rp-line);
    --bs-border-radius:        var(--rp-radius);
    --bs-border-radius-sm:     8px;
    --bs-border-radius-lg:     var(--rp-radius-lg);
    --bs-primary:           var(--rp-primary);
    --bs-primary-rgb:       44, 47, 54;
    --bs-link-color:        var(--rp-accent-deep);
    --bs-link-hover-color:  var(--rp-accent);
    --bs-success:           var(--rp-green);
    --bs-danger:            var(--rp-red);
    --bs-info:              var(--rp-blue);
    --bs-warning:           var(--rp-accent);
}

/* ---- 3. Типографика ------------------------------------------------------- */
/* 🔴 scrollbar-gutter — w287 (п.4 отчёта 30.07): «при переключении между вкладками дёргается фон
   боковой панели». Замер на вкладках автопарка (окно 1600×720, учётка cabinet-working@): «Бензовозы»
   дают страницу 756px — вертикальная полоса прокрутки есть; «Прицепы» и «Водители» укладываются в
   720px — полосы нет. То есть при каждом переключении окно то теряло, то возвращало ~15px ширины, и
   вся раскладка (вместе с фотографией сайдбара, которая кадрируется по ширине панели) прыгала.
   Место под полосу теперь зарезервировано всегда — переходы перестают дёргать вёрстку по всему
   порталу, а не только в автопарке. Остаток дефекта (фон пересчитывается по ВЫСОТЕ панели) — в
   отчёте раунда: он лечится только сменой геометрии фонового слоя, а она зафиксирована решением
   автора (см. комментарий у `.cab-nav::before`). */
html { background: var(--rp-bg); scrollbar-gutter: stable; }
body {
    margin: 0;                       /* убрать дефолтную рамку 8px вокруг кабинета (w9 #4) — фон до краёв */
    font-family: var(--rp-font);
    background: var(--rp-bg);
    color: var(--rp-ink);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    font-family: var(--rp-font);
    letter-spacing: -0.01em;
    color: var(--rp-ink);
}

/* в макете крупные заголовки экранов жирные (fw 800), Orchid ставит fw-light */
.workspace header h1,
h1.fw-light {
    font-weight: 800 !important;
}

/* ---- 3a. Бренд РАЦИН — фирменный знак картинкой (w57; прежний текстовый wordmark снят) */
.rp-brand { display: inline-flex; align-items: center; line-height: 1; }
/* знак широкий (≈2.5:1): задаём высоту, ширина — авто; не растягиваем и не обрезаем.
   align-self — чтобы во flex-колонке (панель входа) бокс не растягивался на всю ширину */
.rp-logo { display: block; width: auto; max-width: 100%; height: 26px; align-self: flex-start; flex: 0 0 auto; }
@media (max-width: 400px) { .rp-logo { height: 22px; } }

/* ---- 4. Сайдбар (тёмный графит) ------------------------------------------ */
.aside {
    background: var(--rp-sidebar) !important;
    border-right: 1px solid var(--rp-sidebar-line);
    --bs-emphasis-color: #FFFFFF;
    --bs-emphasis-color-rgb: 255, 255, 255;
}

/* в тёмном сайдбаре админки — белая версия знака (подключается вариантом, не цветом) */

/* пункты навигации */
.aside .nav-link {
    color: var(--rp-sidebar-sub);
    border-radius: 10px;
    padding: 10px 12px;
    font-weight: 600;
    transition: background 0.15s ease, color 0.15s ease;
    position: relative;
}
.aside .nav-link .orchid-icon,
.aside .nav-link svg {
    color: var(--rp-sidebar-faint);
    transition: color 0.15s ease;
}
.aside .nav-link:hover {
    background: rgba(255, 255, 255, 0.06);
    color: var(--rp-sidebar-ink);
}
.aside .nav-link:hover .orchid-icon,
.aside .nav-link:hover svg {
    color: var(--rp-sidebar-ink);
}

/* активный пункт — янтарная подсветка + золотой акцент слева */
.aside .nav-link.active,
.aside .nav-pills .nav-link.active,
.aside .nav-item.active > .nav-link {
    background: var(--rp-sidebar-active-bg) !important;
    color: var(--rp-sidebar-active-ink) !important;
    font-weight: 700;
}
.aside .nav-link.active::before {
    content: "";
    position: absolute;
    left: 0;
    top: 9px;
    bottom: 9px;
    width: 3px;
    border-radius: 3px;
    background: var(--rp-sidebar-active-ink);
}
.aside .nav-link.active .orchid-icon,
.aside .nav-link.active svg {
    color: var(--rp-sidebar-active-ink) !important;
}

/* заголовки групп меню */
.aside .nav-item small.text-muted {
    color: var(--rp-sidebar-faint) !important;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 11px;
    font-weight: 700;
}

/* блок профиля внизу сайдбара */
.aside .profile-container {
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--rp-sidebar-line);
}
.aside .profile-container .text-white { color: #FFFFFF !important; }
.aside .profile-container .text-muted { color: var(--rp-sidebar-sub) !important; }

/* ---- 5. Поверхности / карточки ------------------------------------------- */
.bg-white { background-color: var(--rp-card) !important; }
.bg-light { background-color: var(--rp-line-2) !important; }

.workspace .bg-white.rounded,
.workspace .rounded.shadow-sm,
.card {
    border-radius: var(--rp-radius-lg) !important;
    border: 1px solid var(--rp-line);
    box-shadow: 0 1px 2px rgba(35, 38, 43, 0.04);
}

/* ---- 6. Кнопки ------------------------------------------------------------ */
.btn {
    font-weight: 600;
    border-radius: var(--rp-radius);
}
.btn-primary,
.btn-dark {
    --bs-btn-bg: var(--rp-primary);
    --bs-btn-border-color: var(--rp-primary);
    --bs-btn-hover-bg: var(--rp-primary-deep);
    --bs-btn-hover-border-color: var(--rp-primary-deep);
    --bs-btn-active-bg: var(--rp-primary-deep);
    --bs-btn-color: var(--rp-primary-ink);
    --bs-btn-hover-color: var(--rp-primary-ink);
}
.btn-warning {
    --bs-btn-bg: var(--rp-accent);
    --bs-btn-border-color: var(--rp-accent);
    --bs-btn-hover-bg: var(--rp-accent-deep);
    --bs-btn-hover-border-color: var(--rp-accent-deep);
    --bs-btn-color: #FFFFFF;
    --bs-btn-hover-color: #FFFFFF;
}
.btn-link { color: var(--rp-accent-deep); }

/* ---- 7. Поля ввода -------------------------------------------------------- */
.form-control,
.form-select {
    border-radius: var(--rp-radius);
    border-color: var(--rp-line);
    color: var(--rp-ink);
    font-weight: 500;
}
.form-control:focus,
.form-select:focus {
    border-color: var(--rp-accent);
    box-shadow: 0 0 0 3px rgba(245, 179, 1, 0.2);
}
.form-control::placeholder { color: var(--rp-faint); }
.form-label { font-weight: 700; color: var(--rp-ink); }

/* ---- 8. Бейджи / статусы -------------------------------------------------- */
.badge { font-weight: 600; border-radius: 999px; }
.bg-success { background-color: var(--rp-green) !important; }
.bg-danger  { background-color: var(--rp-red) !important; }
.bg-warning { background-color: var(--rp-accent) !important; color: #FFFFFF !important; }
.bg-info    { background-color: var(--rp-blue) !important; }
.text-success { color: var(--rp-green) !important; }
.text-danger  { color: var(--rp-red) !important; }
.text-warning { color: var(--rp-accent-deep) !important; }

/* ---- 9. Хлебные крошки / заголовок экрана --------------------------------- */
.breadcrumb { font-size: 13px; }
.breadcrumb-item a { color: var(--rp-sub); text-decoration: none; }
.breadcrumb-item.active { color: var(--rp-ink); font-weight: 600; }

/* золотой акцент-подчёрк под заголовком экрана (как в макете) */
.command-bar-wrapper header h1 {
    position: relative;
    padding-bottom: 10px;
}
.command-bar-wrapper header h1::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 54px;
    height: 3px;
    border-radius: 2px;
    background: var(--rp-accent);
}

/* ---- 10. Таблицы ---------------------------------------------------------- */
/* Скин Orchid-таблицы (Layout::table) под вид набора ps-ui-orchid — ADR-0016:
   списки админки рендерит Orchid, а выглядят как `.ps-table` (секция 16).
   Здесь переносим состояния набора на разметку Orchid (`.table`, пагинатор). */
.table {
    --bs-table-border-color: var(--rp-line);
    color: var(--rp-ink);
    font-size: 14px;
    margin-bottom: 0;
    --bs-table-hover-bg: var(--rp-line-2);
    --bs-table-hover-color: var(--rp-ink);
    --bs-table-striped-bg: rgba(244, 243, 240, 0.55);
    --bs-table-striped-color: var(--rp-ink);
}
.table > thead th {
    color: var(--rp-faint);
    font-weight: 700;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    background: var(--rp-line-2);
    border-bottom: 1px solid var(--rp-line);
    padding: 12px 16px;
    white-space: nowrap;
}
.table > tbody td { padding: 13px 16px; border-bottom-color: var(--rp-line-2); vertical-align: middle; }
.table > tbody tr:last-child td { border-bottom: none; }
.table:not(.table-striped) > tbody tr { transition: background .12s; }
.table:not(.table-striped) > tbody tr:hover { background: var(--rp-line-2); }
/* сорт-заголовок Orchid (TD->sort() отдаёт ссылку в th) */
.table > thead th a { color: inherit; text-decoration: none; display: inline-flex; align-items: center; gap: 6px; }
.table > thead th a:hover { color: var(--rp-sub); }
.table > thead th a .orchid-icon,
.table > thead th a svg { opacity: .55; }
.table > thead th a:hover .orchid-icon,
.table > thead th a:hover svg { opacity: .9; color: var(--rp-accent-deep); }
.table--compact > thead th, .table.table-compact > thead th { padding: 8px 12px; }
.table--compact > tbody td, .table.table-compact > tbody td { padding: 8px 12px; }
/* утилиты ячеек (двухстрочные значения в списках) */
.td-strong { font-weight: 700; color: var(--rp-ink); }
.td-sub { color: var(--rp-faint); font-size: 12.5px; }

/* Скин пагинатора Orchid (Bootstrap .pagination) под вид `.ps-pagination`/`.ps-page` */
.pagination { display: flex; gap: 6px; flex-wrap: wrap; margin: 0; --bs-pagination-border-color: var(--rp-line); }
.pagination .page-item .page-link {
    min-width: 36px; height: 36px; padding: 0 10px; border-radius: 9px;
    border: 1px solid var(--rp-line); background: var(--rp-card); color: var(--rp-sub);
    font-weight: 700; font-size: 13.5px; display: inline-flex; align-items: center; justify-content: center;
    transition: border-color .12s, color .12s, background .12s;
}
.pagination .page-item .page-link:hover { border-color: var(--rp-accent-deep); color: var(--rp-accent-deep); background: var(--rp-card); z-index: 0; }
.pagination .page-item.active .page-link { background: var(--rp-primary); border-color: var(--rp-primary); color: #fff; }
.pagination .page-item.disabled .page-link { opacity: .5; border-color: var(--rp-line); background: var(--rp-card); }
.pagination .page-item .page-link:focus { box-shadow: 0 0 0 3px rgba(245, 179, 1, 0.2); }

/* ---- 11. Кастомный скроллбар (BR: примитив дизайн-системы) ---------------- */
* { scrollbar-width: thin; scrollbar-color: rgba(35, 38, 43, 0.22) transparent; }
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-thumb {
    background: rgba(35, 38, 43, 0.18);
    border-radius: 7px;
    border: 3px solid transparent;
    background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background: rgba(35, 38, 43, 0.32); background-clip: padding-box; }

/* ---- 12. Sandbox-витрина (служебные утилиты показа компонентов) ----------- */
.rp-sandbox-note {
    border: 1px dashed var(--rp-line);
    background: var(--rp-card);
    border-radius: var(--rp-radius-lg);
    padding: 32px;
    color: var(--rp-sub);
}
.rp-sandbox-note .rp-sandbox-badge {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: var(--rp-accent-soft);
    color: var(--rp-accent-deep);
    font-weight: 700;
    font-size: 12.5px;
    padding: 4px 11px;
    border-radius: 999px;
    margin-bottom: 14px;
}
.rp-sandbox-note h2 { font-weight: 800; margin: 0 0 8px; }

/* ---- 13. Адаптив (BR-18) -------------------------------------------------- */
@media (max-width: 991.98px) {
    .aside { border-right: none; border-bottom: 1px solid var(--rp-sidebar-line); }
    .command-bar-wrapper header h1 { font-size: 1.4rem; }
}

/* ============================================================================
   14. Экраны авторизации (Fortify-views) — макет auth_maket.zip
   Сплит-экран: брендовая графит-панель + аграрное фото слева, форма справа.
   На общих токенах --rp-* (единый набор с ps-ui-orchid / Sandbox). Раунд: F · f2.
   ========================================================================= */
.auth-root {
    min-height: 100vh;
    display: flex;
    font-family: var(--rp-font);
    color: var(--rp-ink);
    background: var(--rp-card);
}

/* — левая брендовая панель — */
.auth-brand {
    position: relative;
    width: 560px;
    flex-shrink: 0;
    overflow: hidden;
    background: var(--rp-sidebar);
}
.auth-brand__photo {
    position: absolute; inset: 0;
    background-image: var(--auth-photo, none);
    background-size: cover;
    background-position: 55% 64%;
    filter: grayscale(0.45) brightness(1.05) contrast(0.95);
}
.auth-brand__overlay {
    position: absolute; inset: 0;
    background: linear-gradient(178deg,
        var(--rp-sidebar) 0%, var(--rp-sidebar) 30%,
        rgba(31,34,40,0.9) 46%, rgba(31,34,40,0.5) 66%,
        rgba(31,34,40,0.12) 88%, rgba(31,34,40,0) 100%);
}
.auth-brand__stripe { position: absolute; top: 0; left: 0; right: 0; height: 4px; background: var(--rp-accent); }
.auth-brand__inner {
    position: relative; z-index: 1;
    height: 100%; min-height: 100vh;
    padding: 44px 52px;
    display: flex; flex-direction: column;
}
.auth-brand__logo { height: 38px; }   /* знак на брендовой панели входа (w57) */
.auth-brand__pitch { margin-top: auto; }
.auth-brand__tag {
    display: inline-flex; align-items: center; gap: 8px;
    background: rgba(255,255,255,0.1);
    border: 1px solid rgba(255,255,255,0.18);
    border-radius: 999px; padding: 6px 13px 6px 11px;
    backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
    margin-bottom: 20px;
    font-size: 12.5px; font-weight: 700; color: rgba(255,255,255,0.9);
}
.auth-brand__tag .dot { width: 7px; height: 7px; border-radius: 4px; background: var(--rp-accent); }
.auth-brand__h1 {
    font-size: 36px; line-height: 1.12; font-weight: 800; letter-spacing: -0.02em;
    margin: 0; color: #fff; max-width: 430px; text-wrap: balance;
}
.auth-brand__sub { font-size: 15.5px; line-height: 1.5; color: rgba(255,255,255,0.78); margin: 16px 0 0; max-width: 400px; }

/* — правая колонка с формой — */
.auth-col { flex: 1; min-width: 0; display: flex; flex-direction: column; max-height: 100vh; overflow-y: auto; }
.auth-support { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 24px 40px 0; }
.auth-support .lbl { font-size: 13px; color: var(--rp-faint); }
.auth-support .num { font-size: 13px; font-weight: 700; color: var(--rp-sub); }
/* w387: номер стал ССЫЛКОЙ tel: — с телефона по нему звонят. Вид прежний: подчёркивание и
   ссылочный цвет здесь были бы шумом, это контакт, а не навигация. */
.auth-support a.num { text-decoration: none; }
.auth-support a.num:hover { color: var(--rp-ink); }
.auth-form-area { flex: 1; display: flex; align-items: center; justify-content: center; padding: 32px 40px 48px; }
.auth-form-wrap { width: 408px; max-width: 100%; }

/* — заголовки формы — */
.auth-title { font-size: 27px; font-weight: 800; letter-spacing: -0.015em; margin: 0; color: var(--rp-ink); }
.auth-accent { width: 46px; height: 3px; border-radius: 2px; background: var(--rp-accent); margin: 12px 0 0; }
.auth-lead { font-size: 14.5px; color: var(--rp-sub); margin: 13px 0 24px; line-height: 1.45; }

/* — поля — */
.auth-field { margin-bottom: 16px; }
.auth-label { display: block; font-size: 13.5px; font-weight: 700; margin-bottom: 8px; color: var(--rp-ink); }
.auth-label-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.auth-label-row .auth-label { margin-bottom: 0; }
.auth-input-shell {
    display: flex; align-items: center; gap: 11px;
    background: var(--rp-card);
    border: 1.6px solid var(--rp-line);
    border-radius: 12px; height: 52px; padding: 0 14px;
    transition: border-color .15s, box-shadow .15s;
}
.auth-input-shell:focus-within { border-color: var(--rp-accent); box-shadow: 0 0 0 3px rgba(245,179,1,0.2); }
.auth-input-shell.is-error { border-color: var(--rp-red); box-shadow: 0 0 0 3px rgba(226,72,61,0.13); }
.auth-input-shell.is-ok { border-color: var(--rp-green); box-shadow: 0 0 0 3px rgba(31,157,85,0.1); }
.auth-input {
    flex: 1; min-width: 0; border: none; outline: none; background: transparent;
    font-family: var(--rp-font); font-size: 15.5px; font-weight: 500; color: var(--rp-ink);
}
.auth-input::placeholder { color: var(--rp-faint); }
.auth-field-icon { color: var(--rp-faint); flex-shrink: 0; }
.is-error .auth-field-icon { color: var(--rp-red); }
.is-ok .auth-field-icon { color: var(--rp-green); }
.auth-eye { display: flex; background: none; border: none; cursor: pointer; padding: 2px; color: var(--rp-faint); }
/* глазик: видна ровно одна иконка (обёртки .i-off/.i-on переключаются hidden) — w54 */
.auth-eye .i-off, .auth-eye .i-on, .ps-field__ico-btn .i-off, .ps-field__ico-btn .i-on { display: flex; }
.auth-eye [hidden], .ps-field__ico-btn [hidden] { display: none !important; }
.auth-hint { margin-top: 7px; font-size: 12.5px; color: var(--rp-faint); }
.auth-ok-hint { margin-top: 7px; font-size: 12.5px; font-weight: 600; color: var(--rp-green); display: flex; align-items: center; gap: 6px; }
.auth-error { display: flex; align-items: center; gap: 6px; margin-top: 7px; font-size: 12.5px; font-weight: 600; color: var(--rp-red); }
.auth-error-icon { flex-shrink: 0; }

/* — индикатор парольной политики — */
.auth-pwd-policy { display: flex; flex-wrap: wrap; gap: 7px 14px; margin: -6px 0 16px; }
.auth-pwd-policy .chk { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600; color: var(--rp-faint); }
.auth-pwd-policy .chk .box { width: 14px; height: 14px; border-radius: 7px; border: 1.5px solid var(--rp-line); display: flex; align-items: center; justify-content: center; }
.auth-pwd-policy .chk.on { color: var(--rp-green); }
.auth-pwd-policy .chk.on .box { background: var(--rp-green); border-color: var(--rp-green); color: #fff; }
/* w155: СОВЕТ по составу пароля — намеренно без галочки и без зелёного: галочка читается как
   выполненное требование, а состав сервер не проверяет. Требование — выше, совет — здесь. */
.auth-pwd-advice { margin: -10px 0 16px; font-size: 12px; color: var(--rp-faint); }

/* — капча (визуальный плейсхолдер; серверная сверка — за B) — */
.auth-captcha { margin-bottom: 16px; }
.auth-captcha__row { display: flex; gap: 10px; }
.auth-captcha__img {
    width: 132px; height: 52px; border-radius: 12px; flex-shrink: 0;
    background: repeating-linear-gradient(135deg, #EDEBE5 0 6px, #F6F5F1 6px 12px);
    border: 1.6px solid var(--rp-line);
    display: flex; align-items: center; justify-content: center; overflow: hidden;
    position: relative; user-select: none;
}
.auth-captcha__img .ch {
    display: inline-block; font-family: "JetBrains Mono", ui-monospace, monospace;
    font-size: 25px; font-weight: 700; color: var(--rp-ink); opacity: 0.82;
}
.auth-captcha__refresh {
    width: 52px; height: 52px; border-radius: 12px; flex-shrink: 0;
    border: 1.6px solid var(--rp-line); background: var(--rp-card); cursor: pointer; color: var(--rp-sub);
    display: flex; align-items: center; justify-content: center;
}
/* w380 (ТЗ Владельца 04.08, «Замечания»): поле кода НЕ должно выпирать по ширине относительно
   остальных инпутов и кнопки «Зарегистрироваться». Причина была не в самом поле, а в правиле
   флексов: у флекс-элемента `min-width` по умолчанию `auto`, поэтому оболочка поля не сжималась
   ниже собственной ширины (input по умолчанию size=20 символов) — ряд капчи разъезжался до 453px
   при колонке формы 408px и 310px на 360-м экране. `min-width: 0` разрешает сжатие. */
.auth-captcha__input { flex: 1; min-width: 0; }
.auth-captcha__input input { width: 100%; }
.auth-captcha__input input { font-family: "JetBrains Mono", ui-monospace, monospace; font-weight: 700; letter-spacing: 0.15em; text-transform: uppercase; }

/* — кнопки / ссылки — */
.auth-btn {
    width: 100%; height: 54px; margin-top: 6px;
    display: flex; align-items: center; justify-content: center; gap: 9px;
    background: var(--rp-primary); color: var(--rp-primary-ink);
    border: none; border-radius: 13px;
    font-family: var(--rp-font); font-size: 16px; font-weight: 800; cursor: pointer;
    transition: background .15s;
}
.auth-btn:hover { background: var(--rp-primary-deep); }
.auth-btn:disabled { background: var(--rp-line); color: var(--rp-faint); cursor: not-allowed; }
.auth-btn--ghost { background: var(--rp-card); color: var(--rp-ink); border: 1.6px solid var(--rp-line); }
.auth-btn--ghost:hover { background: var(--rp-line-2); }
.auth-link { color: var(--rp-accent-deep); font-weight: 600; text-decoration: none; }
.auth-link:hover { color: var(--rp-accent); }
.auth-foot { font-size: 14px; color: var(--rp-sub); text-align: center; margin: 22px 0 0; }
.auth-foot a { color: var(--rp-accent-deep); font-weight: 700; text-decoration: none; }
/* — согласие под кнопкой регистрации (w387, ТЗ Владельца §2) —
   Мелкий вторичный текст: это условие, а не заголовок. Ссылки на документы — отдельной строкой
   и с иконкой: они СКАЧИВАЮТСЯ, и человек должен видеть, что это файлы, а не разделы сайта. */
.auth-consent { font-size: 12.5px; line-height: 1.45; color: var(--rp-faint); text-align: center; margin: 14px 0 0; }
.auth-consent--links { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 16px; margin-top: 8px; }
.auth-consent--links a { display: inline-flex; align-items: center; gap: 5px; color: var(--rp-accent-deep); font-weight: 600; text-decoration: none; }
.auth-consent--links a:hover { color: var(--rp-accent); text-decoration: underline; }

.auth-back { display: inline-flex; align-items: center; gap: 7px; background: none; border: none; color: var(--rp-sub); font-family: var(--rp-font); font-size: 13.5px; font-weight: 700; cursor: pointer; padding: 0; margin-bottom: 20px; text-decoration: none; }

/* — баннеры/состояния — */
.auth-banner { display: flex; gap: 11px; align-items: flex-start; border-radius: 12px; padding: 12px 14px; margin-bottom: 18px; }
.auth-banner.ok  { background: rgba(31,157,85,0.08); border: 1px solid rgba(31,157,85,0.28); }
.auth-banner.err { background: rgba(226,72,61,0.08); border: 1px solid rgba(226,72,61,0.28); }
.auth-banner.info{ background: rgba(245,179,1,0.09); border: 1px solid rgba(245,179,1,0.3); }
.auth-banner .ico-ok  { color: var(--rp-green); flex-shrink: 0; }
.auth-banner .ico-err { color: var(--rp-red); flex-shrink: 0; }
.auth-banner .ico-info{ color: var(--rp-accent-deep); flex-shrink: 0; }
.auth-banner .ttl { font-size: 13.5px; font-weight: 700; color: var(--rp-ink); margin-bottom: 2px; }
.auth-banner .txt { font-size: 13px; color: var(--rp-sub); line-height: 1.45; }
.auth-centered { text-align: center; }
.auth-centered__icon { width: 64px; height: 64px; border-radius: 32px; display: flex; align-items: center; justify-content: center; margin: 0 auto 20px; }
.auth-centered__icon.ok  { background: rgba(31,157,85,0.12); color: var(--rp-green); }
.auth-centered__icon.err { background: rgba(226,72,61,0.12); color: var(--rp-red); }
.auth-centered h2 { font-size: 24px; font-weight: 800; letter-spacing: -0.01em; margin: 0 0 10px; }
.auth-centered p { font-size: 14.5px; color: var(--rp-sub); line-height: 1.5; margin: 0 auto 24px; max-width: 360px; }
.auth-centered__actions { display: flex; flex-direction: column; gap: 10px; }

/* — адаптив (BR-18): на узких экранах брендовая панель скрывается — */
@media (max-width: 880px) {
    .auth-brand { display: none; }
    .auth-col { max-height: none; }
    .auth-support { padding: 16px 20px 0; }
    .auth-form-area { padding: 24px 20px 40px; }
}

/* — ЭЦП на регистрации (w272): выбор сертификата, кнопка подписи, состояния —
   🔴 Стили висят на КЛАССАХ И АТРИБУТАХ, которые ставит eds-client.js, а не на классах из Blade:
   всю разметку внутри точки монтирования (`select.eds-select`, `.eds-state`, кнопку
   `[data-eds-nonce-submit]`) создаёт скрипт, из шаблона туда класс не передать. Крипто-слой при этом
   не тронут — CSS ничего не знает о подписи.
   Те же классы работают и в «Моей организации» (там тот же CertificatePicker) — до w272 их не было
   оформлено нигде. */
.eds-picker { margin-top: 4px; }
.eds-select {
    width: 100%; height: 52px; padding: 0 14px; margin-top: 2px;
    background: var(--rp-card); color: var(--rp-ink);
    border: 1.6px solid var(--rp-line); border-radius: 13px;
    font-family: var(--rp-font); font-size: 15px; font-weight: 600; cursor: pointer;
}
.eds-select:focus { outline: none; border-color: var(--rp-accent-deep); }
.eds-select option:disabled { color: var(--rp-faint); }
/* Состояния списка (загрузка / нет плагина / нет сертификатов / отказ) — блоком, а не голым текстом. */
.eds-state {
    display: flex; flex-direction: column; gap: 8px; align-items: flex-start;
    border: 1.6px dashed var(--rp-line); border-radius: 13px; padding: 14px 16px;
    background: var(--rp-line-2);
}
.eds-state__msg { margin: 0; font-size: 13.5px; line-height: 1.45; color: var(--rp-sub); }
[data-eds-state="error"] .eds-state,
[data-eds-state="plugin_missing"] .eds-state {
    border-style: solid; border-color: rgba(226,72,61,0.28); background: rgba(226,72,61,0.06);
}
[data-eds-state="error"] .eds-state__msg,
[data-eds-state="plugin_missing"] .eds-state__msg { color: var(--rp-ink); }
[data-eds-instruction] { font-size: 13px; font-weight: 700; color: var(--rp-accent-deep); text-decoration: none; }
.eds-note { margin: 0 0 10px; font-size: 13px; line-height: 1.45; color: var(--rp-sub); }
/* Кнопку подписи вставляет скрипт сразу за точкой монтирования — вид «главного действия» экрана. */
[data-eds-nonce-submit] {
    width: 100%; height: 54px; margin-top: 12px;
    display: flex; align-items: center; justify-content: center; gap: 9px;
    background: var(--rp-primary); color: var(--rp-primary-ink);
    border: none; border-radius: 13px;
    font-family: var(--rp-font); font-size: 16px; font-weight: 800; cursor: pointer;
    transition: background .15s;
}
[data-eds-nonce-submit]:hover { background: var(--rp-primary-deep); }
[data-eds-nonce-submit]:disabled { background: var(--rp-line); color: var(--rp-faint); cursor: not-allowed; }
/* 🔴 w380: на ШАГЕ ПОДПИСАНИЯ документа главное действие — «Подписать ЭЦП», а привязка сертификата
   вспомогательна. Полноширинная тёмная плашка (вид выше) там перетягивала бы внимание на себя и
   читалась как главная кнопка экрана. Селектор узкий: соседняя кнопка точки выбора, помеченной как
   держатель подписи, — на регистрации и в «Моей организации» (гейта нет) вид не меняется.
   Кнопку скрипт вставляет сразу за точкой монтирования, поэтому соседний комбинатор и работает. */
[data-eds-sign-gate] + [data-eds-nonce-submit],
[data-eds-sign-gate] ~ [data-eds-demo-bind] {
    width: auto; height: 44px; padding: 0 18px; margin-top: 10px;
    background: var(--rp-card); color: var(--rp-ink);
    border: 1.6px solid var(--rp-line); border-radius: 12px;
    font-family: var(--rp-font); font-size: 14.5px; font-weight: 700; cursor: pointer;
}
[data-eds-sign-gate] + [data-eds-nonce-submit]:hover,
[data-eds-sign-gate] ~ [data-eds-demo-bind]:hover { background: var(--rp-line-2); }
/* Отказ проверки: пустой узел не должен занимать место и рисовать пустую рамку. */
.eds-error { margin-top: 12px; font-size: 13.5px; font-weight: 600; line-height: 1.45; color: var(--rp-red); }
.eds-error:empty { display: none; }
.eds-logout { display: flex; align-items: baseline; justify-content: center; gap: 6px; flex-wrap: wrap; }
.eds-logout__btn {
    background: none; border: none; padding: 0; cursor: pointer;
    font-family: var(--rp-font); font-size: 14px; font-weight: 700; color: var(--rp-accent-deep);
}
.eds-logout__btn:hover { color: var(--rp-accent); }

/* ============================================================================
   15. Набор компонентов ps-ui-orchid (Sandbox-витрина)
   Источник: docs/40-ui/portal_main_maket.zip (wizard-*.jsx) + spec-ps-ui-orchid-primitives.md.
   Переиспользуемая коллекция на токенах --rp-*. Раунд: F · f3 (ЦР-75).
   Используется Blade-компонентами resources/views/components/ps/* и витриной Sandbox.
   ========================================================================= */

/* — витрина: каркас секций — */
.ps-toolbar { position: sticky; top: 0; z-index: 5; display: flex; flex-wrap: wrap; gap: 8px; padding: 12px 0 16px; background: var(--rp-bg); margin-bottom: 8px; }
.ps-toolbar a { font-size: 13px; font-weight: 600; color: var(--rp-sub); text-decoration: none; padding: 6px 11px; border-radius: 8px; border: 1px solid var(--rp-line); background: var(--rp-card); }
.ps-toolbar a:hover { border-color: var(--rp-accent-deep); color: var(--rp-accent-deep); }
.ps-section { background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: var(--rp-radius-lg); padding: 22px 24px; margin-bottom: 18px; scroll-margin-top: 16px; }
.ps-section > h2 { font-size: 18px; font-weight: 800; margin: 0 0 4px; color: var(--rp-ink); }
.ps-section > .ps-section__sub { font-size: 13px; color: var(--rp-faint); margin: 0 0 18px; }
.ps-group { margin-bottom: 22px; }
.ps-group:last-child { margin-bottom: 0; }
.ps-group__label { font-size: 11px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--rp-faint); margin-bottom: 10px; }
.ps-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.ps-col { display: flex; flex-direction: column; gap: 14px; max-width: 380px; }
/* F2·w388: вертикальный стек полей БЕЗ ограничения ширины. `.ps-col` для этого не годится — у него
   max-width 380px под узкие демо-колонки; а поля, стоящие в секции формы подряд (не в сетке), до
   сих пор шли вплотную: отступы давала только `.ps-form__grid`, и одиночное поле с подсказкой
   слипалось со следующей подписью. */
.ps-stack { display: flex; flex-direction: column; gap: 14px; }
.ps-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px; }

/* — каталог-реестр набора + ярусы (w5) —
   Обзор набора «с высоты птичьего полёта»: реестр сверху (по 3 ярусам, каждая
   запись → якорь на живое демо), ярус-разделители над секциями демонстраций. */
.ps-catalog { background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: var(--rp-radius-lg); padding: 22px 24px; margin-bottom: 18px; scroll-margin-top: 16px; }
.ps-catalog > h2 { font-size: 18px; font-weight: 800; margin: 0 0 4px; color: var(--rp-ink); }
.ps-catalog__lead { font-size: 13px; color: var(--rp-faint); margin: 0 0 18px; max-width: 800px; }
.ps-catalog__tier { margin-bottom: 20px; }
.ps-catalog__tier:last-child { margin-bottom: 0; }
.ps-catalog__head { display: flex; align-items: baseline; gap: 9px; margin-bottom: 12px; }
.ps-catalog__head .n { font-size: 11px; font-weight: 800; letter-spacing: .03em; color: var(--rp-accent-deep); background: var(--rp-accent-soft); border-radius: 999px; padding: 3px 10px; white-space: nowrap; }
.ps-catalog__head .t { font-size: 14.5px; font-weight: 800; color: var(--rp-ink); }
.ps-catalog__head .c { font-size: 12px; color: var(--rp-faint); font-weight: 600; margin-left: auto; }
.ps-catalog__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(236px, 1fr)); gap: 10px; }

.ps-reg { display: block; text-decoration: none; background: var(--rp-bg); border: 1px solid var(--rp-line); border-radius: var(--rp-radius); padding: 12px 14px; transition: border-color .14s, box-shadow .14s, transform .06s; }
a.ps-reg:hover { border-color: var(--rp-accent-deep); box-shadow: 0 2px 12px rgba(0,0,0,.05); }
a.ps-reg:active { transform: translateY(1px); }
.ps-reg__top { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.ps-reg__name { font-size: 13.5px; font-weight: 700; color: var(--rp-ink); }
.ps-reg__tag { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; font-weight: 600; color: var(--rp-sub); background: var(--rp-line-2); border: 1px solid var(--rp-line); border-radius: 6px; padding: 2px 6px; white-space: nowrap; }
.ps-reg__desc { font-size: 12px; color: var(--rp-faint); line-height: 1.45; }
.ps-reg--backlog { background: transparent; border-style: dashed; cursor: default; }
.ps-reg--backlog .ps-reg__name { color: var(--rp-sub); }
.ps-reg--backlog .ps-reg__name::before { content: "☐ "; color: var(--rp-faint); }

/* ярус-разделители над секциями демонстраций */
.ps-tier { display: flex; align-items: baseline; flex-wrap: wrap; gap: 12px; margin: 34px 0 16px; padding-bottom: 10px; border-bottom: 2px solid var(--rp-line); scroll-margin-top: 16px; }
.ps-tier:first-of-type { margin-top: 10px; }
.ps-tier__no { font-size: 12px; font-weight: 800; letter-spacing: .04em; color: var(--rp-accent-deep); background: var(--rp-accent-soft); border-radius: 999px; padding: 4px 12px; white-space: nowrap; }
.ps-tier__title { font-size: 20px; font-weight: 800; color: var(--rp-ink); margin: 0; }
.ps-tier__sub { font-size: 13px; color: var(--rp-faint); margin: 0; }

/* галерея иконок (набор <x-ps.icon>) */
.ps-iconwall { display: grid; grid-template-columns: repeat(auto-fill, minmax(94px, 1fr)); gap: 8px; }
.ps-iconwall__cell { display: flex; flex-direction: column; align-items: center; gap: 7px; padding: 13px 6px; background: var(--rp-bg); border: 1px solid var(--rp-line); border-radius: 10px; color: var(--rp-ink); }
.ps-iconwall__cell code { font-size: 11px; color: var(--rp-faint); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }

/* — кнопки — */
.ps-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    height: 44px; padding: 0 18px; border-radius: var(--rp-radius);
    font-family: var(--rp-font); font-size: 14.5px; font-weight: 700;
    border: 1.5px solid transparent; cursor: pointer; white-space: nowrap;
    transition: background .15s, border-color .15s, filter .12s, transform .06s, box-shadow .15s;
    user-select: none; text-decoration: none;
}
.ps-btn:active { transform: translateY(1px); }
.ps-btn--primary { background: var(--rp-primary); color: var(--rp-primary-ink); }
.ps-btn--primary:hover { background: var(--rp-primary-deep); }
.ps-btn--secondary { background: var(--rp-card); color: var(--rp-ink); border-color: var(--rp-line); }
.ps-btn--secondary:hover { background: var(--rp-line-2); border-color: var(--rp-faint); }
.ps-btn--accent { background: var(--rp-accent); color: #fff; }
.ps-btn--accent:hover { background: var(--rp-accent-deep); }
.ps-btn--danger { background: transparent; color: var(--rp-red); border-color: rgba(226,72,61,0.45); }
.ps-btn--danger:hover { background: rgba(226,72,61,0.08); }
.ps-btn--ghost { background: transparent; color: var(--rp-sub); border-color: transparent; }
.ps-btn--ghost:hover { background: var(--rp-line-2); color: var(--rp-ink); }
.ps-btn--sm { height: 36px; padding: 0 13px; font-size: 13px; border-radius: 9px; }
.ps-btn--lg { height: 52px; padding: 0 24px; font-size: 16px; border-radius: 13px; }
.ps-btn--icon { width: 44px; padding: 0; }
.ps-btn--icon.ps-btn--sm { width: 36px; }
.ps-btn:disabled, .ps-btn.is-disabled { background: var(--rp-line); color: var(--rp-faint); border-color: transparent; cursor: not-allowed; transform: none; }
.ps-btn.is-loading { color: transparent !important; position: relative; pointer-events: none; }
.ps-btn.is-loading::after {
    content: ""; position: absolute; width: 17px; height: 17px; border-radius: 50%;
    border: 2.5px solid currentColor; border-top-color: transparent;
    color: var(--rp-primary-ink); animation: ps-spin .6s linear infinite;
}
.ps-btn--secondary.is-loading::after, .ps-btn--danger.is-loading::after, .ps-btn--ghost.is-loading::after { color: var(--rp-sub); }
@keyframes ps-spin { to { transform: rotate(360deg); } }

/* — поля ввода — */
.ps-field { display: flex; flex-direction: column; }
/* display:block — w287 (п.24). Правило «подпись → инпут = 7px» держалось только потому, что подпись
   всегда лежала внутри flex-контейнера `.ps-field` (там элемент блокируется и вертикальный margin
   работает). В рукописной разметке (форма залога) `<label>` оставался СТРОЧНЫМ, а вертикальный margin
   у строчного элемента не применяется — зазор схлопывался в 1px, и отступы «шли вразнобой». Теперь
   правило одно и не зависит от того, кто родитель. */
.ps-field__label { display: block; font-size: 13.5px; font-weight: 700; color: var(--rp-ink); margin-bottom: 7px; }
/* w139: маркер обязательности был заскоуплен на .ps-field__label (кабинет), а экраны входа/
   регистрации используют .auth-label — вставленная там звёздочка не красилась бы вовсе.
   Селектор общий: один маркер на весь портал. */
/* w287: и у ЗАГОЛОВКА СЕКЦИИ тоже — маркер обязательности переехал туда, где блок обязателен целиком
   (форма залога, «Документы залога*»), и без отступа звёздочка липла к слову. */
.ps-field__label .req, .auth-label .req, .ps-form__section-h .req { color: var(--rp-red); margin-left: 3px; }
/* w81: у .ps-select__btn и .ps-dp__btn box-sizing уже был, а у текстового поля — нет: рамки
   прибавлялись к height, и поле выходило 52px против 50px у селекта и датапикера. Поля набора
   были РАЗНОЙ высоты. Задаём по рамке — все поля ровно 50px и совпадают с кнопкой пикера. */
.ps-input-shell {
    box-sizing: border-box;
    display: flex; align-items: center; gap: 11px;
    background: var(--rp-card); border: 1.6px solid var(--rp-line);
    border-radius: var(--rp-radius); height: 50px; padding: 0 14px;
    transition: border-color .15s, box-shadow .15s;
}
.ps-input-shell:focus-within { border-color: var(--rp-accent); box-shadow: 0 0 0 3px rgba(245,179,1,0.2); }
.ps-input-shell.is-error { border-color: var(--rp-red); box-shadow: 0 0 0 3px rgba(226,72,61,0.13); }
.ps-input-shell.is-ok { border-color: var(--rp-green); box-shadow: 0 0 0 3px rgba(31,157,85,0.1); }
.ps-input-shell.is-disabled { background: var(--rp-line-2); border-color: var(--rp-line); cursor: not-allowed; opacity: .75; }
.ps-input { flex: 1; min-width: 0; border: none; outline: none; background: transparent; font-family: var(--rp-font); font-size: 15px; font-weight: 500; color: var(--rp-ink); }
.ps-input::placeholder { color: var(--rp-faint); }
.ps-input:disabled { cursor: not-allowed; }
.ps-field__icon { color: var(--rp-faint); flex-shrink: 0; }
.is-error .ps-field__icon { color: var(--rp-red); }
.is-ok .ps-field__icon { color: var(--rp-green); }
.ps-field__hint { margin-top: 7px; font-size: 12.5px; color: var(--rp-faint); }
/* w255 (п.39): счётчик остатка длины. Отдельный класс, а НЕ .ps-field__hint — логика ошибок поля
   (psFieldShowError/psFieldClearError) гасит и показывает именно hint, и счётчик мигал бы пустой
   строкой на каждом вводе. На пределе — янтарный (портальный warning-цвет). */
.ps-field__count { margin-top: 7px; font-size: 12.5px; color: var(--rp-faint); }
.ps-field__count.is-limit { color: var(--rp-amber); font-weight: 600; }
.ps-field__error { display: flex; align-items: center; gap: 6px; margin-top: 7px; font-size: 12.5px; font-weight: 600; color: var(--rp-red); }
/* hidden-атрибут должен побеждать display:flex (подсказка/ошибка датапикера переключаются им) */
.ps-field__error[hidden], .ps-field__hint[hidden], .ps-field__count[hidden] { display: none !important; }
.ps-field__ico-btn { display: flex; background: none; border: none; cursor: pointer; padding: 2px; color: var(--rp-faint); }

/* — селекты (нативный, стилизованный) — */
/* старый скин нативного <select> (.ps-select-shell) снят в w60: список теперь кастомный,
   а сам селект скрыт под капотом. Класс .ps-select переиспользован контейнером компонента. */

/* — поисковый select (BR-3.2: поиск по нескольким полям) — */
.ps-combo { position: relative; }
.ps-combo__menu { position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 20; background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: 12px; box-shadow: 0 16px 44px rgba(35,38,43,0.14); padding: 6px; max-height: 280px; overflow-y: auto; display: none; }
.ps-combo.is-open .ps-combo__menu { display: block; }
.ps-combo__opt { display: flex; align-items: center; gap: 11px; width: 100%; text-align: left; border: none; background: transparent; border-radius: 9px; padding: 9px 11px; cursor: pointer; font-family: var(--rp-font); }
.ps-combo__opt:hover, .ps-combo__opt.is-active { background: var(--rp-accent-soft); }
.ps-combo__opt .t { font-size: 14px; font-weight: 700; color: var(--rp-ink); }
/* w376: статус-бейдж прямо в опции списка (поверка техники в мастере). Кегль мельче обычного —
   это пометка при подписи, а не самостоятельный статус; строка опции от него не растёт. */
.ps-combo__badge { margin-left: 6px; font-size: 10.5px; padding: 1px 7px; vertical-align: middle; }
.ps-combo__opt .s { font-size: 12.5px; color: var(--rp-sub); }
.ps-combo__opt .av { width: 36px; height: 36px; border-radius: 9px; background: var(--rp-accent-soft); color: var(--rp-accent-deep); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.ps-combo__empty { padding: 14px; text-align: center; font-size: 13px; color: var(--rp-faint); }
.ps-combo__opt.is-selected { background: var(--rp-accent-soft); }
.ps-combo__opt.is-selected .t::after { content: ' ✓'; color: var(--rp-accent-deep); }

/* — множественный выбор <x-ps.multicombo> (F2·w388): те же список и поиск, что у комбо, плюс
     галочка в строке и чипы выбранного под полем. Галочка — та же `.ps-check__box`, что у
     чекбоксов набора: вид отметки в портале один. — */
.ps-multi__opt { cursor: pointer; }
.ps-multi__opt input[type="checkbox"] { position: absolute; opacity: 0; width: 1px; height: 1px; }
.ps-multi__opt .ps-check__box { flex-shrink: 0; }
/* Строка выбранной опции галочку УЖЕ показывает — второй маркер (✓ у подписи) здесь лишний. */
.ps-multi__opt.is-selected .t::after { content: none; }
.ps-multi__chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.ps-multi__chips:empty { display: none; }
.ps-multi__chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 10px; border-radius: 999px; cursor: pointer;
    background: var(--rp-accent-soft); color: var(--rp-accent-deep);
    border: 1px solid transparent;
    font-family: var(--rp-font); font-size: 12.5px; font-weight: 700;
}
.ps-multi__chip::after { content: '×'; font-size: 15px; line-height: 1; opacity: 0.75; }
.ps-multi__chip:hover { border-color: var(--rp-accent-deep); }

/* — кастомная выпадашка <x-ps.select> (w60): список рисуем МЫ, не браузер — */
.ps-select { position: relative; }
/* нативный select — источник значения/валидации/динамики: скрыт визуально, но остаётся в потоке
   (не display:none — иначе браузер не сфокусирует его при провале required) */
.ps-select__native { position: absolute; left: 12px; bottom: 6px; width: 1px; height: 1px; padding: 0; border: 0; opacity: 0; pointer-events: none; }
.ps-select__btn {
    display: flex; align-items: center; gap: 10px; width: 100%; height: 50px; box-sizing: border-box;
    padding: 0 14px; border: 1.6px solid var(--rp-line); border-radius: var(--rp-radius);
    background: var(--rp-card); cursor: pointer; font-family: var(--rp-font); text-align: left;
    transition: border-color .15s, box-shadow .15s;
}
.ps-select__btn:hover { border-color: var(--rp-faint); }
.ps-select__btn:focus-visible { outline: none; border-color: var(--rp-accent); box-shadow: 0 0 0 3px rgba(245,179,1,.2); }
.ps-select.is-open .ps-select__btn { border-color: var(--rp-accent); box-shadow: 0 0 0 3px rgba(245,179,1,.2); }
.ps-select.is-error .ps-select__btn { border-color: var(--rp-red); box-shadow: 0 0 0 3px rgba(226,72,61,.13); }
.ps-select.is-disabled .ps-select__btn { background: var(--rp-line-2); cursor: not-allowed; opacity: .75; }
.ps-select__value { flex: 1; min-width: 0; font-size: 15px; font-weight: 500; color: var(--rp-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-select__value.is-placeholder { color: var(--rp-faint); font-weight: 400; }
.ps-select__chev { color: var(--rp-faint); flex-shrink: 0; transition: transform .18s; }
.ps-select.is-open .ps-select__chev { transform: rotate(180deg); }
/* меню — ровно по ширине поля */
.ps-select__menu {
    position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 40; display: none; box-sizing: border-box;
    padding: 6px; background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: 12px;
    box-shadow: 0 16px 44px rgba(35,38,43,.14); max-height: 280px; overflow-y: auto;
}
.ps-select.is-open .ps-select__menu { display: block; }
.ps-select__opt { display: flex; align-items: center; gap: 8px; width: 100%; padding: 9px 11px; border: none; border-radius: 9px; background: transparent; cursor: pointer; font-family: var(--rp-font); text-align: left; }
.ps-select__opt .t { flex: 1; min-width: 0; font-size: 14px; font-weight: 600; color: var(--rp-ink); overflow-wrap: anywhere; }
.ps-select__opt .m { color: var(--rp-accent-deep); flex-shrink: 0; }
.ps-select__opt:hover, .ps-select__opt:focus-visible { background: var(--rp-line-2); outline: none; }
.ps-select__opt.is-selected { background: var(--rp-accent-soft); }
.ps-select__opt.is-selected .t { font-weight: 800; }
.ps-select__opt.is-empty .t { color: var(--rp-faint); font-weight: 500; }
/* ── Вариант «список с картинками» (F·w356, запрос клиента 01.08) ────────────────────────────────
   Картинка слева от подписи — и у пунктов, и у выбранного значения. Кадр тот же приём, что у строк
   автопарка (`.fleet-thumb`, w355) и карточек сцепки мастера: ОДНА пропорция на все картинки (по
   самой широкой из набора техники — полуприцеп 426×185) + `object-fit: contain`. Отсюда главное
   свойство списка: подписи пунктов начинаются от ОДНОЙ вертикали независимо от того, какой формы
   машина нарисована, и короткий прицеп не растягивается до ширины полуприцепа.
   Кадр рисуется, только если вызывающий передал карту картинок: у обычных селектов портала (тип
   налива, страна, вид цены) разметка не меняется вовсе. */
.ps-select__ico { flex: 0 0 auto; height: 22px; aspect-ratio: 426 / 185; display: flex; align-items: center; justify-content: center; }
.ps-select__ico img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* В свёрнутом поле кадр чуть крупнее: там он один и соседствует с 15px подписью, а не с 14px. */
.ps-select__btn--img .ps-select__ico { height: 26px; }

/* — кастомный датапикер <x-ps.datepicker> (w60): свой календарь; ОДНА иконка (справа, крупная) — */
.ps-field__label--dp { margin-bottom: 9px; }          /* заголовок не прилипает к полю (замечание автора) */
/* w369 (отчёт 02.08 ч.2, п.6): в панели фильтров отступ под заголовком — ОДИН на оба фильтра.
   🔴 Уравниваю ВВЕРХ, к 9px автора, а не вниз к общим 7px: 9px — записанное решение автора
   («заголовок не прилипает к полю»), и переигрывать его ради выравнивания двух блоков нельзя.
   Правило заскоуплено на панель: остальные формы портала остаются на своих 7px и не сдвигаются. */
.ps-filters--fields .ps-field__label { margin-bottom: 9px; }
.ps-dp { position: relative; width: 190px; max-width: 100%; }   /* поле под дату — не зияет пустотой */
/* w436: обёртка поля даты больше не кнопка — внутри текстовый ввод (ручной набор дд.мм.гггг)
   и кнопка-иконка календаря. Рамка/высота/фокус — прежние; фокус теперь через :focus-within
   (подсвечивается и при наборе, и при работе с календарём). */
.ps-dp__btn {
    display: flex; align-items: center; gap: 10px; width: 100%; height: 50px; box-sizing: border-box;
    padding: 0 12px 0 14px; border: 1.6px solid var(--rp-line); border-radius: var(--rp-radius);
    background: var(--rp-card); font-family: var(--rp-font); text-align: left;
    transition: border-color .15s, box-shadow .15s;
}
.ps-dp__btn:hover { border-color: var(--rp-faint); }
.ps-dp__btn:focus-within { outline: none; border-color: var(--rp-accent); box-shadow: 0 0 0 3px rgba(245,179,1,.2); }
.ps-dp.is-open .ps-dp__btn { border-color: var(--rp-accent); box-shadow: 0 0 0 3px rgba(245,179,1,.2); }
.ps-dp.is-error .ps-dp__btn { border-color: var(--rp-red); box-shadow: 0 0 0 3px rgba(226,72,61,.13); }
.ps-dp.is-disabled .ps-dp__btn { background: var(--rp-line-2); cursor: not-allowed; opacity: .75; }
.ps-dp__text { flex: 1; font-size: 15px; font-weight: 600; color: var(--rp-ink); font-variant-numeric: tabular-nums; }
.ps-dp__text.is-placeholder { color: var(--rp-faint); font-weight: 400; }
input.ps-dp__text {
    border: 0; background: transparent; padding: 0; margin: 0; min-width: 0; width: 100%;
    height: 100%; outline: none; font-family: var(--rp-font);
}
input.ps-dp__text::placeholder { color: var(--rp-faint); font-weight: 400; }
.ps-dp.is-disabled input.ps-dp__text { cursor: not-allowed; }
.ps-dp__open { display: flex; align-items: center; border: 0; background: none; padding: 0; margin: 0; cursor: pointer; }
.ps-dp__open:disabled { cursor: not-allowed; }
.ps-dp__ico { color: var(--rp-accent-deep); flex-shrink: 0; }
.ps-dp__pop { position: absolute; top: calc(100% + 6px); left: 0; z-index: 45; box-sizing: border-box; width: 268px; max-width: calc(100vw - 32px); padding: 12px; background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: 14px; box-shadow: 0 16px 44px rgba(35,38,43,.16); }
.ps-dp__pop[hidden] { display: none; }
.ps-dp__head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
/* w71: заголовок стал кнопкой — открывает выбор года (раньше были только ‹/› по месяцам) */
.ps-dp__title { flex: 1; text-align: center; font-size: 14px; font-weight: 800; color: var(--rp-ink); border: none; background: transparent; cursor: pointer; font-family: var(--rp-font); padding: 4px 6px; border-radius: 8px; }
.ps-dp__title:hover { background: var(--rp-line-2); }
.ps-dp__years { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
.ps-dp__year { height: 36px; border: none; border-radius: 8px; background: transparent; color: var(--rp-ink); font-family: var(--rp-font); font-size: 13px; font-weight: 700; cursor: pointer; font-variant-numeric: tabular-nums; }
.ps-dp__year:hover:not(:disabled) { background: var(--rp-line-2); }
.ps-dp__year.is-selected { background: var(--rp-accent); color: var(--rp-primary-deep); }
.ps-dp__year.is-off, .ps-dp__year:disabled { color: var(--rp-faint); opacity: .45; cursor: default; }
.ps-dp__years[hidden], .ps-dp__grid[hidden], .ps-dp__dows[hidden] { display: none !important; }
.ps-dp__nav { width: 30px; height: 30px; border-radius: 8px; border: 1px solid var(--rp-line); background: var(--rp-card); color: var(--rp-sub); cursor: pointer; display: flex; align-items: center; justify-content: center; }
.ps-dp__nav:hover:not(:disabled) { border-color: var(--rp-accent-deep); color: var(--rp-accent-deep); }
.ps-dp__nav:disabled { opacity: .4; cursor: not-allowed; }
.ps-dp__dows { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; margin-bottom: 4px; }
.ps-dp__dows span { text-align: center; font-size: 11px; font-weight: 700; color: var(--rp-faint); text-transform: uppercase; }
.ps-dp__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.ps-dp__day { height: 32px; border: none; border-radius: 8px; background: transparent; color: var(--rp-ink); font-family: var(--rp-font); font-size: 13px; font-weight: 600; cursor: pointer; font-variant-numeric: tabular-nums; }
.ps-dp__day:hover:not(:disabled) { background: var(--rp-line-2); }
.ps-dp__day:focus-visible { outline: 2px solid var(--rp-accent); outline-offset: -2px; }
.ps-dp__day.is-pad { pointer-events: none; }
.ps-dp__day.is-today { box-shadow: inset 0 0 0 1.5px var(--rp-line); }
.ps-dp__day.is-selected { background: var(--rp-accent); color: var(--rp-primary-deep); font-weight: 800; }
.ps-dp__day.is-off, .ps-dp__day:disabled { color: var(--rp-faint); opacity: .45; cursor: not-allowed; }
.ps-dp__foot { display: flex; gap: 10px; justify-content: flex-end; margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--rp-line-2); }
.ps-dp__link { border: none; background: none; padding: 0; cursor: pointer; font-family: var(--rp-font); font-size: 12.5px; font-weight: 700; color: var(--rp-accent-deep); }
.ps-dp__link:hover { text-decoration: underline; }
@media (max-width: 620px) { .ps-dp__pop { left: 0; right: auto; width: min(268px, calc(100vw - 32px)); } }

/* — раскладка Ш1 мастера (w61): слева широкая колонка с сортами топлива, справа — управляющие
     параметры (вид оплаты + дата). На мобильном — вертикально: сначала параметры, потом каталог. — */
.wiz-step1 { display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(320px, 1fr); align-items: start; }
.wiz-step1__side { border-left: 1px solid var(--rp-line); }
.wiz-step1__radios { display: flex; flex-direction: column; gap: 10px; }
@media (max-width: 1080px) {
    .wiz-step1 { grid-template-columns: 1fr; }
    .wiz-step1__side { border-left: none; border-bottom: 1px solid var(--rp-line); order: -1; }   /* параметры — первыми */
    .wiz-step1__radios { flex-direction: row; gap: 22px; flex-wrap: wrap; }
}

/* — Ш2 (w236 #9): две колонки одной ширины — слева поля (в столбик, сужены), справа «Обеспечение» — */
.wiz-step2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 4px 28px; align-items: start; }
.wiz-step2__fields { display: flex; flex-direction: column; gap: 16px; }
@media (max-width: 900px) { .wiz-step2 { grid-template-columns: 1fr; } }

/* — live-пересчёт (w61 → w62): индикатор загрузки убран (мелькал и дёргал высоту), остаётся
     ТОЛЬКО сообщение об ошибке сети — молчать при обрыве нельзя — */
.wiz-live { display: flex; align-items: center; gap: 8px; margin: 0 20px 8px; padding: 9px 12px; border-radius: 10px; background: var(--rp-red-soft); font-size: 12.5px; font-weight: 600; color: var(--rp-red); }
.wiz-live[hidden] { display: none; }

/* — блок «Договор и средства» на Ш1 мастера (w58, З-2): показывается ВСЕГДА, в т.ч. без договора — */
.wiz-gate { display: flex; flex-direction: column; gap: 10px; padding: 14px 16px; border: 1px solid var(--rp-line); border-radius: var(--rp-radius); background: var(--rp-line-2); }
.wiz-gate__item { display: flex; align-items: center; gap: 12px; min-height: 36px; }
/* w236 (#24): при 1280×1024 подписи обрезались «…»; переносим целыми словами, а не режем. */
.wiz-gate__k { display: inline-flex; align-items: flex-start; gap: 7px; font-size: 12.5px; font-weight: 600; color: var(--rp-sub); flex: 1 1 auto; min-width: 0; line-height: 1.3; }
.wiz-gate__k > span { min-width: 0; overflow-wrap: normal; word-break: normal; }
.wiz-gate__k svg { margin-top: 1px; }
.wiz-gate__k svg { flex-shrink: 0; }
.wiz-gate__v { flex-shrink: 0; }
.wiz-gate__v { display: inline-flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.wiz-gate__sum { font-size: 16px; font-weight: 800; color: var(--rp-ink); font-variant-numeric: tabular-nums; }
.wiz-gate__none { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; color: var(--rp-faint); }
.wiz-gate__note { margin: 2px 0 0; font-size: 12.5px; color: var(--rp-faint); line-height: 1.5; }

/* — карточки выбора типа сцепки (мастер заявки, шаг «Транспорт», w11) — радио-карточки, без дропдауна — */
.ps-couplings { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 10px; max-width: 780px; }
.ps-coupling-card { position: relative; display: block; cursor: pointer; }
.ps-coupling-card input { position: absolute; opacity: 0; width: 0; height: 0; }
/* box-sizing ОБЯЗАТЕЛЕН: без него height:100% + паддинги + рамка дают карточку ВЫШЕ своей ячейки —
   она вылезала за контейнер на 20px и накрывала поле поиска бензовоза (правка автора, w80).
   Глобального ресета box-sizing в файле нет — та же мина уже кусала <textarea> (w71). */
.ps-coupling-card__body { box-sizing: border-box; display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 4px 11px; height: 100%; padding: 12px 13px; border: 1.6px solid var(--rp-line); border-radius: 12px; background: var(--rp-card); transition: border-color .15s, box-shadow .15s; }
.ps-coupling-card:hover .ps-coupling-card__body { border-color: var(--rp-line-strong, var(--rp-sub)); }
.ps-coupling-card input:focus-visible + .ps-coupling-card__body { outline: 2px solid var(--rp-accent); outline-offset: 2px; }
.ps-coupling-card:has(input:checked) .ps-coupling-card__body { border-color: var(--rp-accent-deep); box-shadow: 0 0 0 3px var(--rp-accent-soft); }
.ps-coupling-card__ico { grid-row: span 2; width: 34px; height: 34px; border-radius: 9px; background: var(--rp-line-2); color: var(--rp-sub); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.ps-coupling-card:has(input:checked) .ps-coupling-card__ico { background: var(--rp-accent-soft); color: var(--rp-accent-deep); }
.ps-coupling-card__title { font-size: 13.5px; font-weight: 700; color: var(--rp-ink); min-width: 0; overflow-wrap: anywhere; }
.ps-coupling-card__hint { font-size: 11.5px; color: var(--rp-faint); line-height: 1.3; min-width: 0; overflow-wrap: anywhere; }
@media (max-width: 720px) { .ps-couplings { grid-template-columns: 1fr; } }

/* — экраны ELMA-стадий мастера (w58, шаги 6–7): ожидание встречной подписи / документ подписан — */
.wiz-elma { display: flex; flex-direction: column; gap: 14px; }
.wiz-wait { display: flex; align-items: center; gap: 16px; padding: 22px 24px; border: 1px solid var(--rp-line); border-radius: var(--rp-radius-lg); background: var(--rp-card); }
.wiz-wait__ico { width: 52px; height: 52px; border-radius: 14px; background: var(--rp-accent-soft); color: var(--rp-accent-deep); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.wiz-wait__t { font-size: 16px; font-weight: 800; color: var(--rp-ink); }
.wiz-wait__s { font-size: 13.5px; color: var(--rp-sub); margin-top: 4px; line-height: 1.5; }
.wiz-wait__bar { position: relative; height: 4px; border-radius: 2px; background: var(--rp-line-2); overflow: hidden; margin-top: 12px; }
.wiz-wait__bar::after { content: ""; position: absolute; inset: 0 auto 0 0; width: 34%; border-radius: 2px; background: var(--rp-accent); animation: wiz-wait 1.6s ease-in-out infinite; }
@keyframes wiz-wait { 0% { transform: translateX(-100%); } 100% { transform: translateX(320%); } }
@media (prefers-reduced-motion: reduce) { .wiz-wait__bar::after { animation: none; } }
.wiz-demo { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 12px 14px; border: 1px dashed var(--rp-line); border-radius: 12px; background: var(--rp-line-2); font-size: 12.5px; color: var(--rp-faint); }
/* w71 🔴: класса .ps-link НЕ СУЩЕСТВОВАЛО — все `<a class="ps-link">` (таблицы: «Подробно»,
   «Скачать», номер договора) рендерились дефолтной браузерной ссылкой: синей и подчёркнутой,
   мимо дизайн-системы. Заводим в наборе: инлайновая ссылка внутри контента и ячеек таблиц.
   Отличие от .ps-linkbtn — та стоит ПОД полем/блоком (свой margin-top), эта живёт в строке. */
.ps-link { display: inline-flex; align-items: center; gap: 5px; color: var(--rp-accent-deep); font-family: var(--rp-font); font-size: 13px; font-weight: 700; text-decoration: none; white-space: nowrap; }
.ps-link:hover { color: var(--rp-accent-deep); text-decoration: underline; }
.ps-link:focus-visible { outline: 2px solid var(--rp-accent); outline-offset: 2px; border-radius: 4px; }
.ps-link svg { flex-shrink: 0; }

.ps-linkbtn { display: inline-flex; align-items: center; gap: 5px; margin-top: 7px; border: none; background: none; padding: 2px 0; cursor: pointer; font-family: var(--rp-font); font-size: 12.5px; font-weight: 700; color: var(--rp-accent-deep); }
.ps-linkbtn:hover { text-decoration: underline; }

/* — чекбокс / радио / switch — */
.ps-check { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; font-size: 14px; color: var(--rp-ink); user-select: none; }
.ps-check input { position: absolute; opacity: 0; width: 0; height: 0; }
.ps-check__box { width: 20px; height: 20px; border-radius: 6px; border: 1.8px solid var(--rp-line); background: var(--rp-card); display: flex; align-items: center; justify-content: center; flex-shrink: 0; transition: background .15s, border-color .15s; color: #fff; }
.ps-check__box svg { opacity: 0; transition: opacity .12s; }
/* 🔴 w398: «отмечаешь пункты, а галочки не появляются». Отметка в пункте множественного выбора
   (`<x-ps.multicombo>`) рисуется ТОЙ ЖЕ разметкой `.ps-check__box`, но правила состояния были
   привязаны к предку `.ps-check`, которого у пункта списка нет: рамка отображалась, а заливка и
   сама галочка — никогда. Замер до правки: клик по пункту → `checked=true`, значение в форме и чип
   есть, а у отметки `background: rgb(255,255,255)`, `svg opacity: 0` — то есть человек не видел
   своего выбора В САМОМ СПИСКЕ. Дефект родом из w388 (когда компонент заводился), а не из w396.
   Лечим РАСШИРЕНИЕМ существующих правил, а не копией: вид отметки в портале остаётся один. */
.ps-check input:checked + .ps-check__box,
.ps-multi__opt input:checked + .ps-check__box { background: var(--rp-primary); border-color: var(--rp-primary); }
.ps-check input:checked + .ps-check__box svg,
.ps-multi__opt input:checked + .ps-check__box svg { opacity: 1; }
.ps-check input:focus-visible + .ps-check__box,
.ps-multi__opt input:focus-visible + .ps-check__box { box-shadow: 0 0 0 3px rgba(245,179,1,0.25); }
.ps-check--radio .ps-check__box { border-radius: 50%; }
.ps-check--radio input:checked + .ps-check__box { background: var(--rp-card); border-color: var(--rp-primary); }
.ps-check--radio .ps-check__box::after { content: ""; width: 10px; height: 10px; border-radius: 50%; background: var(--rp-primary); opacity: 0; transition: opacity .12s; }
.ps-check--radio input:checked + .ps-check__box::after { opacity: 1; }
.ps-check input:disabled + .ps-check__box { background: var(--rp-line-2); border-color: var(--rp-line); }
.ps-check.is-disabled { color: var(--rp-faint); cursor: not-allowed; }

.ps-switch { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; font-size: 14px; color: var(--rp-ink); user-select: none; }
.ps-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.ps-switch__track { width: 42px; height: 24px; border-radius: 999px; background: var(--rp-line); position: relative; transition: background .18s; flex-shrink: 0; }
.ps-switch__track::after { content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.25); transition: transform .18s; }
.ps-switch input:checked + .ps-switch__track { background: var(--rp-green); }
.ps-switch input:checked + .ps-switch__track::after { transform: translateX(18px); }
.ps-switch input:focus-visible + .ps-switch__track { box-shadow: 0 0 0 3px rgba(245,179,1,0.25); }
.ps-switch input:disabled + .ps-switch__track { opacity: .5; }

/* — бейджи статусов — */
.ps-badge { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; padding: 4px 11px 4px 9px; border-radius: 999px; line-height: 1.1; white-space: nowrap; }
.ps-badge .dot { width: 7px; height: 7px; border-radius: 4px; flex-shrink: 0; }
.ps-badge--neutral { background: var(--rp-primary-soft); color: var(--rp-sub); } .ps-badge--neutral .dot { background: var(--rp-faint); }
.ps-badge--info    { background: rgba(44,123,229,0.12); color: var(--rp-blue); } .ps-badge--info .dot { background: var(--rp-blue); }
.ps-badge--warning { background: var(--rp-accent-soft); color: var(--rp-accent-deep); } .ps-badge--warning .dot { background: var(--rp-accent); }
.ps-badge--success { background: rgba(31,157,85,0.12); color: var(--rp-green); } .ps-badge--success .dot { background: var(--rp-green); }
.ps-badge--danger  { background: rgba(226,72,61,0.12); color: var(--rp-red); } .ps-badge--danger .dot { background: var(--rp-red); }

/* — табы — */
.ps-tabs__nav { display: flex; gap: 4px; border-bottom: 1px solid var(--rp-line); margin-bottom: 16px; overflow-x: auto; scrollbar-width: none; }
.ps-tabs__nav::-webkit-scrollbar { display: none; }
/* вкладка — <button> (панели на месте) ЛИБО <a> (GET-навигация по разделу: автопарк, w55) */
/* w368 (отчёт 02.08 ч.2, пп. 16–17):
   п.16 — неактивные вкладки были `--rp-sub` (#5E646C) и читались как отключённые: на белом это
          6.2:1, тогда как у активной 12.6:1 — разница вдвое, глаз принимал её за «недоступно».
          Берём основной цвет текста интерфейса (`--rp-ink`), как и просил ориентир отчёта.
          Активную по-прежнему отличают вес шрифта и жёлтая полоска — цветом её больше не выделяем,
          и это не потеря: «где я» показывает полоска, а не оттенок серого.
   п.17 — полоска-индикатор 2px → 4px. Цвет и ширина прежние; растёт она вверх, нижний край вкладки
          остаётся на линии панели (за это отвечает `margin-bottom: -1px`, его не трогаем). */
.ps-tabs__tab { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; background: none; border: none; padding: 10px 14px; font-family: var(--rp-font); font-size: 14px; font-weight: 600; color: var(--rp-ink); cursor: pointer; position: relative; border-bottom: 4px solid transparent; margin-bottom: -1px; text-decoration: none; }
.ps-tabs__tab:hover { color: var(--rp-ink); }
.ps-tabs__tab.is-active { color: var(--rp-ink); font-weight: 700; border-bottom-color: var(--rp-accent); }
/* счётчик записей во вкладке (сколько водителей/ТС — видно без перехода) */
.ps-tabs__count { min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px; background: var(--rp-line-2); color: var(--rp-sub); font-size: 11.5px; font-weight: 800; display: inline-flex; align-items: center; justify-content: center; }
.ps-tabs__tab.is-active .ps-tabs__count { background: var(--rp-accent-soft); color: var(--rp-accent-deep); }
@media (max-width: 620px) { .ps-tabs__tab { padding: 10px 10px; font-size: 13.5px; } }
.ps-tabs__panel { display: none; font-size: 14px; color: var(--rp-sub); line-height: 1.5; }
.ps-tabs__panel.is-active { display: block; }

/* — загрузка файла (ps.upload, w54): drag-and-drop + клик; без browser-плейсхолдеров — */
.ps-upload { display: flex; flex-direction: column; gap: 10px; }
.ps-upload__zone {
    position: relative; display: flex; flex-direction: column; align-items: center; text-align: center;
    gap: 6px; padding: 22px 18px; border: 1.5px dashed var(--rp-line); border-radius: var(--rp-radius);
    background: var(--rp-card); cursor: pointer; transition: border-color .15s, background .15s;
}
.ps-upload__zone:hover { border-color: var(--rp-accent); background: var(--rp-accent-soft); }
.ps-upload.is-drag .ps-upload__zone { border-color: var(--rp-accent); background: var(--rp-accent-soft); border-style: solid; }
.ps-upload.is-error .ps-upload__zone { border-color: var(--rp-red); }
.ps-upload.is-disabled .ps-upload__zone { opacity: .55; cursor: not-allowed; background: var(--rp-line-2); }
.ps-upload__ico { width: 40px; height: 40px; border-radius: 12px; background: var(--rp-line-2); color: var(--rp-sub); display: flex; align-items: center; justify-content: center; }
.ps-upload.is-drag .ps-upload__ico, .ps-upload__zone:hover .ps-upload__ico { background: var(--rp-card); color: var(--rp-accent-deep); }
.ps-upload__t { font-size: 13.5px; font-weight: 700; color: var(--rp-ink); }
.ps-upload__s { font-size: 12px; color: var(--rp-faint); }
/* нативный input скрыт (кнопки «Выбрать файл» и надписи «Файл не выбран» на экране нет), но
   остаётся в форме и доступен с клавиатуры: фокус подсвечивает область */
.ps-upload__input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.ps-upload__input:focus-visible + .ps-upload__t, .ps-upload__input:focus-visible ~ .ps-upload__t { outline: none; }
.ps-upload__zone:focus-within { border-color: var(--rp-accent); box-shadow: 0 0 0 3px rgba(245,179,1,.22); }
.ps-upload__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.ps-upload__file { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-radius: 10px; background: var(--rp-line-2); font-size: 13.5px; }
.ps-upload__file .n { flex: 1; min-width: 0; font-weight: 600; color: var(--rp-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-upload__file .s { font-size: 12px; color: var(--rp-faint); flex-shrink: 0; }
.ps-upload__file .x { border: none; background: none; color: var(--rp-faint); font-size: 19px; line-height: 1; cursor: pointer; padding: 0 2px; flex-shrink: 0; }
.ps-upload__file .x:hover { color: var(--rp-red); }
.ps-upload__err { display: flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--rp-red); }
.ps-upload__err[hidden], .ps-upload__list[hidden] { display: none; }

/* — сегмент-контрол (взаимоисключающий выбор значения: ссылки ИЛИ radio-группа формы, w51) — */
.ps-segment { display: inline-flex; align-self: flex-start; gap: 4px; padding: 4px; box-sizing: border-box; background: var(--rp-line-2); border: 1px solid var(--rp-line); border-radius: var(--rp-radius); }
.ps-segment--fluid { display: flex; width: 100%; align-self: stretch; }
.ps-segment__opt { position: relative; display: inline-flex; flex: 0 1 auto; min-width: 0; }
.ps-segment--fluid .ps-segment__opt { flex: 1 1 0; }
/* в форм-режиме элемент-обёртка — <label>, кнопка-пилюля внутри тянется на неё целиком
   (в режиме ссылок сам <a> несёт оба класса и ширину не задаёт — иначе сегменты вылезают из пилюли) */
.ps-segment__opt > .ps-segment__btn { width: 100%; }
/* 🔴 w369 (отчёт 02.08 ч.2, п.6): высота 38 → 40, то есть сегмент целиком 48 → 50px
   (4+4 padding + 40 + 2 рамки). Отчёт просил свести оба контрола панели прайса к 48px — делаю
   НАОБОРОТ, и вот почему. 50px — не случайная величина датапикера, а инвариант набора w81: «все
   поля ровно 50px» (.ps-input-shell, .ps-select__btn, .ps-dp__btn). Опусти я датапикер до 48 —
   панель прайса сошлась бы, но поле даты стало бы на 2px ниже соседних текстовых полей и селектов
   на КАЖДОЙ форме портала (автопарк, залоги, договоры). Поднимаю сегмент: панель ровная,
   инвариант цел. Сегмент живёт в двух местах — прайс и фильтр договоров. */
.ps-segment__btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 7px; box-sizing: border-box;
    height: 40px; padding: 0 16px; border: none; border-radius: 9px; background: transparent;
    color: var(--rp-sub); font-family: var(--rp-font); font-size: 14px; font-weight: 700;
    white-space: nowrap; text-decoration: none; cursor: pointer;
    transition: background .15s, color .15s, box-shadow .15s;
}
.ps-segment--sm .ps-segment__btn { height: 30px; padding: 0 12px; font-size: 13px; border-radius: 7px; }
.ps-segment__btn:hover { color: var(--rp-ink); background: rgba(255,255,255,.65); }
/* активный — «пилюля» на карточном фоне (и в режиме ссылок, и на нативном :checked) */
.ps-segment__opt.is-active, .ps-segment__input:checked + .ps-segment__btn { background: var(--rp-card); color: var(--rp-ink); box-shadow: 0 1px 3px rgba(35,38,43,.12); }
.ps-segment__input { position: absolute; opacity: 0; width: 0; height: 0; margin: 0; }
.ps-segment__btn:focus-visible, .ps-segment__input:focus-visible + .ps-segment__btn { outline: none; box-shadow: 0 0 0 3px rgba(245,179,1,.35); }
.ps-segment__opt.is-disabled, .ps-segment__input:disabled + .ps-segment__btn { opacity: .45; cursor: not-allowed; pointer-events: none; }
/* мобайл — сегменты на всю ширину равными долями (§5.3 адаптива) */
@media (max-width: 620px) {
    .ps-segment { display: flex; width: 100%; }
    .ps-segment__opt { flex: 1; }
}
/* узкие экраны (≤400px): длинное имя вида оплаты («Отсрочка платежа») должно влезать ЦЕЛИКОМ —
   сокращать нельзя (требование автора). Ужимаем шрифт/отступы и разрешаем перенос в 2 строки (w54). */
@media (max-width: 400px) {
    .ps-segment { gap: 3px; padding: 3px; }
    .ps-segment__btn { font-size: 12.5px; padding: 0 7px; gap: 5px; height: auto; min-height: 38px; white-space: normal; line-height: 1.2; text-align: center; }
}

/* — аккордеон — */
.ps-acc__item { border: 1px solid var(--rp-line); border-radius: var(--rp-radius); margin-bottom: 10px; overflow: hidden; }
.ps-acc__head { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; background: var(--rp-card); border: none; padding: 14px 16px; font-family: var(--rp-font); font-size: 14.5px; font-weight: 700; color: var(--rp-ink); cursor: pointer; }
.ps-acc__head .chev { margin-left: auto; transition: transform .2s; color: var(--rp-faint); }
.ps-acc__item.is-open .ps-acc__head .chev { transform: rotate(90deg); }
.ps-acc__body { display: none; padding: 0 16px 16px; font-size: 13.5px; color: var(--rp-sub); line-height: 1.55; }
.ps-acc__item.is-open .ps-acc__body { display: block; }
/* «богатая» шапка: иконка-плитка + заголовок с подписью + сводка справа (сканирование без раскрытия, w51) */
.ps-acc__head:hover { background: var(--rp-line-2); }
.ps-acc__ico { width: 38px; height: 38px; border-radius: 10px; background: var(--rp-accent-soft); color: var(--rp-accent-deep); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.ps-acc__main { flex: 1; min-width: 0; }
.ps-acc__main .t { display: block; font-size: 15px; font-weight: 800; color: var(--rp-ink); }
.ps-acc__main .s { display: block; font-size: 12.5px; font-weight: 600; color: var(--rp-sub); margin-top: 2px; }
.ps-acc__sum { text-align: right; flex-shrink: 0; margin-left: auto; }
.ps-acc__sum .v { display: block; font-size: 15px; font-weight: 800; color: var(--rp-ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ps-acc__sum .s { display: block; font-size: 11px; font-weight: 600; color: var(--rp-faint); margin-top: 2px; }
.ps-acc__head .ps-acc__sum + .chev { margin-left: 0; }
.ps-acc__body--flush { padding: 0; border-top: 1px solid var(--rp-line-2); }
/* ── Карточки в ДВЕ КОЛОНКИ (F·w303, отчёт 30.07 п.17) ────────────────────────────────────────
   Прайс-лист шёл одной колонкой: сортов топлива у контрагента 5–8, каждый — отдельная карточка на
   всю ширину рабочей зоны (1246px под таблицу из двух колонок), и список уезжал далеко вниз.
   Раскладка — грид, а не колонки CSS: `column-count` разрезал бы карточку между колонками, а нам
   нужна целая карточка в ячейке. `align-items:start` — чтобы раскрытие одной карточки не тянуло
   высоту соседней.
   🔴 Порог 1180px — тот же, на котором сворачиваются в одну колонку сетки главной (.cab-split /
   .cab-tri): при более узкой рабочей зоне половина ширины уже не вмещает пару «склад — цена», и
   внутри карточки появился бы горизонтальный скролл — ровно то, что закрывали в п.16. */
@media (min-width: 1181px) {
    .ps-acc--2col { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 14px; align-items: start; }
    /* ── Нечётная последняя карточка (F·w350, отчёт 31.07 п.4) ────────────────────────────
       Сортов у контрагента бывает нечётное число, и последняя карточка стояла в левой колонке,
       оставляя справа от себя пустую ячейку в полэкрана — витрина выглядела недогруженной.
       `:last-child:nth-child(odd)` — это ровно «последняя И без пары»: при чётном числе карточек
       правило не срабатывает вовсе. Работает и на одной-единственной карточке. */
    .ps-acc--2col > .ps-acc__item:last-child:nth-child(odd) { grid-column: 1 / -1; }
}
/* ── Плоский вариант: карточки без сворачивания (F·w350, отчёт 31.07 п.1) ─────────────────────
   Прайс-лист был аккордеоном, хотя сворачивать в нём нечего: в карточке 1–3 строки, и цена, за
   которой человек и пришёл, пряталась за кликом. Вариант снимает механику целиком — шапка не
   кликабельна, тело открыто всегда, шеврона в разметке нет. Базовый `.ps-acc` не тронут: на нём
   живёт FAQ, где сворачивание — суть компонента. */
.ps-acc--flat .ps-acc__head { cursor: default; }
.ps-acc--flat .ps-acc__head:hover { background: var(--rp-card); }
.ps-acc--flat .ps-acc__body { display: block; }
@media (max-width: 620px) {
    .ps-acc__head { flex-wrap: wrap; gap: 8px 10px; }
    .ps-acc__sum { margin-left: 0; text-align: left; order: 3; flex-basis: 100%; }
    .ps-acc__sum .v { font-size: 17px; }
    .ps-acc__head .chev { margin-left: auto; }
}

/* — тултип — */
/* 🔴 w287 (п.16 отчёта 30.07): «внутри карточек появился горизонтальный скролл».
   Виновата была ЭТА подсказка, а не вёрстка прайса. Тултип — абсолютно позиционированный ::after
   ширины ~172px, отцентрованный по кнопке (`left:50%` + `translate(-50%)`). Кнопка ⓘ стоит в
   последней колонке, у правого края ячейки, поэтому половина подсказки выходила за карточку — и
   `overflow-x:auto` обёртки таблицы честно показывал полосу прокрутки, хотя видимого контента за
   краем нет. Замер до правки: ячейка 592px, её scrollWidth 654px — ровно на вылет подсказки.

   Лечим двумя правилами, оба класса, а не по месту:
   • `content: none` в покое — в состоянии покоя подсказки в раскладке НЕТ ВОВСЕ, значит ни один
     скролл-контейнер портала не получит от неё фантомную полосу. Плата — исчезла анимация
     появления: у пседоэлемента, который только что создан, transition не проигрывается. Честный
     обмен: полоса прокрутки на витрине заметнее, чем 140 мс проявления подсказки.
   • `.ps-tip--end` — вариант «подсказка прижата к правому краю кнопки»: для иконок в последней
     колонке, где даже на наведении центрирование выносило бы её за контейнер. */
.ps-tip { position: relative; display: inline-flex; }
.ps-tip::after { content: none; position: absolute; left: 50%; bottom: calc(100% + 8px); transform: translate(-50%, 0); background: var(--rp-primary-deep); color: #fff; font-size: 11.5px; font-weight: 600; line-height: 1.35; padding: 6px 10px; border-radius: 8px; white-space: nowrap; pointer-events: none; box-shadow: 0 8px 24px rgba(0,0,0,.3); z-index: 60; }
.ps-tip:hover::after, .ps-tip:focus-visible::after { content: attr(data-tip); }
/* 🔴 w401 (отчёт 04.08, пп. 5/7/11): подсказку-псевдоэлемент режет любой предок с `overflow: hidden`
   (портлеты главной, список прайса). Когда скрипт набора жив, подсказку рисует общий узел в <body>
   с `position: fixed` (см. W0b) — здесь гасим псевдоэлемент, чтобы не было двух подсказок разом.
   Класс ставит сам скрипт: без него всё остаётся как было, и подсказка не пропадает совсем. */
.ps-tips-js .ps-tip:hover::after, .ps-tips-js .ps-tip:focus-visible::after { content: none; }
.ps-tip__pop {
    position: fixed; z-index: 80; pointer-events: none;
    background: var(--rp-primary-deep); color: #fff;
    font-family: var(--rp-font); font-size: 11.5px; font-weight: 600; line-height: 1.35;
    padding: 6px 10px; border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0,0,0,.3);
    /* Текст переносится, а не режется многоточием: на 360px «Печатная форма ещё не сформирована»
       в одну строку не помещается, а прочитать её надо целиком — ради неё подсказка и нужна. */
    max-width: min(320px, calc(100vw - 24px));
    white-space: normal; overflow-wrap: anywhere;
}
.ps-tip__pop[hidden] { display: none; }
.ps-tip--end::after { left: auto; right: 0; transform: none; }

/* — тосты — */
.ps-toast-host { position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%); z-index: 2000; display: flex; flex-direction: column; gap: 10px; align-items: center; }
.ps-toast { display: flex; align-items: center; gap: 10px; background: var(--rp-primary-deep); color: #fff; padding: 13px 18px; border-radius: 12px; box-shadow: 0 12px 40px rgba(0,0,0,.3); font-size: 14px; font-weight: 600; animation: ps-toast-in .25s ease; }
.ps-toast .dot { width: 8px; height: 8px; border-radius: 4px; flex-shrink: 0; }
.ps-toast--success .dot { background: var(--rp-green); } .ps-toast--error .dot { background: var(--rp-red); } .ps-toast--info .dot { background: var(--rp-accent); }
@keyframes ps-toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* — алерт-баннеры (инлайн уведомления с семантикой) — */
.ps-alert { display: flex; gap: 11px; align-items: flex-start; border-radius: 12px; padding: 12px 14px; }
.ps-alert .ttl { font-size: 13.5px; font-weight: 700; color: var(--rp-ink); }
/* w71: текст в блоке-подсказке был слишком тонким/бледным — читался хуже, чем должен */
.ps-alert .txt { font-size: 13px; color: var(--rp-ink); font-weight: 500; line-height: 1.45; }
.ps-alert--success { background: rgba(31,157,85,0.08); border: 1px solid rgba(31,157,85,0.28); } .ps-alert--success .i { color: var(--rp-green); }
.ps-alert--error   { background: rgba(226,72,61,0.08); border: 1px solid rgba(226,72,61,0.28); } .ps-alert--error .i { color: var(--rp-red); }
/* w246: вернули янтарный `warning` (предупреждение ≠ ошибка). Цвет — портальный --rp-amber (#E5A400),
   тот же, что у is-warn/is-waiting/tile--warn; плотнее очень светлого accent-инфо → визуально отличим. */
.ps-alert--warning { background: var(--rp-amber-soft); border: 1px solid rgba(229,164,0,0.45); } .ps-alert--warning .i { color: var(--rp-amber); }
.ps-alert--info    { background: rgba(245,179,1,0.09); border: 1px solid rgba(245,179,1,0.3); } .ps-alert--info .i { color: var(--rp-accent-deep); }
.ps-alert .i { flex-shrink: 0; }

/* — прогресс-бар оформления (шаги заявки, BR-3.1) — */
/* w71: единый степпер портала. Состояния и палитра — как у мастера (.ps-prog): выполнено —
   зелёный, текущий — янтарный, ожидает — серый, отклонено — красный. Отступы свои: раньше
   степпер стоял голым flex и прилипал к краям .ps-card (у неё padding нет). */
.ps-steps { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 0; padding: 20px 22px; }
.ps-steps__item { display: flex; align-items: center; gap: 9px; }
.ps-steps__dot { width: 32px; height: 32px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 800; flex-shrink: 0; border: 2px solid var(--rp-line); color: var(--rp-faint); background: var(--rp-line-2); }
.ps-steps__item.is-done     .ps-steps__dot { background: var(--rp-green); border-color: var(--rp-green); color: #fff; }
.ps-steps__item.is-active   .ps-steps__dot { background: var(--rp-accent); border-color: var(--rp-accent); color: var(--rp-primary-deep); }
.ps-steps__item.is-rejected .ps-steps__dot { background: var(--rp-red); border-color: var(--rp-red); color: #fff; }
.ps-steps__label { font-size: 13px; font-weight: 600; color: var(--rp-sub); white-space: nowrap; }
.ps-steps__item.is-active .ps-steps__label { color: var(--rp-ink); font-weight: 700; }
.ps-steps__item.is-rejected .ps-steps__label { color: var(--rp-red); font-weight: 700; }
.ps-steps__bar { flex: 1; height: 2px; background: var(--rp-line); margin: 0 12px; min-width: 24px; }
.ps-steps__item.is-done + .ps-steps__bar, .ps-steps__bar.is-filled { background: var(--rp-green); }   /* w71: заливка линии — цветом «выполнено» */
.ps-progress { height: 8px; background: var(--rp-line); border-radius: 4px; overflow: hidden; }
.ps-progress__fill { height: 100%; background: var(--rp-accent); border-radius: 4px; }

/* — кастомный скроллбар (демо-бокс) — */
.ps-scrollbox { max-height: 150px; overflow-y: auto; border: 1px solid var(--rp-line); border-radius: var(--rp-radius); padding: 14px; font-size: 13.5px; color: var(--rp-sub); line-height: 1.6; }

/* — модалка / диалог — */
.ps-modal-backdrop { position: fixed; inset: 0; z-index: 1500; background: rgba(20,22,26,0.5); backdrop-filter: blur(2px); display: none; align-items: center; justify-content: center; padding: 24px; }
.ps-modal-backdrop.is-open { display: flex; }
/* ширина — размерами набора (w54): sm 380 · md 460 (дефолт, как было) · lg 720 · xl 980.
   Высокая модалка (формы ТС) скроллится телом, шапка/подвал остаются на месте. */
.ps-modal { width: 460px; max-width: 100%; max-height: calc(100vh - 48px); display: flex; flex-direction: column; background: var(--rp-card); border-radius: 18px; box-shadow: 0 24px 70px rgba(0,0,0,.35); overflow: hidden; animation: ps-pop .2s cubic-bezier(.2,.8,.2,1); }
.ps-modal--sm { width: 380px; }
.ps-modal--lg { width: 720px; }
.ps-modal--xl { width: 980px; }
/* ── w368 (отчёт 02.08 ч.2, пп. 3 и 5): формы техники автопарка ──────────────────────────────
   Свой размер, а НЕ правка `--xl`: на 980px его держат другие окна (витрина, таблицы), и сузить
   класс глобально значило бы починить автопарк ценой всех остальных.
   Откуда 504px: эталон ширины — колонка блока «оси и массы» (218px). Две такие колонки плюс зазор
   20px = контент 456px, плюс поля тела модалки 24px с каждой стороны = 504px.
   Поля формы ТС раскладывались тремя разными сетками (3 / 4 / 2 колонки), и одно и то же поле
   меняло ширину от блока к блоку — 297px, 218px, 456px. Здесь все сетки формы приводятся к ДВУМ
   колонкам, то есть к одной ширине поля во всём окне. Разметку партиала не трогаем: он общий с
   мастером заявки, и правка классов там разъехалась бы по чужим экранам. */
.ps-modal--fleet { width: 504px; }
.ps-modal--fleet .ps-form__grid--3,
.ps-modal--fleet .ps-form__grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* Секции и трубопроводы — по 4 в ряд (7 полей ложатся 4+3). Зазор колонок здесь свой, 12px:
   при нём поле выходит ровно (456 − 3×12) / 4 = 105px. Уже — не делаем: объём в четыре знака
   («12500») в поле уже 105px начинает поджиматься. */
.ps-modal--fleet .fleet-cells { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px 12px; }
@media (max-width: 620px) {
    .ps-modal-backdrop { padding: 12px; align-items: flex-end; }
    .ps-modal, .ps-modal--sm, .ps-modal--lg, .ps-modal--xl, .ps-modal--fleet { width: 100%; max-height: calc(100vh - 24px); }
}
/* 🔴 Своё мобильное правило обязательно: медиазапрос НЕ добавляет специфичности, и общее
   «на узком — одна колонка» (ниже по файлу, 0-1-0) проиграло бы правилам выше (0-2-0). Без этого
   форма осталась бы двухколонной на телефоне. */
@media (max-width: 720px) {
    .ps-modal--fleet .ps-form__grid,
    .ps-modal--fleet .ps-form__grid--3,
    .ps-modal--fleet .ps-form__grid--4 { grid-template-columns: 1fr; }
    .ps-modal--fleet .fleet-cells { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@keyframes ps-pop { from { transform: scale(.97); opacity: .6; } to { transform: none; opacity: 1; } }
.ps-modal__head { display: flex; align-items: flex-start; gap: 12px; padding: 20px 24px 0; }
.ps-modal__head h3 { margin: 0; font-size: 19px; font-weight: 800; color: var(--rp-ink); }
.ps-modal__head p { margin: 5px 0 0; font-size: 13.5px; color: var(--rp-sub); }
.ps-modal__x { margin-left: auto; width: 32px; height: 32px; border-radius: 8px; border: none; background: var(--rp-line-2); color: var(--rp-sub); cursor: pointer; font-size: 18px; line-height: 1; flex-shrink: 0; }
.ps-modal__body { padding: 18px 24px; font-size: 14px; color: var(--rp-sub); line-height: 1.5; overflow-y: auto; flex: 1 1 auto; }
.ps-modal__foot { display: flex; gap: 10px; justify-content: flex-end; padding: 16px 24px; border-top: 1px solid var(--rp-line); background: #FAFAF8; flex-shrink: 0; }
.ps-modal__head { flex-shrink: 0; }

/* — меню / навигация (ховер-подсветка) — */
.ps-menu { background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: var(--rp-radius); padding: 8px; width: 240px; }
.ps-menu__item { display: flex; align-items: center; gap: 11px; padding: 10px 12px; border-radius: 9px; font-size: 14px; font-weight: 600; color: var(--rp-sub); cursor: pointer; transition: background .12s, color .12s; }
.ps-menu__item:hover { background: var(--rp-line-2); color: var(--rp-ink); }
.ps-menu__item.is-active { background: var(--rp-accent-soft); color: var(--rp-accent-deep); }
.ps-menu__item .ico { color: var(--rp-faint); } .ps-menu__item:hover .ico, .ps-menu__item.is-active .ico { color: inherit; }

/* — аватар / блок пользователя — */
.ps-avatar { width: 40px; height: 40px; border-radius: 50%; background: var(--rp-primary); color: #fff; display: inline-flex; align-items: center; justify-content: center; font-weight: 800; font-size: 14px; flex-shrink: 0; }
.ps-avatar--sm { width: 30px; height: 30px; font-size: 12px; }
.ps-avatar--accent { background: var(--rp-accent-soft); color: var(--rp-accent-deep); }
.ps-userblock { display: inline-flex; align-items: center; gap: 11px; padding: 8px 12px; border: 1px solid var(--rp-line); border-radius: var(--rp-radius); background: var(--rp-card); }
.ps-userblock .n { font-size: 14px; font-weight: 700; color: var(--rp-ink); line-height: 1.2; }
.ps-userblock .r { font-size: 12px; color: var(--rp-faint); }

/* — date-picker: нативный input[type=date], стилизованный как поле — */
.ps-input[type="date"] { cursor: pointer; }
.ps-input[type="date"]::-webkit-calendar-picker-indicator { cursor: pointer; opacity: .55; }

/* ============================================================================
   16. Админ-примитивы: списки / справочники / формы (раунд F · w1)
   Таблица данных, пагинация, тулбар списка + фильтры, раскладка форм, textarea.
   Всё на токенах --rp-*; ими «переодеваются» экраны разделов Orchid (поток 7).
   Спека пробелов и покрытия — docs/40-ui/ps-ui-orchid-gaps.md.
   ========================================================================= */

/* — карточка-чром (общая для таблиц, форм, панелей) — */
.ps-card, .ps-table-card { background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: var(--rp-radius-lg); overflow: hidden; }
/* w60: карточка с нашими оверлеями (выпадашка select / календарь) НЕ должна их обрезать —
   overflow:hidden нужен таблицам ради радиуса, но списку/календарю он рубил хвост. */
.ps-card:has([data-ps-select]), .ps-card:has([data-ps-datepicker]), .ps-card:has([data-ps-combo]) { overflow: visible; }
.ps-form__section:has([data-ps-select]), .ps-form__section:has([data-ps-datepicker]) { overflow: visible; }
/* таблица внутри чужого чрома (аккордеон, модалка) — без своей рамки/радиуса */
.ps-table-card--flush { border: none; border-radius: 0; }

/* — таблица данных — */
.ps-table-wrap { overflow-x: auto; }
.ps-table { width: 100%; border-collapse: collapse; font-size: 14px; color: var(--rp-ink); }
.ps-table thead th {
    text-align: left; padding: 12px 16px; background: var(--rp-line-2);
    color: var(--rp-faint); font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: 0.03em;
    border-bottom: 1px solid var(--rp-line); white-space: nowrap;
}
.ps-table tbody td { padding: 13px 16px; border-bottom: 1px solid var(--rp-line-2); vertical-align: middle; }
.ps-table tbody tr:last-child td { border-bottom: none; }
.ps-table tbody tr { transition: background .12s; }
.ps-table tbody tr:hover { background: var(--rp-line-2); }
.ps-table tbody tr.is-selected { background: var(--rp-accent-soft); }
.ps-table--zebra tbody tr:nth-child(even) { background: rgba(244,243,240,0.55); }
.ps-table--zebra tbody tr:nth-child(even):hover { background: var(--rp-line-2); }
.ps-table--compact thead th { padding: 8px 12px; }
.ps-table--compact tbody td { padding: 8px 12px; }
/* ── w287, прайс-лист (отчёт 30.07, пп. 18–19) ─────────────────────────────────────────────
   Пара «склад отгрузки — цена» в карточке сорта. Дефекты были такие:
   п.18 — между названием базы и ценой ~500px пустоты: две колонки растягивались на всю карточку
          (1246px), название прижато влево, цена — вправо. Теперь колонка склада фиксированной
          ширины, а цена идёт сразу за ней. Выравнивание цен между строками при этом сохраняется —
          все они начинаются от одной границы, сравнивать по-прежнему можно.
   п.19 — шапка «СКЛАД ОТГРУЗКИ / ЦЕНА, ₽/Т» была 43px высотой при 12px отступов; здесь она
          подпись к двум колонкам, а не отдельный блок, — отступы минимальные.
   🔴 Только на десктопе: на ≤620px работает `.ps-table--cards` (каждая ячейка — блок), и
   фиксированная ширина колонки там сломала бы карточную раскладку, сделанную сознательно. */
@media (min-width: 621px) {
    .ps-table-card--pricepair .ps-table thead th { padding: 5px 16px; }
    /* w303: было ровно `340px`. В две колонки (п.17) карточка стала вдвое уже, и жёсткие 340px
       распирали таблицу — внутри карточки возвращался горизонтальный скролл (п.16). Половина
       ширины — потолок, ниже которого колонка склада не растёт; на широкой одиночной карточке
       52% всё ещё больше 340px, поэтому там ширина прежняя и п.18 не отменяется.
       🔴 w350 (отчёт 31.07, пп. 2–3): `min(340px, 52%)` давал ДВА дефекта сразу.
       п.3 — «разрыв между названием склада и ценой слишком большой»: колонка выходила ~305px при
             имени базы в ~110px — остаток был пустым воздухом. Полка снижена до 200px: замер до/после
             на карточке 612px — разрыв 187px → 115px, а длинное имя («Нефтебаза «Тихорецкая-Южная»»)
             всё ещё влезает в строку.
       п.2 — «позиция цены скачет от карточки к карточке»: 52% считались от ШИРИНЫ КАРТОЧКИ, а карточки
             бывают разной ширины (нечётная последняя занимает обе колонки, п.4) — цена в ней начиналась
             с другого места. Пиксельная полка одинакова в любой карточке.
       `table-layout: fixed` — чтобы ширина колонки была обещанием, а не пожеланием: при авторазметке
       длинное имя базы раздвигало колонку, и цена снова уезжала (auto считает по содержимому).
       🔴 И ровно поэтому ширина здесь — ЧИСТЫЕ ПИКСЕЛИ, а не `min(200px, 46%)`: при фиксированной
       раскладке Chrome из `min()` пиксельную ветку не берёт (замер: карточка 612px → колонка 305px,
       ровно половина таблицы, то есть заданная ширина игнорировалась вовсе). Процентный потолок w303
       был нужен против горизонтального скролла в половинной карточке — `table-layout: fixed` закрывает
       это надёжнее: таблица не может стать шире контейнера в принципе, а лишнее имя базы переносится
       на вторую строку. */
    .ps-table-card--pricepair .ps-table { table-layout: fixed; }
    .ps-table-card--pricepair .ps-table th:first-child,
    .ps-table-card--pricepair .ps-table td:first-child { width: 200px; }
    .ps-table-card--pricepair .ps-table th.ps-table__num,
    .ps-table-card--pricepair .ps-table td.ps-table__num { text-align: left; }
    .ps-table-card--pricepair .ps-price-cell { justify-content: flex-start; }
    /* w350 (п.2): ⓘ «скакала» по горизонтали — она стоит сразу за числом, а числа разной длины
       («8 500 ₽» против «125 400 ₽»). Число получает полку ширины (цифры и так моноширинные —
       `tabular-nums`), поэтому иконка у всех строк и всех карточек стоит на одной вертикали.
       10ch — с запасом на семизначную цену; замер: даже «1 052 000 ₽» полку не переполняет. */
    .ps-table-card--pricepair .ps-price-cell > b { min-width: 10ch; }
}
/* w71: шапка числовой колонки съезжала влево во ВСЕХ таблицах портала. Причина — специфичность:
   `.ps-table thead th { text-align: left }` (0-1-2) перебивало `.ps-table__num` (0-1-0) для `th`,
   а у `td` левого правила нет — цифры уходили вправо, заголовок оставался слева.
   Лечим в наборе: выравнивание задаём с той же специфичностью, что и базовое правило шапки. */
/* w310 (отчёт тестировщика, пп. 6 и 10): «1 507 200,00 ₽» переносилось на две строки — «₽» уезжал
   вниз отдельной строкой. Причина не в шрифте и не в ширине: MoneyFormat печатает сумму ОБЫЧНЫМИ
   пробелами (и разряды, и отступ перед знаком валюты), а обычный пробел — законное место переноса.
   Лечим показом, а не строкой: неразрывные пробелы в самом значении разошлись бы с тестами, которые
   сверяют сумму текстом, и всё равно не спасли бы от переноса внутри длинных разрядов.
   Числовая колонка целиком не переносится — это одно число, а не фраза. */
.ps-table__num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ps-table thead th.ps-table__num { text-align: right; }
/* колонка ДЕЙСТВИЯ («Подробно», «Скачать», «Открыть») — это не числа: свой класс, свой смысл.
   Раньше на неё вешали `__num`, и правки выравнивания чисел тянули за собой ссылки. */
.ps-table__act { text-align: right; white-space: nowrap; }
.ps-table thead th.ps-table__act { text-align: right; }
.ps-table__actions { display: inline-flex; gap: 4px; white-space: nowrap; }
/* ── w353, список заявок ДТ (отчёт тестировщика 31.07, пп. 10–11) ───────────────────────────
   п.10 — номер вида «ДТ-ТК-22-2026» вставал на две строки: дефис для браузера — законное место
          переноса, и в первой колонке номер рвался. Держим ячейку номера в одну строку. Таблица
          от этого не разъезжается: на узком экране она и так прокручивается внутри своей обёртки
          `.ps-table-wrap` — сознательный приём набора, см. набор section-tables-w310.
   п.11 — колонки просили выровнять единообразно по ЛЕВОМУ краю. Правим только ЭТОТ экран, через
          модификатор карточки: общие `.ps-table__num` / `.ps-table__act` живут ещё в Платежах,
          Отгрузках и Счетах, которых требование не касается.
   🔴 Классы `ps-table__num` с ячеек НЕ снимаем — вместе с выравниванием ушли бы `tabular-nums` и
   `white-space: nowrap`, а последний держит сумму в одну строку (w310, пп. 6 и 10). Меняем ровно
   выравнивание — правилами с большей специфичностью, чем базовые правила набора. */
.ps-table-card--orders .ps-table thead th,
.ps-table-card--orders .ps-table tbody td { text-align: left; }
.ps-table-card--orders .ps-table thead th.ps-table__num,
.ps-table-card--orders .ps-table thead th.ps-table__act { text-align: left; }
.ps-table-card--orders .ps-orders-no { white-space: nowrap; }
/* 🔴 Найдено замером, а не глазами: с левым выравниванием подпись «Сумма, ₽» встала на 20px правее
   своих цифр. Причина — правило w310 выше: у сортируемой ЧИСЛОВОЙ шапки иконка сортировки уходит
   влево от подписи (`row-reverse`), и тогда левым краем блока становится иконка. Для правого
   выравнивания это было лекарством, для левого — та же болезнь наизнанку. На этом экране
   возвращаем прямой порядок: слева подпись, иконка за ней. Остальных таблиц правило не касается —
   там колонка по-прежнему правая, и `row-reverse` там по-прежнему нужен. */
.ps-table-card--orders .ps-table thead th.ps-table__num .ps-th-sort { flex-direction: row; }

/* ── w310, списки раздела «Документы» ──────────────────────────────────────────────────────
   .bill-no — номер счёта и бейдж «Новый» в ОДНОЙ ячейке: отдельной колонки «Статус» больше нет
   (п. 12), она стояла почти всегда пустой. Бейдж не выброшен, а переехал к номеру — отметка
   «этот счёт вы ещё не открывали» живая (см. комментарий в bills.blade.php).
   .doc-contract — подпись договора из учётной системы. Имена длинные (71…93 символа), в ячейку не
   помещаются: держим одну строку с многоточием, полный текст — в подсказке `title`. Потолок в `ch`,
   а не в пикселях: он привязан к ширине символа, поэтому переживает смену размера шрифта. */
.bill-no { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.doc-contract { display: inline-block; max-width: 22ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }

/* мобайл: строки таблицы → карточки (вместо горизонтального скролла; w51).
   Ячейки подписывают себя из data-label; на широких экранах модификатор ничего не меняет. */
@media (max-width: 620px) {
    .ps-table--cards { display: block; }
    .ps-table--cards thead { display: none; }
    .ps-table--cards tbody, .ps-table--cards tr, .ps-table--cards td { display: block; }
    .ps-table--cards tbody tr { background: var(--rp-line-2); border-radius: 12px; padding: 12px 14px; margin-bottom: 10px; }
    .ps-table--cards tbody tr:last-child { margin-bottom: 0; }
    .ps-table--cards tbody td { border: none; padding: 4px 0; display: flex; align-items: center; gap: 10px; text-align: left; }
    .ps-table--cards tbody td[data-label]::before { content: attr(data-label); flex: 1; font-size: 12.5px; font-weight: 600; color: var(--rp-sub); }
    .ps-table--cards tbody td.ps-table__num { justify-content: space-between; font-size: 16px; }
    .ps-table--cards tbody td.ps-w-actions { justify-content: flex-end; width: auto; }
}
.ps-table th.ps-w-check, .ps-table td.ps-w-check { width: 44px; text-align: center; }
.ps-table th.ps-w-actions, .ps-table td.ps-w-actions { width: 1%; white-space: nowrap; }

/* сортируемая шапка (button — витрина Песочницы, a — серверная сортировка списков, w145) */
.ps-th-sort { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; user-select: none; color: inherit; text-decoration: none; background: none; border: none; font: inherit; text-transform: inherit; letter-spacing: inherit; padding: 0; }
.ps-th-sort:hover, .ps-th-sort:focus-visible { color: var(--rp-sub); text-decoration: none; }
/* w310 (отчёт тестировщика, п. 1): в списке заявок ДТ «Объём, т» и «Сумма, ₽» стояли по-разному.
   Замер (headless, набор section-tables-w310): «Объём» — расхождение 0.00px, «Сумма» — РОВНО 20.00px.
   Двадцать — это ширина иконки сортировки (14px) плюс зазор (6px): шапка-ссылка `.ps-th-sort` —
   inline-flex «подпись + иконка», по правому краю выравнивается ВЕСЬ блок, поэтому у сортируемой
   колонки подпись отъезжает влево на иконку, а цифры в ячейках остаются у самого края. У
   несортируемой колонки иконки нет — она и совпадала. То есть дело не в конкретной таблице: так
   стояла КАЖДАЯ сортируемая числовая колонка портала.
   Лечим порядком, а не отступами: в числовой колонке иконка уходит ВЛЕВО от подписи, и правым краем
   блока становится сама подпись — ровно там же, где цифры. Разметка не меняется (иконка остаётся
   после текста, порядок чтения с экрана прежний), и на текстовых колонках правило не работает. */
.ps-table thead th.ps-table__num .ps-th-sort { flex-direction: row-reverse; }
.ps-th-sort .ps-sort-ico { opacity: .45; transition: opacity .12s, transform .12s, color .12s; }
.ps-th-sort:hover .ps-sort-ico { opacity: .8; }
.ps-th-sort.is-asc .ps-sort-ico { opacity: 1; color: var(--rp-accent-deep); }
.ps-th-sort.is-desc .ps-sort-ico { opacity: 1; color: var(--rp-accent-deep); transform: rotate(180deg); }

/* пустое состояние таблицы */
.ps-table__empty { padding: 48px 24px; text-align: center; color: var(--rp-faint); }
.ps-table__empty .ico { width: 52px; height: 52px; border-radius: 50%; background: var(--rp-line-2); color: var(--rp-faint); display: inline-flex; align-items: center; justify-content: center; margin-bottom: 14px; }
.ps-table__empty .t { font-size: 15px; font-weight: 700; color: var(--rp-sub); margin-bottom: 4px; }
.ps-table__empty .s { font-size: 13px; }

/* строка-загрузка (скелетон) */
.ps-skel { display: block; height: 12px; border-radius: 6px; background: linear-gradient(90deg, var(--rp-line-2) 0%, var(--rp-line) 50%, var(--rp-line-2) 100%); background-size: 200% 100%; animation: ps-skel 1.2s ease infinite; }
@keyframes ps-skel { to { background-position: -200% 0; } }

/* — пагинация — */
.ps-pagination { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ps-pagination__info { font-size: 13px; color: var(--rp-faint); margin-right: auto; }
.ps-page { min-width: 36px; height: 36px; padding: 0 10px; border-radius: 9px; border: 1px solid var(--rp-line); background: var(--rp-card); color: var(--rp-sub); font-family: var(--rp-font); font-size: 13.5px; font-weight: 700; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 6px; transition: border-color .12s, color .12s, background .12s; text-decoration: none; }
.ps-page:hover { border-color: var(--rp-accent-deep); color: var(--rp-accent-deep); }
.ps-page.is-active { background: var(--rp-primary); border-color: var(--rp-primary); color: #fff; cursor: default; }
.ps-page.is-disabled { opacity: .5; pointer-events: none; }
.ps-page--gap { border: none; background: none; cursor: default; color: var(--rp-faint); }

/* — тулбар списка + фильтры — */
.ps-listbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.ps-listbar__search { flex: 1 1 260px; min-width: 200px; max-width: 440px; }
.ps-listbar__spacer { flex: 1; }
.ps-filters { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* панель фильтров-полей (подпись над контролом): в строку на десктопе, колонкой на мобайле (w51) */
.ps-filters--fields { align-items: flex-start; gap: 22px; }   /* подписи полей — на одной линии */
.ps-filters--fields .ps-input-shell { width: 190px; }
@media (max-width: 620px) {
    .ps-filters--fields { align-items: stretch; flex-direction: column; gap: 14px; }
    .ps-filters--fields .ps-field, .ps-filters--fields .ps-input-shell { width: 100%; }
}
.ps-filter-chip { display: inline-flex; align-items: center; gap: 7px; height: 40px; padding: 0 13px; border-radius: 10px; border: 1px solid var(--rp-line); background: var(--rp-card); color: var(--rp-sub); font-family: var(--rp-font); font-size: 13.5px; font-weight: 600; cursor: pointer; white-space: nowrap; transition: border-color .12s, background .12s, color .12s; }
.ps-filter-chip:hover { border-color: var(--rp-faint); }
.ps-filter-chip.is-active { border-color: var(--rp-accent); background: var(--rp-accent-soft); color: var(--rp-accent-deep); }
.ps-filter-chip .x { display: inline-flex; opacity: .7; }
.ps-filter-chip .x:hover { opacity: 1; }
.ps-filter-count { min-width: 19px; height: 19px; padding: 0 5px; border-radius: 10px; background: var(--rp-primary); color: #fff; font-size: 11px; font-weight: 800; display: inline-flex; align-items: center; justify-content: center; }
.ps-filter-chip.is-active .ps-filter-count { background: var(--rp-accent-deep); }

/* — раскладка форм — */
.ps-form__section { padding: 22px 24px; border-bottom: 1px solid var(--rp-line); }
.ps-form__section:last-child { border-bottom: none; }
.ps-form__section-h { font-size: 15px; font-weight: 800; color: var(--rp-ink); margin: 0 0 3px; }
.ps-form__section-s { font-size: 13px; color: var(--rp-faint); margin: 0 0 18px; }
.ps-form__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px 20px; align-items: start; }
.ps-form__grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ps-form__grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }   /* короткие числовые поля (массы/оси), w55 */
@media (max-width: 980px) { .ps-form__grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.ps-form__full { grid-column: 1 / -1; }
.ps-form__actions { display: flex; align-items: center; gap: 10px; padding: 16px 24px; border-top: 1px solid var(--rp-line); background: #FAFAF8; border-radius: 0 0 var(--rp-radius-lg) var(--rp-radius-lg); }
.ps-form__actions .ps-spacer { flex: 1; }
@media (max-width: 720px) { .ps-form__grid, .ps-form__grid--3, .ps-form__grid--4 { grid-template-columns: 1fr; } }

/* — формы автопарка: поле с галочкой сбоку и вертикальные ряды (w456) — */
/* Галочка «Нет отчества» стоит СПРАВА от своего поля (образец действующего портала): под полем
   она читалась бы как отдельная настройка формы, а не как «у этого человека отчества нет».
   Отступ сверху = высота подписи (19) + её нижний зазор (7) + половина поля (25) − половина
   галочки (10): так она встаёт по центру поля и не съезжает от текста ошибки под ним. */
.fleet-form__pair { display: flex; align-items: flex-start; gap: 14px; }
.fleet-form__pair-field { flex: 1 1 auto; min-width: 0; }
.fleet-form__pair-check { flex: 0 0 auto; margin-top: 41px; white-space: nowrap; }
/* На узком экране поле и галочка в строку не помещаются — поле сжималось бы до нечитаемого. */
@media (max-width: 520px) {
    .fleet-form__pair { flex-direction: column; }
    .fleet-form__pair-check { margin-top: 8px; }
}
/* Ряды полей друг под другом: грузоподъёмность обязана стоять ПОД массами, из которых считается,
   а не сбоку от них — иначе связь «это разность соседей» на экране не читается. */
.fleet-form__rows { display: grid; gap: 16px; }

/* — стороны накладной и место разгрузки на шаге ЭТрН (w466) — */
.ps-etrn-party, .ps-etrn-unloading { display: flex; flex-direction: column; gap: 12px; padding: 18px 20px; border: 1px solid var(--rp-line); border-radius: var(--rp-radius-lg); background: var(--rp-card); }
.ps-etrn-party__title { font-size: 15px; font-weight: 800; color: var(--rp-ink); }
.ps-etrn-party__sub { font-size: 13px; color: var(--rp-faint); margin-top: 3px; }
/* Реквизиты стороны — только показ: две колонки на широком, одна на узком (правила .org-reqs). */
.ps-etrn-party__reqs { margin: 0; }
.ps-etrn-party__actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
/* Сторона без выбора — подпись, а не пустое место: человек должен понимать, чего от него ждут. */
.ps-etrn-party__empty { margin: 0; }
/* Сторона, которую выбирать нельзя (грузополучатель не-холдинга): значение видно, списка нет —
   отключённый список читается как поломка, а не как «здесь иначе не бывает». */
.ps-etrn-party__locked { display: flex; flex-direction: column; gap: 4px; padding: 12px 14px; border-radius: var(--rp-radius); background: var(--rp-line-2); }
.ps-etrn-party__locked-name { font-weight: 700; color: var(--rp-ink); }
.ps-etrn-unloading__address { font-size: 13.5px; color: var(--rp-sub); }

/* — блок адреса девятью полями (x-ps.address-block, w452) — */
/* Поле, погашенное флажком («офиса нет»): звёздочка обязательности уходит ВМЕСТЕ с полем —
   иначе на экране остаётся требование заполнить то, что человек только что объявил
   несуществующим, а само поле уже не принимает ввод. Гашение — хук G4 в behaviors. */
.ps-address__cell .ps-field.is-off .ps-field__label { color: var(--rp-faint); }
.ps-address__cell .ps-field.is-off .ps-field__label .req { display: none; }
.ps-address__no-office { margin-top: 9px; }

/* — textarea (в раскладке ps-field) — */
/* w71: «Комментарий» вылезал за контейнер на ~30px. Причина — `width:100%` + паддинги + рамки при
   content-box (глобального ресета в файле нет). Ширина теперь считается ПО РАМКЕ. */
.ps-textarea { box-sizing: border-box; width: 100%; min-height: 96px; resize: vertical; border: 1.6px solid var(--rp-line); border-radius: var(--rp-radius); background: var(--rp-card); padding: 11px 14px; font-family: var(--rp-font); font-size: 15px; font-weight: 500; color: var(--rp-ink); outline: none; transition: border-color .15s, box-shadow .15s; }
.ps-textarea:focus { border-color: var(--rp-accent); box-shadow: 0 0 0 3px rgba(245,179,1,0.2); }
.ps-textarea::placeholder { color: var(--rp-faint); }
.ps-textarea:disabled { background: var(--rp-line-2); cursor: not-allowed; opacity: .75; }
.ps-textarea.is-error { border-color: var(--rp-red); box-shadow: 0 0 0 3px rgba(226,72,61,0.13); }

/* ============================================================================
   17. Набор ps-ui-orchid — компоненты UI-волны (w6)
   Перевод поставки Claude Design (docs/40-ui/delivery-sandbox/*.jsx) в набор
   на токенах --rp-*: карточка заявки, деньги-сводка, пусто-блок, выбор прайса,
   индикатор средств, сводка-подтверждение, прогресс-бар (7 позиций+состояния),
   дата-ограничения, зависимые поля, распределитель секций, визард-обвязка,
   переключатель организации, иконка-счётчик + витринная DemoCard/StateBar.
   ========================================================================= */

/* — витрина: карточка компонента (DemoCard) + переключатель состояний (StateBar) — */
.ps-demo { background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: 18px; overflow: hidden; margin-bottom: 18px; scroll-margin-top: 16px; }
.ps-demo__head { padding: 18px 22px; border-bottom: 1px solid var(--rp-line); }
.ps-demo__titles { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ps-demo__prio { font-size: 11px; font-weight: 800; letter-spacing: .03em; padding: 3px 8px; border-radius: 6px; }
.ps-demo__prio--p1 { color: var(--rp-accent-deep); background: var(--rp-accent-soft); }
.ps-demo__prio--p2 { color: var(--rp-blue); background: var(--rp-blue-soft); }
.ps-demo__title { margin: 0; font-size: 18px; font-weight: 800; color: var(--rp-ink); letter-spacing: -.01em; }
.ps-demo__tag { font-size: 12.5px; font-weight: 600; color: var(--rp-sub); background: var(--rp-line-2); padding: 3px 8px; border-radius: 6px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.ps-demo__purpose { margin: 9px 0 0; font-size: 13.5px; color: var(--rp-sub); line-height: 1.5; max-width: 760px; }
.ps-demo__body { padding: 22px; background: var(--rp-bg); }
.ps-statebar { display: inline-flex; flex-wrap: wrap; gap: 4px; margin-top: 14px; background: var(--rp-line-2); border: 1px solid var(--rp-line); border-radius: 11px; padding: 4px; }
.ps-statebar__btn { border: none; border-radius: 8px; padding: 7px 13px; cursor: pointer; font-family: var(--rp-font); font-size: 13px; font-weight: 700; background: transparent; color: var(--rp-sub); transition: background .13s, color .13s; }
.ps-statebar__btn.is-active { background: var(--rp-card); color: var(--rp-ink); box-shadow: 0 1px 3px rgba(0,0,0,.08); }
/* переключаемые набором элементы (панели состояний, зависимые поля, ошибки) — hidden скрывает
   независимо от собственного display (иначе inline display:flex перебивает [hidden]) */
[hidden] { display: none !important; }

/* — выбираемая плитка/пилюля (общая: источник средств, тип сцепки, выбор прайса) — */
.ps-choice { display: flex; align-items: center; gap: 11px; text-align: left; border: 1.5px solid var(--rp-line); background: var(--rp-card); border-radius: 12px; padding: 13px 15px; cursor: pointer; font-family: var(--rp-font); transition: border-color .15s, background .15s; }
.ps-choice:hover { border-color: var(--rp-accent-deep); }
.ps-choice.is-on { border-color: var(--rp-accent-deep); background: var(--rp-accent-soft); }
.ps-choice__ico { color: var(--rp-sub); flex-shrink: 0; }
.ps-choice.is-on .ps-choice__ico { color: var(--rp-accent-deep); }
.ps-choice__label { font-size: 14px; font-weight: 700; color: var(--rp-ink); }
.ps-choice.is-on .ps-choice__label { color: var(--rp-accent-deep); }
.ps-choice__check { margin-left: auto; color: var(--rp-accent-deep); display: none; }
.ps-choice.is-on .ps-choice__check { display: inline-flex; }
.ps-choice--pill { padding: 9px 13px; border-radius: 10px; font-size: 13px; font-weight: 700; color: var(--rp-sub); }
.ps-choice--pill.is-on { color: var(--rp-ink); }

/* — карточка заявки (order-card) — */
/* w254 (Г3): min-width:0 — карточка ОБЯЗАНА уметь сжиматься. Значения внутри идут `white-space:nowrap`,
   поэтому min-content карточки равен ширине самой длинной строки (Базис/Грузополучатель бывают
   длинными) — без этого grid-колонка не сжималась ниже своего содержимого, сетка вылезала за
   контейнер и карточки наезжали друг на друга (жалоба тестировщика). Усечение уже есть — ему просто
   не давали сработать. */
.ps-ocard { position: relative; box-sizing: border-box; min-width: 0; text-align: left; width: 100%; display: flex; flex-direction: column; background: var(--rp-card); border: 1px solid var(--rp-line); border-left: 3px solid var(--rp-accent); border-radius: 14px; padding: 15px 17px; cursor: pointer; font-family: var(--rp-font); transition: border-color .15s, box-shadow .18s, transform .12s; }
.ps-ocard:hover { box-shadow: 0 8px 26px rgba(35,38,43,.09); transform: translateY(-2px); }
.ps-ocard:active { transform: translateY(0); }
.ps-ocard--denied { border-color: rgba(226,72,61,.4); border-left-color: var(--rp-red); }
.ps-ocard--cancelled { border-color: var(--rp-line); border-left-color: var(--rp-faint); opacity: .82; }
.ps-ocard__top { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; min-width: 0; }
.ps-ocard__no { font-size: 15px; font-weight: 800; color: var(--rp-ink); }
/* w254 (Г1): номер — ЕДИНСТВЕННАЯ ссылка карточки, и подчёркнута только она (по ховеру/фокусу).
   ::after растянут на всю карточку: клик по любому месту по-прежнему открывает заявку (тап-таргет
   мобилки не урезан), но текст карточки браузерное подчёркивание ссылки больше не наследует —
   раньше корнем был сам <a>, и «Объём/Сумма/Базис» читались как ссылки. */
a.ps-ocard__no { text-decoration: none; }
a.ps-ocard__no:hover, a.ps-ocard__no:focus-visible { text-decoration: underline; }
a.ps-ocard__no::after { content: ''; position: absolute; inset: 0; border-radius: inherit; }
.ps-ocard__date { font-size: 12.5px; color: var(--rp-faint); }
.ps-ocard__fuel { display: flex; align-items: center; gap: 8px; margin-bottom: 13px; min-width: 0; }
.ps-ocard__fuel span { min-width: 0; font-size: 14.5px; font-weight: 700; color: var(--rp-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-ocard__reason { display: flex; gap: 7px; align-items: flex-start; background: rgba(226,72,61,.08); border: 1px solid rgba(226,72,61,.25); border-radius: 9px; padding: 8px 10px; margin-bottom: 13px; font-size: 12px; color: var(--rp-sub); line-height: 1.4; }
.ps-ocard__grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 11px 14px; margin-top: auto; }
.ps-ocard__grid > div { min-width: 0; }
.ps-ocard__k { font-size: 11.5px; color: var(--rp-faint); font-weight: 600; margin-bottom: 2px; }
.ps-ocard__v { font-size: 13.5px; font-weight: 600; color: var(--rp-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-ocard__v.is-strong { font-weight: 800; }
/* w254 (Г2): подвал держит кнопку чата (слева) и статус (прижат вправо `margin-left:auto` — без
   `space-between`, чтобы одиночный статус остался справа, как и был). */
.ps-ocard__foot { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--rp-line-2); }
.ps-ocard__st { margin-left: auto; }
.ps-ocards { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; }

/* — стат-плитка (money tile) — */
.ps-stat { background: var(--rp-line-2); border-radius: 12px; padding: 13px 15px; }
.ps-stat__label { font-size: 12px; color: var(--rp-faint); font-weight: 600; margin-bottom: 6px; }
.ps-stat__value { font-size: 20px; font-weight: 800; color: var(--rp-ink); font-variant-numeric: tabular-nums; }
.ps-stat__value.is-neg { color: var(--rp-red); }
.ps-stat__value.is-none { color: var(--rp-faint); }
.ps-stat__hint { font-size: 11.5px; color: var(--rp-faint); margin-top: 4px; }

/* — сводка «Деньги и доступность» (money-summary) — */
.ps-money { background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: 16px; overflow: hidden; }
.ps-money__head { width: 100%; display: flex; align-items: center; gap: 11px; padding: 9px 18px; background: transparent; border: none; font-family: var(--rp-font); }
.ps-money.is-open .ps-money__head { border-bottom: 1px solid var(--rp-line); }
.ps-money__ico { width: 34px; height: 34px; border-radius: 9px; background: var(--rp-accent-soft); color: var(--rp-accent-deep); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.ps-money__title { font-size: 15px; font-weight: 800; color: var(--rp-ink); }
.ps-money__chev { margin-left: auto; color: var(--rp-faint); transition: transform .2s; }
.ps-money.is-open .ps-money__chev { transform: rotate(180deg); }
.ps-money__body { padding: 18px; }
.ps-money:not(.is-open) .ps-money__body { display: none; }
.ps-money__tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; margin-bottom: 16px; }
.ps-money__rows { display: flex; flex-direction: column; }
.ps-money__row { display: flex; align-items: center; gap: 10px; padding: 11px 4px; }
.ps-money__row + .ps-money__row { border-top: 1px solid var(--rp-line-2); }
.ps-money__row > span:first-child { font-size: 13.5px; color: var(--rp-sub); font-weight: 600; }
.ps-money__row > .b { margin-left: auto; }
.ps-money__err { background: var(--rp-card); border: 1px solid rgba(226,72,61,.35); border-radius: 14px; padding: 22px; display: flex; align-items: center; gap: 13px; }
.ps-money__err .t { font-size: 14.5px; font-weight: 700; color: var(--rp-ink); }
.ps-money__err .s { font-size: 13px; color: var(--rp-sub); margin-top: 2px; }

/* — w260: отметка времени финпоказателей + тихий индикатор обновления —
   Индикатор намеренно мелкий и внизу панели: обновление идёт фоном (холодный круг к кредитному
   сервису мерили в 42 с), остальная страница всё это время рабочая. `is-stale` — «обновиться не
   удалось»: янтарь, а не красный, потому что числа на экране верные — устарела только их свежесть. */
.ps-fin { display: flex; align-items: center; gap: 7px; margin-top: 12px; font-size: 11.5px; line-height: 1.35; color: var(--rp-faint); }
.ps-fin.is-stale { color: var(--rp-amber); }
.ps-fin__spin { width: 11px; height: 11px; flex-shrink: 0; border-radius: 50%; border: 2px solid var(--rp-line); border-top-color: var(--rp-faint); animation: ps-fin-spin .8s linear infinite; }
.ps-fin__spin[hidden] { display: none; }
@keyframes ps-fin-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .ps-fin__spin { animation: none; } }

/* — пустое состояние блока (empty-block) — */
.ps-empty { background: var(--rp-card); border: 1px dashed var(--rp-line); border-radius: 16px; padding: 44px 24px; text-align: center; }
.ps-empty__ico { width: 60px; height: 60px; border-radius: 16px; background: var(--rp-accent-soft); color: var(--rp-accent-deep); display: flex; align-items: center; justify-content: center; margin: 0 auto 16px; }
.ps-empty__title { font-size: 18px; font-weight: 800; color: var(--rp-ink); }
.ps-empty__text { font-size: 13.5px; color: var(--rp-sub); line-height: 1.5; max-width: 340px; margin: 8px auto 20px; }

/* — каталог-выбор позиции прайса (price-picker) — */
.ps-pick { display: flex; flex-direction: column; gap: 10px; }
.ps-pick__opt { display: flex; align-items: center; gap: 13px; text-align: left; border: 1.5px solid var(--rp-line); background: var(--rp-card); border-radius: 12px; padding: 13px 16px; cursor: pointer; font-family: var(--rp-font); transition: border-color .15s, background .15s, box-shadow .15s; }
/* w61: карточки топлива — ЯНТАРНЫЕ (accent), а не коричневые (accent-deep выглядел грязно) */
.ps-pick__opt:hover { border-color: var(--rp-accent); background: rgba(245,179,1,.05); }
.ps-pick__opt.is-on { border-color: var(--rp-accent); background: var(--rp-accent-soft); box-shadow: 0 0 0 3px rgba(245,179,1,.18); }
/* выбор через нативный radio внутри label (мастер, server-render) — мгновенная подсветка без JS */
.ps-pick__opt:has(input:checked) { border-color: var(--rp-accent); background: var(--rp-accent-soft); box-shadow: 0 0 0 3px rgba(245,179,1,.18); }
.ps-pick__opt:has(input:checked) .ps-pick__ico { background: #fff; color: var(--rp-accent-deep); }
.ps-pick__opt:has(input:checked) .ps-pick__radio { border-color: var(--rp-accent); background: var(--rp-accent); color: var(--rp-primary-deep); }
.ps-pick__opt:has(input:checked) .ps-pick__radio svg { display: inline; }
.ps-pick__opt { position: relative; }
.ps-pick__ico { width: 38px; height: 38px; border-radius: 9px; background: var(--rp-line-2); color: var(--rp-accent-deep); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.ps-pick__opt.is-on .ps-pick__ico { background: #fff; }
.ps-pick__main { flex: 1 1 auto; min-width: 0; }
.ps-pick__fuel { display: block; font-size: 14.5px; font-weight: 700; color: var(--rp-ink); }
.ps-pick__basis { display: block; font-size: 12.5px; color: var(--rp-sub); margin-top: 2px; }
.ps-pick__price { text-align: right; flex-shrink: 0; margin-left: auto; padding-left: 8px; }
.ps-pick__price b { font-size: 15.5px; font-weight: 800; color: var(--rp-ink); font-variant-numeric: tabular-nums; }
.ps-pick__price span { display: block; font-size: 11.5px; color: var(--rp-faint); }
.ps-pick__radio { width: 22px; height: 22px; border-radius: 11px; border: 1.6px solid var(--rp-line); display: flex; align-items: center; justify-content: center; flex-shrink: 0; color: #fff; }
.ps-pick__opt.is-on .ps-pick__radio { border-color: var(--rp-accent); background: var(--rp-accent); color: var(--rp-primary-deep); }
/* w63: галочка скрыта по умолчанию и показывается ТОЛЬКО у выбранной карточки — по классу (витрина,
   там radio нет) ЛИБО по реальному radio (мастер). Раньше правило `:not(.is-on) svg { display:none }`
   перебивало `:has(input:checked)` и у нового выбора галочка не появлялась. */
.ps-pick__radio svg { display: none; }
.ps-pick__opt.is-on .ps-pick__radio svg,
.ps-pick__opt:has(input:checked) .ps-pick__radio svg { display: inline; }
/* w65: резерв высоты каталога — карточка-держатель места. У отсрочки позиций на одну меньше, чем у
   предоплаты, и в УЗКОЙ раскладке (≤1080px, в т.ч. зум 150%), где колонки Ш1 встают друг под друга,
   длина каталога влияет на высоту страницы: при смене вида оплаты она скакала (замер: 1358 ↔ 1282),
   а с ней и высота сайдбара → `cover` пересчитывал фото и фон дёргался.
   Держатель невидим, но занимает ровно высоту карточки (та же разметка → без магических чисел),
   поэтому высота каталога не зависит от вида оплаты.
   В ШИРОКОЙ раскладке резерв не нужен и вреден: там правая колонка выше левой, высота страницы от
   каталога не зависит (замер: 991 = 991) — держатели убраны из потока, пустых «дыр» не появляется.
   Правила стоят ПОСЛЕ `.ps-pick__opt` намеренно: специфичность равная, и `display: flex` из базовой
   карточки иначе перебивал бы `display: none`. */
.ps-pick__opt--spacer { visibility: hidden; pointer-events: none; }

/* w153: причина отказа в строке договора — под бейджем «Отказ», мелким вторичным текстом. */
.cab-deny-reason { margin-top: 6px; font-size: 11.5px; line-height: 1.35; color: var(--rp-sub); max-width: 34ch; }

/* w148: базис, недоступный ИМЕННО этому контрагенту (ограничения склада из ELMA). Карточка не
   исчезает — она глушится и несёт причину + следующее действие. Выбор физически невозможен
   (input disabled), так что подсветка/hover тут не нужны. */
.ps-pick__opt.is-blocked { cursor: not-allowed; background: var(--rp-line-2); border-color: var(--rp-line); opacity: .72; }
.ps-pick__opt.is-blocked:hover { border-color: var(--rp-line); background: var(--rp-line-2); }
.ps-pick__opt.is-blocked .ps-pick__fuel,
.ps-pick__opt.is-blocked .ps-pick__price b { color: var(--rp-sub); }
.ps-pick__opt.is-blocked .ps-pick__radio { visibility: hidden; }
.ps-pick__block { display: block; font-size: 11.5px; line-height: 1.35; color: var(--rp-sub); margin-top: 4px; }
@media (min-width: 1081px) { .ps-pick__opt--spacer { display: none; } }

/* — индикатор доступности средств (funds-indicator) — */
.ps-funds { max-width: 560px; display: flex; flex-direction: column; gap: 14px; }
.ps-funds__label { font-size: 13.5px; font-weight: 700; color: var(--rp-ink); margin-bottom: 8px; }
.ps-funds__result { border-radius: 14px; padding: 16px 18px; border: 1px solid; }
.ps-funds__result--ok { background: var(--rp-green-soft); border-color: rgba(31,157,85,.3); }
.ps-funds__result--no { background: var(--rp-red-soft); border-color: rgba(226,72,61,.3); }
.ps-funds__result--none { background: var(--rp-line-2); border-color: var(--rp-line); }
.ps-funds__head { display: flex; align-items: center; gap: 10px; }
.ps-funds__result--ok .ps-funds__head { margin-bottom: 12px; }
.ps-funds__result--no .ps-funds__head { margin-bottom: 12px; }
.ps-funds__headline { font-size: 16px; font-weight: 800; }
.ps-funds__result--ok .ps-funds__headline { color: var(--rp-green); }
.ps-funds__result--no .ps-funds__headline { color: var(--rp-red); }
.ps-funds__result--none .ps-funds__headline { color: var(--rp-sub); }
.ps-funds__line { display: flex; justify-content: space-between; font-size: 13.5px; margin-bottom: 5px; }
.ps-funds__line span:first-child { color: var(--rp-sub); font-weight: 600; }
.ps-funds__line b { font-weight: 800; color: var(--rp-ink); font-variant-numeric: tabular-nums; }
.ps-funds__total { padding-top: 8px; border-top: 1px solid rgba(0,0,0,.1); }
.ps-funds__total b.is-ok { color: var(--rp-green); } .ps-funds__total b.is-no { color: var(--rp-red); }
.ps-funds__note { font-size: 13px; color: var(--rp-sub); margin: 4px 0 0; line-height: 1.45; }
.ps-funds__actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 13px; }

/* — сводка-подтверждение (review-summary) — */
/* — предпросмотр текста заявки-доверенности (w20) — читаемая копия данных .docx — */
.ps-docpreview { font-size: 13px; color: var(--rp-ink); }
.ps-docpreview__title { font-size: 14.5px; font-weight: 800; }
.ps-docpreview__sub { font-size: 12.5px; color: var(--rp-sub); margin: 2px 0 14px; }
.ps-docpreview__grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px 20px; }
.ps-docpreview__group { border-top: 1px solid var(--rp-line-2); padding-top: 8px; }
.ps-docpreview__gt { font-size: 11px; font-weight: 800; letter-spacing: .03em; text-transform: uppercase; color: var(--rp-faint); margin-bottom: 5px; }
.ps-docpreview__row { display: flex; align-items: baseline; gap: 10px; padding: 2px 0; }
.ps-docpreview__row > span { flex-shrink: 0; min-width: 120px; color: var(--rp-sub); }
.ps-docpreview__row > b { font-weight: 700; }
.ps-docpreview__chips { display: flex; flex-wrap: wrap; gap: 6px; }
.ps-docpreview__chip { font-size: 12px; font-weight: 700; padding: 3px 9px; border-radius: 7px; background: var(--rp-line-2); color: var(--rp-ink); }
.ps-docpreview__chip--pipe { background: var(--rp-accent-soft); color: var(--rp-accent-deep); }
@media (max-width: 620px) { .ps-docpreview__grid { grid-template-columns: 1fr; } }

/* — раздел «Моя организация» (w22) — реквизиты + списки счетов/сотрудников — */
.org-reqs { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px 24px; }
.org-req { display: flex; align-items: baseline; gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--rp-line-2); }
.org-req > span { flex-shrink: 0; min-width: 170px; font-size: 12.5px; color: var(--rp-sub); font-weight: 600; }
.org-req > b { font-weight: 700; color: var(--rp-ink); }
.org-list { display: flex; flex-direction: column; gap: 10px; }
.org-item { display: flex; align-items: center; gap: 14px; padding: 12px 14px; border-radius: 12px; background: var(--rp-line-2); }
.org-item__main { flex: 1; min-width: 0; }
.org-item__title { display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 700; color: var(--rp-ink); flex-wrap: wrap; }
.org-item__cur { font-size: 11.5px; font-weight: 700; color: var(--rp-faint); }
.org-item__meta { font-size: 12.5px; color: var(--rp-sub); margin-top: 3px; }
.org-item__actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.org-item__actions form { margin: 0; }
/* F·w441: сотрудник с закрытым доступом остаётся в списке, но читается как «не при делах» —
   приглушаем ИМЯ и подпись, а не всю строку: значки прав и кнопка «Открыть доступ» должны
   оставаться разборчивыми, иначе вернуть человека будет труднее, чем убрать. */
.org-item.is-access-closed .org-item__title { color: var(--rp-sub); }
.org-item.is-access-closed .org-item__meta { color: var(--rp-faint); }
/* ── B·w385 (ТЗ Владельца 04.08 §3): ЧТО сотрудник вправе подписывать — явным списком ───────────
   Один и тот же список в двух местах: живая подсказка в окне добавления/правки (пересчёт по
   галочкам) и карточка сотрудника в списке. Состояние строки — классом, а не подменой значка из
   JS: обе иконки лежат в разметке, показывает одну CSS. Так живой пересчёт не тащит в скрипт
   геометрию иконок набора (она осталась там, где ей и место — в компоненте). */
.org-rights { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.org-rights__item { display: flex; align-items: center; gap: 8px; font-size: 12.5px; line-height: 1.35; }
.org-rights__item.is-on { color: var(--rp-ink); }
.org-rights__item.is-off { color: var(--rp-faint); }
.org-rights__item.is-on .org-rights__no,
.org-rights__item.is-off .org-rights__yes { display: none; }
.org-rights__item.is-on .org-rights__yes { color: var(--rp-green, #1a7f4b); display: inline-flex; }
.org-rights__item.is-off .org-rights__no { color: var(--rp-faint); display: inline-flex; }
.org-rights__yes, .org-rights__no { flex-shrink: 0; align-items: center; }
/* ── Автопарк: картинка типа техники первым элементом строки (F·w355, запрос клиента 01.08) ──────
   Пришла на смену 22px-пиктограмме (w287 п.7, класс `.fleet-type` — удалён вместе с ней): клиенту
   понравились иллюстрации техники на шаге «Бензовоз» мастера, и он попросил их же в автопарке.
   Приём — тот же, что у карточек сцепки (`.wiz-t3__couplings .ps-coupling-card__img`): ОДИН кадр на
   все типы, заданный пропорцией САМОЙ ШИРОКОЙ картинки (полуприцеп 426×185), плюс `object-fit:
   contain`. Отсюда два свойства, ради которых приём и взят: строки списка не прыгают по высоте от
   типа техники (высота кадра фиксирована), а короткая цистерна или прицеп не растягиваются и не
   обрезаются — просто занимают в кадре меньше ширины.
   40px — компромисс по месту: пиктограмма была 22px и терялась, а выше 40px строка списка начинает
   читаться как карточка (у строки всего две текстовые строки, ~44px). */
.fleet-thumb { flex: 0 0 auto; height: 40px; aspect-ratio: 426 / 185; display: flex; align-items: center; justify-content: center; }
.fleet-thumb img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* ── w368 (отчёт 02.08 ч.2, п.29): картинки в строках стояли неровно ─────────────────────────
   🔴 Кадр-то был один на все типы (см. выше) — «разной ширины» оказалась сама КАРТИНКА внутри него.
   `object-fit: contain` вписывает изображение в кадр и центрирует остаток: у цистерны (359×171) при
   высоте 40px выходит 84px, у тягача (282×183) — 62px, у прицепа (244×171) — 57px, у полуприцепа
   (426×185) — 92px. Разница до 35px, и каждая картинка висела по центру своего кадра — то есть по
   разным вертикалям.
   Лечим краем, а не кадром: кадр сужаем до самой широкой картинки ВКЛАДКИ (пропорцией, чтобы
   работало и на 30px мобильной высоты), а содержимое прижимаем — техника вкладки «Цистерны и
   тягачи» смотрит вправо, поэтому её выравниваем ВЛЕВО (морды на одной вертикали); прицепы и
   полуприцепы цепляются слева — их ВПРАВО, как и просил отчёт (правые края совпадают).
   Текст строк при этом начинается на одной вертикали: кадр внутри вкладки одной ширины. */
.fleet-thumb--trucks { aspect-ratio: 359 / 171; justify-content: flex-start; }
.fleet-thumb--trailers { aspect-ratio: 426 / 185; justify-content: flex-end; }
.fleet-thumb--trucks img, .fleet-thumb--trailers img { width: auto; max-width: 100%; }
@media (max-width: 620px) {
    .org-reqs { grid-template-columns: 1fr; }
    .org-item { flex-wrap: wrap; }
    /* На телефоне строка и так переносится: кадр ужимаем, чтобы картинка не съедала ширину
       у номера и марки (тот же приём, что у карточек сцепки на узком экране). */
    .fleet-thumb { height: 30px; }
}

/* — формы автопарка (w32): подзаголовки блоков + сетка 7+7 секций/трубопроводов — */
.fleet-form__sub { font-size: 12px; font-weight: 800; letter-spacing: .02em; text-transform: uppercase; color: var(--rp-faint); border-top: 1px solid var(--rp-line-2); padding-top: 12px; margin: 14px 0 8px; }
.fleet-cells { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 8px 12px; }
.fleet-cell .ps-field__label { font-size: 11.5px; }
[data-cistern-block][hidden], [data-pipelines-block][hidden], [data-ru-passport][hidden], [data-other-passport][hidden], [data-middle-req][hidden], [data-pledge-files][hidden], [data-warehouse-block][hidden] { display: none !important; }

/* экран «Прайс-лист» держался на вне-наборных .price-* (w30) — в w51 переложен на набор:
   ps-segment · ps-filters--fields · ps-acc (богатая шапка) · ps-table--cards · ps-note */

.ps-review { display: flex; flex-direction: column; gap: 12px; }   /* ширину задаёт экран, не набор (w58) */
.ps-review__sec { background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: 14px; overflow: hidden; }
.ps-review__sec.is-warn { border-color: rgba(229,164,0,.5); }
.ps-review__head { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-bottom: 1px solid var(--rp-line-2); background: var(--rp-line-2); }
.ps-review__sec.is-warn .ps-review__head { background: var(--rp-amber-soft); }
.ps-review__head .k { font-size: 14.5px; font-weight: 800; color: var(--rp-ink); }
.ps-review__edit { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; background: transparent; border: none; color: var(--rp-accent-deep); font-family: var(--rp-font); font-size: 13px; font-weight: 700; cursor: pointer; }
/* w367 (п.25): у текстовых действий портала обязаны быть ховер и КЛАВИАТУРНЫЙ фокус — иначе с
   клавиатуры не видно, где ты находишься. Обводка та же, что у `.ps-link` (одно правило на портал). */
.ps-review__edit:hover { text-decoration: underline; }
.ps-review__edit:focus-visible { outline: 2px solid var(--rp-accent); outline-offset: 2px; border-radius: 4px; }
.cab-usermenu__item:focus-visible { outline: 2px solid var(--rp-accent); outline-offset: -2px; }
.cab-help__row:focus-visible { outline: 2px solid var(--rp-accent); outline-offset: 2px; border-radius: 4px; }
.ps-review__rows { padding: 6px 16px 10px; }
.ps-review__row { display: flex; gap: 14px; padding: 8px 0; }
.ps-review__row + .ps-review__row { border-top: 1px solid var(--rp-line-2); }
.ps-review__row .k { font-size: 13px; color: var(--rp-faint); font-weight: 600; width: 150px; flex-shrink: 0; }
.ps-review__row .v { font-size: 13.5px; color: var(--rp-ink); font-weight: 700; }
.ps-review__row .v.is-warn { color: var(--rp-red); }

/* — прогресс-бар заявки: 7 позиций + состояния (progress-bar) — */
.ps-prog { background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: 16px; padding: 26px 24px; }
/* w240 (R-67): единый степпер под мастер И карточку. --bare — без карточной обёртки (уже внутри .ps-card). */
.ps-prog--bare { background: transparent; border: none; border-radius: 0; padding: 6px 2px 2px; }
/* адаптив: 7 подписей снизу не влезают в узкую раскладку (мобильная) — горизонтальная прокрутка,
   а не обрезка/налезание. Верт. паддинг оставляет место пульс-кольцу is-waiting (не режется). */
/* padding по бокам — чтобы подписи КРАЙНИХ стадий (широкое одно слово, напр. «Формирование»),
   вылезающие за свой шаг, не срезал overflow-x у контейнера. */
.ps-prog__chain { display: flex; align-items: flex-start; overflow-x: auto; scrollbar-width: thin; padding: 3px 10px; }
.ps-prog__step { display: flex; flex-direction: column; align-items: center; gap: 9px; flex: 0 0 auto; width: 84px; }
.ps-prog__step.is-clickable { cursor: pointer; }
/* степпер-как-кнопка (режим мастера, clickable): сброс дефолтных стилей button */
button.ps-prog__step { border: none; background: none; padding: 0; font-family: inherit; color: inherit; }
button.ps-prog__step:not(.is-clickable) { cursor: default; }
.ps-prog__node { position: relative; width: 38px; height: 38px; border-radius: 19px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; font-size: 14px; font-weight: 800; border: 2px solid var(--rp-line); background: var(--rp-line-2); color: var(--rp-faint); }
.ps-prog__step.is-done   .ps-prog__node { background: var(--rp-green); border-color: var(--rp-green); color: #fff; }
.ps-prog__step.is-current .ps-prog__node { background: var(--rp-accent); border-color: var(--rp-accent); color: #fff; }
.ps-prog__step.is-waiting .ps-prog__node { background: var(--rp-amber-soft); border-color: var(--rp-amber); color: var(--rp-amber); }
.ps-prog__step.is-rejected .ps-prog__node { background: var(--rp-red); border-color: var(--rp-red); color: #fff; }
.ps-prog__step.is-waiting .ps-prog__node::after { content: ""; position: absolute; inset: -2px; border-radius: 21px; border: 2px solid rgba(229,164,0,.4); animation: ps-pulse 1.2s ease infinite alternate; }
@keyframes ps-pulse { from { transform: scale(.97); } to { transform: scale(1.06); } }
.ps-prog__label { font-size: 11.5px; font-weight: 600; color: var(--rp-faint); text-align: center; line-height: 1.25; }
.ps-prog__step.is-current .ps-prog__label { font-weight: 800; color: var(--rp-ink); }
.ps-prog__step.is-done .ps-prog__label, .ps-prog__step.is-waiting .ps-prog__label { color: var(--rp-ink); }
.ps-prog__step.is-rejected .ps-prog__label { color: var(--rp-red); }
.ps-prog__conn { flex: 1; height: 3px; border-radius: 2px; margin-top: 17.5px; background: var(--rp-line); min-width: 12px; }
.ps-prog__conn.is-filled { background: var(--rp-green); }
.ps-prog__banner { display: flex; align-items: center; gap: 9px; margin-top: 20px; background: var(--rp-red-soft); border: 1px solid rgba(226,72,61,.3); border-radius: 10px; padding: 11px 14px; font-size: 13px; color: var(--rp-sub); font-weight: 600; }
.ps-prog--compact { max-width: 360px; display: flex; align-items: center; gap: 12px; padding: 13px 16px; }
.ps-prog__dots { display: flex; gap: 5px; }
.ps-prog__dot { width: 8px; height: 8px; border-radius: 4px; background: var(--rp-line); }
.ps-prog__dot.is-cur { width: 20px; }
.ps-prog__dot.is-done { background: var(--rp-green); }
.ps-prog__dot.is-current { background: var(--rp-accent); }
.ps-prog__dot.is-waiting { background: var(--rp-amber); }
.ps-prog__dot.is-rejected { background: var(--rp-red); }
.ps-prog__meta { margin-left: auto; font-size: 13px; font-weight: 700; color: var(--rp-ink); }
.ps-seg { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
.ps-seg__label { font-size: 12.5px; color: var(--rp-faint); font-weight: 600; }

/* — распределитель секций / трубопроводов (compartment-allocator) — */
.ps-alloc { max-width: 640px; background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: 16px; overflow: hidden; }
.ps-alloc__cells { padding: 16px 18px 6px; display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 12px; }
.ps-alloc__label { font-size: 12.5px; font-weight: 700; color: var(--rp-sub); margin-bottom: 6px; }
.ps-alloc__label.is-pipe { color: var(--rp-blue); }
.ps-alloc__cap { font-size: 11.5px; color: var(--rp-faint); margin-top: 5px; }
.ps-alloc__cell.is-over .ps-alloc__cap { color: var(--rp-red); }
.ps-alloc__foot { border-top: 1px solid var(--rp-line); background: var(--rp-line-2); padding: 14px 18px; }
.ps-alloc__sumrow { display: flex; align-items: center; margin-bottom: 10px; }
.ps-alloc__sumrow .t { font-size: 13.5px; font-weight: 700; color: var(--rp-ink); }
.ps-alloc__sumrow .v { margin-left: auto; font-size: 13.5px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--rp-ink); }
.ps-alloc__sumrow .v span { color: var(--rp-faint); font-weight: 700; }
.ps-alloc__bar { height: 8px; background: var(--rp-line); border-radius: 4px; overflow: hidden; }
.ps-alloc__fill { height: 100%; background: var(--rp-accent); border-radius: 4px; transition: width .25s; }
.ps-alloc__fill.is-exact { background: var(--rp-green); }
.ps-alloc__status { display: flex; align-items: center; gap: 7px; margin-top: 9px; font-size: 12.5px; font-weight: 700; color: var(--rp-accent-deep); }
.ps-alloc__status.is-exact { color: var(--rp-green); }
.ps-alloc__status .ico-warn { display: inline-flex; color: var(--rp-accent-deep); }
.ps-alloc__status .ico-ok { display: none; color: var(--rp-green); }
.ps-alloc__status.is-exact .ico-warn { display: none; }
.ps-alloc__status.is-exact .ico-ok { display: inline-flex; }

/* — репитер строк-позиций (ps.line-items, w39c: мультипозиционная корзина + живой итог) — */
.ps-line-items { border: 1px solid var(--rp-line); border-radius: 14px; overflow: hidden; background: var(--rp-card); }
.ps-line-items__rows { display: flex; flex-direction: column; }
.ps-line-items__row { display: grid; grid-template-columns: minmax(0,2.4fr) 0.9fr 1.1fr 1fr auto; gap: 12px; align-items: end; padding: 14px 16px; border-bottom: 1px solid var(--rp-line); }
.ps-line-items__row:last-child { border-bottom: none; }
.ps-line-items__cell { min-width: 0; }
.ps-line-items__cell .ps-field__label { margin-bottom: 5px; }
.ps-line-items__cell--rowsum { text-align: right; }
.ps-line-items__rowsum { padding: 9px 2px; font-size: 13.5px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--rp-ink); }
.ps-line-items__rm { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 40px; border: none; background: transparent; color: var(--rp-faint); border-radius: 8px; cursor: pointer; }
.ps-line-items__rm:hover { background: rgba(226,72,61,0.09); color: var(--rp-red); }
.ps-line-items__bar { display: flex; align-items: center; gap: 14px; padding: 14px 16px; background: var(--rp-line-2); border-top: 1px solid var(--rp-line); flex-wrap: wrap; }
.ps-line-items__total-wrap { margin-left: auto; display: flex; align-items: baseline; gap: 7px; }
.ps-line-items__total-lbl { font-size: 12.5px; font-weight: 700; color: var(--rp-sub); }
.ps-line-items__total { font-size: 16px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--rp-ink); }
.ps-line-items__cur { font-size: 13px; font-weight: 700; color: var(--rp-faint); }
.ps-line-items__hint { padding: 0 16px 14px; font-size: 12px; color: var(--rp-faint); }
@media (max-width: 720px) {
    .ps-line-items__row { grid-template-columns: 1fr 1fr; grid-template-areas: 'product product' 'qty price' 'rowsum rm'; }
    .ps-line-items__cell--product { grid-area: product; }
    .ps-line-items__cell--qty { grid-area: qty; }
    .ps-line-items__cell--price { grid-area: price; }
    .ps-line-items__cell--rowsum { grid-area: rowsum; text-align: left; align-self: center; }
    .ps-line-items__cell--rm { grid-area: rm; justify-self: end; align-self: center; }
}

/* — визард-обвязка (wizard shell) — */
.ps-wizard { max-width: 720px; background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: 16px; overflow: hidden; }
.ps-wizard__prog { display: flex; gap: 6px; padding: 16px 20px; border-bottom: 1px solid var(--rp-line-2); }
.ps-wizard__seg { flex: 1; text-align: left; border: none; background: transparent; padding: 0; font-family: var(--rp-font); }
.ps-wizard__seg.is-done { cursor: pointer; }
.ps-wizard__segbar { height: 4px; border-radius: 2px; background: var(--rp-line); margin-bottom: 7px; }
.ps-wizard__seg.is-done .ps-wizard__segbar { background: var(--rp-green); }
.ps-wizard__seg.is-current .ps-wizard__segbar { background: var(--rp-accent); }
.ps-wizard__seglabel { display: flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 600; color: var(--rp-faint); }
.ps-wizard__seg.is-done .ps-wizard__seglabel { color: var(--rp-sub); }
.ps-wizard__seg.is-current .ps-wizard__seglabel { font-weight: 800; color: var(--rp-ink); }
.ps-wizard__seg:not(.is-done) .ps-wizard__seglabel svg { display: none; }
/* w367 (отчёт 02.08, п.13): полоса-сводка над формой мастера была 41px при 11px вертикальных
   отступов — «избыточно высокая» для одной строки в 12,5px. Отступы 7px дают 33px; горизонтальные
   и внешний (cab-mb) не тронуты, текст остаётся по центру вертикали (align-items у flex по умолчанию
   растягивает элементы, высота задаётся строкой). */
.ps-wizard__ctx { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 18px; padding: 7px 20px; background: var(--rp-line-2); font-size: 12.5px; color: var(--rp-faint); }
.ps-wizard__ctx b { color: var(--rp-ink); }
/* w367 (п.28): скрытая ПЕРВАЯ submit-кнопка формы-мастера. Неявная отправка по Enter выбирает первую
   submit-кнопку в разметке — до правки ею была «Назад», и Enter в поле секции уводил на шаг назад с
   потерей ввода. Страж несёт действие ТЕКУЩЕГО шага, поэтому даже без скрипта Enter ведёт вперёд.
   Не `display:none` и не `hidden`: скрытая такими способами кнопка перестаёт быть submitter'ом. */
.ps-enter-guard { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; border: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
.ps-wizard__body { padding: 20px 20px 8px; }
.ps-wizard__steptitle { font-size: 16px; font-weight: 800; color: var(--rp-ink); margin-bottom: 4px; }
.ps-wizard__stepmeta { font-size: 12.5px; color: var(--rp-faint); margin-bottom: 16px; }
.ps-wizard__nav { display: flex; align-items: center; gap: 10px; padding: 16px 20px; border-top: 1px solid var(--rp-line-2); }
.ps-wizard__nav .spacer { margin-left: auto; }
.ps-wizard__state { max-width: 720px; margin-top: 10px; font-size: 12.5px; color: var(--rp-red); font-weight: 600; display: flex; align-items: center; gap: 6px; }

/* — переключатель организации (org-switcher) — */
.ps-orgsw { position: relative; max-width: 340px; }
.ps-orgsw__trigger { width: 100%; display: flex; align-items: center; gap: 11px; background: var(--rp-card); border: 1.5px solid var(--rp-line); border-radius: 12px; padding: 11px 14px; cursor: pointer; font-family: var(--rp-font); text-align: left; }
.ps-orgsw.is-open .ps-orgsw__trigger { border-color: var(--rp-accent-deep); }
.ps-orgsw__ava { width: 34px; height: 34px; border-radius: 9px; background: var(--rp-primary); color: #fff; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.ps-orgsw__name { display: block; font-size: 13.5px; font-weight: 700; color: var(--rp-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-orgsw__inn { display: block; font-size: 11.5px; color: var(--rp-faint); }
.ps-orgsw__chev { color: var(--rp-faint); transition: transform .18s; }
.ps-orgsw.is-open .ps-orgsw__chev { transform: rotate(180deg); }
.ps-orgsw__menu { position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 41; background: #fff; border: 1px solid var(--rp-line); border-radius: 12px; box-shadow: 0 16px 44px rgba(0,0,0,.16); overflow: hidden; }
.ps-orgsw:not(.is-open) .ps-orgsw__menu { display: none; }
.ps-orgsw__opt { width: 100%; display: flex; align-items: center; gap: 10px; padding: 11px 14px; border: none; background: transparent; cursor: pointer; font-family: var(--rp-font); text-align: left; }
.ps-orgsw__opt + .ps-orgsw__opt { border-top: 1px solid var(--rp-line-2); }
.ps-orgsw__opt.is-on { background: var(--rp-accent-soft); }
.ps-orgsw__opt:hover { background: var(--rp-line-2); }
.ps-orgsw__opt.is-on:hover { background: var(--rp-accent-soft); }
.ps-orgsw__opt .chk { margin-left: auto; color: var(--rp-accent-deep); display: none; }
.ps-orgsw__opt.is-on .chk { display: inline-flex; }

/* — иконка со счётчиком (counter-icon) — */
.ps-counter { position: relative; width: 44px; height: 44px; border-radius: 11px; border: 1px solid var(--rp-line); background: var(--rp-card); color: var(--rp-ink); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }
/* w287 (п.29): фирменный вариант кнопки-счётчика — колокольчик уведомлений в шапке. Он стоял
   чёрно-белым среди акцентных элементов той же шапки и читался как чужой.
   w353 (п.15, требование в третий раз): «тёмный янтарь по контуру» — это была полумера, просили
   ЗОЛОТОЙ ФОН и ЧЁРНЫЙ колокольчик. Берём ровно ту пару токенов, что у жёлтой плашки шапки
   кабинета (`.cab-imp`): фон --rp-accent, контент --rp-primary-deep. Довод w287 про контраст снят
   самой правкой: иконка теперь не на белой подложке, а на золоте. Замерено откатом в наборе
   orders-bell-w353 — было 2.83:1 (тёмное золото по белому, то есть w287 сам не дотягивал до
   порога 4.5), стало 9.1:1 (чёрное по золоту). Это строго лучше, а не «мягче». */
.ps-counter--accent { background: var(--rp-accent); border-color: var(--rp-accent); color: var(--rp-primary-deep); }
.ps-counter--accent:hover { background: var(--rp-accent-deep); border-color: var(--rp-accent-deep); }
.ps-counter__badge { position: absolute; top: -6px; right: -6px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 10px; background: var(--rp-red-deep); color: #fff; font-size: 11px; font-weight: 800; display: flex; align-items: center; justify-content: center; border: 2px solid var(--rp-bg); font-variant-numeric: tabular-nums; }
/* 🔴 w377 (решение Владельца 04.08): фон бейджа переведён на `--rp-red-deep`. Находка моя же, из
   w353: белая надпись на прежнем красном не дотягивала до порога. ⚠ Число в отчёте w353 (3.37:1)
   было неточным — фактический замер даёт 4.02:1; вывод «ниже порога 4.5» от этого не меняется.
   Стало 4.98:1. Размеры бейджа не тронуты (соседи не дёргаются), красный остался красным, а его
   читаемость НА ЗОЛОТОЙ кнопке заодно выросла: 2.17 → 2.69:1 (тёмный красный дальше от золота).
   Правило общее для всех счётчиков набора — чат-док, пункт меню, темы: один бейдж, один вид. */
/* w353: бейдж непрочитанного лежит углом на кнопке и углом на тёмной шапке. Светлая обводка
   (--rp-bg) была рассчитана на белую кнопку: на золоте она даёт 1.6:1 и края бейджа не отделяет,
   а красный по золоту — всего 2.2:1. Тёмная обводка разделяет обе стороны сразу: к золоту 9.1:1,
   к красному 4.2:1. Сам бейдж не трогаем — красный здесь семантика «непрочитанное». */
.ps-counter--accent .ps-counter__badge { border-color: var(--rp-primary-deep); }
.ps-counter__badge[data-count="0"] { display: none; }
.ps-ctrbtn { width: 36px; height: 36px; border-radius: 9px; border: 1px solid var(--rp-line); background: var(--rp-card); color: var(--rp-ink); font-size: 20px; font-weight: 700; cursor: pointer; line-height: 1; }

/* — блок «результат/пусто/ошибка» вне таблиц (общий inline) — */
.ps-inlinebox { display: flex; align-items: center; gap: 12px; background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: 12px; padding: 18px; font-size: 13.5px; color: var(--rp-sub); }
.ps-inlinebox--err { border-color: rgba(226,72,61,.35); }
.ps-inlinebox--empty { border-style: dashed; flex-direction: column; text-align: center; padding: 40px 20px; }
.ps-inlinebox--empty .t { font-size: 15px; font-weight: 700; color: var(--rp-ink); }
.ps-inlinebox--empty .s { font-size: 13px; color: var(--rp-sub); margin-top: 5px; }

@media (max-width: 720px) {
    .ps-ocard__grid { grid-template-columns: 1fr; }
    .ps-review__row { flex-direction: column; gap: 2px; }
    .ps-review__row .k { width: auto; }
    /* w240: не ужимаем шаг до 60px (широкие однословные подписи «Формирование»/«Согласование»
       налезали на соседей). Полная ширина + горизонтальная прокрутка chain — подписи не сталкиваются. */
    .ps-prog__label { font-size: 10.5px; }
}

/* ============================================================================
   18. Набор ps-ui-orchid — блоки главной кабинета (w6b)
   Перевод delivery/home-blocks.jsx в набор на --rp-*: плитки-действия, портлеты
   (цены/отгрузки/документы), онбординг-чек-лист. Общий портлет-хром .ps-portlet.
   ========================================================================= */

/* — общий хром портлета (карточка с шапкой-иконкой и подвалом-ссылкой) — */
.ps-portlet { background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: 16px; overflow: hidden; }
.ps-portlet__head { display: flex; align-items: center; gap: 10px; padding: 15px 18px; border-bottom: 1px solid var(--rp-line-2); }
.ps-portlet__ico { width: 32px; height: 32px; border-radius: 9px; background: var(--rp-accent-soft); color: var(--rp-accent-deep); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.ps-portlet__title { font-size: 15.5px; font-weight: 800; color: var(--rp-ink); }
.ps-portlet__meta { margin-left: auto; font-size: 11.5px; color: var(--rp-faint); }
/* подвал-панели ссылка-переход — единый стиль ссылок-CTA (эталон .ps-tile__cta «Оформить →»):
   компактная, слева, акцент+стрелка, тонкий верхний разделитель. w16. */
/* w236 (#28): «Скачать заявку»/«Все документы» терялись — подняли кегль на ~2,5 пункта. */
/* 🔴 w372: `box-sizing` здесь не косметика. У подвала `width: 100%` + `padding: 0 18px`, а
   глобального ресета в файле нет — элемент выходил за плитку ровно на 36px (замер набора). Видно
   этого не было: `.ps-portlet { overflow: hidden }` срезал правый отступ, — но плитка при этом
   честно имела горизонтальное переполнение, и любая проверка «не едет вбок» на ней была красной.
   Найдено замером в w372, к правкам строки цены отношения не имеет. */
.ps-portlet__foot, .ps-money__foot { box-sizing: border-box; width: 100%; display: flex; align-items: center; justify-content: flex-start; gap: 6px; padding: 12px 18px; margin-top: 0; border: none; border-top: 1px solid var(--rp-line-2); background: transparent; cursor: pointer; font-family: var(--rp-font); font-size: 15px; font-weight: 700; color: var(--rp-accent-deep); text-decoration: none; }
.ps-portlet__foot:hover, .ps-money__foot:hover { text-decoration: underline; background: transparent; }
.ps-portlet__state { padding: 34px 22px; text-align: center; }
.ps-portlet__state .ico { color: var(--rp-faint); display: block; margin: 0 auto 10px; }
.ps-portlet__state .t { font-size: 14.5px; font-weight: 700; color: var(--rp-ink); }
.ps-portlet__state .s { font-size: 13px; color: var(--rp-sub); margin: 5px 0 14px; }
.ps-portlet__err { display: flex; align-items: center; gap: 12px; padding: 18px; font-size: 13.5px; color: var(--rp-sub); }

/* — секционный заголовок с действием — */
.ps-sechead { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.ps-sechead__ico { color: var(--rp-accent-deep); }
.ps-sechead h2 { margin: 0; font-size: 17px; font-weight: 800; color: var(--rp-ink); letter-spacing: -.01em; }
/* подпись рядом с заголовком (единица измерения, НДС и т.п.; на мобайле — со строки ниже) */
.ps-sechead__sub { font-size: 13px; color: var(--rp-sub); }
/* сноска-пояснение под блоком (мелкий вторичный текст)
   🔴 E·w403 (П.15 отчёта тестировщика): цвет был `--rp-faint` — на белой карточке это 2.64:1 при
   пороге 4.5:1 для обычного текста, то есть подписи физически плохо читались. А в сносках у нас
   лежит не декор, а смысл: «Документ подписан. Отправьте подпись в РАЦИН» говорит, что делать
   дальше, «Демо-кнопка формирует фейк-подпись…» предупреждает о характере действия.
   Стало `--rp-sub` — 5.97:1, порог пройден. Правка ОДНОГО класса чинит все сноски разом; сам токен
   `--rp-faint` не трогаем (он живёт по всему порталу, включая админку), но для ТЕКСТА он не годится
   нигде — это отдельная работа дизайна. */
.ps-note { margin: 14px 2px 0; font-size: 12.5px; color: var(--rp-sub); line-height: 1.55; }
.ps-note b { color: var(--rp-ink); font-weight: 700; }
@media (max-width: 620px) { .ps-sechead { flex-wrap: wrap; } .ps-sechead__sub { flex-basis: 100%; } }
/* действие sec-head — тот же единый вид ссылки-перехода (акцент+стрелка, компактно, w16) */
.ps-sechead__action { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; background: transparent; border: none; color: var(--rp-accent-deep); font-family: var(--rp-font); font-size: 12.5px; font-weight: 700; cursor: pointer; text-decoration: none; }
.ps-sechead__action:hover { text-decoration: underline; }

/* — сетка плиток-действий (action-tile) — */
.ps-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px; }
.ps-tile { position: relative; overflow: hidden; text-align: left; border: 1px solid var(--rp-line); background: var(--rp-card); border-radius: 15px; padding: 16px 17px; cursor: pointer; font-family: var(--rp-font); min-height: 132px; display: flex; flex-direction: column; text-decoration: none; transition: border-color .15s, box-shadow .18s, transform .12s; }
.ps-tile:hover { border-color: rgba(35,38,43,.2); box-shadow: 0 8px 26px rgba(35,38,43,.09); transform: translateY(-2px); }
.ps-tile__row { position: relative; display: flex; align-items: center; width: 100%; }
.ps-tile__ico { width: 42px; height: 42px; border-radius: 11px; display: flex; align-items: center; justify-content: center; }
.ps-tile__flag { margin-left: auto; font-size: 10.5px; font-weight: 800; padding: 3px 8px; border-radius: 6px; }
.ps-tile__flag--main { color: var(--rp-primary-deep); background: var(--rp-accent); }
.ps-tile__flag--soon { color: var(--rp-faint); background: var(--rp-line-2); }
.ps-tile__title { position: relative; font-size: 15px; font-weight: 800; margin-top: 12px; }
.ps-tile__hint { position: relative; font-size: 12px; margin-top: 5px; line-height: 1.4; }
.ps-tile__cta { position: relative; margin-top: auto; padding-top: 10px; display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 700; }
/* тона плитки */
.ps-tile--go { background: var(--rp-sidebar); border-color: transparent; }
.ps-tile--go::after { content: ""; position: absolute; top: 0; right: 0; width: 130px; height: 100%; background: radial-gradient(120% 120% at 100% 0%, rgba(245,179,1,.2) 0%, transparent 62%); }
/* 🔴 w369 (п.22): ЗДЕСЬ знак НАМЕРЕННО остаётся #F5B301, вопреки букве «цвет знака везде #C98F00».
   Довод отчёта — «#F5B301 светлее и хуже читается» — верен на светлом фоне; эта плитка ТЁМНАЯ
   (--rp-sidebar #1F2228), и на ней всё наоборот. Замер контраста: #F5B301 — 8.6:1, #C98F00 — 5.63:1.
   То есть требуемая замена ухудшила бы читаемость в полтора раза ровно там, где отчёт хотел её
   улучшить. Остальные четыре плитки светлые и переведены на #C98F00 (правило ghost выше). */
.ps-tile--go .ps-tile__ico { background: rgba(245,179,1,.16); color: var(--rp-accent); }
.ps-tile--go .ps-tile__title { color: #fff; }
.ps-tile--go .ps-tile__hint { color: var(--rp-sidebar-sub); }
.ps-tile--go .ps-tile__cta { color: var(--rp-accent); }
.ps-tile--warn { border-color: rgba(229,164,0,.4); }
.ps-tile--warn .ps-tile__ico { background: var(--rp-amber-soft); color: var(--rp-amber); }
.ps-tile--warn .ps-tile__title { color: var(--rp-ink); } .ps-tile--warn .ps-tile__hint { color: var(--rp-sub); } .ps-tile--warn .ps-tile__cta { color: var(--rp-amber); }
.ps-tile--stop { border-color: rgba(226,72,61,.4); }
.ps-tile--stop .ps-tile__ico { background: var(--rp-red-soft); color: var(--rp-red); }
.ps-tile--stop .ps-tile__title { color: var(--rp-ink); } .ps-tile--stop .ps-tile__hint { color: var(--rp-sub); } .ps-tile--stop .ps-tile__cta { color: var(--rp-red); }
.ps-tile--soon { border-style: dashed; }
.ps-tile--soon .ps-tile__ico { background: var(--rp-line-2); color: var(--rp-faint); }
.ps-tile--soon .ps-tile__title { color: var(--rp-faint); } .ps-tile--soon .ps-tile__hint { color: var(--rp-faint); }
/* w369 (п.22): знак плитки быстрого действия — #C98F00, как в эталонном блоке цен (было серым
   #5E646C). Это ЧЕТЫРЕ плитки из пяти на главной; пятая — «go» и тёмная, про неё правило ниже.
   Фон подложки не трогаю: отчёт просил цвет ЗНАКА, а перекраска фона — уже другое решение. */
.ps-tile--ghost .ps-tile__ico { background: var(--rp-line-2); color: var(--rp-accent-deep); }
.ps-tile--ghost .ps-tile__title { color: var(--rp-ink); } .ps-tile--ghost .ps-tile__hint { color: var(--rp-sub); }

/* — портлет «Цены на топливо» (price-portlet) — */
/* 🔴 w287 (п.31 отчёта 30.07, «не исправлено с прошлого раза»). Разделителя строк здесь больше нет.
   Он и был тем самым «подчёркиванием»: `text-decoration` у названия позиции никогда не стояло
   (проверено вычисленным стилем — `none`), а вот линия строки шла во всю её ширину прямо под текстом
   «сорт · склад», который занимает почти всю строку. На демо-именах («ДТ Евро, летнее») это ещё
   читалось как разделитель, а на боевых именах ELMA — «Топливо дизельное, летнее, сорта С, эк.класса
   К5 (елх) · Елховский Нефтеперерабатывающий Завод», то есть ровно на примере из отчёта, — текст
   доходит до цены и линия становится его подчёркиванием. Кликабельна при этом только кнопка-стрелка.
   Строки НЕ разделяет ничего — ни линия, ни «зебра».

   🔴 w309 (п.16 нового отчёта, 31.07). w287 заменил линию на «зебру», рассудив, что раз прайс-лист
   просит полосы (п.20), то и витрина цен на главной должна говорить на том же языке. Тестировщик
   поправил ровно это: «Именно там [в прайс-листе, внутри карточек] нужны и колонки, и
   разделительные полосы — на Главной странице ни того, ни другого быть не должно». Полосы в
   карточках прайса (`.ps-table--zebra`) остаются — их правило другое и лежит отдельно. */
.ps-pricerow { display: flex; align-items: center; gap: 12px; padding: 12px 18px; }
/* ── w373: раздел «Прайс-лист» — тот же компонент строки, ДОБАВЛЕНИЕМ модификатора ──────────────
   Базовый вид (плитка Главной) не тронут ни на пиксель: он под замерами F·w372, и правило задачи
   было прямым — компонент менять только добавлением. Здесь строка просторнее: у раздела вся ширина
   рабочей зоны, а не половина ряда, и полтора десятка строк подряд при плиточных отступах читаются
   как сплошная простыня. Разделитель между строками — вместо рамок карточек, которые сняты. */
.ps-pricelist { border: 1px solid var(--rp-line); border-radius: 14px; background: var(--rp-card); overflow: hidden; }
.ps-pricerow--list { padding: 15px 20px; gap: 16px; }
.ps-pricerow--list + .ps-pricerow--list { border-top: 1px solid var(--rp-line-2); }
.ps-pricerow--list .ps-pricerow__fuel { font-size: 14.5px; }
.ps-pricerow--list .ps-pricerow__basis { font-size: 12.5px; }
.ps-pricerow--list:hover { background: var(--rp-line-2); }
.ps-pricerow__main { flex: 1; min-width: 0; }
.ps-pricerow__fuel { display: block; font-size: 13.5px; font-weight: 700; color: var(--rp-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-pricerow__basis { display: block; font-size: 12px; color: var(--rp-sub); margin-top: 2px; }
/* B5: сорт · склад в одну строку — склад тем же кеглем, thin/серый; точка-разделитель */
.ps-pricerow__main--inline { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.ps-pricerow__main--inline .ps-pricerow__fuel { display: inline; }
.ps-pricerow__main--inline .ps-pricerow__basis { display: inline; margin-top: 0; font-size: 13.5px; font-weight: 400; }
.ps-pricerow__dot { color: var(--rp-faint); font-weight: 400; }
/* ── Строка цены: ДВЕ ЗОНЫ (F·w372; моб. отчёт 02.08 п.4.1, согласовано Владельцем 04.08) ────────
   Требование заказчика: значки ⓘ стоят строго друг под другом независимо от длины наименования и
   склада. Отдельной колонкой под значок это НЕ делается — иначе мобильная раскладка и десктопная
   разошлись бы в две разные сетки. Вместо этого правая зона фиксированной ширины: цена + значок +
   действие. Значки выравниваются сами, потому что зона всегда одной ширины и прижата к правому краю.
   Ширина 186px — цена до «1 250 000 ₽» (tabular-nums) + значок 28px + кнопка 52px + зазоры. */
.ps-pricerow__side { flex: 0 0 186px; display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
.ps-pricerow__price { text-align: right; flex-shrink: 0; }
/* Цена занимает всю свободную ширину зоны и прижата вправо — значок и кнопка встают на фиксированные
   позиции от правого края, то есть в одну вертикаль во всех строках. */
.ps-pricerow__side .ps-pricerow__price { flex: 1 1 auto; }
.ps-pricerow__info { flex: 0 0 auto; color: var(--rp-faint); }
.ps-pricerow__price b { font-size: 15px; font-weight: 800; color: var(--rp-ink); font-variant-numeric: tabular-nums; }
.ps-pricerow__price span { display: block; font-size: 11px; color: var(--rp-faint); }
/* B5: бейджик оформления — до высоты текста строки (компактный, иконки ужаты) */
.ps-pricerow__go { flex-shrink: 0; display: inline-flex; align-items: center; gap: 3px; height: 24px; padding: 0 7px; border-radius: 7px; border: 1px solid var(--rp-line); background: var(--rp-card); color: var(--rp-accent-deep); font-family: var(--rp-font); font-size: 12.5px; font-weight: 700; cursor: pointer; text-decoration: none; }
.ps-pricerow__go svg { width: 13px; height: 13px; }
/* ── Мобильная раскладка строки цены (F·w372, моб. отчёт п.4 — согласована Владельцем) ───────────
   На 360/390/414 в одну линию не помещались уже название и цена, а со значком ⓘ (п.9) места стало
   ещё меньше. Строка перестраивается вертикально:
     • наименование — ЦЕЛИКОМ, до двух строк, без многоточия (обрезка прячет как раз то, чем сорта
       отличаются друг от друга: «летнее / межсезонное / зимнее» стоит в хвосте);
     • склад — своей строкой, мельче и приглушённо; разделитель-точка не нужен и скрыт;
     • цена, значок и «Оформить» — нижней линией: цена крупно слева, действие справа.
   Правая зона теряет фиксированную ширину: она больше не колонка, а строка. Порог 620px — тот же,
   на котором на карточную раскладку переходят таблицы набора (`.ps-table--cards`). */
@media (max-width: 620px) {
    .ps-pricerow { flex-direction: column; align-items: stretch; gap: 6px; }
    .ps-pricerow__main--inline { display: block; }
    .ps-pricerow__fuel { white-space: normal; overflow: visible; text-overflow: clip;
        display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; line-height: 1.3; }
    .ps-pricerow__dot { display: none; }
    .ps-pricerow__main--inline .ps-pricerow__basis { display: block; margin-top: 2px; font-size: 12px; color: var(--rp-sub); }
    .ps-pricerow__side { flex: 1 1 auto; width: 100%; justify-content: flex-start; gap: 10px; }
    .ps-pricerow__side .ps-pricerow__price { flex: 0 0 auto; text-align: left; }
    .ps-pricerow__price b { font-size: 17px; }
    .ps-pricerow__go { margin-left: auto; }
}
/* w369 (п.22): прежний ховер «только рамка темнеет» заменён общей инверсией — правило стоит рядом
   с .ps-docrow__dl, чтобы две кнопки одного стиля не разъезжались по разным местам файла. */
.ps-pricerow__go { transition: background .13s, border-color .13s, color .13s; }

/* — стат-портлет «Отгружено топлива» (shipped-stats) — */
.ps-shipped__chips { display: flex; gap: 5px; flex-wrap: wrap; margin-bottom: 16px; }
.ps-shipped__chip { border: 1px solid var(--rp-line); background: var(--rp-card); color: var(--rp-sub); border-radius: 8px; padding: 5px 11px; cursor: pointer; font-family: var(--rp-font); font-size: 12px; font-weight: 700; }
.ps-shipped__chip.is-on { border-color: var(--rp-accent-deep); background: var(--rp-accent-soft); color: var(--rp-ink); }
.ps-shipped__val { display: flex; align-items: flex-end; gap: 16px; }
.ps-shipped__big { font-size: 34px; font-weight: 800; color: var(--rp-ink); font-variant-numeric: tabular-nums; line-height: 1; }
.ps-shipped__big span { font-size: 18px; color: var(--rp-sub); }
.ps-shipped__cap { font-size: 12.5px; color: var(--rp-faint); margin-top: 6px; }
.ps-shipped__delta { margin-left: auto; display: inline-flex; align-items: center; gap: 5px; border-radius: 999px; padding: 5px 10px; font-size: 12.5px; font-weight: 800; }
.ps-shipped__delta.is-up { background: var(--rp-green-soft); color: var(--rp-green); }
.ps-shipped__delta.is-down { background: var(--rp-red-soft); color: var(--rp-red); }
.ps-shipped__none { padding: 10px 0; }
.ps-shipped__none .n { font-size: 30px; font-weight: 800; color: var(--rp-faint); }
.ps-shipped__none .s { font-size: 12.5px; color: var(--rp-faint); margin-top: 4px; }

/* — строка портлета (общий примитив: «Мои договоры», «Мои счета») — */
/* w287 (класс п.31): строка портлета устроена ТОЧНО так же, как строка цены — текст слева, кнопка
   справа, линия под текстом; линию сняли в обоих местах разом. w309 (п.16): «зебру», которой w287
   линию заменил, тоже сняли — полосы нужны в карточках прайса, а не на главной. */
.ps-docrow { display: flex; align-items: center; gap: 12px; padding: 12px 18px; }
.ps-docrow__ico { color: var(--rp-faint); flex-shrink: 0; }
.ps-docrow__main { flex: 1; min-width: 0; overflow: hidden; }
/* w236 (#1): в узкой плитке (1280×1024) бейдж сжимался/наезжал, а мета переносилась и вылезала
   из схлопнутой текстовой колонки под бейдж. Держим бейдж и кнопку фиксированными, а тип/мету —
   в одну строку с усечением «…»; текст ужимается, ничего не наезжает. */
.ps-docrow > .ps-badge { flex-shrink: 0; }
.ps-docrow__type { display: block; font-size: 13.5px; font-weight: 700; color: var(--rp-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-docrow__meta { display: block; font-size: 12px; color: var(--rp-sub); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* w369 (отчёт 02.08 ч.2, п.22): кнопка скачивания приведена к кнопке строки цены (.ps-pricerow__go) —
   она названа эталоном. Было 34×34 со СЕРЫМ знаком; стало 45×26 (24 + 2 рамки), скругление 7px,
   знак #C98F00. Объявления списаны с эталона один в один, а не с замеров отчёта: у эталона рамка
   1px, отчёт прочитал 1.25px (округление devtools) — совпадение с эталоном важнее цифры из отчёта,
   иначе две «одинаковые» кнопки снова разъедутся на четверть пикселя. */
/* 🔴 border-box, а не content-box: у эталона ширины нет вовсе (он растёт по содержимому и
   выходит 45×26 вместе с рамками), и заданные «45» в content-box дали бы 47 — ровно это и
   поймал браузерный набор. Считаем ПО РАМКЕ — тот же довод, что в w81 про высоту полей. */
.ps-docrow__dl { flex-shrink: 0; box-sizing: border-box; width: 45px; height: 26px; border-radius: 7px; border: 1px solid var(--rp-line); background: var(--rp-card); color: var(--rp-accent-deep); cursor: pointer; display: flex; align-items: center; justify-content: center; text-decoration: none; transition: background .13s, border-color .13s, color .13s; }
.ps-docrow__dl svg { width: 13px; height: 13px; }
/* Ховер-инверсия (п.22) — общая для обеих кнопок: тёмная заливка + жёлтый знак. Меняются ТОЛЬКО
   цвета: ни размеры, ни рамка по толщине не трогаются, иначе строка дёргалась бы под курсором. */
.ps-docrow__dl:hover, .ps-pricerow__go:hover { background: var(--rp-primary-deep); border-color: var(--rp-primary-deep); color: var(--rp-accent); }
/* Клавиатурный фокус остаётся заметным и ПОСЛЕ инверсии: у обеих кнопок своё кольцо, а не
   браузерное — тёмная заливка съела бы дефолтный контур. */
.ps-docrow__dl:focus-visible, .ps-pricerow__go:focus-visible { outline: none; border-color: var(--rp-accent); box-shadow: 0 0 0 3px rgba(245,179,1,.35); }
/* 🔴 w401 (отчёт 04.08, п.6): НЕДОСТУПНАЯ кнопка скачивания. Раньше она отличалась от рабочей
   только прозрачностью знака (инлайновый `opacity:.45` прямо в портлетах — мимо набора), и разница
   читалась как дефект отрисовки, а не как состояние: причину знал только тот, кто навёл мышь,
   а на тач-устройстве — никто. Теперь состояние узнаётся БЕЗ наведения и одним приёмом на портал:
   пунктирная рамка + приглушённая заливка + серый знак + курсор «нельзя». Само правило «нет
   печатной формы → скачивать нечего» не меняется: правится только его читаемость. */
.ps-docrow__dl.is-off {
    border-style: dashed; border-color: var(--rp-line);
    background: var(--rp-line-2); color: var(--rp-faint);
    cursor: not-allowed;
}
.ps-docrow__dl.is-off:hover { background: var(--rp-line-2); border-color: var(--rp-line); color: var(--rp-faint); }
/* 🔴 w408 (решение Владельца 06.08): тот же приём — для ЛЮБОЙ кнопки набора. Раньше «недоступно»
   выглядело по-разному в разных местах: у складов кнопка удаления просто ПРОПАДАЛА, у договоров
   гасла без объяснения — человек видел, что у одного склада действие есть, а у другого нет, и
   считал это дефектом. Теперь одно правило: кнопка на месте, приглушена, причина — рядом. */
.ps-btn.is-off {
    border-style: dashed; border-color: var(--rp-line);
    background: var(--rp-line-2); color: var(--rp-faint);
    cursor: not-allowed; box-shadow: none; transform: none;
}
.ps-btn.is-off:hover { background: var(--rp-line-2); border-color: var(--rp-line); color: var(--rp-faint); }
/* Бейдж причины: в разметке ЕСТЬ ВСЕГДА, показывается там, где подсказку прочитать нечем —
   на тач-устройстве (нет наведения) и на узком экране. На узком экране с мышью пусть тоже виден:
   лучше показать причину, чем спрятать её за наведение. */
.ps-reason {
    display: none;
    align-items: center; gap: 5px;
    padding: 2px 8px; border-radius: 999px;
    background: var(--rp-line-2); color: var(--rp-sub);
    border: 1px solid var(--rp-line);
    font-family: var(--rp-font); font-size: 11.5px; font-weight: 700; line-height: 1.45;
    /* Длинная причина на 360px переносится, а не растягивает строку списка. */
    max-width: 100%; overflow-wrap: anywhere; white-space: normal;
}
@media (hover: none), (pointer: coarse), (max-width: 640px) {
    .ps-reason { display: inline-flex; }
}
/* w336 (п.6 обхода): в трёхколонном ряду главной (.cab-tri) на ширинах 1181–1439 колонка портлета
   ужимается до ~290px, и однострочная раскладка w236 оставляет тексту ~75px: сумма счёта видна как
   «1 004 …», номер договора — как «ДТ-2026/…». Суть строки (сумма / номер) нечитаема — поэтому в
   этом окне бейдж уезжает НА ВТОРУЮ СТРОКУ под текст (grid), и тексту достаётся вся ширина.
   Ниже 1181 ряд складывается в одну колонку (медиазапрос .cab-tri), выше 1439 — места хватает,
   там прежняя однострочная раскладка. Правило w236 «ничего не наезжает» сохранено: колонки grid
   не пересекаются по построению. */
@media (min-width: 1181px) and (max-width: 1439px) {
    .cab-tri .ps-docrow { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; column-gap: 12px; row-gap: 5px; }
    .cab-tri .ps-docrow__ico { grid-column: 1; grid-row: 1 / span 2; align-self: center; }
    .cab-tri .ps-docrow__main { grid-column: 2; grid-row: 1; }
    .cab-tri .ps-docrow > .ps-badge { grid-column: 2; grid-row: 2; justify-self: start; }
    .cab-tri .ps-docrow__dl { grid-column: 3; grid-row: 1 / span 2; align-self: center; }
}

/* — онбординг-чек-лист (onboarding-checklist) — */
.ps-onb { background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: 18px; padding: 22px; }
.ps-onb__title { font-size: 18px; font-weight: 800; color: var(--rp-ink); margin-bottom: 4px; }
.ps-onb__sub { font-size: 13.5px; color: var(--rp-sub); margin-bottom: 20px; }
.ps-onb__step { display: flex; gap: 14px; }
.ps-onb__rail { display: flex; flex-direction: column; align-items: center; }
.ps-onb__node { position: relative; width: 38px; height: 38px; border-radius: 19px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; z-index: 1; font-size: 14px; font-weight: 800; border: 2px solid var(--rp-line); background: var(--rp-line-2); color: var(--rp-faint); }
.ps-onb__step.is-done .ps-onb__node { background: var(--rp-green); border-color: var(--rp-green); color: #fff; }
.ps-onb__step.is-active .ps-onb__node { background: var(--rp-accent); border-color: var(--rp-accent); color: #fff; }
.ps-onb__step.is-waiting .ps-onb__node { background: var(--rp-amber-soft); border-color: var(--rp-amber); color: var(--rp-amber); }
.ps-onb__step.is-waiting .ps-onb__node::after { content: ""; position: absolute; inset: -3px; border-radius: 22px; border: 2px solid rgba(229,164,0,.4); animation: ps-pulse 1.1s ease infinite alternate; }
.ps-onb__conn { width: 2px; flex: 1; min-height: 22px; background: var(--rp-line); margin: 2px 0; }
.ps-onb__step.is-done .ps-onb__conn { background: var(--rp-green); }
.ps-onb__body { flex: 1; padding-bottom: 18px; }
.ps-onb__step:last-child .ps-onb__body { padding-bottom: 0; }
.ps-onb__head { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.ps-onb__name { font-size: 14.5px; font-weight: 800; color: var(--rp-ink); }
.ps-onb__step.is-blocked .ps-onb__name { color: var(--rp-faint); }
.ps-onb__label { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 6px; }
.ps-onb__step.is-done .ps-onb__label { color: var(--rp-green); background: rgba(31,157,85,.12); }
.ps-onb__step.is-active .ps-onb__label { color: var(--rp-accent-deep); background: var(--rp-accent-soft); }
.ps-onb__step.is-waiting .ps-onb__label { color: var(--rp-amber); background: var(--rp-amber-soft); }
.ps-onb__step.is-blocked .ps-onb__label { color: var(--rp-faint); background: var(--rp-line-2); }
.ps-onb__text { font-size: 12.5px; color: var(--rp-sub); margin-top: 4px; line-height: 1.45; }
.ps-onb__lock { margin-top: 9px; display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--rp-faint); }
.ps-onb__cta { margin-top: 11px; }

/* ============================================================================
   19. Каркас клиентского кабинета (w6b) — тёмная шапка + сайдбар + контент.
   Server-render Blade вне Orchid (ADR-0010); токены --rp-*. Блоки экрана — набор.
   ========================================================================= */
/* ═══ КАРКАС КАБИНЕТА (w298, решение автора 30.07 по п.4 отчёта тестировщика) ═══════════════════
   🔴 Что изменилось и почему. Было `min-height: 100vh`: каркас РОС вместе со страницей, `.cab-body`
   растягивался по самой высокой колонке, и высоту боковой панели задавало СОДЕРЖИМОЕ. Замер до
   правки (окно 1600×720, учётка cabinet-working@): панель 654px на списке заявок, 695 на бензовозах,
   839 на карточке заявки, 885 в мастере, 977 на форме залога, 992 в прайсе, **1694 на главной**. А по
   высоте панели кадрируется фотография её фона (`cover` на слое `inset: 0`) — отсюда и «дёргается фон
   при переключении вкладок»: 292×695 против 292×654 на соседних вкладках автопарка.

   Теперь высота каркаса равна ОКНУ, а прокручивается рабочая зона. Панель перестала зависеть от
   страницы — значит и кадр фона перестал пересчитываться. Сам слой фона не тронут (условие автора:
   «фон останется таким же зумленным») — тот же `inset: 0` и тот же `cover`, см. `.cab-nav::before`.
   Следствие, которое автор назвал отдельно: панель стало возможно сворачивать на узкой ширине —
   она больше не часть потока страницы (см. медиазапрос 860px ниже).

   Единицы: сначала `100vh` как фолбэк, затем `100dvh`. `100vh` на мобильных считается от окна БЕЗ
   адресной строки — при фиксированной высоте это даёт обрезанный низ; `dvh` едет вместе со строкой.
   Порядок объявлений значим: браузер без `dvh` возьмёт первое. */
.cab-root {
    height: 100vh; height: 100dvh; overflow: hidden;
    display: flex; flex-direction: column; background: var(--rp-bg); font-family: var(--rp-font); color: var(--rp-ink);
}
/* Документ в кабинете не прокручивается — иначе к полосе рабочей зоны добавится вторая, оконная.
   Признак ставит layout кабинета (`<body class="cab-shell">`); страницы вне кабинета (вход, ошибки,
   админка Orchid) прокручиваются документом как раньше. */
body.cab-shell { overflow: hidden; }
/* 🔴 Резерв места под полосу прокрутки (w287, п.4) переезжает вместе с самой полосой. У `html`
   правило остаётся — им живут страницы вне кабинета; но в кабинете документ не прокручивается, и
   там резерв обернулся бы мёртвой полосой у правого края. Резерв — у рабочей зоны (`.cab-main`). */
html:has(body.cab-shell) { scrollbar-gutter: auto; }

/* — баннер входа-за-пользователя (impersonation, w14) — заметная янтарная полоса поверх шапки —
   flex-shrink: 0 — каркас теперь фиксированной высоты, и без этого полосу сжало бы, а её текст съехал.
   Никаких «66px» в геометрии каркаса нет: он flex-колонка, поэтому появление полосы просто отдаёт
   рабочей зоне меньше места, а панель сама встаёт под сдвинутую шапку. */
.cab-imp { flex-shrink: 0; display: flex; align-items: center; gap: 14px; flex-wrap: wrap; padding: 9px 26px; background: var(--rp-accent); color: var(--rp-primary-deep); font-size: 13px; font-weight: 700; }
.cab-imp__txt { display: inline-flex; align-items: center; gap: 8px; }
.cab-imp__txt b { font-weight: 800; }
.cab-imp__form { margin-left: auto; }
.cab-imp__btn { display: inline-flex; align-items: center; gap: 6px; border: 1.5px solid var(--rp-primary-deep); background: transparent; color: var(--rp-primary-deep); border-radius: 8px; padding: 5px 12px; cursor: pointer; font-family: var(--rp-font); font-size: 12.5px; font-weight: 800; }
.cab-imp__btn:hover { background: rgba(0,0,0,.08); }
@media (max-width: 620px) { .cab-imp { padding: 9px 14px; } .cab-imp__form { margin-left: 0; } }

/* — шапка — */
.cab-header { position: relative; display: flex; align-items: center; gap: 16px; padding: 0 26px; height: 66px; background: var(--rp-sidebar); flex-shrink: 0; }
.cab-header__logo { display: inline-flex; text-decoration: none; }
/* Кнопка вызова меню (w298). На широком экране её нет: панель и так на виду. Появляется там, где
   панель становится выдвижной (≤860px) — до w298 меню на телефоне просто пропадало (`display: none`)
   и добраться до него было НЕЧЕМ. */
.cab-navtoggle { display: none; align-items: center; justify-content: center; width: 40px; height: 40px; flex-shrink: 0; border: 1px solid var(--rp-sidebar-line); border-radius: 10px; background: transparent; color: #fff; cursor: pointer; }
.cab-navtoggle:hover { background: rgba(255,255,255,.08); }
.cab-navtoggle:focus-visible { outline: 2px solid var(--rp-accent); outline-offset: 2px; }
.cab-header__sep { width: 1px; height: 24px; background: var(--rp-sidebar-line); }
.cab-header__right { margin-left: auto; display: flex; align-items: center; gap: 10px; }
/* — переключатель продуктов (ps-prodsw, w59): в тёмной шапке, на месте бейджа организации.
     Раскрытие — native <details>; закрытие по клику вне / Esc — data-ps-dismiss-outside (behaviors). — */
.ps-prodsw { position: relative; }
.ps-prodsw__btn { display: flex; align-items: center; gap: 10px; cursor: pointer; list-style: none; border: 1px solid var(--rp-sidebar-line); border-radius: 10px; padding: 6px 10px 6px 8px; max-width: 280px; }
.ps-prodsw__btn::-webkit-details-marker { display: none; }
.ps-prodsw__btn:hover { background: rgba(255,255,255,.06); }
.ps-prodsw__btn:focus-visible { outline: 2px solid var(--rp-accent); outline-offset: 2px; }
.ps-prodsw__ava { width: 30px; height: 30px; border-radius: 8px; background: var(--rp-accent); color: var(--rp-primary-deep); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.ps-prodsw__text { min-width: 0; }
.ps-prodsw__name { display: block; font-size: 12.5px; font-weight: 800; letter-spacing: .02em; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-prodsw__sub { display: block; font-size: 10.5px; color: var(--rp-sidebar-sub); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-prodsw__chev { color: var(--rp-sidebar-sub); flex-shrink: 0; transition: transform .18s; }
.ps-prodsw[open] .ps-prodsw__chev { transform: rotate(180deg); }

.ps-prodsw__pop { position: absolute; top: calc(100% + 8px); left: 0; z-index: 61; box-sizing: border-box; width: 320px; max-width: calc(100vw - 24px); padding: 8px; background: #fff; border: 1px solid var(--rp-line); border-radius: 14px; box-shadow: 0 18px 48px rgba(0,0,0,.22); }
.ps-prodsw__pop-head { padding: 6px 8px 8px; font-size: 11px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--rp-faint); }

/* карточка продукта: слот под ФОНОВУЮ КАРТИНКУ — --ps-prodsw-bg (картинки придут от автора) */
/* w62: box-sizing — иначе активная карточка (<div>, content-box) была шире соседней (<button>,
   border-box) и вылезала из выпадашки. Место под галочку зарезервировано у ВСЕХ карточек
   (padding-right), сама галочка — вне потока: на ширину не влияет. */
.ps-prodsw__card { box-sizing: border-box; position: relative; overflow: hidden; display: flex; align-items: center; gap: 11px; width: 100%; padding: 12px 34px 12px 12px; border: 1px solid var(--rp-line); border-radius: 12px; background: var(--rp-line-2); text-align: left; text-decoration: none; font-family: var(--rp-font); cursor: pointer; transition: border-color .15s, box-shadow .15s, background .15s; }
.ps-prodsw__card + .ps-prodsw__card { margin-top: 8px; }
.ps-prodsw__card:hover { border-color: var(--rp-accent-deep); box-shadow: 0 6px 18px rgba(35,38,43,.08); }
.ps-prodsw__card.is-active { border-color: var(--rp-accent); background: var(--rp-accent-soft); cursor: default; }
.ps-prodsw__card.is-soon { cursor: pointer; }
.ps-prodsw__card.is-soon .ps-prodsw__card-title, .ps-prodsw__card.is-soon .ps-prodsw__card-sub { color: var(--rp-sub); }
/* фон-картинка карточки: подкладывается слоем под контент, читаемость держит градиент-вуаль */
.ps-prodsw__card.has-image::before { content: ""; position: absolute; inset: 0; background-image: var(--ps-prodsw-bg); background-size: cover; background-position: center; opacity: .9; }
.ps-prodsw__card.has-image::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(255,255,255,.94) 42%, rgba(255,255,255,.72) 100%); }
.ps-prodsw__card.has-image > * { position: relative; z-index: 1; }
.ps-prodsw__card-ico { width: 34px; height: 34px; border-radius: 9px; background: var(--rp-card); color: var(--rp-accent-deep); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.ps-prodsw__card-main { flex: 1; min-width: 0; }
.ps-prodsw__card-title { display: flex; align-items: center; gap: 7px; font-size: 13.5px; font-weight: 800; color: var(--rp-ink); }
.ps-prodsw__card-sub { display: block; font-size: 12px; color: var(--rp-sub); margin-top: 2px; }
.ps-prodsw__soon { font-size: 10px; font-weight: 800; letter-spacing: .03em; text-transform: uppercase; color: var(--rp-primary-deep); background: var(--rp-accent); border-radius: 5px; padding: 1px 6px; }
.ps-prodsw__card-mark { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); color: var(--rp-accent-deep); }

/* ── w357, вид КАРТОЧКИ (требование заказчика 01.08) ────────────────────────────────────────
   Продукты видны сразу, рядом, РАВНОЙ ширины: `flex: 1 1 0` + `min-width: 0` — доли равны при любой
   длине подписи (без min-width длинное название распирало бы свою плитку, и «равной ширины» осталось
   бы намерением). Ряд живёт в тёмной шапке, поэтому у плиток свой цвет — светлые карточки выпадашки
   на графите не читаются.
   Выбор виден с одного взгляда: у активной — золотая рамка, подсветка фона и золотой аватар;
   у соседней ничего этого нет. Различие не одним оттенком: рамка + фон + аватар сразу, чтобы выбор
   читался и без цветового зрения.
   Плитки НЕ интерактивны (кроме реальной ссылки на другой продукт): ни курсора-руки, ни фокуса —
   поэтому здесь нет ни :hover, ни :focus-visible для не-ссылок. */
/* ── w365 (правка автора 02.08): карточки шире на 15% ────────────────────────────────────────
   Ширину задаём РЯДУ, а не каждой карточке: доли внутри — `flex: 1 1 0`, поэтому равенство ширин
   держится само, и «сделать обе шире» — это одно число, а не два костыля.
   Откуда 458px: замер ПЕРЕД правкой дал 195,48px на карточку (ряд 398,97px, одинаково на 870, 900 и
   1280 — то есть это его естественная ширина по содержимому, а не ужатое состояние). ×1,15 =
   224,80px, две карточки плюс зазор 8px = 457,6px, округлено до 458px (карточка выходит 225px).
   ⚠ В постановке ориентиром стояло 218px — от замера w357 (189,81px). Тот замер снят при другой
   занятости шапки и текущему виду не соответствует: считать +15% от него значило бы дать прибавку
   в 11,8% от того, что автор видит на экране. Считаем от фактической ширины — просьба была «обе
   шире на 15%». Оба числа держит набор, разойдётся вёрстка — он скажет.
   🔴 `flex: 0 1 458px`, а НЕ `width`: базис — «сколько хотим», `shrink: 1` — «уступим, если тесно».
   Сразу за порогом 860px шапке места мало (там же логотип, колокольчик и меню пользователя), и
   жёсткая ширина выдавила бы соседей за край. Замер показал, что прибавка влезает и на 870px, но
   право ужаться оставляем: подписи продуктов ещё будут меняться. */
.ps-prodsw-cards { display: flex; align-items: stretch; gap: 8px; min-width: 0; flex: 0 1 458px; max-width: 520px; }
.ps-prodsw-tile { box-sizing: border-box; flex: 1 1 0; min-width: 0; display: flex; align-items: center; gap: 9px; padding: 6px 10px 6px 8px; border: 1px solid var(--rp-sidebar-line); border-radius: 10px; background: transparent; text-decoration: none; font-family: var(--rp-font); }
.ps-prodsw-tile.is-active { border-color: var(--rp-accent); background: rgba(245,179,1,.12); }
.ps-prodsw-tile__ava { width: 30px; height: 30px; border-radius: 8px; background: rgba(255,255,255,.08); color: var(--rp-sidebar-sub); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.ps-prodsw-tile.is-active .ps-prodsw-tile__ava { background: var(--rp-accent); color: var(--rp-primary-deep); }
.ps-prodsw-tile__text { min-width: 0; }
.ps-prodsw-tile__name { display: flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 800; letter-spacing: .02em; color: var(--rp-sidebar-sub); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-prodsw-tile.is-active .ps-prodsw-tile__name { color: #fff; }
.ps-prodsw-tile__sub { display: block; font-size: 10.5px; color: var(--rp-sidebar-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-prodsw-tile.is-active .ps-prodsw-tile__sub { color: var(--rp-sidebar-sub); }
/* ссылка на ДРУГОЙ продукт (не активный и не «скоро») — единственная кликабельная плитка */
a.ps-prodsw-tile { cursor: pointer; }
a.ps-prodsw-tile:hover { border-color: var(--rp-accent); background: rgba(255,255,255,.06); }
a.ps-prodsw-tile:focus-visible { outline: 2px solid var(--rp-accent); outline-offset: 2px; }
/* Порог — существующий порог шапки (860px): там панель становится выдвижной и шапка сжимается.
   Нового брейкпоинта не заводим. В режиме `auto` показан ровно один вид, второй снят из потока. */
@media (max-width: 860px) { .ps-prodsw-cards.ps-prodsw-v--auto { display: none; } }
@media (min-width: 861px) { details.ps-prodsw.ps-prodsw-v--auto { display: none; } }

@media (max-width: 620px) {
    .ps-prodsw { position: static; }                /* якорь выпадашки — шапка, а не сама кнопка */
    .ps-prodsw__btn { padding: 5px 8px 5px 6px; gap: 8px; }
    .ps-prodsw__sub { display: none; }              /* на узком экране — только название продукта */
    .ps-prodsw__pop { top: calc(100% - 8px); left: 12px; right: 12px; width: auto; max-width: none; }
}

.cab-org { display: flex; align-items: center; gap: 10px; border: 1px solid var(--rp-sidebar-line); border-radius: 10px; padding: 6px 12px 6px 8px; max-width: 280px; }
.cab-org__ava { width: 30px; height: 30px; border-radius: 8px; background: var(--rp-accent); color: var(--rp-primary-deep); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.cab-org__text { min-width: 0; }
.cab-org__name { display: block; font-size: 12.5px; font-weight: 700; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cab-org__inn { display: block; font-size: 10.5px; color: var(--rp-sidebar-sub); }
/* бейдж организации в сайд-панели (w59): на всю ширину панели, длинное имя — многоточием + title */
.cab-org--side { box-sizing: border-box; max-width: 100%; width: 100%; margin-bottom: 14px; padding: 9px 10px 9px 8px; background: rgba(255,255,255,.04); }
.cab-org--side .cab-org__text { flex: 1 1 auto; min-width: 0; }
.cab-org--side .cab-org__name { font-size: 13px; }
.cab-counter { position: relative; width: 40px; height: 40px; border-radius: 10px; border: 1px solid var(--rp-sidebar-line); background: transparent; color: var(--rp-sidebar-ink); cursor: pointer; display: flex; align-items: center; justify-content: center; }
.cab-counter:hover { background: rgba(255,255,255,.06); }
.cab-counter__badge { position: absolute; top: -5px; right: -5px; min-width: 19px; height: 19px; padding: 0 5px; border-radius: 10px; background: var(--rp-red); color: #fff; font-size: 10.5px; font-weight: 800; display: flex; align-items: center; justify-content: center; border: 2px solid var(--rp-sidebar); }

/* — меню пользователя (native details) — */
.cab-usermenu { position: relative; }
.cab-usermenu__btn { display: flex; align-items: center; gap: 9px; cursor: pointer; list-style: none; padding: 2px; }
.cab-usermenu__btn::-webkit-details-marker { display: none; }
.cab-usermenu__who { text-align: left; }
.cab-usermenu__name { display: block; font-size: 12.5px; font-weight: 700; color: #fff; }
.cab-usermenu__role { display: block; font-size: 10.5px; color: var(--rp-sidebar-sub); }
.cab-usermenu__chev { color: var(--rp-sidebar-sub); transition: transform .18s; }
.cab-usermenu[open] .cab-usermenu__chev { transform: rotate(180deg); }
.cab-usermenu__pop { position: absolute; top: calc(100% + 8px); right: 0; width: 210px; z-index: 61; background: #fff; border: 1px solid var(--rp-line); border-radius: 12px; box-shadow: 0 18px 48px rgba(0,0,0,.22); overflow: hidden; }
/* text-decoration: none — w287 (класс п.31). Пункты меню пользователя — обычные <a>, и браузер
   подчёркивал их по умолчанию: «Профиль» и «Моя организация» выглядели подчёркнутыми ссылками,
   тогда как ни один другой пункт навигации портала не подчёркнут. Правило класса, а не по месту. */
.cab-usermenu__item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 11px 14px; border: none; background: transparent; cursor: pointer; font-family: var(--rp-font); font-size: 13.5px; font-weight: 600; color: var(--rp-ink); text-align: left; text-decoration: none; }
.cab-usermenu__item:hover { background: var(--rp-line-2); }
.cab-usermenu__item.is-danger { color: var(--rp-red); }

/* — тело: сайдбар + контент — */
.cab-body { flex: 1; display: flex; min-height: 0; }
/* 🔴 Модель прокрутки — w298 (решение автора 30.07). Была ОБЩАЯ (w63): страница прокручивалась целиком
   и боковая панель уезжала вместе с ней; именно поэтому её высоту задавало содержимое, а фон дёргался.
   Стало: панель и шапка самостоятельны, прокручивается только рабочая зона. Это отменяет откат w62,
   но НЕ возвращает его целиком: тогда фиксировали ещё и геометрию фонового слоя (w63/w64) — вот её
   как раз не трогаем, слой ниже остался прежним. */
/* Фон сайдбара — изображение авторизации, снизу уходит в прозрачность (проступает базовый цвет) — w9 #7.
   Картинка в ::before под контентом; маска-градиент даёт затухание. Контент — z-index выше.

   w65. Слой — РОВНО как исходно (до w62): `inset: 0` на всю панель, изображение растянуто по высоте
   (`cover`). Попытки отвязать фон от высоты панели (w63 — фиксированная высота в вьюпорт; w64 —
   вписывание по ширине) меняли его вид и отвергнуты автором: фон трогать нельзя.
   w298: слой так и не тронут — ни `inset`, ни `cover`, ни градиент скрима. Изменилось ДРУГОЕ: высота
   самой панели больше не зависит от страницы, поэтому `cover` нечего пересчитывать. Зум сохранён
   ровно потому, что механизм прежний: `cover` на узкой высокой панели.

   🔴 Прокручивается НЕ панель, а её внутренний слой `.cab-nav__scroll`. Если повесить `overflow-y`
   на саму панель, фотография поедет вместе с меню: абсолютный `::before` внутри скролл-контейнера
   попадает в его прокручиваемое содержимое и `inset: 0` перестаёт означать «на всю панель». */
.cab-nav { position: relative; z-index: 0; width: 292px; flex-shrink: 0; background-color: var(--rp-sidebar); display: flex; flex-direction: column; overflow: hidden; }
/* Прокручиваемое содержимое панели. Паддинг переехал сюда с `.cab-nav` — поэтому её ширина указана
   как 292px: те же 264 + 2×14, что и раньше, кадр фона по ширине не изменился. Меню длиннее панели
   (11 пунктов + раскрытая группа «Документы» ≈ 810px против 654px панели в окне 720px) — без
   собственной прокрутки нижние пункты были бы недостижимы. */
.cab-nav__scroll { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 18px 14px; display: flex; flex-direction: column; gap: 3px; }
.cab-nav::before {
    content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
    /* Скрим-градиент поверх фото: сверху (за меню) — сплошной цвет сайдбара для читаемости,
       снизу истончается → проступает изображение. Без mask (устойчиво во всех браузерах). */
    background:
        linear-gradient(to top, rgba(31,34,40,0.08) 0%, rgba(31,34,40,0.52) 38%, var(--rp-sidebar) 66%),
        url('../img/auth-brand.jpg') bottom center / cover no-repeat;
}
.cab-nav > *, .cab-nav__scroll > * { position: relative; }   /* контент поверх фоновой картинки */
/* 🔴 w287 (п.25 отчёта 30.07): читаемость пунктов меню «по всей панели», а не только внизу.
   Скрим фона (выше) задан ПРОЦЕНТАМИ от высоты панели, а панель тянется на высоту страницы: на
   разделах страница короткая, сплошная зона кончается на ~230px, а меню идёт до ~630px — нижние
   пункты («Организация», «Автопарк», «Склады», «Залоги», «Чат») оказываются на солнечном поле
   фотографии и сливаются с ней. Тестировщик предложил «шрифт темнее», но фон под пунктами и светлый,
   и тёмный сразу — любой один цвет шрифта где-то проиграет. Поэтому подложку получает САМ СПИСОК: он
   обнимает ровно пункты (сколько бы их ни осталось после фильтра доступа) и снизу уходит в
   прозрачность, так что фотография ниже видна как раньше. Геометрию фонового слоя не трогаем — она
   зафиксирована решением автора (см. w65 выше). */
/* 🔴 w374 (мобильный отчёт 02.08, п.5): подложка таяла ПРОЦЕНТАМИ от высоты списка — сплошная до
   74%, дальше в прозрачность. На десктопе список длинный и 26% хвоста приходились на пустоту под
   пунктами; в узком выдвижном меню список короче, и в прозрачную зону попадал последний пункт —
   «Чат». Замер: подложка над ним a=0.36, контраст текста на светлом участке фотографии 1.1:1.
   Это ровно та же ошибка, что чинил w287 п.25 (проценты от высоты, которая не фиксирована) — она
   просто переехала на новую высоту панели.
   Лечим тем же приёмом, но без процентов: сплошная зона идёт до начала нижнего отступа, а таяние
   занимает ровно его (26px). Сколько бы пунктов ни осталось после фильтра доступа и какой бы
   высоты ни была панель, ВСЕ пункты лежат на сплошном фоне, а фотография под списком проступает
   как прежде. */
.cab-nav__list {
    display: flex; flex-direction: column; gap: 3px; margin: 0 -14px; padding: 0 14px 26px;
    background: linear-gradient(to bottom, var(--rp-sidebar) 0%, var(--rp-sidebar) calc(100% - 26px), rgba(31,34,40,0) 100%);
}
/* 🔴 w309 (п.17 нового отчёта, 31.07): вес пунктов меню 600 → 700. Тестировщик назвал боковую
   панель ЕДИНСТВЕННЫМ местом, где утолщение уместно: пункты лежат на фотографии, и подложки
   (w287 п.25) с более тёмным цветом там мало — «на пару пунктов жирнее» дочитывает читаемость.
   Активный пункт был 700 и стал 800, чтобы разница «активный / остальные» не схлопнулась. */
.cab-nav__item { box-sizing: border-box; display: flex; align-items: center; gap: 12px; padding: 11px 13px; border-radius: 10px; border: none; cursor: pointer; font-family: var(--rp-font); font-size: 14px; font-weight: 700; background: transparent; color: var(--rp-sidebar-sub); text-align: left; text-decoration: none; width: 100%; white-space: nowrap; }
.cab-nav__item:hover { background: rgba(255,255,255,.06); color: var(--rp-sidebar-ink); }
.cab-nav__item.is-active { background: var(--rp-sidebar-active-bg); color: var(--rp-sidebar-active-ink); font-weight: 800; }
.cab-nav__item.is-active svg { color: var(--rp-accent); }
.cab-nav__item svg { flex-shrink: 0; }
.cab-nav__label { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }   /* название в одну строку (w9 #2) */
.cab-nav__soon { margin-left: auto; font-size: 10px; font-weight: 700; color: var(--rp-sidebar-faint); background: rgba(255,255,255,.06); padding: 2px 7px; border-radius: 6px; }
/* F2·w388: раздел недоступен, пока регистрация не подтверждена. Приглушён, но ЧИТАЕМ — человек
   должен видеть, что его ждёт за анкетой; замок справа объясняет, почему пункт не нажимается. */
.cab-nav__item.is-locked { opacity: 0.55; cursor: not-allowed; }
.cab-nav__item.is-locked:hover { background: transparent; }
.cab-nav__lock { margin-left: auto; color: var(--rp-sidebar-faint); flex-shrink: 0; }
/* w308: виджет помощи в подвале панели. Своя подложка — по той же причине, что и у списка пунктов
   (w287 п.25): фотография фона панели уходит в светлое поле, и текст без подложки на ней не читается.
   ── w360 (замечание тестировщика 02.08) ───────────────────────────────────────────────────
   Подложка была БЕЛОЙ и почти прозрачной (6%): на светлом участке фотографии она ничего не
   перекрывала, и тёмный текст поверх светлого фото не читался вовсе. Заменена на плотную ТЁМНУЮ
   (значения тестировщика приняты как есть) — фото под ней лишь угадывается, а весь текст блока стал
   светлым. Светлую плашку сознательно НЕ делаем: она выбилась бы из тёмной панели.
   `backdrop-filter` — размытие того, что под подложкой: даже на пёстром участке фото за текстом
   остаётся ровное поле, а не рябь.
   🔴 Контрасты меряны при ХУДШЕМ фоне (белый участок фотографии под 80% подложкой) в наборе
   sidebar-help-w360: заголовок 8.92:1, часы, строки телефона/почты и подпись 5.40:1 — все выше
   порога 4.5:1. Числа держит набор, а не эта запись: подберут другое фото — проверка скажет. */
/* margin-top:auto прижимает блок к нижнему краю панели (хотфикс 03.08 по просьбе автора); при меню
   длиннее панели auto сворачивается в 0 — минимальный зазор тогда держит gap самого .cab-nav__scroll. */
.cab-help { margin: auto 0 0; padding: 12px 13px; border-radius: 10px; background: rgba(15,18,22,.8); backdrop-filter: blur(8px); display: flex; flex-direction: column; gap: 6px; }
.cab-help__title { font-size: 13px; font-weight: 800; color: rgba(255,255,255,.92); }
.cab-help__hours { font-size: 11.5px; color: rgba(255,255,255,.65); }
/* 🔴 Строки телефона и почты в постановке названы не были, но живут на той же подложке. Замер
   показал 4.29:1 у прежнего `--rp-sidebar-sub` — ниже порога, то есть починив заголовок, мы
   оставили бы нечитаемыми сами контакты, ради которых блок и существует. Тот же светлый токен.
   Сбросы `<button>` (background/border/padding/cursor/text-align/font-family) из правила убраны:
   кнопки в блоке больше нет, а для `<a>` они ничего не значили. */
.cab-help__row { display: flex; align-items: center; gap: 8px; font-size: 12.5px; font-weight: 600; color: rgba(255,255,255,.65); text-decoration: none; }
.cab-help__row:hover { color: #fff; }
.cab-help__row svg { flex-shrink: 0; }
.cab-help__note { font-size: 11.5px; color: rgba(255,255,255,.65); line-height: 1.35; }
/* w37: сворачиваемая группа nav («Документы» → Договоры/Счета/Платежи/Отгрузки). */
.cab-nav__group { display: flex; flex-direction: column; gap: 3px; }
.cab-nav__caret { margin-left: auto; transition: transform .18s ease; color: var(--rp-sidebar-faint); }
.cab-nav__group.is-open .cab-nav__caret { transform: rotate(180deg); }
.cab-nav__sub { display: none; flex-direction: column; gap: 2px; padding-top: 2px; }
.cab-nav__group.is-open .cab-nav__sub { display: flex; }
.cab-nav__subitem { display: block; margin-left: 30px; padding: 8px 12px; border-radius: 8px; font-size: 13px; font-weight: 600; color: var(--rp-sidebar-sub); text-decoration: none; white-space: nowrap; }
.cab-nav__subitem:hover { background: rgba(255,255,255,.06); color: var(--rp-sidebar-ink); }
.cab-nav__subitem.is-active { background: var(--rp-sidebar-active-bg); color: var(--rp-sidebar-active-ink); font-weight: 700; }
.cab-nav__help { margin-top: auto; background: var(--rp-sidebar-line); border-radius: 12px; padding: 14px; }
.cab-nav__help-head { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; font-size: 12.5px; font-weight: 700; color: #fff; }
.cab-nav__help-head svg { color: var(--rp-accent); }
.cab-nav__help-text { font-size: 11.5px; color: var(--rp-sidebar-sub); margin: 0 0 10px; line-height: 1.4; }
.cab-nav__help-btn { width: 100%; height: 34px; border-radius: 8px; border: none; background: var(--rp-accent); color: var(--rp-primary-deep); font-family: var(--rp-font); font-size: 12.5px; font-weight: 800; cursor: pointer; }

/* Рабочая зона — единственное, что прокручивается (w298). `min-width: 0` обязателен: без него
   flex-элемент не сжимается ниже min-content своего содержимого, и широкая таблица выдавливала бы
   зону за пределы каркаса — то есть под панель. `scrollbar-gutter` здесь, а не у `html`: полоса
   переехала сюда, и без резерва её появление снова дёргало бы раскладку (заслон w287). */
.cab-main { flex: 1; min-width: 0; overflow-y: auto; scrollbar-gutter: stable; padding: 26px 30px 80px; }
.cab-wrap { max-width: 1360px; margin: 0 auto; width: 100%; }
.cab-mb { margin-bottom: 28px; }
.cab-mt { margin-top: 20px; }
/* шапка списка: заголовок секции слева + действие («Оформить заявку») справа (w9) */
.cab-listhead { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.cab-listhead .ps-sechead { margin: 0; flex: 1; }
.cab-listhead > .ps-btn { flex-shrink: 0; }
/* 🔴 w283 (отчёт 29.07, п.6): шапка статуса ВНУТРИ .ps-card. У самой .ps-card padding'а нет (она
   обёртка для блоков со своими отступами), а .cab-listhead — голый flex, поэтому «Статус заявки»
   прилипал к левому краю. В w135 это лечили инлайновым padding'ом ПО МЕСТУ и класс сознательно не
   трогали — карточка залога такой правки не получила, и дефект вернулся ровно там. Теперь отступ
   живёт в классе: новая карточка статуса получит его по построению, а не по памяти автора правки.
   22px по горизонтали — как у .ps-prog внутри карточки, иначе шапка и степпер разъезжаются. */
.cab-cardhead { padding: 20px 22px 0; margin-bottom: 16px; }
/* 🔴 w287 (п.13 отчёта 30.07): «граница контейнера статуса совпадает с границей родительского».
   Так и было: у `.ps-card` своего padding'а нет (она обёртка для блоков со своими отступами), а
   плашку-состояние кладут в неё напрямую — её рамка ложилась ровно на рамку карточки (замер до
   правки: 323px против 322px, то есть в один пиксель рамки). Отступ по бокам — 22px, как у
   `.cab-cardhead` и `.ps-prog`, иначе шапка, степпер и плашка разъедутся по вертикали.
   Класс, а не инлайн: карточки заказа МУ и залога устроены так же и получают его по построению. */
.cab-cardstate { padding: 0 22px 20px; }
/* Статусов без плашки хватает (напр. «Новый» у залога) — пустая обёртка не должна оставлять
   двадцать пикселей воздуха под степпером. */
.cab-cardstate:not(:has(*)) { padding: 0; }
.cab-grid { display: grid; grid-template-columns: 1fr 380px; gap: 22px; align-items: start; }
/* w254 (Г3): `minmax(0, 1fr)` вместо `1fr`. `1fr` = `minmax(auto, 1fr)`, то есть колонка не сжимается
   ниже min-content своего содержимого — а внутри карточки значения идут `nowrap`, и min-content равен
   полной ширине самой длинной строки. Из-за этого три колонки суммарно вылезали за контейнер, и
   карточки наезжали друг на друга. `minmax(0, …)` + `min-width:0` на карточке дают усечению сработать. */
.cab-orders { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
/* w18: ряд 1 главной — асимметрия «Цены (широкая 1fr) | Деньги (узкая)» */
.cab-split { display: grid; grid-template-columns: 1fr 300px; gap: 22px; align-items: start; }
/* 🔴 w283 (п.5): вторая колонка — финансовая панель, а она рисуется НЕ всем (доступ к финансам,
   R-05). Без неё в ряду оставался один блок, но колонка под панель никуда не девалась: верхний ряд
   обрывался на 322px раньше «Последних заказов» — ровно тот дефект, о котором говорит отчёт, только
   на аккаунте без финансов. Один ребёнок → одна колонка во всю ширину, и ряд доходит до края всегда.
   (Замер на аккаунте С финансами расхождения не показал ни на одной ширине — см. отчёт w283.) */
.cab-split:has(> :only-child) { grid-template-columns: 1fr; }
/* ── w359 (п.2, повторное — потерялось 30.07): денежная панель в высоту строки ───────────────
   Ряд выровнен по началу (`align-items: start`), поэтому панель занимала свои 268px при строке в
   311px и обрывалась на 42px раньше «Цен на топливо». Тянем ТОЛЬКО её: `start` у ряда оставляем —
   он защищает единственный оставшийся блок от растяжки на аккаунте без финансов (см. `:has` выше).
   🔴 Пустоту распределяем ВНУТРИ, а не оставляем нижним пустым брюхом с рамкой: панель и её тело
   становятся колонками, а стат-плитки делят прибавку между собой (`grid-auto-rows: 1fr`). Отметка
   времени остаётся под ними, прижатая к низу. Замер до/после — в наборе home-tiles-w359. */
.cab-split > .ps-money { align-self: stretch; display: flex; flex-direction: column; }
.cab-split > .ps-money .ps-money__body { flex: 1; display: flex; flex-direction: column; }
.cab-split > .ps-money .ps-money__tiles { flex: 1; grid-auto-rows: 1fr; }
.cab-split > .ps-money .ps-fin { margin-top: auto; padding-top: 12px; }
/* ряд из трёх панелей равной высоты: Мои счета | Отгружено | Мои договоры (w309; align-items:stretch — карты тянутся) */
.cab-tri { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; align-items: stretch; }
.cab-tri > .ps-money, .cab-tri > .ps-portlet { height: 100%; }
/* w154: ряд из двух равных панелей — «Последние платежи» | «Последние отгрузки» (как в легаси-главной) */
.cab-duo { display: grid; grid-template-columns: repeat(2, 1fr); gap: 22px; align-items: stretch; }
.cab-duo > .ps-portlet { height: 100%; min-width: 0; }   /* min-width:0 — иначе таблица распирает колонку грида */
/* w283 (п.11): сумма в плитках главной ломалась на две строки — «1 234 567,00» переносилось по
   пробелам разряда, и число читалось как два. Разрывать деньги нельзя: колонка узкая, но перенос
   здесь врёт сильнее, чем горизонтальная прокрутка плитки (она уже есть, overflow-x на обёртке). */
.cab-duo .ps-table th.ps-table__num, .cab-duo .ps-table td.ps-table__num { white-space: nowrap; }
/* ── w359 (п.3, отчёт 02.08): «в последней строке ИНН в скобках не переносится» ──────────────
   🔴 Причина оказалась НЕ в последней строке — правил `:last-child` про перенос здесь нет и не было,
   и на стендовых данных все пять строк ведут себя одинаково. Дело в СОДЕРЖИМОМ: `overflow-wrap`
   по умолчанию `normal`, то есть браузер переносит только ПО ПРОБЕЛАМ. Пока в названии есть пробелы,
   оно аккуратно ложится в несколько строк; как только длинный кусок неразрывен — «(1635006952)»,
   длинное слово, склейка без пробелов — перенести его негде, и он выпирает из узкой колонки
   плитки. Строка, которой такой кусок достался, и выглядит «не переносящейся».
   Поэтому чиним причину, а не последнюю строку: в плитках главной разрешаем разрыв внутри слова.
   Колонки суммы это не касается — у неё свой `nowrap` выше (w283), деньги рвать нельзя. */
.cab-duo .ps-table td:not(.ps-table__num) { overflow-wrap: anywhere; }
/* компактная панель «Деньги» (w16; w18 — действует в любом ряду, вынесена в ряд 1) */
.ps-money__tiles { grid-template-columns: 1fr; margin-bottom: 0; gap: 8px; }   /* плитки в столбик, компактно */
.ps-money__body { padding: 14px; }                                            /* компактнее без шапки */
/* 🔴 w309 (п.16 нового отчёта, 31.07): у стат-плиток финансовой панели снята ЗАЛИВКА. В общем виде
   `.ps-stat` — серая плашка (`--rp-line-2`), и это правильно там, где плитки стоят рядом в строку.
   Но в панели «Деньги» они идут в СТОЛБИК на ширине 300px, и три серые плашки одна под другой
   читаются как три горизонтальные полосы — тестировщик назвал их поимённо («Доступная предоплата» /
   «Остаток лимита кредитования» / «Кредитный лимит») и потребовал убрать: полосы нужны в карточках
   прайса, а не на главной.
   ⚠ Замер, чтобы не соврать в отчёте: сама заливка НЕ «появилась» от правок 30–31.07 — она стоит с
   w16, ни один коммит того раунда `.ps-stat` не трогал (A/B рендер главной на CSS до и после дал
   ноль расхождений). Появилась соседняя «зебра» строк цены; её сняли выше. Заливку снимаем не как
   регрессию, а по названному требованию: панель перестаёт читаться полосами, плитки различает
   отступ. */
.ps-money .ps-stat { padding: 9px 2px; background: transparent; }
/* контраст меток стат-плиток «Денег» (темнее/жирнее — w16; подписи убраны в w17) */
.ps-money .ps-stat__label { color: var(--rp-sub); font-weight: 700; margin-bottom: 3px; }

/* — плавающий чат-док — */
.cab-chatdock { position: fixed; right: 24px; bottom: 24px; z-index: 30; display: flex; align-items: center; gap: 10px; height: 52px; padding: 0 20px 0 16px; border-radius: 26px; border: none; background: var(--rp-primary); color: #fff; font-family: var(--rp-font); font-size: 14.5px; font-weight: 700; cursor: pointer; box-shadow: 0 12px 34px rgba(0,0,0,.28); }
.cab-chatdock__ico { position: relative; display: flex; }
.cab-chatdock__badge { position: absolute; top: -4px; right: -4px; min-width: 16px; height: 16px; border-radius: 8px; background: var(--rp-red); color: #fff; font-size: 10px; font-weight: 800; display: flex; align-items: center; justify-content: center; border: 2px solid var(--rp-primary); }
/* честная подпись «скоро» на кнопке чата (мессенджер не построен, w54) */
.cab-chatdock__soon { font-size: 10.5px; font-weight: 800; letter-spacing: .02em; text-transform: uppercase; color: var(--rp-primary-deep); background: var(--rp-accent); border-radius: 6px; padding: 2px 6px; }

@media (max-width: 1180px) { .cab-grid { grid-template-columns: 1fr; } .cab-orders { grid-template-columns: repeat(2, minmax(0, 1fr)); } .cab-tri { grid-template-columns: 1fr; } .cab-split { grid-template-columns: 1fr; } .cab-duo { grid-template-columns: 1fr; } }
/* 🔴 B·w375 (моб. отчёт 02.08, п.3): колонка `1fr` сама по себе НЕ спасает от распирания — грид-
   ребёнок не сжимается ниже своей min-content-ширины, а её задают nowrap-строки прайса (~1038px).
   Обёртка портлета (overflow: visible) наследовала эту ширину, и весь документ уезжал вбок на
   360/390/414, срезая справа и соседние блоки (.ps-ocard). `min-width: 0` разрешает детям ряда
   сжаться до вьюпорта; переполнение строк остаётся ВНУТРИ портлета (у него overflow: hidden) до
   их собственной починки (F·w372). Только узкие ширины — десктопная геометрия (w359) не тронута. */
@media (max-width: 1180px) { .cab-split > * { min-width: 0; } }
/* ── Узкая ширина: панель СВОРАЧИВАЕТСЯ (w298) ────────────────────────────────────────────────
   До w298 здесь стояло `.cab-nav { display: none }` — меню на телефоне не пряталось, а ИСЧЕЗАЛО, и
   вызвать его было нечем: ни бургера, ни ящика. Второе следствие, названное автором («мы сможем
   сделать её сворачиваемой»), стало возможно ровно потому, что панель больше не элемент потока
   страницы: она фиксирована от низа шапки до низа окна, и её высота (а с ней кадр фона) постоянна.
   Убрана с экрана сдвигом, а не `display: none`: так работает переход, а содержимое панели остаётся
   в разметке для скринридера и для замеров. */
@media (max-width: 860px) {
    .cab-nav {
        position: fixed; top: var(--cab-top, 66px); bottom: 0; left: 0; z-index: 45;
        transform: translateX(-100%); transition: transform .22s ease;
    }
    .cab-nav.is-open { transform: translateX(0); box-shadow: 0 18px 60px rgba(0,0,0,.5); }
    .cab-navscrim { position: fixed; inset: var(--cab-top, 66px) 0 0 0; z-index: 44; background: rgba(0,0,0,.5); opacity: 0; pointer-events: none; transition: opacity .22s ease; }
    .cab-navscrim.is-open { opacity: 1; pointer-events: auto; }
    .cab-navtoggle { display: inline-flex; }
    .ps-prodsw__btn { max-width: 190px; }
    .cab-usermenu__who { display: none; }
    .cab-main { padding: 20px 16px 80px; }
    /* B·w375 (моб. отчёт 02.08, п.8): название топлива в карточке заказа переносится на ДВЕ строки,
       а не режется многоточием на первой — эк. класс («…сорта С, экологического класса К5») и есть
       та часть, что отличает позиции. Свыше двух строк — прежнее многоточие (clamp). */
    .ps-ocard__fuel span {
        white-space: normal;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
    }
}
/* Ящик — только узкая ширина. На широкой панель в потоке, затемнение не нужно даже как узел. */
.cab-navscrim { display: none; }
@media (max-width: 860px) { .cab-navscrim { display: block; } }
/* ── w374 (мобильный отчёт 02.08, п.6): плавающая кнопка чата при открытом меню ───────────────
   Замер показал, что нажатие она НЕ перехватывает: её z-index 30 против 44 у затемнения, в точке
   кнопки лежит скрим. Но видно её всё равно — затемнение полупрозрачное (50%), и яркая кнопка
   сквозь него читается как активная. Плюс на экране одновременно два входа в один и тот же чат: она и
   пункт «Чат» в самом меню.
   🚩 Выбрал СКРЫТЬ, а не «увести ниже» (второе уже сделано и вопроса не сняло). Скрываем мягко —
   прозрачностью с переходом, чтобы кнопка не мигала при каждом открытии, и снимаем с неё нажатия.
   `:has` на body: скрим и кнопка лежат в разных ветках разметки, соседним селектором не связать. */
body:has(.cab-navscrim.is-open) .cab-chatdock { opacity: 0; pointer-events: none; transition: opacity .18s ease; }
/* Кому анимация мешает (системная настройка) — сдвиг мгновенный. */
@media (prefers-reduced-motion: reduce) {
    .cab-nav, .cab-navscrim { transition: none; }
}
@media (max-width: 620px) { .cab-orders { grid-template-columns: minmax(0, 1fr); } .cab-header { padding: 0 14px; gap: 10px; } }
/* мобильная шапка (w54): раньше правый блок (счётчики + меню пользователя) не сжимался и уезжал
   за край — горизонтальный скролл на ВСЕХ экранах кабинета. Теперь блок организации сжимается
   (имя уже с многоточием), правый блок фиксирован, разделитель скрыт. Проверено 320/360/390. */
@media (max-width: 620px) {
    /* 🔴 w374 (мобильный отчёт 02.08, пп.1 и 2): `overflow: hidden` отсюда СНЯТ. Он стоял против
       горизонтального скролла (w54), но обрезал по границе шапки оба выпадающих меню — профиля и
       переключателя продуктов: списки рисовались и были в разметке, а человек их не видел вовсе.
       Причина переполнения, ради которой его ставили, вылечена там же и правилами ниже: блок
       продуктов сжимается (`flex: 1 1 auto; min-width: 0`), правый блок не сжимается, разделитель
       скрыт. Держать сверх этого обрезку — значит платить за старую болезнь работающим меню.
       Отсутствие горизонтальной прокрутки на 360/390/414 закреплено набором mobile-header-drawer-w374. */
    .cab-header { padding: 0 12px; gap: 8px; }
    .cab-header__logo { flex-shrink: 0; }
    .ps-prodsw { flex: 1 1 auto; min-width: 0; }
    .ps-prodsw__btn { max-width: none; }
    .cab-header__right { gap: 6px; flex-shrink: 0; }
    .cab-header__sep { display: none; }
    .cab-chatdock { right: 14px; bottom: 14px; }
}
@media (max-width: 400px) {
    .cab-counter { width: 36px; height: 36px; }
}

/* ═══ ЧАТ (w69) — компоненты набора: entity-card · topic-list · chat-feed · chat-composer ═══ */

.ps-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* — карточка-ссылка на сущность (заявка/залог) внутри сообщения и в черновике ввода — */
.ps-entity { display: flex; align-items: center; gap: 9px; padding: 8px 10px; border: 1px solid var(--rp-line); border-radius: 10px; background: var(--rp-card); text-decoration: none; max-width: 100%; }
.ps-entity--link:hover { border-color: var(--rp-accent); background: var(--rp-accent-soft); }
.ps-entity__ico { flex-shrink: 0; width: 26px; height: 26px; border-radius: 7px; background: var(--rp-line-2); color: var(--rp-accent-deep); display: flex; align-items: center; justify-content: center; }
.ps-entity__main { flex: 1 1 auto; min-width: 0; }
.ps-entity__title { display: block; font-size: 12.5px; font-weight: 700; color: var(--rp-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-entity__sub { display: block; font-size: 11px; color: var(--rp-sub); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-entity__go { flex-shrink: 0; color: var(--rp-faint); }
.ps-entity__x { flex-shrink: 0; border: none; background: transparent; color: var(--rp-faint); cursor: pointer; padding: 2px; display: flex; }
.ps-entity__x:hover { color: var(--rp-red); }

/* — список тем со счётчиками — */
.ps-topics { display: flex; flex-direction: column; gap: 2px; }
.ps-topics__item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 10px; border: none; border-radius: 9px; background: transparent; cursor: pointer; text-align: left; font-family: var(--rp-font); }
.ps-topics__item:hover { background: var(--rp-line-2); }
.ps-topics__item.is-active { background: var(--rp-accent-soft); }
.ps-topics__ico { flex-shrink: 0; color: var(--rp-accent-deep); display: flex; }
.ps-topics__main { flex: 1 1 auto; min-width: 0; }
.ps-topics__name { display: block; font-size: 13px; font-weight: 700; color: var(--rp-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-topics__sub { display: block; font-size: 11px; color: var(--rp-faint); }
/* бейдж — тот же примитив, что в шапке; внутри строки он в потоке, а не приколот к углу */
.ps-topics__badge { position: static; border: none; flex-shrink: 0; }
.ps-topics__empty { text-align: center; padding: 22px 12px; color: var(--rp-sub); }
.ps-topics__empty .t { font-size: 13px; font-weight: 700; color: var(--rp-ink); margin-top: 6px; }
.ps-topics__empty .s { font-size: 12px; margin-top: 3px; }

/* — лента сообщений — */
.ps-feed { display: flex; flex-direction: column; min-height: 0; flex: 1; }
.ps-feed__scroll { flex: 1; overflow-y: auto; padding: 14px; min-height: 0; }
.ps-feed__list { display: flex; flex-direction: column; gap: 8px; }
.ps-feed__empty { text-align: center; padding: 34px 16px; color: var(--rp-sub); }
.ps-feed__empty .t { font-size: 12.5px; margin-top: 8px; line-height: 1.45; }
.ps-feed__day { align-self: center; font-size: 11px; font-weight: 700; color: var(--rp-sub); background: var(--rp-line-2); border-radius: 8px; padding: 3px 10px; margin: 6px 0; }
.ps-feed__unread { align-self: stretch; text-align: center; font-size: 11px; font-weight: 800; color: var(--rp-red); border-top: 1px solid var(--rp-red); margin: 8px 0 2px; padding-top: 5px; }

.ps-msg { display: flex; max-width: 100%; gap: 8px; align-items: flex-end; }
/* w308: аватар менеджера (инициалы в кружке) — слева от чужого пузыря, по нижнему краю, как в
   мессенджерах. `[hidden]` у своих/системных сообщений: `display:flex` на элементе перебил бы
   встроенное `display:none`, поэтому гасим явно. */
.ps-msg__ava { display: inline-flex; align-self: flex-end; }
.ps-msg__ava[hidden] { display: none; }
.ps-msg--mine { justify-content: flex-end; }
.ps-msg--their { justify-content: flex-start; }
.ps-msg--system { justify-content: center; }
.ps-msg__bubble { max-width: 78%; border-radius: 12px; padding: 8px 11px; background: var(--rp-line-2); color: var(--rp-ink); display: flex; flex-direction: column; gap: 5px; }
.ps-msg--mine .ps-msg__bubble { background: var(--rp-accent-soft); }
.ps-msg--system .ps-msg__bubble { background: transparent; border: 1px dashed var(--rp-line); color: var(--rp-sub); max-width: 92%; text-align: center; }
.ps-msg__author { font-size: 11px; font-weight: 800; color: var(--rp-accent-deep); }
.ps-msg__body { font-size: 13.5px; line-height: 1.45; white-space: pre-wrap; word-break: break-word; }
.ps-msg__atts { display: flex; flex-direction: column; gap: 4px; }
.ps-msg__att { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--rp-accent-deep); text-decoration: none; background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: 8px; padding: 5px 8px; }
.ps-msg__att:hover { border-color: var(--rp-accent); }
.ps-msg__att-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-msg__meta { display: flex; align-items: center; justify-content: flex-end; gap: 5px; }
.ps-msg__time { font-size: 10.5px; color: var(--rp-faint); font-variant-numeric: tabular-nums; }
/* галочка: серая = отправлено, янтарная = прочитано менеджером (§20.5) */
.ps-msg__tick { display: flex; color: var(--rp-faint); }
.ps-msg__tick.is-read { color: var(--rp-accent-deep); }

/* — поле ввода — */
.ps-composer { border-top: 1px solid var(--rp-line); padding: 10px 12px 12px; background: var(--rp-card); flex-shrink: 0; }
.ps-composer__ctx { margin-bottom: 8px; }
.ps-composer__files { list-style: none; margin: 0 0 8px; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.ps-composer__file { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--rp-sub); background: var(--rp-line-2); border-radius: 7px; padding: 4px 8px; }
.ps-composer__file-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-composer__file-x { border: none; background: transparent; color: var(--rp-faint); cursor: pointer; display: flex; padding: 0; }
.ps-composer__file-x:hover { color: var(--rp-red); }
.ps-composer__row { display: flex; align-items: flex-end; gap: 8px; }
.ps-composer__clip { flex-shrink: 0; width: 36px; height: 36px; border-radius: 9px; border: 1px solid var(--rp-line); background: var(--rp-card); color: var(--rp-sub); display: flex; align-items: center; justify-content: center; cursor: pointer; }
.ps-composer__clip:hover { border-color: var(--rp-accent); color: var(--rp-accent-deep); }
.ps-composer__input { flex: 1 1 auto; min-width: 0; resize: none; max-height: 140px; border: 1px solid var(--rp-line); border-radius: 10px; padding: 9px 11px; font-family: var(--rp-font); font-size: 13.5px; line-height: 1.4; color: var(--rp-ink); background: var(--rp-card); }
.ps-composer__input:focus { outline: none; border-color: var(--rp-accent); box-shadow: 0 0 0 3px rgba(245,179,1,.18); }
/* Кнопка отправки — круглая янтарная со стрелкой (выбор автора, w70): иконка вместо текста,
   гаснет на пустом поле, лёгкий подъём при наведении. Скрепка рядом — квадратная, тихая. */
.ps-composer__send { flex-shrink: 0; width: 38px; height: 38px; border-radius: 50%; border: none; background: var(--rp-accent); color: var(--rp-primary-deep); display: flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: 0 1px 3px rgba(0,0,0,.14); transition: transform .12s ease, box-shadow .12s ease, background .12s ease; }
.ps-composer__send:hover:not(:disabled) { background: var(--rp-accent-deep); transform: translateY(-1px); box-shadow: 0 3px 8px rgba(0,0,0,.18); }
.ps-composer__send:active:not(:disabled) { transform: translateY(0); box-shadow: 0 1px 2px rgba(0,0,0,.16); }
.ps-composer__send:disabled { opacity: .45; box-shadow: none; cursor: default; }
.ps-composer.is-sending .ps-composer__input { opacity: .7; }
.ps-composer__hint { font-size: 10.5px; color: var(--rp-faint); margin-top: 6px; }
.ps-composer__kbd { font-weight: 700; color: var(--rp-sub); background: var(--rp-line-2); border-radius: 4px; padding: 1px 4px; }
.ps-composer__err { font-size: 11.5px; color: var(--rp-red); font-weight: 600; margin-top: 6px; }

/* ═══ панель чата кабинета (разворачивается из плавающей кнопки — решение автора w69) ═══ */
.cab-chat { position: fixed; right: 24px; bottom: 88px; z-index: 40; width: 620px; max-width: calc(100vw - 48px); height: min(620px, calc(100vh - 130px)); display: flex; flex-direction: column; background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: 16px; box-shadow: 0 24px 64px rgba(0,0,0,.26); overflow: hidden; }
.cab-chat__head { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--rp-line); flex-shrink: 0; }
.cab-chat__title { flex: 1 1 auto; min-width: 0; font-size: 14px; font-weight: 800; color: var(--rp-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cab-chat__x, .cab-chat__back { border: none; background: transparent; color: var(--rp-sub); cursor: pointer; display: flex; padding: 4px; border-radius: 7px; }
.cab-chat__x:hover, .cab-chat__back:hover { background: var(--rp-line-2); color: var(--rp-ink); }
.cab-chat__back { display: none; }                    /* «назад к темам» — только в узкой раскладке */
.cab-chat__body { flex: 1; display: flex; min-height: 0; }
.cab-chat__topics { width: 210px; flex-shrink: 0; border-right: 1px solid var(--rp-line); padding: 8px; overflow-y: auto; }
.cab-chat__dialog { flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; }
/* w336: полоса «менеджер пока не назначен» над композером — предупреждение ДО письма, не после. */
.cab-chat__notice { flex-shrink: 0; padding: 8px 12px; font-size: 12px; line-height: 1.45; color: var(--rp-amber); background: var(--rp-amber-soft); border-top: 1px solid var(--rp-line); }

/* узкая раскладка: панель на весь экран; сначала темы, тема открывается поверх, есть «назад» */
@media (max-width: 700px) {
    .cab-chat { right: 0; bottom: 0; width: 100vw; max-width: 100vw; height: 100dvh; border-radius: 0; border: none; }
    .cab-chat__topics { width: 100%; border-right: none; }
    .cab-chat__dialog { display: none; }
    .cab-chat.is-dialog .cab-chat__topics { display: none; }
    .cab-chat.is-dialog .cab-chat__dialog { display: flex; }
    .cab-chat.is-dialog .cab-chat__back { display: flex; }
}

/* бейджи непрочитанного на точках входа (w69): пункт меню и плавающая кнопка — тот же примитив */
.cab-nav__badge { position: static; margin-left: auto; border: none; }
.cab-chatdock__ico { position: relative; }
.cab-chatdock__badge { top: -7px; right: -9px; border-color: var(--rp-primary); }
/* карточка заявки с кнопкой чата (w69 → w254): кнопка ВНУТРИ карточки, в подвале рядом со статусом.
   `position:relative; z-index:1` — поверх растянутой ссылки номера, иначе клик по кнопке уходил бы
   в «открыть заявку». Обёртки `.ps-ocard-wrap` больше нет: корень карточки один и тот же с кнопкой
   и без неё (раньше обёртка требовалась, чтобы кнопка снаружи <a> не стала ячейкой grid-списка). */
.ps-ocard__chat { position: relative; z-index: 1; display: flex; }

/* w71: цена + ⓘ в одной ячейке (иконка была вынесена в отдельную колонку и «отрывалась» от цифры) */
.ps-price-cell { display: inline-flex; align-items: center; gap: 6px; justify-content: flex-end; }

/* ═══ Ш3 «Данные бензовоза и водителя» — новая раскладка (w80) ═══
   Было: длинная вертикаль (сцепка → водитель → бензовоз → прицеп → характеристики → секции),
   справа пустота. Стало: водитель на всю ширину → ТРИ РАВНОВЫСОКИЕ колонки → кнопки. */
.wiz-t3 { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr) minmax(0, .9fr); align-items: stretch; }
.wiz-t3 > * { min-width: 0; }
.wiz-t3 .ps-form-section { display: flex; flex-direction: column; }   /* колонки одной высоты */
.wiz-t3__driver { max-width: 520px; }

/* Карточки сцепки (правки автора): ТРИ В ОДНУ ЛИНИЮ, без переноса, машины сопоставимого масштаба.
   Приём: всем картинкам задан ОДИН кадр — по пропорции самой длинной сцепки (628×171). Кадр
   масштабируется вместе с карточкой, а `object-fit: contain` вписывает в него рисунок: длинная сцепка
   занимает кадр целиком, короткая цистерна — только часть ширины, но ВЫСОТА у всех одна. Так уходит
   исходный разнобой (57 / 40 / 33 px), и при этом ничего не переносится.  */
.wiz-t3__couplings { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 14px; }
.wiz-t3__couplings .ps-coupling-card { min-width: 0; }
.wiz-t3__couplings .ps-coupling-card__body { grid-template-columns: 1fr; justify-items: center; text-align: center; gap: 6px; padding: 9px 7px; }
.wiz-t3__couplings .ps-coupling-card__img {
    width: 100%; height: auto; aspect-ratio: 628 / 171; object-fit: contain; display: block;
}
/* w236 (#13): базовый .ps-coupling-card__title рвёт слова (overflow-wrap:anywhere) — «полуприцеп»
   ломался буквой «п». Здесь переносим только по пробелам, слова целиком. */
.wiz-t3__couplings .ps-coupling-card__title { font-size: 12px; line-height: 1.2; overflow-wrap: normal; word-break: keep-all; hyphens: none; }

/* Узкая раскладка: карточки в столбик — кадр тот же, машины по-прежнему одной высоты. */
@media (max-width: 760px) {
    .wiz-t3__couplings { grid-template-columns: 1fr; }
}

.wiz-t3__pick { margin-bottom: 10px; }
.wiz-t3__sub { font-size: 13px; font-weight: 700; color: var(--rp-ink); margin-bottom: 6px; }
.wiz-t3__warn { display: flex; align-items: flex-start; gap: 7px; margin: 10px 0 0; padding: 8px 10px; border-radius: 9px; background: var(--rp-amber-soft); font-size: 12px; font-weight: 600; line-height: 1.35; color: var(--rp-amber); }
.wiz-t3__warn svg { flex: 0 0 auto; margin-top: 1px; }

/* характеристики */
.wiz-t3__specs { display: flex; flex-direction: column; gap: 12px; }
.wiz-t3__spec-head { font-size: 13px; font-weight: 700; color: var(--rp-ink); margin-bottom: 5px; }
.wiz-t3__spec-list { margin: 0; display: flex; flex-direction: column; gap: 3px; }
.wiz-t3__spec-list > div { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.wiz-t3__spec-list dt { font-size: 12.5px; color: var(--rp-sub); margin: 0; }
.wiz-t3__spec-list dd { margin: 0; font-size: 12.5px; font-weight: 700; color: var(--rp-ink); font-variant-numeric: tabular-nums; }
.wiz-t3__total { margin-top: auto; padding-top: 10px; border-top: 1px solid var(--rp-line); display: flex; flex-direction: column; gap: 2px; }
.wiz-t3__total > span:first-child { font-size: 12.5px; color: var(--rp-sub); }
.wiz-t3__total b { font-size: 16px; color: var(--rp-ink); font-variant-numeric: tabular-nums; }
.wiz-t3__total-note { font-size: 11.5px; color: var(--rp-faint); line-height: 1.35; }
.wiz-t3__empty { text-align: center; padding: 26px 12px; color: var(--rp-sub); }
.wiz-t3__empty .t { font-size: 13px; font-weight: 700; color: var(--rp-ink); margin-top: 6px; }
.wiz-t3__empty .s { font-size: 12px; margin-top: 3px; line-height: 1.4; }

/* узкая раскладка: три колонки → одна (сначала транспорт, потом секции, потом характеристики) */
@media (max-width: 1180px) {
    .wiz-t3 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
    .wiz-t3 > *:last-child { grid-column: 1 / -1; }
}
@media (max-width: 860px) {
    .wiz-t3 { grid-template-columns: 1fr; }
    .wiz-t3 > *:last-child { grid-column: auto; }
    .wiz-t3__couplings { grid-template-columns: 1fr; }
    .wiz-t3__couplings .ps-coupling-card__body { grid-template-columns: auto 1fr; justify-items: start; text-align: left; }
    .ps-coupling-card__img { max-width: 84px; }
}

/* ═══ ps.entity-picker (w81): выбор сущности + «+ Новый» + карандаш правки ═══
   Кнопка «+ Новый» — СТРОГО той же высоты, что поле (поле набора = 50px, базовая .ps-btn = 44px:
   выравниваем здесь, глобальную кнопку не трогаем). box-sizing задаём явно — глобального ресета в
   файле нет (на этом уже обожглись: карточка сцепки вылезала за ячейку и накрывала поле). */
.ps-epick { display: flex; flex-direction: column; box-sizing: border-box; min-width: 0; }
.ps-epick__row { display: flex; align-items: flex-start; gap: 8px; min-width: 0; }
.ps-epick__field { position: relative; flex: 1 1 auto; min-width: 0; }
.ps-epick__field .ps-field { margin: 0; }
/* место под карандаш — только когда он ВИДЕН (без выбора он есть в DOM, но скрыт) */
.ps-epick__field:has(.ps-epick__edit:not([hidden])) .ps-input { padding-right: 26px; }
.ps-epick__edit {
    position: absolute; top: 0; right: 34px; height: 50px; width: 30px;
    display: flex; align-items: center; justify-content: center;
    border: none; background: transparent; color: var(--rp-sub); cursor: pointer; padding: 0; z-index: 2;
}
.ps-epick__edit[hidden] { display: none !important; }   /* у кнопки display:flex — иначе hidden не сработает */
.ps-epick__edit:hover { color: var(--rp-accent-deep); }
.ps-epick__edit:focus-visible { outline: 2px solid var(--rp-accent); outline-offset: -2px; border-radius: 8px; }
.ps-epick__new { box-sizing: border-box; height: 50px; flex-shrink: 0; padding: 0 14px; }
.ps-epick__empty { margin-top: 6px; font-size: 12px; color: var(--rp-warn, #b26a00); }

/* узкая колонка: подпись кнопки прячем, остаётся «+» — в строку по-прежнему влезает */
@media (max-width: 1180px) {
    .ps-epick__new-text { display: none; }
    .ps-epick__new { padding: 0 12px; }
}

/* ─────────────────────────────────────────────────────────────────────────
   Контент (F·w85, FR-BO-04): превью баннера + двухколоночный редактор страниц.
   ───────────────────────────────────────────────────────────────────────── */

/* Превью загруженной картинки баннера на форме */
.ps-banner-preview {
    margin-top: 10px;
    border: 1px dashed var(--rp-border, #d9dee6);
    border-radius: 10px;
    padding: 10px;
    background: var(--rp-surface-2, #f7f9fc);
    min-height: 64px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.ps-banner-preview img { max-width: 100%; max-height: 220px; border-radius: 8px; display: block; }
.ps-banner-preview.is-empty { color: var(--rp-sub); }

/* Миниатюра баннера в списке */
.ps-banner-thumb {
    width: 80px; height: 40px; object-fit: cover;
    border-radius: 6px; border: 1px solid var(--rp-border, #d9dee6); display: block;
}

/* Двухколоночный редактор правовой страницы: textarea | живое превью */
.ps-content-editor {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    align-items: start;
}
.ps-content-editor__col { min-width: 0; }
.ps-content-preview {
    border: 1px solid var(--rp-border, #d9dee6);
    border-radius: 10px;
    padding: 14px 16px;
    background: #fff;
    min-height: 220px;
    max-height: 520px;
    overflow: auto;
    color: var(--rp-text, #1f2733);
    line-height: 1.5;
    word-break: break-word;
}
.ps-content-preview :first-child { margin-top: 0; }
.ps-content-preview img { max-width: 100%; height: auto; }

/* узкий экран — колонки в стопку */
@media (max-width: 900px) {
    .ps-content-editor { grid-template-columns: 1fr; }
}

/* ── Панель уведомлений кабинета (R-18, B2·w183) ─────────────────────────────
   Раскрывается колокольчиком в шапке. Геометрия и тени — как у панели чата
   (.cab-chat), только якорь сверху-справа: панель висит под своей кнопкой. */
/* 🔴 w298 (ловушка из задания): `top` был зашит числом 68px — «шапка 66 плюс 2». С плашкой
   входа-за-пользователя шапка съезжает вниз (замер до правки: низ шапки 113px), и панель ложилась
   ПОВЕРХ неё. Теперь отсчёт от `--cab-top` — фактического низа шапки, его ставит `<x-ps.behaviors>`
   по замеру (величина зависит от плашки, а та переносится по строкам и в CSS не вычисляется). --cab-top
   объявлен и как запас: без JS панель встанет там же, где стояла. */
.cab-notifpanel { position: fixed; right: 24px; top: calc(var(--cab-top, 66px) + 2px); z-index: 40; width: 420px; max-width: calc(100vw - 32px); max-height: min(560px, calc(100dvh - var(--cab-top, 66px) - 34px)); display: flex; flex-direction: column; background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: 16px; box-shadow: 0 24px 64px rgba(0,0,0,.26); overflow: hidden; }
.cab-notifpanel[hidden] { display: none; }
.cab-notifpanel__head { display: flex; align-items: center; gap: 8px; padding: 12px 14px; border-bottom: 1px solid var(--rp-line); flex-shrink: 0; }
.cab-notifpanel__title { font-size: 14px; font-weight: 800; color: var(--rp-ink); }
.cab-notifpanel__list { flex: 1; overflow-y: auto; }
.cab-notifpanel__empty { padding: 28px 18px; text-align: center; color: var(--rp-sub); }
.cab-notifpanel__empty .t { margin-top: 8px; font-size: 13.5px; font-weight: 700; color: var(--rp-ink); }
.cab-notifpanel__empty .s { margin-top: 4px; font-size: 12.5px; line-height: 1.45; }

.cab-notifitem { display: flex; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--rp-line-2); text-decoration: none; color: inherit; }
.cab-notifitem:hover { background: var(--rp-line-2); }
.cab-notifitem.is-unread { background: rgba(0,0,0,.02); }
.cab-notifitem.is-unread .cab-notifitem__title { font-weight: 800; }
.cab-notifitem__dot { flex: 0 0 auto; width: 8px; height: 8px; margin-top: 6px; border-radius: 50%; background: var(--rp-sub); }
.cab-notifitem__dot--success { background: var(--rp-green, #2e9e5b); }
.cab-notifitem__dot--danger { background: var(--rp-red); }
.cab-notifitem__dot--info { background: var(--rp-primary); }
.cab-notifitem__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cab-notifitem__title { font-size: 13.5px; color: var(--rp-ink); }
.cab-notifitem__text { font-size: 12.5px; line-height: 1.45; color: var(--rp-sub); overflow-wrap: anywhere; }
.cab-notifitem__date { font-size: 11.5px; color: var(--rp-faint); }

@media (max-width: 720px) {
    /* top тот же, что и на широком экране — от фактического низа шапки (w298); зашитые 60px давали
       наложение на шапку с плашкой имперсонации так же, как 68px на широкой. */
    .cab-notifpanel { right: 8px; left: 8px; width: auto; }
}

/* ─── Страницы отказов (F·w195) ───
   Своих страниц ошибок не было вовсе — показывался стоковый шаблон фреймворка с чужой типографикой
   и английским заголовком. Здесь минимальный набор поверх уже существующих переменных набора:
   новых сущностей не заводим, кнопки — те же `.ps-btn`. */
.err-root { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px; background: var(--rp-bg); }
.err-card { max-width: 560px; width: 100%; background: var(--rp-card); border: 1px solid var(--rp-line); border-radius: var(--rp-radius, 14px); padding: 32px; text-align: center; }
.err-code { font-family: 'JetBrains Mono', monospace; font-size: 46px; font-weight: 700; line-height: 1; color: var(--rp-faint); letter-spacing: .04em; }
.err-title { margin: 14px 0 0; font-size: 22px; font-weight: 800; color: var(--rp-ink); }
.err-lead { margin: 10px 0 0; font-size: 14.5px; line-height: 1.5; color: var(--rp-sub); }
/* Объяснение из самого отказа — главное на странице, поэтому выделено, а не сноской снизу. */
.err-msg { margin: 18px 0 0; padding: 14px 16px; text-align: left; font-size: 14px; line-height: 1.55;
           color: var(--rp-ink); background: rgba(245,179,1,0.09); border: 1px solid rgba(245,179,1,0.3); border-radius: 10px; }
.err-actions { margin: 22px 0 0; display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
.err-foot { margin: 18px 0 0; font-size: 12px; color: var(--rp-faint); }
@media (max-width: 560px) {
    .err-card { padding: 22px; }
    .err-actions .ps-btn { width: 100%; justify-content: center; }
}

/* ── F2·w319, админка: список тумблеров уведомлений ────────────────────────────────────────
   Строка = «что за событие» + тумблер справа. Отдельные классы, а не таблица: у строки нет колонок,
   которые имело бы смысл сравнивать глазом по вертикали, а на узком экране пара «подпись + тумблер»
   обязана оставаться рядом, а не разъезжаться по ячейкам. */
   B·w381: раскладка понадобилась второму разделу (тумблеры продуктов), поэтому у неё появилось
   НЕЙТРАЛЬНОЕ имя `ps-toggle-row*`. Прежние `ps-notif-toggle*` оставлены синонимами — экран
   уведомлений не трогаем ради переименования, а третьему разделу с тумблерами уже незачем
   притворяться уведомлением. */
.ps-notif-toggles, .ps-toggle-rows { display: flex; flex-direction: column; }
.ps-notif-toggle, .ps-toggle-row {
    display: flex; align-items: center; gap: 16px;
    padding: 12px 0; border-bottom: 1px solid var(--rp-line-2);
}
.ps-notif-toggle:last-child, .ps-toggle-row:last-child { border-bottom: none; }
.ps-notif-toggle__main, .ps-toggle-row__main { flex: 1; min-width: 0; }
.ps-notif-toggle__title, .ps-toggle-row__title { font-size: 14px; font-weight: 600; color: var(--rp-ink); }
.ps-notif-toggle__sub, .ps-toggle-row__sub { font-size: 12.5px; color: var(--rp-sub); margin-top: 2px; }
