/* ============================================================================
   «Чемпионат России по футболу» — ОБЩИЙ СЛОЙ: структура, размеры, сетки.
   Здесь нет ни цветов, ни гарнитур, ни формы углов: это кожа направлений,
   она живёт в league-style-proto.css («Газета») и league-style-board.css
   («Табло»), которые Directions JS подключает ПО ОДНОМУ. Поэтому в этом файле
   любое визуальное решение выражено переменной (--card-bg, --font-num, --r-pill),
   а направление только задаёт её значение. Порядок подключений: theme → стиль.
   Механику выбора и сохранение см. в public/league-appearance.js (STYLE_*).
   ============================================================================ */

/* ---------- инсеты VK Mini App ----------
   --vk-inset-* выставляет public/league.js из insets события VKWebAppUpdateConfig
   (и стартового VKWebAppGetConfig), --vk-banner-h — из высоты нижнего баннера.
   В обычном браузере все они нулевые, остаётся только safe-area-inset. */
:root {
  --vk-inset-top: 0px;
  --vk-inset-right: 0px;
  --vk-inset-bottom: 0px;
  --vk-inset-left: 0px;
  --vk-banner-h: 0px;
  --safe-top: max(env(safe-area-inset-top, 0px), var(--vk-inset-top));
  --safe-bottom: max(env(safe-area-inset-bottom, 0px), var(--vk-inset-bottom), var(--vk-banner-h));
  --vk-side: max(env(safe-area-inset-left, 0px), var(--vk-inset-left));
  --vk-side-r: max(env(safe-area-inset-right, 0px), var(--vk-inset-right));
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; padding: 0; }
body {
  min-height: 100vh;
  background: var(--page-bg);
  color: var(--text);
  font-family: var(--font-text);
  font-weight: var(--w-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
button, select { font: inherit; color: inherit; }
a, button, select { touch-action: manipulation; }
/* нативное ощущение: без резины и полос прокрутки */
html { scrollbar-width: none; }
html::-webkit-scrollbar, body::-webkit-scrollbar { width: 0; height: 0; }
body { overscroll-behavior-y: none; }
/* [hidden] должен прятать элемент и когда у класса свой display: UA-правило
   [hidden] { display: none } проигрывает классу по специфичности, поэтому чип
   «обновлено только что» оставался видимым на не-live матчах (его выключают
   именно атрибутом hidden). */
[hidden] { display: none; }
.chip[hidden], .hello[hidden], .hint[hidden], .sheet-wrap[hidden] { display: none; }

/* ---------- каркас ---------- */
/* Отступы под инсеты VK и safe-area применяем один раз — к .page (контейнер
   скролла): .topbar стоит первым внутри .page, поэтому отдельный padding-top
   шапке не добавляем — иначе отступ под статус-бар удваивается. */
.page {
  width: min(100%, 720px); margin: 0 auto;
  padding: calc(14px + var(--safe-top)) calc(14px + var(--vk-side-r)) calc(28px + var(--safe-bottom)) calc(14px + var(--vk-side));
}
/* Жидкое стекло: шапка прилипает к самому верху экрана (top: 0), а отступ под
   статус-бар VK и поле страницы забирает на себя собственным padding-ом —
   раньше между шапкой и верхом оставалась полоса, сквозь которую при
   прокрутке просвечивал контент. Полупрозрачный фон + сильный blur/saturate
   дают «стекло»: текст читается поверх размытого списка. */
.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  margin: calc(-14px - var(--safe-top)) calc(-14px - var(--vk-side-r)) 14px calc(-14px - var(--vk-side));
  padding: calc(16px + var(--safe-top)) calc(14px + var(--vk-side-r)) 10px calc(14px + var(--vk-side));
  background: var(--bg-blur);
  -webkit-backdrop-filter: blur(26px) saturate(1.8) brightness(1.05);
  backdrop-filter: blur(26px) saturate(1.8) brightness(1.05);
  box-shadow: inset 0 1px 0 var(--glass-hi), 0 1px 0 var(--line-2), 0 10px 24px -18px var(--bar-ambient);
}
/* «стекло» держит читаемость только с backdrop-filter; там, где его нет
   (старые WebView), шапка становится обычной глухой полосой */
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .topbar { background: var(--bg); }
}
.topbar .back {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: var(--r-btn); border: var(--btn-border);
  background: var(--btn-bg); display: grid; place-items: center; cursor: pointer; color: var(--text);
  box-shadow: var(--btn-shadow);
}
.topbar .back svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.topbar .title { flex: 1 1 auto; min-width: 0; }
.topbar .title b { display: block; font-family: var(--font-display); font-weight: var(--w-strong); font-size: 17px; letter-spacing: var(--ls-title); text-transform: var(--tt-title); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar .title i { display: block; font-style: normal; color: var(--muted); font-size: 12px; margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar .theme { flex: 0 0 auto; width: 40px; height: 40px; border-radius: var(--r-btn); border: var(--btn-border); background: var(--btn-bg); display: grid; place-items: center; cursor: pointer; box-shadow: var(--btn-shadow); }
.topbar .theme svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; }

.hero { text-align: var(--hero-align, center); padding: 26px 8px 20px; }
.hero .kicker { display: inline-flex; padding: 6px 13px; border-radius: var(--r-pill); border: var(--tag-border); background: var(--tag-bg); color: var(--tag-fg); font-family: var(--font-cap); font-size: 11px; font-weight: var(--w-cap); letter-spacing: .16em; text-transform: uppercase; }
.hero h1 { margin: 8px 0 6px; font-family: var(--font-display); font-weight: var(--w-display); font-size: var(--fs-hero); line-height: 1.08; letter-spacing: var(--ls-hero); text-transform: var(--tt-hero); }
.hero .sub { color: var(--muted); font-size: 13px; }

.card {
  background: var(--card-bg);
  border: var(--card-border);
  border-radius: var(--r-lg);
  box-shadow: var(--card-shadow); overflow: hidden; margin-bottom: 14px;
}
.card-head {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 14px 18px; border-bottom: var(--card-head-line); font-size: 13px; color: var(--muted);
}
.card-head b { color: var(--text); font-family: var(--font-display); font-weight: var(--w-strong); font-size: 15px; letter-spacing: var(--ls-head); text-transform: var(--tt-head); }
.head-btns { display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.chip { display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px; border-radius: var(--r-pill); border: var(--tag-border); background: var(--tag-bg); color: var(--tag-fg); font-family: var(--font-cap); font-size: 11.5px; font-weight: var(--w-cap); letter-spacing: .04em; }
.chip.live { background: var(--chip-live-bg); color: var(--live); }
.chip.live::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--live); animation: pulse 1.2s infinite; }
@keyframes pulse { 50% { opacity: .3; } }
/* Живой пульс live-матча: точка «дышит» в такт минутному тику данных —
   сразу после обновления она вспыхивает и за минуту плавно разгорается,
   поэтому по ней видно и свежесть, и ритм обновлений. */
.chip.live.tick::before { animation: rpl-tick 60s linear 1 forwards; }
@keyframes rpl-tick {
  0% { transform: scale(2.2); opacity: .3; }
  8% { transform: scale(1); opacity: .45; }
  100% { transform: scale(1); opacity: 1; }
}

.controls { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.controls select, .controls .btn {
  flex: 1 1 140px; min-width: 0; height: 44px; padding: 0 14px; border-radius: var(--r-btn);
  border: var(--ctl-border); background: var(--ctl-bg); color: var(--text); font-weight: var(--w-strong);
  box-shadow: var(--ctl-shadow);
}
/* Полотно выпадающего списка рисует система, а текст опций по умолчанию
   наследует цвет контрола. Без своей пары «фон + текст» получался белый
   список с приглушённой подписью (в «Газете» на тёмной теме). */
select option { background: var(--card); color: var(--text); }
.controls .btn { flex: 0 0 auto; cursor: pointer; }
.controls .btn:disabled { opacity: .4; cursor: default; }
/* галочка «только мой клуб»: та же высота и рамка, что у списка туров */
.controls .tgl { display: inline-flex; align-items: center; gap: 8px; flex: 1 1 140px; min-width: 0; height: 44px; padding: 0 14px; border-radius: var(--r-btn); border: var(--ctl-border); background: var(--ctl-bg); box-shadow: var(--ctl-shadow); color: var(--text); font-weight: var(--w-strong); cursor: pointer; }
.controls .tgl input { flex: none; width: 18px; height: 18px; margin: 0; accent-color: var(--accent); }
.controls .tgl span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.empty { padding: 28px 16px; text-align: center; color: var(--muted); font-size: 13.5px; }
/* Плашка «Данные: …» — в конце контента, а не поверх экрана: fixed-бейдж
   ездил по экрану и наезжал на карточки и на нижнюю панель. Её создаёт
   League.status() и кладёт в конец .page (см. public/league.js). */
.status { display: block; width: fit-content; max-width: 100%; margin: calc(6px * var(--ui-scale)) auto 0;
  padding: 5px 12px; border-radius: var(--r-pill); border: var(--status-border); background: var(--status-bg);
  color: var(--muted); font-size: 11px; text-align: center; }
.status.err { color: var(--loss); background: var(--status-err-bg); }

/* ---------- знак клуба ----------
   Разметка одна и та же (.crest с двумя переменными цвета), начертание —
   у направления: --crest-bg / --crest-r / --crest-gloss / --crest-shadow. */
.crest {
  flex: 0 0 auto; display: inline-block; width: 26px; height: 18px; position: relative; overflow: hidden;
  background: var(--crest-bg); border-radius: var(--crest-r); box-shadow: var(--crest-shadow);
  vertical-align: middle;
}
.crest::after { content: ''; position: absolute; inset: 0; background: var(--crest-gloss); }
.crest.lg { width: 44px; height: 30px; }
.crest.xl { width: 66px; height: 44px; }
.crest.sm { width: 20px; height: 14px; }
/* Эмблема клуба вместо косого среза цветов: файл лежит в /ClubICO, разрешение
   есть только у части клубов. Градиент плашки гасим — иначе под прозрачным
   щитом проступит косой клин --c1/--c2. object-fit: contain — щит упирается в
   высоту слота и не растягивается в прямоугольник. */
.club-ico { background: none; box-shadow: none; object-fit: contain; }
/* Щиты у клубов разные по пропорциям (Балтика — 0.94, Крылья Советов — 0.63),
   а contain упирается в высоту слота: узкий щит выходит заметно уже цветной
   плашки соседа (58x40) и читается мельче, хотя по высоте даже больше. Поэтому
   высоту слота поднимаем по соотношению сторон — но не больше чем в 1.2 раза,
   иначе щит выпирает из шапки. Пропорцию отдаёт League.crest() (--ico-ar). */
.crest.club-ico { width: auto; --ico-grow: clamp(1, calc(0.85 / var(--ico-ar, 1)), 1.25);
  height: calc(28px * var(--ui-scale, 1) * var(--ico-grow)); }
.crest.club-ico.sm { height: calc(20px * var(--ui-scale, 1) * var(--ico-grow)); }
/* В шапке матча (составы, анонс, ближайший матч) знак стоит отдельной строкой
   над названием — там сравнение «эмблема против среза» видно всего отчётливее,
   поэтому высота больше, чем у самой плашки у этого направления. */
:root .feature .club .crest.club-ico.xl { width: auto; height: calc(58px * var(--ui-scale, 1) * var(--ico-grow)); }

.team { display: inline-flex; align-items: center; gap: 9px; min-width: 0; }
.team .tn { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--w-strong); font-family: var(--font-name); letter-spacing: var(--ls-name); text-transform: var(--tt-name); }
.team .tc { display: block; color: var(--muted); font-size: 11px; font-weight: var(--w-body); }

