/* Каркас приложения: фиксированный топбар, фиксированный рельс слева, прокручиваемая середина.

   Прокручивается ТОЛЬКО середина. Это правило, а не следствие вёрстки: у канваса, таблицы моделей и
   списка прогонов разная высота содержимого, и пока прокручивалась страница целиком, рельс уезжал
   вверх вместе с ней — на длинном списке навигация оказывалась за верхней кромкой окна.

   Топбар вернулся, хотя однажды был убран. Тогда он держал логотип и переключатель темы, то есть не
   держал ничего, и 64 пикселя высоты честно отдали канвасу. Теперь на нём то, что обязано быть видно
   всегда и на каждой странице: кто вошёл, сколько у него кредитов и как выйти. Высота при этом
   меньше — 52px, — и уходит она из общей вертикали один раз, через --fb-topbar-h.

   Каркас свой, а не MudLayout: постоянный рельс — не выдвижной ящик, и MudDrawer, который никогда не
   закрывается, пришлось бы бороть его же отступами. Ссылки остались Mud'овскими — MudNavLink сам
   знает про активный маршрут. */

.fb-shell {
    display: flex;
    flex-direction: column;
    height: 100vh;
    background: var(--fb-bg);
}

/* ---------- марка ----------

   «Fabrika.» — точка после названия и есть весь знак. Логотипа нет: рисовать его не из чего, а
   выдуманный значок был бы ровно той «тематической метафорой», которой система избегает.
   Точка — единственное место, где акцентный цвет стоит не на элементе управления. */

.fb-brand {
    display: inline-flex;
    align-items: baseline;
    gap: 0;
    font-family: var(--fb-display);
    /* Крупнее подписи раздела рядом: марка — единственный знак продукта, и на кегле соседнего чипа
       точка после названия читалась как опечатка. Запасное значение обязательно: незагруженный токен
       обнулил бы объявление, и кегель наследовался бы от родителя. */
    font-size: var(--fb-fs-26, 26px);
    font-weight: 800;
    letter-spacing: var(--fb-tr-head);
    line-height: 1;
    color: var(--fb-ink);
    text-decoration: none;
    white-space: nowrap;
}

.fb-brand::after {
    content: ".";
    color: var(--fb-primary);
}

/* По наведению марка целиком уходит в акцент — тот же цвет, что и точка. Раньше здесь белел
   литерал `#fff`, и в светлой теме название пропадало бы с бумаги. */
.fb-brand:hover { color: var(--fb-primary); }

/* ---------- топбар ---------- */

.fb-topbar {
    display: flex;
    align-items: center;
    gap: 14px;
    flex: none;
    height: var(--fb-topbar-h);
    padding: 0 14px;
    background: var(--fb-bg);
    border-bottom: 1px solid var(--fb-line);
    /* Над содержимым: у канваса свои слои, и без этого палитра нод накрыла бы меню профиля. */
    position: relative;
    z-index: 30;
}

/* Раздел, в котором человек находится. Стоит рядом с маркой, а не в шапке страницы: в админке и в
   кабинете совпадают адреса разделов («Шаблоны» есть и там, и там), и различить их можно только
   здесь. */
.fb-topbar-scope {
    padding: 3px 8px;
    border: 1px solid var(--fb-line);
    border-radius: var(--fb-r-chip);
    background: var(--fb-sunken);
    font-family: var(--fb-ui);
    font-size: var(--fb-fs-10);
    font-weight: 600;
    letter-spacing: var(--fb-tr-eyebrow);
    text-transform: uppercase;
    color: var(--fb-ink-dim);
}

.fb-topbar-spacer { margin-left: auto; }

/* Баланс. Моноширинный, потому что это число, которое человек сверяет с ценой запуска (§4). */
.fb-credits {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    padding: 4px 9px;
    border: 1px solid var(--fb-line);
    border-radius: var(--fb-r-chip);
    background: var(--fb-sunken);
    text-decoration: none;
    transition: border-color .12s ease;
}

.fb-credits:hover { border-color: var(--fb-line-hi); }

.fb-credits-value {
    font-family: var(--fb-mono);
    font-size: var(--fb-fs-12);
    font-weight: 500;
    color: var(--fb-ink);
}

.fb-credits-label {
    font-family: var(--fb-ui);
    font-size: var(--fb-fs-10);
    color: var(--fb-ink-faint);
}

