/* /Components/Layout/MainLayout.razor.rz.scp.css */
/* Макет держит RadzenLayout: сетка «шапка сверху, панель слева, тело справа», прокрутка у тела.
   Название в шапке тема красит сама — белым по основному цвету и без подчёркивания, — и своих
   правил ему не нужно.

   Ширина свёрнутой панели лежит НЕ здесь, а в app.css, и это не небрежность: изолированный стиль
   метит своим признаком только собственные элементы разметки, а боковую панель рисует компонент
   Radzen — до её класса правило отсюда не достаёт. Проверено на живой странице: класс на элементе
   стоял, ширина оставалась прежней. */

/* Подвал ошибки. Цвета из переменных темы: жёлтая полоса шаблона с `color-scheme: light only`
   не имела к приложению никакого отношения и в тёмной теме светилась как фонарь. Красный тут по
   делу — это отказ, а не предупреждение. */
#blazor-error-ui[b-el24tl097i] {
    display: none;
    position: fixed;
    left: 0;
    bottom: 0;
    width: 100%;
    box-sizing: border-box;
    z-index: 1000;

    align-items: center;
    gap: 1rem;
    padding: 0.75rem 1.25rem;

    /* Фон СПЛОШНОЙ. Полупрозрачный оттенок пропускал сквозь себя карту и легенду, и текст отказа
       читался поверх чужого текста — на телефоне это была каша. Подвал сообщает об отказе, его
       обязано быть видно на любом содержимом. */
    background: var(--rz-base-background-color);
    color: var(--rz-text-color);
    border-top: 3px solid var(--rz-danger);
    box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.25);
}

    /* Показывает подвал сценарий Blazor, выставляя display: block. Раскладку строкой задаём мы. */
    #blazor-error-ui[style*="display: block"][b-el24tl097i],
    #blazor-error-ui[style*="display:block"][b-el24tl097i] {
        display: flex !important;
    }

    #blazor-error-ui .error-text[b-el24tl097i] {
        flex: 1 1 auto;
        min-width: 0;
    }

    #blazor-error-ui .reload[b-el24tl097i] {
        color: var(--rz-danger-dark);
        font-weight: 500;
        white-space: nowrap;
    }

    #blazor-error-ui .dismiss[b-el24tl097i] {
        cursor: pointer;
        padding: 0 0.25rem;
        opacity: 0.7;
    }

    #blazor-error-ui .dismiss:hover[b-el24tl097i] {
        opacity: 1;
    }
/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
/* Окно потери связи.

   Все правила для содержимого идут через ::deep, и это обязательно: надписи и кнопки внутри
   рисует Radzen, а изолированный стиль метит своим признаком только собственные элементы
   разметки. Без ::deep показ по состоянию просто не сработал бы — на экране оказались бы разом
   все надписи. Правила для самого диалога, наоборот, идут без ::deep: он наш.

   Классы состояний (`components-reconnect-*`) ставит на диалог сам Blazor. */

#components-reconnect-modal[b-2klwzip20z]  .components-reconnect-first-attempt-visible,
#components-reconnect-modal[b-2klwzip20z]  .components-reconnect-repeated-attempt-visible,
#components-reconnect-modal[b-2klwzip20z]  .components-reconnect-failed-visible,
#components-reconnect-modal[b-2klwzip20z]  .components-pause-visible,
#components-reconnect-modal[b-2klwzip20z]  .components-resume-failed-visible,
#components-reconnect-modal[b-2klwzip20z]  .components-rejoining-animation {
    display: none;
}

#components-reconnect-modal.components-reconnect-show[b-2klwzip20z]  .components-reconnect-first-attempt-visible,
#components-reconnect-modal.components-reconnect-show[b-2klwzip20z]  .components-rejoining-animation,
#components-reconnect-modal.components-reconnect-paused[b-2klwzip20z]  .components-pause-visible,
#components-reconnect-modal.components-reconnect-resume-failed[b-2klwzip20z]  .components-resume-failed-visible,
#components-reconnect-modal.components-reconnect-retrying[b-2klwzip20z]  .components-reconnect-repeated-attempt-visible,
#components-reconnect-modal.components-reconnect-retrying[b-2klwzip20z]  .components-rejoining-animation,
#components-reconnect-modal.components-reconnect-failed[b-2klwzip20z]  .components-reconnect-failed-visible {
    display: block;
}