/* ---------- навигация (index) ---------- */
.tiles { display: grid; gap: 14px; margin-bottom: 14px; }
.tile {
  display: grid; grid-template-columns: 56px 1fr 22px; align-items: center; gap: 16px;
  padding: 18px; border-radius: var(--r-lg); background: var(--tile-bg);
  border: var(--tile-border); box-shadow: var(--tile-shadow);
}
.tile:hover { background: var(--tile-bg-hover); }
.tile .ticon { width: 56px; height: 56px; border-radius: var(--r-ic); background: var(--tile-ic-bg); border: var(--tile-ic-border); display: grid; place-items: center; }
.tile .ticon svg { width: 27px; height: 27px; stroke: var(--tile-ic-stroke); fill: none; stroke-width: var(--ic-weight); stroke-linecap: round; stroke-linejoin: round; }
.tile b { display: block; font-family: var(--font-display); font-weight: var(--w-strong); font-size: 17px; letter-spacing: var(--ls-tile); text-transform: var(--tt-tile); }
.tile i { display: block; font-style: normal; color: var(--muted); font-size: 13px; margin-top: 3px; }
.tile .arr { color: var(--faint); font-size: 26px; line-height: 1; text-align: right; }
.legal { margin-top: 20px; color: var(--faint); font-size: 11px; text-align: center; line-height: 1.5; }

/* ---------- инструкция «мой клуб» (низ таблицы) ---------- */
.hint {
  background: var(--note-bg); border: var(--note-border);
  border-radius: var(--r-md); box-shadow: var(--note-shadow);
  padding: 14px 16px; margin-bottom: 14px;
  color: var(--muted); font-size: 12.5px; line-height: 1.55;
}
.hint b { display: block; color: var(--text); font-size: 13px; font-weight: var(--w-strong); margin-bottom: 5px; }
.hint i { font-style: normal; color: var(--accent); font-weight: var(--w-strong); }

/* ---------- нативные press-состояния ---------- */
.tile, .controls .btn, .theme-toggle, .topbar .back, .topbar .theme, a.feature {
  transition: transform .14s ease, background-color .2s ease, color .2s ease, border-color .2s ease, box-shadow .2s ease;
}
.tile:active, .controls .btn:active, .theme-toggle:active, .topbar .back:active, .topbar .theme:active, a.feature:active { transform: scale(.97); }
.tile, .topbar .back, .topbar .theme, .theme-toggle { user-select: none; -webkit-user-select: none; }
a.match:active { background: var(--line-2); }

/* ---------- смена темы на главной ----------
   Кнопка живёт в ряду .ui-tools (первая, слева от «Инструкции»), поэтому раму,
   фон и поля она берёт у .ui-tools button — здесь только выравнивание значка с
   подписью. Вправо ряд сдвинут от кнопок VK «…» и «×» (см. html.vkapp .hero
   .ui-tools). Ряд НЕ переносится: три кнопки обязаны влезать в одну строку на
   телефоне. Считано по метрикам гарнитур обоих направлений («ИНСТРУКЦИЯ» в
   Oswald/Golos при 12,5px с разрядкой 0,6 от --ls-btn — 102–123px, «ТЕМА» с
   значком — 74–84px, квадрат настроек 38px, два зазора по 5px: итого
   217–249px), а на 360px экране с учётом отступа от кнопок VK ряду остаётся
   250px. Запас тонкий, поэтому до 480px подпись «Тема» убирается (в шапках
   разделов переключатель и так только со значком), а ряд умеет сжиматься. */
.theme-toggle { display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-width: 0; }
.theme-toggle svg { width: 16px; height: 16px; flex: 0 0 auto; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; }
/* подпись — гибкий элемент: без min-width она бы расталкивала весь ряд */
.theme-toggle span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* ---------- таблица ---------- */
/* Раскладка фиксированная: в авто-раскладке max-width на ячейке не работает,
   и nowrap-название клуба диктовало ширину своей колонки — числовые колонки
   схлопывались до отступов, а их значения и «КОМАНДА» в заголовке залезали
   друг на друга. На экранах шире 420px (iPhone Pro Max, большинство Android
   флагманов) .hide-xs уже не применяется, и это было видно всегда.
   Ширина колонок задаётся в первой строке (thead) — отсюда классы c-*. */
.tbl { width: 100%; table-layout: fixed; border-collapse: collapse; }
.tbl th, .tbl td { padding: 10px 4px; text-align: center; border-bottom: 1px solid var(--line-2); white-space: nowrap; font-variant-numeric: tabular-nums; overflow: hidden; }
.tbl th { font-size: 11px; color: var(--muted); letter-spacing: var(--ls-col); text-transform: uppercase; font-weight: var(--w-cap); font-family: var(--font-cap); }
.tbl tr:last-child td { border-bottom: none; }
.tbl th.c-pos { width: clamp(38px, calc(44px * var(--ui-scale, 1)), 56px); }
.tbl td.pos { width: clamp(38px, calc(44px * var(--ui-scale, 1)), 56px); color: var(--muted); font-weight: var(--w-strong); font-family: var(--font-num); }
.tbl th.c-num { width: clamp(21px, calc(25px * var(--ui-scale, 1)), 33px); }
.tbl td.num { width: clamp(21px, calc(25px * var(--ui-scale, 1)), 33px); padding-left: 2px; padding-right: 2px; }
.tbl th.c-goals { width: clamp(44px, calc(50px * var(--ui-scale, 1)), 66px); }
.tbl td.goals { width: clamp(44px, calc(50px * var(--ui-scale, 1)), 66px); padding-left: 2px; padding-right: 2px; }
.tbl th.c-diff { width: clamp(26px, calc(30px * var(--ui-scale, 1)), 40px); }
.tbl td.diff { width: clamp(26px, calc(30px * var(--ui-scale, 1)), 40px); }
.tbl th.c-form { width: clamp(54px, calc(62px * var(--ui-scale, 1)), 84px); }
.tbl td.form { width: clamp(54px, calc(62px * var(--ui-scale, 1)), 84px); padding-left: 2px; padding-right: 2px; vertical-align: middle; }
.tbl th.c-pts { width: clamp(28px, calc(32px * var(--ui-scale, 1)), 44px); }
.tbl td.pts { width: clamp(28px, calc(32px * var(--ui-scale, 1)), 44px); font-weight: var(--w-strong); font-size: var(--fs-pts); color: var(--pts-fg); font-family: var(--font-num); }
/* Ширина числовых колонок не зависит от содержимого, но растёт вместе с
   масштабом (в ячейке calc(13px * var(--ui-scale))): на 120–150% цифры иначе
   не влезают в колонку. clamp() держит и нижнюю границу (на 5% колонки не
   превращаются в нитку), и верхнюю (на 150% таблица не расползается за
   карточку). */
/* 320–360px с крупным масштабом: на самых узких экранах потолок ширин ниже,
   иначе на 135–150% под колонку названия не оставалось бы места вовсе */
@media (max-width: 360px) {
  .tbl th.c-pos, .tbl td.pos { width: clamp(36px, calc(40px * var(--ui-scale, 1)), 46px); }
  .tbl th.c-num, .tbl td.num { width: clamp(20px, calc(23px * var(--ui-scale, 1)), 30px); }
  .tbl th.c-diff, .tbl td.diff { width: clamp(24px, calc(28px * var(--ui-scale, 1)), 34px); }
  .tbl th.c-pts, .tbl td.pts { width: clamp(26px, calc(30px * var(--ui-scale, 1)), 38px); }
}
/* Крупный масштаб = широкие числовые колонки, и «Команда» рискует остаться ни
   с чем: на корзине «l» убираем «Мячи» (это дубль «±»), на «xl» — ещё и
   «Форму». Атрибут data-ui-scale-bucket ставит league-appearance.js. */
html[data-ui-scale-bucket="l"] .tbl .hide-lg, html[data-ui-scale-bucket="xl"] .tbl .hide-lg,
html[data-ui-scale-bucket="xl"] .tbl .hide-xl { display: none; }
@media (max-width: 560px) { html[data-ui-scale-bucket="l"] .tbl .hide-xl { display: none; } }
.tbl td.team-cell, .tbl th.team-col { text-align: left; padding-left: 10px; }
/* Название клуба переносим в две строки, а не режем многоточием: «Динамо» и
   «Динамо Махачкала» обязаны читаться целиком (тот же приём, что и в .match) */
.tbl td.team-cell { width: auto; min-width: 0; white-space: normal; }
/* плашка и зазор в узкой колонке стоят дороже, чем кажется: 26+9 против 20+6 */
.tbl td.team-cell .team { display: flex; gap: 6px; min-width: 0; }
.tbl td.team-cell .crest { width: 20px; }
/* Эмблема почти квадратная, а щиты у клубов разные: в квадратном слоте узкий
   щит (0.63 у «Крыльев») теряет треть ширины против плашки соседа и читается
   пятном. Поэтому слоту задаём высоту по той же формуле, что и везде, а не
   фиксированный квадрат. Высоту строки держит название в две строки. */
.tbl td.team-cell .club-ico { width: auto; height: calc(24px * var(--ui-scale, 1) * var(--ico-grow)); }
.tbl td.team-cell .tn { white-space: normal; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
  font-size: var(--fs-club); line-height: 1.12; }
.tbl td.diff.pos-d { color: var(--win); } .tbl td.diff.neg-d { color: var(--loss); }
/* сдвиг после последнего тура: ▲/▼ у места. Цифру не дублируем при |Δ|=1 —
   «▲» уже значит «на одну позицию» */
.tbl .mv { display: inline-block; margin-left: 2px; font-size: calc(9px * var(--ui-scale, 1));
  font-style: normal; font-weight: var(--w-strong); line-height: 1; vertical-align: 1px; color: var(--faint); }
.tbl .mv.up { color: var(--win); } .tbl .mv.down { color: var(--loss); }
.tbl tr.zone-top td.pos { box-shadow: inset 3px 0 0 var(--accent); }
.tbl tr.zone-bottom td.pos { box-shadow: inset 3px 0 0 var(--loss); }
.tbl tr.zone-playoff td.pos { box-shadow: inset 3px 0 0 var(--gold); }
.form { display: inline-flex; gap: 3px; vertical-align: middle; }
/* В ячейке таблицы форму центруем сами: inline-flex выравнивается по базовой
   линии своего содержимого (у «Газеты» это буквы), и блок уходил вверх. */
.tbl td.form .form { display: flex; align-items: center; justify-content: center; }
.form i { width: 8px; height: 8px; border-radius: var(--r-form); background: var(--draw); display: inline-block;
  font: var(--fs-form, 0)/1 var(--font-cap); font-style: normal; text-align: center; color: var(--form-fg);
  border: var(--form-border); box-sizing: content-box; }
.form i.W { background: var(--win); } .form i.L { background: var(--loss); }
.legend { display: flex; flex-wrap: wrap; gap: 10px 16px; padding: 12px 18px; color: var(--muted); font-size: 11.5px; border-top: 1px solid var(--line-2); }
.legend i { display: inline-block; width: var(--lg-w); height: var(--lg-h); border-radius: var(--r-lg-mark); margin-right: 5px; vertical-align: -1px; background: currentColor; }
@media (max-width: 420px) {
  .tbl th, .tbl td { padding: 9px 3px; font-size: 13px; }
  .tbl .hide-xs { display: none; }
}
/* 421–560px: «Мячи» — единственное, что можно убрать без потери смысла (это
   дубль «±»), зато колонка названия получает ~50px и не просит переносов */
@media (max-width: 560px) { .tbl .hide-sm { display: none; } }

/* ---------- матчи ---------- */
.day { padding: 10px 18px 6px; color: var(--muted); font-size: 12px; letter-spacing: var(--ls-day); text-transform: uppercase; font-weight: var(--w-cap); font-family: var(--font-cap); border-top: var(--day-rule); }
.match {
  /* minmax(0, 1fr): колонки названий могут сжиматься ниже содержимого —
     иначе длинное название «раздувает» трек и лезет за карточку */
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 8px;
  padding: 13px 14px; border-bottom: 1px solid var(--line-2);
}
.match:last-child { border-bottom: none; }
a.match:hover { background-color: var(--line-2); }
.match .side { display: flex; align-items: center; gap: 8px; min-width: 0; }
.match .side.home { justify-content: flex-end; text-align: right; }
/* национальные названия не режем многоточием: «Динамо-Москва» и «Динамо
   Махачкала» оба стали бы «Динамо…». Переносим на вторую строку и только
   третью и далее обрезаем (line-clamp).
   Целые слова НЕ разрываем: перенос — только между словами (пробел, дефис:
   «Динамо» / «Махачкала», «Спартак-» / «Москва»). Поэтому без break-word и
   без hyphens — «Краснодар» остаётся одним словом */