/* Мало кредитов — жёлтого здесь быть не может: жёлтый означает «ждёт человека» и занят прогонами.
   Пустой баланс — это не ожидание, а препятствие, поэтому цвет отказа. */
.fb-credits.is-low { border-color: var(--fb-danger); }
.fb-credits.is-low .fb-credits-value { color: var(--fb-danger); }

/* ---------- переключатель темы ----------

   Одна кнопка, а не пара «солнце/луна» и не выпадающий список из трёх пунктов: тем ровно две, и
   кнопка показывает ту, В КОТОРУЮ переключит, — иначе значок читается как «текущее состояние», и
   человек жмёт его, чтобы получить то, что уже видит.

   Системную тему ОС мы не слушаем вовсе (см. tokens.css), поэтому пункта «как в системе» здесь
   нет и быть не должно: он обещал бы поведение, которого нет.

   Кнопка стоит в топбаре кабинета и админки, на карточке входа и в шапке лендинга. Разметка у
   всех одна, обработчик — общий делегат в js/theme.js по атрибуту data-fabrika-theme-toggle. */
.fb-theme-toggle {
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    padding: 0;
    flex: none;
    border: 1px solid var(--fb-line);
    border-radius: var(--fb-r-in);
    background: var(--fb-sunken);
    color: var(--fb-ink-dim);
    cursor: pointer;
    transition: var(--transition-control);
}

/* ---------- бургер ----------

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

   В широком окне её нет вовсе (display: none ниже по умолчанию), потому что рельс там стоит на
   месте: кнопка, открывающая то, что и так открыто, — это кнопка, которая ничего не делает. */
.fb-burger {
    display: none;
    place-items: center;
    width: 28px;
    height: 28px;
    padding: 0;
    flex: none;
    border: 1px solid var(--fb-line);
    border-radius: var(--fb-r-in);
    background: var(--fb-sunken);
    color: var(--fb-ink-dim);
    cursor: pointer;
    transition: var(--transition-control);
}

.fb-burger:hover { border-color: var(--fb-line-hi); color: var(--fb-ink); }
.fb-burger:focus-visible { outline: none; box-shadow: var(--fb-ring); }
.fb-burger .mud-icon-root { font-size: 17px; }

/* Затемнение под выехавшим рельсом. В широком окне его нет: гасить нечего. */
.fb-nav-scrim { display: none; }

.fb-theme-toggle:hover { border-color: var(--fb-line-hi); color: var(--fb-ink); }
.fb-theme-toggle:focus-visible { outline: none; box-shadow: var(--fb-ring); }
.fb-theme-toggle svg { width: 15px; height: 15px; grid-area: 1 / 1; }

/* Значок выбирает CSS по теме документа, а не C# по состоянию: тема приезжает из JS асинхронно, и
   значок, выбранный при рендере, был бы гонкой. Правило читается «в тёмной теме показываем то, во
   что переключим» — солнце. */
.fb-theme-toggle .fb-theme-light { display: none; }

[data-theme="light"] .fb-theme-toggle .fb-theme-dark { display: none; }
[data-theme="light"] .fb-theme-toggle .fb-theme-light { display: block; }

/* Кнопка профиля. Инициал вместо аватара: картинки пользователя в системе нет, а серый силуэт —
   это картинка, которая ничего не сообщает.

   Кружок надет НА ШТАТНУЮ кнопку MudMenu, а не на свой <span> в ActivatorContent: со своим
   активатором меню не открывается по клику вовсе (то же самое чинилось на палитре нод, см.
   `.graph-rail .mud-menu .mud-button-root`). Селектор из трёх классов бьёт `.mud-button-root`
   скина порядком специфичности, поэтому !important здесь не нужен. */
.fb-usermenu.mud-menu .mud-button-root {
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    min-width: 0;
    padding: 0;
    border: 1px solid var(--fb-line);
    border-radius: 50%;
    background: var(--fb-grad);
    font-family: var(--fb-ui);
    font-size: var(--fb-fs-12);
    font-weight: 600;
    line-height: 1;
    color: var(--fb-ink-dim);
    transition: border-color .12s ease, color .12s ease;
}

