/* ── CyberCore — стили поверх MudBlazor ── */

/* Длинные адреса (AgentUrl интегрированных агентов, DID, ссылки визиток)
   переносятся на новые строки вместо выхода за границы карточек/таблиц. */
code, a, .mud-typography {
    overflow-wrap: anywhere;
    word-break: break-word;
}

/* Используем переменные MudBlazor для фона и текста */
html, body {
    background-color: var(--mud-palette-background) !important;
    color: var(--mud-palette-text-primary) !important;
    transition: background-color 0.3s ease, color 0.3s ease;
    font-family: 'JetBrains Mono', Consolas, monospace;
}

/* JetBrains Mono — программистский шрифт с лигатурами: последовательности символов
   (напр. «!!!!») подменяются комбинированными глифами и отображаются некорректно
   (в тёмной теме — «цветом фона»). Отключаем лигатуры/контекстные альтернативы ВЕЗДЕ,
   включая поля ввода; !important и явные селекторы — чтобы обыграть возможный
   font-шорткат/MudBlazor-стиль на конкретном элементе. */
html, body, .mud-typography, .mud-input, .mud-input-slot, .mud-input-root,
input, textarea, select, button, code, pre {
    font-variant-ligatures: none !important;
    font-feature-settings: "liga" 0, "calt" 0 !important;
}

/* Убираем статические фоны для навбара и других элементов */
.navbar {
    background: transparent !important;
    backdrop-filter: none !important;
    border-bottom: none !important;
}

/* Кастомные карточки — только если они не MudBlazor */
.card {
    border-radius: var(--mud-default-borderradius);
    box-shadow: var(--mud-elevation-1);
    transition: box-shadow 0.2s, border-color 0.2s;
}

/* Тост-уведомления (оставляем, они свои) */
.cc-toaster {
    position: fixed;
    top: 4.5rem;
    right: 1rem;
    z-index: 1080;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    max-width: min(360px, calc(100vw - 2rem));
}

.cc-toast {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.65rem 0.75rem;
    border-radius: var(--mud-default-borderradius);
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-divider);
    border-left: 4px solid var(--mud-palette-primary);
    box-shadow: var(--mud-elevation-3);
    font-size: 0.875rem;
    animation: cc-toast-in 0.2s ease-out;
}

.cc-toast-msg {
    flex: 1;
    color: var(--mud-palette-text-primary);
}

.cc-toast-close {
    border: none;
    background: none;
    color: var(--mud-palette-text-secondary);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    padding: 0 0.15rem;
}

    .cc-toast-close:hover {
        color: var(--mud-palette-text-primary);
    }

.cc-toast-info {
    border-left-color: var(--mud-palette-info);
}

.cc-toast-success {
    border-left-color: var(--mud-palette-success);
}

.cc-toast-warning {
    border-left-color: var(--mud-palette-warning);
}

.cc-toast-error {
    border-left-color: var(--mud-palette-error);
}

@keyframes cc-toast-in {
    from {
        opacity: 0;
        transform: translateX(1rem);
    }

    to {
        opacity: 1;
        transform: translateX(0);
    }
}

/* Unread badge */
.unread-badge {
    display: inline-block;
    min-width: 1.3rem;
    height: 1.3rem;
    line-height: 1.3rem;
    border-radius: 0.65rem;
    background: var(--mud-palette-error);
    color: white;
    font-size: 0.7rem;
    text-align: center;
    padding: 0 0.3rem;
    margin-left: 0.25rem;
    vertical-align: middle;
}

/* MudBlazor: убрать подчёркивание у бренда-ссылки */
.brand-logo {
    text-decoration: none !important;
}

/* Blazor error (оставляем, он отдельный) */
#blazor-error-ui {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0,0,0,0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

/* === Аватар с blur-фоном (горизонтальные изображения) === */
.avatar-frame {
    position: relative;
    overflow: hidden;
    border-radius: 50%;
    flex-shrink: 0;
}

.avatar-blur {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    filter: blur(10px);
    transform: scale(1.3);
}

