/*
Theme Name: Жидкое стекло
Description: Светлая тема, собранная из полупрозрачных стеклянных панелей. На главной — спутниковая карта Беларуси. Цвета, плотность стекла, кнопки и вид карты настраиваются в «Внешний вид → Настроить».
Author: Школьный проект «Родина. Цифровой след»
Version: 3.70.1
Requires at least: 6.0
Requires PHP: 7.4
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: rb-memorial
*/

/* ═══════════════════════════════════════════════════════════════════════
   Этот файл — общий вид сайта: шрифт, цвета, кнопки, шапка, подвал, текст.
   Всё, что относится только к карте, лежит отдельно в assets/css/map.css.

   Цвета и размеры заданы переменными в :root. Значения ниже — запасные:
   на живом сайте их перекрывает блок, который тема печатает в <head>
   по настройкам из «Внешний вид → Настроить».
   ═══════════════════════════════════════════════════════════════════════ */


/* ── Шрифт ──────────────────────────────────────────────────────────────
   Inter — свободный шрифт, ближайший по рисунку к системному шрифту Apple.
   Лежит у нас в теме, а не подключается с серверов Google: так браузер
   посетителя не ходит на сторонний домен. Файл вариативный — одна начертание
   покрывает весь диапазон толщин от тонкого до жирного.
   Разбит по алфавитам: браузер скачает кириллицу и не тронет остальное. */
@font-face {
    font-family: "Inter var";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("assets/fonts/inter-cyrillic-ext.woff2") format("woff2");
    unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}

@font-face {
    font-family: "Inter var";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("assets/fonts/inter-cyrillic.woff2") format("woff2");
    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
    font-family: "Inter var";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("assets/fonts/inter-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
                   U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
                   U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: "Inter var";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("assets/fonts/inter-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                   U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                   U+2212, U+2215, U+FEFF, U+FFFD;
}


/* ── Переменные ─────────────────────────────────────────────────────────
   Ни один цвет и размер ниже не написан «прямо в правиле» — всё через
   переменные. Благодаря этому настройки темы меняют вид сайта целиком,
   а карта в assets/js/map.js читает те же переменные и не может
   разъехаться с вёрсткой. */
:root {
    --accent: #0071e3;
    --ink: #1d1d1f;              /* основной текст, никогда не чистый чёрный */
    --ink-muted: rgba(0, 0, 0, .56);
    --surface: #f5f5f7;          /* нейтральный фон страницы */

    /* Состояние культурной ценности. Цвет один и тот же у кружка в метке
       на карте и у плашки в карточке объекта, поэтому живёт здесь,
       а не в каждом из двух мест отдельно: разъехаться им нельзя,
       иначе красное на карте окажется не тем красным, что в карточке.

       Рядом с каждым — цвет надписи. Сам красный на светлой плашке даёт
       около 3:1, для текста этого мало; тёмный — 6:1 и выше. С жёлтым
       ещё хуже: жёлтые буквы не читаются вовсе. */
    /* Зелёный «одобрить». Тёмный, а не яблочный салатовый: на нём
       белые буквы, и светлый даёт меньше трёх к одному. */
    --positive: #1c7f3e;

    --status-lost: #e30000;
    --status-lost-ink: #8a1c18;
    --status-restoration: #f5b800;
    --status-restoration-ink: #6b4a00;

    /* «Материал» — полупрозрачное стекло, из которого сделан весь интерфейс.
       Три плотности: чем больше текста несёт поверхность, тем она плотнее,
       иначе буквы теряют контраст на фоне карты. */
    --material-thin: rgba(255, 255, 255, .62);
    --material: rgba(255, 255, 255, .8);
    --material-strong: rgba(255, 255, 255, .93);
    /* Тёмное стекло — не плотность белого, а другой цвет. Белое стекло
       на светлой странице почти не отличимо от неё, а знак сайта должен
       выделяться. Заливкой поверхностей оно не служит: из него сделан
       знак, см. .glass-mark. */
    --material-dark: rgba(0, 0, 0, .72);
    --vibrancy: saturate(1.8) blur(20px);
    --hairline: rgba(0, 0, 0, .06);

    /* Из чего складывается убедительное стекло, кроме размытия.
       Блик — свет, скользящий по верхней кромке и слабое отражение снизу.
       Кромки — светлая полоска сверху и едва заметная тень снизу: именно
       они читаются как толщина материала, а не как нарисованная рамка. */
    /* Плотность и тень числами — для мест, где стекло собрано не заливкой
       и нужен расчёт. Значения перекрываются настройками темы. */
    --glass-density: .8;
    --shadow-strength: .18;

    --glass-sheen: linear-gradient(
        180deg,
        rgba(255, 255, 255, .38),
        rgba(255, 255, 255, .06) 46%,
        rgba(255, 255, 255, .14)
    );
    --glass-edges:
        inset 0 1px 0 rgba(255, 255, 255, .72),
        inset 0 -1px 0 rgba(0, 0, 0, .05),
        inset 1px 0 0 rgba(255, 255, 255, .22),
        inset -1px 0 0 rgba(255, 255, 255, .22);

    --pill: 980px;               /* полное скругление таблетки */
    --tap: 44px;                 /* цель касания пальцем */
    --tap-fine: 38px;            /* то же для мыши — она точнее */
    /* Три высоты подъёма над фоном. Силу всех трёх задаёт одна настройка
       «Тень» в разделе «Стекло»; значения ниже — запасные. */
    --shadow: 0 4px 14px rgba(0, 0, 0, .18);
    --shadow-soft: 0 2px 8px rgba(0, 0, 0, .12);
    --shadow-lifted: 0 10px 34px rgba(0, 0, 0, .16);

    --header-height: 52px;
    --header-title: 15px;

    --ease: cubic-bezier(.25, .1, .25, 1);
    --font: "Inter var", -apple-system, BlinkMacSystemFont, system-ui, "Segoe UI",
            Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif;
}


/* ── Основа ─────────────────────────────────────────────────────────── */
*,
*::before,
*::after {
    box-sizing: border-box;
}

/* Атрибут hidden должен прятать что угодно.
   Браузер понимает его как display: none, но это самое слабое правило,
   какое бывает, и любой наш display его перебивает. Элемент со своим
   display — flex, grid, inline-flex — остаётся на виду, хотя в разметке
   стоит hidden, и ошибка эта из неочевидных: в коде страницы всё
   правильно, а на экране нет. Наступали дважды: на сообщении об ошибке
   под полем ввода и на надписи «фотографий пока нет». Одно правило
   закрывает случай навсегда. */
[hidden] {
    display: none !important;
}

/* Верхней панели WordPress на сайте нет — её прячет тема (inc/cleanup.php).
   Эти два правила остаются подстраховкой: вернут панель — сайт не поедет.
   Отступ она навязывает свой, поэтому его гасим, а сдвиг делаем сами,
   переменной, которую подставляет сам WordPress. */
html {
    margin-top: 0 !important;
}

body {
    --chrome-top: 0px;
    margin: 0;
    font-family: var(--font);
    font-size: 16px;
    line-height: 1.55;
    color: var(--ink);
    background: var(--surface);
    -webkit-font-smoothing: antialiased;
}

body.admin-bar {
    --chrome-top: var(--wp-admin--admin-bar--height, 32px);
}

/* Снимки Esri отдаются «как есть» и рядом со светлым фоном смотрятся
   тускло. Небольшой подъём цвета — карта становится сочнее, но остаётся
   правдоподобной. Фильтр работает потому, что слою снимков задан свой
   класс, и OpenLayers рисует его в отдельный canvas.

   Правило общее: этот слой есть и на большой карте, и в окне «Показать
   на карте», и выглядеть они должны одинаково. */
.satellite-layer {
    filter: saturate(var(--map-image-saturation, 1.22))
            brightness(var(--map-image-brightness, 1.07))
            contrast(1.03);
}

a {
    color: var(--accent);
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}

img {
    max-width: 100%;
    height: auto;
}

.skip-to-content {
    position: absolute;
    top: -100px;
    left: 12px;
    z-index: 100;
    padding: 10px 16px;
    background: var(--material-strong);
    border-radius: 10px;
}

.skip-to-content:focus {
    top: calc(var(--chrome-top) + 8px);
}


/* ── Стекло: общий слой интерфейса ──────────────────────────────────────
   Классы ниже — единственный источник «стеклянного» вида. Новый элемент
   берёт готовый класс, а не собирает эффект заново.

   Стекло даёт ровно один класс — .glass. Он вешается на что угодно: блок,
   карточку, кнопку, шапку. Плотность, размытие, насыщенность и тень берутся
   из настроек темы, поэтому меняются везде разом.

   Классы вида .button и .panel сами по себе стекла НЕ дают — они отвечают
   только за размер и форму. Стеклянность всегда написана в разметке,
   поэтому по коду страницы сразу видно, что из чего сделано.

   Два правила, которые легко нарушить по незнанию:
   1. Стекло не вкладывают в стекло. Размытие берёт то, что ЗА элементом,
      поэтому вложенные слои просто мутнеют. Стекло держит внешняя панель,
      внутри неё — обычные прозрачные блоки.
   2. Плотность выбирают по количеству текста: thin — метка в пару слов,
      strong — форма или карточка с описанием. */
/* Второй селектор — из-за плагина карты. Его правило
   `.wpgmza_map .ol-viewport .ol-control button` весит больше любого класса
   и перекрашивало кнопки масштаба в сплошной белый; перебить его можно
   только идентификатором. Свойства при этом написаны один раз — задвоен
   только список селекторов.

   Область действия у этой добавки нарочно узкая: внутри карты и нигде
   больше. Раньше она была просто `#content .glass` и потому накрывала
   любую панель на любой странице. Идентификатор перебивает не только
   плагин, но и наши собственные классы: красная плашка ошибки и зелёная
   плашка удачи оставались белыми, и каждой пришлось заводить такую же
   пару. Чем уже добавка, тем меньше правил тянут за собой близнеца. */
.glass,
#content .wpgmza_map .glass {
    /* Цвет и блик — два разных слоя одного фона: сначала градиент, под ним
       заливка. Так блик не мешает менять плотность стекла в настройках. */
    background-color: var(--material);
    background-image: var(--glass-sheen);
    -webkit-backdrop-filter: var(--vibrancy);
    backdrop-filter: var(--vibrancy);
    border: 1px solid var(--hairline);
    box-shadow: var(--glass-edges), var(--shadow);
    color: var(--ink);
}

/* Две другие плотности того же стекла. Выбирают по количеству текста:
   тонкое — метка в пару слов, плотное — форма или карточка с описанием.
   Чем больше текста, тем плотнее подложка, иначе буквы теряют контраст. */
.glass--thin {
    background-color: var(--material-thin);
    box-shadow: var(--glass-edges), var(--shadow-soft);
}

.glass--strong {
    background-color: var(--material-strong);
    box-shadow: var(--glass-edges), var(--shadow-lifted);
}

.panel {
    border-radius: 18px;
    padding: 24px;
}

/* Отступы крайних абзацев складывались бы с отступом панели, и сверху
   выходило бы вдвое больше, чем по бокам. */
.panel > :first-child {
    margin-top: 0;
}

.panel > :last-child {
    margin-bottom: 0;
}

/* Табличка входа. Высоту задают настройки темы; 0 означает «по содержимому»,
   и тогда min-height ни на что не влияет. Если высоту задали больше, чем
   нужно полям, содержимое остаётся по центру, а не липнет к верхнему краю. */
.auth-panel {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: var(--login-height, 0px);
}

/* ── Кнопки ─────────────────────────────────────────────────────────────
   Три вида: стеклянная (обычная), главная и кругляш.

   Каждый размер и цвет записан так: сначала своя переменная вида, а если
   её нет — общая. Например `var(--pill)`.
   Свою переменную тема печатает только тогда, когда в настройках включили
   «настроить отдельно» для этого вида. Пока не включили — все виды слушают
   общие настройки и выглядят согласованно, а значения не продублированы. */

.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    min-height: var(--tap);
    padding: 11px 21px;
    font: 400 17px/1.2 var(--font);
    letter-spacing: -.013em;
    border-radius: var(--pill);
    box-shadow: var(--glass-edges), var(--shadow);
    text-decoration: none;
    cursor: pointer;
    /* box-shadow в переходе намеренно нет. Ни наведение, ни нажатие тень
       не меняют, так что анимировать нечего. Хуже того: пока переход на неё
       висел, браузер переставал обновлять тень при смене переменной —
       ползунок «Тень» в настройках не действовал на кнопки до перезагрузки. */
    transition:
        background-color 180ms var(--ease),
        border-color 180ms var(--ease),
        color 180ms var(--ease),
        transform 180ms var(--ease);
}

