/* ============================================================
   КСЛТ — СТРАНИЦА МАТЧА.  Префикс lm-
   ============================================================
   РАМКА СТРАНИЦЫ — ЭТАЛОН ЛЕНДИНГА, решение Кости 24.09.
   Своих чисел у страницы нет: поле от края задаёт --pad-x,
   ширину ограничивает та же формула (максимум 1400),
   отбивку сверху — --header-h. Было: контейнер 1100 и поля
   20 / 12 числом, отсюда левый край 110 против 28 у шапки.
   Это дефект h243 из описания компонента Header 168:147.

   СЕТКА НЕ МЕНЯЕТСЯ. Слева видео, если есть youtube_url, и
   ход матча, если его нет. Табло справа всегда одной ширины.
   Решение Кости 24.09: «если будет ссылка с youtube — будет
   видео, если нет — будет это». Одна сетка — одна раскладка
   в коде, одна в заморозке, один тест, и появившаяся посреди
   матча трансляция не перекладывает страницу под руками.

   Доска: Live match — the score is the page, video joins it.
   ============================================================ */

.lm-container {
    /* 40 — «воздух под шапкой» по доске 323:2 */
    /* ШАПКУ ОТБИВАЕТ main, А НЕ СТРАНИЦА. Поймано 25.09: Костя сказал
       «подними всё вверх, названия спонсоров обрезаются внизу» — я померил
       и нашёл, что высота шапки считалась ДВАЖДЫ. main { padding-top:
       var(--header-h) } даёт 64, и страница добавляла её второй раз:
       64 + 64 + 40 = ссылка «На главную» на 168 вместо 104. Сто четыре
       пикселя пустоты под шапкой вместо сорока, и вся страница на эти
       64 ниже — из-за чего подписи спонсоров и уезжали за сгиб.
       ЭТО ТА ЖЕ ПОЛОМКА, ЧТО УЖЕ ОПИСАНА в style.css у правила
       main:has(.hero) — там её вылечили обнулением main, здесь лечим с
       другой стороны: страница перестаёт отбивать шапку сама.
       Одно определение на одно понятие. Остаётся только воздух — 40,
       «воздух под шапкой» по доске 323:2. */
    padding: var(--space-10) var(--pad-x) var(--space-10);

    /* СТУПЕНИ ЖУРНАЛА уехали 02.11 в `css/tokens.css`, на `:root`:
       журнал показывают оба продукта, а здесь их видела только
       страница — в приложении `var(--lm-game-h)` не разрешалось вовсе.
       Значения те же, `:root` стоит выше этого контейнера, вид прежний. */

    /* СТРАНИЦА ЖИВЁТ В ОДНОМ ЭКРАНЕ. Решение Кости 25.09: «надо будет всё
       разместить на одном окне без скролов». Правило стояло ТОЛЬКО выше
       992, и ниже страница росла как хотела: на 390 x 844 документ был
       2356 при экране 844, на 844 x 390 — 2616 при экране 390. Табло
       начиналось на 1301, 1287 и 1256 — счёт, ради которого страницу
       открывают, лежал ниже сгиба на полтора-три экрана. Тест этого не
       ловил: я сам загнал проверку выше 992. Костя: «нет, не прошло».
       100dvh, А НЕ 100vh: на телефоне 100vh считается без адресной
       строки, и низ страницы уезжает под неё. На десктопе они равны. */
    height: calc(100dvh - var(--header-h));
    display: flex;
    flex-direction: column;
}

/* ── НАЗАД ────────────────────────────────────────────────
   Ссылка, а не кнопка: она ничего не отправляет. Но цель
   нажатия берёт ступень md 44 у Button 17:82 и кольцо фокуса
   3px — «required on every button», WCAG 2.4.7. Тот же приём
   уже применён к .auth-back-link. */
.lm-back-link {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    width: fit-content;
    min-height: var(--btn-h-md);
    font-size: var(--fs-sm);
    font-weight: var(--fw-semibold);
    color: var(--text-secondary);
    text-decoration: none;
    margin-bottom: var(--space-2);
    transition: color var(--transition-fast);
}
.lm-back-link:hover { color: var(--text-primary); }
.lm-back-link:focus-visible {
    outline: var(--bw-heavy) solid var(--accent);
    outline-offset: 3px;
    border-radius: var(--radius-sm);
}

/* ── ЗАГОЛОВОК МАТЧА ──────────────────────────────────────
   Страница называет матч. Раньше заголовка не было вовсе, и
   первым заголовком документа был h4 подвала. */
.lm-title {
    font-size: var(--fs-2xl);
    font-weight: var(--fw-extrabold);
    line-height: var(--lh-tight);
    letter-spacing: -0.02em;
    color: var(--text-primary);
    margin: 0 0 var(--space-2);
}
/* СТРОКА ПОД ЗАГОЛОВКОМ. Решение Кости 25.09: «можно будет размер
   увеличить и сделать может белым — это название турнира же».
   Было 14 / 400 на --text-muted (50 %): имя турнира читалось как
   служебная приписка, хотя это единственное место на странице, где
   сказано, ГДЕ играют.
   Ступень вверх по шкале, 14 → 16, и цвет на ступень громче:
   --text-muted → --text-secondary. Белым целиком не делаю — строка встала
   бы вровень с заголовком 32/800 и поспорила с ним; --text-secondary даёт
   9.94 против 5.33, читается уверенно и остаётся подписью.
   Имя турнира внутри строки — 600, формат остаётся 400. Отличаем ВЕСОМ,
   а не вторым цветом: краска на этой странице уже занята игроками.
   ПОД ТАБЛО НИЧЕГО НЕ ТРОГАЛ — решение Кости: «там под счетом оставить
   как есть без изменений». Строки «Подаёт · Турнир · Формат» остались
   12 / 400 на --text-muted. */
