﻿/*
    Каркас, общий для всей системы: боковая навигация, шапка страницы.

    Лежит отдельно, потому что его используют оба — и обычные страницы панели,
    и приложение логгера. Пока эти правила были у каждого свои, переход между
    разделами читался как переход между программами: слева то список, то строка
    сверху, заголовки в разных местах и разного размера.

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

    Цвета, размеры и шаг отступов — в tokens.css. Здесь только раскладка.

    Размеры приведены к руководству по стилю (19.08.2026). Прежние доли rem
    давали мелкоту: подписи групп 9.9 точки при норме 11-12, приписка внизу
    столько же. На плотном экране это первое, что перестаёт читаться.
*/

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

.sidebar {
    position: sticky;
    top: 0;
    height: 100vh;
    display: flex;
    flex-direction: column;
    padding: var(--gap-5) var(--gap-4) var(--gap-4);
    border-right: 1px solid var(--line-soft);
    background: var(--sidebar);
    overflow-y: auto;
}

.brand {
    display: flex;
    align-items: center;
    gap: var(--gap-3);
    padding: 0 var(--gap-2) var(--gap-6);
    letter-spacing: .08em;
    color: var(--text);
    text-decoration: none;
}
/*
    Знак проекта — картинка, а не буква в рамке.

    Скругление, а не круг: логотип квадратный, и обрезка в круг съела бы у него
    углы вместе с частью рисунка. Рамка убрана — у картинки своя граница, и
    синяя рамка вокруг оранжевого знака читалась бы как чужая.
*/
.brand-mark {
    width: var(--control-h);
    height: var(--control-h);
    flex: none;
    border-radius: var(--radius-small);
    object-fit: cover;
}
.brand strong { display: block; font-size: var(--size-section); font-weight: var(--weight-strong); }
.brand small { display: block; margin-top: 2px; color: var(--subtle); font-size: var(--size-badge); font-weight: var(--weight-strong); }

.nav { display: grid; gap: 3px; }

/*
    Заголовок группы разделов.

    Старой админки — двадцать пять разделов и сто семьдесят девять экранов, и
    всё это нам переносить. Плоским списком столько нечитаемо, а верхней
    строкой невместимо: она переполнялась уже на семи пунктах. Группы и есть
    то, что делает список пригодным.
*/
.nav-group {
    margin: var(--gap-4) 0 var(--gap-1);
    padding: 0 var(--gap-3);
    color: var(--subtle);
    font-size: var(--size-badge);
    font-weight: var(--weight-strong);
    letter-spacing: .12em;
    text-transform: uppercase;
}

.nav-item {
    display: flex;
    align-items: center;
    gap: var(--gap-3);
    width: 100%;
    padding: var(--gap-2) var(--gap-3);
    min-height: var(--control-h);
    border: 0;
    border-left: 2px solid transparent;
    background: transparent;
    color: var(--muted);
    text-align: left;
    font-size: var(--size-body);
    cursor: pointer;
}
.nav-item span { color: var(--subtle); font-family: var(--font-mono); font-size: var(--size-meta); }
.nav-item:hover { background: var(--sidebar-hover); color: var(--text); }
.nav-item.active { border-left-color: var(--accent); background: var(--surface-selected); color: var(--text); }
.nav-item.active span { color: var(--accent); }

/* Разделы, которые уходят по ссылке, а не переключают вид внутри страницы. */
a.nav-item { box-sizing: border-box; text-decoration: none; }

/* Подраздел: виден только внутри своего раздела, поэтому и смещён. */
.nav-sub { padding-left: var(--gap-6); font-size: var(--size-table); }

.sidebar-spacer { flex: 1; }

.sidebar-user {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    padding: var(--gap-3) var(--gap-2);
    border-top: 1px solid var(--line-soft);
    font-size: var(--size-table);
}