.match .side .nm { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: normal; overflow-wrap: normal; word-break: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; font-weight: var(--w-strong); font-size: 14px; font-family: var(--font-name); letter-spacing: var(--ls-name); text-transform: var(--tt-name); }
/* min-width — обычный день (счёт/время), max-width — чтобы длинная дата
   («Понедельник, 26 октября») не съела названия клубов. Потолок в vw, а не в %:
   процент от auto-трека на этапе расчёта ширины неопределён и не работает.
   Всё, что шире потолка, переносится ВНУТРИ колонки (см. .meta) — иначе текст
   вытекает за бокс и наезжает на эмблемы по бокам. От --ui-scale горизонталь не
   зависит намеренно: крупный шрифт должен добавлять строк, а не двигать сетку. */
.match .mid { display: grid; justify-items: center; gap: 3px; min-width: 64px; max-width: min(150px, 46vw); }
.match .score { font-family: var(--font-num); font-weight: var(--w-display); font-size: var(--fs-score); letter-spacing: .03em; padding: 3px 12px; border-radius: var(--score-r); background: var(--score-bg); border: var(--score-border); }
.match .score.live { color: var(--live); border-color: var(--live); box-shadow: var(--score-live-glow); }
.match .time { font-family: var(--font-num); font-weight: var(--w-display); font-size: 17px; color: var(--text); }
/* nowrap + узкий бокс = текст лезет поверх соседей (обрезки у .mid нет), поэтому
   дата и статус переносятся по словам, а длинное слово разбивается */
.match .meta { color: var(--muted); font-size: 10.5px; text-align: center; white-space: normal; overflow-wrap: anywhere; }
.match .venue { grid-column: 1 / -1; color: var(--faint); font-size: 11px; text-align: center; margin-top: -4px; }
@media (max-width: 380px) {
  .match .side .nm { font-size: 13px; }
  .match .score { font-size: 17px; }
}
/* на узких экранах дата в 64px переносится в две строки — колонка остаётся
   шириной со счёт/время и названия не режутся (на широких достаточно потолка
   .mid выше, там дата стоит в одну строку) */
@media (max-width: 430px) {
  .match .meta { white-space: normal; max-width: 64px; overflow-wrap: break-word; }
}
/* самые узкие экраны (320px): отыгрываем место у отступов и плашки, чтобы
   названия-слова («Краснодар», «Махачкала», «Локомотив») влезали целиком,
   а не рвались и не резались краем */
@media (max-width: 340px) {
  .match { padding: 12px 8px; gap: 5px; }
  .match .side, .match .side .nmrow { gap: 5px; }
  .match .side .crest { width: 20px; height: 14px; }
}

/* анонс — крупная карточка матча. Фоновое «свечение» цветами клубов
   (--glow-h/--glow-a ставит League.glow) использует только «Табло»;
   «Газета» оставляет их прозрачными и ставит вместо этого линейки. */
.feature {
  --glow-h: transparent;
  --glow-a: transparent;
  --club-h: transparent;
  --club-a: transparent;
  position: relative; overflow: hidden;
  padding: 22px 16px; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px;
  background: var(--feat-bg);
  border-top: var(--feat-rule); border-bottom: var(--feat-rule);
}
/* «разметка поля» — декор направления: прозрачная линия = декора нет */
.feature::before { content: ''; position: absolute; left: 50%; top: 50%; width: 200px; height: 200px; transform: translate(-50%, -50%); border: var(--pitch-ring); border-radius: 50%; pointer-events: none; }
.feature::after { content: ''; position: absolute; left: 50%; top: 0; bottom: 0; width: 1.5px; background: var(--pitch-line); pointer-events: none; }
.feature > * { position: relative; }
/* Чей цвет где: порядок детей фиксированный (клуб, счёт, клуб, стадион), поэтому
   привязка стороны к переменной — структура, а решение «как красить» — у
   направления (--club-h / --club-a отдаёт League.glow, они же наследуются). */
.feature .club:first-of-type { --club: var(--club-h); }
/* гости — третий div блока (клуб, счёт, клуб, [стадион]) */
.feature .club:nth-of-type(3) { --club: var(--club-a); }
.feature .club { display: grid; justify-items: center; gap: 8px; text-align: center; min-width: 0; }
.feature .club b { font-size: var(--fs-club-lg); font-weight: var(--w-strong); line-height: 1.15; font-family: var(--font-display); text-transform: var(--tt-hero); letter-spacing: var(--ls-hero); }
.feature .club i { font-style: normal; color: var(--muted); font-size: 11.5px; }
.feature .vs { display: grid; justify-items: center; gap: 4px; max-width: min(160px, 42vw); }
.feature .vs > * { max-width: 100%; overflow-wrap: anywhere; }
.feature .vs .t { font-family: var(--font-num); font-weight: var(--w-display); font-size: var(--fs-score-lg); letter-spacing: -.02em; }
.feature .vs .d { color: var(--muted); font-size: 12px; white-space: normal; overflow-wrap: anywhere; }
/* Строки сетки заданы ЯВНО. У элемента с одним лишь grid-column
   авторазмещение занимает следующую свободную строку и уводит вниз соседей:
   ссылка клуба захватывала вторую строку, счёт и гости съезжали под неё, а блок
   хозяев оставался в первой строке один — визуально он «улетал вверх». С явной
   строкой элементы с определённой позицией расставляются первыми, а клубы и
   счёт остаются в первой строке. */
.feature .place { grid-row: 2; grid-column: 1 / -1; text-align: center; color: var(--muted); font-size: 12px; }
/* Ссылка клуба читается рядом со своим клубом — сразу под блоками (строка 2),
   а стадион опускается под неё. Класс .has-link разметка ставит только когда
   ссылка есть: без него стадион уехал бы на пустую третью строку и между
   клубами и стадионом появился бы лишний отступ (gap: 10px). */
.feature.has-link .place { grid-row: 3; }
/* Ссылка клуба в шапке матча: стоит под цветной полосой блока (у направления
   «Газета» полоса — это border-bottom самого .club), поэтому лежит вне .club и
   занимает свою колонку сетки, а не растягивается на весь экран, как .place */
.feature .club-link { grid-row: 2; justify-self: center; max-width: 100%; text-align: center;
  font-size: calc(11.5px * var(--ui-scale, 1)); color: var(--accent);
  text-decoration: underline; text-underline-offset: 2px; }
/* Отклик на тап — сразу: сам клиент ВК поднимает браузер секунды, и без
   подтверждения тап читается как «кнопка не работает» */
.feature .club-link:active { opacity: .5; }
.feature .club-link.h { grid-column: 1; }
.feature .club-link.a { grid-column: 3; }

/* ---------- бомбардиры ---------- */
.scorer { display: grid; grid-template-columns: 30px 1fr auto; align-items: center; gap: 10px; padding: 12px 18px; border-bottom: 1px solid var(--line-2); }
.scorer:last-child { border-bottom: none; }
.scorer .rank { color: var(--muted); font-weight: var(--w-strong); text-align: center; font-family: var(--font-num); }
.scorer:nth-child(1) .rank { color: var(--gold); }
.scorer:nth-child(1) { background: var(--lead-bg); }
.scorer .who b { display: block; font-weight: var(--w-strong); font-family: var(--font-name); text-transform: var(--tt-name); letter-spacing: var(--ls-name); }
.scorer .who .team { margin-top: 3px; font-size: 12px; color: var(--muted); }
.scorer .goals { font-family: var(--font-num); font-weight: var(--w-display); font-size: var(--fs-goals); color: var(--goals-fg); min-width: 34px; text-align: right; }

/* ---------- составы ---------- */
.lineups { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 480px) { .lineups { grid-template-columns: 1fr; } }
.squad .sq-head { display: flex; align-items: center; gap: 8px; padding: 12px; border-bottom: 1px solid var(--line-2); }
.squad .sq-head b { font-size: 14px; font-weight: var(--w-strong); font-family: var(--font-name); text-transform: var(--tt-name); }
.squad .sq-head i { font-style: normal; color: var(--muted); font-size: 11.5px; margin-left: auto; }
.squad .grp { padding: 8px 12px 2px; color: var(--faint); font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase; font-weight: var(--w-cap); font-family: var(--font-cap); }
/* Амплуа — «авто»-колонка без contain и без правого поля: длинное
   «Полузащитник» влезало в карточку только ценой обрезки справа. */
