/*
 * Кирпич · переменные.
 *
 * Значения объявлены один раз. Блок ссылается на переменную, а не на цвет
 * или размер, поэтому палитра и ритм сайта меняются в одном месте.
 *
 * Значение правится здесь, а не переопределяется в шаблоне сайта. Да,
 * правка меняет вид сразу всех подключённых сайтов — но если величина
 * не подошла одному из них, значит она неверна и в пакете. Второе
 * объявление рядом с импортом расходится с этим при первой же правке.
 */
:root {
    /* Колонка чтения. */
    --site-width: 925px;
    /* Поле до края экрана, пока экран уже колонки. */
    --site-gutter: 20px;
    /*
     * Отбивка содержимого от полосы меню и от низа страницы. Сверху
     * меньше: там текст отделяет ещё и сама полоса, а внизу за
     * последней строкой пусто, и близкий край выглядит обрывом.
     */
    --site-space-top: 24px;
    --site-space-bottom: 64px;

    /* Кегль основного текста. */
    --text: 17px;
    /* Строка ритма: на ней стоят и текст, и заголовки. */
    --line: 22px;
    /* Вертикальное поле пункта списка. */
    --step: 15px;
    /* Просвет между абзацами. Меньше строки: абзац остаётся в потоке. */
    --gap: 17px;

    /* Мелкий текст: подписи под строкой, код внутри абзаца. */
    --text-small: 15px;

    /* Картинка в списке и в плитке: размер миниатюры и ширина колонки. */
    --card-image: 64px;
    /* Две плитки на iPhone 12 mini: (375 - 2*20 - 17) / 2 = 159px. */
    --tile-width: 159px;
    --line-small: 18px;

    /*
     * Подпись под плиткой. Убирается по частям, а не целиком: у витрины
     * работ хватает одних картинок, у каталога название нужно, а
     * описание под ним только сорит.
     *
     * Значением идёт display, а не множитель: подпись это текст, у него
     * нечему стать нулевым, а строка «none» гасит блок как есть.
     */
    --tile-title-display: block;
    --tile-lead-display: -webkit-box;

    /*
     * Отладка раскладки: контуры всех элементов. Толщина множителем,
     * поэтому ноль означает «ничего не рисовать» и лишнего правила под
     * выключенное состояние не нужно.
     */
    --debug-on: 0;
    --debug-color: rgb(255 0 128 / 60%);

    /* Системный шрифт: свой у каждой платформы, грузить нечего. */
    --font:
        -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto,
        'Helvetica Neue', Arial, sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;

    /*
     * Вес заголовков: страницы, секции, подзаголовка в статье. Один на
     * всех, потому что уровень между ними держит размер, а не жирность.
     */
    --title-weight: 800;

    /* Заголовок страницы. Строка равна кеглю: в две строки он не разъезжается. */
    --page-title-size: 34px;
    --page-title-space-under: 10px;

    /* Лид статьи: крупнее основного текста, но легче заголовка. */
    --lead-size: 20px;
    --lead-line: 30px;

    /*
     * Скругление того, что занимает всю колонку: картинка в статье, блок
     * кода. Заметно крупнее, чем у значка: там скругляется квадрат в
     * 29px, здесь снимок во всю ширину, и та же величина на нём просто
     * не читается.
     *
     * Величина одна на всех: картинка и блок кода стоят в тексте
     * соседями, и разное скругление у них читается как небрежность.
     */
    --image-radius: 18px;

    /*
     * Форма угла. border-radius задаёт его размер, corner-shape — кривую,
     * которой угол рисуется. Обычная дуга окружности на крупном радиусе
     * резко стыкуется с прямой стороной, а суперэллипс входит в неё
     * плавно, как скругления в macOS и iOS.
     *
     * squircle это superellipse(2). Свойство новое: браузеры на Chromium
     * его понимают, WebKit и Firefox пока нет. Незнакомое свойство
     * пропускается, и угол остаётся обычным скруглением того же размера,
     * поэтому ставить его можно уже сейчас.
     */
    --corner-shape: squircle;

    /*
     * Скругление мелкой плашки: подложка строки, кнопка колонки. Мельче
     * картинки — плашка размером со строку, и крупная скруглённость
     * превращает её в таблетку.
     */
    --surface-radius: 8px;

    /* Значок в начале строки списка: квадрат со скруглением. */
    --icon-size: 29px;
    --icon-radius: 6px;
    --icon-space: 16px;

    /*
     * Ступень вложенного списка. Каждый следующий уровень отходит вправо
     * на неё же: правило рекурсивное, поэтому величина одна на все
     * уровни. На узком экране блок уменьшает её вдвое сам.
     */
    --nest-space: 20px;

    /* Заголовок секции: размер и поля. */
    --title-size: 22px;
    --title-space: 30px;
    --title-space-under: 10px;

    /*
     * Значок перед заголовком секции. Размер равен кеглю заголовка: значок
     * держится наравне с текстом, а не спорит с ним и не теряется.
     */
    --title-icon-size: var(--title-size);
    --title-icon-space: 10px;

    /*
     * Показывать ли полосу меню. Ноль убирает её вместе с высотой:
     * содержимое поднимается к верху страницы, а боковая колонка
     * перестаёт отступать от полосы, которой больше нет.
     */
    --menu-on: 1;

    /* Меню: высота полосы, просвет между разделами, кегль. */
    --menu-height: calc(50px * var(--menu-on));
    --menu-gap: 25px;
    --menu-text: 15px;
    /* Название сайта и приписка рядом с ним. */
    --menu-brand: 24px;
    --menu-note: 13px;
    /*
     * Вид полосы меню. Два готовых: стекло и растворение.
     *
     *     0 — стекло: полупрозрачная заливка, размытие под ней и тонкая
     *         полоска снизу. Край полосы виден, содержимое под ним
     *         обрывается.
     *     1 — растворение: заливки и полоски нет, под меню лежит полоса,
     *         сходящая на нет книзу. Край не читается, содержимое тает,
     *         уходя под полосу.
     *
     * Одной переменной, а не четырьмя галочками: это два цельных
     * решения, а не набор независимых свойств. Части ниже всё равно
     * выводятся из неё, и любую можно переопределить отдельно, если
     * понадобится третий вид.
     */
    --menu-view: 0;

    /*
     * Части полосы. Каждая включается своей переменной, но значение по
     * умолчанию берёт из вида: стекло это заливка с размытием и
     * полоской, растворение — только заливка снизу.
     */

    /* Заливка полосы: цвет и его непрозрачность. */
    --menu-back-on: calc(1 - var(--menu-view));
    --menu-back-color: var(--color-page);
    --menu-back-alpha: 0.7;
    --menu-back: rgb(
        from var(--menu-back-color) r g b /
        calc(var(--menu-back-alpha) * var(--menu-back-on))
    );

    /*
     * Размытие под полосой. Само по себе видно только сквозь
     * полупрозрачную заливку: под сплошной размывать нечего.
     */
    --menu-blur-on: calc(1 - var(--menu-view));
    --menu-blur: calc(20px * var(--menu-blur-on));
    /*
     * Насыщенность под полосой. Единица это «как есть»: при выключенном
     * размытии стекла нет, и подкрашивать страницу нечем и незачем.
     * Отсчёт идёт от неё, а не от нуля, иначе полоса обесцвечивала бы
     * то, что под ней проходит.
     */
    --menu-saturate: calc(1 + 0.8 * var(--menu-blur-on));

    /*
     * Растворение: второй способ отделить полосу от страницы вместо
     * стекла. Под меню лежит полоса заливки, сходящая на нет книзу, и
     * содержимое не обрывается под краем полосы, а тает, уходя под неё.
     *
     * Выше самой полосы и выходит за её низ: если растворение кончается
     * там же, где полоса, переход получается резким, край читается
     * чертой, и смысл приёма теряется.
     *
     * Отношение 1,4: при полосе в 50px заливка занимает 70px, то есть
     * заходит за низ на два десятка. Меньше — переход снова жёсткий,
     * больше — заливка расползается на четверть экрана.
     */
    --menu-fade-on: var(--menu-view);
    --menu-fade-color: var(--color-page);
    --menu-fade-height: calc(var(--menu-height) * 1.4);
    /*
     * Тень под полосой вместо линии: под стеклом жёсткий волосок читается
     * как шов. Два слоя, ближний и дальний, дают мягкий край без заметной
     * серой полосы.
     *
     * Цвет и включённость свои: тень отделяет полосу от страницы, и на
     * тёмном фоне или под сплошной заливкой она нужна не всегда.
     */
    --menu-shadow-on: calc(1 - var(--menu-view));
    --menu-shadow-color: rgba(0, 0, 0, 0.1);
    --menu-shadow:
        0 1px 3px rgb(
            from var(--menu-shadow-color) r g b / calc(alpha * var(--menu-shadow-on))
        ),
        0 1px 2px -1px rgb(
            from var(--menu-shadow-color) r g b / calc(alpha * var(--menu-shadow-on))
        );

    /*
     * Логотип рядом с названием сайта: герб, эмблема, знак. Заодно
     * задаёт рост аватарки: слева и справа от меню стоят кружок и знак
     * одного размера, поэтому полоса выглядит уравновешенной.
     *
     * Меньше высоты полосы: иначе картинка растягивает меню, а не
     * вписывается в него.
     */
    --menu-logo: 36px;
    /*
     * Подложка знака. Круг по умолчанию: знак в нём читается эмблемой, а
     * не картинкой рядом с названием. Прозрачный фон и нулевые поля
     * возвращают логотип как есть — герб или готовую эмблему обводить
     * второй раз не надо.
     */
    --menu-logo-radius: 50%;
    --menu-logo-back: var(--color-title);
    --menu-logo-color: var(--color-page);
    --menu-logo-space: 7px;

    /*
     * Боковая колонка: разделы столбцом слева от текста. Прибавляется к
     * колонке чтения, а не отъедает от неё, поэтому текст читается так
     * же, как на странице без неё.
     */
    /*
     * Показывать ли колонку. Ноль убирает её вместе с занимаемым местом:
     * ширина и просвет обнуляются, и текст встаёт на всю полосу, потому
     * что --aside-main считается остатком от неё.
     *
     * Множитель, а не display: none на самой колонке. Скрытая колонка
     * оставила бы за собой долю грида, и текст остался бы сдвинутым
     * вправо на её ширину.
     */
    --aside-on: 1;

    --aside-width: calc(220px * var(--aside-on));
    --aside-space: calc(40px * var(--aside-on));
    /*
     * Ширина текста рядом с колонкой: остаток полосы содержимого после
     * самой колонки и просвета. Считается здесь, а не в блоке, потому
     * что вместе с --site-width, --aside-width и --aside-space образует
     * одну сумму: полоса содержимого от появления колонки не меняется.
     */
    --aside-main: calc(
        var(--site-width) - var(--aside-width) - var(--aside-space)
    );
    /*
     * Значок в колонке: сам рисунок, без подложки. Мельче квадрата из
     * строки списка, где значок держит блок текста, а не одно слово.
     */
    --aside-icon: 20px;
    /*
     * Просвет между значком и подписью в колонке. Уже, чем в строке
     * списка: там за значком идёт название с описанием под ним, а здесь
     * одно слово, и широкий зазор разрывает строку надвое.
     */
    --aside-icon-space: 10px;
    /*
     * Порог, ниже которого колонка не помещается рядом с текстом и
     * становится полосой внизу, записан в самом блоке числом: медиазапрос
     * переменных не понимает, и переменная здесь была бы обманом.
     */

    /* Высота полосы внизу экрана: строка подписи и значок над ней. */
    --tabbar-height: 56px;
    --tabbar-icon: 24px;
    --tabbar-text: 11px;

    /*
     * Аватарка: круг с буквой в конце меню. Размер свой, а не от логотипа:
     * круг с одной буквой при высоте логотипа выглядит тяжелее названия
     * сайта и перетягивает конец полосы на себя.
     */
    --avatar-size: 30px;
    --avatar-text: 13px;
    --avatar-back: var(--color-accent);
    --avatar-color: #fff;

    /*
     * Кегль в поле ввода. Не меньше 16px: Safari на телефоне увеличивает
     * страницу при фокусе в поле с мелким текстом, и после выхода из поля
     * вёрстка остаётся увеличенной.
     */
    --field-text: 16px;
    /* Просвет между флажком согласия и его текстом. */
    --field-space: 12px;

    /*
     * Флажок согласия. Крупнее строчной буквы: по нему попадают пальцем
     * на телефоне, а не курсором.
     */
    --check-size: 20px;

    /*
     * Кнопка: таблетка во всю ширину формы. Скругление заведомо больше
     * половины высоты, поэтому торцы остаются полукруглыми и высоту не
     * приходится повторять в скруглении.
     */
    --button-height: 52px;
    --button-radius: 140px;

    /* Разделитель: на retina тоньше пикселя, иначе выглядит грубо. */
    --hairline: 1px;
    --separator: rgba(0, 0, 0, 0.09);

    /*
     * Краска разделителя. Рисуется фоном, а не бордером: так линия не
     * участвует в раскладке и не сдвигает содержимое.
     *
     * Блок задаёт ей позицию и размер сам, потому что у списка линия
     * стоит сверху пункта (0 0), а у заголовка снизу (0 100%):
     *
     *     background: var(--separator-line) 0 0 / 100% var(--hairline)
     *         no-repeat;
     */
    --separator-line: linear-gradient(
        to bottom,
        var(--separator) var(--hairline),
        transparent var(--hairline)
    );

    /*
     * Заливка вверху страницы: цвет у верхнего края, тающий в фон к
     * низу полосы. Держится на месте при прокрутке, содержимое проходит
     * поверх неё.
     *
     * Ноль убирает её целиком: непрозрачность и есть выключатель, и
     * отдельного «да/нет» тут не нужно.
     */
    --glow-on: 0;
    --glow-color: #bf9aff;
    /* Докуда тает. Доля высоты экрана, а не пикселей: полоса та же на любом экране. */
    --glow-height: 25vh;

    /* Фон страницы. */
    --color-page: #fff;
    --color-title: #1d1d1f;
    --color-text: rgba(29, 29, 31, 0.82);
    --color-accent: #4267a9;
    /* Приглушённый текст: подписи, цитаты, номера пунктов. */
    --color-muted: rgba(29, 29, 31, 0.45);
    /* Подложка: блок кода, плашки. */
    --color-surface: #f2f2f7;
}

