/*
 * Кирпич · боковая колонка.
 *
 * Разделы столбцом слева от текста, а на телефоне та же разметка
 * становится полосой внизу экрана. Переключение делает медиазапрос,
 * поэтому поведения здесь нет вовсе и прятать колонку нечем.
 *
 *     body.with-aside
 *         nav.menu
 *         aside
 *             menu
 *                 li a Раздел
 *                 li a.here Текущий раздел
 *         main
 *
 * Класс стоит на body, а не на самой колонке: раскладку держит страница
 * целиком, и main обязан знать, что слева от него кто-то есть. Колонка
 * при этом просто соседствует с текстом, а не оборачивает его.
 *
 * Полоса меню сверху остаётся на месте: колонка её не заменяет, а
 * дополняет. Сайту нужно либо одно, либо другое, либо оба сразу, и
 * выбор делает разметка страницы, а не стили.
 */

/*
 * Страница с колонкой раскладывается гридом: слева колонка заданной
 * ширины, справа текст.
 *
 * Ширина сайта от колонки не меняется: --site-width держит всю полосу
 * содержимого, и колонка отъедает место у текста, а не прибавляется
 * сбоку. Строка чтения на такой странице короче, и это осознанно:
 * добавить навигацию не значит расширить сайт.
 */
@media (min-width: 900px) {
    /*
     * Обычная страница заранее держит место под системную полосу
     * прокрутки на html. Здесь корень заперт и прокручивается внутренняя
     * колонка, поэтому прежний резерв оставлял справа пустую белую
     * полосу между scrollbar и краем окна.
     */
    html:has(> body.with-aside) {
        scrollbar-gutter: auto;
    }

    .with-aside {
        display: grid;
        height: 100dvh;
        min-height: 0;
        overflow: hidden;
        /*
         * Ряды описаны именами, а не порядком. Порядковый номер ряда
         * достаётся тому, кто первым лежит в body, а туда попадает и
         * чужая разметка: панель редактирования, счётчики, всплывающие
         * окна. Меню тогда оказывается во втором ряду с долей высоты и
         * растягивается на треть экрана, оставляя под собой пустоту.
         *
         * Доля у ряда содержимого: лишнее место достаётся тексту, и
         * подвал прижимается к низу, как на странице без колонки. Ряд
         * подвала остаётся пустым, если подвала на странице нет.
         */
        grid-template-areas:
            'menu menu menu menu menu'
            '. aside gap main .';
        grid-template-rows: auto minmax(0, 1fr);
        /*
         * Колонки стоят внутри той же полосы содержимого, что и текст на
         * странице без колонки: --site-width держит колонку, просвет и
         * текст вместе, поэтому сайт от её появления не расширяется.
         *
         * Средние доли заданы жёстко, крайние забирают остаток и потому
         * равны между собой: содержимое встаёт ровно посередине экрана,
         * как и внутренний слой меню со своим max-width. Отсюда общий
         * левый край у названия сайта и первого раздела колонки.
         *
         * Схлопнуться до нуля крайние не могут, минимум равен полю
         * страницы, поэтому на узком экране содержимое не липнет к краю.
         */
        /*
         * Текст берёт минимум из своей ширины и остатка экрана: доля 1fr
         * с потолком в --aside-main. Жёсткая ширина здесь не годится —
         * сумма середин перерастала бы узкое окно, крайним долям нечего
         * было бы отдавать, и текст уезжал бы за правый край.
         */
        grid-template-columns:
            minmax(var(--site-gutter), 1fr)
            var(--aside-width)
            var(--aside-space)
            minmax(0, var(--aside-main))
            minmax(var(--site-gutter), 1fr);
    }

    /*
     * Внутренний слой меню правок не требует: формула каркаса держит его
     * на ширине полосы содержимого, а колонка с текстом стоят внутри той
     * же полосы. Оба центрируются одинаково, поэтому название сайта и
     * первый раздел колонки встают по одному левому краю сами.
     */

    /* Полоса меню во всю ширину экрана, над обеими колонками. */
    .with-aside > .menu {
        grid-area: menu;
    }

    .with-aside > aside {
        grid-area: aside;
    }


    /*
     * Просвет между колонкой и текстом стоит отдельной долей грида, а не
     * полем: поле входило бы в ширину текста, и колонка чтения выходила
     * бы уже заявленной.
     */
    .with-aside > .page-column {
        grid-area: main;
        grid-row: 1 / -1;
        box-sizing: border-box;
        min-height: 0;
        overflow-x: hidden;
        overflow-y: auto;
        overscroll-behavior: contain;
        padding-top: var(--menu-height);
    }

    /*
     * Без правого оглавления область прокрутки доходит до края окна:
     * полоса стоит у края браузера, а не у края текстовой колонки.
     * Сами текст и подвал сохраняют прежнюю ширину.
     */
    .with-aside:not(.with-outline) > .page-column {
        grid-column-end: -1;
    }

    .with-aside > .page-column > main {
        max-width: var(--aside-main);
        margin-inline: 0 auto;
        padding-left: 0;
        padding-right: 20px;
    }

    .with-aside:not(.with-outline) > .page-column > footer {
        max-width: var(--aside-main);
        margin-inline: 0 auto;
        padding-right: 20px;
    }

    /*
     * Колонка и текст занимают второй ряд экрана и прокручиваются каждый
     * внутри себя. Внешняя страница заперта, поэтому Safari не передаёт
     * прокрутку body у края списка и не утягивает весь каркас вверх.
     */
    .with-aside > aside {
        min-height: 0;
        overflow-x: hidden;
        overflow-y: auto;
        overscroll-behavior: contain;
        /*
         * Та же отбивка от меню, что у текста: колонка стоит с ним
         * рядом, и первая строка обоих должна начинаться на одной
         * высоте. Нижнее поле оставляет последнему пункту воздух у края
         * окна, когда список прокручен до конца.
         */
        padding-block: var(--site-space-top);
        scrollbar-width: thin;
    }

}

