/* Единый слой стилей админки. Загружается после vendor/bootstrap и tokens.css.
   Здесь нет литеральных цветов и «магических» размеров — только токены.

   Порядок разделов:
     1. База документа
     2. Оболочка: сайдбар, топбар, рабочая область
     3. Навигация сайдбара
     4. Настройка компонентов Bootstrap под токены
     5. Служебные компоненты (тосты, состояния таблиц, статистика, дропзона)
     6. Стили конкретных страниц, переехавшие из <style> в шаблонах
     7. Страница входа
*/

/* ============================================================ 1. База */

body {
    background-color: var(--bg-body);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: var(--text-base);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 {
    color: var(--text-primary);
    font-weight: 600;
    line-height: 1.3;
}

code, kbd, pre, samp, .font-mono {
    font-family: var(--font-mono);
    font-size: 0.9em;
}

/* Числа в таблицах и счётчиках должны стоять в колонку. */
table, .tabular-nums, .stat-tile__value {
    font-variant-numeric: tabular-nums;
}

:focus-visible {
    outline: 2px solid var(--c-accent-500);
    outline-offset: 2px;
}

/* ======================================================== 2. Оболочка */

.app-shell {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    min-height: 100vh;
}

.app-sidebar {
    --bs-offcanvas-width: var(--sidebar-width);
    /* Bootstrap на lg+ гасит фон самого offcanvas и его body через
       `background-color: transparent !important`, поэтому красим внутренний
       контейнер, а не элемент оболочки. */
}

.app-sidebar .offcanvas-body {
    padding: 0;
}

.app-sidebar__inner {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-width: 0;
    background-color: var(--sidebar-bg);
}

.app-sidebar__brand {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-4) var(--space-4);
    color: var(--c-neutral-0);
    font-size: var(--text-lg);
    font-weight: 600;
    text-decoration: none;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.app-sidebar__brand:hover {
    color: var(--c-neutral-0);
}

.app-sidebar__brand i {
    color: var(--c-accent-400);
    font-size: 1.25em;
}

.app-body {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.app-topbar {
    position: sticky;
    top: 0;
    z-index: 1020;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: var(--topbar-height);
    padding: 0 var(--space-4);
    background-color: var(--bg-surface);
    border-bottom: 1px solid var(--border-color);
}

.app-topbar__title {
    margin: 0;
    font-size: var(--text-base);
    font-weight: 600;
}

.app-main {
    flex: 1 1 auto;
    min-width: 0;
    padding: var(--space-5) var(--space-4);
}

@media (min-width: 992px) {
    .app-shell {
        /* minmax(0, 1fr): иначе широкая таблица растягивает колонку контента
           и ломает сетку вместо того, чтобы скроллиться внутри себя. */
        grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
    }

    .app-sidebar {
        position: sticky;
        top: 0;
        align-self: start;
        height: 100vh;
        overflow-y: auto;
        /* Колонка + растянутый offcanvas-body: на lg+ Bootstrap оставляет
           .offcanvas-body с flex-grow: 0, из-за чего внутренний контейнер
           (он и красит сайдбар) обрывался по высоте меню, а не колонки. */
        display: flex;
        flex-direction: column;
    }

    .app-sidebar .offcanvas-body {
        flex: 1 1 auto;
    }

    .app-main {
        padding: var(--space-5) var(--space-6);
    }
}

/* Утилита Bootstrap ведёт на свой серый (#f8f9fa) мимо нашей палитры — из-за
   неё на страницах появлялся второй оттенок фона. Приводим к токену. */
.bg-light {
    background-color: var(--bg-subtle) !important;
}

/* Кнопка-иконка топбара (бургер, действия). */
.btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    color: var(--text-secondary);
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
}

.btn-icon:hover {
    color: var(--text-primary);
    background-color: var(--bg-subtle);
}

/* ============================================== 3. Навигация сайдбара */

.app-sidebar .nav {
    /* nowrap у flex-колонки: иначе при малой высоте во время анимации collapse
       пункты переносятся в соседние «столбцы» (визуально — горизонтальный
       прыжок). НЕ трогаем display, чтобы не перебить
       .collapse:not(.show){display:none}. */
    flex-wrap: nowrap;
    padding: var(--space-2) 0 var(--space-5);
}

.app-sidebar .nav-link {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 1px var(--space-2);
    padding: var(--space-2) var(--space-3);
    color: var(--sidebar-text);
    font-size: var(--text-sm);
    border-radius: var(--radius-sm);
    transition: background-color var(--transition-fast), color var(--transition-fast);
}

.app-sidebar .nav-link:hover {
    color: var(--sidebar-text-hover);
    background-color: var(--sidebar-item-hover);
}

.app-sidebar .nav-link.active {
    color: var(--text-on-accent);
    background-color: var(--sidebar-item-active);
    font-weight: 500;
}

.app-sidebar .nav-link i {
    width: 1.15em;
    flex: none;
    text-align: center;
}

.nav-section {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    padding: var(--space-4) var(--space-4) var(--space-1);
    color: var(--sidebar-section);
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    cursor: pointer;
    user-select: none;
}

.nav-section:hover {
    color: var(--sidebar-text-hover);
}

.nav-section .caret {
    font-size: 0.7em;
    transition: transform var(--transition);
}

.nav-section[aria-expanded="false"] .caret {
    transform: rotate(-90deg);
}

/* ========================= 4. Компоненты Bootstrap на наших токенах */

/* Кнопки: задаём переменные компонента, а не свойства — так остаются
   работать состояния :hover/:active/:disabled самого Bootstrap. */
.btn {
    --bs-btn-font-size: var(--text-sm);
    --bs-btn-padding-y: 0.4375rem;
    --bs-btn-padding-x: 0.875rem;
    font-weight: 500;
}

.btn-sm {
    --bs-btn-font-size: var(--text-xs);
    --bs-btn-padding-y: 0.25rem;
    --bs-btn-padding-x: 0.5rem;
}

.btn-primary {
    --bs-btn-bg: var(--c-accent-600);
    --bs-btn-border-color: var(--c-accent-600);
    --bs-btn-hover-bg: var(--c-accent-700);
    --bs-btn-hover-border-color: var(--c-accent-700);
    --bs-btn-active-bg: var(--c-accent-700);
    --bs-btn-active-border-color: var(--c-accent-700);
    --bs-btn-disabled-bg: var(--c-accent-400);
    --bs-btn-disabled-border-color: var(--c-accent-400);
}

.btn-outline-primary {
    --bs-btn-color: var(--c-accent-600);
    --bs-btn-border-color: var(--border-strong);
    --bs-btn-hover-bg: var(--c-accent-50);
    --bs-btn-hover-border-color: var(--c-accent-200);
    --bs-btn-hover-color: var(--c-accent-700);
    --bs-btn-active-bg: var(--c-accent-100);
    --bs-btn-active-border-color: var(--c-accent-200);
    --bs-btn-active-color: var(--c-accent-700);
}

/* Второстепенные аутлайн-кнопки в админке — нейтральные: цветными остаются
   только действия со смыслом (успех/опасность). */
.btn-outline-secondary {
    --bs-btn-color: var(--text-secondary);
    --bs-btn-border-color: var(--border-strong);
    --bs-btn-hover-bg: var(--bg-subtle);
    --bs-btn-hover-border-color: var(--border-strong);
    --bs-btn-hover-color: var(--text-primary);
}

.card {
    --bs-card-bg: var(--bg-surface);
    --bs-card-border-color: var(--border-color);
    --bs-card-border-radius: var(--radius-lg);
    --bs-card-inner-border-radius: calc(var(--radius-lg) - 1px);
    --bs-card-spacer-x: var(--space-4);
    --bs-card-spacer-y: var(--space-4);
    --bs-card-cap-bg: var(--bg-surface);
    box-shadow: var(--shadow-xs);
}

.card + .card {
    margin-top: var(--space-4);
}

/* Прокручиваемое содержимое карточки: длинные списки (история запросов,
   логи) не должны растягивать страницу. */
.card-body--scroll {
    max-height: 18.75rem;
    overflow-y: auto;
}

.card-header {
    display: flex;
    align-items: center;
    /* Переносим: в заголовках лежат легенды, фильтры и поиск — без переноса
       они не дают карточке сжаться на узком экране. */
    flex-wrap: wrap;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    color: var(--text-primary);
    font-size: var(--text-sm);
    font-weight: 600;
    border-bottom: 1px solid var(--border-color);
}

.card-header i {
    color: var(--text-muted);
}

.form-label {
    margin-bottom: var(--space-1);
    color: var(--text-secondary);
    font-size: var(--text-sm);
    font-weight: 500;
}

.form-control, .form-select {
    --bs-body-bg: var(--bg-surface);
    border-color: var(--border-strong);
    font-size: var(--text-sm);
}

.form-control:focus, .form-select:focus {
    border-color: var(--c-accent-400);
    box-shadow: 0 0 0 0.2rem var(--bs-focus-ring-color);
}

.form-text {
    color: var(--text-muted);
    font-size: var(--text-xs);
}

.form-check-input:checked {
    background-color: var(--c-accent-600);
    border-color: var(--c-accent-600);
}

.form-check-input:focus {
    border-color: var(--c-accent-400);
    box-shadow: 0 0 0 0.2rem var(--bs-focus-ring-color);
}

.table {
    --bs-table-bg: transparent;
    --bs-table-hover-bg: var(--bg-hover);
    --bs-table-border-color: var(--border-color);
    font-size: var(--text-sm);
    margin-bottom: 0;
}

.table > thead > tr > th {
    padding: var(--space-2) var(--space-3);
    color: var(--text-muted);
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;
    border-bottom-color: var(--border-color);
}

.table > tbody > tr > td {
    padding: var(--space-3);
    vertical-align: middle;
}

/* Таблица во всю ширину карточки: рамки карточки достаточно. */
.card > .card-body > .table-responsive > .table > :not(caption) > * > *:first-child,
.card > .table-responsive > .table > :not(caption) > * > *:first-child {
    padding-left: var(--space-4);
}

.badge {
    --bs-badge-font-size: var(--text-xs);
    --bs-badge-font-weight: 500;
    --bs-badge-padding-x: 0.5em;
    --bs-badge-padding-y: 0.3em;
    --bs-badge-border-radius: var(--radius-sm);
}

.nav-tabs {
    --bs-nav-tabs-border-color: var(--border-color);
    --bs-nav-tabs-link-active-color: var(--c-accent-600);
    --bs-nav-tabs-link-active-border-color: var(--border-color) var(--border-color) var(--bg-surface);
    --bs-nav-link-color: var(--text-secondary);
    --bs-nav-link-hover-color: var(--text-primary);
    --bs-nav-link-font-size: var(--text-sm);
    --bs-nav-link-font-weight: 500;
}

.modal-content {
    border: 0;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
}

.modal-header, .modal-footer {
    border-color: var(--border-color);
}

.modal-title {
    font-size: var(--text-lg);
}

.pagination {
    --bs-pagination-color: var(--text-secondary);
    --bs-pagination-border-color: var(--border-color);
    --bs-pagination-hover-bg: var(--bg-subtle);
    --bs-pagination-hover-color: var(--text-primary);
    --bs-pagination-active-bg: var(--c-accent-600);
    --bs-pagination-active-border-color: var(--c-accent-600);
    --bs-pagination-font-size: var(--text-sm);
}

.alert {
    --bs-alert-border-radius: var(--radius-md);
    font-size: var(--text-sm);
}

.progress {
    --bs-progress-bg: var(--bg-subtle);
    --bs-progress-font-size: var(--text-xs);
    --bs-progress-border-radius: var(--radius-sm);
    height: 1.25rem;
}

.progress-bar {
    transition: width var(--transition);
}

/* ================================== 5. Служебные компоненты админки */

/* Заголовок страницы: единый для всех разделов (макрос page_header). */
.page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
    margin-bottom: var(--space-5);
}