.fb-usermenu.mud-menu .mud-button-root:hover {
    border-color: var(--fb-primary);
    color: var(--fb-ink);
    background: var(--fb-grad);
}

/* Подпись кнопки Mud лежит в собственном span, и без обнуления его отступов инициал стоит не по
   центру кружка, а со сдвигом вправо на материаловский зазор под иконку. */
.fb-usermenu.mud-menu .mud-button-label { margin: 0; padding: 0; line-height: 1; }

/* ---------- тело ---------- */

.fb-body {
    display: flex;
    align-items: stretch;
    flex: 1 1 auto;
    min-height: 0;
}

/* ---------- навигация ---------- */

.fb-nav {
    display: flex;
    flex-direction: column;
    flex: none;
    width: var(--fb-nav-w);
    padding: 12px 10px 10px;
    background: var(--fb-bg);
    border-right: 1px solid var(--fb-line);
    /* Рельс не прокручивается вместе с содержимым: своя прокрутка нужна ему только если пунктов
       станет больше, чем помещается. */
    overflow-y: auto;
}

/* Подпись группы. Тот же приём, что у разделов палитры нод, и означает то же самое — «дальше идут
   пункты одного рода». */
.fb-nav-section {
    margin: 12px 0 4px;
    padding: 0 10px;
    font-family: var(--fb-ui);
    font-size: var(--fb-fs-10);
    font-weight: 600;
    letter-spacing: var(--fb-tr-eyebrow);
    text-transform: uppercase;
    color: var(--fb-ink-faint);
}

.fb-nav-section:first-child { margin-top: 0; }

.fb-nav .mud-navmenu { padding: 0; }

/* Подпункты рельса — последние разговоры чата. Мельче и тише основных пунктов: это не разделы, а
   закладки внутри одного раздела, и спорить с ним по весу они не должны. Отступ слева выравнивает
   их по подписи пункта, а не по его значку — так видно, что они принадлежат чату. */
.fb-nav-subs {
    display: flex;
    flex-direction: column;
    margin: 0 0 2px;
    padding-left: 10px;
}

.fb-nav-sub {
    padding: 5px 10px 5px 27px;
    border-radius: var(--fb-r-in);
    font-family: var(--fb-ui);
    font-size: var(--fb-fs-12);
    line-height: var(--fb-lh-control);
    color: var(--fb-ink-faint);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: color .12s ease, background .12s ease;
}

.fb-nav-sub:hover { color: var(--fb-ink); background: var(--fb-surface); }
.fb-nav-sub.is-active { color: var(--fb-ink); background: var(--fb-surface); }
.fb-nav-sub.is-more { color: var(--fb-ink-dim); }

.fb-nav .mud-nav-link {
    position: relative;
    gap: 10px;
    min-height: 32px;
    margin: 1px 0;
    padding: 6px 10px;
    border-radius: var(--fb-r-in);
    font-family: var(--fb-ui);
    font-size: var(--fb-fs-13);
    font-weight: 500;
    line-height: var(--fb-lh-control);
    color: var(--fb-ink-dim);
    background: transparent;
    transition: color .12s ease, background .12s ease;
}

.fb-nav .mud-nav-link .mud-icon-root {
    font-size: 17px;
    color: inherit;
    opacity: .85;
}

.fb-nav .mud-nav-link:hover {
    color: var(--fb-ink);
    background: var(--fb-surface);
}

/* Активный пункт — заливка плюс корешок слева. Материаловская таблетка целиком в Primary кричала
   громче кнопки «Новый ролик» на той же странице: указатель места не должен спорить с действием. */
.fb-nav .mud-nav-link.active {
    color: var(--fb-ink);
    background: var(--fb-surface);
}

.fb-nav .mud-nav-link.active::before {
    content: "";
    position: absolute;
    left: 0;
    top: 7px;
    bottom: 7px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: var(--fb-primary);
}

.fb-nav .mud-nav-link.active .mud-icon-root { color: var(--fb-primary); opacity: 1; }

/* Нижний блок рельса: то, ради чего приложение не открывают. */
.fb-nav-foot {
    margin-top: auto;
    padding-top: 8px;
    border-top: 1px solid var(--fb-line);
}