.lm-meta {
    font-size: var(--fs-base);
    color: var(--text-secondary);
    /* Отбивка до сетки была и остаётся 24. Чуть не потерял её, переписывая
       правило целиком: менялись кегль и цвет, а не отступ. */
    margin: 0 0 var(--space-6);
}
.lm-meta-tour { font-weight: var(--fw-semibold); }

/* ── СЕТКА ────────────────────────────────────────────────
   2 : 1 при зазоре 24. На 1280 содержимое 1224 — это ровно
   800 и 400; на 1400 — 917 и 459. Число колонок — свойство
   экрана, ширина табло выводится из него, а не задаётся. */
.lm-grid {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: var(--space-6);
    /* КОЛОНКИ ЧИТАЮТСЯ КАК ОДНА КАРТОЧКА, ПОЭТОМУ ТЯНУТСЯ ДО ОБЩЕЙ ВЫСОТЫ.
       Было align-items: start — и при короткой ленте слева стояла коробка
       96 высотой против 291 справа. Костя спросил дважды, и он прав: две
       коробки разной высоты рядом читаются как поломка вёрстки, а не как
       решение.
       Это НЕ возвращение серого прямоугольника «Нет трансляции». Тот был
       пуст и извинялся; эта коробка полна и просто ещё невысокая — к
       середине матча лента её перерастает. Разница между «зарезервировали
       место под ничто» и «у контейнера есть своя форма». */
    align-items: stretch;
    /* СЕТКА ЗАБИРАЕТ ОСТАТОК ЭКРАНА. grid-template-rows ОБЯЗАТЕЛЕН: без
       него ряд остаётся auto и растёт по содержимому, сколько бы высоты
       ни было у самой сетки — журнал вымахал до 1016 при контейнере 736.
       minmax(0, 1fr) разрешает ряду сжиматься. */
    flex: 1 1 auto;
    min-height: 0;
    grid-template-rows: minmax(0, 1fr);
}

/* ── ДВЕ КОЛОНКИ ──────────────────────────────────────────
   ЛЕВАЯ: видео, а под ним журнал. До 25.09 это было ИЛИ — ИЛИ, и на
   матчах с трансляцией журнала не было видно вовсе, то есть ровно там,
   где смотрит больше всего людей. Вопрос задал Костя: «а когда там будет
   трансляция, куда журнал пойдёт?». Под видео: журналу нужна ШИРИНА, а не
   высота — в ряд на 800 влезает 18 очков против 8 в колонке 400, — и
   ширина у левой колонки уже есть.
   ПРАВАЯ: табло сверху, спонсоры прижаты к НИЗУ. Решение Кости 25.09:
   «блок спонсоры надо будет спустить вниз самый, на уровне что будет окно
   трансляции». Поэтому колонка тянется во всю высоту ряда, а не стоит по
   содержимому, и нижний край карусели совпадает с нижним краем журнала. */
.lm-left {
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
    min-width: 0;
}
.lm-right {
    align-self: stretch;
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
    min-width: 0;
}
/* Табло по содержимому, спонсоры — вниз. margin-top: auto съедает весь
   остаток колонки и прижимает блок к нижнему краю; gap при этом не
   удваивается, потому что между ними уже нет свободного места. */
.lm-right .lm-sponsors { margin-top: auto; }


/* ── ВИДЕО ────────────────────────────────────────────────*/
.lm-video {
    width: 100%;
    border-radius: var(--radius-lg);
    overflow: hidden;
    background: var(--bg-card);
}
.lm-video-wrapper { position: relative; padding-bottom: 56.25%; height: 0; }
.lm-video-wrapper iframe {
    position: absolute; inset: 0;
    width: 100%; height: 100%; border: none;
}

/* ── ТАБЛО ────────────────────────────────────────────────
   Коробка — Card 29:65: радиус 16, 1px border/subtle, bg/card. */
.lm-score-panel {
    background: var(--bg-card);
    border: var(--bw-hair) solid var(--border-subtle);
    border-radius: var(--radius-lg);
    overflow: hidden;
}

/* Бейдж статуса НЕ объявляется здесь: страница берёт .live-badge
   лендинга вместе с тонами is-live / is-warmup / is-paused.
   Одно определение на одно понятие — до 24.09 их было два, и
   они расходились: разминка была янтарной на главной и серой
   здесь, пауза наоборот. */

.lm-players { padding: 0; }

.lm-player-row {
    display: grid;
    grid-template-columns: 40px 1fr auto;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border-bottom: var(--bw-hair) solid var(--border-subtle);
}
.lm-player-row:last-child { border-bottom: none; }
/* КЛЮЧ К ЦВЕТУ ЛЕНТЫ — САМИ СТРОКИ ИГРОКОВ.
   Полоска у розыгрыша говорит, кто взял очко, но до 24.09 нигде не было
   сказано, ЧЬЯ полоска какая. Костя: «цветами выделил классно, а вот у
   игроков нет цветов». Теперь та же краска стоит у имени на табло — ключ
   лежит там, где и так написаны имена, и отдельной легенды не нужно. */
.lm-player-row { box-shadow: inset 3px 0 0 var(--player-1); }
.lm-player-row + .lm-player-row { box-shadow: inset 3px 0 0 var(--player-2); }
.lm-player-row.lm-serving { background: var(--surface-glass); }
.lm-player-row.lm-winner-row { background: var(--accent-subtle); }

/* Аватар — ступени Avatar 29:82: md 40 широкий, sm 32 телефон.
   Было 44 / 36 / 32 — ни одна не на шкале компонента. */