.avatar-img {
    position: relative;
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* === Плашка «экспериментальная альфа» (AlphaNotice.razor) ===
   Плашка — В ПОТОКЕ, не position:fixed. Раньше она висела поверх контента и перекрывала строку
   табов коммуникатора: клик по «Потоку» попадал в плашку, вкладка не переключалась (баг 2026-10-18).
   Чтобы «остаток экрана» у панелей остался точным, высоту плашки меряет JS
   (cybercoreAlphaNoticeHeight) и кладёт в --alpha-notice-h — её вычитает .comm-panel. */
.alpha-notice {
    padding: 0 0.5rem 0.5rem;
}

/* === Переключатель языка (LanguageFlag.razor) ===
   Флаг — inline SVG (emoji-флаги на Windows не имеют глифов → «GB»/«RU» буквами).
   Тонкая обводка нужна, чтобы белая полоса RU-флага не сливалась со светлым фоном. */
.lang-switch {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

.lang-flag {
    display: block;
    width: 1.5rem;
    height: 1rem;
    border-radius: 2px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.18);
    flex-shrink: 0;
}

.lang-switch-code {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1;
}

/* === Аватар-миниатюра (AvatarThumb): квадрат 100×100 со скруглёнными углами ===
   MudAvatar в MudBlazor 9.x НЕ имеет параметра Image — аватар рисуем
   обычным <img>, чтобы картинка реально отображалась (Image сплэтился
   бы на div как мёртвый атрибут, и круг оставался серым). */
.avatar-thumb {
    display: block;
    object-fit: cover;
    border-radius: 8px;
    flex-shrink: 0;
    background-color: var(--mud-palette-background-grey);
}

/* === Индикатор состояния контрагента (огонёк) ===
   Три состояния: зелёный (агент+принципал онлайн), серый (агент онлайн,
   принципал офлайн), красный (агент недоступен). Зелёный/красный идут через
   MudBlazor (Color.Success/Error → mud-success-text/mud-error-text), а «серый»
   (Color.Default → mud-icon-default) полагался на тему и мог сливаться с
   текстом/фоном. Задаём явный muted-цвет, чтобы серый читался однозначно. */
.agent-status-indicator .mud-icon-default {
    color: var(--mud-palette-text-secondary) !important;
}

/* ── Индикатор загрузки Blazor (index.html #app + App.razor «словарь не готов») ──
   Без этих стилей SVG-кружки отрисовываются нестилизованными — чёрный «блин»
   со скруглением в левом верхнем углу (~1/3 экрана) до старта приложения.
   Стили — из стандартного шаблона Blazor WASM: центрированный прогресс-ринг. */
.loading-progress {
    position: relative;
    display: block;
    width: 8rem;
    height: 8rem;
    margin: 20vh auto 1rem auto;
}

    .loading-progress circle {
        fill: none;
        stroke: #e0e0e0;
        stroke-width: 0.6rem;
        transform-origin: 50% 50%;
        transform: rotate(-90deg);
    }

        .loading-progress circle:last-child {
            stroke: #0d6efd;
            stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
            transition: stroke-dasharray 0.05s ease-in-out;
        }

.loading-progress-text {
    position: absolute;
    text-align: center;
    font-weight: bold;
    inset: calc(20vh + 3.25rem) 0 auto 0;
}

    .loading-progress-text:after {
        content: var(--blazor-load-percentage-text, "Загрузка…");
    }

/* === Коммуникатор (Communication.razor) ===
   Панель занимает ОСТАТОК высоты экрана → страница НЕ скроллится (одна прокрутка —
   внутри списка/переписки, без вложенного скролла).
   --comm-chrome-h — фактическая высота хрома НАД панелями (appbar + табы + отступы +
   плашка альфы). Значение пишет JS (`cybercoreChromeHeight`), потому что константа
   ломалась при смене appbar/баннера/зума; 156px — только первая отрисовка до запуска JS.
   --comm-bottom-h — нижний отступ контейнера страницы, чтобы панель не выталкивала скролл. */
:root {
    --comm-chrome-h: 156px;
    --comm-bottom-h: 0px;

    /* === UI-токены (U0) ===
       Один набор отступов/радиусов/высот вместо магических px по файлам: панели
       выравниваются по одним и тем же числам, правки в одном месте не «пляшут».
       Сетка отступов кратна 4 — так элементы стыкуются без половин пикселя. */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-6: 24px;

    --radius-sm: 8px;
    --radius-md: 12px;
    --radius-lg: 16px;

    /* Высоты контролов: 32 — компактные (внутри панелей), 40 — основные кнопки/поля.
       --hit-target — минимальная зона нажатия для иконочных кнопок (на тач-устройствах
       увеличивается до 44px, см. медиазапрос ниже). */
    --control-h-sm: 32px;
    --control-h-md: 40px;
    --hit-target: 40px;

    /* Заголовок панели: фиксированная высота — панели не «пляшут» при появлении
       действий/кнопки «назад» (пустое место резервируется, а не сдвигает ленту). */
    --panel-header-h: 48px;
    /* Зазор между панелями и внутри панели. */
    --content-gap: var(--space-2);
}

/* На тач-устройствах зона нажатия иконочных кнопок — от 44px (палец, а не курсор). */
@media (pointer: coarse) {
    :root {
        --hit-target: 44px;
    }
}

/* Заголовок панели (AppPanelHeader): одна высота на все панели — переписка, файлы,
   участники, ветка. Заголовки больше не «скачут», когда кнопок становится больше. */
.cc-panel-header {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-height: var(--panel-header-h);
    padding: 0 var(--space-2);
    box-sizing: border-box;
    flex-wrap: nowrap;
    /* P2 (U8): корень заголовка тоже сжимается — иначе длинный заголовок с действиями
       распирает панель и появляется горизонтальный скролл на узком экране. На ≤400px
       (см. медиазапрос ниже) строка переносится, чтобы кнопки не «выдавливали» текст. */
    min-width: 0;
}

.cc-panel-header-title {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;         /* длинное имя не распирает панель */
}

.cc-panel-header-title > .cc-panel-header-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cc-panel-header-actions {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    margin-inline-start: auto;
    flex-shrink: 0;
}

/* Пустое состояние (AppEmptyState): иконка, текст и подсказка-действие по центру. */
.cc-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-6) var(--space-4);
    text-align: center;
    color: var(--mud-palette-text-secondary);
}