/* Конструктор шаблона забирает окно целиком: у него уже есть свой вертикальный рельс (палитра нод),
   и два рельса подряд съедали ширину, за которую канвас и так дерётся. Уходят со страницы стрелкой
   «назад» в её шапке.

   Правило висит на разметке, а не на маршруте: `.graph-page.has-rail` есть ровно у конструктора
   (прогон рисуется тем же графом, но без палитры), поэтому знать про адреса каркасу не нужно. */
@media (min-width: 901px) {
    .fb-body:has(.graph-page.has-rail) .fb-nav { display: none; }
}

/* ---------- рабочая область ---------- */

.fb-main {
    flex: 1 1 auto;
    /* min-width обязателен: без него широкая таблица растягивает flex-элемент и рельс уезжает
       за левый край окна. */
    min-width: 0;
    /* Единственное, что прокручивается. */
    overflow-y: auto;
    padding: 18px 22px 24px;
}

/* ---------- шапка страницы ---------- */

.fb-head {
    display: flex;
    align-items: flex-end;
    gap: 16px;
    margin-bottom: 16px;
}

.fb-head-eyebrow {
    display: block;
    margin-bottom: 4px;
    font-family: var(--fb-ui);
    font-size: var(--fb-fs-10);
    font-weight: 600;
    letter-spacing: var(--fb-tr-eyebrow);
    text-transform: uppercase;
    color: var(--fb-ink-faint);
}

.fb-head-title {
    font-family: var(--fb-display);
    font-size: var(--fb-fs-26);
    font-weight: 800;
    line-height: var(--fb-lh-head);
    letter-spacing: var(--fb-tr-head);
    color: var(--fb-ink);
}

.fb-head-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: auto;
    flex-wrap: wrap;
    justify-content: flex-end;
}

/* Полоса фильтров над таблицей: утоплена, потому что это орудие для списка, а не сам список. */
.fb-toolbar {
    display: flex;
    align-items: flex-end;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 12px;
    padding: 10px 12px;
    border: 1px solid var(--fb-line);
    border-radius: var(--fb-r-card);
    background: var(--fb-surface);
}

.fb-toolbar-count {
    margin-left: auto;
    font-family: var(--fb-mono);
    font-size: var(--fb-fs-11);
    color: var(--fb-ink-faint);
}

/* Mud держит на .mud-input-control «flex: 1 1 auto» — в своей флекс-строке поле из-за этого
   растягивается на весь остаток ширины: заданные ему 300px работают лишь как отправная точка роста,
   а кнопки уезжают к правому краю. Ширину задаёт Style поля, растягиваться ему здесь незачем. */
.fb-toolbar > .mud-input-control,
.fb-toolbar > .mud-select,
.fb-field-row > .mud-input-control,
.fb-field-row > .mud-select {
    flex: 0 0 auto;
}

/* Шапка таблицы липнет к верху прокручиваемой середины: на сотне моделей без неё непонятно, что за
   колонка перед глазами. */
.fb-main .mud-table-sticky-header thead th,
.fb-main .mud-table-head-bordered thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--fb-bg);
}

/* Пустой список — приглашение к действию, а не сообщение об отсутствии данных. */
.fb-empty {
    padding: 40px 16px;
    text-align: center;
    color: var(--fb-ink-dim);
    font-size: var(--fb-fs-13);
}

.fb-empty-title {
    margin-bottom: 4px;
    font-family: var(--fb-ui);
    font-size: var(--fb-fs-14);
    font-weight: 600;
    color: var(--fb-ink);
}

/* ---------- секция настроек ---------- */

/* Настройки — не пять одинаковых плит подряд, а список разделов с общей левой колонкой заголовков:
   так видно, что раздел про одно, а поля справа — его содержимое. */
.fb-section { margin-bottom: 12px; padding: 14px 16px; }

.fb-section-head {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin-bottom: 4px;
}

.fb-section-title {
    font-family: var(--fb-ui);
    font-size: var(--fb-fs-14);
    font-weight: 600;
    color: var(--fb-ink);
}

.fb-section-note {
    margin-bottom: 12px;
    font-size: var(--fb-fs-12);
    line-height: var(--fb-lh-text);
    color: var(--fb-ink-dim);
    max-width: 78ch;
}

.fb-field-row {
    display: flex;
    align-items: flex-end;
    gap: 8px;
    flex-wrap: wrap;
}