.lm-avatar,
.lm-avatar-placeholder {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-full);
}
.lm-avatar { object-fit: cover; border: var(--bw-thick) solid var(--border-subtle); }
.lm-avatar-placeholder {
    display: flex; align-items: center; justify-content: center;
    background: var(--surface-glass-hover);
    font-size: var(--fs-sm);
    font-weight: var(--fw-bold);
    color: var(--text-secondary);
}

.lm-name-block { min-width: 0; }
/* ИМЯ НА ТАБЛО — 18, А НЕ 21. Решение Кости 25.09 глазами: «название
   мелкие, а там слишком крупные» — он поставил рядом имя в журнале (11) и
   имя на табло (21) и увидел, что это одно и то же понятие на слишком
   разных ступенях.
   Померено до правки, 1280: табло — очки 40/800 · сет 26/800 · имя 21/700
   · аватар 14/700 · инфо 12/400 · бейдж 11/500; журнал — заголовок гейма
   14/700 · цифра 12/700 · имя 11/400.
   Ступень вниз. Лестница табло остаётся лестницей: 40 · 26 · 18, и счёт
   доминирует сильнее прежнего. Заодно чинится обрезка: «Иван
   Корабельников» на 21/700 не помещался в колонку 400 и заканчивался
   многоточием — было видно на снимке Кости.
   ДВА ИМЕНИ НЕ СВЕДЕНЫ В ОДНУ СТУПЕНЬ НАМЕРЕННО: на табло имя — подпись
   строки-заголовка, в журнале — повторяющаяся метка строки таблицы,
   и 11 там взято у Badge 27:53. Разная плотность блоков — законная
   причина для разных ступеней; двукратный разрыв — нет. */
.lm-player-name {
    display: flex; align-items: center; gap: var(--space-2);
    font-size: var(--fs-md);
    font-weight: var(--fw-bold);
    line-height: var(--lh-tight);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lm-serve-indicator {
    width: 8px; height: 8px; border-radius: var(--radius-full);
    background: var(--success);
    flex-shrink: 0;
}

/* ЛЕСТНИЦА ЦИФР. До 24.09 имя, счёт сета и очки были все трое
   16 — три уровня одним кеглем, иерархии нет. Ступени взяты из
   шкалы, промежуточных не заведено (правило Stat tile 39:57). */
.lm-scores { display: flex; gap: var(--space-2); align-items: baseline; }
.lm-set-score {
    min-width: 26px;
    text-align: center;
    font-size: var(--fs-xl);
    font-weight: var(--fw-extrabold);
    font-variant-numeric: tabular-nums;
    color: var(--text-muted);
}
.lm-set-score.lm-current { color: var(--text-primary); }
/* ОЧКИ ТОГО ЖЕ КЕГЛЯ, ЧТО И ГЕЙМЫ — 26. Решение Кости 25.09 глазами:
   «лаймовые цифры надо будет сделать такого же размера, что и геймы».
   Тот же довод, которым он снял лишнюю ширину у ячейки «ГЕЙМ» в журнале:
   лайм здесь И ЕСТЬ признак, размером его дублировать не нужно.
   ОТМЕНЯЕТ МОЁ ПРЕЖНЕЕ РЕШЕНИЕ «очки 40 · сеты 26 · имя 21», записанное
   на доске 447:9 и в правиле «число может быть главным только там, где с
   ним никто не спорит». Не стираю его, помечаю: правило остаётся верным,
   но Костя решил, что на этом табло с числом спорит соседнее число, и
   развести их достаточно краской.
   ЧЕМ ПЛАТИМ, называю честно: у табло больше нет верхней ступени.
   Лестница была 40 · 26 · 18, стала 26 · 26 · 18 — текущее очко перестало
   быть самым громким на странице, и отличается от счёта по геймам только
   цветом. У ATP и Уимблдона текущее очко крупнее геймов. Если на живом
   матче окажется, что счёт читается хуже, — вернуть ступень 32, она между
   ними и свободна.
   Ширина ячейки 56 → 40: под двумя знаками («40», «AD») 56 давало дыру. */
.lm-points-score {
    min-width: 40px;
    text-align: center;
    font-size: var(--fs-xl);
    font-weight: var(--fw-extrabold);
    font-variant-numeric: tabular-nums;
    line-height: var(--lh-tight);
    color: var(--accent);
}

/* ── ПОДАЧА И СВЕДЕНИЯ ────────────────────────────────────*/
/* ПОДПИСЬ ПОД ТАБЛО, А НЕ ЧАСТЬ ТАБЛО. Было: подложка карточки и полоса
   сверху — блок читался как нижний этаж счёта, и карточка счёта тянулась
   на 95 ниже полосы под вторым игроком. Рядом стоящий блок спонсоров
   тянулся ей вровень и пустовал снизу. Решение Кости 25.09.
   Узел теперь и в разметке стоит ПОСЛЕ табло (js/live-match.js). */
.lm-info {
    padding: 0 var(--space-1);
    border-top: 0;
    background: transparent;
    display: flex; flex-direction: column; gap: var(--space-2);
}
.lm-info-row {
    display: flex; justify-content: space-between; gap: var(--space-3);
    font-size: var(--fs-xs);
    /* Было rgba(255,255,255,0.4) — контраст 3.83 при пороге 4.5.
       --text-muted это 50 %, и он порог проходит. */
    color: var(--text-muted);
}
.lm-info-val { color: var(--text-secondary); font-weight: var(--fw-semibold); }

/* ── СПОНСОР МАТЧА ────────────────────────────────────────
   Поле sponsor_logo в базе есть с самого начала и рисовалось
   только на табло для зала (js/scoreboard.js). Человек, который
   смотрит матч из дома, спонсора не видел вовсе. Лайма здесь
   нет: акцент принадлежит главному действию экрана, 109:370. */
.lm-sponsor {
    display: flex; align-items: center; gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border-top: var(--bw-hair) solid var(--border-subtle);
    font-size: var(--fs-xs);
    color: var(--text-muted);
}
.lm-sponsor-logo { max-height: 20px; width: auto; display: block; }
.lm-sponsor-name { color: var(--text-secondary); font-weight: var(--fw-semibold); }

/* ── ПОБЕДИТЕЛЬ ───────────────────────────────────────────*/
.lm-winner-block {
    padding: var(--space-4);
    text-align: center;
    background: var(--accent-subtle);
    border-top: var(--bw-hair) solid var(--border-subtle);
}
.lm-winner-text {
    font-size: var(--fs-base);
    font-weight: var(--fw-bold);
    color: var(--accent);
}
.lm-final-score {
    font-size: var(--fs-sm);
    color: var(--text-muted);
    margin-top: var(--space-2);
}

.lm-tiebreak-badge {
    text-align: center;
    padding: var(--space-2);
    font-size: var(--fs-2xs);
    font-weight: var(--fw-semibold);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--warning);
    background: var(--warning-subtle);
}