/*
 * Колонка выключена. Стоит вне медиазапросов: на широком экране надо
 * убрать столбец, на узком — нижнюю полосу, и настройка на обеих
 * ширинах одна.
 *
 * Место в гриде освобождают --aside-width и --aside-space: они уже
 * умножены на --aside-on и обращаются в ноль сами. Здесь остаётся
 * убрать саму колонку, иначе в нулевой доле её содержимое вылезает за
 * край, а внизу полоса просто продолжает висеть.
 */
aside {
    /*
     * Прячется масштабом, а не display: none. Настройка это значение
     * переменной, и убирать колонку надо тоже значением: свойство,
     * которое умеет читать --aside-on, а не отдельное правило под
     * класс. Нулевой масштаб убирает и рисунок, и высоту полосы внизу.
     */
    scale: var(--aside-on, 1);
    overflow: hidden;
}

/*
 * Список разделов. Классов внутри нет: колонка это перечень ссылок, и
 * теги описывают его сами.
 */
aside menu {
    margin: 0;
    padding: 0;
    list-style: none;
}

/*
 * Вложенное меню отбивается от своего раздела так же, как соседние
 * пункты друг от друга: оно продолжение колонки, а не вставка в неё.
 *
 * Отбивка снизу, как и везде: расстояние держит тот, кто стоит выше.
 */
aside menu menu {
    margin: 0 0 2px;
}

aside a {
    display: block;
    color: var(--color-text);
    text-decoration: none;
}

/* Пункт колонки это строка целиком: линия под ней прочертила бы весь пункт. */
aside a:hover {
    text-decoration: none;
}

/*
 * Текущий раздел выделяется весом и краской заголовка: подложка под
 * ссылкой в колонке из пяти пунктов читается как кнопка, которую можно
 * нажать ещё раз.
 */
aside a.here {
    color: var(--color-title);
    font-weight: 600;
}

/*
 * Значок раздела лежит в теге i, как в списках и в форме. Необязателен:
 * колонка без значков выглядит так же, только уже.
 */
aside i {
    display: flex;
    flex: none;
    align-items: center;
    justify-content: center;
}

aside i > img,
aside i > svg {
    display: block;
    width: auto;
    height: auto;
}

/*
 * Широкий экран: разделы столбцом, значок слева от подписи.
 */