/* Ряд выравнивается по нижнему краю ПОЛЯ, и никаких подобранных отступов для этого не нужно.

   Мешали ровно две вещи, обе — собственная геометрия Mud, а не разная высота блоков:

   1. Подсказка под полем есть не у всех соседей (у пароля прокси есть, у логина нет), и при
      выравнивании по низу она опускала своё поле относительно остальных. Поэтому подсказка выведена
      из потока: она висит под контролом, а высоту ряда больше не определяет. Место под неё
      резервирует padding ряда — иначе она налезла бы на следующий блок.
   2. У `.mud-input-control` свои `margin-top: 8px` и `margin-bottom: 4px`. При выравнивании по низу
      сходятся ГРАНИЦЫ МАРГИН-БОКСОВ, поэтому нижние 4px уводили видимый край поля на те же 4px выше
      кнопки — расхождение маленькое, но заметное, потому что рядом стоит прямая вертикаль рамки.

   `!important` тут потому, что оба маргина Mud задаёт селектором специфичнее двух классов; правило
   действует только внутри своих контейнеров, поэтому на остальной интерфейс не влияет. */
.fb-field-row .mud-input-control,
.fb-toolbar .mud-input-control {
    position: relative;
    margin-top: 0 !important;
    margin-bottom: 0 !important;
}

.fb-field-row .mud-input-helper-text,
.fb-toolbar .mud-input-helper-text {
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 3px;
}

.fb-field-row:has(.mud-input-helper-text),
.fb-toolbar:has(.mud-input-helper-text) { padding-bottom: 18px; }

/* Замаскированный ключ — машинное значение, поэтому моноширинный тег, как ключ артефакта (§8.1). */
.fb-secret {
    font-family: var(--fb-mono);
    font-size: var(--fb-fs-11);
    line-height: 1;
    padding: 4px 7px;
    border-radius: var(--fb-r-chip);
    border: 1px solid var(--fb-line);
    background: var(--fb-sunken);
    color: var(--fb-ink-dim);
    white-space: nowrap;
}

/* ---------- вход и регистрация ---------- */

/* Отдельный каркас: у форм входа нет ни рельса, ни топбара приложения — человек ещё не внутри.
   Сетка на фоне — та самая единственная текстура системы, здесь она отделяет «порог» от «улицы». */
.fb-auth {
    position: relative;
    display: grid;
    place-items: center;
    min-height: 100vh;
    padding: 24px;
    background-color: var(--fb-bg);
}

/* Угол окна входа: сюда становится переключатель темы. Абсолютом, а не в потоке — карточка
   отцентрована по обеим осям, и любой сосед в потоке сместил бы её. */
.fb-auth-corner {
    position: absolute;
    top: 16px;
    right: 16px;
}

.fb-auth-card {
    width: 100%;
    max-width: 380px;
    padding: 26px 26px 22px;
    border: 1px solid var(--fb-line);
    border-radius: var(--fb-r-page);
    background: var(--fb-grad);
    box-shadow: var(--fb-shadow);
}

.fb-auth-brand { margin-bottom: 20px; display: block; }

.fb-auth-title {
    font-family: var(--fb-display);
    font-size: var(--fb-fs-26);
    font-weight: 800;
    line-height: var(--fb-lh-head);
    letter-spacing: var(--fb-tr-head);
    color: var(--fb-ink);
}

.fb-auth-note {
    margin: 6px 0 18px;
    font-size: var(--fb-fs-13);
    line-height: var(--fb-lh-text);
    color: var(--fb-ink-dim);
}

.fb-auth-fields { display: grid; gap: 12px; }

.fb-auth-error {
    margin-top: 12px;
    padding: 8px 10px;
    border-radius: var(--fb-r-in);
    background: var(--fb-danger-soft);
    color: var(--fb-danger);
    font-size: var(--fb-fs-12);
    line-height: var(--fb-lh-text);
}

.fb-auth-foot {
    margin-top: 18px;
    padding-top: 14px;
    border-top: 1px solid var(--fb-line);
    font-size: var(--fb-fs-12);
    color: var(--fb-ink-dim);
    text-align: center;
}

.fb-auth-foot a { color: var(--fb-primary); text-decoration: none; }
.fb-auth-foot a:hover { text-decoration: underline; }

/* Второй способ входа. Не в подвале карточки: это равноправная дорога, а не сноска, поэтому стоит
   сразу под кнопкой — там, где человек ищет её, не найдя пароля в памяти. */