/* ── ХОД МАТЧА ────────────────────────────────────────────
   Занимает место видео, когда трансляции нет. Построено на
   Timeline item 39:78: точка 12 на рельсе 2, отступ 16,
   ведущее слово 14 Bold акцентом. «Last has no trailing rail» —
   поэтому рельс обрывается на текущем гейме. */

/* СНИМОК НА ВСЕЙ ПАНЕЛИ, а не полосой снизу.
   ПОПРАВКА К СЕБЕ, 25.09. Я написал Косте, что гасить надо на 84 % и что
   это «не видно вовсе», и сосчитал по СРЕДНЕЙ яркости — а средняя врёт:
   у тёмного снимка она низкая и тогда, когда предмет в кадре прекрасно
   читается. Костя выбрал ракетку, я померил её отдельно — и она держится:
   гашение 79 % (яркость 0.206, цвет 0.55), ракетка и мяч видны, а самая
   тусклая цифра держит 4.57 при пороге 4.5 В ЛЮБОЙ точке панели.
   Работает это потому, что снимок тёмный сам по себе и предмет на нём —
   силуэт: гашение забирает у него яркость, но не форму. У арены с
   прожекторами так не вышло бы — её пришлось бы гасить до пустоты.
   Затемнение запечено в файл, 12 КБ.

   Маска добавляет вертикальный уклон: вверху, где заголовок и первый
   гейм, темнее; внизу снимок в полную силу. Маска только УБАВЛЯЕТ —
   замеренный пол 4.57 от неё не падает, а растёт. */
/* ЖУРНАЛ НЕ РАСТЁТ БЕЗ КОНЦА. Решение Кости 25.09: «спонсоры съехали
   из-за того, что таблица журнала начала расти, может там поставить
   скролл».
   Он прав, и вот почему это не вкусовое: журнал растёт линейно по ходу
   матча. Три сета — это тридцать с лишним геймов по ~90 пикселей, то есть
   почти три тысячи. Всё, что ниже — спонсоры, подвал, — уезжало бы тем
   дальше, чем дольше идут. Высота страницы не должна зависеть от того,
   сколько времени играют.
   Прокрутка ВНУТРИ, а не свёртка прошлых геймов: свёртку мы уже пробовали
   и Костя её отверг — закрытый гейм терял свои розыгрыши. Так же устроен
   пойнт-бай-пойнт у Flashscore и Уимблдона.
   Идущий гейм стоит ПЕРВЫМ в списке, поэтому прокрутка начинается ровно
   на том, что происходит сейчас, и закреплять его отдельно не нужно.

   ТОЛЬКО ТАМ, ГДЕ ЕСТЬ ВТОРАЯ КОЛОНКА. Ниже 992 сетка становится в одну
   колонку, и вложенная прокрутка на телефоне — известная беда: палец
   двигает не то, что человек хотел. Там журнал растёт свободно, а
   прокручивается сама страница: ей всё равно больше нечего показывать
   рядом. Правило привязано к той же границе 992, что и сетка, а не к
   своему числу. */


/* Колонка: заголовок и чипы по содержимому, список забирает остаток.
   Без min-height: 0 у списка flex-элемент не сжимается ниже содержимого,
   и прокрутка не включится вовсе. */


/* Переключение сетов — ЧИП (Filter chip 49:77), а не таб: он фильтрует
   список на месте, а не переключает весь экран. «They look similar and
   must not be swapped» — из описания компонента. */

/* ── ГЕЙМ: ДВЕ СТРОКИ, ВЫРОВНЕННЫЕ ПО КОЛОНКАМ ────────────
   Решение Кости 25.09 по макету.

   Было: один ряд чипов «15–0 · 30–0 · 30–15». Не сказано, чей счёт
   первый; победитель очка закодирован дугой 3px без подписи; «40–40 ·
   40–AD · 40–40» плоским рядом читается как сбой. Костя: «не понятно».

   Стало: верх — очки первого, низ — второго, ячейки одной ширины, одна
   под другой. Взявшего очко видно по тому, ЧЬЁ ЧИСЛО СДВИНУЛОСЬ. Краска
   осталась рельсом слева, тем же, что у строк табло, и значит ровно одно:
   кто есть кто. Так устроен пойнт-бай-пойнт у Уимблдона и ATP. */

/* Идущий гейм — единственный, кто доминирует в списке. Тот же тон, что
   у бейджа LIVE: Badge 27:53, Danger. */

/* Рельс игрока — ровно та же пара, что у строк табло справа.
   Одно определение на одно понятие: цвет значит «кто», и только. */


/* Длинный гейм уезжает вбок прокруткой, а не ломает строку и не мельчает:
   пара строк обязана остаться парой, иначе колонки разойдутся и читать
   будет нечего. */