.page-header__title {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0;
    font-size: var(--text-2xl);
}

.page-header__title i {
    color: var(--text-muted);
}

.page-header__subtitle {
    margin: var(--space-1) 0 0;
    color: var(--text-muted);
    font-size: var(--text-sm);
}

.page-header__actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}

/* Контейнер тостов: создаётся один раз в ui.js, тосты в нём стекируются.
   Сдвинут под топбар — при top: 0 стопка накрывала заголовок страницы и его
   пояснение. */
.app-toasts {
    top: var(--topbar-height);
    z-index: var(--z-toast);
}

/* Плитка показателя (сводки на дашбордах). */
.stat-tile {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    height: 100%;
    padding: var(--space-4);
    background-color: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xs);
}

.stat-tile__label {
    color: var(--text-muted);
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.stat-tile__value {
    color: var(--text-primary);
    font-size: var(--text-2xl);
    font-weight: 600;
    line-height: 1.2;
}

.stat-tile__hint {
    color: var(--text-muted);
    font-size: var(--text-xs);
}

.stat-tile--clickable {
    cursor: pointer;
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.stat-tile--clickable:hover {
    border-color: var(--c-accent-200);
    box-shadow: var(--shadow-sm);
}

/* Единое пустое/ошибочное состояние: и в таблицах, и в блоках. */
.state-block {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-6) var(--space-4);
    color: var(--text-muted);
    text-align: center;
}

.state-block i {
    font-size: 1.75rem;
    opacity: 0.6;
}

.state-block--error {
    color: var(--c-danger-700);
}

.state-block__text {
    font-size: var(--text-sm);
}

/* Состояние внутри небольшой карточки: базовые 2rem по вертикали там выше
   самого содержимого. */
.state-block--compact {
    padding: var(--space-3) var(--space-2);
}

.state-block--compact i {
    font-size: 1.25rem;
}

/* Блок вывода модели или JSON: общая поверхность для «ответ пришёл — читай».
   .result-container — тот же блок, но с минимальной высотой, чтобы страница
   не прыгала между «пусто» и «результат». */
.output-box, .result-container, .json-view {
    padding: var(--space-4);
    background-color: var(--bg-body);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    font-size: var(--text-sm);
    white-space: pre-wrap;
    word-break: break-word;
}

.json-view {
    max-height: 31.25rem;
    overflow: auto;
    font-family: var(--font-mono);
}

/* Контейнер графика. Chart.js с maintainAspectRatio: false рисует по размеру
   родителя, поэтому высота задаётся здесь — и с запасом на полосу подписей оси,
   иначе внутри карточки появляется собственный вертикальный скролл. */
.chart-box {
    position: relative;
    height: 18rem;
}

/* Прокручиваемый список выбора: длинные наборы чекбоксов (логины и т.п.). */
.scroll-list {
    max-height: 12.5rem;
    overflow-y: auto;
}

/* Дропзона загрузки файлов. */
.drop-zone {
    padding: var(--space-6);
    color: var(--text-secondary);
    text-align: center;
    background-color: var(--c-accent-50);
    border: 1px dashed var(--c-accent-200);
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: background-color var(--transition-fast), border-color var(--transition-fast);
}

.drop-zone:hover, .drop-zone.dragover {
    background-color: var(--c-accent-100);
    border-color: var(--c-accent-400);
}

.drop-zone i {
    color: var(--c-accent-500);
    font-size: 2rem;
}

/* ================== 6. Страницы: стили, переехавшие из шаблонов */

/* --- Чат (chat.html) --- */
.chat-messages {
    height: 25rem;
    padding: var(--space-4);
    overflow-y: auto;
    background-color: var(--bg-body);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
}

.message {
    max-width: 80%;
    margin-bottom: var(--space-3);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-md);
    font-size: var(--text-sm);
    white-space: pre-wrap;
}