.fb-auth-alt {
    margin-top: 10px;
    font-size: var(--fb-fs-12);
    text-align: center;
}

.fb-auth-alt a { color: var(--fb-primary); text-decoration: none; }
.fb-auth-alt a:hover { text-decoration: underline; }

/* Согласие с условиями. Кегль мельче полей формы, но не мельче подписей: это не мелкий шрифт из
   договора, а строка, которую человек должен прочитать. */
.fb-auth-consent {
    font-size: var(--fb-fs-12);
    line-height: var(--fb-lh-text);
    color: var(--fb-ink-dim);
}

.fb-auth-consent a { color: var(--fb-primary); text-decoration: none; }
.fb-auth-consent a:hover { text-decoration: underline; }

/* Плашка «подтвердите почту» в кабинете. Прижата к верху середины и не липкая: она сообщает о
   состоянии, а не требует немедленного действия, и закрывать ею содержимое страницы незачем. */
.fb-confirm-banner { margin-bottom: 16px; }

/* Плашка «сервис недоступен» стоит там же и ведёт себя так же — отступ у них общий по смыслу, но
   класс свой: это разные сообщения, и однажды одно из них захочется двигать отдельно. */
.fb-service-banner { margin-bottom: 16px; }

/* Подробность для администратора — тем же кеглем, но приглушённо: это сноска к сообщению, а не
   вторая его половина. */
.fb-service-detail {
    display: block;
    margin-top: 4px;
    opacity: 0.85;
}

.fb-confirm-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
}

/* Текст забирает свободное место, поэтому кнопки не разъезжаются по ширине окна. */
.fb-confirm-text { flex: 1 1 260px; }

/* Шести цифрам широкое поле ни к чему, а растянутое выглядит как поле для фразы. */
.fb-confirm-code { flex: 0 0 140px; }

/* Разделитель «или». Линия с надписью посередине, а не слово между двумя блоками: без линии оно
   читается как заголовок следующего раздела. */
.fb-auth-or {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 18px 0 14px;
    font-size: var(--fb-fs-11);
    color: var(--fb-ink-faint);
}

.fb-auth-or::before,
.fb-auth-or::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
    background: var(--fb-line);
}

/* Внешние входы. Кнопки стоят до того, как заработают: место под них решается сейчас, вместе с
   раскладкой формы, а не тогда, когда провайдер будет подключён. Отключённая кнопка честно говорит
   «пока нельзя» — в отличие от кнопки, которой нет. */
.fb-oauth {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 8px;
}

.fb-oauth-btn {
    display: grid;
    place-items: center;
    height: 38px;
    border: 1px solid var(--fb-line);
    border-radius: var(--fb-r-in);
    background: var(--fb-sunken);
    color: var(--fb-ink-dim);
    cursor: pointer;
    transition: border-color .12s ease, color .12s ease;
}

.fb-oauth-btn:hover:not(:disabled) { border-color: var(--fb-line-hi); color: var(--fb-ink); }
.fb-oauth-btn:focus-visible { outline: none; box-shadow: var(--fb-ring); }
.fb-oauth-btn:disabled { opacity: .3; cursor: default; }
.fb-oauth-btn svg, .fb-oauth-btn img { width: 17px; height: 17px; }

/* ---------- узкие окна ----------

   ДВЕ ступени, и обе про то, чего не хватает.

   ≤900px не хватает ШИРИНЫ: вертикальный рельс в 208 точек забирает половину полезной. Он уезжает
   за левый край и вызывается бургером.

   ≤560px не хватает ещё и ВЫСОТЫ: там снимаются поля и скругления, а шапка страницы складывается
   в столбик.

   Горизонтальная лента под топбаром здесь когда-то была — пункты те же, раскладка другая. Она не
   выжила по трём причинам, и все три стоит помнить, чтобы не завести её снова:
   1. Пунктов девять. В 414 точек влезает четыре, остальные уходят за правый край в прокрутку без
      всякого признака, что там что-то есть. «Тариф и баланс» — куда человек идёт, увидев пустой
      баланс, — оказывался невидим ровно тогда, когда нужен.
   2. Последние разговоры — столбик, и в строке они разваливались наружу, поверх содержимого.
   3. Лента съедала 55 точек постоянной высоты на той оси, которой на телефоне и так нет. */