/* КЕГЛЬ ЦИФРЫ 14, А НЕ 16. Решение Кости 25.09 глазами: «цифры мелкого
   счёта через чур большие». Ступень вниз по шкале, не промежуточная.
   ВТОРОЙ ЗАХОД, тем же вечером: «цифры всё равно большие». Померил, из
   чего складывался вес, и оказалось, что дело не в кегле, а в ПЛАШКЕ:
   36 x 28 сплошной заливки вокруг двух знаков читается как кнопка, а не
   как счёт. У Уимблдона и ATP в пойнт-бай-пойнте плашек нет вовсе —
   выигравшее очко держится весом и цветом.
   Убавлено и то и другое: кегль 14 → 12, плашка 36 x 28 → 32 x 24.
   ЛЕСТНИЦА ВНУТРИ ГЕЙМА: заголовок гейма 14 Bold · цифра счёта 12 ·
   имя игрока 11 · итог гейма 11 · ячейка «гейм» 11.
   Имя поехало следом, с 12 на 11: пара «цифра + имя» читается как пара и
   обязана ехать одной границей, иначе они встанут на одну ступень и
   строка перестанет говорить, что в ней главное. */
/* Ячейка, которой закрыт гейм. Слово, а не нули: база пишет выигравшее
   очко уже со сброшенным счётом — см. комментарий в js. */
/* ЯЧЕЙКА «ГЕЙМ» ТОЙ ЖЕ ШИРИНЫ, ЧТО И ОСТАЛЬНЫЕ. Решение Кости 25.09:
   «лаймовые уменьшить, может такого же размера, что и остальные — они и
   так лаймовые, и будет понятно». Он прав: лайм здесь и есть признак,
   лишняя ширина ничего не добавляла, а ряд из-за неё сбивался с шага.
   ПОМЕРЕНО в браузере, прежде чем править файл: «гейм» на 11 с трекингом
   0.06em требует 34 и раздвигает ячейку обратно; с обычным трекингом —
   ровно 32. Поэтому убран трекинг, а НЕ кегль: 11 — нижняя ступень шкалы,
   мельче счёт уже не прочитать. Слово четырёхбуквенное на всех трёх
   языках (гейм · гейм · game), ширина у всех одна. */
/* Метка судьи — эйс или двойная. Необязательна: её отсутствие ничего не
   утверждает. Стоит над ячейкой того, кто очко взял. */


/* ── ПУСТО ────────────────────────────────────────────────
   Empty state 37:53: «Always say what will appear here and how,
   never just no data». Единственное место, где надпись уместна:
   матч не начался, показывать нечего ни слева, ни справа. */

.lm-loading, .lm-error {
    text-align: center;
    padding: var(--space-12) var(--space-4);
    color: var(--text-muted);
    font-size: var(--fs-md);
}
.lm-error { color: var(--danger); }

/* ── СПОНСОРЫ ЛИГИ ────────────────────────────────────────
   Карусель, решение Кости 24.09: «лучше каруселью, чем просто». Дорожка
   и её движение живут в общем style.css — здесь только рамка страницы и
   заголовок, чтобы не заводить вторую карусель.
   Это ВТОРОЕ спонсорское место на странице, и это осознанно: под табло
   стоит спонсор ЭТОГО матча, внизу — спонсоры лиги. Разные вещи с
   разными подписями. */
/* БЛОК СПОНСОРОВ ЛИГИ ЖИВЁТ В ПРАВОЙ КОЛОНКЕ, а не полосой внизу
   страницы. Поэтому у него больше нет ни поля от края экрана (--pad-x
   задаёт страница, а блок теперь внутри колонки), ни отбивки сверху
   (её держит gap правой колонки).
   Стал коробкой той же семьи, что табло: Card 29:65, bg/card, радиус 16,
   рамка 8 % белого — иначе логотипы висели бы в воздухе рядом с панелью.
   Дорожка карусели сузилась с 1224 до 400 и от этого идёт быстрее на
   глаз: слайд 200 плюс поля 24 — в окно попадает полтора логотипа. */
.lm-sponsors {
    padding: var(--space-4) 0 0;
    background: var(--bg-card);
    border: var(--bw-hair) solid var(--border-subtle);
    border-radius: var(--radius-lg);
    overflow: hidden;
}
/* КОРОБКА СПОНСОРОВ НИЖЕ ТАБЛО, А НЕ ВРОВЕНЬ С НИМ. Решение Кости 25.09:
   «давай сделаем размер спонсоров меньше, а не равно».
   Он прав по существу: две коробки одной высоты рядом читаются как две
   равные вещи, а счёт и реклама не равны. Табло 277 — спонсоры ниже.
   Ужимаются ВСЕ слагаемые высоты, а не одно: поля коробки 40 → 16,
   плитка логотипа 100 → 64, слайд 200 → 132, поля слайда 24 → 12.
   Правила ограничены .lm-right: карусель на первом экране лендинга и в
   других местах не трогается, там свои размеры и своё решение. */
.lm-right .sponsors-carousel-infinite {
    padding: var(--space-4) 0;
    margin-bottom: 0;
}
.lm-right .carousel-slide-infinite {
    width: 132px;
    margin: 0 var(--space-3);
    gap: var(--space-2);
}
.lm-right .carousel-slide-infinite img {
    height: 64px;
    padding: 8px;
}

/* ── ПОЛОСА СПОНСОРОВ ПОД ВИДЕО ───────────────────────────
   Та же карусель, но вдвое ниже: 120 вместо 200. Решение Кости 25.09,
   вариант Б2 — именно эти 80 пикселей и уходят видео, из-за чего кадр
   вырастает с 485 до 656 по ширине.
   Подписи логотипов убраны: на полосе 120 они съедали бы треть высоты, а
   имя спонсора уже стоит в атрибуте alt картинки — диктор его прочитает.
   Это НЕ потеря доступности, а перенос подписи с экрана в разметку. */