.player { display: grid; grid-template-columns: 26px minmax(0, 1fr) auto; gap: 7px; align-items: center; padding: 7px 10px 7px 12px; font-size: 13.5px; }
.player .num { color: var(--muted); font-variant-numeric: tabular-nums; font-weight: var(--w-strong); text-align: right; font-family: var(--font-num); }
.player .pn { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.player .pn .cap { display: inline-block; margin-left: 5px; padding: 0 5px; border-radius: var(--r-tag); background: var(--gold); color: var(--on-gold); font-size: 10px; font-weight: var(--w-cap); }
.player .role { color: var(--faint); font-size: 10.5px; white-space: nowrap; text-align: right; }
.events { padding: 6px 0; }
.event { display: grid; grid-template-columns: 1fr 44px 1fr; align-items: center; gap: 6px; padding: 6px 14px; font-size: 13px; }
.event .h { text-align: right; } .event .a { text-align: left; }
.event .min { text-align: center; color: var(--muted); font-variant-numeric: tabular-nums; font-weight: var(--w-strong); font-family: var(--font-num); }
/* Гол — мяч, а не цветной круг: ободок и пятиугольная «заплатка». Берут цвет
   --ic-ink (акцент темы, для автогола — красный), поэтому значок читаем и на
   светлой, и на тёмной карточке, и на пользовательской палитре. */
.event .ic, .ev-legend .ic { display: inline-block; width: 12px; height: 12px; border-radius: 50%; vertical-align: -1px; margin: 0 5px; }
.event .ic.goal, .event .ic.penalty, .event .ic.own-goal,
.ev-legend .ic.goal, .ev-legend .ic.penalty, .ev-legend .ic.own-goal {
  position: relative; box-sizing: border-box;
  border: 1.5px solid var(--ic-ink, var(--accent)); background: transparent;
}
.event .ic.goal::before, .event .ic.penalty::before, .event .ic.own-goal::before,
.ev-legend .ic.goal::before, .ev-legend .ic.penalty::before, .ev-legend .ic.own-goal::before {
  content: ''; position: absolute; left: 50%; top: 50%; width: 4px; height: 4px;
  margin: -2.5px 0 0 -2px; background: var(--ic-ink, var(--accent));
  clip-path: polygon(50% 0, 100% 38%, 81% 100%, 19% 100%, 0 38%);
}
.event .ic.own-goal, .ev-legend .ic.own-goal { --ic-ink: var(--loss); }
.event .ic.yellow, .ev-legend .ic.yellow { background: var(--card-yellow); border-radius: var(--r-card-mark); width: 9px; height: 12px; }
.event .ic.red, .ev-legend .ic.red { background: var(--card-red); border-radius: var(--r-card-mark); width: 9px; height: 12px; }
.event .ic.sub, .ev-legend .ic.sub { background: transparent; border: 2px solid var(--muted); box-sizing: border-box; }
.event .ic.penalty-miss, .ev-legend .ic.penalty-miss { background: transparent; border: 2px solid var(--loss); box-sizing: border-box; }
/* расшифровка значков — только те, что реально есть в списке событий: строка
   мелких подписей под матчем, а не второй экран текста */
.ev-legend { display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: center;
  margin: 0; padding: 9px 12px 10px; border-top: 1px solid var(--line-2);
  color: var(--faint); font-size: 11px; font-weight: var(--w-cap); font-family: var(--font-cap); }
.ev-legend span { display: inline-flex; align-items: center; }
.ev-legend .ic { margin: 0 4px 0 0; }

/* ---------- skeleton ---------- */
.skeleton { padding: 16px; display: grid; gap: 10px; }
.skeleton i { display: block; height: 14px; border-radius: var(--r-sk); background: var(--sk-bg); background-size: 200% 100%; animation: sk 1.3s linear infinite; }
@keyframes sk { to { background-position: -200% 0; } }

/* ---------- VK Mini App ---------- */
/* Кнопки VK «…» и «×» рисуются поверх приложения в правом верхнем углу:
   интерактивных элементов там не держим (тема — слева в шапке / в нижней
   панели) и резервируем справа место, чтобы заголовок не уходил под них. */
html.vkapp .topbar { padding-right: 96px; }
/* ---------- оверлей-iframe (навигация внутри VK Mini App) ----------
   Разделы открываются в кадре на весь экран. «Назад» — одна кнопка в шапке
   самого раздела: плавающая кнопка поверх контента дублировала её и наезжала
   на нижние строки (списки составов, футер тренера). */
#frameWrap { position: fixed; inset: 0; z-index: 50; display: none; background: var(--bg); }
#frameWrap.open { display: block; }
#pageFrame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; background: var(--bg); }

/* ---------- QoL: каскадное появление карточек и строк ---------- */
@keyframes rise { from { opacity: 0; transform: translateY(16px) scale(.985); } to { opacity: 1; transform: none; } }
.tile, .card, .tbl tbody tr, .match, .scorer, .squad, .day {
  animation: rise .5s cubic-bezier(.22, .9, .3, 1) backwards;
}
/* плавная смена темы (у элементов из press-блока transition уже есть) */
body, .card, .topbar, .controls select, .match .score, .chip, .tbl td, .crest {
  transition: background-color .25s ease, color .25s ease, border-color .25s ease, box-shadow .25s ease;
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ---------- Верхние уведомления: ниже нативных кнопок VK ---------- */
:root { --toast-top: calc(14px + var(--safe-top)); }
html.vkapp { --toast-top: calc(62px + var(--safe-top)); }
.toast {
  position: fixed; left: 50%; top: var(--toast-top); z-index: 80;
  transform: translate(-50%, -12px); opacity: 0; pointer-events: none;
  width: max-content;
  max-width: min(92vw, 420px); padding: 10px 16px; border-radius: var(--r-pop);
  background: var(--pop-bg); border: 1px solid var(--line);
  -webkit-backdrop-filter: var(--pop-blur); backdrop-filter: var(--pop-blur);
  color: var(--pop-fg); font-size: 13px; font-weight: var(--w-strong); text-align: center;
  box-shadow: var(--pop-shadow); font-family: var(--font-text);
  transition: opacity .25s ease, transform .25s ease;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
/* Небольшой короткий залп: только 14 декоративных частиц, без canvas/зависимостей. */
.toast-confetti { position: absolute; left: 50%; top: 100%; z-index: -1; width: 0; height: 0; pointer-events: none; }
.toast-confetti i {
  position: absolute; width: var(--cf-w); height: var(--cf-h); border-radius: var(--r-cf);
  background: var(--accent); opacity: 0; pointer-events: none;
  animation: toast-burst 1s ease-out both;
}
.toast-confetti i:nth-child(3n) { background: var(--gold); }
.toast-confetti i:nth-child(3n + 1) { background: var(--cf-2); }
.toast-confetti i:nth-child(4n) { background: var(--cf-3); border-radius: var(--r-cf-dot); }
.toast-confetti i:nth-child(1) { --cx: -125px; --cy: 50px; }
.toast-confetti i:nth-child(2) { --cx: -100px; --cy: 76px; }
.toast-confetti i:nth-child(3) { --cx: -76px; --cy: 38px; }
.toast-confetti i:nth-child(4) { --cx: -53px; --cy: 85px; }
.toast-confetti i:nth-child(5) { --cx: -30px; --cy: 62px; }
.toast-confetti i:nth-child(6) { --cx: -12px; --cy: 95px; }
.toast-confetti i:nth-child(7) { --cx: 15px; --cy: 54px; }
.toast-confetti i:nth-child(8) { --cx: 38px; --cy: 82px; }
.toast-confetti i:nth-child(9) { --cx: 60px; --cy: 44px; }
.toast-confetti i:nth-child(10) { --cx: 83px; --cy: 70px; }
.toast-confetti i:nth-child(11) { --cx: 104px; --cy: 38px; }
.toast-confetti i:nth-child(12) { --cx: 125px; --cy: 87px; }
.toast-confetti i:nth-child(13) { --cx: -110px; --cy: 96px; }
.toast-confetti i:nth-child(14) { --cx: 110px; --cy: 104px; }
@keyframes toast-burst {
  0% { opacity: 0; transform: translate(0, 0) rotate(0); }
  15% { opacity: 1; }
  50% { opacity: 1; transform: translate(calc(var(--cx) * .65), calc(var(--cy) * .3)) rotate(120deg); }
  100% { opacity: 0; transform: translate(var(--cx), var(--cy)) rotate(280deg); }
}
@media (prefers-reduced-motion: reduce) { .toast-confetti { display: none; } }
.achv-progress { margin: 0; padding: 0 14px calc(14px * var(--ui-scale)); color: var(--muted); font-size: calc(12px * var(--ui-scale)); }
.achv-progress.err { color: var(--live); }

/* ---------- QoL: ближайшее достижение и шаринг своего результата ----------
   Вместо простыни из 31 бейджа — одна ближайшая цель с полоской прогресса
   (.goal) и кнопки «поделиться» (достижения / расклад сезона). */
.goal { margin: 0 14px calc(10px * var(--ui-scale)); padding: 10px 12px; border-radius: var(--r-item); background: var(--item-bg); border: var(--item-border); }
.goal-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; font-size: calc(12px * var(--ui-scale)); }
.goal-top b { color: var(--text); font-weight: var(--w-strong); font-family: var(--font-cap); letter-spacing: var(--ls-head); text-transform: var(--tt-head); }
.goal-top span { color: var(--muted); }
.goal-bar { margin-top: 8px; height: var(--h-bar); border-radius: var(--r-bar); background: var(--bar-track); overflow: hidden; }
.goal-bar i { display: block; height: 100%; width: 0; border-radius: var(--r-bar); background: var(--bar-fill); transition: width .45s ease; }
.card-actions { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 14px calc(14px * var(--ui-scale)); }


/* ---------- QoL: «мой клуб» ----------
   Подсветка всего, что связано с выбранным клубом, — градиентом
   слева направо (акцент у левого края, тает к правому). */
.tbl tbody tr[data-club] { cursor: pointer; }
.tbl tr.fav { background: var(--fav-fill); }
.tbl tr.fav td.pos { box-shadow: inset 3px 0 0 var(--accent); color: var(--accent); }
.match.fav, .scorer.fav, .squad.fav {
  background-image: var(--fav-fill);
  box-shadow: var(--fav-rule);
}

/* ---------- QoL-волна 2: sheet, форма, hello, бейджи, таймлайн, h2h ---------- */
.sheet-wrap { position: fixed; inset: 0; z-index: 70; display: flex; align-items: flex-end; justify-content: center; }
.sheet-back { position: absolute; inset: 0; background: var(--sheet-back-bg); opacity: 0; transition: opacity .2s ease; }
.sheet-wrap.open .sheet-back { opacity: 1; }
.sheet {
  position: relative; width: min(100%, 560px); overflow: hidden;
  background: var(--sheet-bg); border-radius: var(--r-sheet); border-top: var(--sheet-rule);
  padding: 10px 12px calc(14px + var(--safe-bottom));
  box-shadow: var(--sheet-shadow); display: grid; gap: 6px;
  transform: translateY(100%); transition: transform .25s cubic-bezier(.22, .9, .3, 1);
}
.sheet-wrap.open .sheet { transform: none; }
.sheet::before { content: ''; display: block; width: 40px; height: 4px; border-radius: var(--r-pill); background: var(--line); margin: 2px auto 6px; }
/* знак клуба фоном всего листа: окно сразу видно чьё — ещё до чтения пунктов.
   Крупно, размыто и полупрозрачно: это фон, а не эмблема в списке. */
.sheet-bg { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
/* Эмблема занимает лист целиком, от края до края: cover (а не contain) —
   contain вписывал щит по одной стороне и оставлял широкие поля, из-за чего
   знак выглядел мелким. Пропорции щита cover сохраняет: за край уходит только
   лишнее, а для размытого фона это как раз то, что нужно. */
.sheet-bg .crest { width: 100%; height: 100%; object-fit: contain; opacity: .14; filter: blur(6px); }
.sheet > *:not(.sheet-bg) { position: relative; }
.sheet-note { display: grid; gap: 2px; }
.sheet-item { height: 50px; border: var(--item-border); border-radius: var(--r-item); background: var(--item-bg); color: var(--text); font-weight: var(--w-strong); font-size: 14px; cursor: pointer; font-family: var(--font-name); text-transform: var(--tt-item); letter-spacing: var(--ls-item); }
.sheet-item.cancel { background: transparent; color: var(--muted); }
/* пункт со строкой игры: подпись, знаки и счёт в одну линию, знак — вплотную
   к названию своего клуба. Высоту пункта отдаём содержимому, а не фиксируем:
   строка из пяти частей длиннее обычной подписи. */
.sheet-item.with-rich { height: auto; min-height: 50px; padding: 8px 12px; }
/* строка игры прижата к левому краю, как любая другая подпись в этом листе:
   по центру она читается как заголовок, а не как пункт списка */
.sheet-item.with-rich .gi-row { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; justify-content: flex-start; text-align: left; }
.gi-label { font-style: normal; color: var(--muted); font-weight: var(--w-body); }
.gi-side { display: inline-flex; align-items: center; gap: 5px; min-width: 0; }
.gi-side .crest { height: calc(22px * var(--ui-scale, 1)); flex: none; }
.gi-score { font-style: normal; font-weight: var(--w-strong); }
.sheet-item:active { transform: scale(.98); }
/* Пункт-ссылка — <a>, а не <button>: у строчного элемента height не работает,
   из-за чего подпись прижималась к верху относительно соседних кнопок.
   Центрируем только по вертикали: по горизонтали подпись стоит у левого края,
   как у кнопок — направление задаёт .sheet-item { text-align: left; padding: 0 14px }. */
a.sheet-item { display: flex; align-items: center; text-decoration: none; }

.form.sm i { width: 6px; height: 6px; }
.match .side { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
/* max-width: у колоночного .side при align-items: flex-end/flex-start .nmrow
   считался по содержимому и был шире колонки, поэтому .nm не сжимался и
   многоточие не наступало — название уезжало за карточку и резалось краем */
.match .side .nmrow { display: flex; align-items: center; gap: 8px; min-width: 0; max-width: 100%; }
.match .side.home { align-items: flex-end; }
.match .side.home .nmrow { justify-content: flex-end; }
.match .side.away { align-items: flex-start; }

.hello { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; margin-top: 10px; }
/* Кнопка топа — в ряду плашек клуба, справа: ряд центрирован, поэтому кнопку
   прижимаем к правому краю сама. Отличается и формой (рамка акцента), и тем,
   что в ней есть иконка: плашка информации не должна выглядеть кнопкой. */
.hello-top { display: inline-flex; align-items: center; gap: 5px; margin-left: auto; border: 1px solid var(--accent); background: var(--accent-dim); color: var(--accent); }
.hello-top svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.hello-top:active { transform: scale(.97); }
/* Вопрос об участии в топе: спрашиваем один раз, молчание согласием не считаем */
/* Диалог согласия — тот же нижний лист, что и везде: фон, скругление и тень
   берём из токенов направления (--sheet-*). Свои литералы здесь означали бы,
   что смена направления это окно не перекрасит. */
.consent { position: fixed; inset: 0; z-index: 60; display: flex; align-items: flex-end; justify-content: center; background: var(--sheet-back-bg); padding: 14px; }
.consent-card { width: 100%; max-width: 420px; padding: 16px 16px 14px; border-radius: var(--r-sheet); background: var(--card); border: var(--item-border); box-shadow: var(--sheet-shadow); margin-bottom: var(--safe-bottom); }
.consent-card b { display: block; font-size: 15px; margin-bottom: 6px; }
.consent-card p { margin: 0 0 12px; font-size: 13px; color: var(--muted); line-height: 1.45; }
.consent-btns { display: flex; gap: 8px; }
.consent-btns .chip.btn { flex: 1; text-align: center; background: var(--accent-dim); color: var(--accent); }
.consent-link { margin-top: 10px; padding: 0; border: none; background: none; color: var(--muted); font: inherit; font-size: 12.5px; text-decoration: underline; cursor: pointer; }
/* Топ участников */
.trow { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-top: var(--item-border); cursor: pointer; }
.trow:first-child { border-top: none; }
.trank { width: 22px; text-align: right; color: var(--muted); font-family: var(--font-num); font-variant-numeric: tabular-nums; font-size: 13px; }
.tavatar { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; background: var(--item-bg); flex: 0 0 auto; }
.tavatar-empty { display: inline-flex; align-items: center; justify-content: center; color: var(--muted); font-weight: var(--w-strong); }
.trow .tpt { flex: 1; min-width: 0; }
.trow .tpt b { display: block; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.trow .tpt i { display: block; font-size: 12px; color: var(--muted); }
.tpct { font-family: var(--font-num); font-variant-numeric: tabular-nums; font-weight: var(--w-strong); color: var(--accent); }
/* Участник с персональной наградой: подсветка — цветом награды */
.trow-award { box-shadow: inset 3px 0 0 var(--gold); padding-left: 8px; }
/* Рамка аватара — право «рамка в топе»: цвет берём у самой награды, поэтому
   золотая награда даёт золотую рамку, а синяя — синюю. */
.tf-gold { box-shadow: 0 0 0 2px var(--gold); }
.tf-blue { box-shadow: 0 0 0 2px var(--tone-blue); }
.tf-green { box-shadow: 0 0 0 2px var(--tone-green); }
.tf-violet { box-shadow: 0 0 0 2px var(--tone-violet); }
.tf-gray { box-shadow: 0 0 0 2px var(--faint); }
/* Девиз под именем: право «девиз в топе». Курсив, чтобы не спорить с именем. */
.tmotto { display: block; font-style: italic; font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tsheet .tmotto { text-align: center; font-size: 13px; margin-top: -2px; }
.tsheet { display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; padding: 6px 2px 2px; }
.tsheet .tavatar { width: 56px; height: 56px; }
.tsheet b { font-size: 16px; }
.tsheet i { font-style: normal; color: var(--muted); font-size: 13px; }
.tsheet-awards { display: flex; flex-wrap: wrap; gap: 5px; justify-content: center; }
.tsheet-achv { margin-top: 6px; }
.tsheet-achv b { display: block; font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); font-family: var(--font-cap); margin-bottom: 3px; }
.tsheet-achv span { font-size: 13px; }

.badges { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 8px; padding: 12px 14px; }
.badge { border-radius: var(--r-item); padding: 10px 8px; text-align: center; background: var(--item-bg); border: var(--item-border); color: var(--faint); font-size: 11px; font-weight: var(--w-cap); line-height: 1.3; }
.badge b { display: block; font-size: 12px; font-weight: var(--w-strong); color: var(--muted); margin-bottom: 3px; }
.badge.on { background: var(--accent-dim); color: var(--accent); }
.badge.on b { color: var(--text); }

.events { position: relative; }
.events::before { content: ''; position: absolute; left: 50%; top: 8px; bottom: 8px; width: 2px; background: var(--line-2); }
.event .min { background: var(--card); border-radius: 999px; padding: 1px 7px; border: 1px solid var(--line-2); font-size: 11px; }

.h2h-row { display: grid; grid-template-columns: 1fr auto 1fr; gap: 10px; align-items: center; padding: 9px 14px; font-size: 13px; }
.h2h-row .v { font-weight: var(--w-strong); font-variant-numeric: tabular-nums; }
.h2h-row .v.r { text-align: right; }
.h2h-row .lbl { color: var(--muted); font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; font-weight: var(--w-strong); text-align: center; }
.h2h-row .bar { height: 6px; border-radius: 999px; background: var(--card-2); overflow: hidden; margin-top: 4px; }
.h2h-row .bar i { display: block; height: 100%; background: var(--accent); border-radius: 999px; }
.h2h-row .bar.r i { margin-left: auto; background: var(--accent-2); }

.chip.btn { cursor: pointer; border: none; font: inherit; }

/* ---------- QoL-волна 3: предикты счёта («Анонсы») и «Мои предикты» ----------
   Блок предикта — отдельный сосед матча (ВНЕ <a class="match">): тапы по
   «−/+» и галочке не открывают матч. Обёртка .mrow берёт на себя разделитель. */
.mrow { border-bottom: 1px solid var(--line-2); }
.mrow:last-child { border-bottom: none; }
.mrow .match { border-bottom: none; }
.mrow .hint { margin: 0 14px 12px; background-color: var(--card-2); background-image: none; box-shadow: none; }
.predict { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 0 14px 12px; }
.predict .psum { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.predict .plabel { color: var(--muted); font-size: 11.5px; font-weight: var(--w-cap); letter-spacing: .04em; text-transform: uppercase; font-family: var(--font-cap); }
.predict .pstep-wrap { display: inline-flex; align-items: center; gap: 2px; background: var(--item-bg); border: var(--item-border); border-radius: var(--r-pill); padding: 2px; }
.predict .pstep { width: 26px; height: 26px; border: var(--step-border); border-radius: var(--r-step); background: var(--step-bg); color: var(--text); font-size: 15px; font-weight: var(--w-strong); line-height: 1; cursor: pointer; transition: transform .12s ease, background-color .2s ease; }
.predict .pstep:active:not(:disabled) { transform: scale(.94); background: var(--accent-dim); }
.predict .pstep:disabled { opacity: .35; cursor: default; }
.predict .pval { min-width: 18px; text-align: center; font-family: var(--font-num); font-weight: var(--w-display); font-size: 15px; font-variant-numeric: tabular-nums; }
.predict .pcolon { color: var(--faint); font-weight: var(--w-strong); }
.predict .pfix { border: none; }
.predict.locked .psum { opacity: .7; }
/* Рейтинг предиктов («как поставили другие») — распределение по счетам полоской.
   Пустой блок не занимает места: данные приходят с сервера уже после отрисовки. */
.prate { display: block; padding: 0 14px 12px; }
.prate:empty { display: none; }
.prate-h { display: block; margin-bottom: 4px; color: var(--muted); font-size: 11.5px; font-weight: var(--w-cap); letter-spacing: .04em; text-transform: uppercase; font-family: var(--font-cap); }
.prate-row { display: flex; align-items: center; gap: 6px; margin-top: 3px; font-size: 13.5px; color: var(--text); }
/* Десять счетов в один столбец — это десять строк на карточку тура. Сетка
   в два столбца держит тот же объём в половину высоты; на самом узком
   экране столбец всё равно один. */
.prate-grid { display: grid; grid-template-columns: 1fr 1fr; column-gap: 14px; row-gap: 2px; }
.prate-grid .prate-row { margin-top: 0; }
.prate-grid .prate-row, .prate-row.prown { font-size: calc(12.5px * var(--ui-scale)); }
@media (max-width: 340px) { .prate-grid { grid-template-columns: 1fr; } }
.prate-row b { min-width: 30px; font-family: var(--font-num); font-variant-numeric: tabular-nums; }
.prate-row .pbar { flex: 1; height: 6px; overflow: hidden; border: var(--item-border); border-radius: var(--r-pill); background: var(--item-bg); }
.prate-row .pbar s { display: block; height: 100%; background: var(--accent-dim); text-decoration: none; }
.prate-row em { min-width: 40px; font-style: normal; text-align: right; color: var(--muted); font-variant-numeric: tabular-nums; }
/* свой счёт — тем же цветом, что подсветка выбранного: «вот куда вы поставили» */
.prate-row.mine .pbar s { background: var(--accent); }
.prate-row.mine em { color: var(--text); }
/* Значок персональной награды. Награду выдаёт владелец вручную, поэтому знак
   должен читаться как знак, а не как ещё один результат: своя плашка, свой
   цвет. Цвета тонов заданы прямо здесь (кроме золотого — он из темы: в тёмной
   теме золото другое, и плашка обязана меняться вместе с ней). */
.pbadge {
  display: inline-flex; align-items: center; max-width: 100%;
  padding: 2px 7px; border-radius: var(--r-pill);
  background: var(--pbadge-bg, var(--accent-dim)); color: var(--pbadge-fg, var(--accent));
  font-size: 10.5px; font-weight: var(--w-cap); letter-spacing: .02em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pbadge-gold { --pbadge-bg: var(--gold); --pbadge-fg: var(--on-gold); }
/* Цвета тонов задаёт направление (--tone-*): в тёмной газете синий другой, и
   плашка обязана меняться вместе с темой. Текст на заливке — --ui-on-accent:
   это «чернила по акценту», а не случайный белый. */
.pbadge-blue { --pbadge-bg: var(--tone-blue); --pbadge-fg: var(--ui-on-accent); }
.pbadge-green { --pbadge-bg: var(--tone-green); --pbadge-fg: var(--ui-on-accent); }
.pbadge-violet { --pbadge-bg: var(--tone-violet); --pbadge-fg: var(--ui-on-accent); }
.pbadge-gray { --pbadge-bg: var(--item-bg); --pbadge-fg: var(--muted); }
.pbadge-inline { margin-left: 6px; vertical-align: middle; }
/* Знак награды больше не живёт в строке счёта: там он вытеснял процент и
   обрезался по ширине строки (длинное название превращалось в «Ораку…»).
   Теперь он стоит отдельным блоком под распределением, на всю ширину.
   Сам блок показывается один раз на тур — в первом матче со своим счётом,
   дальше цвет награды помечает сами предикты. */
/* Свой предикт помечен цветом награды: полоска и счёт. Тон задаёт направление
   (--tone-*), поэтому в каждом скине свой оттенок. */
.prate-row.mine-award { box-shadow: inset 2px 0 0 var(--award-tone, var(--accent)); padding-left: 6px; }
.prate-row.mine-award .pbar s { background: var(--award-tone, var(--accent)); }
.prate-row.mine-award b { color: var(--award-tone, var(--accent)); }
.ptone-gold { --award-tone: var(--gold); }
.ptone-blue { --award-tone: var(--tone-blue); }
.ptone-green { --award-tone: var(--tone-green); }
.ptone-violet { --award-tone: var(--tone-violet); }
.ptone-gray { --award-tone: var(--faint); }
/* Прогноз обладателя награды: своей строкой под распределением, чтобы не
   спорить с процентами — это не «ещё один голос», а отдельный знак.
   Заголовок обязателен: без него строка «Оракул 3:1» читалась как часть
   распределения, и никто не понимал, что это чей-то прогноз. */
.prate-pick { display: flex; flex-direction: column; gap: 3px; margin-top: 7px; padding: 7px 9px; border-radius: var(--r-item); background: var(--item-bg); border: var(--item-border); }
.ppick-h { font-size: 10.5px; font-weight: var(--w-cap); letter-spacing: .04em; text-transform: uppercase; color: var(--muted); font-family: var(--font-cap); }
.ppick-line { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; font-size: 13px; color: var(--text); }
/* Тап принимает весь блок, а не только кружок «?»: попасть в кружок пальцем
   трудно, а вопрос «что это такое» возникает у всего блока целиком. */
.prate-pick, .paward-mine { cursor: pointer; }
.ppick-line b { font-family: var(--font-num); font-variant-numeric: tabular-nums; }
/* Кнопка «?» — заметная, но не спорящая со счётом: кружок в рамке */
.ppick-info { margin-left: auto; width: 20px; height: 20px; flex: 0 0 auto; padding: 0; border-radius: 50%; border: var(--item-border); background: transparent; color: var(--muted); font-size: 12px; font-weight: var(--w-strong); line-height: 1; cursor: pointer; }
.ppick-info:active { background: var(--accent-dim); color: var(--accent); }
/* «сыграл» / «мимо» — только по факту счёта, а не в надежде на него */
.ppick-res { font-style: normal; font-size: 11.5px; color: var(--muted); }
.ppick-res.ok { color: var(--accent); font-weight: var(--w-cap); }
/* Свои награды под распределением — тем же блоком, что прогноз по награде:
   подпись, знак, пояснение. Отличаем только отступом сверху. */
.paward-mine { display: flex; flex-direction: column; gap: 3px; margin-top: 7px; padding: 7px 9px; border-radius: var(--r-item); background: var(--item-bg); border: var(--item-border); }
/* Пояснение под знаком: чем награда заслужена и что она даёт. Мелко и тихо,
   но именно оно отвечает на вопрос «что это за слово». */
.ppick-text { font-size: 11.5px; line-height: 1.35; color: var(--muted); }
/* Знак в блоке не обрезаем: длинное название переносится на вторую строку,
   а не превращается в «Железный бо…». В строке счёта места нет, здесь — есть. */
.prate-pick .pbadge, .paward-mine .pbadge { white-space: normal; max-width: 100%; }
/* Метка точного прогноза: награда угадала счёт этого матча */
.pstar { display: flex; align-items: center; gap: 6px; margin-top: 6px; font-size: 12.5px; color: var(--text); }
/* Что даёт награда, в «Моих матчах»: строка «Даёт: …» под пояснением */
.aperk { display: block; margin-top: 4px; }
.aperk b { display: block; font-size: 11.5px; font-weight: var(--w-cap); letter-spacing: .02em; color: var(--accent); }
.aperk em { display: block; font-style: normal; font-size: 12px; color: var(--muted); line-height: 1.35; margin-top: 1px; }
.aperk.dim b { color: var(--muted); }
/* Общий итог предиктов под заголовком «Мои предикты»: три числа — счёт, исход,
   мимо. Считается по всей истории, а не по показанным десяти строкам, поэтому
   список можно резать: ответ на вопрос «сколько я угадал» остаётся честным. */
.psum { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 0 8px; }
/* Редактор девиза (награда с правом «девиз в топе»): фразу пишет сам человек */
.amotto { margin-top: 6px; padding: 8px 9px; border-radius: var(--r-item); background: var(--item-bg); border: var(--item-border); }
.amotto label { display: block; font-size: 11.5px; font-weight: var(--w-cap); letter-spacing: .04em; text-transform: uppercase; color: var(--muted); font-family: var(--font-cap); }
.amotto-row { display: flex; gap: 6px; margin-top: 5px; }
.amotto-in { flex: 1 1 auto; min-width: 0; padding: 7px 9px; border-radius: var(--r-item); border: var(--item-border); background: var(--bg); color: var(--text); font: inherit; font-size: 14px; }
.amotto-note, .amotto-msg { display: block; font-style: normal; font-size: 11.5px; line-height: 1.35; color: var(--muted); margin-top: 4px; }
.amotto-msg:empty { display: none; }
/* Итог тура под списком матчей: личный счёт рядом со средним по участникам */
.ptour { display: flex; flex-direction: column; gap: 2px; padding: 10px 14px 12px; border-top: var(--item-border); }
.ptour b { font-size: 11.5px; font-weight: var(--w-cap); letter-spacing: .04em; text-transform: uppercase; color: var(--muted); font-family: var(--font-cap); }
.ptour span { font-size: 12.5px; color: var(--text); }
.ptours { margin-top: 6px; }
.chip.ok { background: var(--accent-dim); color: var(--accent); }
.chip.warn { background: var(--chip-warn-bg); color: var(--gold); }
.chip.dim { background: var(--card-2); color: var(--muted); }
.prow, .ptour-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 11px 14px; border-bottom: 1px solid var(--line-2); }
.prow:last-child, .ptour-row:last-child { border-bottom: none; }
.prow .pt, .ptour-row .pt { min-width: 0; }
.prow .pt b, .ptour-row .pt b { display: block; font-weight: var(--w-strong); font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--font-name); text-transform: var(--tt-name); }
.prow .pt i, .ptour-row .pt i { display: block; font-style: normal; color: var(--muted); font-size: 11.5px; margin-top: 2px; }

/* ---------- Инструкция и настройки: общий верхний ряд, вне кнопок VK ----------
   Три кнопки обязаны помещаться в одну строку на телефоне (360px минус 82px на
   кнопки VK «…» и «×»). Поэтому ряд nowrap, кнопки умеют сжиматься, а рамка
   подписи не даёт переноса внутрь кнопки. Шрифт растёт от ползунка масштаба
   не пропорционально, а демпфированно (+6px на каждые +100%): на «150%» ряд
   остаётся строкой. */
.ui-tools { display: flex; flex-wrap: nowrap; align-items: center; justify-content: center; gap: 5px; margin-bottom: 12px; font-size: calc(12.5px + (var(--ui-scale, 1) - 1) * 6px); }
.topbar .ui-tools { flex: 0 0 100%; margin: 0; }
.hero { padding-top: 8px; }
html.vkapp .hero .ui-tools { padding-right: 82px; padding-left: 0; }
.ui-tools button, .ui-dialog button {
  border: var(--ctl-border); border-radius: var(--r-btn); padding: 9px 10px;
  background: var(--ctl-bg); color: var(--text); font: inherit; font-weight: var(--w-strong); cursor: pointer;
  font-family: var(--font-cap); letter-spacing: var(--ls-btn); text-transform: var(--tt-btn);
}
/* Разрядка — главный пожиратель ширины в капительных подписях: в ряду её
   держим в 0,6 от токена, чтобы «ИНСТРУКЦИЯ» не выталкивала шестерёнку. */
.ui-tools button {
  min-width: 0; min-height: 38px; flex: 0 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  letter-spacing: calc(var(--ls-btn) * .6);
}
/* Высота ряда задаётся один раз (min-height), поэтому кнопка настроек — ровно
   тот же квадрат и не сжимается: иначе на узком экране она превращается в овал,
   а значок обрезается. */
.ui-tools .ui-icon { display: grid; place-items: center; width: 38px; height: 38px; padding: 7px; flex: 0 0 auto; }
.ui-tools .ui-icon svg { width: 20px; height: 20px; }
.ui-dialog .ui-icon { display: grid; place-items: center; width: 36px; height: 36px; padding: 6px; flex: 0 0 36px; }
.ui-icon svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linejoin: round; }
.ui-tools button:focus-visible, .ui-dialog :focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
/* Phones: подпись «Тема» уходит первой — с ней ряд в «Табло» (Golos Text — не
   узкий Oswald) уже не гарантированно влезает между 360px и кнопками VK. Значок
   остаётся, доступное имя — на aria-label, который синхронизирует League.theme.
   Last resort (320px + крупный масштаб) — многоточие на «Инструкции», строка
   всё равно одна. */
@media (max-width: 480px) {
  .ui-tools .theme-toggle span { display: none; }
  /* значок без подписи: 16 + 2×11 = 38px — квадрат наравне с кнопкой настроек */
  .ui-tools .theme-toggle { padding-left: 11px; padding-right: 11px; }
}
/* Модалка — слой на весь экран, а не «коробка по центру»: тогда тап по
   затемнённому полю ВНЕ панели попадает в <dialog> и его можно обработать
   (league-ui.js). Панель умещается целиком: не нужно догадываться, что
   под ней есть продолжение. */
.ui-dialog {
  /* height: 100% обязателен: UA-стиль dialog задаёт block-size: fit-content, и
     без явной definite-высоты «max-height: 100%» панели не с чем сравнить —
     панель не ограничивалась, не прокручивалась и упиралась содержимым за
     нижний край (на длинной инструкции это терялись «Понятно» и чекбокс). */
  position: fixed; inset: 0; height: 100%; margin: 0; overflow: hidden;
  /* Верхний/нижний отступы ограничены: insets приходят из VKWebAppGetConfig,
     и одно странное значение съедало панель целиком — оставалась полоска в
     две строки. 20vh — запас, которого хватает и на статус-бар, и на «…». */
  padding: min(calc(12px + var(--safe-top)), 20vh) min(14px, 4vw) min(calc(12px + var(--safe-bottom)), 20vh);
  width: 100%; max-width: none; max-height: none; border: 0; border-radius: 0;
  background: transparent; color: var(--text);
  /* flex-start + margin: auto у панели, а не align-items: center: центрирование
     flex-элемента, который выше контейнера, обрезает его сверху и до него
     нельзя дотянуться скроллом */
  display: flex; align-items: flex-start; justify-content: center;
}
/* author-правило с display перебивает UA-правило dialog:not([open]) — закрытое
   окно осталось бы на экране, поэтому «спрятан» прописан явно */
.ui-dialog:not([open]) { display: none; }
/* В VK правый верхний угол занимают кнопки «…» и «×»: окно не должно
   подставлять свой крестик им под них */
html.vkapp .ui-dialog { padding-top: min(calc(48px + var(--safe-top)), 22vh); }
.ui-dialog::backdrop { background: var(--panel-backdrop); }
.ui-panel {
  /* min(520px, 100% - 0) + жёсткий потолок по вьюпорту: панель физически не
     может стать шире экрана, а значит её текст не уйдёт за правый край */
  width: min(520px, 100%); max-width: calc(100vw - 16px); margin: auto; min-width: 0;
  max-height: 100%; max-height: min(100%, calc(100dvh - 32px));
  /* Два значения overflow — это X, затем Y. Вбок панель не свайпится
     (hidden), а скролл по вертикали обязателен (auto): инструкция и панель
     настроек бывают выше вьюпорта, и на обратном порядке их нижний край с
     кнопками «Понятно» / «По умолчанию» оказывался отрезан без прокрутки. */
  overflow: hidden auto; overscroll-behavior: contain;
  padding: 14px 16px 16px; border: var(--panel-border); border-radius: var(--r-lg);
  background: var(--card); color: var(--text); box-shadow: var(--panel-shadow);
  font: var(--w-body) 13px/1.45 var(--font-text);
  /* на ПК панель обязана ПОКАЗЫВАТЬ, что прокручивается: без полосы
     прокрутки длинная инструкция и «Настройки» выглядели обрезанными */
  scrollbar-width: thin; scrollbar-color: var(--muted) transparent;
}
/* Длинное слово или блок шире панели не должен расталкивать её саму:
   min-width: 0 разрешает сжиматься, break-word — переносить непонятные токены
   (hex-значение, ссылка) вместо того, чтобы расширить окно за край экрана. */
/* WebKit/Blink (VK Desktop = WebView2) красит полосу сам: светлая полоса на
   тёмной панели не читается, поэтому задаём её сами через токены темы */
.ui-panel::-webkit-scrollbar { width: 10px; height: 10px; }
.ui-panel::-webkit-scrollbar-track { background: transparent; }
.ui-panel::-webkit-scrollbar-thumb { background: var(--muted); border: 3px solid transparent; border-radius: var(--r-pill); background-clip: content-box; }
.ui-panel > *, .ui-panel p, .ui-panel li { min-width: 0; overflow-wrap: break-word; }
.ui-panel img, .ui-panel svg { max-width: 100%; }
.ui-dialog-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.ui-dialog h2 { font-family: var(--font-display); font-size: 17px; line-height: 1.2; margin: 0; letter-spacing: var(--ls-head); text-transform: var(--tt-head); font-weight: var(--w-strong); }
.ui-dialog h3 { font-size: 13px; margin: 0; }
.ui-dialog p { margin: 8px 0; }
.ui-dialog ul { padding-left: 18px; margin: 6px 0; }
.ui-dialog li + li { margin-top: 4px; }
.ui-dialog a { color: var(--accent); text-decoration: underline; }
.ui-notice { background: var(--item-bg); border: var(--item-border); border-radius: var(--r-md); padding: 12px; margin: 12px 0 0; }
.ui-notice p { margin: 6px 0; }
.ui-notice .ui-primary { margin-top: 10px; }
.ui-dialog .ui-primary { background: var(--accent); border-color: transparent; color: var(--ui-on-accent); }
.ui-dialog button:disabled { opacity: .5; cursor: default; }
.ui-check { display: flex; gap: 8px; align-items: center; min-height: 40px; }
.ui-check input { width: 20px; height: 20px; accent-color: var(--accent); }
.ui-dialog .ui-note { color: var(--muted); font-size: 11.5px; line-height: 1.4; margin: 10px 0 0; }
/* «подпись — контрол» в один ряд: направление, масштаб и обе палитры видны без прокрутки */
.ui-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 12px; }
/* Переключатель направления: две крупные кнопки, а не список — выбор визуального
   языка должен быть виден целиком (названия различимы, подпись под рядом). */
/* flex-basis у плиты — auto, а не 0: на basis:0 кнопки делили остаток строки
   пополам, min-width:0 снимал пол по ширине содержимого — и «ГАЗЕТА» рвалась
   посреди слога («ГАЗЕТ / А»). Теперь плитка охватывает подпись, растёт на всю
   ширину ряда (значит обе плитки равные), а если ширины ряда не хватает —
   переносится ВТОРАЯ плитка целиком, слово не рвётся никогда. */
.ui-styles { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; flex: 1 1 auto; }
.ui-style {
  flex: 1 1 auto; padding: 9px 12px; cursor: pointer;
  white-space: nowrap; text-align: center;
  border: var(--btn-border); background: var(--btn-bg); color: var(--text);
  border-radius: var(--r-btn); font-family: var(--font-cap); font-size: 13px; font-weight: var(--w-strong);
}
.ui-style[aria-pressed=true] { color: var(--accent); box-shadow: inset 0 0 0 1.5px var(--accent); }
.ui-stepper { display: flex; align-items: center; gap: 8px; }
.ui-stepper button { width: 34px; height: 32px; font-size: 18px; padding: 0; line-height: 1; }
.ui-stepper output { min-width: 56px; text-align: center; font-size: 17px; font-weight: var(--w-strong); font-variant-numeric: tabular-nums; font-family: var(--font-num); }
.ui-colors { margin: 12px 0 0; padding: 4px 10px 10px; border: 1px solid var(--line); border-radius: var(--r-md); min-width: 0; }
.ui-colors legend { font-weight: var(--w-strong); font-size: 12px; color: var(--muted); padding: 0 6px; }
.ui-color-field { display: flex; align-items: center; gap: 8px; }
.ui-color-field + .ui-color-field { margin-top: 8px; }
.ui-color-field > label { flex: 0 0 auto; color: var(--muted); font-size: 12px; }
.ui-palette { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-left: auto; }
.ui-dialog .ui-swatch { background: var(--swatch); width: 26px; height: 26px; padding: 0; border: 2px solid var(--muted); border-radius: var(--r-swatch); }
.ui-swatch[aria-pressed=true] { outline: 2px solid var(--accent); outline-offset: 2px; }
.ui-custom { display: flex; align-items: center; gap: 4px; font-size: 12px; }
/* Превью своего цвета: значение --swatch приходит из динамического stylesheet
   #ui-hex-preview (league-ui.js), inline-стилей нет. До первого значения — нейтральный фон. */
.ui-hex-swatch { flex: 0 0 20px; width: 20px; height: 20px; border: 1px solid var(--line); border-radius: var(--r-swatch); background: var(--swatch, var(--card-2)); }
.ui-custom input {
  width: 72px; height: 30px; padding: 0 6px; border: 1px solid var(--line); border-radius: var(--r-input);
  background: var(--card); color: var(--text); font: var(--w-cap) 12px/1.2 var(--font-num); text-transform: lowercase;
}
.ui-dialog .ui-custom input:disabled { opacity: .5; cursor: default; }
.ui-actions { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.ui-actions .ui-note { flex: 1 1 140px; margin: 0; text-align: right; }
.ui-wide { width: 100%; margin-top: 12px; padding: 12px; text-align: center; }
/* ---------- Ранний показ оформления (league-appearance.js) ----------
   Класс league-ui-pending ставится только в VK, когда uid и кеш оформления ещё
   неизвестны, и снимается сразу после ответа Storage или через 1.2 с (fallback).
   Вне VK и при наличии кеша страница не прячется. */
html.league-ui-pending body { visibility: hidden; }

/* Плавная подмена темы и направления (League.smoothSwap в league.js): поверх
   страницы на мгновение ложится плотный слой цветом ТЕКУЩЕГО экрана, под ним
   сходятся скин, палитра и гарнитуры, затем слой уходит. Переходов на самих
   элементах нет — они перебивали бы transition контролов. Длительности дублирует
   JS (SWAP_IN_MS / SWAP_OUT_MS в league.js): менять надо вместе, иначе слой
   успеет исчезнуть раньше, чем применится новый скин.
   Слой внутри открытого диалога: модалка живёт в верхнем слое, и обычным
   position: fixed поверх неё не перекрыться (см. комментарий в league.js). */
.swap-veil {
  position: fixed; inset: 0; z-index: 120; pointer-events: none;
  background: var(--bg); opacity: 0; transition: opacity 210ms linear;
}
html.league-swapping .swap-veil { opacity: 1; transition-duration: 140ms; }
html.league-swapping.league-swap-out .swap-veil { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .swap-veil { display: none; } }

/* ---------- Персональный масштаб: только типографика и вертикальные размеры.
   Ни zoom, ни масштабирования контейнеров; горизонтальные padding/gap, размеры
   колонок и переносы .nm остаются независимы от --ui-scale. Настройки и кнопка
   их открытия намеренно не уменьшаются — даже с 5% можно вернуть читаемый вид. */
:root { --ui-scale: 1; }
body, .card-head b, .feature .club b, .predict .pstep, .predict .pval { font-size: calc(15px * var(--ui-scale)); }
.topbar .title b, .tile b, .match .time { font-size: calc(17px * var(--ui-scale)); }
.topbar .title i, .day, .feature .vs .d, .feature .place, .scorer .who .team, .badge b { font-size: calc(12px * var(--ui-scale)); }
.hero .kicker, .status, .team .tc, .legal, .tbl th, .match .venue, .badge, .event .min { font-size: calc(11px * var(--ui-scale)); }
.hero h1 { font-size: calc(clamp(24px, 6.4vw, 34px) * var(--ui-scale)); }
.hero .sub, .card-head, .tile i, .hint b, .event, .h2h-row { font-size: calc(13px * var(--ui-scale)); }
.chip, .legend, .feature .club i, .squad .sq-head i, .predict .plabel, .prow .pt i, .ptour-row .pt i, .prate-h, .ptour b, .tm-when { font-size: calc(11.5px * var(--ui-scale)); }
.empty, .player, .prow .pt b, .ptour-row .pt b, .prate-row { font-size: calc(13.5px * var(--ui-scale)); }
.tile .arr { font-size: calc(26px * var(--ui-scale)); }
.hint, .ptour span { font-size: calc(12.5px * var(--ui-scale)); }
.tbl td.pts { font-size: calc(16px * var(--ui-scale)); }
.match .side .nm, .squad .sq-head b, .sheet-item, .tm-vs b { font-size: calc(14px * var(--ui-scale)); }
.match .score { font-size: calc(19px * var(--ui-scale)); }
.match .meta, .squad .grp, .player .role, .h2h-row .lbl { font-size: calc(10.5px * var(--ui-scale)); }
.feature .vs .t { font-size: calc(24px * var(--ui-scale)); }
.scorer .goals { font-size: calc(20px * var(--ui-scale)); }
.player .pn .cap { font-size: calc(10px * var(--ui-scale)); }
.card-head, .hint { padding-top: calc(14px * var(--ui-scale)); padding-bottom: calc(14px * var(--ui-scale)); }
.tile { padding-top: calc(18px * var(--ui-scale)); padding-bottom: calc(18px * var(--ui-scale)); }
.tile .ticon { height: calc(56px * var(--ui-scale)); }
.tile .ticon svg { height: calc(27px * var(--ui-scale)); }
.hero { padding-bottom: calc(20px * var(--ui-scale)); }
.hero .kicker, .status, .event, .events { padding-top: calc(6px * var(--ui-scale)); padding-bottom: calc(6px * var(--ui-scale)); }
.ev-legend { padding-top: calc(9px * var(--ui-scale)); padding-bottom: calc(10px * var(--ui-scale)); }
.chip { padding-top: calc(4px * var(--ui-scale)); padding-bottom: calc(4px * var(--ui-scale)); }
.empty { padding-top: calc(28px * var(--ui-scale)); padding-bottom: calc(28px * var(--ui-scale)); }
.tbl th, .tbl td, .badge { padding-top: calc(10px * var(--ui-scale)); padding-bottom: calc(10px * var(--ui-scale)); }
.day { padding-top: calc(10px * var(--ui-scale)); padding-bottom: calc(6px * var(--ui-scale)); }
.match { padding-top: calc(13px * var(--ui-scale)); padding-bottom: calc(13px * var(--ui-scale)); row-gap: calc(8px * var(--ui-scale)); }
.match .mid, .match .side { row-gap: calc(3px * var(--ui-scale)); }
.match .score { padding-top: calc(3px * var(--ui-scale)); padding-bottom: calc(3px * var(--ui-scale)); }
.feature { padding-top: calc(22px * var(--ui-scale)); padding-bottom: calc(22px * var(--ui-scale)); row-gap: calc(10px * var(--ui-scale)); }
.feature .club { row-gap: calc(8px * var(--ui-scale)); }
.feature .vs { row-gap: calc(4px * var(--ui-scale)); }
.scorer, .squad .sq-head, .legend { padding-top: calc(12px * var(--ui-scale)); padding-bottom: calc(12px * var(--ui-scale)); }
.squad .grp { padding-top: calc(8px * var(--ui-scale)); padding-bottom: calc(2px * var(--ui-scale)); }
.player { padding-top: calc(7px * var(--ui-scale)); padding-bottom: calc(7px * var(--ui-scale)); }
.h2h-row { padding-top: calc(9px * var(--ui-scale)); padding-bottom: calc(9px * var(--ui-scale)); }
.prow, .ptour-row { padding-top: calc(11px * var(--ui-scale)); padding-bottom: calc(11px * var(--ui-scale)); }
.predict { padding-bottom: calc(12px * var(--ui-scale)); }
.predict .pstep { height: calc(26px * var(--ui-scale)); }
.sheet-item { height: calc(50px * var(--ui-scale)); }
.controls select, .controls .btn { height: calc(44px * var(--ui-scale)); }
.topbar .back, .topbar .theme { height: calc(40px * var(--ui-scale)); }
.topbar .back svg, .topbar .theme svg { height: calc(18px * var(--ui-scale)); }
.form i { height: calc(8px * var(--ui-scale)); }
.form.sm i, .h2h-row .bar { height: calc(6px * var(--ui-scale)); }
.legend i { height: calc(10px * var(--ui-scale)); }
.event .ic, .ev-legend .ic { height: calc(12px * var(--ui-scale)); }
.skeleton i { height: calc(14px * var(--ui-scale)); }
.crest { height: calc(18px * var(--ui-scale)); }
.crest.lg { height: calc(30px * var(--ui-scale)); }
.crest.xl { height: calc(44px * var(--ui-scale)); }
.crest.sm { height: calc(14px * var(--ui-scale)); }
.card, .hint, .controls { margin-bottom: calc(14px * var(--ui-scale)); }
/* сетка плиток и карточки под ней должны сходиться одним отступом: у grid
   работает только row-gap, поэтому вниз нужен явный margin */
.tiles { row-gap: calc(14px * var(--ui-scale)); margin-bottom: calc(14px * var(--ui-scale)); }
/* Авто-треки не должны расширяться от более крупного текста — но contain:
   inline-size для этого не годится: колонка перестаёт видеть содержимое,
   остаётся в min-width, а широкое содержимое ВЫТЕКАЕТ за бокс поверх соседей
   (отчёт: дата «Понедельник, 26 октября» в «Мои матчи» легла на плашки клубов —
   и в обычном режиме, и в компактном, потому что режим меняет отступы, а не
   ширину трека). Правильный инструмент — потолок на колонке + перенос внутри
   (см. .match .mid и .feature .vs): трек от текста не зависит, но текст в него
   врастает, а не вылезает. Горизонтальные размеры ниже --ui-scale не трогаем. */
.match .mid > * { max-width: 100%; }
.feature .vs { min-width: 100px; }
.scorer .goals { contain: inline-size; }
.scorer .who { min-width: 0; overflow-wrap: anywhere; }
.scorer .who .team { max-width: 100%; }
.player .role { min-width: 0; }
.h2h-row .lbl { contain: inline-size; min-width: 100px; overflow-wrap: anywhere; }
/* Таблица: ширины колонок заданы одним блоком выше (.tbl th.c-*, .tbl td.*),
   они уже содержат var(--ui-scale). Здесь остаётся только типографика: раньше
   эти правила дублировали ширины и перебивали их по специфичности, из-за чего
   сумма фиксов (8×34 + 2×66) превышала ширину карточки и колонка «Команда»
   раздувалась до содержимого, а его текст шёл поверх чисел. */
.tbl td { font-size: calc(13px * var(--ui-scale)); font-family: var(--font-num); }
@media (max-width: 420px) {
  .tbl th, .tbl td { font-size: calc(13px * var(--ui-scale)); padding-top: calc(9px * var(--ui-scale)); padding-bottom: calc(9px * var(--ui-scale)); }
}
@media (max-width: 380px) {
  .match .side .nm { font-size: calc(13px * var(--ui-scale)); }
  .match .score { font-size: calc(17px * var(--ui-scale)); }
}
@media (max-width: 340px) {
  .match { padding-top: calc(12px * var(--ui-scale)); padding-bottom: calc(12px * var(--ui-scale)); }
  .match .side .crest { height: calc(14px * var(--ui-scale)); }
}

/* ---------- «Путь по сезону» (h2h): мини-график мест по турам ----------
   Две линии — та же цветовая пара, что и полоски сравнения выше: левый клуб —
   акцент, правый — accent-2 (цвета клубов на тёмной карточке местами не читаются).
   Подписи живут ВНЕ <svg>: график растянут по ширине карточки через
   preserveAspectRatio=none, и текст внутри него вытянуло бы. */
.path { display: flex; gap: 8px; padding: 2px 14px 0; }
.path-y { display: flex; flex-direction: column; justify-content: space-between; align-items: flex-end; padding: 6px 0 24px; color: var(--faint); font-size: 10px; font-weight: var(--w-strong); font-variant-numeric: tabular-nums; }
.path-plot { flex: 1 1 auto; min-width: 0; }
.path-plot svg { display: block; width: 100%; height: calc(112px * var(--ui-scale, 1)); }
.path .l1, .path .l2 { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.path .l1 { stroke: var(--accent); }
/* l2 — второй клуб: направление задаёт, не повторять акцент */
.path .l2 { stroke: var(--accent-2); }
.path .grid, .path .xmark { stroke-width: 1; vector-effect: non-scaling-stroke; }
.path .grid { stroke: var(--line-2); }
.path .xmark { stroke: var(--line); stroke-dasharray: 3 3; }
.path .dot1 { fill: var(--accent); }
.path .dot2 { fill: var(--accent-2); }
.path-x { display: flex; justify-content: space-between; padding-top: 4px; color: var(--faint); font-size: 10px; font-weight: var(--w-strong); }
.path-note { display: flex; flex-wrap: wrap; gap: 4px 14px; padding: 4px 14px 12px; color: var(--muted); font-size: 11.5px; }
.path-note .k { display: inline-block; width: 9px; height: 3px; border-radius: var(--r-mark); margin-right: 5px; vertical-align: 2px; background: var(--accent); }
.path-note .k2 { background: var(--accent-2); }


/* ---------- Лист строки таблицы: путь по последним турам ----------
   Статичный блок внутри .sheet (L.sheet принимает item.html). Линия — декор,
   поэтому aria-hidden: настоящие числа подписаны строкой .spark-ticks под ней,
   а ось перевёрнута (1-е место сверху, как в таблице). preserveAspectRatio=none
   растягивает линию по ширине листа — штрих спасает non-scaling-stroke. */
.spark { display: grid; gap: 3px; padding: 8px 12px 10px; border-radius: var(--r-spark); background: var(--card-2); }
.spark-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; min-width: 0; }
.spark-top b { font-family: var(--font-display); font-weight: var(--w-strong); font-size: 14px; overflow-wrap: anywhere; }
.spark-top i { font-style: normal; color: var(--muted); font-size: 10.5px; font-weight: var(--w-strong); letter-spacing: .02em; white-space: nowrap; }
.spark-line { display: block; width: 100%; height: 40px; }
.spark-line polyline { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.spark-ticks { display: flex; justify-content: space-between; gap: 4px; color: var(--muted); font-size: 10.5px; font-weight: var(--w-strong); font-variant-numeric: tabular-nums; }
/* график: точка тура — круглая кнопка поверх самой линии (22 px под палец).
   Позиция — margin, не transform: в этой части файла transform запрещён. */
.spark-plot { position: relative; }
.spark-dot { position: absolute; width: 22px; height: 22px; margin: -11px 0 0 -11px; padding: 0; border: 0; border-radius: 50%; background: transparent; cursor: pointer; }
.spark-dot::after { content: ''; position: absolute; inset: 7px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 1.5px var(--card-2); }
/* точка тура — цветом итога: зелёная победа, красная поражение, жёлтая ничья.
   Несыгранный тур остаётся цветом акцента: красить его нечем. */
.spark-dot.win::after { background: var(--res-win); }
.spark-dot.loss::after { background: var(--res-loss); }
.spark-dot.draw::after { background: var(--res-draw); }
.spark-dot:active::after { background: var(--text); }
/* окно тура: размытие фона под листом и карточка матча */
.sheet-wrap.blur .sheet-back { -webkit-backdrop-filter: blur(6px) saturate(1.1); backdrop-filter: blur(6px) saturate(1.1); }
.tm { position: relative; overflow: hidden; display: grid; gap: 4px; padding: 4px 12px 10px; text-align: center; cursor: pointer; }
/* Итог матча словами и цветом: «Балтика выиграла» — зелёным, «проиграла» —
   красным, «сыграла вничью» — жёлтым. Те же цвета, что в форме команды (В/Н/П):
   человек уже выучил их по таблице. Знак победителя здесь не нужен — он не
   отвечает на вопрос «кто проиграл». */
.tm-res { position: relative; display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 2px 0 6px; font-weight: var(--w-strong); font-size: calc(14px * var(--ui-scale)); }
.tm-res i { width: 8px; height: 8px; flex: none; border-radius: var(--r-form); background: var(--muted); }
/* цвет итога — отдельные токены: --draw у направлений серый или вовсе
   прозрачный (он для клеток формы), а фраза «сыграла вничью» должна читаться */
.tm-res.win { color: var(--res-win); } .tm-res.win i { background: var(--res-win); }
.tm-res.loss { color: var(--res-loss); } .tm-res.loss i { background: var(--res-loss); }
.tm-res.draw { color: var(--res-draw); } .tm-res.draw i { background: var(--res-draw); }
.tm-res.none { color: var(--muted); }
.tm-vs, .tm-when { position: relative; }
.tm-vs { display: flex; align-items: center; justify-content: center; gap: 10px; }
/* пункт листа со знаками клубов: текст не должен вытеснять эмблемы */
.sheet-item.with-icon { display: flex; align-items: center; gap: 8px; }
.si-icon { display: inline-flex; align-items: center; gap: 2px; flex: none; }
.si-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* без text-transform: проверка масштаба запрещает в этой части файла любое
   transform (да и прописные в окне тура ни к чему) */
.tm-vs b { font-family: var(--font-name); font-weight: var(--w-strong); font-size: 14px; }
.tm-vs i { font-style: normal; font-family: var(--font-num); font-variant-numeric: tabular-nums; font-weight: var(--w-display); font-size: 19px; color: var(--accent); }
.tm-when { color: var(--muted); font-size: 11.5px; font-weight: var(--w-cap); letter-spacing: .02em; }
.spark-ticks .now { color: var(--text); }
.spark-ticks .nil { color: var(--faint); }
.spark-trend { font-size: 11.5px; font-weight: var(--w-strong); }
.spark-trend.up { color: var(--win); }
.spark-trend.down { color: var(--loss); }
.spark-trend.flat { color: var(--muted); }
.spark-who { font-size: 11.5px; color: var(--muted); overflow-wrap: anywhere; }

/* ---------- Компактные списки (настройки → плотность) ----------
   --ui-scale отвечает за РАЗМЕР текста, этот режим — за число строк на экран:
   один множитель --dense режет только вертикальные отступы строк и карточек.
   Типографика, ширины колонок, радиусы и цвета не меняются — список остаётся
   тем же списком, просто в него влезает в полтора раза больше строк.
   Specificity у html.ui-compact выше, чем у базовых правил и у секции масштаба,
   поэтому порядок в файле не важен. */
html.ui-compact { --dense: .6; }
html.ui-compact .card, html.ui-compact .hint, html.ui-compact .controls { margin-bottom: calc(14px * var(--ui-scale, 1) * var(--dense)); }
html.ui-compact .tiles { row-gap: calc(14px * var(--ui-scale, 1) * var(--dense)); margin-bottom: calc(14px * var(--ui-scale, 1) * var(--dense)); }
html.ui-compact .card-head { padding-top: calc(14px * var(--ui-scale, 1) * var(--dense)); padding-bottom: calc(14px * var(--ui-scale, 1) * var(--dense)); }
html.ui-compact .tile { padding-top: calc(18px * var(--ui-scale, 1) * var(--dense)); padding-bottom: calc(18px * var(--ui-scale, 1) * var(--dense)); }
html.ui-compact .tbl th, html.ui-compact .tbl td { padding-top: calc(10px * var(--ui-scale, 1) * var(--dense)); padding-bottom: calc(10px * var(--ui-scale, 1) * var(--dense)); }
html.ui-compact .scorer { padding-top: calc(12px * var(--ui-scale, 1) * var(--dense)); padding-bottom: calc(12px * var(--ui-scale, 1) * var(--dense)); }
html.ui-compact .match { padding-top: calc(13px * var(--ui-scale, 1) * var(--dense)); padding-bottom: calc(13px * var(--ui-scale, 1) * var(--dense)); }
html.ui-compact .day { padding-top: calc(10px * var(--ui-scale, 1) * var(--dense)); padding-bottom: calc(6px * var(--ui-scale, 1) * var(--dense)); }
html.ui-compact .player { padding-top: calc(7px * var(--ui-scale, 1) * var(--dense)); padding-bottom: calc(7px * var(--ui-scale, 1) * var(--dense)); }
html.ui-compact .squad .sq-head { padding-top: calc(12px * var(--ui-scale, 1) * var(--dense)); padding-bottom: calc(12px * var(--ui-scale, 1) * var(--dense)); }
html.ui-compact .event { padding-top: calc(6px * var(--ui-scale, 1) * var(--dense)); padding-bottom: calc(6px * var(--ui-scale, 1) * var(--dense)); }
html.ui-compact .h2h-row, html.ui-compact .prow, html.ui-compact .ptour-row { padding-top: calc(9px * var(--ui-scale, 1) * var(--dense)); padding-bottom: calc(9px * var(--ui-scale, 1) * var(--dense)); }
html.ui-compact .legend { padding-top: calc(12px * var(--ui-scale, 1) * var(--dense)); padding-bottom: calc(12px * var(--ui-scale, 1) * var(--dense)); }

/* Компьютер: колонка команды шире, и щит в 24 пикселя читается хуже, чем мог
   бы. На широком экране поднимаем слот — и эмблеме, и цветной плашке соседа,
   чтобы сравнение осталось честным. */
@media (min-width: 900px) {
  .tbl td.team-cell .crest { width: 24px; }
  .tbl td.team-cell .club-ico { height: calc(28px * var(--ui-scale, 1) * var(--ico-grow)); }
  .crest.club-ico { height: calc(30px * var(--ui-scale, 1) * var(--ico-grow)); }
  .crest.club-ico.sm { height: calc(21px * var(--ui-scale, 1) * var(--ico-grow)); }
}
