/* Скин MudBlazor: компоненты берём у Mud, вид даём токенами (DESIGN_SYSTEM.md §9).

   Почему CSS-переопределения, а не свои контролы: разметки в приложении около 7500 строк, и она уже
   написана на Mud. Скин здесь означает, что каждое существующее поле, кнопка и таблица получают вид
   системы без единой правки в .razor. Самописный контрол пришлось бы ещё и подставить в 143 места.

   Файл подключается ПОСЛЕ MudBlazor.min.css — на равной специфичности выигрывает порядок, поэтому
   !important стоит только там, где Mud задаёт свойство анимацией или очень специфичным селектором
   (позиция плавающей подписи). */

/* ---------- база ---------- */

html, body {
    background: var(--fb-bg);
    font-family: var(--fb-ui);
}

/* Mud раздаёт Roboto каждому типографскому классу. Раньше он тянулся с Google Fonts и был единственным
   обращением в сеть во всём приложении — при работе офлайн шрифт молча подменялся системным, и
   интерфейс выглядел иначе, чем при разработке. Гарнитуру задаёт тема (Typography в MainLayout),
   здесь добираются классы, до которых тема не достаёт. */
.mud-typography, .mud-input-slot, .mud-button-root, .mud-chip, .mud-table {
    font-family: var(--fb-ui);
}

/* Машинное значение — моноширинным (§4). Класс вешается там, где в поле лежит ключ, id или цена. */
.fb-mono, .fb-mono .mud-input-slot, .fb-mono input {
    font-family: var(--fb-mono);
    font-size: 11.5px;
    letter-spacing: -.01em;
}

/* ---------- поля ввода ---------- */

/* Плавающая подпись, уезжающая в вырез рамки, — самый узнаваемый признак дефолтного Material.
   Здесь подпись стоит НАД полем и не двигается: она читается всегда, в том числе когда поле
   заполнено, и строка не перекомпоновывается на фокусе.

   Подпись лежит в DOM ПОСЛЕ поля (label — сосед .mud-input внутри контейнера), поэтому колонка
   разворачивается column-reverse, а не переносом узла: порядок в разметке остаётся Mud'овским,
   и обновления компонента его не ломают. */
.mud-input-control .mud-input-control-input-container {
    display: flex;
    flex-direction: column-reverse;
    align-items: stretch;
    gap: 5px;
    height: auto;
}

.mud-input-control,
.mud-input-control.mud-input-sizing-fixed {
    height: auto;
}

/* !important здесь не украшение: Material задаёт размер подписи не свойством, а scale-трансформом
   на «сжатом» состоянии (16px, уменьшенные до 12 при заполненном поле). Трансформ снят — иначе
   подпись поехала бы в вырез рамки, — и без явного размера остаётся базовый 16px, крупнее самого
   значения в поле. */
.mud-input-control .mud-input-label,
.mud-input-control .mud-input-label-outlined,
.mud-input-control .mud-input-label-inputcontrol {
    position: static !important;
    transform: none !important;
    transform-origin: unset;
    max-width: none;
    padding: 0 2px;
    font-family: var(--fb-ui);
    font-size: 11px !important;
    font-weight: 500 !important;
    line-height: 1.2 !important;
    letter-spacing: .02em;
    color: var(--fb-ink-dim);
    pointer-events: auto;
    transition: color .12s ease;
}

/* Рамку рисует сам блок поля, а материаловская `fieldset` с вырезом под подпись убирается целиком.

   Селектор обязан нести ДВА класса на `.mud-input`: у Mud правило записано как
   `.mud-input.mud-input-outlined .mud-input-outlined-border`, и одноклассовый
   `.mud-input .mud-input-outlined-border` ему проигрывает по специфичности. Проигрыш выглядел не как
   «стиль не применился», а как тёмный прямоугольник, разрывающий верхнюю границу поля: `legend`
   внутри `fieldset` имеет нулевую высоту и прорезает в рамке дыру шириной с подпись — тот самый
   вырез, ради которого он там и стоит. */
.mud-input.mud-input-outlined .mud-input-outlined-border,
.mud-input.mud-input-filled .mud-input-outlined-border { display: none; }

.mud-input.mud-input-outlined,
.mud-input.mud-input-filled,
.mud-input.mud-input-text {
    background: var(--fb-sunken);
    border: 1px solid var(--fb-line);
    border-radius: var(--fb-r-in);
    min-height: 38px;
    padding: 0 10px;
    gap: 6px;
    transition: border-color .12s ease, box-shadow .15s ease, background .12s ease;
}