.sidebar-note {
    margin: var(--gap-3) 0 0;
    padding: 0 var(--gap-2);
    color: var(--subtle);
    font-size: var(--size-meta);
    line-height: 1.45;
}
/* Номер сборки живёт в размер самой приписки. Общий .mono теперь берёт долю от
   соседнего текста, а приписка и так набрана мелко: доля от мелкого — это уже
   не читается, а номер сборки называют вслух, когда что-то не сходится. */
.sidebar-note .mono { display: block; margin-top: 6px; font-size: 1em; }

/* ── Рабочая область ───────────────────────────────────────────────────── */

/*
    Ширины у рабочей области не было вовсе, и таблицы журнала, читеров и игроков
    растягивались на весь монитор: строка в две тысячи точек читается по частям,
    глаз теряет, в какой он строке. Число то же, с которым живёт логгер
    (.view в Investigations/Ui/app.css).
*/
.main { min-width: 0; max-width: 1800px; padding: 0 var(--pad-page) var(--gap-8); }

.topbar {
    /* Было 105 точек при примерно 50 точках чернил внутри. */
    min-height: 76px;
    /* Отбивка от первой карточки: без неё её рамка встаёт вплотную к линии
       шапки и две линии сливаются в одну толстую. */
    margin-bottom: var(--gap-3);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--gap-6);
    border-bottom: 1px solid var(--line-soft);
}
.topbar h1 { margin: var(--gap-1) 0 0; font-size: var(--size-title); font-weight: var(--weight-strong); letter-spacing: -.01em; }

/* Надпись над заголовком: какой это раздел. */
.eyebrow {
    margin: 0;
    color: var(--accent);
    font-size: var(--size-badge);
    font-weight: var(--weight-strong);
    letter-spacing: .13em;
    text-transform: uppercase;
}

.topbar-actions, .button-group { display: flex; align-items: center; gap: var(--gap-2); }

/*
    ШАПКА СТРАНИЦЫ — ОДИН КОМПОНЕНТ НА ВСЕ ЭКРАНЫ.

    Крошки, один заголовок, одна строка описания, действия справа. По концепту
    и по требованию аудита: раньше описание печатала каждая страница по-своему,
    и на части экранов его не было вовсе.
*/
.eyebrow {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
}

.eyebrow a { color: inherit; text-decoration: none; }
.eyebrow a:hover { color: var(--accent-strong); }
.crumb-sep { color: var(--subtle); }

.page-lead {
    max-width: 68ch;
    margin: 6px 0 0;
    color: var(--muted);
    font-size: .92rem;
    line-height: 1.5;
}

/*
    Узкий экран: боковая ложится строкой сверху и прокручивается вбок.

    Правило пришло из логгера, где оно уже было, и переехало сюда, потому что
    каркас теперь один. Пока оно жило только у него, на узком экране логгер
    выглядел разумно, а остальная панель отдавала боковой полосе двести
    тридцать восемь точек из восьмисот.
*/
/*
    ШИРОКИЙ ЭКРАН: кнопки меню и подложки нет.

    СТОИТ ПЕРЕД медиазапросом, и это не вкус. Правила равной силы разрешаются
    порядком в файле: пока эта строка стояла НИЖЕ, она перебивала `display:
    inline-flex` из узкого экрана — кнопка не появлялась никогда, а боковая не
    уезжала за край.

    Найдено замером в браузере 04.09.2026. Чтением найти было нельзя: в тексте
    оба правила на месте, и выглядит всё верно.
*/
.nav-open, .nav-backdrop { display: none; }