.button:hover {
    background-color: var(--material-strong);
    transform: translateY(-1px);
}

.button:active {
    transform: scale(.96);
}


/* Главное действие — сплошная заливка, а не стекло. Белый текст на синем
   стекле даёт около 3.5:1 даже при плотности 95%, это ниже нормы читаемости;
   сплошной цвет держит 5.3:1. */
.button--primary {
    min-height: var(--tap);
    border-radius: var(--pill);
    background-color: var(--accent);
    border-color: transparent;
    color: #fff;
    box-shadow: var(--shadow);
}

/* Вторичная кнопка: пустая, с обводкой и буквами цвета ссылки, а при
   наведении заливается и становится главной. Так у apple.com — у них
   прозрачный фон, цвет и обводка #06c, при наведении заливка и белый
   текст. Цвет берём свой, из настроек: иначе вторичная кнопка станет
   при наведении не такой, как соседняя главная.

   Тень ей не нужна: пустая кнопка не «лежит» на странице, а нарисована
   на ней, и приподнимать нечего. */
/* Решения проверяющего. Обе — главные кнопки: человек пришёл сюда
   именно решать, и прятать одну из двух в оформление второстепенной
   значило бы подталкивать к ответу. */
.button--approve {
    min-height: var(--tap);
    border-radius: var(--pill);
    background-color: var(--positive);
    border-color: transparent;
    color: #fff;
    box-shadow: var(--shadow);
}

.button--approve:hover {
    background-color: var(--positive);
    filter: brightness(1.12);
}

.button--reject {
    min-height: var(--tap);
    border-radius: var(--pill);
    background-color: var(--status-lost);
    border-color: transparent;
    color: #fff;
    box-shadow: var(--shadow);
}

.button--reject:hover {
    background-color: var(--status-lost);
    filter: brightness(1.12);
}

.button--secondary {
    background-color: transparent;
    border: 1px solid var(--accent);
    color: var(--accent);
    box-shadow: none;
}

.button--secondary:hover {
    background-color: var(--accent);
    color: #fff;
}

/* Мелкая кнопка — для шапки: в полосу высотой 52 пикселя обычная
   в 44 не помещается, оставляя по четыре пикселя сверху и снизу. */
.button--small {
    min-height: 34px;
    padding: 0 15px;
    font-size: 15px;
}

.button--primary:hover {
    background-color: var(--accent);
    filter: brightness(1.08);
}


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

   Стекло у него из общего правила выше: кругляш часто ставят одним классом,
   без `.button`, поэтому он перечислен там наравне с остальными.

   Вторые селекторы — та же добавка для карты, что у стекла, и по той же
   причине: единственный кругляш на сайте это кнопка масштаба, а её размер
   и скругление плагин задаёт своими правилами потяжелее наших классов. */
.button--round,
#content .wpgmza_map .button--round {
    width: var(--tap);
    height: var(--tap);
    min-height: 0;
    padding: 0;
    border-radius: var(--pill);
    font-size: calc(var(--tap) * .48);
}

.button--round:hover,
#content .wpgmza_map .button--round:hover {
    background-color: var(--material-strong);
}

@media (pointer: fine) {
    .button--round,
    #content .wpgmza_map .button--round {
        width: var(--tap-fine);
        height: var(--tap-fine);
        font-size: calc(var(--tap-fine) * .48);
    }
}

/* Чип: короткая метка на стекле. Своя тень мягче, чем у кнопки, но кромки
   те же — без них метка выглядит наклейкой, а не кусочком материала. */
.small-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 11px;
    font-size: 12px;
    letter-spacing: -.01em;
    border-radius: var(--pill);
}

/* ── Формы ──────────────────────────────────────────────────────────────
   Строка ввода снята с формы поиска на странице «не найдено» у apple.com
   (файл pagenotfound.css), поэтому числа здесь странные на вид, но не
   выдуманные: у них размеры записаны в rem при основании 17 пикселей,
   а тут переведены в пиксели.

   Как это работает. Поле высокое — 56 пикселей, — и текст в нём начинается
   не от верха, а с отступом 18. Пустое место сверху занимает подпись: пока
   поле пустое, она стоит в строке текста и выглядит как подсказка внутри
   поля; стоит начать печатать или просто щёлкнуть — уезжает вверх, в тот
   самый отступ, и уменьшается до 12 пикселей.

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

   Делается это без единой строчки скрипта, на :placeholder-shown. Отсюда
   и placeholder=" " в разметке: пробел — не пустота, поэтому браузер
   считает подсказку заданной, а правило ниже отличает пустое поле
   от заполненного. Без пробела правило не работает вовсе. */
.form {
    display: grid;
    gap: 16px;
    margin-top: 22px;
}

.text-field {
    position: relative;
}

.text-field__input {
    appearance: none;
    box-sizing: border-box;
    width: 100%;
    height: 56px;
    /* Сверху 18 — место для уехавшей подписи. Слева 44 — место для значка. */
    padding: 18px 16px 0 44px;
    border: 1px solid #86868b;
    border-radius: 12px;
    /* Поле намеренно не берёт плотность из настроек стекла. Сквозь текст,
       который человек печатает, не должна просвечивать карта: у apple.com
       здесь тоже почти непрозрачный белый. */
    background-color: rgba(255, 255, 255, .8);
    color: var(--ink);
    font-family: inherit;
    font-size: 17px;
    letter-spacing: -.022em;
    line-height: 1.235;
}

/* При выделении граница синеет и становится вдвое толще. Толщину даёт
   не border-width, а внутренняя тень в один пиксель поверх границы.

   У apple.com здесь именно border-width: 2px, но тогда приходится
   уменьшать отступы на тот же пиксель, иначе текст и значок дёргаются
   в момент щелчка, — и вдобавок жмётся внутренний край скругления
   (внешний радиус 12, внутренний — 12 минус толщина границы).
   Внутренняя тень ложится поверх границы: и внешний край, и оба
   скругления, и отступы остаются на месте. Полоса той же толщины,
   подгонять нечего. */