.mud-input.mud-input-margin-dense { min-height: 34px; }

/* Подчёркивание — приём Material, которого в системе нет: состояние поля кодируется рамкой и
   кольцом, как у всех остальных объектов (§7). */
.mud-input.mud-input-text::before,
.mud-input.mud-input-text::after,
.mud-input.mud-input-filled::before,
.mud-input.mud-input-filled::after { display: none; }

/* Высоту поля задаёт слот, а не только рамка: у Mud он несёт собственные отступы под плавающую
   подпись, и без их обнуления поле остаётся материаловских 56/40px независимо от min-height. */
.mud-input .mud-input-slot,
.mud-input input.mud-input-root,
.mud-input textarea.mud-input-root {
    padding: 0;
    height: auto;
    min-height: 0;
    color: var(--fb-ink);
    font-size: 13px;
    line-height: 1.35;
}

/* Обнулять ОТСТУП, а не только padding: Mud даёт outlined-textarea `margin-top: 18.5px` — место
   под плавающую подпись, которая у нас статична (см. блок про label выше). Отступ оставался
   незанятым, и в поле промпта на шесть строк пропадала целая первая строка. */
.mud-input textarea.mud-input-root {
    margin: 0;
    padding: 8px 0;
    line-height: 1.45;
}

/* Ручка растягивания. Mud глушит её у всех textarea; повод вернуть — промпт шага, которому шести
   строк мало ровно тогда, когда работа идёт всерьёз. Правило общее, а не на одно поле: одинаковые
   с виду поля, ведущие себя по-разному, читаются как баг, а тесно бывает и параметрам, и описанию.

   Растим только по вертикали: ширину держит колонка инспектора, и горизонтальная ручка вылезала бы
   за панель. Поле с автовысотой (`sizing-auto`, ввод чата) исключено — оно меряет себя из JS, и
   ручка дралась бы с ним на каждый символ. */
.mud-input:not(.mud-input-sizing-auto) textarea.mud-input-root {
    resize: vertical;
}

.mud-input .mud-input-slot::placeholder {
    color: var(--fb-ink-faint);
    opacity: 1;
}

.mud-input:hover:not(.mud-disabled) { border-color: var(--fb-line-hi); }

/* Фокус — то же кольцо, что у выделенной ноды и выбранной карточки голоса (§7). Одно понятие —
   одна форма записи: «этот объект сейчас в работе» выглядит одинаково везде. */
.mud-input.mud-focused,
.mud-input-control:focus-within .mud-input {
    border-color: var(--fb-primary);
    box-shadow: var(--fb-ring);
    background: var(--fb-inset);
}

.mud-input-control:focus-within .mud-input-label { color: var(--fb-primary); }

.mud-input-control.mud-input-error .mud-input,
.mud-input.mud-input-error {
    border-color: var(--fb-danger);
    box-shadow: var(--fb-ring-danger);
}

.mud-input-control.mud-input-error .mud-input-label { color: var(--fb-danger); }

.mud-input.mud-disabled,
.mud-input-control .mud-disabled {
    opacity: .45;
    cursor: default;
}

/* Подсказка под полем: третий уровень текста, отдельно от подписи над ним. */
.mud-input-helper-text {
    margin-top: 4px;
    padding: 0 2px;
    font-size: 10.5px;
    line-height: 1.35;
    color: var(--fb-ink-faint);
}

.mud-input-helper-text.mud-input-error { color: var(--fb-danger); }

/* Иконка внутри поля (поиск, глаз пароля, стрелка списка) — служебная, поэтому приглушена. */
.mud-input-adornment .mud-icon-root { font-size: 17px; color: var(--fb-ink-dim); }
.mud-input-adornment .mud-icon-button { padding: 3px; }
.mud-input-adornment-start { margin-right: 2px; }

.mud-select .mud-input .mud-select-input { color: var(--fb-ink); }

/* Спиннеры числового поля: Mud рисует их крупными, в узкой панели инспектора они съедают поле. */
.mud-input-numeric-spin .mud-icon-button { padding: 1px; }
.mud-input-numeric-spin .mud-icon-root { font-size: 14px; }

/* ---------- переключатели ---------- */

.mud-switch .mud-switch-track { background: var(--fb-line); opacity: 1; }
.mud-switch .mud-switch-base.mud-checked + .mud-switch-track { background: var(--fb-primary); opacity: .55; }
.mud-switch .mud-switch-thumb { background: var(--fb-ink-dim); }
.mud-switch .mud-checked .mud-switch-thumb { background: var(--fb-primary); }
.mud-switch .mud-switch-label, .mud-checkbox .mud-checkbox-label { font-size: 13px; color: var(--fb-ink); }