.message.user {
    margin-left: auto;
    color: var(--text-on-accent);
    background-color: var(--c-accent-600);
}

.message.assistant {
    background-color: var(--bg-surface);
    border: 1px solid var(--border-color);
}

/* --- Анализ фото и документы (photo.html, documents.html) --- */
.preview-image {
    max-width: 18.75rem;
    max-height: 18.75rem;
    border-radius: var(--radius-md);
}

.document-item {
    margin-bottom: var(--space-2);
    padding: var(--space-3) var(--space-4);
    background-color: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
}

/* --- Таблицы устройств (devices.html, video_analysis.html) --- */
/* Оба шаблона ведут свои сущности: у устройств чата признак `is_active`
   (класс .disabled), у устройств видеоанализа — `is_blocked` (.blocked).
   Вид у обоих состояний один, поэтому правило общее. */
.device-row.limit-exceeded {
    background-color: var(--c-warning-50);
}

.device-row.disabled, .device-row.blocked {
    background-color: var(--c-danger-50);
}

.status-badge {
    font-size: var(--text-xs);
}

.tokens-display {
    font-family: var(--font-mono);
    font-size: var(--text-sm);
}

/* --- Дашборд обработки (processing_dashboard.html) --- */
#chartTime, #chartModel, #chartService {
    cursor: pointer;
}