/*
 * Тёмная тема. Переопределяются только цвета: ритм, размеры и формы у
 * обеих тем общие, и разъезжаться им незачем.
 *
 * Включается двумя способами. Системная настройка — но лишь пока сайт
 * не сказал иное, поэтому :not([data-theme='light']). И прямой выбор
 * через data-theme, вне медиазапроса: нажатая на сайте кнопка должна
 * работать при любой настройке в системе, выбор человека главнее
 * системного.
 *
 * Палитра написана дважды, по разу на способ. Свести её в один набор
 * без препроцессора нельзя: селекторы живут в разных условиях. Копия
 * держится рядом, чтобы правка сразу попадала в обе.
 */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme='light']) {
        color-scheme: dark;

        --color-page: #16161a;
        --color-title: #f5f5f7;
        --color-text: rgba(245, 245, 247, 0.82);
        --color-accent: #7aa2e3;
        --color-muted: rgba(245, 245, 247, 0.45);
        --color-surface: #232329;

        /*
         * Разделители и тень на тёмном строятся из светлого, а не из
         * чёрного: чёрная линия на тёмном фоне не видна вовсе.
         */
        --separator: rgba(255, 255, 255, 0.12);
        --menu-shadow-color: rgba(0, 0, 0, 0.5);
    }
}

/*
 * Светлая тема выбрана вручную. Своих цветов не объявляет: они уже
 * стоят в :root, а медиазапрос выше её не трогает из-за :not(). Здесь
 * остаётся сказать браузеру, какие ему рисовать полосы прокрутки и
 * системные поля.
 */
:root[data-theme='light'] {
    color-scheme: light;
}

:root[data-theme='dark'] {
    color-scheme: dark;

    --color-page: #16161a;
    --color-title: #f5f5f7;
    --color-text: rgba(245, 245, 247, 0.82);
    --color-accent: #7aa2e3;
    --color-muted: rgba(245, 245, 247, 0.45);
    --color-surface: #232329;

    --separator: rgba(255, 255, 255, 0.12);
    --menu-shadow-color: rgba(0, 0, 0, 0.5);
}

@media (min-width: 640px) {
    :root {
        --site-gutter: 28px;
    }
}

@media (-webkit-min-device-pixel-ratio: 2) {
    :root {
        --hairline: 0.5px;
    }
}

@media (-webkit-min-device-pixel-ratio: 3) {
    :root {
        --hairline: 0.33px;
    }
}