@media (min-width: 900px) {
    /* Отбивка снизу: расстояние держит пункт сверху, а не следующий. */
    aside li:not(:last-child) {
        margin-bottom: 2px;
    }

    /*
     * Строка колонки того же роста, что строка списка: поле --step
     * сверху и снизу вокруг строки ритма. Колонка и список стоят на
     * одной странице рядом, и разный рост у одинаковых по смыслу строк
     * сразу заметен.
     *
     * Кегль тот же, что у строки списка: колонка стоит вровень с
     * содержанием страницы, а не приписью к нему.
     */
    aside a {
        box-sizing: border-box;
        display: flex;
        min-height: calc(var(--line) + var(--step) * 2);
        align-items: center;
        /*
         * Просвет уже, чем в строке списка: там значок стоит перед
         * названием с описанием под ним и держит целый блок текста, а в
         * колонке за ним идёт одно слово, и широкий зазор разрывает
         * строку надвое.
         */
        gap: var(--aside-icon-space);
        padding: 0 var(--field-space);
        border-radius: var(--surface-radius);
        font-size: var(--text);
    }

    aside a.here {
        background: var(--color-surface);
    }

    /*
     * Вложенный раздел: подпункт под своим разделом. Список лежит внутри
     * пункта, а не соседом с ним, в отличие от строк: пункт меню — это
     * ссылка со своими подпунктами, и разорвать их значит потерять связь
     * при чтении с экрана.
     *
     *     li
     *         a Раздел
     *         menu
     *             li a Подраздел
     *
     * Уровни перечислены поштучно по той же причине, что и в списках:
     * наследуемую глубину пришлось бы считать от себя самой, а такую
     * ссылку браузер отбрасывает. Трёх хватает: колонка глубже читается
     * хуже любого отступа.
     *
     * Отступ рисуется полем ссылки, а не списка: подложка текущего
     * раздела при этом остаётся во всю ширину колонки и не превращается
     * в лесенку плашек разной длины.
     */
    aside menu menu a {
        padding-left: calc(var(--field-space) + var(--nest-space));
    }

    aside menu menu menu a {
        padding-left: calc(var(--field-space) + var(--nest-space) * 2);
    }

    /*
     * Значок в колонке мельче, чем в строке списка: там он квадрат с
     * подложкой и держит блок текста, а здесь стоит без подложки перед
     * одним словом, и размер списка рядом с ним выглядит великоватым.
     */
    aside i {
        width: var(--aside-icon);
        height: var(--aside-icon);
    }

    aside i > img,
    aside i > svg {
        max-width: 100%;
        max-height: 100%;
    }
}

/*
 * Узкий экран: колонка становится полосой внизу, значок над подписью.
 *
 * Именно полоса внизу, а не выезжающая панель: до неё дотягивается
 * большой палец, она не закрывает содержимое и не требует поведения,
 * чтобы открыться.
 */
@media (max-width: 899px) {
    .with-aside > aside {
        position: fixed;
        right: 0;
        bottom: 0;
        left: 0;
        z-index: 15;
        background: var(--menu-back);
        backdrop-filter: saturate(180%) blur(20px);
        -webkit-backdrop-filter: saturate(180%) blur(20px);
        /* Линия сверху, а не тень: под полосой у нижнего края её не видно. */
        box-shadow: 0 calc(var(--hairline) * -1) 0 var(--separator);
        /*
         * Поле под вырез снизу: на телефонах с жестовой навигацией внизу
         * экрана лежит системная полоса, и подписи уходили бы под неё.
         */
        padding-bottom: env(safe-area-inset-bottom);
    }

    .with-aside > aside > menu {
        display: flex;
        justify-content: space-around;
    }

    /*
     * Подразделы в полосу не помещаются: место в ней есть только под
     * разделы верхнего уровня, и вложенные вставали бы вторым и третьим
     * рядом, отъедая треть экрана. До них добираются со страницы
     * раздела, куда полоса и ведёт.
     */
    .with-aside > aside menu menu {
        display: none;
    }

    .with-aside > aside li {
        flex: 1;
    }

    /*
     * Пункт полосы: значок, под ним подпись. Высота задана целиком,
     * потому что по пункту попадают пальцем, а не курсором.
     */
    .with-aside > aside a {
        display: flex;
        height: var(--tabbar-height);
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 2px;
        color: var(--color-muted);
        font-size: var(--tabbar-text);
        line-height: 1;
        text-align: center;
    }

    .with-aside > aside a.here {
        color: var(--color-accent);
        font-weight: 400;
    }

    .with-aside > aside i {
        width: var(--tabbar-icon);
        height: var(--tabbar-icon);
    }

    .with-aside > aside i > img,
    .with-aside > aside i > svg {
        max-width: 100%;
        max-height: 100%;
    }

    /*
     * Место под полосу в конце страницы: без него последняя строка
     * текста оказывается под ней и дочитать её нельзя.
     */
    .with-aside > .page-column > main {
        padding-bottom: calc(
            var(--tabbar-height) + env(safe-area-inset-bottom) + 24px
        );
    }
}