/* ---------- кнопки ---------- */

.mud-button-root {
    border-radius: var(--fb-r-in);
    font-family: var(--fb-ui);
    font-size: 12.5px;
    font-weight: 600;
    letter-spacing: .01em;
    /* ЗАГЛАВНЫЕ — материаловская привычка: русские подписи вроде «ДУБЛИРОВАТЬ» из-за неё читаются
       заметно хуже, а строка кнопок в таблице превращается в забор. */
    text-transform: none;
    transition: background .12s ease, border-color .12s ease, color .12s ease, box-shadow .15s ease;
}

.mud-button-filled {
    box-shadow: none;
    background: var(--fb-primary);
    color: var(--fb-on-primary);
}

.mud-button-filled:hover { box-shadow: var(--fb-ring); filter: brightness(1.08); }

.mud-button-filled.mud-button-filled-error { background: var(--fb-danger); color: var(--text-inverse); }

.mud-button-outlined {
    border-color: var(--fb-line);
    background: var(--fb-sunken);
    color: var(--fb-ink);
}

.mud-button-outlined:hover {
    border-color: var(--fb-primary);
    background: var(--fb-surface-hi);
}

.mud-button-text { color: var(--fb-ink-dim); }
.mud-button-text:hover { color: var(--fb-ink); background: var(--fb-hover); }
.mud-button-text.mud-button-text-error { color: var(--fb-danger); }

.mud-icon-button { border-radius: var(--fb-r-in); color: var(--fb-ink-dim); }
.mud-icon-button:hover { color: var(--fb-ink); background: var(--fb-hover); }

/* Клавиатурный фокус обязан быть виден — кольцо системы, а не браузерная пунктирная рамка. */
.mud-button-root:focus-visible,
.mud-nav-link:focus-visible,
.mud-icon-button:focus-visible {
    outline: none;
    box-shadow: var(--fb-ring);
}

/* ---------- поверхности ---------- */

.mud-paper {
    background: var(--fb-grad);
    border: 1px solid var(--fb-line);
    border-radius: var(--fb-r-card);
    box-shadow: var(--fb-inner-hi), var(--fb-shadow);
}

/* Всплывающие поверхности рисуются тем же .mud-paper, но градиент на списке под полем выглядит
   как вторая карточка: у меню фон ровный и темнее — оно «над», а не «рядом». */
.mud-popover.mud-paper, .mud-menu-popover .mud-paper {
    background: var(--fb-surface);
    box-shadow: var(--fb-shadow);
}

/* Двойной скролл-бар в дропдаунах — стык нашей рамки с формулой Mud, а не его баг.

   MudSelect вешает на поповер инлайновый `max-height: 300px`, а Mud объявляет
   `.mud-popover .mud-list { max-height: inherit }` — список берёт ЗАЯВЛЕННЫЕ 300px, а не
   внутреннюю высоту поповера. У нас же `.mud-paper` несёт `border: 1px`, и при border-box
   content-box поповера равен 298px: список на 2px не влезает, а собственный `overflow-y: auto`
   поповера честно рисует под эти 2px вторую полосу рядом с настоящей.

   Лечим причину, а не полосу: поповер перестаёт быть скроллером вовсе, а список flex-элементом
   занимает его content-box сам — тогда 300px из `inherit` не участвуют в раскладке. Скроллером
   остаётся ровно один элемент, и им оказывается тот, у кого есть что прокручивать.
   У Mud рамки на .mud-paper нет, поэтому апстрим на это не наступает и чинить там нечего. */
.mud-popover.mud-paper:has(> .mud-list) {
    overflow: hidden;
    display: flex;
}

/* Список обязан занять ВСЮ ширину поповера, а не ширину своего текста. Флекс-элемент по умолчанию
   не растягивается (`flex: 0 1 auto`), поэтому у поповера шириной с поле список получался шириной с
   самый длинный пункт: полоса прокрутки висела посреди меню, а подсветка выбранного пункта
   обрывалась там же, где кончалось слово. `min-width: 0` — чтобы длинный пункт, наоборот, не
   раздувал список шире поповера. */
.mud-popover.mud-paper > .mud-list {
    max-height: none;
    flex: 1 1 auto;
    min-width: 0;
}

.mud-divider { border-color: var(--fb-line); }

/* ---------- списки и меню ---------- */