/* --- Архив БИОТ (biot_archive.html) --- */
.archive-col {
    height: calc(100vh - 17rem);
    overflow-y: auto;
}

.archive-item {
    margin-bottom: var(--space-1);
    padding: var(--space-2) var(--space-3);
    background-color: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.archive-item:hover {
    background-color: var(--c-accent-50);
}

.archive-item.active {
    color: var(--text-on-accent);
    background-color: var(--c-accent-600);
    border-color: var(--c-accent-600);
}

.archive-item small {
    opacity: 0.85;
}

.archive-item .title {
    word-break: break-word;
}

.msg-row {
    display: flex;
    margin-bottom: var(--space-3);
}

.msg-row.user {
    justify-content: flex-end;
}

.msg-bubble {
    max-width: 80%;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-md);
    font-size: var(--text-sm);
    white-space: pre-wrap;
    word-break: break-word;
}

.msg-row.user .msg-bubble {
    color: var(--text-on-accent);
    background-color: var(--c-accent-600);
}

.msg-row.assistant .msg-bubble {
    background-color: var(--bg-surface);
    border: 1px solid var(--border-color);
}

.msg-meta {
    font-size: var(--text-xs);
    opacity: 0.7;
    margin-top: var(--space-1);
}

.img-badge {
    display: inline-block;
    margin-top: var(--space-1);
    font-size: var(--text-xs);
}