.lm-sponsors.is-strip {
    padding: var(--space-3) 0 0;
}
.lm-sponsors.is-strip .lm-sponsors-title {
    font-size: var(--fs-2xs);
    letter-spacing: 2px;
    margin: 0 0 var(--space-2);
}
.lm-sponsors.is-strip .sponsors-carousel-infinite {
    padding: var(--space-2) 0;
    margin-bottom: 0;
}
.lm-sponsors.is-strip .carousel-slide-infinite {
    width: 120px;
    margin: 0 var(--space-3);
    gap: 0;
}
.lm-sponsors.is-strip .carousel-slide-infinite img {
    height: 56px;
    padding: 6px;
}
/* Подпись под логотипом — только на полосе. В обычном блоке она есть. */
.lm-sponsors.is-strip .carousel-slide-infinite > :not(img) { display: none; }
/* ВИД ПОДПИСИ ЖИВЁТ В style.css, вместе с подписью на первом экране
   лендинга — одно определение на одно понятие. Здесь только отбивка,
   которая принадлежит этому блоку, а не подписи вообще.
   Было: свой тихий серый на --text-muted, свой кегль и своё межбуквенное.
   Три свойства из четырёх расходились с лендингом, и никто этого не
   видел, потому что блоки стоят на разных страницах. */
.lm-sponsors-title {
    margin: 0 0 var(--space-4);
}

.lm-left, .lm-right { height: 100%; }

/* ТАБЛО НЕ СЖИМАЕТСЯ НИКОГДА. Без этого flex сжал панель с 277 до 101. */
.lm-right .lm-score-panel { flex: 0 0 auto; }
.lm-right.has-feed .lm-feed { flex: 1 1 auto; min-height: 0; }
.lm-left:not(.has-video) .lm-feed { flex: 1 1 auto; min-height: 0; }

/* Кадр держит 16:9 и уступает по ВЫСОТЕ, когда экран низкий. Было только
   выше 992 — из-за чего на узких видах кадр вообще не знал своей высоты. */
.lm-left.has-video .lm-video {
    flex: 1 1 0;
    min-height: 0;
    aspect-ratio: 16 / 9;
    align-self: center;
    width: auto;
    max-width: 100%;
}
.lm-left.has-video .lm-video .lm-video-wrapper { padding-bottom: 0; height: 100%; }


/* БЕЙДЖ LIVE ПРЯЧЕТСЯ ТОЛЬКО ПРИ ИДУЩЕЙ ТРАНСЛЯЦИИ: кадр и есть live, а
   его 51 нужен журналу. Сначала я убрал бейдж на всех узких видах ради
   высоты — и забрал у паузы и у завершённого матча единственное место,
   где они себя называют. Поймано Playwright, не глазами. */
.lm-video-idet .lm-live-badge-wrap { display: none; }

/* ── ВЫШЕ 992 ─────────────────────────────────────────────
   Медиазапросы держатся все вместе в конце файла: БАЗА в прувере — это
   всё до первого @media, и блок, вставленный в середину, обрезал её на
   трети файла. Пять правил заморозки разом перестали видеть собственный
   код. Поймано прувером 25.09. */
@media (min-width: 993px) {
    /* КАДР ВО ВСЮ ШИРИНУ СВОЕЙ КОЛОНКИ — вровень с полосой спонсоров под
       ним. Решение Кости 25.09: «тут надо будет экран по ширине спонсоров
       сделать». 16:9 на 800 — это 450, и вместе с полосой 111 и зазором
       выходит 585 при 513. Недостающее берётся у шапки страницы: при
       идущей трансляции мета уходит (турнир и формат стоят на табло), а
       верхняя отбивка ужимается с 40 до 16. ПОСЧИТАНО, проверено:
       кадр 800 x 450, полоса 800, низ колонок сошёлся. */
    .lm-video-idet .lm-left.has-video .lm-video {
        width: 100%;
        max-width: 100%;
        height: auto;
        flex: 0 0 auto;
        align-self: stretch;
        aspect-ratio: 16 / 9;
    }
    .lm-video-idet .lm-left.has-video .lm-video .lm-video-wrapper {
        padding-bottom: 56.25%;
        height: 0;
    }
    /* Полоса прижата к низу своей колонки — то же правило, что у блока
       спонсоров в правой колонке. Иначе на 1024 x 768 под полосой
       оставалось 60 пустоты и колонки кончались на разной высоте. */
    .lm-video-idet .lm-left.has-video .lm-sponsors { margin-top: auto; }
    .lm-video-idet .lm-meta { display: none; }
    .lm-video-idet .lm-container { padding-top: var(--space-4); }
    /* Подписи под табло при трансляции нет: её высоту забирает журнал, а
       кто подаёт — видно по мячику. Журнал вырос с 213 до 379. */
    .lm-video-idet .lm-info { display: none; }
}

/* ── ПЛАНШЕТ СТОЯ ─────────────────────────────────────────
   Две границы на весь продукт: 640 и 992. Остальное делится высотой и
   поворотом. Одна колонка держалась до 992 — и 400 пикселей ширины
   выбрасывались зря; у планшета стоя колонок теперь две. */
