@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;500;600;700&display=swap');

/* Тёмная типографская тема. Весь сайт набран одной засечковой гарнитурой
   и одним белым цветом по чёрному — оттенки задаются прозрачностью, а не
   новыми красками. --ink правится в одной строке и меняет цвет всего сайта. */
:root {
    --paper: #000000;
    --ink: #ffffff;
    --ink-muted: rgba(255, 255, 255, .62);
    --ink-faint: rgba(255, 255, 255, .42);
    --rule: rgba(255, 255, 255, .22);
    --rule-strong: rgba(255, 255, 255, .45);
    --wash: rgba(255, 255, 255, .06);

    /* Чтобы браузер рисовал полосы прокрутки и системные элементы формы
       в тёмном варианте, а не белыми поверх чёрного фона. */
    color-scheme: dark;
}

@font-face {
    font-family: 'KonstFont'; 
    src: url('konstrukt/KONSTRUKT-Regular.otf') format('opentype');
    font-display: swap;
}

html, body {
    background-color: var(--paper);
    color: var(--ink);
    height: 100%;
}

html {
    scroll-behavior: smooth;

    /* iOS Safari в альбомной ориентации самовольно увеличивает шрифт
       и ломает раскладку — отключаем автоподбор размера. */
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

/* Одна гарнитура на весь сайт — от вывески до подписей под курсами. */
body {
    display: flex;
    flex-direction: column;
    margin: 0;
    font-family: 'Playfair Display', 'Times New Roman', Georgia, serif;
}

* {
    box-sizing: border-box;
}

.app {
    flex: 1;

    display: flex;
    flex-direction: column;

    /* Отступ под шапку меняется на каждом кадре прокрутки, и браузер норовит
       подправить прокрутку, чтобы содержимое осталось на месте, — ровно то,
       чего мы здесь добиваться не хотим: получалась обратная связь и дрожь. */
    overflow-anchor: none;
}

main {
    flex: 1;

    /* Футер должен оставаться за пределами первого экрана —
       даже когда контента страницы почти нет (например, заглушка). */
    min-height: 100vh;
}

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

    border-radius: 20px;
}

a {
    text-decoration: none;   
}

ul{
    margin-top: 10px;
}

.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 20px;
}

/* Шапка прилипает к верху и по мере прокрутки ужимается в одну строку —
   тот же приём, что у референса: вывеска уступает место содержимому,
   но навигация остаётся под рукой.

   position: fixed, а не sticky, намеренно. Ужимаясь, шапка меняет свою
   высоту; в потоке это укорачивало документ, браузер подтягивал прокрутку
   назад, от этого вывеска разворачивалась обратно — и страница застревала
   у верхнего края, не давая себя промотать. Вынутая из потока шапка на
   высоту документа не влияет, а место под неё держит отступ у .app, который
   header.js ведёт вслед за высотой шапки. */
.header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;

    /* Выпадающий список лиг раскрывается поверх .main, а у .main из-за zoom
       свой контекст наложения — без слоя у шапки список уходил бы под него. */
    z-index: 5;

    background-color: var(--paper);
    color: var(--ink);

    padding-top: 18px;
}

.header > .container {
    position: relative;

    z-index: 50;

    max-width: none;
}

/* Вывеска: имя растянуто по ширине страницы, как заголовок на обложке.
   Размер задан в vw, поэтому строка занимает ту же долю экрана и на
   ноутбуке, и на большом мониторе. */
.header__wordmark {
    display: block;

    font-size: clamp(52px, 23.2vw, 420px);
    font-weight: 500;
    line-height: .92;

    /* Разрядку ведёт JS двумя значениями: обычным и для ужатой вывески.
       Переход между ними плавный, но случается один раз за прокрутку, а не
       на каждом кадре — пересчёт раскладки такой строки слишком дорог. */
    letter-spacing: var(--wordmark-spacing, .02em);
    text-align: center;
    text-transform: uppercase;

    color: var(--ink);

    /* Ужатая вывеска лежит поверх строки навигации во всю её ширину.
       Клики ловит только сама надпись, а не весь блок, — иначе она
       перехватывала бы нажатия по ссылкам и кнопкам под собой. */
    pointer-events: none;
}