/*
    НА ШИРОКОМ ЭКРАНЕ ФЛАЖОК УБРАН ИЗ ОБХОДА ЦЕЛИКОМ.

    Найдено скептиком итоговой проверки 05.09.2026 и подтверждено замером.
    Флажок стоял `opacity: 0; pointer-events: none` — то есть невидимый, но
    ФОКУСИРУЕМЫЙ, и на широком экране был второй остановкой обхода на КАЖДОЙ
    странице. Нажатие ничего не делало: меню там и так открыто. Ореол
    сосредоточения не показывался дважды — собственный гас вместе с
    прозрачностью, а выделенное правило рисует его на метке `.nav-open`, у
    которой на широком `display: none`.

    Значит на каждой странице был шаг обхода в никуда, без единого признака
    того, что фокус вообще где-то есть.

    `display: none` убирает элемент из обхода по устройству, а не подпоркой
    `tabindex="-1"`: подпорку надо помнить, а это правило действует само. На
    узком экране флажок возвращается — там он и работает.
*/
#nav-toggle { display: none; }

/*
    УЗКИЙ ЭКРАН: ВЫДВИЖНОЕ МЕНЮ, А НЕ ЛЕНТА.

    Переделано 04.09.2026 по пункту 8 приоритетного плана UX-аудита.

    Что было. Боковая ложилась горизонтальной лентой и прокручивалась вбок:
    двадцать восемь пунктов, из которых видно три-четыре, а остальные за
    прокруткой, о которой ничто не сообщает. Подписи групп скрывались, и лента
    становилась плоским перечнем без смысла. И главное — скрывались профиль,
    роль и ВЫХОД: с узкого экрана выйти из панели было нельзя.

    Что теперь. Боковая уезжает за край и выдвигается кнопкой. Внутри она
    ровно та же, что на широком, — со всеми подписями групп, профилем и
    выходом. Ничего не прячется: меню либо открыто целиком, либо закрыто.

    БЕЗ JAVASCRIPT ТОЖЕ РАБОТАЕТ: открытие держится на скрытом флажке
    (`#nav-toggle`), а не на скрипте. Меню — последнее, что должно зависеть от
    исполнения скриптов: без него оператор не сможет даже выйти.
*/
/*
    ВИДИМЫЙ ФОКУС — ТРЕБОВАНИЕ АУДИТА, И ДО 04.09.2026 ЕГО НЕ БЫЛО ВОВСЕ.

    Слова `:focus-visible` не встречалось ни в одном файле стилей панели. То
    есть человек, работающий с клавиатуры, видел ровно то, что рисует браузер
    по умолчанию, — а в двух местах и этого не видел, потому что ореол снят
    руками (`input, select, textarea { outline: 0 }` и поле палитры).

    `:focus-visible`, а не `:focus`: ореол нужен тому, кто пришёл клавиатурой.
    По нажатию мыши он только мешает и выглядит поломкой.
*/
:where(a, button, summary, [tabindex], input, select, textarea):focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius-small);
}

/* Скрытый флажок меню фокус получает, но рисуется не он, а его метка. */
#nav-toggle:focus-visible ~ .app-shell .nav-open {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/*
    ССЫЛКА «К СОДЕРЖИМОМУ» — первое, на что попадает Tab.

    Без неё путь до содержимого лежит через всё боковое меню: двадцать восемь
    пунктов на каждой странице, и так на каждой.

    Видна только при фокусе: мышью её никто не ищет.
*/
.skip-link {
    position: absolute;
    z-index: 60;
    left: -9999px;
    top: 0;
    padding: var(--gap-2) var(--gap-4);
    border: 1px solid var(--accent);
    border-radius: 0 0 var(--radius-small) 0;
    background: var(--surface-2);
    color: var(--text);
    text-decoration: none;
}
.skip-link:focus { left: 0; }