.comm-panel {
    /* Высота = остаток экрана: хром и нижний отступ меряет JS (--comm-chrome-h/--comm-bottom-h).
       min-height: 0 — иначе на низких экранах (ландшафт телефона, зум) панель распирает
       страницу и появляется второй скролл. */
    height: calc(100dvh - var(--comm-chrome-h) - var(--comm-bottom-h));
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    /* Якорь для панели ветки (position:absolute внутри панели переписки). */
    position: relative;
}

/* === U1: один экран — один скролл ===
   Цепочка flex от контейнера страницы до ленты обязана иметь min-height: 0: без этого
   содержимое распирает панель, и страница начинает прокручиваться вместе с лентой. */
.comm-page,
.comm-page .mud-tabs-panels,
.comm-page .mud-tabs-panel-content,
.comm-page .mud-grid,
.comm-page .mud-grid-item,
.comm-page .comm-panel,
.comm-page .comm-col-split {
    min-height: 0;
}

/* Колонка-ячейка сетки — тоже flex-колонка, чтобы панель занимала её целиком. */
.comm-page .mud-grid-item {
    display: flex;
    flex-direction: column;
}

/* Единственный вертикальный скролл — у ленты/списка. overscroll-behavior не даёт
   «протекать» прокрутке на страницу, scrollbar-gutter держит ширину при появлении полосы
   (иначе на появлении/исчезновении скроллбара колонки дёргаются). */
.comm-feed,
.comm-list-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-gutter: stable;
}

.comm-feed {
    padding: 1rem;
}

/* === Модалка управления комнатой: одна прокрутка ===
   Внутри .mud-dialog-content стояли списки с max-height/overflow-y (участники для
   добавления, ссылки, журнал) — получалось два-три вложенных скролла, и колесо
   «залипало» на внутреннем списке. Теперь прокручивается только тело диалога.
   overscroll-behavior: contain — прокрутка диалога не «протекает» на страницу под ним. */
.room-dialog-list {
    display: block;
}

.mud-dialog-content {
    overscroll-behavior: contain;
}

/* === Действия под сообщением: лайк / ответ / ветка ===
   Компактные кнопки-иконки: серые по умолчанию, «своя» реакция — акцентная.
   Живут в мета-строке (.msg-meta) под пузырём вместе с датой/временем. */
.msg-actions {
    display: inline-flex;
    align-items: center;
    gap: 0.15rem;
    flex-shrink: 0;
}

/* Мета-строка под пузырём: «21.10.2026 14:05» + кнопки. Отделена от пузыря,
   поэтому действия больше не занимают ширину рядом с текстом (важно для мобилы). */
.msg-meta {
    margin-top: 0.1rem;
    min-height: 1.5rem;
}

.msg-time {
    font-size: 0.68rem;
    line-height: 1.2;
    color: var(--mud-palette-text-secondary);
    opacity: 0.85;
    white-space: nowrap;
}

.msg-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.2rem;
    /* Зона попадания не меньше 2rem: кнопки идут вплотную, и на телефоне палец
       легко попадает в соседнюю («ответить»/ветка) вместо лайка. */
    min-width: 2rem;
    min-height: 2rem;
    padding: 0.15rem 0.3rem;
    border: none;
    border-radius: 999px;
    background: transparent;
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
    line-height: 1;
}

.msg-action:hover {
    background: var(--mud-palette-action-default-hover);
    color: var(--mud-palette-text-primary);
}

.msg-action-active {
    color: var(--mud-palette-primary);
}

.msg-action-count {
    font-size: 0.72rem;
    font-weight: 600;
}