/* Появление при открытии главной: надпись опускается сверху и проявляется.
   Оба свойства браузер меняет без пересчёта раскладки, поэтому анимация
   идёт целиком на видеокарте. */
@keyframes wordmark-enter {

    from {
        opacity: 0;
        transform: translateY(-64px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

body.page-home .header__wordmark-text {
    animation: wordmark-enter 1s cubic-bezier(.22, .61, .36, 1) both;
}

/* Кликается только там, где действительно нарисованы буквы. Строка вывески
   заметно шире и выше их: при постоянном кегле её невидимый бокс накрывал
   ссылки навигации и кнопку меню, и нажатие на них уводило на главную.
   Раньше на главной клики вывеске были не нужны вовсе — она вела на главную,
   где пользователь и так стоял. Теперь она открывает меню, и нажимать по ней
   надо на всех страницах. */
.header__wordmark-text {
    display: inline-block;

    pointer-events: auto;

    cursor: pointer;

    /* Отъезд к правому краю строки: сдвиг считает header.js, здесь только
       сам полёт. Пологая кривая — надпись трогается мягко и мягко тормозит
       у кнопок масштаба. */
    transition: transform .75s cubic-bezier(.22, .61, .36, 1);
}

/* На My soccer после выбора лиги вывеска уступает строку названию лиги. */
body.league-picked .header__wordmark-text {
    transform: translateX(var(--wordmark-park, 0px));
}

/* Строка навигации под вывеской: разделы слева, служебное справа.

   Ширину ограничиваем: растянутая на весь экран строка заставляла бы на
   широком мониторе гонять курсор из угла в угол. Предел выбран шире
   колонки содержимого — ужимаясь, вывеска опускается в эту строку, и при
   более узкой она начинала бы задевать ссылки по краям. */
.header__bar {
    max-width: 1400px;
    margin: 0 auto;

    /* Строка лежит поверх вывески. У вывески свой transform, и браузер рисует
       её выше обычного потока — её невидимый бокс, заметно выше самих букв,
       накрывал ссылки, и нажатие по ним доставалось ей. Пока вывеска вела на
       главную, клики ей просто отключали; теперь она открывает меню, и нужны
       обе: буквы кликаются там, где нарисованы, ссылки — поверх них. */
    position: relative;
    z-index: 1;

    /* Ловит клики не сама строка, а только то, что в ней нарисовано, — см.
       правило ниже. Пустое поле строки шире её содержимого, и на внутренних
       страницах, где вывеска ужата и стоит прямо в этой строке, оно накрывало
       её целиком: надпись переставала открывать меню. */
    pointer-events: none;

    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;

    padding: 18px 0 14px;
}

/* Вывеска пересчитывается на каждом кадре прокрутки. Ужимается она
   масштабом, а не кеглем: так буквы растрируются один раз, а не рисуются
   заново на каждом кадре — от этого прокрутка и была рваной. Точка отсчёта
   наверху по центру: надпись ужимается к своей верхней кромке, оставаясь
   на месте, а пустоту под ней снимает отрицательный отступ. */
.header__wordmark {
    transform-origin: 50% 0;

    transition: letter-spacing .35s cubic-bezier(.22, .61, .36, 1);

    will-change: transform;
}

.header.is-tight .header__wordmark {
    letter-spacing: var(--wordmark-spacing-tight, .16em);
}

.header__nav {
    display: flex;
    align-items: center;
    gap: 26px;

    /* Как и у строки: группа шире своих ссылок, и её пустое поле тоже
       перехватывало бы нажатие по вывеске. */
    pointer-events: none;
}

/* Кликается то, что видно: ссылки, выбор лиги и кнопки масштаба. Их боксы
   малы и стоят по краям строки, поэтому вывеске между ними места хватает. */
.header__cta,
.league-selector,
.header__zoom {
    pointer-events: auto;
}

/* Разделы — простые надписи капсом, без плашек и подложек. */
.header__cta {
    color: var(--ink);

    font-size: 16px;
    font-weight: 500;

    text-transform: uppercase;
    letter-spacing: .04em;
    white-space: nowrap;

    padding-bottom: 2px;
    border-bottom: 1px solid transparent;

    transition: border-color .2s ease;
}

.header__cta:hover {
    border-bottom-color: var(--ink);
}

.header__cta:focus-visible {
    outline: 1px solid var(--ink);
    outline-offset: 3px;
}

.header__tools {
    display: flex;
    align-items: center;
    gap: 22px;

    /* Как и строка с навигацией: группа шире кнопок внутри, и её пустое поле
       перехватывало бы нажатие по вывеске. */
    pointer-events: none;
}

.header__zoom {
    display: flex;
    align-items: center;
    gap: 10px;
}

.header__zoom-btn {
    width: 22px;
    height: 22px;

    display: flex;
    align-items: center;
    justify-content: center;

    font-family: inherit;
    font-size: 17px;
    line-height: 1;

    color: var(--ink);
    background: transparent;
    border: none;

    cursor: pointer;
    opacity: .55;

    transition: opacity .2s ease;
}

.header__zoom-btn:hover {
    opacity: 1;
}

.header__zoom-level {
    min-width: 42px;
    text-align: center;

    font-size: 15px;
    letter-spacing: .04em;

    color: var(--ink-muted);
}

/* Тонкая линия по нижней кромке шапки — единственный разделитель темы. */
.header::after {
    content: '';
    display: block;

    height: 1px;

    background: var(--rule);
}

/* --- Меню -------------------------------------------------------------- */
.menu {
    /* Ширина полосы закрытия у правого края. Панель отступает от края на
       столько же, чтобы пункты меню не оказались под полосой. */
    --menu-edge: 100px;

    position: fixed;
    inset: 0;

    z-index: 40;

    background: rgba(0, 0, 0, 0);

    transition: background .4s ease;
}

.menu.is-open {
    background: rgba(0, 0, 0, .4);
}

.menu__panel {
    position: absolute;
    inset: 0;

    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 40px;

    padding: 120px max(40px, var(--menu-edge)) 40px;

    background: var(--paper);
    border-bottom: 1px solid var(--rule);

    overflow-y: auto;

    /* Панель разворачивается сверху вниз, а не выезжает и не масштабируется:
       содержимое при этом стоит на месте, открывается только «шторка».
       clip-path, а не height, — иначе центрированный контент прыгал бы. */
    clip-path: inset(0 0 100% 0);

    transition: clip-path .5s cubic-bezier(.22, .61, .36, 1);
}

.menu.is-open .menu__panel {
    clip-path: inset(0 0 0 0);
}

/* Полоса по правой кромке экрана — вторая, крупная кнопка закрытия.
   Ширина намеренно мелкая: попасть в неё можно броском курсора в край
   экрана, не целясь, поэтому большего размера она не требует. */
.menu__edge {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;

    width: var(--menu-edge);

    padding: 0;

    background: transparent;
    border: none;
    border-left: 1px solid transparent;

    cursor: pointer;

    /* Проявляется вместе с панелью, а не до неё. */
    opacity: 0;

    transition: opacity .3s ease, background .2s ease, border-color .2s ease;
}

.menu.is-open .menu__edge {
    opacity: 1;
}

.menu__edge:hover {
    background: var(--wash);
    border-left-color: var(--rule);
}

.menu__edge:focus-visible {
    outline: 1px solid var(--ink);
    outline-offset: -3px;
}

/* Пункты не разложены по колонкам, а уложены потоком и переносятся сами:
   разная длина слов и даёт ту рваную строку, что у референса. */
.menu__nav {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: baseline;

    gap: 4px 40px;

    max-width: 1100px;
}

.menu__link {
    font-size: clamp(40px, 7.5vw, 104px);
    font-weight: 500;
    line-height: 1.1;

    text-transform: uppercase;
    letter-spacing: .01em;

    color: var(--ink);

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

       Подъём задан отдельным свойством translate, а не через transform:
       наведение растит пункт через scale, и будь они одним transform, вторая
       анимация стирала бы первую. Врозь у каждой своя длительность и своя
       задержка — разбег при открытии не тормозит отклик под курсором. */
    opacity: 0;
    translate: 0 16px;

    /* Порядок свойств важен: задержки ниже перечислены по этому же списку. */
    transition:
        opacity .4s ease,
        translate .4s ease,
        scale .3s ease,
        filter .3s ease;
}

.menu.is-open .menu__link {
    opacity: 1;
    translate: 0;
}

/* Разбег только у появления: свечение под курсором ждать своей очереди
   не должно. */
.menu.is-open .menu__link:nth-child(1) {
    transition-delay: .22s, .22s, 0s, 0s;
}

.menu.is-open .menu__link:nth-child(2) {
    transition-delay: .29s, .29s, 0s, 0s;
}

.menu.is-open .menu__link:nth-child(3) {
    transition-delay: .36s, .36s, 0s, 0s;
}

/* Служебная строка внизу панели: мелкий капс с подчёркиванием. */
.menu__meta {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;

    gap: 12px 40px;

    margin-top: 24px;
}

.menu__meta-link {
    display: inline-flex;
    align-items: center;
    gap: 10px;

    font-size: 14px;
    font-weight: 500;

    text-transform: uppercase;
    letter-spacing: .08em;

    /* Белые, как и разделы над ними: в меню нет главных и второстепенных
       строк, есть один список того, куда можно уйти. */
    color: var(--ink);

    opacity: 0;
    translate: 0 16px;

    /* Порядок свойств важен: задержки появления ниже перечислены по этому
       же списку. */
    transition:
        filter .3s ease,
        scale .3s ease,
        opacity .4s ease,
        translate .4s ease;
}

.menu.is-open .menu__meta-link {
    opacity: 1;
    translate: 0;
}

.menu.is-open .menu__meta-link:nth-child(1) {
    transition-delay: 0s, 0s, .58s, .58s;
}

.menu.is-open .menu__meta-link:nth-child(2) {
    transition-delay: 0s, 0s, .63s, .63s;
}

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

   drop-shadow, а не text-shadow: свечение нужно и значку рядом с адресом,
   а он нарисован svg — по контуру буквы и по контуру значка свет ложится
   одинаково.

   Только там, где наведение вообще есть: на тач-экране :hover залипает
   после нажатия, и подсвеченной осталась бы последняя нажатая строка. */
@media (hover: hover) {

    .menu.is-open .menu__link:hover,
    .menu.is-open .menu__meta-link:hover {
        filter:
            drop-shadow(0 0 6px rgba(255, 255, 255, .6))
            drop-shadow(0 0 18px rgba(255, 255, 255, .4))
            drop-shadow(0 0 44px rgba(255, 255, 255, .25));
    }

    /* Крупным строкам хватает малой прибавки, мелким нужна заметнее —
       иначе на четырнадцати пикселях её просто не видно. */
    .menu.is-open .menu__link:hover {
        scale: 1.05;
    }

    .menu.is-open .menu__meta-link:hover {
        scale: 1.1;
    }
}

.menu__meta-icon {
    width: 15px;
    height: 15px;

    flex: none;
}

/* Пока меню открыто, в шапке остаётся только кнопка-крестик. */
.header__nav,
.header__zoom {
    transition: opacity .4s ease, transform .4s ease;
}

/* У вывески transform занят ужатием и меняется на каждом кадре прокрутки —
   плавный переход по нему превратил бы её в вечно догоняющую, поэтому здесь
   переходом гасится только прозрачность, а уезжает она вместе со всеми. */
.header__wordmark {
    transition: opacity .4s ease;
}

body.menu-open .header__nav,
body.menu-open .header__zoom {
    opacity: 0;
    transform: translateY(-24px);

    pointer-events: none;
}

body.menu-open .header__wordmark {
    opacity: 0;

    pointer-events: none;
}

/* Пока меню открыто, шапка лежит поверх панели прозрачным слоем. Клики
   она перехватывать не должна: по верху экрана попадали не в меню, а в
   спрятанную вывеску — и та, оставаясь ссылкой, уводила на главную.
   Теперь клик там закрывает меню, как и в любом другом свободном месте. */
body.menu-open .header > .container {
    pointer-events: none;
}

/* Надпись гасим отдельной строкой: у неё собственное pointer-events: auto,
   и запрет, поставленный предку, она бы перебила. */
body.menu-open .header__wordmark-text {
    pointer-events: none;
}

.main {
    padding-bottom: 8px;
}

/* Содержимое и подвал сдвигаются вслед за шапкой на каждом кадре прокрутки.
   Отдельными слоями их держит сам сдвиг — он задаётся трёхмерным, а этого
   браузеру достаточно; отдельная подсказка will-change сверху только
   удвоила бы память под слои такого размера. */

.main__title {
    font-size:32px;
}

.rates {
    padding: 34px 0 45px;
}

/* Цифры курса — тот же приём, что у крупных чисел референса: никаких
   плашек, заливок и линеек, только сами числа. */
.rates__grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
}

.rate-card {
    padding: 18px;

    text-align: center;
}

.rate-card__value {
    margin: 0;

    font-size: 34px;
    font-weight: 500;
    line-height: 1.05;

    color: var(--ink);
    white-space: nowrap;

    font-variant-numeric: tabular-nums;
}

.rate-card__label {
    margin: 8px 0 0;

    font-size: 10px;
    font-weight: 500;

    text-transform: uppercase;
    letter-spacing: .12em;

    color: var(--ink-muted);
}

.rates__crypto {
    display: flex;
    justify-content: center;
}

/* Биткоин отделён от рублёвых курсов строкой: он единственный котируется
   не к рублю и обновляется не раз в сутки, а постоянно. */
.rate-card--btc {
    min-width: 225px;
}

.stub {
    min-height: 55vh;

    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;

    text-align: center;
}

.stub__title {
    font-size: 48px;
    font-weight: 500;

    letter-spacing: .01em;

    color: var(--ink);

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

       text-shadow, а не filter: здесь только текст, а тень по букве дешевле
       для браузера, чем фильтр на всю коробку заголовка. */
    text-shadow:
        0 0 8px rgba(255, 255, 255, .55),
        0 0 24px rgba(255, 255, 255, .35),
        0 0 60px rgba(255, 255, 255, .2);
}

/* --- Замок тестируемой страницы ------------------------------------------
   Четыре цифры кода под заголовком заглушки. Никакой плашки вокруг: как и
   везде на сайте, форму держат только линейки и прозрачности по чёрному. */
.gate {
    /* Заголовок выкладывается побуквенно; замок проявляется следом,
       когда последняя буква уже на месте. */
    animation: gateIn .6s ease .9s both;

    margin-top: 34px;

    display: flex;
    flex-direction: column;
    align-items: center;
}

@keyframes gateIn {
    from {
        opacity: 0;
        transform: translateY(8px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* display у класса сильнее, чем display:none, который браузер даёт атрибуту
   hidden, — без этой пары правил скрытые блоки остаются на экране. */
.gate[hidden],
.gate-content[hidden] {
    display: none;
}

.gate__label {
    margin: 0 0 16px;

    font-size: 11px;
    font-weight: 500;

    text-transform: uppercase;
    letter-spacing: .12em;

    color: var(--ink-muted);
}

.gate__cells {
    display: flex;
    gap: 12px;
}

/* Цифру набирают в квадрате, а не в поле со стрелками: number подсовывает
   счётчик и пускает в поле «e» с минусом — здесь нужен ровно один знак. */
.gate__cell {
    width: 64px;
    height: 64px;

    padding: 0;

    background: var(--wash);
    border: 1px solid var(--rule);
    border-radius: 12px;

    font-family: inherit;
    font-size: 30px;
    font-weight: 500;
    line-height: 1;

    text-align: center;
    color: var(--ink);

    font-variant-numeric: tabular-nums;
    caret-color: var(--ink);

    /* Точка, которой браузер закрывает цифру, рисуется мельче самой цифры —
       поднимаем её до размера квадрата и растягиваем интервал, иначе набранный
       знак теряется в центре клетки. */
    letter-spacing: .1em;
    text-indent: .1em;

    transition: border-color .2s ease, box-shadow .2s ease, background .2s ease;
}

.gate__cell:focus {
    outline: none;

    background: rgba(255, 255, 255, .1);
    border-color: var(--rule-strong);

    /* Тот же ровный свет, что у заголовка, — только по рамке квадрата. */
    box-shadow:
        0 0 8px rgba(255, 255, 255, .28),
        0 0 24px rgba(255, 255, 255, .14);
}

/* Заполненный квадрат держит рамку поярче — видно, сколько цифр уже набрано,
   даже когда курсор ушёл дальше. */
.gate__cell--filled {
    border-color: var(--rule-strong);
}

.gate__cell:disabled {
    opacity: .5;
}

.gate__note {
    min-height: 18px;
    margin: 14px 0 0;

    font-size: 12px;
    letter-spacing: .04em;

    color: var(--ink-faint);
}

.gate__note--error {
    color: var(--ink);
}

/* Неверный код: короткая отмашка по горизонтали. Отдельного красного цвета
   на сайте нет, и заводить его ради одной ошибки незачем — движение
   читается быстрее подписи. */
.gate--wrong .gate__cells {
    animation: gateShake .4s ease;
}

@keyframes gateShake {
    20% { transform: translateX(-8px); }
    40% { transform: translateX(8px); }
    60% { transform: translateX(-5px); }
    80% { transform: translateX(3px); }

    to { transform: translateX(0); }
}

/* --- Рабочая область за кодом --- */
.gate-content {
    animation: gateIn .5s ease both;

    width: 100%;
    margin-top: 10px;

    text-align: center;
}

/* Фокус переводим сюда, когда код принят: экранный диктор прочитает
   заголовок открывшейся области, а не подпись кнопки. Рамку вокруг него
   браузеру рисовать незачем — фокус здесь служебный. */
.gate-content__title:focus {
    outline: none;
}

.gate-content__title {
    margin: 0;

    font-size: 40px;
    font-weight: 500;

    color: var(--ink);

    text-shadow:
        0 0 8px rgba(255, 255, 255, .55),
        0 0 24px rgba(255, 255, 255, .35),
        0 0 60px rgba(255, 255, 255, .2);
}

.gate-content__note {
    margin: 14px 0 0;

    font-size: 14px;

    color: var(--ink-muted);
}

/* Сюда лягут данные страницы, когда они появятся. */
.gate-content__data {
    margin-top: 26px;
    padding-top: 22px;

    border-top: 1px solid var(--rule);
}

.gate-content__lock {
    margin: 26px 0 0;

    padding: 0;

    background: none;
    border: none;

    font-family: inherit;
    font-size: 11px;
    font-weight: 500;

    text-transform: uppercase;
    letter-spacing: .12em;

    color: var(--ink-faint);
    cursor: pointer;

    transition: color .2s ease;
}

.gate-content__lock:hover,
.gate-content__lock:focus-visible {
    color: var(--ink);
}

/* Системная синяя рамка фокуса по чёрному чужеродна — подсвечиваем
   кнопку тем же ровным светом, что и остальную страницу. */
.gate-content__lock:focus-visible {
    outline: none;

    text-shadow:
        0 0 8px rgba(255, 255, 255, .5),
        0 0 20px rgba(255, 255, 255, .28);
}

/* Слово целиком. Буквы внутри — inline-block-спаны, и без этой обёртки
   браузер разрывает слово между любыми двумя буквами. */
.stub__word {
    display: inline-block;
    white-space: nowrap;
}

.stub__char {
    display: inline-block;

    opacity: 0;
    transform: translateX(-21px);

    animation: stubCharIn .5s ease forwards;
}

@keyframes stubCharIn {
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

@media (max-width: 768px) {
    .rates {
        padding: 16px 0 50px;
    }

    .stub__title {
        font-size: 34px;
    }

    /* Четыре ячейки в ряд на телефоне не помещаются — раскладываем 2×2. */
    .rates__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .rate-card {
        padding: 14px 10px;
    }

    .rate-card__value {
        font-size: 32px;
    }

    .rate-card__label {
        font-size: 14px;
        letter-spacing: .1em;
    }
}

.footer {
    background: var(--paper);
    color: var(--ink);

    margin-top: 60px;

    border-top: 1px solid var(--rule);
}

.footer > .container {
    max-width: none;
}

.footer__wrap {
    padding: 40px 0 28px;
}

.footer__panel {
    padding: 0;
}

.footer__cols {
    display: flex;
    gap: 56px;
}

.footer__col {
    display: flex;
    flex-direction: column;
    gap: 8px;

    min-width: 150px;
}

/* Крупные ссылки той же гарнитуры: подчёркивание появляется по наведению,
   как у ссылок референса. */
.footer__link {
    font-size: 30px;
    font-weight: 500;
    letter-spacing: .01em;

    color: var(--ink);

    padding-bottom: 2px;
    border-bottom: 1px solid transparent;

    transition: border-color .2s ease;
}

.footer__link:hover {
    border-bottom-color: var(--ink);
}

.footer__contacts {
    display: flex;
    flex-direction: column;
    gap: 10px;

    margin-top: 28px;
    padding-top: 20px;

    border-top: 1px solid var(--rule);
}

.footer__contact {
    display: inline-flex;
    align-items: center;
    gap: 10px;

    font-size: 14px;
    font-weight: 500;

    text-transform: uppercase;
    letter-spacing: .08em;

    color: var(--ink-muted);

    transition: color .2s ease;
}

.footer__contact:hover {
    color: var(--ink);
}

.footer__contact-icon {
    width: 15px;
    height: 15px;

    flex: none;
}

/* Нижняя служебная строка: слева копирайт, справа приписка. */
.footer__meta {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 8px 24px;

    margin-top: 34px;
    padding-top: 16px;

    border-top: 1px solid var(--rule);
}

.footer__copyright,
.footer__note {
    margin: 0;

    font-size: 13px;
    font-weight: 500;

    text-transform: uppercase;
    letter-spacing: .1em;

    color: var(--ink-muted);
}

.footer__tagline {
    margin: 14px 0 0;

    font-size: 15px;

    color: var(--ink-faint);
}

/* ==========================================================================
   МОБИЛЬНАЯ ВЕРСИЯ
   Все правила ниже включаются только на тач-устройствах и узких экранах.
   Десктопная раскладка (шире 768px, указатель «мышь») не затрагивается.
   ========================================================================== */

/* --- Тач-устройства: убираем «залипший» hover ----------------------------
   После тапа мобильный браузер оставляет :hover на последнем нажатом
   элементе, и ссылка в шапке так и остаётся увеличенной и подсвеченной,
   пока не тапнешь в другое место. Возвращаем таким элементам обычный вид. */
@media (hover: none) {

    .header__cta:hover,
    .footer__link:hover {
        border-bottom-color: transparent;
    }

    .header__zoom-btn:hover {
        opacity: .55;
    }

    .footer__contact:hover {
        color: var(--ink-muted);
    }
}

/* --- Смартфоны ----------------------------------------------------------- */
@media (max-width: 768px) {

    /* Серый прямоугольник поверх ссылок при тапе в Chrome/Safari на Android
       и iOS выглядит как артефакт — у элементов есть свои :active-состояния. */
    a,
    button {
        -webkit-tap-highlight-color: transparent;
    }

    /* Страховка от горизонтальной прокрутки: даже если какой-то блок
       окажется шире экрана, страница вбок не поедет. clip, а не hidden —
       hidden превратил бы body в отдельный контейнер прокрутки. */
    body {
        overflow-x: clip;
    }

    /* Учитываем «челку» и скруглённые углы (viewport-fit=cover). */
    .container {
        padding-left: max(16px, env(safe-area-inset-left));
        padding-right: max(16px, env(safe-area-inset-right));
    }

    /* 100vh на мобильных считается по экрану БЕЗ адресной строки, поэтому
       первый экран получается выше видимой области и низ контента срезан.
       svh — это высота с видимой панелью браузера, то есть гарантированный
       минимум. Заодно остаётся исходный смысл: футер ниже первого экрана. */
    main {
        min-height: 100svh;
    }

    /* --- Шапка --- */
    .header {
        padding-top: 10px;
    }

    .header__bar {
        padding: 12px 0 10px;
    }

    /* На телефоне в строке помещаются только служебные кнопки — разделы
       дублируются внутри панели меню. */
    .header__nav .header__cta {
        display: none;
    }

    /* Выбор лиги занимает всю строку: рядом с кнопкой меню он не помещается. */
    .header__nav {
        flex: 1;
        min-width: 0;
    }

    .menu {
        --menu-edge: 44px;
    }

    .menu__panel {
        gap: 28px;

        padding: 90px max(20px, var(--menu-edge)) 24px;
    }

    /* На широком экране пункты уложены потоком и переносятся сами — в этом
       приём референса. На экране телефона потока не выходит: «CEX Arbitrage»
       занимает всю строку целиком, короткие названия делят строку с длинными,
       и колонка встаёт вразнобой. Поэтому здесь — строго по пункту в строке,
       каждый по центру. */
    .menu__nav {
        flex-direction: column;
        align-items: center;

        gap: 0;
    }

    .menu__link {
        min-height: 44px;

        display: inline-flex;
        align-items: center;
        justify-content: center;

        /* «CEX Arbitrage» в 40px не помещается в ширину экрана и переносится
           внутри самого пункта. Без выравнивания короткая первая строка
           прижималась бы к левому краю, а вторая шла во всю ширину. */
        text-align: center;
    }

    .menu__meta {
        margin-top: 12px;
    }

    .menu__meta-link {
        min-height: 44px;
    }

    .header__wordmark {
        font-size: clamp(40px, 21vw, 120px);
    }

    /* На телефоне выбор лиги занимает отдельную строку под вывеской, и
       уступать ему место незачем: надпись остаётся ровно по центру,
       как и до выбора. Отъезд вправо нужен только там, где лига и
       вывеска делят одну строку, — на широком экране. */
    body.league-picked .header__wordmark-text {
        transform: none;
    }

    /* Кнопки масштаба на смартфоне не нужны и вредны: у мобильного браузера
       есть свой зум жестом, а zoom у .main ломает раскладку и вызывает
       горизонтальную прокрутку. Скрипт шапки дополнительно сбрасывает zoom. */
    .header__zoom {
        display: none;
    }

    /* --- Курсы валют на главной --- */
    .rates {
        padding: 16px 0 40px;
    }

    .rate-card__value {
        font-size: clamp(22px, 6.4vw, 32px);
    }

    .rates__crypto {
        margin-top: 12px;
    }

    .rate-card--btc {
        min-width: 0;
        width: 100%;
    }

    /* --- Заглушка --- */
    .stub {
        min-height: 45svh;
    }

    .stub__title {
        font-size: clamp(24px, 8vw, 34px);
        line-height: 1.2;
    }

    /* Четыре квадрата по 64 px с отступами в строку узкого экрана не влезают:
       размер и просветы считаем от ширины экрана. */
    .gate {
        margin-top: 26px;
    }

    .gate__cells {
        gap: clamp(8px, 2.6vw, 12px);
    }

    .gate__cell {
        width: clamp(52px, 16vw, 64px);
        height: clamp(52px, 16vw, 64px);

        font-size: clamp(24px, 7vw, 30px);
    }

    .gate-content__title {
        font-size: clamp(26px, 8vw, 40px);
    }

    /* --- Подвал --- */
    .footer {
        margin-top: 24px;
    }

    .footer__wrap {
        padding: 0 0 max(12px, env(safe-area-inset-bottom));
    }


    .footer__cols {
        gap: 20px;
    }

    .footer__col {
        min-width: 0;
        gap: 0;
    }

    /* Ссылки подвала стоят плотным столбиком: без вертикальных отступов
       соседние пункты слипаются и попасть пальцем в нужный сложно. */
    .footer__link {
        display: inline-flex;
        align-items: center;

        min-height: 44px;

        font-size: 20px;
    }

    .footer__contacts {
        margin-top: 18px;
        padding-top: 14px;
    }

    .footer__contact {
        min-height: 44px;
        font-size: 12px;
    }

    .footer__meta {
        margin-top: 18px;
    }

    .footer__copyright,
    .footer__note {
        font-size: 11px;
    }

    .footer__tagline {
        font-size: 12px;
    }
}

/* Совсем узкие экраны (iPhone SE и подобные): шапка в одну строку. */
@media (max-width: 380px) {

    .header__nav {
        gap: 8px;
    }
}

/* --- Уменьшенная анимация ------------------------------------------------
   Системная настройка «уменьшить движение» (iOS/Android/Windows): побуквенное
   появление и плавная прокрутка отключаются. */
@media (prefers-reduced-motion: reduce) {

    html {
        scroll-behavior: auto;
    }

    body.page-home .header__wordmark-text {
        animation: none;
    }

    .header__wordmark {
        transition: none;
    }

    .stub__char {
        animation: none;

        opacity: 1;
        transform: none;
    }

    .gate,
    .gate-content {
        animation: none;
    }

    .gate--wrong .gate__cells {
        animation: none;
    }

    .header__cta,
    .header__wordmark,
    .menu__link {
        transition: none;
    }

    .menu,
    .menu__panel,
    .menu__edge,
    .menu__link,
    .menu__meta-link,
    .header__wordmark,
    .header__nav,
    .header__zoom {
        transition: none;
    }
}