@media (max-width: 900px) {
    .app-shell { width: 100%; grid-template-columns: minmax(0, 1fr); overflow-x: clip; }

    /*
        ЗАКРЫТЫЙ ЯЩИК ЗАКРЫТ И ДЛЯ КЛАВИАТУРЫ.

        Заведено 05.09.2026 по находке UX-03 повторного аудита Codex.

        ЧТО БЫЛО. Здесь стоял один `transform: translateX(-100%)`. Он уводит
        ящик за край экрана — и только. Ссылки внутри остаются в обходе по Tab и
        в дереве доступности: человек, идущий по странице с клавиатуры, проходит
        через десяток НЕВИДИМЫХ ссылок, а чтец экрана их читает. Ни ошибки, ни
        признака — просто фокус пропадает в пустоте.

        `visibility: hidden` убирает и то и другое: элемент не получает фокуса и
        не попадает в дерево доступности. При этом он, в отличие от `display`,
        поддаётся переходу — поэтому ящик по-прежнему выезжает плавно.

        ЗАДЕРЖКА В ПЕРЕХОДЕ и есть весь трюк: при закрытии видимость снимается
        ПОСЛЕ того, как ящик уехал (180 мс), а при открытии — сразу, иначе он
        выезжал бы невидимым.

        БЕЗ СКРИПТА, И ЭТО РЕШЕНИЕ. Меню держится на флажке нарочно: оно
        последнее, что должно зависеть от исполнения скриптов. Аудит просит
        сверх того кнопку с `aria-expanded`, `inert`, Escape и возврат фокуса —
        всё это требует скрипта, и запись об этом лежит в БЭКЛОГ отдельным
        пунктом, а не молча пропущена.
    */
    .sidebar {
        position: fixed;
        z-index: 40;
        top: 0;
        left: 0;
        width: min(300px, 86vw);
        height: 100vh;
        padding: var(--gap-4) var(--gap-4) var(--gap-4);
        transform: translateX(-100%);
        visibility: hidden;
        transition: transform 180ms ease, visibility 0s linear 180ms;
        box-shadow: var(--shadow);
    }

    /* Флажок стоит перед каркасом, поэтому дотянуться можно только вперёд. */
    /* Флажок возвращается в обход: здесь он и есть кнопка меню. */
    #nav-toggle { position: absolute; display: block; opacity: 0; pointer-events: none; }
    #nav-toggle:checked ~ .app-shell .sidebar {
        transform: translateX(0);
        visibility: visible;

        /* Видимость возвращается СРАЗУ: иначе ящик выезжал бы невидимым. */
        transition: transform 180ms ease, visibility 0s;
    }

    #nav-toggle:checked ~ .app-shell .nav-backdrop {
        opacity: 1;
        pointer-events: auto;
    }

    .nav-backdrop {
        /*
            DISPLAY ВОЗВРАЩАЕТСЯ ЗДЕСЬ, И БЕЗ ЭТОГО ПОДЛОЖКИ НЕ БЫЛО ВОВСЕ.

            Выше по файлу стоит `.nav-open, .nav-backdrop { display: none; }` —
            правило вне медиазапроса, гасящее обе вещи на широком экране. У
            кнопки открытия `display` внутри запроса возвращается, у подложки
            возвращался только `opacity` и `pointer-events`, а `display: none`
            бил их обоих.

            То есть нажатие мимо меню НИКОГДА его не закрывало, при том что в
            журнале 1.9.140 записано обратное. Найдено разбором 04.09.2026;
            чтением не находилось — в тексте оба правила на месте и выглядят
            верно.
        */
        display: block;
        position: fixed;
        z-index: 39;
        inset: 0;
        background: rgba(0, 0, 0, .5);
        opacity: 0;
        pointer-events: none;
        transition: opacity 180ms ease;
    }

    .nav-open {
        display: inline-flex;
        align-items: center;
        gap: var(--gap-2);
        min-height: 44px;
        padding: 0 var(--gap-3);
        border: 1px solid var(--line);
        border-radius: var(--radius);
        background: var(--surface);
        color: var(--text);
        cursor: pointer;
    }

    .main { width: 100%; min-width: 0; max-width: 100vw; padding: 0 var(--gap-4) var(--gap-8); overflow-x: clip; }
}


@media (prefers-reduced-motion: reduce) {
    .sidebar, .nav-backdrop { transition: none; }
}