@media (max-width: 900px) {
    .fb-burger { display: grid; }

    /* Подпись раздела уходит: «Кабинет» и «Администрирование» видно по составу рельса, а место в
       топбаре нужнее балансу. */
    .fb-topbar-scope { display: none; }

    /* Рельс — панель поверх содержимого, а не колонка рядом с ним. `fixed`, а не `absolute`:
       считать его положение от прокручиваемого предка значило бы возить панель вместе с текстом.

       Ширина 300 точек, а не прежние 208: место здесь больше не отнимается у содержимого, и
       названия разговоров наконец помещаются целиком, а не обрываются на третьем слове. */
    .fb-nav {
        position: fixed;
        top: var(--fb-topbar-h);
        left: 0;
        bottom: 0;
        z-index: 40;
        width: min(84vw, 300px);
        padding: 10px 10px 16px;
        border-right: 1px solid var(--fb-line);
        box-shadow: var(--shadow-dialog);
        transform: translateX(-100%);
        /* visibility снимается с задержкой в длину переезда: иначе панель исчезает мгновенно, и
           обратного движения не видно вовсе. Она обязана исчезать, а не просто уезжать, — иначе
           Tab уводит фокус в невидимое меню за краем экрана. */
        visibility: hidden;
        transition:
            transform var(--duration-base) var(--ease-standard),
            visibility 0s linear var(--duration-base);
    }

    .fb-shell.nav-open .fb-nav {
        transform: none;
        visibility: visible;
        transition: transform var(--duration-base) var(--ease-standard);
    }

    .fb-nav-scrim {
        display: block;
        position: fixed;
        inset: var(--fb-topbar-h) 0 0 0;
        z-index: 35;
        background: var(--fb-overlay);
        opacity: 0;
        pointer-events: none;
        transition: opacity var(--duration-base) var(--ease-standard);
    }

    .fb-shell.nav-open .fb-nav-scrim { opacity: 1; pointer-events: auto; }

    /* Палец — не курсор: 32 точки хватало мыши, но не подушечке. Тот же рост получают и разговоры:
       промах по соседней строке здесь означает «открыл чужой разговор». */
    .fb-nav .mud-nav-link { min-height: 44px; }
    .fb-nav-sub { padding-top: 10px; padding-bottom: 10px; }

    .fb-main { padding: 14px 14px 20px; }
}

@media (prefers-reduced-motion: reduce) {
    .fb-nav,
    .fb-shell.nav-open .fb-nav,
    .fb-nav-scrim { transition: none; }
}

@media (max-width: 560px) {
    /* Шапка страницы складывается: заголовок и кнопки в одну строку не помещаются, а прижатые
       вправо кнопки на телефоне ещё и дальше всего от большого пальца. */
    .fb-head { flex-direction: column; align-items: stretch; gap: 10px; }
    .fb-head-actions { margin-left: 0; justify-content: flex-start; }
    .fb-head-actions > .mud-button-root { flex: 1 1 auto; }

    /* Поля фильтров в узкой полосе растягиваются на всю ширину: у Mud они несут собственную ширину
       в Style, и без сброса поле в 300 точек торчит за край экрана. */
    .fb-toolbar { padding: 10px; }
    .fb-toolbar > .mud-input-control,
    .fb-toolbar > .mud-select,
    .fb-head-actions > .mud-input-control,
    .fb-head-actions > .mud-select,
    .fb-field-row > .mud-input-control,
    .fb-field-row > .mud-select {
        flex: 1 1 100%;
        width: auto !important;
        min-width: 0;
    }
    .fb-toolbar-count { margin-left: 0; }

    .fb-main { padding: 12px 12px 18px; }
    .fb-topbar { gap: 8px; padding: 0 10px; }

    /* Баланс ужимается до числа: слово «кредитов» знает тот, кто уже видел эту плашку, а места в
       414 точках на него нет — оно вытесняло инициал за край. */
    .fb-credits-label { display: none; }
}

/* Значок провайдера до появления файлов иконок: моноширинные буквы того же кегля, что займёт svg. */
.fb-oauth-mark {
    font-family: var(--fb-mono);
    font-size: var(--fb-fs-11);
    font-weight: 500;
    letter-spacing: 0;
}