.text-field__input:focus {
    border-color: var(--accent);
    box-shadow: inset 0 0 0 1px var(--accent);
    /* Кольцо фокуса тут не нужно: сама граница и есть указатель — синяя,
       вдвое толще обычной. Такое исключение из общего правила сайта
       допустимо ровно потому, что заметный признак фокуса остаётся. */
    outline: none;
}

.text-field__label {
    position: absolute;
    top: 18px;
    left: 45px;
    max-width: calc(100% - 60px);
    overflow: hidden;
    color: #6e6e73;
    font-size: 17px;
    letter-spacing: -.022em;
    line-height: 1.235;
    white-space: nowrap;
    text-overflow: ellipsis;
    /* Ровно как у них: 0.125 секунды, ускоряясь к концу. */
    transition: all 125ms ease-in;
}

/* Подпись уехала наверх: поле в работе или уже заполнено. */
.text-field__input:focus + .text-field__label,
.text-field__input:not(:placeholder-shown) + .text-field__label {
    top: 10px;
    font-size: 12px;
    letter-spacing: -.01em;
    line-height: 1.333;
}

.text-field__icon {
    position: absolute;
    top: 16px;
    left: 12px;
    color: #6e6e73;
    /* Значок не перехватывает щелчки: они должны доходить до поля. */
    pointer-events: none;
}


/* ── Поле выбора ────────────────────────────────────────────────────────
   Снаружи — то же поле ввода: та же рамка, тот же значок, то же место
   для ошибки. Внутри — то же меню, что раскрывает название сайта
   в шапке: с него и снято. Поэтому здесь нет ни своего стекла, ни своих
   строк, ни своего появления — всё это уже описано у .site-menu, и всё
   это достаётся полю даром.

   Подпись у выбора всегда наверху: пустоты у списка нет — что-то в нём
   выбрано всегда, пусть даже строка «Не выбрано», — и ездить ей не по чему. */
.text-field--select .text-field__input {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    /* Справа место под галочку, слева — под значок, как у поля ввода. */
    padding: 18px 14px 0 44px;
    text-align: left;
    cursor: pointer;
}

.text-field--select .text-field__label {
    top: 10px;
    font-size: 12px;
    letter-spacing: -.01em;
    line-height: 1.333;
    /* Подпись тут не <label>, а надпись: нажатие должно доходить
       до кнопки под ней. */
    pointer-events: none;
}

/* Галочка та же, что у названия сайта, и переворачивается так же. */
.text-field--select .icon--chevron {
    flex: 0 0 auto;
    color: #6e6e73;
    transition: transform 200ms var(--ease);
}

.text-field--select [aria-expanded="true"] .icon--chevron {
    transform: rotate(180deg);
}

/* Пока ничего не выбрано, значение бледнее: это не ответ, а приглашение. */
.select-field__value--empty {
    color: #86868b;
}

/* Меню шапки закреплено на экране под шапкой, а это висит под своим
   полем — в этом первое отличие.

   Второе было в заливке: своя, почти непрозрачная (94 процента), и список
   читался обычным белым прямоугольником — при том, что в шапке тот же
   список выглядит стеклянным. Классы у них одинаковые, разница была
   только в этой подмене.

   Своя заливка осталась, но теперь она вдвое прозрачнее штатного лёгкого
   стекла: у списка двадцать процентов против сорока у меню шапки. Меню
   висит над картой, где сквозь стекло видно снимок, и сорока хватает;
   список висит над белой формой, и сорок там читаются почти сплошным
   белым — при том, что подложки под ним и так белые. Двадцать дают
   заметную прозрачность и не мешают читать строки.

   Размытие добавлено к настроенному (фильтры складываются, настройка
   «Размытие» в теме работает по-прежнему), но вложенным стеклом оно почти
   не помогает: подписи полей под списком всё равно видны как есть.
   Это цена прозрачности — на снимке её видно.

   Выше четверти экрана не растёт: список стоит поверх формы, и панель
   во весь экран закрыла бы собой то, ради чего её открыли. Полосы
   прокрутки не видно: своей рамки у панели почти нет, и системная полоса
   была бы в ней единственной системной вещью. Прокрутку это не отменяет. */
.text-field--select .site-menu {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    min-width: 0;
    max-width: none;
    max-height: 25vh;
    overflow-y: auto;
    scrollbar-width: none;

    background-color: rgba(255, 255, 255, .2);
    -webkit-backdrop-filter: var(--vibrancy) blur(60px);
    backdrop-filter: var(--vibrancy) blur(60px);
    /* Тень выше, чем у меню шапки: та висит на странице, а эта — над
       формой, и поднять её надо над тем, что к ней вплотную. */
    box-shadow: var(--glass-edges), var(--shadow-lifted);
}

.text-field--select .site-menu::-webkit-scrollbar {
    display: none;
}

/* Строка меню здесь — кнопка, а не ссылка: выбор никуда не ведёт. Вид
   у неё общий, от .site-menu__item; тут только то, что кнопке приходится
   снимать с себя самой. */
.text-field--select .site-menu__item {
    width: 100%;
    border: 0;
    background: none;
    font: inherit;
    font-size: 14px;
    text-align: left;
    cursor: pointer;
}

/* Выбранная строка — тем же цветом, каким в шапке отмечен текущий
   раздел: человек уже знает этот знак. */
.text-field--select .site-menu__item[aria-current="true"] {
    color: var(--accent);
}


/* Галочка. Размеры из bag.css у apple.com, там же, где корзина: квадрат
   14 пикселей, скругление 3, граница 1 пиксель #86868b на почти белом,
   включённая — сплошная синяя с белой галкой.

   Вид задан самому полю через appearance: none, а не нарисован рядом
   вместо него. Так пробовал сначала: настоящее поле прозрачное, поверх
   свой квадрат. Отказался — прозрачное поле выпадает из дерева
   доступности, то есть программа чтения с экрана его не находит,
   и нажатие срабатывало не всегда. Приём известный и всё равно плохой:
   ради внешности ломается то, что работало.

   appearance: none снимает с поля вид, заданный операционной системой,
   и оставляет само поле: фокус, пробел, чтение с экрана, щелчок по
   подписи. Родная настройка accent-color тут не годится — она меняет
   только цвет заливки, а нам нужны своё скругление и размер. */
.checkbox {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 15px;
    cursor: pointer;
}

.checkbox__input {
    appearance: none;
    -webkit-appearance: none;
    flex: 0 0 auto;
    width: 14px;
    height: 14px;
    margin: 0;
    border: 1px solid #86868b;
    border-radius: 3px;
    background-color: rgba(255, 255, 255, .8);
    background-repeat: no-repeat;
    background-position: center;
    background-size: 10px 10px;
    cursor: pointer;
    transition: background-color 125ms ease-in, border-color 125ms ease-in;
}

/* Галка нарисована прямо в правиле, чтобы не заводить файл ради
   десяти пикселей и не тратить на них отдельный запрос к серверу. */