/* Цитата «в ответ на …» внутри пузыря. */
.msg-quote {
    display: block;
    margin-bottom: 0.25rem;
    padding-inline-start: 0.4rem;
    border-inline-start: 2px solid var(--mud-palette-primary);
    opacity: 0.85;
    font-size: 0.72rem;
}

/* Ссылка внутри сообщения: активна (клик открывает в новой вкладке), но не
   «выпрыгивает» из пузыря — цвет наследуется от темы, длинный адрес переносится
   по любому символу, иначе он растягивает ленту и появляется горизонтальный скролл. */
.msg-link {
    color: var(--mud-palette-primary);
    text-decoration: underline;
    text-underline-offset: 2px;
    overflow-wrap: anywhere;
    word-break: break-word;
}

.msg-link:hover,
.msg-link:focus-visible {
    text-decoration-thickness: 2px;
}

/* В своём пузыре фон — primary, поэтому ссылка того же цвета была бы невидимой:
   наследуем цвет текста пузыря и оставляем только подчёркивание. */
.message-mine .msg-link {
    color: inherit;
}

/* В комнате свой пузырь тоже акцентный, но без класса .message-mine. */
.msg-row .mud-paper[style*="mud-palette-primary"] .msg-link {
    color: inherit;
}

.msg-link:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
    border-radius: 2px;
}

/* Полоса «вы отвечаете на …» над полем ввода. */
.msg-reply-bar {
    background: var(--mud-palette-background-grey);
}

/* === Панель ветки: шторка поверх переписки (десктоп) / весь экран (мобила) === */
/* Подложка под панелью: клик в любом месте вне ветки закрывает её (пожелание из комнаты
   тестирования 08.11.2026 — «выход из ветки не только по стрелке назад»). Прозрачная:
   переписка остаётся читаемой, меняется только область клика. */
.thread-backdrop {
    position: absolute;
    inset: 0;
    z-index: 1;
    background: transparent;
}

.thread-panel {
    position: absolute;
    inset: 0 0 0 auto;
    width: min(26rem, 100%);
    display: flex;
    flex-direction: column;
    background: var(--mud-palette-surface);
    /* Мягкая, но заметная рамка: панель читается как отдельное окно, а не как край ленты. */
    border: 1px solid var(--mud-palette-lines-default);
    box-shadow: -6px 0 18px rgba(0, 0, 0, 0.10);
    z-index: 2;
}

.thread-header {
    display: flex;
    align-items: center;
    padding: 0.35rem 0.5rem;
    flex-shrink: 0;
}

.thread-messages {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-gutter: stable;
    padding: 0.75rem;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.thread-message {
    padding: 0.4rem 0.6rem;
    border-radius: 10px;
    background: var(--mud-palette-background-grey);
}

@media (max-width: 959.98px) {
    .thread-panel {
        width: 100%;
        box-shadow: none;
        /* На мобиле панель занимает экран — рамка по краям экрана лишняя, оставляем только верхнюю. */
        border: none;
        border-block-start: 1px solid var(--mud-palette-divider);
    }
}

/* Строка-превью ветки под корневым сообщением: самих ответов в ленте нет (иначе дублируются внизу),
   вход в ветку — здесь: «↳ Имя: фрагмент · N отв.». */
.msg-thread-preview {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    max-width: 75%;
    margin-top: 0.15rem;
    padding: 0.1rem 0.45rem;
    border: none;
    border-radius: 999px;
    background: transparent;
    color: var(--mud-palette-text-secondary);
    font-size: 0.72rem;
    line-height: 1.3;
    text-align: start;
    cursor: pointer;
}

.msg-thread-preview:hover {
    background: var(--mud-palette-action-default-hover);
    color: var(--mud-palette-text-primary);
}

.msg-thread-preview-author {
    font-weight: 600;
    flex-shrink: 0;
}

.msg-thread-preview-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.msg-thread-preview-count {
    flex-shrink: 0;
    opacity: 0.8;
}

/* Превью ветки с непрочитанными ответами: акцент + пометка «1 новый». */
.msg-thread-preview-new {
    color: var(--mud-palette-primary);
    font-weight: 600;
}

.msg-thread-preview-unread {
    flex-shrink: 0;
    padding: 0 0.35rem;
    border-radius: 999px;
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    font-size: 0.68rem;
    font-weight: 600;
}

/* Плашка-якорь в шапке ленты: «Новые ответы: N» → ведёт в самую свежую ветку. */
.msg-thread-anchor {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-inline-start: 0.5rem;
    padding: 0.15rem 0.5rem;
    border: 1px solid var(--mud-palette-primary);
    border-radius: 999px;
    background: transparent;
    color: var(--mud-palette-primary);
    font-size: 0.75rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
}

.msg-thread-anchor:hover {
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
}

/* === Панель файлов переписки (FilesPanel): шторка / закреплённая колонка === */
.comm-files-drawer {
    position: absolute;
    inset: 0 0 0 auto;
    width: min(24rem, 100%);
    display: flex;
    flex-direction: column;
    z-index: 5;
    box-shadow: -2px 0 12px rgba(0, 0, 0, 0.18);
}

.comm-files-drawer .comm-panel {
    height: 100%;
    min-height: 0;
}

/* «Прикрепить файл» в панели файлов: <label> вокруг скрытого InputFile (как в композере).
   Кнопку-<button> внутрь label класть нельзя — она перехватывает клик и выбор не открывается. */
/* === Зона выбора файла (U3) ===
   Пунктирная область, кнопка «Выбрать …», перетаскивание. Рамка подсвечивается, когда
   файл тащат над зоной: .app-dropzone-over ставит JS на dragenter/dragover. */
.app-dropzone {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2, 8px);
    padding: var(--space-4, 16px);
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: var(--radius-md, 12px);
    background: var(--mud-palette-background);
    text-align: center;
}