.msg-images {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
    margin-top: var(--space-2);
}

.msg-img {
    width: 7.5rem;
    height: 7.5rem;
    object-fit: cover;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    cursor: pointer;
}

/* --- Уведомления об ошибках (error_notifications.html) --- */
.service-cell {
    white-space: nowrap;
}

.service-checks {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.service-checks .form-check {
    margin: 0;
}

.badge-service {
    font-size: var(--text-xs);
}

code.muted {
    color: var(--text-muted);
}

/* --- Тест анализа изображений (test_video_analysis.html) --- */
.preview-container {
    max-width: 100%;
    max-height: 25rem;
    margin-top: var(--space-3);
    overflow: hidden;
    border-radius: var(--radius-md);
}

.preview-container img, .preview-container video {
    max-width: 100%;
    max-height: 25rem;
    object-fit: contain;
}

/* Оформление — в общем правиле .output-box выше; здесь только высота, чтобы
   страница не прыгала между «пусто» и «результат». */
.result-container {
    min-height: 12.5rem;
}

.loading-spinner {
    display: none;
}

.loading .loading-spinner {
    display: inline-block;
}

.token-info {
    color: var(--text-muted);
    font-size: var(--text-sm);
}

.prompt-preview {
    max-height: 9.375rem;
    margin-top: var(--space-2);
    padding: var(--space-3);
    overflow-y: auto;
    background-color: var(--c-warning-50);
    border: 1px solid var(--c-warning-500);
    border-radius: var(--radius-md);
    font-size: var(--text-sm);
}

/* =================================================== 7. Страница входа */

.auth-page {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: var(--space-4);
    background-color: var(--bg-body);
}

.auth-card {
    width: 100%;
    max-width: 24rem;
    padding: var(--space-6);
    background-color: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
}

.auth-card__logo {
    margin-bottom: var(--space-5);
    text-align: center;
}

.auth-card__logo i {
    color: var(--c-accent-500);
    font-size: 2.5rem;
}

.auth-card__logo h1 {
    margin: var(--space-2) 0 0;
    font-size: var(--text-xl);
}