.checkbox__input:checked {
    border-color: var(--accent);
    background-color: var(--accent);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.6 6.3 4.9 8.7 9.4 3.5' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* Пояснение под заголовком формы — «* обязательное поле». */
.form-legend {
    margin: 8px 0 0;
    color: var(--ink-muted);
    font-size: 13px;
}

/* Строчка под кнопкой: «Зарегистрироваться», «Уже есть учётная запись».
   Ссылка синяя и без подчёркивания, подчёркивается при наведении —
   как у apple.com. */
.form__aside {
    margin: 2px 0 0;
    color: var(--ink-muted);
    font-size: 15px;
    text-align: center;
    /* Если внутри кнопка, а не ссылка, абзац становится флексом —
       это делает правило `.content-column p:has(> .button)`, оставшееся
       со страниц ошибок. Во флексе text-align уже ничего не выравнивает,
       поэтому середина задана и вторым способом. */
    justify-content: center;
}

.link {
    color: var(--accent);
    text-decoration: none;
}

.link:hover {
    text-decoration: underline;
}

/* Выбор файла. Вид родной кнопки задаёт операционная система, и привести
   её к виду сайта можно только через ::file-selector-button — другого
   способа нет, если не подменять поле своим, а подменять нельзя:
   спрятанное поле выпадает из дерева доступности. */
.file-field {
    display: grid;
    gap: 6px;
}

.file-field__label {
    font-size: 14px;
    font-weight: 500;
    color: var(--ink-muted);
}

.file-field__input {
    font-family: inherit;
    font-size: 15px;
    color: var(--ink-muted);
}

.file-field__input::file-selector-button {
    height: 34px;
    margin-right: 10px;
    padding: 0 14px;
    border: 1px solid rgba(0, 0, 0, .16);
    border-radius: var(--pill);
    background-color: rgba(255, 255, 255, .8);
    color: var(--accent);
    font-family: inherit;
    font-size: 14px;
    cursor: pointer;
    transition: border-color 160ms var(--ease);
}

.file-field__input::file-selector-button:hover {
    border-color: rgba(0, 0, 0, .3);
}

.file-field__hint {
    margin: 0;
    color: var(--ink-muted);
    font-size: 12px;
}


/* Подзаголовок внутри формы — «Смена пароля». Отделяет часть формы,
   которую заполняют не всегда. */
.form-subtitle {
    margin: 10px 0 0;
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -.015em;
}

/* Аватарка рядом с выбором файла: видно, что меняешь. */
.file-field__row {
    display: flex;
    align-items: center;
    gap: 12px;
}

.file-field__preview {
    flex: 0 0 auto;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    object-fit: cover;
}

/* Сообщение об удаче — то же стекло, что у ошибки, только зелёное. */
.form-success {
    margin: 16px 0 0;
    padding: 11px 14px;
    border-radius: 12px;
    background-color: rgba(222, 245, 226, var(--glass-density));
    border-color: rgba(0, 128, 9, .24);
    /* Тёмно-зелёный: светлый на светлой плашке даёт около 2:1. */
    color: #1b5e20;
    font-size: 15px;
}

/* Ошибка всей формы — «неверный логин или пароль». Стоит над полями и до
   них: если сказать о ней после кнопки, человек её не увидит — он смотрит
   туда, куда только что нажал.

   Стекло у неё обычное, из класса glass в разметке; здесь только красный
   оттенок вместо белого. Плотность берётся из того же ползунка, что
   у остальных панелей, поэтому подкрашиваем в той же мере, в какой
   настроено стекло. */
.form-error {
    margin: 16px 0 0;
    padding: 11px 14px;
    border-radius: 12px;
    background-color: rgba(255, 228, 226, var(--glass-density));
    border-color: rgba(227, 0, 0, .24);
    /* Тёмно-красный, а не алый: на светлой плашке алый даёт около 3:1,
       этого мало для текста. У этого 6.4:1. */
    color: #8a1c18;
    font-size: 15px;
}

/* Ошибка одного поля — «введите логин или почту». Размеры и цвет их же,
   из bag.css: 12 пикселей, межбуквенное -.01em, красный #e30000.

   Своё сообщение вместо всплывающей подсказки браузера: вид той задаёт
   операционная система, она выглядит чужой рядом с формой и пропадает
   через несколько секунд. Это остаётся под полем, пока не исправят. */
.text-field__error {
    display: flex;
    align-items: center;
    gap: 5px;
    margin: 6px 0 0;
    color: #e30000;
    font-size: 12px;
    letter-spacing: -.01em;
    line-height: 1.333;
}

/* Поле с ошибкой краснеет, но только пока в нём не работают: в поле,
   куда человек уже вернулся исправлять, красная рамка мешает и пугает. */
.text-field.is-error .text-field__input:not(:focus) {
    border-color: #e30000;
    background-color: #fff2f4;
}

.text-field.is-error .text-field__label {
    color: #e30000;
}


/* Кольцо фокуса нужно всем, кто ходит по сайту с клавиатуры. Убирать нельзя.

   Скругление здесь не задаётся намеренно. Раньше стояло border-radius: 6px —
   чтобы кольцо выглядело округлым на элементах без своего скругления, — но
   оно перебивало скругление самих элементов: у строки ввода 12 превращалось
   в 6, и в момент щелчка углы распрямлялись на глазах. Нужды в нём нет:
   кольцо и так повторяет скругление элемента, вокруг которого нарисовано. */
a:focus-visible,
button:focus-visible,
.button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 2px;
}

/* Если браузер не умеет размытие, стекло вырождается в плотную заливку */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .glass,
    #content .wpgmza_map .glass {
        background: rgba(255, 255, 255, .95);
    }
}


/* ── Шапка ──────────────────────────────────────────────────────────────
   Полоса не рисует свой фон, а пропускает страницу сквозь себя. Содержимое
   проходит ПОД ней, а не отступает от неё. */
.site-header {
    position: fixed;
    top: var(--chrome-top);
    left: 0;
    right: 0;
    z-index: 10;
    height: calc(var(--header-height) + env(safe-area-inset-top, 0px));
    padding-top: env(safe-area-inset-top, 0px);

    /* Стекло берётся из общего правила выше. Здесь только то, чем полоса
       отличается от плавающей панели: рамка у неё одна, снизу, а внешней
       тени нет — полоса прижата к краю экрана, ей неоткуда отбрасывать
       тень вверх, и с ней она выглядит тяжёлой. */
    border: 0;
    border-bottom: 1px solid rgba(0, 0, 0, .08);
    box-shadow: var(--glass-edges);
}

.site-header__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    height: var(--header-height);
    /* Полоса во всю ширину и содержимое прижато к левому краю. Колонки
       по центру тут не будет: на главной под шапкой карта во весь экран,
       и колонка шириной 1180 оставляла бы название висеть посреди пустоты.
       Отступ маленький, но не нулевой — вплотную к краю экрана значок
       выглядит обрезанным. */
    padding: 0 max(14px, env(safe-area-inset-left, 0px));
}

/* Название сайта — кнопка: она раскрывает меню разделов. Кнопке браузер
   рисует свои рамку и фон и не даёт ей шрифт страницы, поэтому первые
   четыре строки — это «стань обычным текстом». */
.site-brand {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    min-width: 0;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    color: var(--ink);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: opacity 180ms var(--ease);
}

.site-brand:hover {
    opacity: .62;
}

.site-brand__mark {
    flex: 0 0 auto;
    /* Заливка не задана намеренно: её даёт класс glass-mark. */
}