.app-dropzone-over {
    border-color: var(--mud-palette-primary);
    background: var(--mud-palette-action-default-hover);
}

.app-dropzone-icon {
    color: var(--mud-palette-text-secondary);
}

.app-dropzone-error {
    font-size: 0.8rem;
}

/* Иконки-пикеры вложения в композере: подпись живёт в title/aria-label, зона нажатия — как у кнопок. */
.comm-attach-icon {
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--hit-target, 40px);
    min-height: var(--hit-target, 40px);
    padding: 4px;
    border-radius: 50%;
}

.comm-attach-icon:hover {
    background: var(--mud-palette-action-default-hover);
}

.comm-attach-error {
    font-size: 0.8rem;
}

.comm-attach-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.25rem 0.7rem;
    border: 1px solid var(--mud-palette-primary);
    border-radius: 4px;
    color: var(--mud-palette-primary);
    font-size: 0.8rem;
    font-weight: 500;
    line-height: 1.2;
    cursor: pointer;
    user-select: none;
}

.comm-attach-btn:hover {
    background: var(--mud-palette-action-default-hover);
}

@media (max-width: 959.98px) {
    .comm-files-drawer {
        width: 100%;
        box-shadow: none;
    }
}

/* Закреплённые панели: участники сверху / файлы снизу (высота — как у панелей коммуникатора). */
.comm-col-split {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    height: calc(100dvh - var(--comm-chrome-h) - var(--comm-bottom-h));
}

.comm-col-split .comm-panel {
    height: auto;
    flex: 1 1 0;
    min-height: 0;
}

/* Закреплённая панель файлов внутри колонки участников: на десктопе — вторая половина
   колонки, на мобиле не показывается вовсе (там файлы — шторка по кнопке 📎). */
.comm-files-pinned {
    display: flex;
    flex-direction: column;
    flex: 1 1 0;
    min-height: 0;
}

@media (max-width: 959.98px) {
    .comm-files-pinned {
        display: none !important;
    }
}

/* === U2: каркас «список / переписка / контекст» (личные сообщения в три колонки) ===
   На lg+ ширину колонок задаёт MudGrid: список 3, переписка 6, контекст (файлы) 3.
   Ниже lg боковых колонок нет — работает drill-down: список → переписка → контекст.
   min-width: 0 у каждой колонки и её flex-детей: без этого длинное имя переписки или
   имя файла распирают колонку и появляется горизонтальный скролл (проверка — 320px). */
.comm-page .comm-conv-col,
.comm-page .comm-context-col {
    min-width: 0;
}