@media (min-width: 641px) and (max-width: 992px) and (orientation: portrait) {
    .lm-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-6); }
    /* display: contents распускает колонки: детьми сетки становятся сами
       карточки, и порядок задаётся клетками, а не разметкой. */
    .lm-left, .lm-right { display: contents; }
    .lm-right .lm-sponsors { margin-top: 0; }

    /* БЕЗ ТРАНСЛЯЦИИ. Решение Кости 25.09: «увеличить окно журнала по
       ширине и оставить воздух по бокам, а две карточки — счёт и
       спонсоры — спустить вниз в один ряд с одинаковой высотой».
       Ряд auto равняет обе карточки по высокой из них; журнал забирает
       остаток и прокручивается внутри. Сведения — третьим рядом. */
    body:not(.lm-video-idet) .lm-grid { grid-template-rows: minmax(0, 1fr) auto auto; }
    body:not(.lm-video-idet) .lm-feed { grid-column: 1 / -1; grid-row: 1; }
    body:not(.lm-video-idet) .lm-score-panel { grid-column: 1; grid-row: 2; }
    body:not(.lm-video-idet) .lm-sponsors { grid-column: 2; grid-row: 2; }
    body:not(.lm-video-idet) .lm-info { grid-column: 1; grid-row: 3; align-self: start; }

    /* С ТРАНСЛЯЦИЕЙ. Кадр во всю ширину обеих карточек — просьба Кости.
       16:9 на 734 съедает 413 из 737. Чтобы в остаток влезли и журнал, и
       полоса спонсоров, у журнала уходит обвязка, и он показывает идущий
       гейм целиком: 413 + 148 + 111 + 48 = 716 при 737. ПОСЧИТАНО. */
    .lm-video-idet .lm-grid {
        position: relative;
        grid-template-rows: auto auto auto;
        align-content: start;
    }
    .lm-video-idet .lm-video { grid-column: 1 / -1; grid-row: 1; }
    .lm-video-idet .lm-left.has-video .lm-video {
        width: 100%;
        max-width: 100%;
        height: auto;
        aspect-ratio: 16 / 9;
        justify-self: stretch;
        align-self: start;
    }
    .lm-video-idet .lm-left.has-video .lm-video .lm-video-wrapper { padding-bottom: 0; height: 100%; }
    /* Табло НЕ растягивается на весь ряд: карточка кончается полосой под
       вторым игроком. Решение Кости 25.09. */
    .lm-video-idet .lm-score-panel {
        grid-column: 1;
        grid-row: 2;
        align-self: start;
        min-height: var(--lm-feed-min-video);
    }
    .lm-video-idet .lm-info { display: none; }
    /* Обвязка журнала уступает место списку: при полноширинном кадре
       подпись 17 и чипы сетов 36 съедали бы гейм целиком — списку
       оставалось 34 из 152. Померено. */
    .lm-video-idet .lm-feed-title,
    .lm-video-idet .lm-feed-chips { display: none; }
    /* Журнал ложится в ту же клетку АБСОЛЮТНО: иначе он задаёт высоту
       ряда своим содержимым и съедает кадр. Обе границы клетки заданы
       явно — при auto-конце containing block тянется до конца сетки, и
       журнал накрывал полосу спонсоров. Померено. */
    .lm-video-idet .lm-feed {
        position: absolute;
        grid-column: 2 / 3;
        grid-row: 2 / 3;
        inset: 0;
        min-height: 0;
    }
    .lm-video-idet .lm-sponsors { grid-column: 1 / -1; grid-row: 3; }
}

/* ── ТЕЛЕФОН СТОЯ ─────────────────────────────────────────*/
@media (max-width: 640px) {
    .lm-grid { display: flex; flex-direction: column; gap: var(--space-4); }
    .lm-left, .lm-right { display: contents; }

    /* ПОРЯДОК КОСТИ: журнал, счёт, спонсоры. Кадр, когда он есть, идёт
       первым. В разметке журнал и табло лежат в разных колонках, и на
       узком порядок задаётся order, а не переносом узлов. */
    .lm-video { order: 1; }
    .lm-left.has-video .lm-video {
        flex: 0 0 auto;
        width: 100%;
        max-width: 100%;
        align-self: stretch;
        aspect-ratio: auto;
    }
    .lm-left.has-video .lm-video .lm-video-wrapper { padding-bottom: 56.25%; height: 0; }
    .lm-feed { order: 2; flex: 1 1 auto; min-height: var(--lm-game-h); display: flex; flex-direction: column; }
    .lm-score-panel { order: 3; flex: 0 0 auto; }
    .lm-info { order: 4; flex: 0 0 auto; }
    .lm-sponsors { order: 5; flex: 0 0 auto; margin-top: 0; padding-top: var(--space-3); }

    /* КОМПАКТ. Бейдж LIVE уезжает: слово «идёт» и так стоит в журнале, а
       его 51 пиксель — это половина гейма. Заголовок ступенью ниже: на 26
       он вставал в две строки. */
    .lm-container { padding-top: var(--space-3); padding-bottom: var(--space-4); }
    .lm-title { font-size: var(--fs-lg); margin-bottom: var(--space-1); }
    .lm-meta { margin-bottom: var(--space-3); }
    .lm-info { flex-direction: row; flex-wrap: wrap; gap: var(--space-2) var(--space-4); padding: var(--space-2) var(--space-4); }
    .lm-info-row { gap: var(--space-2); }

    /* С ТРАНСЛЯЦИЕЙ: место уступают сведения и обвязка журнала, список
       получает идущий гейм целиком — 136 вместо 47. */
    .lm-video-idet .lm-info { display: none; }
    .lm-video-idet .lm-feed-title,
    .lm-video-idet .lm-feed-chips { display: none; }
    .lm-video-idet .lm-feed { min-height: var(--lm-feed-min-video); }

    /* УЗКИЕ СТУПЕНИ ЖУРНАЛА уехали 02.11 в `css/tokens.css` вместе с
       самим журналом: его показывают оба продукта. Здесь остался
       `order` у `.lm-feed` — порядок колонок СТРАНИЦЫ, выше. */

    .lm-player-row { grid-template-columns: 32px 1fr auto; gap: var(--space-2); padding: var(--space-3); }
    .lm-avatar, .lm-avatar-placeholder { width: 32px; height: 32px; }
    .lm-avatar-placeholder { font-size: var(--fs-xs); }
    .lm-player-name { font-size: var(--fs-base); }
    .lm-set-score { font-size: var(--fs-lg); min-width: 20px; }
    .lm-points-score { font-size: var(--fs-lg); min-width: 32px; }

    /* Спонсоры полосой. Значения совпадают с .lm-sponsors.is-strip
       НАМЕРЕННО: это один и тот же вид блока, и за их расхождением следит
       правило-сторож в tools/check-live-stranica.js. */
    .lm-sponsors .lm-sponsors-title { font-size: var(--fs-2xs); letter-spacing: 2px; margin: 0 0 var(--space-2); }
    .lm-sponsors .sponsors-carousel-infinite { padding: var(--space-2) 0; margin-bottom: 0; }
    .lm-sponsors .carousel-slide-infinite { width: 120px; margin: 0 var(--space-3); gap: 0; }
    .lm-sponsors .carousel-slide-infinite img { height: 56px; padding: 6px; }
    .lm-sponsors .carousel-slide-infinite > :not(img) { display: none; }
}