#components-reconnect-modal.components-reconnect-retrying[b-2klwzip20z],
#components-reconnect-modal.components-reconnect-failed[b-2klwzip20z] {
    display: block;
}

/* Цвета и скругления — из переменных темы: окно обязано выглядеть частью приложения и переживать
   переключение на тёмную тему. Белым фоном и синей кнопкой шаблона оно в тёмной теме било бы по
   глазам. */
#components-reconnect-modal[b-2klwzip20z] {
    background-color: var(--rz-base-background-color);
    color: var(--rz-text-color);
    width: 22rem;
    max-width: calc(100vw - 2rem);
    margin: 20vh auto;
    padding: 2rem;
    border: 0;
    border-radius: var(--rz-border-radius);
    box-shadow: var(--rz-shadow-4, 0 3px 6px 2px rgba(0, 0, 0, 0.3));
    opacity: 0;
    transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity-b-2klwzip20z 0.5s both;
}

#components-reconnect-modal[open][b-2klwzip20z] {
    animation:
        components-reconnect-modal-slideUp-b-2klwzip20z 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s,
        components-reconnect-modal-fadeInOpacity-b-2klwzip20z 0.5s ease-in-out 0.3s;
    animation-fill-mode: both;
}

#components-reconnect-modal[b-2klwzip20z]::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
    animation: components-reconnect-modal-fadeInOpacity-b-2klwzip20z 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp-b-2klwzip20z {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-2klwzip20z {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity-b-2klwzip20z {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.reconnect-body[b-2klwzip20z] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal[b-2klwzip20z]  p {
    text-align: center;
}

/* Круги ожидания — единственная своя графика. Цвет из темы, как у всего остального. */
.components-rejoining-animation[b-2klwzip20z] {
    position: relative;
    width: 80px;
    height: 80px;
}

    .components-rejoining-animation div[b-2klwzip20z] {
        position: absolute;
        border: 3px solid var(--rz-primary);
        opacity: 1;
        border-radius: 50%;
        animation: components-rejoining-animation-b-2klwzip20z 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
    }

        .components-rejoining-animation div:nth-child(2)[b-2klwzip20z] {
            animation-delay: -0.5s;
        }

@keyframes components-rejoining-animation-b-2klwzip20z {
    0% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    4.9% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    5% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 1;
    }

    100% {
        top: 0px;
        left: 0px;
        width: 80px;
        height: 80px;
        opacity: 0;
    }
}
/* /Components/Pages/MapView.razor.rz.scp.css */
/* Карта склада. Стили изолированы компонентом, ::deep — для содержимого слоёв. */

.map-shell[b-l16oxdjxoj] {
    display: flex;
    gap: 1rem;
    align-items: stretch;
    min-height: 0;
}

.map-canvas[b-l16oxdjxoj] {
    flex: 1 1 auto;
    min-width: 0;

    /* Ползунок и миникарта лежат поверх холста, а не рядом: место на карте дороже. */
    position: relative;

    /* Жесты внутри холста принадлежат карте, а не странице. Запрет стоит на ЭТОМ div, а не на
       самом SVG: на SVG-элементах браузеры touch-action пропускают мимо ушей, и на телефоне щипок
       увеличивал страницу, а протяжка её прокручивала — карта не получала ни того, ни другого. */
    touch-action: none;

    /* Вычитается ровно то, что стоит над холстом: шапка макета, поля тела и строка заголовка.
       Прежние 14rem считались от окна без шапки и теперь оставляли под холстом сотню пустых
       пикселей — на экране, где место дороже всего. */
    height: calc(100dvh - 8.5rem);
    border: 1px solid var(--rz-base-300);
    border-radius: var(--rz-border-radius);
    overflow: hidden;
    background: var(--rz-base-background-color);
}

/* Выравнивание шапки по базовой линии. Задавать его на самой стопке бесполезно: Radzen ставит
   align-items классом с !important, и стиль на элементе проигрывает — проверено в браузере,
   вычисленное значение оставалось `normal`. Отсюда и !important здесь, и правило от нашего div:
   изолированный стиль метит своим признаком только собственные элементы разметки.

   По базовой линии, а не по центру: у заголовка кегль вдвое крупнее соседей, и отцентрованные
   коробки дают разъехавшиеся строки, а растянутые — мелкий текст, прижатый к верху. */
.map-head[b-l16oxdjxoj]  > .rz-stack {
    align-items: baseline !important;
}

/* Ползунок масштаба и миникарта. Оба ведёт JS-модуль: положение ползунка следует за видом, рамка
   на миникарте показывает его границы. До сервера ни то, ни другое не доходит.

   Стоят одной стопкой в углу: возить мышь через весь холст от ползунка к миникарте — работа,
   которой не должно быть. Приглушены, пока к ним не потянулись: они лежат ПОВЕРХ карты, и место
   под ними дороже их самих. focus-within — ради клавиатуры: ползунок под фокусом обязан быть
   виден целиком. */
.map-nav[b-l16oxdjxoj] {
    position: absolute;
    right: 0.75rem;
    bottom: 0.75rem;
    width: 11rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    opacity: 0.55;
    transition: opacity 0.15s ease;

    /* Коробка стопки кликов НЕ берёт, их берут только сами органы управления. Иначе прозрачные
       промежутки между ползунком, линейкой и миникартой съедают клики по карте под ними — на этом
       и попалась станция, оказавшаяся под ползунком. */
    pointer-events: none;
}

.map-nav > *[b-l16oxdjxoj] {
    pointer-events: auto;
}

/* Наведение ловится через :has, потому что сама стопка кликов не берёт и :hover ей не приходит. */
.map-nav:has(:hover)[b-l16oxdjxoj],
.map-nav:focus-within[b-l16oxdjxoj] {
    opacity: 1;
}

/* Поля у ползунка свои, браузерные, и из-за них он не сходился краями с миникартой. */
.map-zoom[b-l16oxdjxoj] {
    display: block;
    width: 100%;
    margin: 0;
    padding: 0;
    accent-color: var(--rz-primary);
    cursor: pointer;
}

/* Линейка: отрезок известной длины и подпись в метрах. Ими меряют расстояние на глаз — «во
   сколько раз приблизился» на этот вопрос не отвечает. */
.map-scale[b-l16oxdjxoj] {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.75rem;
    color: var(--rz-text-secondary-color);

    /* Линейку не нажимают: её полоса возвращается карте под ней. */
    pointer-events: none;
}

.map-scale-line[b-l16oxdjxoj] {
    height: 0.55rem;
    border: 1px solid var(--rz-text-secondary-color);
    border-top: none;
}

.map-mini[b-l16oxdjxoj] {
    width: 100%;

    /* Соотношение сторон приходит разметкой из холста: миникарта обязана быть той же формы,
       иначе рамка на ней врёт о том, что видно. */
    background: var(--rz-base-background-color);
    border: 1px solid var(--rz-base-300);
    border-radius: var(--rz-border-radius);
    cursor: pointer;
}

.map-mini .map-mini-edge[b-l16oxdjxoj] {
    fill: none;
    stroke: var(--rz-text-tertiary-color);
    stroke-width: 1px;
    vector-effect: non-scaling-stroke;
}

.map-mini .map-mini-view[b-l16oxdjxoj] {
    fill: var(--rz-primary);
    fill-opacity: 0.12;
    stroke: var(--rz-info);
    stroke-width: 1.5px;
    vector-effect: non-scaling-stroke;
}

/* Легенда. Цвета берутся из тех же переменных темы, что и сама карта, — иначе на тёмной теме
   образцы разъехались бы с холстом, а именно ради сверки с холстом легенда и заведена.
   Размеры образцов повторяют иерархию на карте: робот крупнее станции, станция крупнее точки. */
.map-legend[b-l16oxdjxoj] {
    display: grid;
    grid-template-columns: 1.25rem 1fr;
    align-items: center;
    gap: 0.4rem 0.6rem;
    font-size: 0.8rem;
    color: var(--rz-text-secondary-color);
}

.map-legend-mark[b-l16oxdjxoj] {
    justify-self: center;
    border-radius: 50%;
    width: 0.75rem;
    height: 0.75rem;
    background: var(--rz-success);
}

.map-legend-attention[b-l16oxdjxoj] {
    background: var(--rz-danger);
}

.map-legend-untrusted[b-l16oxdjxoj] {
    background: var(--rz-text-tertiary-color);
}

/* Образец «робот везёт груз»: тот же кружок, что у робота на связи, с квадратом паллеты поверх.
   Собран вложением через ::before, потому что образец легенды — один элемент сетки. */
.map-legend-load[b-l16oxdjxoj]::before {
    content: "";
    display: block;
    width: 0.375rem;
    height: 0.375rem;
    margin: 0.1875rem;
    background: var(--rz-base-background-color);
    border: 1.5px solid var(--rz-text-color);
}

/* Образец зарядной станции: оранжевый кружок станции с тёмной молнией поверх — как на холсте. */
.map-legend-bolt[b-l16oxdjxoj] {
    justify-self: center;
    display: grid;
    place-items: center;
    width: 0.75rem;
    height: 0.75rem;
    border-radius: 50%;
    background: var(--rz-warning);
}

.map-legend-bolt svg[b-l16oxdjxoj] {
    width: 0.5rem;
    height: 0.5rem;
    fill: var(--rz-text-color);
}

.map-legend-station[b-l16oxdjxoj] {
    width: 0.6rem;
    height: 0.6rem;
    background: var(--rz-warning);
}

.map-legend-plain[b-l16oxdjxoj] {
    width: 0.35rem;
    height: 0.35rem;
    background: var(--rz-text-disabled-color);
}

.map-legend-line[b-l16oxdjxoj] {
    justify-self: center;
    width: 1.25rem;
    border-top: 2px solid var(--rz-text-tertiary-color);
}

.map-legend-route[b-l16oxdjxoj] {
    border-top: 3px dashed var(--rz-primary);
}

.map-legend-dir[b-l16oxdjxoj] {
    border-top: 3px solid var(--rz-warning);
}

.map-legend-held[b-l16oxdjxoj] {
    border-top: 5px solid var(--rz-warning);
}

.map-legend-halo[b-l16oxdjxoj] {
    justify-self: center;
    width: 0.8rem;
    height: 0.8rem;
    border-radius: 50%;
    border: 2px solid var(--rz-info);
}

.map-side[b-l16oxdjxoj] {
    flex: 0 0 20rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    overflow-y: auto;
    max-height: calc(100dvh - 8.5rem);
}

/* Узкое окно: панель уходит ПОД карту, а не отбирает у неё треть ширины. Порог — 992 px, граница
   `lg` у Radzen: ниже неё двадцать рем панели съедают у холста больше, чем он может отдать, и
   карта перестаёт быть картой. На телефоне боковое меню приложения прячется само (Radzen), так
   что холст получает всю ширину экрана.

   Высота холста при этом задаётся долей окна, а не вычитанием: под ним теперь есть что листать,
   и оставлять там пустоту незачем — наоборот, край панели должен выглядывать, иначе о ней никто
   не догадается. */
@media (max-width: 992px) {
    .map-shell[b-l16oxdjxoj] {
        flex-direction: column;
    }

    .map-canvas[b-l16oxdjxoj] {
        height: 62dvh;
    }

    .map-side[b-l16oxdjxoj] {
        flex: 1 1 auto;
        max-height: none;
        overflow: visible;
    }

    /* Ползунок с миникартой ужимаются: на узком экране они отъедали половину холста. */
    .map-nav[b-l16oxdjxoj] {
        width: 8rem;
    }
}

.map-svg[b-l16oxdjxoj] {
    width: 100%;
    height: 100%;
    cursor: grab;
    touch-action: none;

    /* Двойной клик по карте — это второй шаг чередования выделения, а не попытка выделить слово:
       без запрета браузер подсвечивает имя робота под курсором, и оператор получает синюю кляксу
       вместо ответа. Подписи здесь не текст документа, а часть рисунка. */
    user-select: none;
}

.map-svg.map-dragging[b-l16oxdjxoj] {
    cursor: grabbing;
}

/* На полном отдалении вид равен полному: панорама упёрта со всех сторон, и рука обещала бы то,
   чего нет. Класс ставит JS-модуль, который и без того ведёт вид. */
.map-svg.map-pinned[b-l16oxdjxoj] {
    cursor: default;
}

/* Толщина в пользовательских единицах не годится: при зуме линии распухали бы вместе с картой,
   и на приближении проезд закрывал бы станции. */
.map-svg[b-l16oxdjxoj]  path,
.map-svg[b-l16oxdjxoj]  circle {
    vector-effect: non-scaling-stroke;
}

/* Проезды, стрелки и фоновые точки красятся ПЕРЕДНИМ планом темы, а не оттенками основы.
   Шкала base в тёмной теме уходит в тёмное вместе с фоном — base-500 там #333 на фоне #1e1e1e,
   то есть линия, которой не видно. Цвета текста инвертируются как надо: серый на белом и серый
   на чёрном. Проверено на живой странице в обеих темах. */
.map-svg[b-l16oxdjxoj]  .map-edge {
    fill: none;
    stroke: var(--rz-text-tertiary-color);
    stroke-width: 1.5px;
}

.map-svg[b-l16oxdjxoj]  .map-arrow {
    fill: var(--rz-text-secondary-color);
    stroke: none;
}

/* Точки без нашей локации — фон, и остаются фоном в обеих темах. */
.map-svg[b-l16oxdjxoj]  .map-dot {
    fill: var(--rz-text-disabled-color);
    stroke: none;
}

/* Радиус маркера ЗАЖИМАЕТСЯ экранными пределами, а не задаётся ими: у робота физический размер
   есть — метр в поперечнике, — и в рабочем диапазоне карт он честно масштабируется. Пределы
   спасают на краях: карты заказчиков различаются на два порядка, и без них робот на карте
   эмулятора становится блином в 41 px, а на площадке в 400 м — точкой в один пиксель.

   Радиус объявляется группе, а не кружку: подпись — сосед кружка, а не его потомок, и свой
   отступ она отсчитывает от того же значения. Станция мельче робота и на пределе тоже — иначе
   на общем виде они сравнялись бы, и робот перестал бы отличаться от точки, на которой стоит.

   Числа 0.45 и 0.55 — те самые метры; величина `r` из разметки остаётся запасным путём на случай
   браузера без поддержки геометрических свойств в CSS. */
.map-svg[b-l16oxdjxoj]  .map-stations,
.map-svg[b-l16oxdjxoj]  .map-labels {
    --map-r: clamp(calc(var(--map-marker-min, 0.25px) * 0.8), 0.45px, calc(var(--map-marker-max, 0.6px) * 0.8));
}

.map-svg[b-l16oxdjxoj]  .map-robot {
    --map-r: clamp(var(--map-marker-min, 0.25px), 0.55px, var(--map-marker-max, 0.6px));
}

.map-svg[b-l16oxdjxoj]  .map-station {
    r: var(--map-r);
    fill: var(--rz-warning);
    stroke: var(--rz-base-background-color);
    stroke-width: 1px;
    cursor: pointer;
}

/* Подписи станций прячутся, когда их становится слишком много в поле зрения: на общем виде крупной
   площадки холст превращается в кашу, а на малой карте прятать нечего — их две. Считает JS-модуль,
   класс ставит он же; DOM при этом не трогается (спека 010, AC-33).

   Имена роботов сюда не входят: роботов сотня против двух тысяч станций, и следят как раз за
   ними. Указатель подхода — тоже: он один и появляется только по клику. */
.map-svg[b-l16oxdjxoj]  .map-labels {
    display: none;
}

.map-svg.map-detail[b-l16oxdjxoj]  .map-labels {
    display: initial;
}

/* Кегль, зазор и обводка — в пикселях экрана, а не в метрах карты: у текста физического размера
   нет, а карты заказчиков различаются на два порядка. Переменные ставит JS-модуль по текущему
   масштабу; значения по умолчанию отвечают карте в сотню метров — на случай, если модуль не
   поднялся, подпись останется хоть какого-то размера.

   Сдвиг отсчитывается от радиуса кружка — того же, зажатого пределами: зазор в пикселях
   прибавляется к нему, а не заменяет его, иначе подпись села бы на маркер. Вертикаль — в долях
   кегля. */
.map-svg[b-l16oxdjxoj]  .map-label {
    font-size: var(--map-label-size, 0.75px);
    transform: translate(calc(var(--map-r, 0.45px) + var(--map-gap, 0.3px)), 0.35em);
    fill: var(--rz-text-color);
    paint-order: stroke;
    stroke: var(--rz-base-background-color);
    stroke-width: 0.2em;
    pointer-events: none;
}

/* Указатель подхода выбранной станции.

   Луч в разметке длинный — пять метров, — а видно от него ровно один штрих, и штрих этот меряется
   в ПИКСЕЛЯХ ЭКРАНА: `non-scaling-stroke` делает пунктир экранным. Так длина перестаёт зависеть от
   размаха карты, а элемент остаётся одним путём. Сдвигом пунктира отодвинуть штрих от центра
   станции нельзя — `stroke-dashoffset` при том же `non-scaling-stroke` считается в единицах карты
   (проверено в браузере), — поэтому штрих начинается в центре и выходит из-под маркера сам.

   Цвет станции: указатель принадлежит ей, а не роботу. */
.map-svg[b-l16oxdjxoj]  .map-dir {
    fill: none;
    stroke: var(--rz-warning);
    stroke-width: 3px;
    stroke-linecap: round;
    stroke-dasharray: 34 9999;

    /* Указатель начинается в центре станции и перекрыл бы её кружок, отобрав клик. */
    pointer-events: none;
}

.map-svg[b-l16oxdjxoj]  .map-edge,
.map-svg[b-l16oxdjxoj]  .map-arrow,
.map-svg[b-l16oxdjxoj]  .map-dot,
.map-svg[b-l16oxdjxoj]  .map-route,
.map-svg[b-l16oxdjxoj]  .map-corridor-held,
.map-svg[b-l16oxdjxoj]  .map-endpoint {
    /* Кликать по проездам нечем и незачем, а перехватывать клик у станции они не должны. */
    pointer-events: none;
}

/* Занятый проход — широкой полупрозрачной лентой ПОД дорогой: он отвечает на «почему стоим»,
   а не заменяет собой карту. Сплошной, в отличие от пунктирного маршрута: маршрут — оценка,
   а занятость — факт. */
.map-svg[b-l16oxdjxoj]  .map-corridor-held {
    fill: none;
    stroke: var(--rz-warning);
    stroke-width: 7px;
    stroke-linecap: round;
    opacity: 0.35;
}

/* Маршрут заявки — пунктиром: это оценка по нашему графу, а не маршрут робота. */
.map-svg[b-l16oxdjxoj]  .map-route {
    fill: none;
    stroke: var(--rz-primary);
    stroke-width: 3px;
    stroke-dasharray: 6 4;
    opacity: 0.8;
}

.map-svg[b-l16oxdjxoj]  .map-endpoint {
    fill: none;
    stroke: var(--rz-primary);
    stroke-width: 2px;
}

/* Кольцо выделения. Панель справа отвечает на «что это», кольцо — на «который из них»: без него
   оператор не видит, по чему попал (AC-34). Цвет отдельный от маршрута намеренно — маршрут
   говорит «куда поедет», а выделение «вот этот».

   Селектор двойной: у станции кольцо рисуется само по себе, у робота — внутри его группы, где
   правило `.map-robot circle` иначе перекрасило бы его в заливку робота. */
/* Копия выбранной станции поверх роботов кликов не берёт: под ней стоит робот, и клик обязан
   доставаться ему — иначе чередование выделения замрёт на станции (AC-35). */
.map-svg[b-l16oxdjxoj]  .map-selected {
    pointer-events: none;
}

.map-svg[b-l16oxdjxoj]  .map-halo,
.map-svg[b-l16oxdjxoj]  .map-robot .map-halo {
    /* Кольцо физического смысла не несёт, поэтому живёт в пикселях целиком — и обязано остаться
       снаружи маркера, каким бы тот ни вышел после зажима. */
    r: var(--map-halo-r, 0.9px);
    fill: none;
    stroke: var(--rz-info);
    stroke-width: 2.5px;
    pointer-events: none;
}

.map-svg[b-l16oxdjxoj]  .map-robot circle {
    r: var(--map-r);
    fill: var(--rz-success);
    stroke: var(--rz-base-background-color);
    stroke-width: 1px;
    cursor: pointer;

    /* Плавность между кадрами опроса: точка едет, а не прыгает раз в секунду (AC-10). */
    transition: transform 1s linear;
}

.map-svg[b-l16oxdjxoj]  .map-robot {
    transition: transform 1s linear;
}

/* Молния зарядной станции. Кегль — тот же, что у подписей, то есть в пикселях экрана: у знака
   физического размера нет, а карты заказчиков различаются на два порядка.

   Видна ВСЕГДА, в отличие от подписей: их прячет теснота, а зарядок на складе единицы, и именно
   их ищут глазами. Сидит по центру кружка станции и кликов не берёт — выделение принадлежит
   кружку под ней. */
.map-svg[b-l16oxdjxoj]  .map-charger path {
    /* Масштаб в ЕДИНИЦАХ КАРТЫ, посчитанный модулем из пикселей экрана: множитель безразмерный,
       поэтому у него своя переменная, а не общая с кеглем подписи. */
    transform: scale(var(--map-icon, 0.4));
    fill: var(--rz-text-color);
    paint-order: stroke;
    stroke: var(--rz-base-background-color);
    stroke-width: 1.5px;
    vector-effect: non-scaling-stroke;

    /* Кликов не берёт: под ней кружок станции, и выделение принадлежит ему. */
    pointer-events: none;
}

/* Груз на борту. Квадрат поверх кружка — паллета, которую робот везёт, а не условный знак;
   поэтому он и меньше робота, и сидит по центру. Размер идёт от того же зажатого радиуса, что у
   маркера: на карте эмулятора и на карте площадки в 400 м он остаётся долей робота, а не
   превращается в точку или в блин.

   Цвет — фон холста с обводкой цветом маркера: заливка кружка занята состоянием робота (зелёный,
   красный, серый), и второй смысл у той же краски — ровно то, что легенда однажды уже вскрыла. */
.map-svg[b-l16oxdjxoj]  .map-load {
    x: calc(var(--map-r, 0.55px) * -0.5);
    y: calc(var(--map-r, 0.55px) * -0.5);
    width: calc(var(--map-r, 0.55px));
    height: calc(var(--map-r, 0.55px));
    fill: var(--rz-base-background-color);
    stroke: var(--rz-text-color);
    stroke-width: 1.5px;
    vector-effect: non-scaling-stroke;
    pointer-events: none;
}

/* Недостоверное положение — серый, различимый в обеих темах: маркер это не фон, его обязано
   быть видно, просто он не зелёный и не красный. */
.map-svg[b-l16oxdjxoj]  .map-robot-untrusted circle {
    fill: var(--rz-text-tertiary-color);
}

/* Тревожный робот — красный, а не оранжевый: оранжевым нарисованы станции, и пока цвета не были
   названы легендой, одинаковость двух разных вещей просто никому не бросалась в глаза. */
.map-svg[b-l16oxdjxoj]  .map-robot-attention circle {
    fill: var(--rz-danger);
}

/* Расхождение роботов, попавших в одну точку. Номер строки приходит разметкой из C#, а высота
   строки берётся отсюда: разойтись они обязаны НА СВОЙ НАРИСОВАННЫЙ размер, а он зажат пределами.
   Прежние 0.35 м были той же ошибкой в единицах, что и кегль подписи, — на карте эмулятора они
   давали 26 px, а на боевой полпикселя, где маркеры и так стоят впритык.

   В высоту строки входит и подпись: без неё кружки расходятся, а имена продолжают налезать друг
   на друга — подпись шире кружка в разы. */
.map-svg[b-l16oxdjxoj]  .map-stack {
    transform: translateY(calc(var(--map-stack-row, 0)
        * (var(--map-r, 0.55px) * 2 + var(--map-gap, 0.3px) + var(--map-label-size, 0.75px) * 1.4)));
}

/* Имя робота — по тем же правилам, что подпись станции, но ПОД маркером, а не сбоку: робот,
   доехавший до станции, встаёт ровно на неё, и вправо от одной точки ушли бы обе подписи разом.
   Наложенные друг на друга, они не читаются ни как имя, ни как код локации. */
.map-svg[b-l16oxdjxoj]  .map-robot-name {
    font-size: var(--map-label-size, 0.75px);
    text-anchor: middle;
    transform: translate(0, calc(var(--map-r, 0.55px) + var(--map-gap, 0.3px) + 0.85em));
    fill: var(--rz-text-color);
    paint-order: stroke;
    stroke: var(--rz-base-background-color);
    stroke-width: 0.2em;
    pointer-events: none;
}
/* /Components/Pages/Queue.razor.rz.scp.css */
/* Полоса фильтров очереди.

   На телефоне четыре значения в одну строку не помещаются: на экране в 390 px полоса занимает
   364 и упирается в края, а на более узком уезжает за них. Перенос по строкам решает это без
   смены контрола — значения остаются видны все сразу, а не прячутся в выпадающий список, где
   текущее состояние очереди пришлось бы разворачивать лишним касанием.

   ::deep обязателен: полосу рисует компонент Radzen, и признак изоляции на её элемент не
   попадает. */
.queue-filter[b-4rox72efv2]  .rz-selectbar {
    flex-wrap: wrap;
}