.comm-context-col {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

/* Экран контекста — тот же .comm-panel: высота = остаток экрана, как у соседних колонок. */
.comm-context-col > .comm-panel {
    flex: 1 1 auto;
    min-height: 0;
}

/* Ниже lg: одновременно виден РОВНО ОДИН экран. Контекст показывается только тогда,
   когда пользователь явно его открыл (класс comm-context-mobile-open ставит страница) —
   иначе drill-down «список → переписка → контекст» открывался бы сразу с конца. */
@media (max-width: 959.98px) {
    .comm-page .comm-context-col {
        display: none !important;
    }

    .comm-page .comm-context-col.comm-context-mobile-open {
        display: flex !important;
    }

    /* Тулбары панелей: длинный заголовок не распирает панель — действия уходят на вторую строку. */
    .comm-page .mud-toolbar {
        flex-wrap: wrap;
        row-gap: 0.25rem;
        min-width: 0;
    }

    /* Панель переписки на узком экране: меньше отступ у ленты, чтобы пузыри не упирались в края. */
    .comm-page .comm-feed {
        padding: 0.5rem;
    }
}

/* === U2: строка списка переписок — одна высота у всех ===
   Имя и превью — в одну строку с многоточием (полное значение в title), непрочитанные —
   компактный бейдж справа. Раньше счётчик был чипом под временем: строки «прыгали»
   по высоте, а длинное имя распирало колонку. */
.comm-conv-row {
    min-height: 3.5rem;
    padding-top: 0.25rem;
    padding-bottom: 0.25rem;
}

.comm-conv-line {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    min-width: 0;
    overflow: hidden;
}

.comm-conv-avatar {
    display: flex;
    flex: 0 0 auto;
}

/* Мин-ширина 0 обязательна: иначе flex-ребёнок не сжимается и text-overflow не работает. */
.comm-conv-main {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
}

.comm-conv-name-row {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    min-width: 0;
}

.comm-conv-name {
    font-size: 0.875rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.comm-conv-preview {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.comm-conv-side {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    justify-content: center;
    gap: 0.15rem;
    flex: 0 0 auto;
    max-width: 45%;
    margin-inline-start: 0.25rem;
    text-align: end;
}

.comm-conv-time {
    font-size: 0.7rem;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.comm-conv-marks {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 0.25rem;
}

.comm-conv-invite {
    font-size: 0.65rem;
    line-height: 1.4;
    padding: 0 0.35rem;
    border-radius: 999px;
    background: var(--mud-palette-warning);
    color: #4a3600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 6.5rem;
}

/* Бейдж непрочитанных: круглый счётчик справа. Высота фиксирована — строка не растёт. */
.comm-unread-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.25rem;
    height: 1.25rem;
    padding: 0 0.3rem;
    border-radius: 999px;
    background: var(--mud-palette-error);
    color: var(--mud-palette-error-text, #fff);
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    flex: 0 0 auto;
}
/* Подпись таба: на узких экранах прячем текст и оставляем только иконку + бейдж
   (полное название — в tooltip), иначе длинная надпись обрезается посреди слова. */
.tab-label {
    margin-inline-start: 0.4rem;
}

/* Строка поиска по перепискам: одна строка над фильтрами, не «съедает» список. */
.comm-search {
    padding: 0.25rem 0.5rem 0;
    flex-shrink: 0;
}

/* Поиск + сортировка в узкой панели участников: поле тянется, меню сортировки — иконкой. */
.comm-participants-tools {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.35rem 0.5rem;
    flex-shrink: 0;
}
.comm-participants-tools .mud-input-control {
    flex: 1 1 auto;
    min-width: 0;
}

/* === Мини-визитка участника (всплывающая подсказка) ===
   Самое главное о человеке: фото, имя, тип, роль, состояние и адрес. Ширина ограничена,
   длинные значения обрезаются — подсказка не должна расползаться за вьюпорт. */
.participant-card {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    /* P1 (U8): раньше фиксированный min-width:12rem распирал карточку на узком экране
       (320px) и появлялся горизонтальный скролл. Теперь карточка сжимается, но не шире
       90vw; длинные значения (имя/адрес/DID) переносятся по любому символу. */
    min-width: 0;
    max-width: min(18rem, 90vw);
    overflow-wrap: anywhere;
}

.participant-card-avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    overflow: hidden;
    flex-shrink: 0;
    background: var(--mud-palette-action-default-hover);
    font-weight: 600;
}

.participant-card-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.participant-card-row {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    min-width: 0;
}

.participant-card-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}

.participant-card-dot-green { background: var(--mud-palette-success); }
.participant-card-dot-gray { background: var(--mud-palette-text-disabled); }
.participant-card-dot-red { background: var(--mud-palette-error); }

.participant-card-address {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Строка фильтров списка переписок (Все / Личные / Комнаты). На узкой колонке
   чипы переносятся на вторую строку — горизонтальной прокрутки быть не должно. */
.comm-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    padding: 0.25rem 0.5rem 0.4rem;
    overflow: visible;
    flex-shrink: 0;
}

.comm-filters .mud-chip {
    flex-shrink: 0;
}

/* Иконка фильтра: на мобиле заменяет подпись (см. медиа-запрос ниже),
   на десктопе скрыта — там подписи видны целиком и лишняя ширина не нужна. */
.filter-icon {
    margin-inline-end: 0.25rem;
}

.filter-count {
    font-variant-numeric: tabular-nums;
}

@media (min-width: 960px) {
    /* Регрессия «на десктопе у фильтров появилась горизонтальная прокрутка»:
       иконки добавляли ~20px на чип, и в узкой колонке списка строка переставала
       помещаться. На десктопе оставляем только подписи со счётчиками. */
    .comm-filters .filter-icon {
        display: none;
    }
}

@media (max-width: 959.98px) {
    .tab-label {
        display: none;
    }

    /* Фильтры «Все / Личные / Комнаты»: на мобиле оставляем иконку + счётчик,
       подпись скрыта (полная — в aria-label/title). Так все три чипа влезают в строку
       и ничего не обрезается посреди слова. */
    .comm-filters {
        justify-content: center;
        gap: 0.5rem;
    }

    .comm-filters .filter-label {
        display: none;
    }

    .comm-filters .filter-icon {
        margin-inline-end: 0;
    }

    .comm-filters .filter-count {
        margin-inline-start: 0.3rem;
    }

    .comm-hide-mobile {
        display: none !important;
    }
}

/* === Утилиты, которых НЕТ в MudBlazor (после удаления Bootstrap) ===
   Использовались в разметке и молча не работали (no-op) — Bootstrap CSS в index.html
   не подключён, а MudBlazor определяет лишь часть утилит. Маппим на переменные темы MudBlazor. */
.text-muted, .text-secondary { color: var(--mud-palette-text-secondary) !important; }
.text-start { text-align: left !important; }
.text-center { text-align: center !important; }
.text-end { text-align: right !important; }
.text-success { color: var(--mud-palette-success) !important; }
.text-danger { color: var(--mud-palette-error) !important; }
.text-warning { color: var(--mud-palette-warning) !important; }
.text-info { color: var(--mud-palette-info) !important; }
.bg-primary { background-color: var(--mud-palette-primary) !important; color: var(--mud-palette-primary-text) !important; }
.bg-secondary { background-color: var(--mud-palette-secondary) !important; color: var(--mud-palette-secondary-text) !important; }
.bg-light { background-color: var(--mud-palette-background-grey) !important; color: var(--mud-palette-text-primary) !important; }
.bg-success { background-color: var(--mud-palette-success) !important; color: var(--mud-palette-success-text) !important; }
.bg-danger { background-color: var(--mud-palette-error) !important; color: var(--mud-palette-error-text) !important; }
.ms-1 { margin-left: 0.25rem !important; }
.ms-2 { margin-left: 0.5rem !important; }
.badge { display: inline-block; padding: 0.2em 0.55em; border-radius: 0.4rem; font-size: 0.75em; font-weight: 600; line-height: 1; background: var(--mud-palette-primary); color: var(--mud-palette-primary-text); }
.card-body { padding: 1rem; }
.card-title { margin: 0 0 0.5rem; font-size: 1.25rem; font-weight: 500; }

/* Высотные утилиты Bootstrap (использовались в разметке, не были определены). */
.h-100 { height: 100% !important; }

/* H4: строки большой загруженной истории — браузер не рендерит то, что вне экрана. */
.comm-room-row {
    content-visibility: auto;
    contain-intrinsic-size: auto 120px;
}

/* H2: разделитель «N непрочитанных» в ленте комнаты. */
.comm-unread-divider {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0.15rem 0 0.6rem;
    color: var(--mud-palette-primary);
    font-size: 0.8rem;
    font-weight: 600;
}
.comm-unread-divider::before,
.comm-unread-divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: currentColor;
    opacity: 0.35;
}

/* P2: статус ветки — компактный чип в мета-строке рядом с лайком/ответом/веткой.
   Раньше бейджи стояли над пузырём, и было непонятно, к какому сообщению относятся. */
.msg-status-slot {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    margin-inline-start: 0.15rem;
}

.msg-status {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    flex-wrap: wrap;
}

.comm-status-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.15rem;
    font-size: 0.68rem;
    line-height: 1.4;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    border: 1px solid rgba(0, 0, 0, 0.12);
    white-space: nowrap;
}