/* ── ТЕЛЕФОН БОКОМ ────────────────────────────────────────
   Ширина здесь 844 — по ширине это «широкий» вид, и лестница осталась бы
   крупной при высоте экрана 390. Делится высотой и поворотом.
   ПОЛНОЭКРАННЫЙ РЕЖИМ. Решение Кости 25.09: «в горизонтальном наверно
   сразу чтобы открывался полноразмерный экран — как у всех: перевернул,
   окно видео на весь экран». Раз режим полноэкранный — уходит и шапка, и
   подвал: иначе страница остаётся прокручиваемой и за кадром во весь
   рост стоит подвал. Костя это и увидел. */
@media (orientation: landscape) and (max-height: 500px) {
    header.floating-header { display: none; }
    body > footer, .site-footer { display: none; }
    main { padding-top: 0; }
    .lm-container { height: 100dvh; padding-top: var(--space-2); padding-bottom: var(--space-2); }
    /* Цель нажатия остаётся 44 и в полноэкранном режиме: я было
       опустил её до 36 ради высоты — поймал тест. WCAG 2.5.5 не
       отменяется поворотом телефона. */
    .lm-back-link { min-height: var(--btn-h-md); position: absolute; opacity: .9; }
    /* Заголовок отбивается от ссылки «назад» ступенью шкалы, а не
       подогнанным числом: ссылка 102 широкая, 128 даёт 26 зазора. */
    .lm-title { font-size: var(--fs-lg); margin: 0 0 var(--space-2) var(--space-32); }
    .lm-meta { display: none; }
    .lm-info { display: none; }

    /* Журнал шире, счёт и спонсоры уже — просьба Кости 25.09. Пропорция
       не выдумана: это та же 2 : 1, что у сетки везде. */
    .lm-grid { gap: var(--space-4); grid-template-columns: 2fr 1fr; }
    .lm-left { height: 100%; }
    .lm-right { height: 100%; justify-content: flex-start; }
    /* Обе правые карточки делят колонку 2 : 1 и вместе держат уровень
       журнала. Спонсоры строго ниже счёта — решение Кости; заморожено
       ОТНОШЕНИЕ, а не числа. */
    .lm-right .lm-score-panel { flex: 2 1 0; display: flex; flex-direction: column; justify-content: center; }
    .lm-right .lm-players { flex: 1 1 auto; display: flex; flex-direction: column; justify-content: center; }
    .lm-right .lm-player-row { flex: 1 1 0; }
    .lm-right .lm-sponsors { flex: 1 1 0; margin-top: 0; display: flex; flex-direction: column; justify-content: center; }

    .lm-sponsors .lm-sponsors-title { font-size: var(--fs-2xs); letter-spacing: 2px; margin: 0 0 var(--space-1); }
    .lm-sponsors .sponsors-carousel-infinite { padding: 0; margin: 0; }
    .lm-sponsors .carousel-slide-infinite { width: 120px; margin: 0 var(--space-3); gap: 0; }
    .lm-sponsors .carousel-slide-infinite img { height: 40px; padding: var(--space-1); }
    .lm-sponsors .carousel-slide-infinite > :not(img) { display: none; }

    /* ЕСТЬ ТРАНСЛЯЦИЯ — КАДР НА ВЕСЬ ЭКРАН, И БОЛЬШЕ НИЧЕГО. Карусель
       спонсоров здесь убрана по прямой просьбе Кости: «там вообще надо
       будет убрать спонсора карусель, оставить только видео».
       Пустая правая колонка ПРЯЧЕТСЯ ЦЕЛИКОМ: дети скрыты, а сама
       колонка держала height 100% и давала странице второй экран
       пустоты — документ был 780 при экране 390. Померено. */
    .lm-video-idet .lm-title,
    .lm-video-idet .lm-score-panel,
    .lm-video-idet .lm-feed,
    .lm-video-idet .lm-right,
    .lm-video-idet .lm-sponsors { display: none; }
    .lm-video-idet .lm-container { padding: 0; height: 100dvh; }
    .lm-video-idet .lm-grid { display: block; gap: 0; }
    .lm-video-idet .lm-left.has-video .lm-video {
        position: fixed;
        inset: 0;
        width: 100%;
        height: 100%;
        max-width: none;
        aspect-ratio: auto;
        border-radius: 0;
        z-index: 1;
    }
    .lm-video-idet .lm-left.has-video .lm-video .lm-video-wrapper { padding-bottom: 0; height: 100%; }
    .lm-video-idet .lm-back-link { position: fixed; top: var(--space-3); left: var(--space-3); z-index: 3; }
}