.mud-list-item {
    border-radius: var(--fb-r-chip);
    font-size: 13px;
    color: var(--fb-ink);
    transition: background .12s ease, color .12s ease;
}

.mud-list-item:hover { background: var(--fb-hover); }

.mud-list-item.mud-selected-item,
.mud-list-item.mud-list-item-selected {
    background: var(--fb-primary-soft);
    color: var(--fb-primary);
}

.mud-list-item-text .mud-typography { font-size: 13px; }

/* ---------- таблицы ---------- */

.mud-table.mud-paper { box-shadow: var(--fb-inner-hi), var(--fb-shadow); overflow: hidden; }

.mud-table-head .mud-table-cell {
    /* Шапка таблицы — служебная строка, а не заголовок: она называет колонки. Отсюда эйрбоу-регистр,
       тот же, что у подписи раздела на рельсе палитры. */
    font-family: var(--fb-ui);
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: var(--fb-tr-eyebrow);
    text-transform: uppercase;
    color: var(--fb-ink-faint);
    background: var(--fb-bg);
    border-bottom: 1px solid var(--fb-line);
    padding: 9px 12px;
    white-space: nowrap;
}

.mud-table-body .mud-table-cell {
    font-size: 13px;
    color: var(--fb-ink);
    border-bottom: var(--fb-div);
    padding: 8px 12px;
}

.mud-table-body .mud-table-row:last-child .mud-table-cell { border-bottom: none; }

.mud-table-body .mud-table-row:hover { background: var(--fb-hover); }

/* Числовое и машинное — моноширинным, выключка вправо: колонка цен должна сравниваться взглядом
   по разряду, а не по случайной ширине пропорциональных цифр (§4). */
.fb-num {
    font-family: var(--fb-mono);
    font-size: 12px;
    font-variant-numeric: tabular-nums;
    text-align: right;
    white-space: nowrap;
}

.fb-key {
    font-family: var(--fb-mono);
    font-size: 11.5px;
    color: var(--fb-ink-dim);
}

/* Строка действий в таблице: кнопки не должны шуметь, пока строку не тронули. */
.fb-row-actions { white-space: nowrap; text-align: right; }
.fb-row-actions .mud-button-root { opacity: .72; transition: opacity .12s ease; }
.mud-table-row:hover .fb-row-actions .mud-button-root,
.fb-row-actions .mud-button-root:focus-visible { opacity: 1; }

/* ---------- чипы и статусы ---------- */

.mud-chip {
    border-radius: var(--fb-r-chip);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .01em;
    height: 20px;
}

.mud-chip.mud-chip-filled { color: var(--fb-on-primary); }

/* Азбука состояний §7. «Готово» — не событие, а покой: зелёная точка стоит приглушённой, текст
   рядом остаётся серым, плашки нет вовсе. Пятнадцать ярких «готово» в списке заглушили бы те две
   строки, которые действительно ждут человека. Громко — только «нужен выбор» и «упало». */
.fb-state {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-family: var(--fb-ui);
    font-size: 11.5px;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
}

.fb-state::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
}

.fb-state-done { color: var(--fb-ink-dim); }
.fb-state-done::before { background: var(--fb-ok); opacity: .75; }

.fb-state-idle { color: var(--fb-ink-faint); }

.fb-state-cancelled { color: var(--fb-ink-faint); opacity: .7; }
.fb-state-cancelled::before { background: var(--fb-ink-faint); }

.fb-state-running { color: var(--fb-primary); }

/* Единственная бесконечная анимация системы означает ожидание (§6). «Выполняется» — ровно оно,
   поэтому точка дышит, а не просто светится. */
.fb-state-running::before { animation: fb-pulse 1.6s ease-in-out infinite; }

/* «Ждёт человека» — единственное состояние с заливкой и кольцом: ради него на экран и смотрят. */
.fb-state-await {
    color: var(--fb-await);
    background: var(--fb-await-soft);
    padding: 3px 7px;
    border-radius: var(--fb-r-chip);
    box-shadow: var(--fb-ring-await);
}

.fb-state-failed {
    color: var(--fb-danger);
    background: var(--fb-danger-soft);
    padding: 3px 7px;
    border-radius: var(--fb-r-chip);
}

@keyframes fb-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: .3; }
}

@media (prefers-reduced-motion: reduce) {
    .fb-state-running::before { animation: none; }
}

/* ---------- диалоги ---------- */

.mud-dialog {
    border: 1px solid var(--fb-line);
    border-radius: var(--fb-r-page);
    background: var(--fb-surface);
    box-shadow: var(--shadow-dialog);
}