.comm-status-important { background: #fff4ce; color: #6b5300; border-color: #efd98b; }
.comm-status-done { background: #e7f5ea; color: #1f6b36; border-color: #b9dfc6; }
.comm-status-closed { background: #eceff1; color: #455a64; border-color: #cfd8dc; }

/* P2: свёрнутая закрытая ветка — одна строка-плашка, статус и меню остаются доступны. */
.comm-closed-plaque {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
    margin: 0.15rem 0 0.35rem;
    padding: 0.35rem 0.6rem;
    border: 1px solid rgba(0, 0, 0, 0.12);
    border-radius: 10px;
    background: rgba(0, 0, 0, 0.03);
    cursor: pointer;
    font-size: 0.82rem;
}

.comm-closed-plaque:hover { background: rgba(0, 0, 0, 0.06); }

.comm-thread-new {
    font-size: 0.68rem;
    padding: 0.05rem 0.35rem;
    border-radius: 999px;
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
}

/* ═══════════════════════════════════════════════════════════════════════
   W5 · U6 «эстетика и выравнивание» + U8 «адаптивность»
   ═══════════════════════════════════════════════════════════════════════ */

/* U6: единая высота тулбаров/заголовков панелей. Резервируем место, чтобы появление/
   исчезновение иконочных кнопок (и разная длина подписей ru/en) не меняли высоту строки
   и панели оставались выровнены по верхней границе. */
.comm-page .mud-toolbar,
.cc-panel-header {
    min-height: var(--panel-header-h);
}

.comm-page .mud-toolbar {
    box-sizing: border-box;
}

/* P2 (U8): иконочная кнопка-меню в ряду с AppIconButton (MudMenu активатор) — та же
   зона нажатия --hit-target, что и у соседних кнопок, иначе ряд «пляшет» по высоте. */
.comm-header-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--hit-target, 40px);
    min-height: var(--hit-target, 40px);
}

/* U6: имя отправителя над пузырём комнаты — одна строка с многоточием (полное — в title),
   длинное имя не распирает пузырь и ленту. */
.msg-sender-name {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* U6: строки участников в модалке управления комнатой — grid [имя 1fr] [действия auto].
   Меню «…» всегда прижато справа, чипы/селекты в зоне действий переносятся (flex-wrap).
   Раньше каждый элемент был отдельным flex-ребёнком — при длинном имени и трёх-четырёх
   кнопках строка «разъезжалась» и вылезала за диалог. */
.room-member-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    column-gap: var(--space-2);
    row-gap: var(--space-1);
    margin-bottom: var(--space-2);
}

.room-member-name {
    min-width: 0;
    overflow-wrap: anywhere;
}

.room-member-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: var(--space-1);
    min-width: 0;
}