.site-brand__name {
    overflow: hidden;
    font-size: var(--header-title);
    font-weight: 600;
    letter-spacing: -.022em;
    line-height: 1.2;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* Галочка справа от названия. Пока меню закрыто, смотрит вниз; открытое
   переворачивает её. Так состояние видно по самой кнопке, даже если меню
   ушло за нижний край экрана. Отрицательный отступ сжимает зазор: общий
   в 9 пикселей рассчитан на знак, а галочка мельче и должна липнуть
   к последней букве. */
.site-brand .icon--chevron {
    flex: 0 0 auto;
    margin-left: -3px;
    opacity: .5;
    transition:
        transform 220ms var(--ease),
        opacity 180ms var(--ease);
}

.site-brand[aria-expanded="true"] .icon--chevron {
    transform: rotate(180deg);
    opacity: .9;
}


/* ── Меню разделов ──────────────────────────────────────────────────────
   Раскрывается из-под названия сайта. Стоит в разметке снаружи шапки:
   стекло не вкладывают в стекло, объяснение — в разделе про стекло выше.
   Из-за этого меню не может быть позиционировано относительно шапки
   и считает своё место от края экрана теми же величинами, какими шапка
   считает свою высоту.

   Закрытое меню убрано через visibility, а не через display: none
   и не через атрибут hidden. Причина: display переключается мгновенно,
   с ним не бывает плавного появления. visibility и анимацию оставляет,
   и убирает меню из обхода табом и из чтения голосом — ровно то, ради
   чего обычно берут hidden. */
.site-menu {
    position: fixed;
    z-index: 11;
    top: calc(var(--chrome-top) + var(--header-height) + env(safe-area-inset-top, 0px) + 6px);
    left: max(14px, env(safe-area-inset-left, 0px));
    min-width: 208px;
    max-width: calc(100vw - 28px);
    padding: 6px;
    border-radius: 14px;

    visibility: hidden;
    opacity: 0;
    transform: translateY(-6px) scale(.97);
    /* Растёт из-под названия, а не из своей середины. */
    transform-origin: top left;
    transition:
        opacity 200ms var(--ease),
        transform 200ms var(--ease),
        /* Пропадает не сразу, а когда доиграет проявление, иначе меню
           исчезает рывком в первый же кадр закрытия. */
        visibility 0s linear 200ms;
}

.site-menu.is-open {
    visibility: visible;
    opacity: 1;
    transform: none;
    transition-delay: 0s;
}

.site-menu__list {
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Строка меню. Подсветка скруглена сильнее, чем сама панель: вложенный
   угол всегда мягче внешнего, иначе кажется, что строка выпирает. */
.site-menu__item {
    display: block;
    padding: 8px 12px;
    border-radius: 9px;
    font-size: 14px;
    letter-spacing: -.01em;
    color: var(--ink);
    text-decoration: none;
    white-space: nowrap;
    transition: background-color 150ms var(--ease);
}

.site-menu__item:hover {
    background-color: rgba(0, 0, 0, .05);
}

/* Раздел, на котором человек сейчас стоит. Цветом, а не подсветкой:
   подсветка занята наведением, и два одинаковых фона рядом сбивают
   с толку — непонятно, где ты и где мышь. */
.site-menu__item[aria-current="page"] {
    color: var(--accent);
}

/* Справа в шапке: кто вошёл — или две кнопки для гостя. */
.site-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: auto;
}

/* Правый край шапки: плюс и кто вошёл. margin-left: auto прижимает их
   вправо, сколько бы всего ни стояло слева. */
.site-account {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    margin-left: auto;
}

/* Очередь проверки. Значок с числом — в правом верхнем углу кнопки,
   как принято у почты и сообщений: там его ищут глазами не задумываясь. */
.site-review {
    position: relative;
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    color: var(--ink);
    text-decoration: none;
    opacity: .72;
    transition: opacity 180ms var(--ease);
}

.site-review:hover {
    opacity: 1;
}

.site-review__count {
    position: absolute;
    top: -3px;
    right: -5px;
    min-width: 16px;
    padding: 0 4px;
    border-radius: 8px;
    background-color: var(--status-lost);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    text-align: center;
    /* Цифры одной ширины: значок не должен дёргаться, когда
       запросов становится то девять, то десять. */
    font-variant-numeric: tabular-nums;
}

/* Плюс: завести объект. Пустой кружок с синей обводкой, при наведении
   заливается — то же поведение, что у вторичной кнопки рядом, только
   круглой: рядом с ним аватарка, и сплошная синяя заливка перетягивала
   бы на себя всё внимание шапки. */
.site-create {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Восемьдесят процентов от аватарки рядом: плюс не главный,
       а подручный, и ровно вровень с ней он спорил бы за внимание.
       Аватарка 28 точек, значит здесь 22. */
    width: 22px;
    height: 22px;
    border: 1px solid var(--accent);
    border-radius: 50%;
    color: var(--accent);
    text-decoration: none;
    transition:
        background-color 180ms var(--ease),
        color 180ms var(--ease);
}

.site-create:hover {
    background-color: var(--accent);
    color: #fff;
}

.site-user {
    display: flex;
    align-items: center;
    gap: 9px;
    min-width: 0;
    color: var(--ink);
    text-decoration: none;
    transition: opacity 180ms var(--ease);
}

/* Круглая при любой картинке: загруженные аватарки квадратные, 512 на 512. */
.site-user__photo {
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    object-fit: cover;
}

.site-user:hover {
    opacity: .62;
}

.site-user__name {
    overflow: hidden;
    max-width: 40vw;
    font-size: 14px;
    font-weight: 500;
    letter-spacing: -.01em;
    white-space: nowrap;
    text-overflow: ellipsis;
}


/* ── Обычные страницы ───────────────────────────────────────────────────
   Главную рисует карта, а всё остальное — эта колонка. Ширина ограничена
   по числу знаков: длинные строки читать тяжело. */
.page-body {
    min-height: 100vh;
    padding: calc(var(--chrome-top) + var(--header-height) + 40px) 20px 64px;
}

.content-column {
    max-width: 72ch;
    margin: 0 auto;
}

/* Колонка пошире — для очереди проверки. Там не текст, а ряд визиток:
   снимок, сведения и кнопки стоят в строку, и в ширину читаемого абзаца
   эта строка не помещается. */
.content-column--wide {
    max-width: 1000px;
}

/* Колонка для форм. Ширину задают настройки темы, раздел «Страница входа»:
   доля экрана отдельно для телефона и для большого экрана. Переключение
   между ними тоже там, в @media, — здесь только готовая переменная.

   Значения приходят в vw, а не в процентах: проценты считались бы от
   колонки внутри отступов страницы, и на телефоне вместо 85 процентов
   экрана выходило бы около 76. Запасное значение на случай, если стили
   темы почему-то не напечатались. */
.content-column--narrow {
    width: var(--login-width, 85vw);
    max-width: none;
}

/* Содержимое по центру высоты экрана — для страниц из одной панели:
   вход, регистрация. Центрируется внутри отступов, а не всего экрана,
   поэтому панель никогда не уходит под шапку. */
.page-body--centered {
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Несколько кнопок подряд: в строку, с переносом на узком экране
   и зазором не меньше 8px — иначе пальцем легко промахнуться. */
.content-column p:has(> .button) {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}


/* ── Снимок страны над главной ──────────────────────────────────────────
   Первое, что видит человек, зашедший на сайт: Беларусь со спутника,
   вырезанная по своей границе. Не в стеклянной панели и без рамки — это
   фотография, а не панель.

   Снимок едет обычным прямоугольником, а видимую часть задаёт контур
   в разметке (см. inc/geo.php). Край поэтому остаётся гладким на любом
   размере экрана, а сам файл можно перепечь в другом разрешении, ничего
   тут не меняя.

   Высота ограничена долей экрана, а не только шириной: страна должна
   помещаться целиком, иначе растворяться она начнёт раньше, чем человек
   успеет её рассмотреть. Числа 2400 и 2080 — размеры снимка из
   assets/data/build_satellite.py; их отношение и держит пропорции. */
.front-hero {
    /* Ширина полосы — по снимку, а сама она по центру страницы. Полоса
       и есть рамка для выносок: снимок занимает её целиком, а выноски лежат
       поверх него и считают своё место в процентах от неё. Обёртка внутри
       была бы лишним звеном между двумя вещами, которые и так совпадают. */
    position: relative;
    /* Полоса объявлена контейнером: от её ширины зависит, помещается ли
       выноска справа от метки или её надо ставить под метку. Спрашивать
       ширину окна тут нельзя — полоса уже окна и зависит ещё и от высоты. */
    container-type: inline-size;
    width: min(92vw, 1100px, calc(64vh * 2400 / 2080));
    margin: 0 auto 36px;
}

.front-hero__map {
    display: block;
    width: 100%;
    height: auto;
    /* Тень по контуру страны, а не по прямоугольнику: filter отбрасывает
       её от того, что видно, а видно здесь ровно вырезанную Беларусь.
       Две тени, как у стекла и у крупного текста: ближняя отделяет край
       снимка от фона, дальняя приподнимает его над страницей. Одной
       дальней мало — она слишком размыта, чтобы дать краю чёткость.
       Силу обеих задаёт общая настройка «Тень» в «Настроить → Стекло». */
    filter:
        drop-shadow(0 8px 18px rgba(0, 0, 0, calc(var(--shadow-strength) * .8)))
        drop-shadow(0 26px 52px rgba(0, 0, 0, calc(var(--shadow-strength) * .7)));
    /* Растворение при прокрутке: число считает assets/js/front-hero.js,
       здесь только подстановка. Без скрипта снимок просто стоит на месте. */
    opacity: var(--front-fade, 1);
}

/* Выноска к выделенному объекту: название и снимок на том же стекле, что
   и панели сайта, — оттого она и читается родной, а не приклеенной. Стоит
   поверх карты, но не внутри снимка: текст и фотографию в картинку
   не поместить.

   Стекло взято лёгкое, а не плотное. Обычно плотность выбирают по количеству
   текста — плотное под карточку с описанием, — но здесь важнее то, что лежит
   под выноской: у плотного стекла заливка почти непрозрачная, и на месте
   страны остаётся белое пятно. Насколько лёгким быть лёгкому стеклу, задаёт
   общий ползунок настроек, поэтому читаемость правится без правки стилей.

   Метка стоит слева от выноски, а не под ней: панель уходит от точки вправо
   целиком. Хвостик при этом целится не в нижнее остриё капли, а в середину
   её головки — туда, где стоит точка: капля растёт вверх от своей точки,
   и остриё снизу читается как «касание земли», а не как указание на значок.
   Растворяется вместе со снимком — за это отвечает та же переменная.

   За правый край полосы ей позволено свисать: там уже не карта, а фон
   страницы, и это способ заслонить меньше всего. Но не дальше, чем на
   странице есть места сбоку от полосы, — на узком окне выноска остаётся
   на полосе целиком, иначе она уехала бы за край экрана. */
.front-hero__callout {
    /* Ширина, зазор до метки и высота, на которой стоит хвостик, — здесь,
       а не в разметке: разметка называет только место метки, остальное
       читается как «сколько ей можно». */
    --callout-width: 240px;
    --callout-gap: 16px;
    /* Насколько панель поднята над рядом головки. Хвостик при этом остаётся
       на месте: он стоит на этой же высоте внутри панели, поэтому его место
       на экране от числа не зависит — поднимается только сама панель.
       Семьдесят восемь точек: стрелка встречает панель чуть выше верхней
       трети, а до шапки остаётся два десятка точек. */
    --callout-tail-y: 78px;
    /* Куда целится хвостик: середина головки капли (25 точек вверх от её
       острия) и её радиус (11.5 точек). Капля нарисована в масштабе 3.15
       в точках снимка, а снимок 2400 на 2080 — отсюда 25 * 3.15 / 2080
       по высоте и 11.5 * 3.15 / 2400 по ширине. Проценты, а не точки:
       метка растёт вместе с полосой, и проценты остаются верными всегда. */
    --callout-head-y: 3.786%;
    --callout-head-r: 1.51%;
    --callout-overhang: max(0px, (100vw - 100%) / 2 - 55px);

    position: absolute;
    /* Левый край отстоит от точки на радиус головки да длину хвостика:
       тогда остриё хвостика приходится ровно на край головки и смотрит
       в её середину, не заслоняя саму метку. */
    left: calc(var(--callout-x, 0%) + var(--callout-head-r) + var(--callout-gap));
    /* Ширина ужимается, если справа её не помещается: лучше панель поуже,
       чем наползающая на метку или вылезающая за край окна. На широком
       окне места хватает и выбирается ровно 240. */
    width: min(var(--callout-width), calc(100% - var(--callout-x, 0%) - var(--callout-head-r) - var(--callout-gap) + var(--callout-overhang)));
    /* По высоте панель поднята так, чтобы ряд головки пришёлся на хвостик. */
    top: calc(var(--callout-y, 0%) - var(--callout-head-y) - var(--callout-tail-y));
    margin: 0;
    padding: 10px;
    border-radius: 16px;
    /* По выноске нажимают и уходят на карту к этому же объекту, поэтому она
       ссылка. Подчёркивание и цвет ссылки тут ни к чему: панель и без них
       видно, а нажимаемость показывает тень при наведении. */
    display: block;
    color: inherit;
    text-decoration: none;
    opacity: var(--front-fade, 1);
}

/* Наведение поднимает тень — тот же знак, что у кнопок и карточек: не цвет
   и не подчёркивание, а высота. */
.front-hero__callout:hover {
    box-shadow: var(--glass-edges), var(--shadow-lifted);
}

/* Хвостик к метке: треугольник, торчащий из левого края панели.

   Не ромб, как делают обычно, и вот почему. Квадрат, повёрнутый на 45
   градусов, наполовину лежит на панели; заливка у обоих полупрозрачная,
   и на наложении она удваивается — внутри панели проступает лишний ромб
   с чёткими краями. Ровно на этих граблях стоит метка на большой карте:
   там капля нарисована одним контуром, а не кругом с приставленным
   треугольником, и по той же причине (см. map.js).

   Поэтому здесь нарисовано только то, что торчит из-за края панели:
   половина ромба, которую видно. Остриё приходится ровно на край головки
   метки, на её середину по высоте, — так он смотрит в значок, а не в точку
   под ним. */
.front-hero__callout::before {
    content: '';
    position: absolute;
    /* Ряд головки: на нём стоит остриё, и на него же сдвинута вся панель. */
    top: var(--callout-tail-y);
    left: calc(-1 * var(--callout-gap));
    width: var(--callout-gap);
    height: 16px;
    margin-top: -8px;
    background-color: var(--material-thin);
    background-image: var(--glass-sheen);
    clip-path: polygon(100% 0, 0 50%, 100% 100%);
    /* Без тени хвостик пропадает: он из того же лёгкого стекла, а за ним
       светлое небо снимка. Тень по контуру, а не рамка: рамку clip-path
       срезает вместе с углами. Та же причина, по которой у метки тёмная
       обводка под стеклом. */
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .22));
}