.mud-dialog-title {
    padding: 14px 18px;
    border-bottom: 1px solid var(--fb-line);
    background: var(--fb-bg);
}

.mud-dialog-title .mud-typography {
    font-family: var(--fb-display);
    font-size: 14px;
    font-weight: 800;
    letter-spacing: .01em;
    color: var(--fb-ink);
}

.mud-dialog-content { padding: 16px 18px; }

.mud-dialog-actions {
    padding: 12px 18px;
    border-top: 1px solid var(--fb-line);
    background: var(--fb-bg);
    gap: 8px;
}

.mud-overlay-dialog { backdrop-filter: blur(2px); }

/* Диалог на телефоне — почти во весь экран. Материаловские поля вокруг рассчитаны на окно, а не на
   414 точек: от «Нового прогона» с брифом и списком материалов оставалась колонка в 340 точек с
   полями по краям, то есть форма шириной с половину экрана. Кнопки действий растягиваются: две
   кнопки, прижатые к правому краю, — самое неудобное место для большого пальца.

   Своей высоты не задаём: диалоги здесь разной длины, и растянутый на весь экран короткий диалог
   выглядел бы страницей, которой он не является. */
@media (max-width: 560px) {
    .mud-dialog {
        width: calc(100vw - 16px);
        max-width: calc(100vw - 16px);
        margin: 8px;
    }

    .mud-dialog-title { padding: 12px 14px; }
    .mud-dialog-content { padding: 14px; max-height: 70vh; }
    .mud-dialog-actions { padding: 10px 14px; }
    .mud-dialog-actions > .mud-button-root { flex: 1 1 auto; }
}

/* ---------- сообщения ---------- */

.mud-alert {
    border-radius: var(--fb-r-in);
    border: 1px solid var(--fb-line);
    font-size: 12.5px;
}

.mud-alert.mud-alert-filled-error, .mud-alert.mud-alert-text-error {
    background: var(--fb-danger-soft);
    border-color: var(--fb-danger);
    color: var(--fb-danger);
}

.mud-alert.mud-alert-filled-warning, .mud-alert.mud-alert-text-warning {
    background: var(--fb-await-soft);
    border-color: var(--fb-await);
    color: var(--fb-await);
}

/* «Успех» в системе тихий: сообщение подтверждает действие, а не празднует его. */
.mud-alert.mud-alert-filled-success, .mud-alert.mud-alert-text-success,
.mud-alert.mud-alert-filled-info, .mud-alert.mud-alert-text-info {
    background: var(--info-tint);
    border-color: var(--info-500);
    color: var(--fb-ink);
}

.mud-alert .mud-alert-icon .mud-icon-root { color: inherit; }

.mud-snackbar {
    border: 1px solid var(--fb-line);
    border-radius: var(--fb-r-in);
    background: var(--fb-surface);
    color: var(--fb-ink);
    font-size: 12.5px;
    box-shadow: var(--fb-shadow);
}

/* Подсказка — своя, не материаловская. Селектор с двумя классами не для красоты: у MudBlazor
   собственное правило `.mud-tooltip.mud-tooltip-default` (серый #616161 и светлый текст), и
   одноклассовое наше ему проигрывало по весу — подсказки во всём приложении оставались чужого
   цвета мимо палитры. Фон непрозрачный: сквозь полупрозрачный просвечивает страница, и текст
   подсказки перестаёт читаться — а она существует ровно затем, чтобы её прочитали. */
.mud-tooltip,
.mud-tooltip.mud-tooltip-default {
    border: 1px solid var(--fb-line);
    border-radius: var(--fb-r-chip);
    background-color: var(--fb-inset);
    color: var(--fb-ink);
    font-size: 11.5px;
    box-shadow: var(--fb-shadow);
}

/* ---------- прогресс ---------- */

.mud-progress-linear { border-radius: 2px; height: 3px; background: var(--fb-line); }
.mud-progress-linear .mud-progress-linear-bar { background: var(--fb-primary); }

/* ---------- раскрывающиеся панели ---------- */

.mud-expand-panel { background: transparent; border: 1px solid var(--fb-line); border-radius: var(--fb-r-in); }
.mud-expand-panel .mud-expand-panel-header { font-size: 12.5px; min-height: 38px; }

/* ---------- полосы прокрутки ---------- */

* { scrollbar-width: thin; scrollbar-color: var(--fb-line) transparent; }
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--fb-line); border-radius: 5px; }
*::-webkit-scrollbar-thumb:hover { background: var(--fb-line-hi); }