/* U6: селекты роли/приглашения одной ширины (min 9rem, max 12rem) — строки участников
   и блок «добавить» выровнены, поля не «скачут» по ширине от значения к значению. */
.room-role-select {
    flex: 0 1 auto;
    min-width: 9rem;
    max-width: 12rem;
}

/* U6: вкладки модалки не меняют высоту контента — резервируем минимальную высоту тела,
   чтобы переключение «Участники/Права/…» не дёргало диалог. */
.room-tab-panel {
    box-sizing: border-box;
    min-height: 16rem;
}

/* == U8: самая узкая ширина (320 px) и зум 200 %. ==
   Ниже 400px уменьшаем отступы/зазоры тулбаров, жмём иконочные кнопки и прячем вторичные
   иконки (закрепить/копировать историю), чтобы ряд действий не выдавливал заголовок и не
   появлялся горизонтальный скролл. Перенос разрешаем только тут — на десктопе заголовки
   остаются в одну строку одинаковой высоты. */
@media (max-width: 400px) {
    .comm-page .mud-toolbar {
        padding-inline: var(--space-1);
        column-gap: var(--space-1);
    }

    .cc-panel-header {
        padding-inline: var(--space-1);
        gap: var(--space-1);
        /* На самых узких экранах строка заголовка может перенестись: кнопки уходят вниз,
           вместо того чтобы выдавливать текст за границу панели. */
        flex-wrap: wrap;
        row-gap: var(--space-1);
    }

    .cc-panel-header-actions {
        gap: 0;
    }

    /* Вторичные действия прячем — остаются «назад», «переключить контекст» и «меню».
       Полный функционал доступен с 401px и выше (планшет/десктоп). */
    .comm-hide-xs {
        display: none !important;
    }

    .comm-feed {
        padding: 0.35rem;
    }

    .msg-action {
        min-width: 1.75rem;
        min-height: 1.75rem;
    }

    /* Строка участника на 320px: действия уходят на вторую строку под имя. */
    .room-member-row {
        grid-template-columns: minmax(0, 1fr);
    }

    .room-member-actions {
        justify-content: flex-start;
    }
}

/* == Меню туров в appbar (U5/W7). Своя выпадашка на Blazor вместо MudMenu:
   попапы MudBlazor в приложении не позиционируются (остаются в −9999 px). == */
.appbar-tour-wrap {
    position: relative;
    display: inline-flex;
    align-items: center;
}

.appbar-tour-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1300;
}

.appbar-tour-popover {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    z-index: 1301;
    min-width: 13rem;
    padding: 4px 0;
    display: flex;
    flex-direction: column;
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    border: 1px solid var(--mud-palette-divider);
    border-radius: 8px;
    box-shadow: var(--mud-elevation-8);
}

.appbar-tour-item {
    text-align: left;
    padding: 8px 16px;
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    cursor: pointer;
}

.appbar-tour-item:hover,
.appbar-tour-item:focus-visible {
    background: var(--mud-palette-action-default-hover);
    outline: none;
}

.appbar-tour-sep {
    height: 1px;
    margin: 4px 0;
    background: var(--mud-palette-divider);
}