/* Полоса уже шестисот двадцати точек — панель справа от метки не помещается:
   она стала бы шириной в палец. Тут выноска встаёт под метку, как было
   до этого: там хватает ширины, и метку она не заслоняет — она под ней. */
@container (max-width: 620px) {
    .front-hero__callout {
        left: clamp(64px, var(--callout-x, 0%), calc(100% - 176px));
        top: calc(var(--callout-y, 0%) + 14px);
        width: var(--callout-width);
        transform: translate(calc(-50% + 56px), 0);
    }

    .front-hero__callout::before {
        top: -8px;
        left: calc(50% - 56px);
        width: 16px;
        height: 8px;
        margin-top: 0;
        margin-left: -8px;
        clip-path: polygon(50% 0, 100% 100%, 0 100%);
    }
}

/* Снимок объекта. Обрезается по рамке: у фотографий разные пропорции,
   а выноска должна быть одной высоты, иначе метка «прыгает». */
.front-hero__photo {
    display: block;
    width: 100%;
    height: 118px;
    border-radius: 10px;
    object-fit: cover;
}

.front-hero__caption {
    display: block;
    margin: 8px 2px 2px;
    font-size: 14px;
    line-height: 1.35;
    letter-spacing: -.01em;
}

/* Лента снимков: все фотографии сайта одной полосой во всю ширину окна.

   Полоса вылезает из полей страницы на их же ширину — по двадцать точек
   с каждой стороны, — поэтому идёт мимо читаемой колонки, а не внутри неё:
   колонка шириной в абзац, а снимкам нужен весь экран. Считать от окна
   (100vw) нельзя: в это число входит полоса прокрутки, и справа вылез бы
   лишний отступ.

   Окно обрезает по краям и растворяет их: иначе снимки обрубаются ножом. */
.front-gallery {
    width: calc(100% + 40px);
    margin: 64px 0 24px -20px;
}

.front-gallery__frame {
    position: relative;
}

