/* CtrlBoard — тонкий слой поверх Bootstrap 5.
   Здесь только то, что не покрыто Bootstrap utility-классами:
   статус-сообщения, off-canvas меню, лог-панель, цветовая индикация карточек. */

/* Фон вешаем на html, чтобы body не растягивался до 100vh — иначе на
   страницах с маленьким контентом появляется ненужный скролл из-за 1px
   нестыковок (box-sizing / scrollbar). */
html { background: #f5f5f5; }
body { background: #f5f5f5; }

.app-container {
    max-width: 1350px;
    margin: 0 auto;
    padding: 20px 16px;
}

/* ---------- Top navbar (sticky) ---------- */

.topnav {
    position: sticky;
    top: 0;
    z-index: 1000;
    background: #fff;
    border-bottom: 1px solid #e5e5e5;
    box-shadow: 0 1px 3px rgba(0,0,0,0.04);
    /* Центрирование topnav-inner через flex родителя — независимо от того,
       как inner вычислит свою ширину. */
    display: flex;
    justify-content: center;
}

.topnav-inner {
    flex: 0 1 1350px;
    min-width: 0;
    padding: 10px 16px;
    display: flex;
    align-items: center;
    /* CCB-64: gap уменьшен 16→10, иначе на ~1400px lang-select и email
       сжимаются и email обрезается ellipsis'ом раньше времени. */
    gap: 10px;
    box-sizing: border-box;
}

.topnav-brand {
    font-weight: 600;
    color: #333;
    text-decoration: none;
    font-size: 1.1rem;
    white-space: nowrap;
    flex-shrink: 0;
}

.topnav-brand:hover { color: #000; text-decoration: none; }

.topnav-links {
    display: flex;
    gap: 8px;
    align-items: center;
    flex: 1;
}

.topnav-links a {
    color: #555;
    text-decoration: none;
    padding: 6px 6px;
    border-radius: 4px;
    font-size: 0.95rem;
}
.topnav-links a:hover { background: #f0f0f0; color: #000; }
.topnav-links a.active { background: #e7f1ff; color: #0a58ca; }

/* Селектор текущего проекта в навбаре. Ужимаем по содержимому, чтобы не растягивался на весь ряд. */
.topnav-project-select {
    width: auto;
    max-width: 220px;
    min-width: 140px;
}
/* Селектор языка: совсем узкий, два варианта (RU/EN). Десктопный
   инстанс — снаружи .topnav-links (рядом с btn-theme); мобильный —
   внутри .topnav-links (в off-canvas, рядом с btn-theme-mobile).
   bootstrap form-select-sm имеет padding-right 2rem под dropdown-стрелочкой
   — это создаёт лишний пробел между select и соседней кнопкой; подрезаем. */
.topnav-lang-select {
    width: auto;
    min-width: 0;
    padding-right: 1.5rem;
    background-position: right 0.4rem center;
}
.topnav-lang-mobile  { display: none; }
.topnav-lang-desktop { display: inline-block; }
.topnav-manage {
    white-space: nowrap;
}

/* На десктопе email/logout-desktop/theme-desktop видимы в основной строке;
   user-mobile/logout-mobile/theme-mobile — внутри off-canvas меню. */
.topnav-user-mobile, .topnav-logout-mobile, .topnav-theme-mobile { display: none; }
.topnav-theme-desktop { padding: 4px 8px; }
/* Английское «Sign out» — два слова; без nowrap flex переносит и растягивает высоту. */
.topnav-logout-desktop { white-space: nowrap; }

.topnav-user {
    color: #666;
    font-size: 0.9rem;
    margin-right: 8px;
    white-space: nowrap;
    /* Очень длинный email обрезается многоточием — обычные (до ~25 символов)
       помещаются полностью, длиннее — ellipsis + полный текст в title (см. nav.js). */
    max-width: 240px;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Email — кликабельная ссылка на /account.html. Лёгкое dotted-подчёркивание
   как hint о кликабельности (полный underline только в hover). */
a.topnav-user-link, a.topnav-user-link:visited {
    color: #555;
    text-decoration: underline dotted #999;
    text-underline-offset: 3px;
    cursor: pointer;
}
a.topnav-user-link:hover { color: #000; text-decoration: underline; }

.topnav-burger {
    display: none;
    background: none;
    border: 1px solid #ccc;
    border-radius: 4px;
    padding: 6px 10px;
    cursor: pointer;
}
.topnav-burger span {
    display: block;
    width: 22px;
    height: 2px;
    background: #333;
    margin: 4px 0;
    border-radius: 2px;
}

/* Off-canvas backdrop */
.topnav-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.35);
    z-index: 1040;
}
.topnav-backdrop.open { display: block; }

/* Burger срабатывает на ширине, где полное меню (brand + project-select +
   5 пунктов + lang-select + email + theme + Выйти) не помещается. После
   добавления language-picker'а break — 1350 (синхронизировано с board). */
@media (max-width: 1349px) {
    .topnav-burger          { display: inline-block; margin-left: auto; }
    .topnav-user            { display: none; }
    .topnav-logout-desktop  { display: none; }
    .topnav-theme-desktop   { display: none; }
    .topnav-lang-desktop    { display: none; }
    /* Все три footer-контрола в off-canvas — равномерно по 12+12 = 24px между
       соседями. У email-mobile padding-bottom убран, border-bottom тоже —
       чтобы между ним и lang было ровно 24, как у lang/theme и theme/logout. */
    .topnav-lang-mobile     { display: block; margin: 24px 16px 12px 16px; }

    .topnav-links {
        position: fixed;
        top: 0;
        right: -280px;
        bottom: 0;
        width: 260px;
        background: #fff;
        flex-direction: column;
        align-items: stretch;
        justify-content: flex-start;
        gap: 0;
        padding: 12px 0 16px 0;
        box-shadow: -2px 0 8px rgba(0,0,0,0.12);
        transition: right 0.25s ease;
        z-index: 1050;
        overflow-y: auto;
    }
    .topnav-links.open { right: 0; }
    .topnav-links a {
        padding: 14px 20px;
        border-radius: 0;
        border-bottom: 1px solid #f0f0f0;
        font-size: 1rem;
    }
    .topnav-project-select {
        margin: 12px 16px;
        max-width: none;
        width: calc(100% - 32px);
    }
    .topnav-user-mobile {
        display: block;
        padding: 14px 20px;
        color: #666;
        font-size: 0.9rem;
        border-bottom: 1px solid #f0f0f0;
    }
    .topnav-theme-mobile {
        display: block;
        margin: 12px 16px;
        width: calc(100% - 32px);
        text-align: left;
    }
    .topnav-logout-mobile {
        display: block;
        margin: 12px 16px;
        width: calc(100% - 32px);
    }
}

/* ---------- Status messages ---------- */

.status {
    margin-top: 12px;
    padding: 10px 14px;
    border-radius: 6px;
    min-height: 20px;
}
.status:empty { padding: 0; min-height: 0; }
.status.success { background: #d1e7dd; color: #0f5132; }
.status.error   { background: #f8d7da; color: #842029; }

/* ---------- Empty placeholder ---------- */

.empty {
    color: #888;
    text-align: center;
    padding: 32px 12px;
    font-style: italic;
}

/* ---------- Modal (native <dialog>) ---------- */

dialog.app-modal {
    border: none;
    border-radius: 8px;
    padding: 0;
    max-width: 560px;
    width: calc(100% - 24px);
    max-height: calc(100vh - 24px);
    box-shadow: 0 8px 24px rgba(0,0,0,0.18);
    overflow: hidden;
}
/* flex-колонка применяется только к открытой модалке — иначе мы перебиваем
   user-agent «display:none» для закрытого <dialog> и close() не скрывает его. */
dialog.app-modal[open] {
    display: flex;
    flex-direction: column;
}
/* Когда внутри dialog лежит <form> (например, modal-device.html),
   именно она становится прямым flex-child'ом. Без display:flex column
   на форме flex-chain рвётся → body не получает min-height:0 → не скроллится
   при длинном контенте (release-notes большого RELEASES.md). */
dialog.app-modal[open] > form {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1 1 auto;
}
dialog.app-modal::backdrop { background: rgba(0,0,0,0.4); }

.app-modal-header {
    padding: 14px 18px;
    border-bottom: 1px solid #eee;
    font-weight: 600;
    font-size: 1.05rem;
    flex-shrink: 0;
}
.app-modal-body {
    padding: 16px 18px;
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
}
.app-modal-footer {
    padding: 12px 18px;
    border-top: 1px solid #eee;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 8px;
    background: #fafafa;
    border-radius: 0 0 8px 8px;
    flex-shrink: 0;
}
/* Статус-блок в footer должен быть на одном уровне с кнопками и той же высоты. */
.app-modal-footer .status {
    margin: 0;
    padding: 8px 12px;
    line-height: 1.5;
    font-size: 1rem;
    min-height: 0;
    display: flex;
    align-items: center;
}

/* ---------- Select-tile: блочный toggle-выбор (entity/group в invite) ---------- */
/* Используется в модалке группы (выбор реле/сенсоров) и в форме invite (выбор групп).
   Клик меняет data-selected — CSS подсвечивает выбранные. */

.tile-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 10px;
}

.tile-grid-tight {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.select-tile {
    border: 1px solid var(--bs-border-color, #dee2e6);
    background: #fff;
    border-radius: 6px;
    padding: 6px 10px;
    cursor: pointer;
    font-size: 0.9rem;
    line-height: 1.3;
    transition: background 0.15s ease, border-color 0.15s ease;
    text-align: left;
}
.select-tile:hover {
    border-color: #6c757d;
}
.select-tile[data-selected="1"] {
    background: #d1e7dd;
    border-color: #198754;
    color: #0a3622;
}
.select-tile:disabled,
.select-tile[disabled] {
    opacity: 0.55;
    cursor: not-allowed;
}

[data-bs-theme="dark"] .select-tile             { background: #23262d; border-color: #2e323a; color: #e6e6e6; }
[data-bs-theme="dark"] .select-tile:hover        { border-color: #6c757d; }
[data-bs-theme="dark"] .select-tile[data-selected="1"] {
    background: #14422a; border-color: #1f6638; color: #d8f0e3;
}

.select-tile-big {
    padding: 10px 14px;
    font-weight: 600;
}

/* ---------- Card-row для списков (devices/tasks/users) ---------- */

.row-card {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 14px;
    background: #fff;
    margin: 6px 0;
    border-radius: 8px;
    border: 1px solid var(--bs-border-color, #dee2e6);
    gap: 12px;
    flex-wrap: wrap;
}
.row-card .row-actions {
    display: flex;
    gap: 6px;
    flex-shrink: 0;
    flex-wrap: wrap;
}

/* ---------- Дашборд: рамка-fieldset вокруг устройства ---------- */
/* Имя устройства сидит ярлычком на верхней рамке — как у <fieldset><legend>,
   визуально близко к "tab + frame" со страницы входа. */
.device-fieldset {
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: 8px;
    padding: 12px 14px 6px;
    margin-bottom: 24px;
    /* fieldset по умолчанию имеет min-width:min-content — снимаем, иначе flex-wrap внутри
       может выпирать за родителя. */
    min-width: 0;
}
.device-legend {
    width: auto;
    float: none;
    padding: 0 8px;
    margin: 0 0 4px 0;
    font-size: 0.95rem;
    line-height: 1.3;
    display: inline-flex;
    flex-wrap: wrap;
    gap: 4px 10px;
    align-items: baseline;
}

/* ---------- Toast уведомления ---------- */

.toast-container {
    position: fixed;
    z-index: 1100;
    right: 16px;
    bottom: 16px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    pointer-events: none;
    max-width: 380px;
    box-sizing: border-box;
}
.toast-msg {
    pointer-events: auto;
    background: #333;
    color: #fff;
    padding: 10px 36px 10px 14px;
    border-radius: 6px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.18);
    font-size: 0.95rem;
    line-height: 1.35;
    position: relative;
    opacity: 1;
    transform: translateY(0);
    transition: opacity 0.18s ease, transform 0.18s ease;
    width: 100%;
    box-sizing: border-box;
}
/* text — block, чтобы action-кнопка ниже него стартовала с новой строки.
   Явно сбрасываем white-space и width на случай наследования от соседних
   правил (.row-card, .topnav). overflow-wrap: anywhere — для русских
   слов без word-break. */
.toast-text {
    display: block;
    width: 100%;
    white-space: normal;
    overflow-wrap: anywhere;
    word-wrap: break-word;
}
.toast-msg.toast-leaving { opacity: 0; transform: translateY(8px); }
.toast-info    { background: #0d6efd; }
.toast-success { background: #198754; }
.toast-error   { background: #dc3545; }
.toast-close {
    position: absolute;
    top: 4px;
    right: 6px;
    background: transparent;
    border: 0;
    color: rgba(255,255,255,0.85);
    font-size: 1.1rem;
    line-height: 1;
    padding: 4px 6px;
    cursor: pointer;
}
.toast-close:hover { color: #fff; }
.toast-action {
    /* Всегда отдельной строкой под текстом — гарантия видимости на
       узких экранах вне зависимости от длины статуса. */
    display: inline-block;
    margin-top: 6px;
    background: rgba(255, 255, 255, 0.18);
    border: 0;
    color: #fff;
    font-size: 0.85rem;
    font-weight: 600;
    border-radius: 4px;
    padding: 3px 10px;
    cursor: pointer;
    transition: background 0.12s ease;
}
.toast-action:hover { background: rgba(255, 255, 255, 0.32); }

@media (max-width: 768px) {
    .toast-container {
        right: 8px;
        left: 8px;
        bottom: 8px;
        /* width вычисляется из left+right (=100vw-16). max-width на случай
           если какой-то ancestor с transform/contain ломает позиционирование
           fixed относительно viewport. */
        max-width: calc(100vw - 16px);
    }
}

/* ---------- Dashboard cards (5.C, заготовка) ---------- */

.device-card {
    background: #fff;
    border: 1px solid #e5e5e5;
    border-radius: 8px;
    padding: 14px;
    cursor: default;
    transition: transform 0.1s ease, box-shadow 0.1s ease;
}
.device-card.clickable { cursor: pointer; }
.device-card.clickable:hover { transform: translateY(-1px); box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
.device-card.state-on  { background: #d1e7dd; border-color: #a3cfbb; }
.device-card.state-off { background: #fff; }
.device-card.state-active { background: #fff3cd; border-color: #ffe69c; }
.device-card.state-stale { background: #f8f9fa; color: #999; }
/* Команда в полёте — оптимистичный state применён, ждём ack от платы. */
.device-card[data-busy="1"] { opacity: 0.6; transition: opacity 0.15s ease; }

/* Плата давно не присылала heartbeat — её устройства полупрозрачные и недоступные.
   Визуально похоже на data-busy, но смысл другой: плата не отвечает, а не «команда в полёте». */
/* Пустые платы (last_state.devices пуст) скрываются по умолчанию. body.show-empty-boards
   снимает скрытие — toggle в шапке проекта. */
.device-fieldset[data-empty="1"] { display: none; }
body.show-empty-boards .device-fieldset[data-empty="1"] { display: block; }

.device-fieldset[data-offline="1"] .device-card {
    opacity: 0.5;
    pointer-events: none;
    cursor: not-allowed;
}
.device-fieldset[data-offline="1"] .device-legend { color: #999; }

/* ---------- Лог-панель (5.D, заготовка) ---------- */

.log-panel {
    background: #1e1e1e;
    color: #d4d4d4;
    font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
    font-size: 0.85rem;
    padding: 10px 12px;
    border-radius: 6px;
    max-height: 320px;
    overflow-y: auto;
}
.log-panel .log-line { white-space: pre-wrap; line-height: 1.45; }
.log-panel .log-i { color: #4ec9b0; }   /* info — бирюзовый */
.log-panel .log-w { color: #ffd166; font-weight: 500; } /* warning — янтарь */
.log-panel .log-e { color: #ff6b6b; font-weight: 500; } /* error  — красный */
.log-panel .log-d { color: #87ceeb; }   /* debug — голубой */
.log-panel .log-ts { color: #6a9955; }  /* timestamp — зелёный (как комментарий) */

/* ============================================================================
   Phase 10 — тёмная тема
   Bootstrap 5.3 переопределяет form/button/card/input через `data-bs-theme="dark"`
   автоматически. Здесь — только наши кастомные классы.
   ============================================================================ */

html[data-bs-theme="dark"] { background: #181a1f; }
[data-bs-theme="dark"] body { background: #181a1f; color: #e6e6e6; }

[data-bs-theme="dark"] .topnav {
    background: #23262d;
    border-bottom-color: #2e323a;
    box-shadow: 0 1px 3px rgba(0,0,0,0.3);
}
[data-bs-theme="dark"] .topnav-brand          { color: #f0f0f0; }
[data-bs-theme="dark"] .topnav-brand:hover    { color: #fff; }
[data-bs-theme="dark"] .topnav-links a        { color: #c0c5cc; }
[data-bs-theme="dark"] .topnav-links a:hover  { background: #2e323a; color: #fff; }
[data-bs-theme="dark"] .topnav-links a.active { background: #1e3a5f; color: #8ebbff; }
[data-bs-theme="dark"] .topnav-user           { color: #aaa; }
[data-bs-theme="dark"] a.topnav-user-link,
[data-bs-theme="dark"] a.topnav-user-link:visited { color: #aaa; text-decoration-color: #666; }
[data-bs-theme="dark"] a.topnav-user-link:hover   { color: #fff; }
[data-bs-theme="dark"] .topnav-burger         { border-color: #4a4f57; }
[data-bs-theme="dark"] .topnav-burger span    { background: #ddd; }

@media (max-width: 1349px) {
    [data-bs-theme="dark"] .topnav-links {
        background: #23262d;
        box-shadow: -2px 0 8px rgba(0,0,0,0.5);
    }
    [data-bs-theme="dark"] .topnav-links a { border-bottom-color: #2e323a; }
}

[data-bs-theme="dark"] .row-card     { background: #23262d; border-color: #2e323a; color: #e6e6e6; }
[data-bs-theme="dark"] .row-card .text-muted { color: #9a9fa6 !important; }

[data-bs-theme="dark"] .device-fieldset { border-color: #2e323a; }

[data-bs-theme="dark"] .device-card             { background: #23262d; border-color: #2e323a; color: #e6e6e6; }
[data-bs-theme="dark"] .device-card.state-on    { background: #14422a; border-color: #1f6638; }
[data-bs-theme="dark"] .device-card.state-off   { background: #23262d; }
[data-bs-theme="dark"] .device-card.state-active{ background: #5a4a14; border-color: #8a7325; }
[data-bs-theme="dark"] .device-card.state-stale { background: #1c1f25; color: #888; }

[data-bs-theme="dark"] dialog.app-modal         { background: #23262d; color: #e6e6e6; }
[data-bs-theme="dark"] .app-modal-header        { border-bottom-color: #2e323a; }
[data-bs-theme="dark"] .app-modal-footer        { background: #1c1f25; border-top-color: #2e323a; }
[data-bs-theme="dark"] dialog.app-modal::backdrop { background: rgba(0,0,0,0.65); }

[data-bs-theme="dark"] .status.success { background: #14422a; color: #a3e0bd; }
[data-bs-theme="dark"] .status.error   { background: #5a1f24; color: #f5c1c6; }

[data-bs-theme="dark"] .empty { color: #6a6f78; }

/* Лог-панель — тёмная и так, в светлой теме контраст приемлемый, в тёмной чуть мягче рамка */
[data-bs-theme="dark"] .log-panel { border: 1px solid #2e323a; }

/* ---------- Page loader (anti-FOUC) ----------
   Полноэкранный overlay со spinner'ом до DOMContentLoaded. Inline-скрипт в
   <head> каждой страницы добавляет class="loaded" на <html> — overlay fade-out. */
.page-loader {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #f5f5f5;
    transition: opacity 200ms ease;
}
.page-loader::after {
    content: "";
    width: 36px;
    height: 36px;
    border: 3px solid rgba(0, 0, 0, 0.12);
    border-top-color: #0d6efd;
    border-radius: 50%;
    animation: page-loader-spin 800ms linear infinite;
}
html.loaded .page-loader { opacity: 0; pointer-events: none; }
@keyframes page-loader-spin { to { transform: rotate(360deg); } }

[data-bs-theme="dark"] .page-loader { background: #181a1f; }
[data-bs-theme="dark"] .page-loader::after {
    border-color: rgba(255, 255, 255, 0.15);
    border-top-color: #6ea8fe;
}

/* Скрытая группа в списке — приглушённая, но кликабельная (toggle/edit/delete). */
.row-card.group-row-hidden { opacity: 0.55; }
.row-card.group-row-hidden:hover { opacity: 0.85; }

/* ---------- Notes (Phase 18) ---------- */

.notes-list {
    max-height: 280px;
    overflow-y: auto;
    border: 1px solid #e5e5e5;
    border-radius: 8px;
    background: #fafafa;
    padding: 8px 10px;
}
.note-row {
    padding: 4px 0;
    border-bottom: 1px solid #eee;
}
.note-row:last-child { border-bottom: none; }
.note-meta {
    display: flex;
    align-items: baseline;
    gap: 8px;
    font-size: 0.85em;
}
.note-author { font-weight: 600; }
.note-time   { font-size: 0.85em; }
.note-text {
    white-space: pre-wrap;
    word-wrap: break-word;
    margin-top: 2px;
}
.note-del {
    margin-left: auto;
    line-height: 1;
    font-size: 1.1em;
}

[data-bs-theme="dark"] .notes-list {
    background: #23262d;
    border-color: #2e323a;
    color: #e6e6e6;
}
[data-bs-theme="dark"] .note-row { border-bottom-color: #2e323a; }

/* Список задач на карточке платы — компактные строки с toggle справа. */
.tasks-block { display: flex; flex-direction: column; gap: 4px; }
.task-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 4px 8px;
    border: 1px solid #e5e5e5;
    border-radius: 8px;
    background: #fff;
}
.task-meta { display: flex; flex-direction: column; min-width: 0; flex: 1; }
[data-bs-theme="dark"] .task-row {
    background: #23262d;
    border-color: #2e323a;
    color: #e6e6e6;
}

/* Кнопка «Отправить» — фон в цвет активной карточки реле (.device-card.state-on),
   цвет текста — как у label'а реле (Bootstrap .text-muted). */
.btn-send-note {
    background: #d1e7dd;
    border: 1px solid #a3cfbb;
    color: var(--bs-secondary-color);
}
.btn-send-note:hover {
    background: #badbcc;
    border-color: #8fbfa3;
    color: var(--bs-secondary-color);
}
[data-bs-theme="dark"] .btn-send-note {
    background: #14422a;
    border-color: #1f6638;
}
[data-bs-theme="dark"] .btn-send-note:hover {
    background: #1c5638;
    border-color: #287a45;
}

/* ---------- Show-password toggle ---------- */

.pwd-wrap {
    position: relative;
    display: block;
}
.pwd-wrap > input.form-control {
    padding-right: 2.4em;
}
.pwd-toggle {
    position: absolute;
    top: 0;
    right: 0;
    height: calc(2.25rem + 2px);
    width: 2.4em;
    border: 0;
    background: transparent;
    cursor: pointer;
    font-size: 1.0em;
    line-height: 1;
    color: inherit;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    user-select: none;
}
.pwd-wrap > input.form-control-lg ~ .pwd-toggle {
    height: calc(2.875rem + 2px);
}
.pwd-toggle:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: -2px;
    border-radius: 4px;
}

/* ---------- Cookie consent banner ---------- */
/* Bottom-right corner, единожды показывается до клика. Использует CSS-vars
   Bootstrap'а — автоматически light/dark theme aware. */

.cookie-banner {
    position: fixed;
    z-index: 1090;          /* ниже toast (1100), чтобы не перекрывал error-уведомления */
    right: 16px;
    bottom: 16px;
    max-width: 380px;
    padding: 12px 14px;
    border-radius: 8px;
    background: var(--bs-body-bg);
    color: var(--bs-body-color);
    border: 1px solid var(--bs-border-color);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.15);
    font-size: 0.9rem;
    line-height: 1.4;
    display: flex;
    flex-direction: column;
    gap: 8px;
    opacity: 1;
    transform: translateY(0);
    transition: opacity 0.18s ease, transform 0.18s ease;
}
.cookie-banner-leaving {
    opacity: 0;
    transform: translateY(8px);
}
.cookie-banner-text {
    color: var(--bs-body-color);
}
.cookie-banner-btn {
    align-self: flex-end;
    min-width: 90px;
}
@media (max-width: 480px) {
    .cookie-banner {
        right: 8px;
        bottom: 8px;
        left: 8px;
        max-width: none;
    }
}

/* CCB-187: admin announcement — fieldset с красной рамкой/легендой как у платы.
   !important чтобы перебить базовый .device-fieldset border (та же specificity).
   Padding-top + legend margin-bottom = 0, чтобы содержимое было сразу под
   легендой без лишнего воздуха. */
.announcement-card {
    border: 2px solid var(--bs-danger, #dc3545) !important;
    padding: 0 14px 8px;
}
.announcement-card > .device-legend {
    color: var(--bs-danger, #dc3545);
    margin-bottom: 0;
}