.front-gallery__window {
    overflow: hidden;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 28px, #000 calc(100% - 28px), transparent);
    mask-image: linear-gradient(90deg, transparent, #000 28px, #000 calc(100% - 28px), transparent);
}

.front-gallery__track {
    display: flex;
    gap: 14px;
    margin: 0;
    padding: 4px 0;
    list-style: none;
    /* Едет переносом, а не прокруткой: прокрутка на телефоне перетянула бы
       жест на себя, и мимо ленты нельзя было бы пролистать страницу. */
    will-change: transform;
}

.front-gallery__item {
    flex: 0 0 auto;
    /* Ширина и высота растут вместе, в прежней пропорции десять на семь:
       снимки у памятников горизонтальные, и от одной только высоты они
       обрезались бы в квадрат. */
    width: 405px;
    height: 285px;
    overflow: hidden;
    border-radius: 14px;
    /* Пустая плитка того же стекла: пока снимок едет, место не мигает
       белым пятном на фоне страницы. */
    background-color: var(--material-thin);
}

.front-gallery__photo {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Стрелки — те же, что в галерее карточки объекта (assets/css/object-panels.css):
   той же величины, того же лёгкого стекла, назад — тот же значок,
   развёрнутый. Своя копия разошлась бы с карточкой при первой же правке.

   Стоят на снимках, а не на растворённом крае: стеклу там нечего
   размывать, и оно выглядело бы простым белым кружком. */
.front-gallery__arrow {
    position: absolute;
    top: 50%;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    /* Класс .button держит наименьшую высоту под палец, и без этого
       стрелка выходит сорок четыре точки в высоту при тридцати восьми
       в ширину — кружок становится овалом. */
    min-height: 0;
    margin-top: -19px;
    padding: 0;
    border-radius: 50%;
    color: var(--ink);
    cursor: pointer;
    transition: background-color 160ms var(--ease);
}

.front-gallery__arrow:hover {
    background-color: var(--material-strong);
}

.front-gallery__arrow--back {
    left: 36px;
    /* Значок один на обе кнопки, назад — тот же, только развёрнутый. */
    transform: scaleX(-1);
}

.front-gallery__arrow--forward {
    right: 36px;
}


/* Метки на снимке: те же, что на большой карте (см. map.js), — стеклянная
   капля с кружком по состоянию объекта. Сама капля нарисована один раз
   в разметке, а здесь только цвет кружка: он и отличает одно состояние
   от другого. Список состояний — общий, из inc/objects.php: заведут
   третье, здесь само собой ничего не сломается, просто останется синий
   кружок — запасной цвет метки. */
.front-hero__pin {
    --pin-dot: var(--accent);
}

.front-hero__pin--lost {
    --pin-dot: var(--status-lost);
}

.front-hero__pin--restoration {
    --pin-dot: var(--status-restoration);
}


/* ── Начало главной ─────────────────────────────────────────────────────
   Название проекта и одна поясняющая строка. По центру, а не по левому
   краю: читать тут почти нечего, а строки в одну-две у левого края
   выглядят обрывком, а не началом. Текст ниже — уже обычный, слева,
   там центровка мешала бы читать. */
.intro {
    margin: 0 0 32px;
    text-align: center;
}

/* Подзаголовок крупнее обычного текста, но тише заголовка: он объясняет,
   куда человек попал, и должен прочитаться раньше, чем всё остальное. */
.intro__lead {
    max-width: 46ch;
    margin: 0 auto;
    font-size: clamp(17px, 2vw, 19px);
    letter-spacing: -.01em;
    color: var(--ink-muted);
}

/* Главная кнопка страницы, под всем текстом. Правило выше ставит кнопкам
   flex и разносит их по левому краю — здесь кнопка одна и стоять ей
   посередине. */
.content-column .page-action {
    justify-content: center;
    margin: 32px 0 0;
}

/* Стрелка в кнопке. Чуть отодвинута от слова: общий зазор рассчитан
   на значок в полную высоту строки, а у стрелки вся тяжесть посередине,
   и с обычным зазором она липнет к букве. */
.button .icon--arrow {
    margin-left: 1px;
}


/* Список с точками. Свои, а не браузерные: браузер ставит точку крупнее
   и выше строки, и рядом с нашим текстом она выглядит чужой. */
.marked-list {
    margin: 12px 0 0;
    padding: 0;
    list-style: none;
}

.marked-list li {
    position: relative;
    padding-left: 20px;
}

.marked-list li + li {
    margin-top: 6px;
}

.marked-list li::before {
    content: "";
    position: absolute;
    /* Половина высоты строки минус половина точки — так она встаёт
       по середине первой строки, даже если пункт перенесётся. */
    top: calc(.775em - 2px);
    left: 6px;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background-color: var(--ink-muted);
}

.content-column h1 {
    margin: 0 0 8px;
    font-size: clamp(28px, 4vw, 40px);
    font-weight: 600;
    letter-spacing: -.025em;
    line-height: 1.15;
}

.content-column h2 {
    margin: 32px 0 8px;
    font-size: 22px;
    font-weight: 600;
    letter-spacing: -.02em;
}

.post-date {
    margin: 0 0 24px;
    font-size: 13px;
    color: var(--ink-muted);
}

.post-list {
    display: grid;
    gap: 16px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.post-title {
    margin: 0 0 4px;
    font-size: 19px;
    font-weight: 600;
    letter-spacing: -.02em;
}

.post-title a {
    color: var(--ink);
    text-decoration: none;
}

.post-title a:hover {
    color: var(--accent);
}

.empty-message {
    color: var(--ink-muted);
}


/* ── Страница ошибки ────────────────────────────────────────────────────
   Крупный код ответа стеклом, под ним название и пояснение, ниже кнопки.

   Стекло тут держится на подсветке ниже. Само по себе оно только размывает
   то, что за ним, — а за ним ровная заливка страницы, размывать нечего,
   и получается белый прямоугольник. Цветные пятна дают материалу что
   преломлять, и он наконец читается как стекло. */
.error-page {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: calc(var(--chrome-top) + var(--header-height) + 40px) 20px 40px;
    text-align: center;
    overflow: hidden;
}

/* Свечение за стеклом. Без него стекло не читается как стекло: заливка
   у него полупрозрачная, страница светлая, и получается белое на белом.
   Стекло становится стеклом тогда, когда за ним есть что преломлять.

   Прикреплено к окну, а не к странице: страницы бывают длиннее экрана,
   и свечение, уезжающее вверх при прокрутке, оставило бы нижнюю половину
   на голой заливке. Пятна расставлены по тем местам, где обычно стоит
   содержимое: вверху по центру и чуть ниже середины. */
.page-glow {
    position: fixed;
    inset: -25%;
    z-index: -1;
    background:
        /* главное пятно — там, где на странице стоит крупное:
           цифры кода ошибки, заголовок, форма */
        radial-gradient(28% 30% at 50% 38%,
            color-mix(in srgb, var(--accent) 75%, transparent), transparent 72%),
        /* ниже середины: без него кнопка стоит на белом и выглядит
           сплошной, хотя она прозрачная */
        radial-gradient(26% 22% at 50% 62%,
            color-mix(in srgb, var(--accent) 55%, transparent), transparent 70%),
        /* по углам, чтобы фон не был плоским */
        radial-gradient(30% 32% at 22% 26%,
            color-mix(in srgb, var(--accent) 55%, transparent), transparent 70%),
        radial-gradient(30% 32% at 80% 66%, rgba(89, 211, 194, .6), transparent 68%);
    filter: blur(60px);
    pointer-events: none;
}

/* Крупный текст «под стекло»: цифры кода ошибки и всё, что захочется
   оформить так же. Отдельный класс, а не .glass, и это не придирка.

   .glass делает поверхность: элемент размывает то, что за ним. Для текста
   такое невозможно — backdrop-filter работает по прямоугольнику элемента,
   а не по контуру буквы. Повесив .glass на цифры, получишь размытый
   прямоугольник позади них, то есть плашку, а не стеклянные буквы.

   Поэтому здесь стекло не настоящее, а собранное: полупрозрачная заливка
   внутри букв, чтобы сквозь неё читался фон, и тени по контуру вместо
   кромок. Плотность и тень берутся из тех же настроек, что у .glass,
   поэтому ползунки действуют и сюда. */
.glass-text {
    /* Своя плотность — та же, что у обычного стекла. Модификаторы ниже
       переключают её на лёгкую или плотную, как и у поверхностей. */
    --glass-text-density: var(--glass-density);

    color: transparent;

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

       Белый не совсем белый: сверху уходит в холодный, снизу в тёплый.
       Стекло всегда подкрашивает проходящий свет, и глаз ловит это
       раньше, чем успевает понять почему. */
    background-image: linear-gradient(
        180deg,
        rgba(247, 251, 255, calc(var(--glass-text-density) * 1.35)),
        rgba(255, 255, 255, calc(var(--glass-text-density) * .45)) 52%,
        rgba(255, 255, 255, calc(var(--glass-text-density) * .5)) 74%,
        rgba(255, 252, 247, calc(var(--glass-text-density) * 1.18)) 91%,
        rgba(255, 252, 247, var(--glass-text-density))
    );
    -webkit-background-clip: text;
    background-clip: text;

    /* Обводки нет намеренно. text-stroke рисуется по средней линии контура,
       и её внутренняя половина просвечивает сквозь полупрозрачную заливку —
       на буквах с изломами, прежде всего на четвёрке, это видно как лишние
       линии внутри цифры. Тени повторяют форму буквы и внутрь не лезут. */
    /* Тени идут снизу вверх: каждая следующая ложится ЗА всё, что дали
       предыдущие. Поэтому сначала то, что должно лежать вплотную к букве,
       и только потом мягкие тени под ней.

       1-2. Светлые кромки сверху и снизу — толщина материала. Они не
            зависят от плотности: это отражённый свет, а не заливка,
            у панелей он тоже задан постоянным значением.
       3-4. Дисперсия. Стекло преломляет холодную и тёплую части света
            под разными углами, и по краям выступает цветная кайма:
            холодная с той стороны, откуда светит, тёплая с другой.
            Один пиксель, почти незаметно поодиночке — но без неё край
            выглядит вырезанным из бумаги.
       5-6. Собственно тень: близкая отделяет букву от фона, дальняя
            приподнимает её над страницей. Одной дальней мало — она
            слишком размыта, чтобы дать краю чёткость. */
    filter:
        drop-shadow(0 -1px 0 rgba(255, 255, 255, .9))
        drop-shadow(0 1px 0 rgba(255, 255, 255, .5))
        drop-shadow(-1px -1px 1px rgba(140, 190, 255, .3))
        drop-shadow(1px 1px 1px rgba(255, 208, 160, .26))
        drop-shadow(0 2px 5px rgba(0, 0, 0, calc(var(--shadow-strength) * 1.1)))
        drop-shadow(0 18px 34px rgba(0, 0, 0, calc(var(--shadow-strength) * 1.1)));
    user-select: none;
}

/* Стекло на векторном знаке — третий способ его собрать, после
   поверхностей (.glass) и крупного текста (.glass-text). Причина та же,
   что у текста: backdrop-filter размывает прямоугольник элемента, а знак
   имеет свой контур, и размытая плашка позади него — не то же самое, что
   стеклянная фигура.

   Поэтому стекло здесь тоже собрано: полупрозрачная чёрная заливка внутри
   фигуры, светлая кромка сверху и тень под ней. Плотность берётся из того
   же ползунка «Плотность: тёмное», что и остальное тёмное стекло. */
.glass-mark {
    fill: var(--material-dark);

    /* Кромка светлее самой фигуры: на тёмном стекле свет собирается
       по верхнему ребру. Тень — та же, что у поверхностей, только мельче:
       знак маленький, и большая тень под ним выглядит грязным пятном. */
    filter:
        drop-shadow(0 -1px 0 rgba(255, 255, 255, .55))
        drop-shadow(0 1px 2px rgba(0, 0, 0, calc(var(--shadow-strength) * .9)));
}

/* Размер и начертание цифр — отдельно от того, как они окрашены.

   Две строчки здесь — про то, чтобы цифры стояли ровно по центру экрана,
   а не просто «примерно». Обе исправляют мелочи, которые поодиночке
   не замечаешь, а вместе они уводят число вбок на добрый десяток пикселей.

   1. tabular-nums — цифры одинаковой ширины. Обычно в шрифте они разной:
      в Inter «4» шире «3» на семь пикселей при нашем размере. Из-за этого
      403 и 404 занимают разную ширину и встают по-разному, хотя обе
      «отцентрованы». С одинаковыми ячейками разница пропадает.

   2. padding-right — расплата за отрицательный межбуквенный интервал.
      Он вычитается и ПОСЛЕ последней цифры, поэтому коробка выходит уже
      самих цифр, и при центровании коробки число уезжает вправо на половину
      интервала. Отступ той же величины возвращает его на место. */
.error-page__code {
    margin: 0;
    padding-right: .05em;
    font-size: clamp(104px, 24vw, 232px);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: .9;
    letter-spacing: -.05em;
}

.error-page__title {
    margin: 18px 0 0;
    font-size: clamp(26px, 4vw, 38px);
    font-weight: 600;
    letter-spacing: -.025em;
    line-height: 1.15;
}

.error-page__text {
    max-width: 46ch;
    margin: 10px 0 0;
    font-size: 15px;
    /* Цвет сплошной, а не полупрозрачный. Общий --ink-muted задан
       прозрачностью, и поверх цветной подсветки он выцветал до контраста
       около 2.8:1 при норме 4.5:1. Сплошной #55555a держит 5.6:1
       и на белом, и на подсветке. */
    color: #55555a;
}

.error-page__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px;
    margin-top: 28px;
}

/* Подвал на странице ошибки лишний: она и так занимает весь экран */
.error-page + .site-footer {
    display: none;
}

/* ── Подвал ─────────────────────────────────────────────────────────── */
.site-footer {
    padding: 32px 20px calc(32px + env(safe-area-inset-bottom, 0px));
    font-size: 12px;
    color: var(--ink-muted);
    text-align: center;
}

.site-footer a {
    color: inherit;
}


@media (prefers-reduced-motion: reduce) {
    * {
        transition: none !important;
        animation: none !important;
    }
}


/* ── Очередь проверки ───────────────────────────────────────────────────
   Визитка запроса: снимок, название, кто и когда прислал, где это.
   Всё, чего хватает, чтобы решить, не открывая объект целиком. */
.request-list {
    display: grid;
    gap: 16px;
    margin: 20px 0 0;
    padding: 0;
    list-style: none;
}

.request {
    display: grid;
    /* Снимок, сведения, кнопки. Кнопки уходят вправо и не растягиваются:
       им нужна своя ширина, а не остаток строки. */
    grid-template-columns: 236px 1fr auto;
    gap: 22px;
    /* Сведения начинаются от верха снимка, а не от середины визитки:
       название — первое, что читают, и стоять оно должно вверху. */
    align-items: start;
    padding: 18px;
    border-radius: 26px;
    /* Нажимается вся визитка, кроме кнопок, — раскрывает объект. */
    cursor: pointer;
}

/* Снимок крупный намеренно: по нему решение и принимают. Картинка
   в углу заставляла бы открывать каждый объект целиком — а это ровно
   та работа, от которой визитка избавляет. */
.request__photo {
    width: 236px;
    height: 176px;
    border-radius: 20px;
    object-fit: cover;
    background-color: rgba(0, 0, 0, .05);
}

/* Объект без снимка сюда попасть не должен — снимок обязателен, —
   но если такой окажется, пустая рамка честнее пропавшей колонки. */
.request__photo--none {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--ink-muted);
    font-size: 12px;
}

.request__body {
    min-width: 0;
}

/* Название и вид заявки — в строку. Плашка переносится под название
   только если места и правда нет. */
.request__head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin: 0 0 8px;
}

/* Двойной класс намеренно: заголовки в колонке отодвинуты сверху
   на 32 пикселя — так они отделяются от предыдущего раздела, — а в
   визитке отделяться не от чего, там заголовок первый. Правило
   `.content-column h2` весит больше одного класса, поэтому здесь
   их два. */
.request .request__title {
    margin: 0;
    font-size: 21px;
    font-weight: 600;
    letter-spacing: -.02em;
}

/* Название — кнопка, но выглядит названием: обычная кнопка браузера
   с рамкой и серым фоном посреди заголовка смотрелась бы чужой. */
.request__open {
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    letter-spacing: inherit;
    text-align: left;
    cursor: pointer;
}

/* Плашка состояния — та же, что в карточке объекта: утрачено красным,
   реставрация жёлтым. Кружок ярче надписи: надпись должна читаться,
   кружок — узнаваться по цвету. */
/* Строка с состоянием. Отдельной строкой, а не рядом с названием:
   рядом уже стоит вид заявки, а три вещи в одну строку не влезают
   на узком экране. */
.request__marks {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0 0 10px;
}

.request__status {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin: 0;
    padding: 4px 11px 4px 9px;
    border-radius: var(--pill);
    font-size: 13px;
    font-weight: 500;
}

/* Вид заявки — такая же таблетка, как у состояния, только серая:
   это не состояние памятника, а сведение о самой заявке. Размеры
   повторяют .request__status намеренно — рядом они должны выглядеть
   одинаково, разниться должен только цвет. */
.request__mark {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    padding: 4px 11px;
    border-radius: var(--pill);
    background-color: rgba(0, 0, 0, .06);
    color: var(--ink-muted);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: -.01em;
}

.request__status-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background-color: currentColor;
}

/* Карандаш в жёлтом кружке слева от названия: заявку правил проверяющий.
   Кружок того же жёлтого, что и состояние «требует реставрации», но сам
   карандаш тёмный: жёлтым по жёлтому не разглядеть, а белым по жёлтому
   не хватает разницы — у жёлтого и белого она около полутора к одному. */
.request__edited {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background-color: var(--status-restoration);
    color: var(--status-restoration-ink);
}

.request__status--lost {
    background-color: rgba(227, 0, 0, .1);
    color: var(--status-lost-ink);
}

.request__status--lost .request__status-dot {
    background-color: var(--status-lost);
}

.request__status--restoration {
    background-color: rgba(245, 184, 0, .18);
    color: var(--status-restoration-ink);
}

.request__status--restoration .request__status-dot {
    background-color: var(--status-restoration);
}

.request__who {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 8px;
    font-size: 15px;
}

.request__avatar {
    flex: 0 0 auto;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    object-fit: cover;
}

.request__when,
.request__where {
    margin: 0 0 3px;
    color: var(--ink-muted);
    font-size: 14px;
}

/* Подпись к значению — «Время добавления:». Бледнее самого значения:
   читают здесь время, а подпись только объясняет, что это за число. */
.request__label {
    color: var(--ink-muted);
    opacity: .75;
}

.request__actions {
    display: flex;
    flex-direction: column;
    gap: 8px;
    /* Посередине высоты: столбик из двух кнопок, прижатый к верху,
       выглядел бы отвалившимся от снимка. */
    align-self: center;
}

/* Кнопки в визитке мельче обычных: их две, стоят они столбиком,
   и в полный рост пара занимала бы больше места, чем сам запрос. */
.request__actions .button {
    min-height: 42px;
    padding: 10px 24px;
    font-size: 15px;
}

/* Что решили. Встаёт вместо кнопок, чтобы визитка не исчезала рывком:
   человек видит, что именно он нажал. */
.request__done {
    margin: 0;
    color: var(--ink-muted);
    font-size: 14px;
    text-align: right;
}

@media (max-width: 620px) {
    .request {
        grid-template-columns: 1fr;
    }

    .request__photo {
        width: 100%;
        height: 210px;
    }

    .request__actions {
        flex-direction: row;
    }

    .request__actions .button {
        flex: 1 1 0;
    }
}


/* ── Журнал заявок ───────────────────────────────────────────────────────
   Строка журнала — та же визитка, что в очереди: снимок, название, кто
   и когда прислал. Отличий два: решать тут нечего, поэтому вместо кнопок
   в правом углу стоит приговор, и запись может пережить сам объект. */
.log-search {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin: 16px 0 0;
}

/* Поле поиска тянется, кнопки — по содержимому. */
.log-search .text-field {
    flex: 1 1 240px;
    margin: 0;
}

.log-entry {
    /* Приговор занимает третью колонку — ту, где в очереди стоят кнопки. */
    cursor: pointer;
}

/* Приговор и кто его вынес. Вверху, у правого края: читается раньше
   всего остального, потому что в журнале ищут именно его. */
.log-entry__verdict {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
    /* Во всю высоту строки: приговор прижат к верху, кнопка возврата —
       к низу, и между ними пусто. */
    align-self: stretch;
    text-align: right;
}

.log-entry__mark {
    display: inline-flex;
    align-items: center;
    padding: 5px 13px;
    border-radius: var(--pill);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: -.01em;
    white-space: nowrap;
}

/* Зелёное и красное — те же, что у кнопок решения: человек уже видел
   их в очереди и узнаёт цвет раньше, чем читает слово. */
.log-entry__mark--published {
    background-color: rgba(28, 127, 62, .12);
    color: var(--positive);
}

.log-entry__mark--rejected {
    background-color: rgba(227, 0, 0, .1);
    color: var(--status-lost-ink);
}

.log-entry__mark--pending {
    background-color: rgba(245, 184, 0, .18);
    color: var(--status-restoration-ink);
}

/* Серое «Удалено» — уборка по сроку: решение принимали за месяц до того,
   и спроса тут ни с кого нет. */
.log-entry__mark--gone {
    background-color: rgba(0, 0, 0, .06);
    color: var(--ink-muted);
}

/* Красное «Удалено» — объект убрал человек. Тем же красным, каким
   на сайте говорят «отклонено»: решение принял кто-то, и рядом с меткой
   стоит его имя. */
.log-entry__mark--erased {
    background-color: rgba(227, 0, 0, .1);
    color: var(--status-lost-ink);
}

.log-entry__judge {
    margin: 0;
    color: var(--ink-muted);
    font-size: 12px;
    line-height: 1.35;
}

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

   `margin-top: auto` опускает пару в самый низ строки: приговор наверху,
   возврат внизу. Подпись выравнивается по кнопке, а не по краю строки,
   поэтому обе лежат в своём столбике с выравниванием по центру. */
.log-entry__back {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    margin-top: auto;
}

/* Срок мелким под кнопкой. Без него кнопка выглядела бы вечной,
   а она исчезнет вместе с объектом — через месяц после отказа. */
.log-entry__until {
    margin: 0;
    color: var(--ink-muted);
    font-size: 12px;
    line-height: 1.3;
    text-align: center;
}

/* Запись пережила объект: возвращать нечего, раскрывать нечего.
   Такая строка темнее остальных — не выцветшая, а именно притемнённая:
   выцветание читалось бы как «неважно», а это запись о том, что было. */
.log-entry--gone {
    cursor: default;
    background-color: rgba(29, 31, 33, .07);
}

.log-entry--gone .request__title {
    color: var(--ink-muted);
    font-weight: 500;
}

/* Вместо снимка — корзина: место, где он был, пустым не оставляем. */
.log-entry__grave {
    color: var(--ink-muted);
}

@media (max-width: 620px) {
    /* На телефоне приговор встаёт под сведениями, а не сбоку. */
    .log-entry__verdict {
        align-items: flex-start;
        text-align: left;
    }
}
