/*
 * Sports betting — Shell theme.
 *
 * Всё на переменных Shell (--bg, --surface, --line, --text, --muted, --accent),
 * поэтому одна и та же вёрстка автоматически подхватывает палитру бренда:
 * жёлтую у Rollzy и фиолетовую у brox.
 *
 * Устройство файла — от общего к частному: токены модуля, каркас, левая
 * колонка (табы, виды спорта, лиги, события), купон, история, выкуп.
 *
 * Из чего складывается «современность» — по разбору Stake и Rainbet:
 *
 *  1. СЧЁТ ВИДЕН ПО КОМАНДАМ, а не строкой «1-0» в подписи. Игрок смотрит
 *     на названия, а не на метаданные, поэтому счёт живёт в своей колонке
 *     напротив каждой команды.
 *  2. КОТИРОВКА — ДВУХСТРОЧНАЯ: подпись исхода мелким сверху, значение
 *     крупным снизу. Так подпись не спорит с ценой за внимание, и строка
 *     кнопок читается как таблица.
 *  3. ВСПЫШКА ПРИ ИЗМЕНЕНИИ ЦЕНЫ. На живом рынке котировка меняется
 *     постоянно, и без подсветки игрок не понимает, что цена ушла. Зелёная
 *     вспышка — рост, красная — падение. Это ключевая механика живых
 *     букмекеров, и без неё интерфейс выглядит мёртвым.
 *  4. ЖИВОЙ МИНУТА-БЕЙДЖ с пульсирующей точкой: состояние матча видно
 *     с первого взгляда, а не вычитывается из названия лиги.
 *  5. ЦИФРЫ ТАБЛИЧНЫЕ (tabular-nums). Котировки и счёт не должны «плясать»
 *     при смене значения — иначе строка дрожит на каждом обновлении.
 */

.sp-wrap,
.sp-slip,
.sp-league {
  /* Токены модуля. Держим локально, чтобы правка спорта не задевала Shell. */
  --sp-radius: 10px;
  --sp-radius-sm: 8px;
  --sp-radius-pill: 999px;
  --sp-gap: 10px;

  /* Высота контролов в строке фильтров: сегмент «Лайв / Линия / …», поиск и
     выбор формата. Один токен на все, потому что разъезжаются они молча: поиск
     остался 30px, пока сегмент вырос до 38, и строка читалась как кривая.
     Внутренние высоты считаются от неё: вкладка — минус паддинги и рамка
     сегмента, поле ввода — на всю высоту обёртки. */
  --sp-top-h: 38px;

  /* Кривые. Встроенные ease/ease-in-out слишком вялые: они медленно
     разгоняются, а именно первые сто миллисекунд решают, отзывчив интерфейс
     или «подвисает». Кривые взяты из набора Emil Kowalski (easing.dev). */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  /* Кривая выдвижной панели из Ionic: быстрый разгон и мягкая парковка.
     Пальцем панель именно так «отпускает» — без рывка в конце хода. */
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);

  /* Длительности. Всё интерфейсное держим короче 300 мс: 160 мс читается как
     «сразу», 400 — как «подожди». Отдельная длительность у нажатия, потому
     что отклик на палец обязан быть мгновенным, и отдельная у вспышки
     котировки — она гаснет медленнее, чем появляется. */
  --sp-t: 160ms var(--ease-out);
  --sp-t-fast: 110ms var(--ease-out);
  --sp-t-list: 200ms var(--ease-out);

  /* Типографика. Фиксированные px не масштабируются: на 360px подпись
     читается, на 1440 выглядит мелкой. clamp ведёт размер от узкого экрана к
     широкому без ступенек на брейкпоинтах. Границы подобраны по замерам
     прежних фиксированных размеров, чтобы плотность строки не поехала.
     Нижние границы подняты по замеру 28.09: подпись исхода давала 9.5px на
     390px и 10.5px на 1440, счётчики — 10.5px. Это не декоративная мета, а
     текст, который читают ПЕРЕД нажатием: какой это исход и сколько событий
     в виде спорта. WCAG минимума кегля не задаёт (критерий только о
     контрасте), поэтому ориентир — практический: подпись не мельче 11px,
     счётчик не мельче 12px. Дороже это не стоит: замер после правки на живой
     линии дал ноль переносов в подписях и рост высоты строки на 2.5px
     (63.4 → 66.1 на десктопе, 132.1 → 134.6 на 390px) — подпись «Больше 2.5»
     влезает в кнопку одной строкой. */
  --sp-fs-2xs: clamp(11.5px, 0.09vw + 11.2px, 12.5px);  /* подпись исхода */
  --sp-fs-xs: clamp(12px, 0.09vw + 11.7px, 13px);       /* счётчики, бейджи */
  --sp-fs-sm: clamp(12px, 0.14vw + 11.5px, 13.5px);    /* метаданные, подписи рынков */
  --sp-fs-md: clamp(13px, 0.19vw + 12.3px, 14.5px);    /* команды, значения котировок */
  --sp-fs-lg: clamp(14px, 0.19vw + 13.3px, 15.5px);    /* табы, заголовок купона */
  --sp-fs-xl: clamp(16px, 0.28vw + 15px, 18px);        /* итоговый коэффициент */

  /* Ритм. Шаг 4/8: горизонтальный отступ строки растёт от 12 до 16, а
     вертикальный остаётся в пределах 7-10 — строка события не «дышит» на
     широком экране и не сжимается до нечитаемой на узком. */
  --sp-pad-x: clamp(12px, 0.28vw + 11px, 16px);
  --sp-row-y: clamp(7px, 0.28vw + 6px, 10px);

  /* Кнопка котировки. На палец минимум 44px (гайдлайн Apple/Google по цели
     касания), на курсор столько не нужно: на десктопе палец не цель, а лишняя
     высота строки — потеря трети экрана в длинной линии. */
  --sp-odd-h: 38px;

  /* Шапка матча липкая, поэтому её высота известна заранее: табы рынков
     липнут ровно под ней. Мерить высоту в JS значило бы поставить липкость
     в зависимость от порядка выполнения скрипта. */
  --sp-mhead-h: 66px;

  /* Верхний отступ области прокрутки Shell (`.shell-main`: 18px, на телефоне
     14px). Единственное место, где спорт знает чужую геометрию, и знает
     осознанно: липкий элемент прижимается не к кромке области прокрутки, а к
     её content-box, то есть на этот отступ НИЖЕ кромки. Оставить это как есть
     нельзя: над закреплённой шапкой матча остаётся полоса высотой в отступ, и
     по ней проезжают кнопки котировок — выглядит как сбой вёрстки. Поэтому
     шапка липнет с отрицательным `top` и накрывает полосу собой.
     Если `.shell-main` сменит отступ, менять здесь. */
  --sp-scroll-pad: 18px;
}

/* Каркас. Колонок всегда ДВЕ: линия и купон.
 *
 * Рельс видов спорта, который раньше занимал третью колонку, убран из
 * страницы вовсе: категории теперь в левой навигации сайта. Три колонки не
 * нужны: на странице матча детей и так двое — линия и купон, а фильтр нужен
 * игроку разово, а не постоянно.
 */
.sp-wrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: var(--sec-gap-sm);
  align-items: start;
  /* Ширина колонки котировок в строке события. Фиксированная, а не auto:
     иначе у строки с исходом матча (три кнопки) и с тоталом (две) колонки
     разной ширины, и правая кромка «пляшет» по вертикали — линия читается
     как кривая. Объявлена на .sp-wrap, а не на .sp-league: событие лежит
     внутри лиги, и значение от ближайшего предка перебило бы переопределение
     на планшете. */
  --sp-odds-w: 204px;
  /* Ширина колонки времени в строке события: «28.09 19:00» при кегле 13px
     занимает ~78px, плюс воздух до кнопок котировок. */
  --sp-time-w: 88px;
}

.sp-main { min-width: 0; }

/* --- Переключатель линия / live и поиск -------------------------------- */

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

   Метрики строки — из макета: режимы слева, службы справа, между ними воздух,
   всё одной высоты 30px. Строка живёт в средней колонке, рядом с полосой
   видов спорта, и не выделяется ни фоном, ни рамкой: это фильтры линии, а не
   отдельная панель. Перенос разрешён — на планшете службы уезжают под режимы,
   а не вылезают за край колонки. */
.sp-top {
  display: flex;
  gap: var(--sp-gap);
  align-items: center;
  flex-wrap: wrap;
  padding-bottom: 10px;
  margin-bottom: var(--sp-gap);
  border-bottom: 1px solid var(--surface-2);
}

/* --- Переключатель линия / live и поиск -------------------------------- */

/* Переключатель режимов — сегмент по содержимому (как в макете): вкладок две,
   и растягивать их на всю строку незачем, свободное место отдаётся поиску.
   Фон сегмента — surface, подложка активной вкладки — surface-2: акцентный
   жёлтый здесь ничего не значит, а в строке рядом стоит такой же по весу
   селект формата, и два жёлтых пятна спорили бы друг с другом. */
.sp-tabs {
  display: inline-flex;
  gap: 3px;
  flex: 0 0 auto;
  min-width: 0;
  padding: 3px;
  /* 30px вкладка + 2×3 паддинга + 2×1 рамки = 38px сегмента. */
  height: var(--sp-top-h);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--sp-radius);
}

.sp-tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  flex: 0 0 auto;
  white-space: nowrap;
  /* Высота вкладки — от высоты сегмента, а не своя: так паддинги и рамка
     сегмента не могут разойтись с вкладкой при правке одной из них. */
  height: calc(var(--sp-top-h) - 8px);
  /* Область нажатия расширяется псевдоэлементом ниже, а НЕ высотой вкладки.
     Здесь уже была попытка поднять вкладку до 44 px «по минимуму касания» —
     и она сломала вид: сегмент на десктопе 38 px, вкладка в нём стала 44 и
     вылезла за границы, вкладки «поплыли». Минимум касания — про область
     нажатия, а не про пиксели самой кнопки. */
  position: relative;
  padding: 0 14px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: var(--sp-fs-sm);
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--sp-t), color var(--sp-t);
}

/* Зона касания вкладки: 30 px вкладки + 7 px сверху и снизу = 44 px минимума.
   Псевдоэлемент лежит внутри ссылки, поэтому нажатие по нему — это нажатие
   по вкладке, а вёрстка не двигается ни на пиксель. */
.sp-tab::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -7px;
  bottom: -7px;
}

.sp-tab:hover { color: var(--text); }

.sp-tab.is-active {
  background: var(--surface-2);
  color: var(--text);
}

/* Иконка в переключателе линия/live: часы у прематча. Лайв использует
   пульсирующую точку — она и есть его иконка состояния. */
.sp-tab-ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.sp-tab-ico svg {
  width: 15px;
  height: 15px;
}

/* --- Поиск по линии --------------------------------------------------- */

.sp-search {
  position: relative;
  display: flex;
  align-items: center;
  gap: 7px;
  /* Поиск забирает свободное место и ужимается первым: селект формата держит
     своё. Метрики и минимум ширины — из макета: поле стоит в строке фильтров
     рядом с сегментом режимов, и на телефоне оно уезжает своей строкой. */
  flex: 1 1 240px;
  min-width: 200px;
  height: var(--sp-top-h);
  padding: 0 11px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--sp-radius-sm);
  transition: border-color var(--sp-t);
}

.sp-search:focus-within { border-color: var(--accent); }

.sp-search svg { width: 15px; height: 15px; flex: 0 0 auto; color: var(--muted); }

.sp-search input {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: var(--sp-fs-sm);
}

/* Встроенное кольцо гасим только там, где своё не нужно: у мыши оно рисуется
   вокруг поля внутри скруглённой рамки и читается как вторая рамка. При
   клавиатуре кольцо остаётся — иначе поле поиска не видно в обходе по Tab. */
.sp-search input:focus:not(:focus-visible) { outline: none; }

.sp-search input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 0;
  border-radius: var(--sp-radius-sm);
}

.sp-search input::placeholder { color: var(--muted); }

/* Крестик очистки у `type="search"` браузер рисует сам, и он не
   стилизуется: свой убираем, свой рисуем — иначе их было бы два. */
.sp-search input::-webkit-search-cancel-button { display: none; }

.sp-search-clear {
  flex: 0 0 auto;
  /* Крестик живёт внутри поля высотой 30px: 32px из прежней строки в него не
     влезали и растягивали поле. Цель для пальца остаётся — 24px, а на
     телефоне поле выше (см. медиазапрос ниже) и крестик растёт вместе с ним. */
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 0;
  border-radius: var(--sp-radius-sm);
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  transition: color var(--sp-t), transform var(--sp-t-fast);
}

/* Крестик появляется только при введённом запросе, и решает это JS: он ставит
   атрибут `hidden`. Правило нужно потому, что `display: grid` из класса
   перебивает `display: none` от атрибута (стили автора сильнее стилей
   браузера), и без него крестик висел в пустом поле всегда. */
.sp-search-clear[hidden] { display: none; }

/* Точка «идёт прямо сейчас»: единственный элемент, которому позволено
   мигать. Всё остальное в интерфейсе статично — иначе мигает всё. */
.sp-live-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--danger);
  animation: sp-pulse 1.5s ease-in-out infinite;
}

@keyframes sp-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: .25; }
}

/* --- Категории рынков на странице матча ------------------------------- */

/* Верхняя строка страницы матча: назад + переключатель формата коэффициентов.
   Тот же селект, что в шапке линии — выбор общий (localStorage). */
.sp-event-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: var(--sp-gap);
}

.sp-event-top .sp-back { margin-bottom: 0; }

/* Возврат к линии. Кнопкой в панели навигации не обойтись: страницу матча
   открывают из списка, и вернуться нужно ровно туда, откуда пришли. */
.sp-back {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  margin-bottom: var(--sp-gap);
  padding: 7px 14px;
  border: 1px solid var(--line);
  border-radius: var(--sp-radius-pill);
  background: var(--surface);
  color: var(--muted);
  font-size: var(--sp-fs-sm);
  font-weight: 600;
  text-decoration: none;
  transition: border-color var(--sp-t), color var(--sp-t), transform var(--sp-t-fast);
}

/* Табы вместо простыни рынков. У матча бывает 40+ рынков, и без категорий
   игрок видит стену однотипных строк, в которой «Тотал 2.5» стоит впереди
   «1X2». Порядок категорий — от популярной к редкой, как на Stake.
 *
 * Табы липнут под шапкой матча: активная категория — это состояние, и оно не
 * должно теряться из виду на тридцатой строке росписи. */
.sp-mk-tabs {
  position: sticky;
  /* Табы липнут под шапкой: от её высоты отнимаем отступ области прокрутки,
     потому что липкость в этой области отсчитывается от content-box, а не от
     кромки (см. `--sp-scroll-pad`). */
  top: calc(var(--sp-mhead-h) - var(--sp-scroll-pad));
  z-index: 3;
  display: flex;
  gap: 6px;
  overflow-x: auto;
  margin-bottom: var(--sp-gap);
  padding: 6px 0 8px;
  background: var(--bg);
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.sp-mk-tabs::-webkit-scrollbar { display: none; }

.sp-mk-tab {
  flex: 0 0 auto;
  min-height: 34px;
  padding: 7px 14px;
  border: 1px solid var(--line);
  border-radius: var(--sp-radius-pill);
  background: var(--surface);
  color: var(--muted);
  font: inherit;
  font-size: var(--sp-fs-sm);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color var(--sp-t), background var(--sp-t), color var(--sp-t), transform var(--sp-t-fast);
}

.sp-mk-tab.is-active {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, var(--surface));
  color: var(--accent);
}

/* Число рынков в категории: без него игрок не знает, стоит ли открывать
   «Четверти» — там может быть один рынок, а может двенадцать. */
.sp-mk-tab-count {
  margin-left: 6px;
  color: var(--muted);
  font-size: var(--sp-fs-xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.sp-mk-tab.is-active .sp-mk-tab-count { color: inherit; opacity: .7; }

/* --- Лиги и события --------------------------------------------------- */

/* Секция вида спорта в смешанной выдаче: подпись вида вынесена в заголовок
   над его лигами, а не повторяется под каждым матчем. По иерархии выше лиги,
   поэтому крупнее и жирнее. */
.sp-sport-section {
  margin-bottom: calc(var(--sp-gap) * 1.5);
}

.sp-sport-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 2px 2px 10px;
  color: var(--text);
  font-size: var(--sp-fs-lg);
  font-weight: 700;
}

.sp-sport-head .sp-sport-emoji {
  width: 18px;
  flex: 0 0 auto;
  font-size: 17px;
  line-height: 1;
  text-align: center;
  opacity: .95;
}

.sp-sport-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Счётчик событий вида спорта: «Футбол (22)». Цифра — не украшение, по ней
   игрок решает, открывать вид или нет, поэтому она обязана проходить AA как
   обычный мелкий текст (4.5:1), а не как «почти декор».

   Было `--muted` на `--surface-2` = #848e9c на #2b3139 = 3.95:1 — не проходит
   (замер аудита подтверждён 28.09 на живом проде: 3.95). Цвет не новый и не
   произвольный: `--muted`, подмешанный к `--text`, — самый светлый оттенок
   той же серой ступени палитры Shell, так что на фиолетовой теме brox
   поведение то же (пересчитывается от её переменных, а не от хардкода).
   При 70% мута получается 5.6:1 — проходит с запасом на любую из тем, тогда
   как 80% давали ровно 5.0, а хардкод вроде #98a1ad сломал бы темизацию. */
.sp-sport-count {
  flex: 0 0 auto;
  padding: 1px 8px;
  border-radius: var(--sp-radius-pill);
  background: var(--surface-2);
  color: color-mix(in srgb, var(--muted) 70%, var(--text));
  font-size: var(--sp-fs-xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.sp-league {
  margin-bottom: var(--sp-gap);
  border: 1px solid var(--line);
  border-radius: var(--sp-radius);
  background: var(--surface);
  /* `clip`, а не `hidden`: скруглённые углы должны обрезать подсветку строк
     (она прямоугольная), но `hidden` заодно делает группу областью прокрутки —
     и липкая шапка лиги перестаёт липнуть, потому что её липкость начинает
     считаться от неподвижной внутренней области. Проверено замером: при
     `hidden` шапка уезжает вместе с группой, при `clip` — остаётся на кромке.
     Заодно `clip` не создаёт лишний слой прокрутки на 260 групп. */
  overflow: clip;
}

/*
 * Шапка лиги липнет к верху списка: в длинной линии игрок прокручивает
 * десяток событий и теряет, какая это лига. У Stake и Rainbet шапка
 * остаётся на виду, и это заметно экономит внимание.
 */
.sp-league-head {
  position: sticky;
  /* Как и шапка матча: липкость считается от content-box области прокрутки,
     поэтому отрицательный `top` — чтобы полоса её отступа не осталась открытой
     (см. `--sp-scroll-pad`). */
  top: calc(var(--sp-scroll-pad) * -1);
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  /* 44 px — минимум касания. Замер на телефоне показывал 42 px, и промах
     по шапке сворачивал не ту лигу: попасть в неё нужно на ходу. */
  min-height: 44px;
  padding: clamp(9px, 0.3vw + 8px, 12px) var(--sp-pad-x);
  border: 0;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  color: var(--muted);
  font: inherit;
  font-size: var(--sp-fs-sm);
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  transition: background var(--sp-t), color var(--sp-t);
}

/* Шапка рынка не липнет: на странице матча сверху уже закреплён заголовок
   матча, и вторая липкая шапка наезжала бы на него при прокрутке. */
.sp-league-head.is-market { position: static; }

/* Свёрнутый рынок приглушаем: так видно, что группа закрыта, а не пуста. */
.sp-league.is-collapsed > .sp-league-head.is-market { color: var(--muted); }

.sp-league-flag {
  font-size: 14px;
  line-height: 1;
}

.sp-league-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sp-league-count {
  padding: 1px 7px;
  border-radius: var(--sp-radius-pill);
  background: var(--bg-deep);
  color: var(--muted);
  font-size: var(--sp-fs-xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.sp-league-caret {
  width: 12px;
  height: 12px;
  opacity: .6;
  transition: transform var(--sp-t);
}

.sp-league.is-collapsed .sp-league-caret { transform: rotate(-90deg); }

.sp-league.is-collapsed .sp-league-body { display: none; }

/* Строка события: команды, время и котировки в трёх колонках.
 *
 * Колонок ровно три, потому что детей ровно три: команды, время, котировки.
 * Здесь стояло правило на две колонки «для прематча» — мол, время начала в
 * прематче не нужно. Но время в прематче как раз нужно (по нему игрок
 * выбирает, успеет ли поставить), и элемент в разметке оставался: третий
 * ребёнок не помещался в две колонки и уезжал во ВТОРУЮ строку, на всю
 * ширину. Строка прематча выходила вдвое выше живой — 139 пикселей против
 * 60, — а котировки стояли отдельной строкой под командами, растянутые на
 * тысячу пикселей. Это и читалось как «2013 год».
 */
.sp-event {
  display: grid;
  /* Третья колонка — «не шире, чем нужно»: на узком экране она ужимается,
     а не выдавливает строку за край. */
  /* Колонка времени — по содержимому, а не «на глазок». В прематче здесь
     стоит дата с часами («28.09 19:00»), и в прежних 58px она не влезала:
     строка вылезала в зазор и упиралась в первую кнопку котировок — читалось
     как «всё вплотную». Токен объявлен рядом с токеном котировок: обе ширины
     меняются вместе, потому что обе стоят в одной строке. */
  grid-template-columns: minmax(0, 1fr) var(--sp-time-w) minmax(0, var(--sp-odds-w));
  gap: 12px;
  align-items: center;
  padding: var(--sp-row-y) var(--sp-pad-x);
  border-bottom: 1px solid var(--line);
  transition: background var(--sp-t);
}

.sp-event:last-child { border-bottom: 0; }

.sp-teams {
  min-width: 0;
  /* Название матча — ссылка на полную роспись. Ссылка без подчёркивания и в
     цвете текста, но с подчёркиванием по наведению: иначе подчёркнутые
     сорок строк подряд превращаются в шум, а без подсказки никто не догадается
     кликнуть. */
  display: block;
  color: inherit;
  text-decoration: none;
}

.sp-team-line {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

/* Шаг 4: строки команд стоят парами, и просвет между ними — тот минимум,
   при котором две строки ещё читаются как разные команды, а не как абзац. */
.sp-team-line + .sp-team-line { margin-top: 4px; }

.sp-team {
  flex: 1;
  min-width: 0;
  color: var(--text);
  font-size: var(--sp-fs-md);
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Кто ведёт — тот и заметен. Толщина, а не цвет: цвет в этом интерфейсе
   занят акцентом и статусами. */
.sp-team-line.is-leading .sp-team { font-weight: 700; }

.sp-team-score {
  min-width: 14px;
  color: var(--text);
  font-size: var(--sp-fs-md);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: right;
  transition: color var(--sp-t), transform var(--sp-t);
}

/* Гол — единственное, что игрок ищет взглядом на живой линии, поэтому счёт
   подсвечивается акцентом. Держим подсветку дольше вспышки котировки (её
   снимает JS): цену игрок и так перепроверит, а гол иначе пролистает. */
.sp-team-score.is-scored,
.sp-score.is-scored {
  transition-duration: 0ms;
  color: var(--accent);
}

.sp-team-line.is-leading .sp-team-score { color: var(--up); }

/* Подсветка гола сильнее роли «ведёт»: во время вспышки зелёный лидера
   уступает акценту, иначе вспышка на нём была бы незаметна. */
.sp-team-line.is-leading .sp-team-score.is-scored { color: var(--accent); }

.sp-meta {
  margin-top: 4px;
  color: var(--muted);
  font-size: var(--sp-fs-xs);
  line-height: 1.2;
}

.sp-score {
  color: var(--accent);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  border-radius: 4px;
  transition: color var(--sp-t);
}

/* Колонка времени: минута у live, время начала у прематча. */
.sp-ev-time {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  color: var(--muted);
  font-size: var(--sp-fs-sm);
  font-variant-numeric: tabular-nums;
  text-align: center;
  white-space: nowrap;
}

/* Клетка времени лайв-строки повторяет ритм прематча: подпись сверху, значение
   под ней. Подпись «Лайв» — та же тихая серая строка, что «Сегодня» у прематча
   (класс .sp-ev-time-label общий), а значение — капсула с минутой. Класс
   `is-live` остаётся хуком для строки: по нему видно, что клетку собрал лайв,
   а не прематч. */

/* Лайв-капсула: пульсирующая точка и минута в ней. Фон — surface-2, а не
   bg-deep кнопок котировок: капсула не нажимается, и выглядеть кнопкой ей
   незачем. Из красного в клетке остаётся только точка: красная капсула с
   жирной красной минутой перекрикивала и названия команд, и кэфы, хотя лайв
   виден по активной вкладке раздела, а капсула нужна лишь чтобы глаз находил
   матч, который идёт прямо сейчас. */
.sp-live-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 6px;
  border-radius: var(--sp-radius-pill);
  background: var(--surface-2);
  color: var(--text);
  font-size: var(--sp-fs-xs);
  font-weight: 700;
  letter-spacing: .02em;
  line-height: 1.3;
  /* Цифры минуты — табличные: «8'» и «77'» одной ширины, и капсула не дёргает
     строку, когда минута меняется на каждой перерисовке. */
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.sp-live-badge .sp-live-dot {
  width: 5px;
  height: 5px;
  flex: 0 0 auto;
}

.sp-ev-time-label {
  font-size: var(--sp-fs-2xs);
  letter-spacing: .03em;
  opacity: .75;
  text-transform: uppercase;
}

/* --- Шапка матча на странице росписи -------------------------------- */

/* Липкая шапка с командами, счётом и минутой. Так показывает матч bet365:
   роспись бывает в четыре экрана, и к её середине игрок уже не помнит, что
   там со счётом, а от счёта зависит, нужен ли ему тотал.
 *
 * Высота фиксирована и лежит в токене: под ней липнут табы рынков, и это
 * единственный способ поставить их ровно без замера высоты в JS. */
.sp-match {
  position: sticky;
  /* Отрицательный `top` — чтобы шапка накрыла полосу отступа области
     прокрутки, по которой иначе проезжали бы котировки (см. `--sp-scroll-pad`).
     Пока страница не прокручена, липкость не включается вовсе: шапка стоит в
     потоке под ссылкой «Назад», и её положение не меняется. */
  top: calc(var(--sp-scroll-pad) * -1);
  z-index: 4;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  height: var(--sp-mhead-h);
  padding: 0 var(--sp-pad-x);
  border: 1px solid var(--line);
  border-radius: var(--sp-radius);
  background: var(--surface);
  overflow: hidden;
}

.sp-match-league {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  color: var(--muted);
  font-size: var(--sp-fs-xs);
  font-weight: 600;
}

.sp-match-league .sp-league-name { font-size: inherit; }

.sp-match-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.sp-match-name {
  color: var(--text);
  font-size: var(--sp-fs-md);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sp-match-row > .sp-match-name:last-child { text-align: right; }

/* Счёт — главное число шапки: он крупнее имён команд и стоит в акценте. */
.sp-match-score {
  min-width: 46px;
  padding: 2px 8px;
  border-radius: var(--sp-radius-sm);
  background: var(--bg-deep);
  color: var(--accent);
  font-size: var(--sp-fs-lg);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  text-align: center;
  transition: color var(--sp-t), background var(--sp-t);
}

.sp-match-score.is-scored {
  transition-duration: 0ms;
  background: var(--accent);
  color: var(--ink);
}

/* В прематче центр строки занимает время начала, а не счёт. Акцентная
   подложка там не нужна: счёт меняется, и его надо заметить, а время —
   справка, которая не меняется никогда. */
.sp-match-score.is-time {
  background: transparent;
  color: var(--muted);
  font-weight: 600;
}

/* На узком экране название лиги прячем: игрок пришёл сюда из этой лиги и
   помнит её, а место в шапке нужнее командам и минуте. */
.sp-match-time {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  color: var(--muted);
  font-size: var(--sp-fs-xs);
  font-weight: 600;
}

/* Правый край строки лиги: минута и кнопки трекера/стрима. Один контейнер,
   чтобы минута не отрывалась от визуализации на перерисовке. */
.sp-match-side {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.sp-match-actions {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* Кнопки трекера/стрима внутри шапки — компактные, без громоздкой подложки. */
.sp-match-actions .sp-visual-btn {
  padding: 4px 10px;
  background: transparent;
  font-size: var(--sp-fs-sm);
  font-weight: 600;
}

@media (max-width: 560px) {
  .sp-match-actions .sp-visual-label { display: none; }
}

/* Роспись без вкладок: первая группа рынков иначе упиралась бы в шапку.
   Отступ именно на следующем элементе, а не `margin-bottom` у шапки: у табов
   свой `top` от её высоты, и зазор под липкой шапкой показывал бы линию. */
.sp-match + .sp-league { margin-top: var(--sp-gap); }

/* --- Кнопки котировок ------------------------------------------------- */

.sp-odds { display: flex; gap: 6px; }

/* В строке события кнопки делят фиксированную колонку поровну: и у исхода
   матча (три кнопки), и у тотала (две) правая кромка одна и та же. */
.sp-event .sp-odd { flex: 1 1 0; min-width: 0; }

/* Кнопка котировки — главный элемент интерфейса, поэтому она читается как
   ячейка таблицы: подпись сверху, цена снизу, обе по центру, числа табличные.
   Ширина минимальная фиксированная: в ряду из трёх кнопок подпись «1 / X / 2»
   занимает разное место, и без общей минимальной ширины кнопки разъезжаются. */
.sp-odd {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-width: 64px;
  min-height: var(--sp-odd-h);
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: var(--sp-radius-sm);
  background-color: var(--bg-deep);
  color: var(--text);
  font: inherit;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
  text-align: center;
  /* Цвет идёт за вспышкой цены, transform — за нажатием. Ширину, отступы и
     высоту не трогаем: анимация вёрстки — это перерасчёт всей строки, а строк
     в линии сотни. */
  transition: border-color var(--sp-t), background-color var(--sp-t), transform var(--sp-t-fast);
}

.sp-odd-label {
  color: var(--muted);
  font-size: var(--sp-fs-2xs);
  font-weight: 600;
  letter-spacing: .02em;
  line-height: 1;
}

.sp-odd-value {
  font-size: var(--sp-fs-md);
  font-weight: 700;
  line-height: 1.15;
  /* Цена — одна строка всегда: перенос удлинил бы строку события, а строк в
     линии сотни. Длинное значение ужимает `.is-sm` / `.is-xs` / `.is-xxs`. */
  white-space: nowrap;
}

.sp-odd.is-picked {
  border-color: var(--accent);
  background-color: var(--accent);
  color: var(--ink);
}

/* Ступени кегля под длину цены. Дробный формат даёт «178/100», американский
   «+1200» — в кнопку шириной 64px это не влезает, и цена наезжала на соседнюю.
   Вместе с кеглем ужимаются боковые отступы: у длинной цены каждый пиксель
   отступа — отнятый у цифр. Пороги задаёт `oddsSizeClass` в sports.js. */
.sp-odd.is-sm .sp-odd-value { font-size: var(--sp-fs-sm); }
.sp-odd.is-xs .sp-odd-value { font-size: var(--sp-fs-xs); letter-spacing: -.01em; }
.sp-odd.is-xxs .sp-odd-value { font-size: var(--sp-fs-2xs); letter-spacing: -.01em; }

/* Подпись выбранного исхода — тёмная краска в акценте, но не настолько
   прозрачная, как раньше: 62% прозрачности давали на фиолетовой палитре
   подпись, которую приходилось вглядываться. */
.sp-odd.is-picked .sp-odd-label { color: color-mix(in srgb, var(--ink) 72%, var(--accent)); }

.sp-odd:disabled {
  opacity: .4;
  cursor: not-allowed;
}

/* Приостановленный рынок: у живых букмекеров цена «замирает» на голах и
   удалениях. Игрок должен видеть, что это пауза, а не поломка. */
.sp-odd.is-suspended {
  border-style: dashed;
  color: var(--muted);
}

/*
 * Вспышка смены цены.
 *
 * Здесь была анимация с keyframes на 1.1 с — и она давала ровно тот дефект,
 * от которого уходят: keyframes при повторном срабатывании стартуют с нуля, а
 * цена на живой линии меняется чаще, чем успевает догореть подсветка, поэтому
 * вспышка дёргалась. Переход доводит текущий цвет до нового, а не начинает
 * заново, и вдобавок вдвое короче: подсветка держится около полусекунды, и
 * этого достаточно, чтобы заметить изменение.
 *
 * Класс снимает JS: удержание задаёт таймер, а не CSS, иначе класс остался бы
 * висеть и следующее изменение цены уже ничего не подсветило бы (класс-то уже
 * стоит). Пока класс есть, длительность перехода нулевая — подсветка обязана
 * появиться мгновенно; гаснет она уже обычными 160 мс базового правила.
 */
.sp-odd.is-up,
.sp-odd.is-down { transition-duration: 0ms; }

.sp-odd.is-up {
  border-color: var(--up);
  background-color: color-mix(in srgb, var(--up) 30%, var(--bg-deep));
}

.sp-odd.is-down {
  border-color: var(--danger);
  background-color: color-mix(in srgb, var(--danger) 30%, var(--bg-deep));
}

/* Ряд внутри рынка: слева линия, справа кнопки исходов.
 *
 * Так показан тотал в bet365: одна строка — одна линия. Раньше линия была
 * склеена с подписью исхода («Больше 2.5»), и чтобы выбрать нужный тотал из
 * двенадцати, игрок читал двенадцать подписей подряд. В ровной колонке
 * чисел нужная линия находится взглядом, а подпись становится общей для
 * всего рынка: «Больше» / «Меньше» — и так понятно.
 */
.sp-mk-row {
  display: grid;
  grid-template-columns: 66px minmax(0, 1fr);
  align-items: center;
  gap: 10px;
  padding: 5px var(--sp-pad-x);
  border-bottom: 1px solid var(--line);
}

.sp-mk-row:last-child { border-bottom: 0; }

/* Рынок без линии — исход матча. Колонка под число не нужна, кнопки
   занимают всю ширину. */
.sp-mk-row.is-whole { grid-template-columns: minmax(0, 1fr); }

.sp-mk-line {
  color: var(--muted);
  font-size: var(--sp-fs-sm);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

/* Число колонок приходит из разметки: у тотала исходов два, у исхода
   матча три, и растягивать две кнопки на три колонки значило бы оставить
   дырку справа. */
.sp-mk-row .sp-odds {
  display: grid;
  grid-template-columns: repeat(var(--sp-cols, 2), minmax(0, 1fr));
  gap: 6px;
}

.sp-mk-row .sp-odd { min-width: 0; }

/* --- Служебные состояния --------------------------------------------- */

/* Пустое состояние: значок, причина и что делать дальше.
 *
 * Раньше здесь была одна серая строка, и она одинаково выглядела и когда
 * линия пуста, и когда поиск ничего не нашёл, и когда купон пуст. Игрок
 * читал «Сейчас нет событий» и не понимал, ждать, искать или кликать. */
.sp-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: clamp(28px, 6vw, 44px) 16px;
  color: var(--muted);
  font-size: var(--sp-fs-sm);
  line-height: 1.45;
  text-align: center;
}

.sp-empty-icon { display: block; margin-bottom: 2px; color: var(--muted); opacity: .55; }
.sp-empty-icon svg { width: 32px; height: 32px; }

.sp-empty-title { color: var(--text); font-size: var(--sp-fs-md); font-weight: 600; }

/* Длину строки держим до 34 знаков: подсказка в две полные строки читается,
   в четыре — уже нет, её пролистывают. */
.sp-empty-hint { max-width: 34ch; }

.sp-empty-action {
  margin-top: 8px;
  padding: 9px 18px;
  border: 1px solid var(--line);
  border-radius: var(--sp-radius-pill);
  background: var(--surface-2);
  color: var(--text);
  font: inherit;
  font-size: var(--sp-fs-sm);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: border-color var(--sp-t), background var(--sp-t), transform var(--sp-t-fast);
}

/* Пустой купон — узкая колонка справа: большие отступы здесь оставляют
   подсказку в середине пустоты, поэтому ужимаем их вдвое. */
.sp-empty--sm { padding: 26px 16px; gap: 4px; }

/* Нет линии по событию — это состояние, а не пустая кнопка. */
.sp-muted {
  padding: 0 4px;
  color: var(--muted);
  font-size: var(--sp-fs-sm);
}

/* Служебный текст для скринридера. Нужен своим классом, а не утилитой Shell:
   правка спорта не должна зависеть от того, есть ли утилита в чужом файле. */
.sp-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Смена списка.
 *
 * innerHTML перерисовывается каждые 20 секунд, и до этой правки DOM
 * пересоздавался одним рывком: сотни строк менялись в одном кадре, а взгляд
 * не успевал понять, что вообще изменилось. Теперь список входит приглушённым
 * и проявляется за 200 мс — переход маскирует подмену.
 *
 * Blur — только на входе данных после скелетона и только на широком экране.
 * Фильтр на контейнере, внутри которого живут липкие шапки лиг и табы, стоит
 * дорого и в Safari создаёт новый containing block; во время опроса линии
 * игрок может стоять в середине росписи, и подмена липких шапок обошлась бы
 * дороже, чем даёт размытие. На входе же список всегда на первом экране, где
 * подмены липких элементов не видно.
 */
.sp-list { transition: opacity var(--sp-t-list), filter var(--sp-t-list); }

.sp-list.is-refresh {
  transition-duration: 0ms;
  opacity: .7;
}

.sp-list.is-enter {
  transition-duration: 0ms;
  opacity: 0;
  filter: blur(2px);
}

@media (max-width: 900px) {
  /* На телефоне размытие отдаём на откуп GPU в последнюю очередь: 200 мс
     фильтра на длинном списке заметны на слабых Android, а выигрыш —
     только в первом кадре после загрузки. */
  .sp-list.is-enter { filter: none; }
}

/* Скелетон загрузки: держит высоту строки, поэтому список не «прыгает»
   в момент прихода данных. */
.sp-skeleton { padding: 14px; display: flex; flex-direction: column; gap: 10px; }

.sp-skel {
  height: 14px;
  border-radius: 6px;
  background: linear-gradient(90deg, var(--surface) 25%, var(--surface-2) 37%, var(--surface) 63%);
  background-size: 200% 100%;
  /* linear — единственная честная кривая для постоянного движения: любая
     другая даёт видимые рывки на каждом обороте. */
  animation: sp-shimmer 1.4s linear infinite;
}

.sp-skel-row { display: flex; gap: 10px; align-items: center; }
.sp-skel-row .sp-skel:first-child { flex: 1; }
/* Заглушка котировки по высоте настоящей кнопки: если она ниже, строка
   подрастает в момент прихода данных и список дёргается. */
.sp-skel-row .sp-skel:last-child { width: 68px; height: var(--sp-odd-h); }

@keyframes sp-shimmer {
  0%   { background-position: 100% 0; }
  100% { background-position: -100% 0; }
}

/* --- Купон ------------------------------------------------------------ */

/* Вход в купон и затемнение под панелью существуют только на узком экране:
   на десктопе купон — колонка, и входить в него не нужно. */
.sp-slip-fab,
.sp-slip-backdrop,
.sp-slip-close { display: none; }

.sp-slip {
  position: sticky;
  /* 12px от верха области прокрутки, а не от окна: прокручивается здесь
     `.shell-main` (у body стоит `overflow: hidden`), а шапка Shell лежит ВНЕ
     этой области. Отсчёт липкости идёт от content-box (после её 18px padding),
     поэтому 12px от кромки = 12px минус scroll-pad; голое 12px сдвигало бы
     купон на 12px ниже верха линии в стартовой позиции. */
  top: calc(12px - var(--sp-scroll-pad));
  border: 1px solid var(--line);
  border-radius: var(--sp-radius);
  background: var(--surface);
  overflow: hidden;
}

/* Шапка купона. Позиционирована, потому что служит и ручкой для жеста
   закрытия: полоска-подсказка нарисована её псевдоэлементом. */
.sp-slip-head {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 13px var(--sp-pad-x);
  border-bottom: 1px solid var(--line);
  font-size: var(--sp-fs-lg);
  font-weight: 700;
}

.sp-slip-clear {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  padding: 4px 8px;
  border: 0;
  border-radius: var(--sp-radius-sm);
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: var(--sp-fs-xs);
  cursor: pointer;
  transition: color var(--sp-t), background var(--sp-t), transform var(--sp-t-fast);
}

.sp-slip-body { max-height: 44vh; overflow-y: auto; }

.sp-pick {
  display: grid;
  /* Три колонки: текст, цена, крестик удаления. Крестик раньше делил вторую
     колонку с ценой и уезжал на вторую строку — строка выбора выходила 88px
     вместо 58px, и удаление занимало место, которое в купоне на счету. */
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 4px 10px;
  padding: 11px var(--sp-pad-x);
  border-bottom: 1px solid var(--line);
  border-left: 2px solid var(--accent);
}

.sp-pick-name {
  color: var(--text);
  font-size: var(--sp-fs-md);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sp-pick-market {
  margin-top: 3px;
  color: var(--muted);
  font-size: var(--sp-fs-xs);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sp-pick-odds {
  /* По центру строки, а не по верху: у выбора две строки текста (матч и
     рынок), и цена, прибитая к верху, читалась как подпись к первой из них.
     Так же выровнен крестик — цена и кнопка удаления стоят на одной линии. */
  align-self: center;
  color: var(--accent);
  font-size: var(--sp-fs-md);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* Пометка у выбора, цена которого уехала вместе с линией («3.33 → 5.32»)
   или который снят с линии. Цвет приходит из JS (up/danger) — правило нужно
   для геометрии и переноса: без него длинная строка раздувала строку купона
   и выталкивала крестик удаления. */
.sp-pick-note {
  grid-column: 1 / -1;
  font-size: var(--sp-fs-xs, 11px);
  line-height: 1.3;
  overflow-wrap: anywhere;
}

/* Крестик удаления — цель 32×32: в купоне палец попадает в него с той же
   частотой, что и в котировку, а промах здесь стоит выбора. */
.sp-pick-remove {
  /* Своя колонка справа от цены и по центру строки: кнопка одна, и её место
     определено разметкой, а не порядком элементов. */
  grid-column: 3;
  grid-row: 1;
  align-self: center;
  justify-self: end;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  /* Отрицательный правый отступ — чтобы крестик встал по кромке текста, а не
     на 6px левее: так он читается частью строки, а не отдельным блоком. */
  margin: 0 -6px 0 0;
  border: 0;
  border-radius: var(--sp-radius-sm);
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
  transition: color var(--sp-t), background var(--sp-t), transform var(--sp-t-fast);
}

.sp-slip-foot { padding: 14px var(--sp-pad-x); border-top: 1px solid var(--line); }

.sp-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 9px;
  color: var(--muted);
  font-size: var(--sp-fs-md);
}

.sp-row b {
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* Итоговый коэффициент и потенциальный выигрыш — главные числа купона,
   поэтому они крупнее прочих строк. */
.sp-row--total { font-size: var(--sp-fs-md); }
.sp-row--total b { color: var(--accent); font-size: var(--sp-fs-xl); font-weight: 800; }

/* Комбо-буст: строка под базовым кэфом, когда купон набирает 3+ ног по 1.50+.
   Базовый кэф перечёркивается (`.is-crossed`), рядом — процент и кэф с бустом. */
.sp-row--boost {
  margin-top: -4px;
  margin-bottom: 9px;
  color: var(--up);
}

.sp-row--boost em {
  font-style: normal;
  font-weight: 700;
}

.sp-row--boost b {
  color: var(--up);
  font-weight: 800;
}

/* Зачёркнутый базовый коэффициент: даёт понять, что итоговый кэф — уже
   с бустом, а не исходный. */
#sp-total.is-crossed {
  text-decoration: line-through;
  text-decoration-color: var(--muted);
  color: var(--muted);
}

.sp-stake {
  width: 100%;
  /* 16px, а не 15: в iOS поле с меньшим кеглем при фокусе вызывает
     автоматический зум страницы, и купон вместе с кнопкой ставки уезжает. */
  padding: 12px 12px;
  margin: 4px 0 10px;
  border: 1px solid var(--line);
  border-radius: var(--sp-radius-sm);
  background: var(--bg-deep);
  color: var(--text);
  font: inherit;
  font-size: 16px;
  font-variant-numeric: tabular-nums;
  transition: border-color var(--sp-t);
}

.sp-stake:focus { border-color: var(--accent); }

/* Встроенное кольцо гасим только у мыши: поле и так подсвечено рамкой. */
.sp-stake:focus:not(:focus-visible) { outline: none; }

.sp-quick {
  display: flex;
  gap: 6px;
  margin-bottom: 12px;
}

.sp-quick button {
  flex: 1;
  /* 44 px — минимум касания, и здесь он важнее, чем где-либо ещё: быстрые
     суммы жмут одной рукой, держа телефон другой, и промах по «+10» означает
     не «не нажалось», а неверную сумму в ставке. Замер 28.09 на телефоне:
     было 32 px, то есть на треть ниже минимума. */
  min-height: 44px;
  padding: 7px 4px;
  border: 1px solid var(--line);
  border-radius: var(--sp-radius-sm);
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: var(--sp-fs-xs);
  font-weight: 600;
  cursor: pointer;
  transition: border-color var(--sp-t), color var(--sp-t), background var(--sp-t), transform var(--sp-t-fast);
}

.sp-place {
  width: 100%;
  min-height: 48px;
  padding: 13px;
  border: 0;
  border-radius: var(--sp-radius-sm);
  background: var(--accent);
  color: var(--ink);
  font: inherit;
  font-size: var(--sp-fs-lg);
  font-weight: 700;
  cursor: pointer;
  transition: background var(--sp-t), transform var(--sp-t-fast);
}

.sp-place:disabled {
  opacity: .45;
  cursor: not-allowed;
}

/* --- Уведомления ------------------------------------------------------ */

/* Тост входит и уходит переходами, а не keyframes: ставки принимаются одна за
   другой, и второй тост поверх первого при keyframes начинал бы движение с
   нуля — это читается как мигание. Переход же доводит текущее состояние до
   нового. Класс появления ставится в разметке и снимается на следующем кадре,
   поэтому стартовое состояние обязано быть нулевой длительности. */
.sp-toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  z-index: 60;
  padding: 12px 20px;
  border-radius: var(--sp-radius-pill);
  background: var(--surface);
  border: 1px solid var(--line);
  color: var(--text);
  font-size: var(--sp-fs-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .35);
  transform: translate(-50%, 0);
  opacity: 1;
  transition: opacity var(--sp-t-list), transform var(--sp-t-list);
}

.sp-toast.is-entering,
.sp-toast.is-leaving {
  transition-duration: 0ms;
  opacity: 0;
  transform: translate(-50%, 8px);
}

/* На выходе длина обычная: появление должно быть мгновенным, уход — мягким. */
.sp-toast.is-leaving {
  transition-duration: var(--sp-t-list);
  transform: translate(-50%, 6px);
}

.sp-toast.is-error { border-color: var(--danger); color: var(--danger); }

/* --- История ставок --------------------------------------------------- */

.sp-hist {
  border: 1px solid var(--line);
  border-radius: var(--sp-radius);
  background: var(--surface);
  overflow: hidden;
}

/* Две карточки в ряд на широком экране.
 *
 * Одна карточка во всю ширину столбца растягивает всё внутри: блок выкупа
 * превращается в полосу, кнопка — в ленту во всю строку, а строки «Общий
 * коэффициент / Потенциальный выигрыш» разъезжаются по краям на полметра.
 * Две колонки дают карточке ~340px — та же плотность, что на телефоне, где
 * карточка читается лучше всего.
 *
 * Колонки — ДВА КОНТЕЙНЕРА, а не `column-count`. Балансировку CSS-колонок
 * делает браузер, и в WebKit она умеет сдвигать вторую колонку вниз: «правый
 * блок начинается ниже левого». Два обычных контейнера начинаются на одной
 * линии в любом движке, а внутри каждый набивается сам по себе — короткая
 * карточка заканчивается, следующая идёт сразу под ней, независимо от соседа.
 *
 * Порог 1400px, а не «резиновый»: столбец истории — это ширина страницы минус
 * полоса видов спорта и купон, и при 1280px двум карточкам остаётся по 260px,
 * а в них уже не влезают названия команд. */
#sp-history.is-grid {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-gap);
}

#sp-history.is-grid .sp-hist-col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-gap);
}

/* Отступ внутри колонки даёт `gap`, а карточка своего отступа не держит:
   иначе он складывался бы с промежутком контейнера. */
#sp-history.is-grid .sp-hist { margin-bottom: 0; }

@media (max-width: 1399px) {
  /* Узкий экран: те же два контейнера разворачиваются в обычный список. */
  #sp-history.is-grid { display: block; }
  #sp-history.is-grid .sp-hist-col { display: block; }
}

.sp-hist-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px var(--sp-pad-x);
  border-bottom: 1px solid var(--line);
  font-size: var(--sp-fs-md);
}

/* Дата ставки — служебная: она нужна, чтобы найти ставку в списке, но не
   спорит со суммой и статусом. Отдельной строкой, а не через точку в той же:
   в карточке шириной 340px «Одиночная · 100 USD · 27.09» переносилось посреди
   даты, и шапка читалась как обрывок. */
.sp-hist-head em {
  display: block;
  margin-top: 2px;
  font-style: normal;
  color: var(--muted);
  font-size: var(--sp-fs-sm);
  font-variant-numeric: tabular-nums;
}

.sp-badge {
  padding: 3px 9px;
  border-radius: var(--sp-radius-pill);
  font-size: var(--sp-fs-xs);
  font-weight: 700;
  letter-spacing: .02em;
  text-transform: uppercase;
}

.sp-badge-BET { background: var(--surface-2); color: var(--muted); }
.sp-badge-WIN { background: var(--up); color: var(--ink); }
.sp-badge-HALF_WIN { background: var(--up); color: var(--ink); }
.sp-badge-LOST { background: var(--danger); color: #fff; }
.sp-badge-HALF_LOST { background: var(--danger); color: #fff; }
.sp-badge-REFUND { background: var(--muted); color: var(--ink); }
.sp-badge-VOID { background: var(--muted); color: var(--ink); }
.sp-badge-CASHOUT { background: var(--accent, var(--up)); color: var(--ink); }

/* --- Выкуп купона ----------------------------------------------------- */

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

   Цена живёт секунды (ttl_seconds на сервере). Полоска под суммой показывает,
   сколько осталось именно этому предложению: без неё сумма менялась бы «сама»
   и читалась как ошибка. Когда срок вышел, блок сам запрашивает свежую цену
   (см. `startLife` в history.blade.php). */

.sp-cashout {
  display: grid;
  gap: 8px;
  padding: 12px var(--sp-pad-x);
  border-top: 1px solid var(--line);
  /* Подсветка «здесь есть действие»: у выкупа своя поверхность, он не должен
     выглядеть ещё одной строкой отчёта. */
  background: color-mix(in srgb, var(--up) 5%, var(--surface));
}

.sp-cashout-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.sp-cashout-label {
  color: var(--muted);
  font-size: var(--sp-fs-xs);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.sp-cashout-value {
  color: var(--up);
  font-size: var(--sp-fs-xl);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}

/* Сравнение служебным цветом: оно объясняет сумму, но не спорит с ней. */
.sp-cashout-vs {
  color: var(--muted);
  font-size: var(--sp-fs-sm);
}

/* Полоска жизни предложения: 2px, во всю ширину блока. Пустеет справа налево —
   так читается как «времени осталось», а не как индикатор загрузки. */
.sp-cashout-life {
  display: block;
  height: 2px;
  border-radius: var(--sp-radius-pill);
  background: color-mix(in srgb, var(--up) 22%, transparent);
  overflow: hidden;
}

.sp-cashout-life i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--up);
  transition: width .9s linear;
}

.sp-cashout-life.is-stale i { background: var(--muted); }

.sp-cashout-btn {
  /* В широкой карточке кнопка не растягивается на полстроки: у выкупа
     фиксированный размер действия, а не полоса во всю ширину. На узких
     экранах (и на телефоне) ограничение не мешает — там 100% и есть 340px. */
  width: 100%;
  max-width: 420px;
  justify-self: start;
  min-height: 44px;
  padding: 11px 16px;
  border: 0;
  border-radius: var(--sp-radius-sm);
  background: var(--up);
  color: var(--ink);
  font: inherit;
  font-size: var(--sp-fs-md);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: filter var(--sp-t), transform var(--sp-t-fast);
}

.sp-cashout-btn:hover:not(:disabled) { filter: brightness(1.06); }
.sp-cashout-btn:active:not(:disabled) { transform: scale(.99); }

.sp-cashout-btn:disabled {
  opacity: .6;
  cursor: default;
}

/* Выкуп закрылся между обновлениями: блок остаётся на месте как справка —
   «здесь был выкуп», — но действие снято и причина названа. */
.sp-cashout.is-gone {
  background: var(--surface);
}

.sp-cashout.is-gone .sp-cashout-value { display: none; }
.sp-cashout.is-gone .sp-cashout-vs,
.sp-cashout.is-gone .sp-cashout-life { display: none; }

.sp-cashout.is-gone .sp-cashout-btn { display: none; }

/* Про выкуп сообщаем словами и скринридеру: сумма пересчитывается сервером,
   и «предложение изменилось» — это то, что обязано быть услышано, а не
   только увидено. Пустой узел уже в разметке, поэтому текст в нём читается
   как изменение, а не как новая страница. */
.sp-cashout-note {
  color: var(--muted);
  font-size: var(--sp-fs-sm);
}

.sp-cashout.is-gone .sp-cashout-note { color: var(--text); }

/* Сумма в модале подтверждения: та же подача, что в блоке, — игрок узнаёт
   число, которое только что видел. */
.sp-modal-offer {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.sp-modal-offer b {
  color: var(--up);
  font-size: var(--sp-fs-xl);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.sp-modal-vs {
  margin-top: 6px;
  color: var(--muted);
  font-size: var(--sp-fs-sm);
}

/* --- Адаптив ---------------------------------------------------------- */

/* Ширина колонки котировок зависит от формата.
 *
 * Замер по живой линии (596 цен, максимум 31.91): самая широкая цена — «18.95»
 * это 41px при кегле 14.5px, «+1633» — 46px, «1407/100» — 66px (и 52px на
 * ступени ниже). Колонка в 204px давала кнопке 45px и 23px под текст: цена
 * выходила за кнопку в 506 строках из 613, и соседние числа соприкасались.
 * Отсюда ширина: три кнопки + два зазора по 6px + «+N» (51px), с запасом.
 *
 * Формат выбирает игрок, поэтому он приходит атрибутом на `<html>`
 * (см. `applyOddsFormat` в sports.js), а не отдельной вёрсткой под каждый
 * вариант. Базовая ширина в 204px остаётся запасной: без JS колонка такая же,
 * как была. */
html[data-sp-odds="decimal"] .sp-wrap,
html[data-sp-odds="hongkong"] .sp-wrap { --sp-odds-w: 268px; }
html[data-sp-odds="american"] .sp-wrap { --sp-odds-w: 288px; }
html[data-sp-odds="fractional"] .sp-wrap { --sp-odds-w: 330px; }

/* Узкая строка события (планшет и телефон): котировки уходят своей строкой во
   всю ширину, названия команд занимают всю строку над ними.
 *
 * Колонка котировок тут не помещается: на планшете строке достаётся 376px
 * (полоса видов спорта и купон забирают больше половины), и трём кнопкам с
 * ценами «178/100» нужно около 240px — названиям команд остаётся 40px, то есть
 * ничего. Своей строкой кнопки получают всю ширину, и цена любого формата
 * влезает целиком, а названия перестают обрезаться. */
@media (max-width: 1239px) {
  .sp-event,
  .sp-event.is-prematch {
    grid-template-columns: minmax(0, 1fr);
    gap: 8px;
  }

  /* Время — подписью над командами: третья колонка в узкой строке отбирает
     место у названий. */
  .sp-ev-time {
    grid-row: 1;
    grid-column: 1 / -1;
    flex-direction: row;
    justify-content: flex-start;
    gap: 6px;
    margin-bottom: 2px;
  }

  .sp-odds { justify-content: stretch; }
  .sp-odd { flex: 1; min-width: 0; }

  /* Быстрые рынки стоят под строкой и держат ту же колонку котировок: на узком
     экране она тоже не помещается, поэтому подпись рынка и кнопки идут
     столбиком — как в самой строке. */
  .sp-extra-row { grid-template-columns: minmax(0, 1fr); gap: 6px; }
}

/* Узкий десктоп и планшет в альбомной ориентации: купон чуть уже, чтобы
   линия дышала. Рельса больше нет — виды спорта живут в дропдауне. */
@media (max-width: 1239px) and (min-width: 901px) {
  .sp-wrap { grid-template-columns: minmax(0, 1fr) 320px; --sp-odds-w: 176px; }

}

/* Порог 760px, а не наши 900px: он взят у `.shell-main` из `shell.css`, потому
   что здесь мы повторяем её отступ. Поставь мы свой порог — на ширине
   761–900px липкая шапка считала бы отступ равным 14px при фактических 18px и
   над ней снова открылась бы полоса в 4px.
 *
 * Переопределяем на тех же селекторах, где токен объявлен, а не на `:root`:
 * блок токенов лежит на `.sp-wrap`, и его собственное значение перекрыло бы
 * значение с `:root` — на телефоне шапка уехала бы на 4px выше кромки. */
@media (max-width: 760px) {
  .sp-wrap,
  .sp-slip,
  .sp-league { --sp-scroll-pad: 14px; }
}

@media (max-width: 900px) {
  .sp-wrap { grid-template-columns: 1fr; }

  /* Последняя строка линии не должна уезжать под кнопку купона: она
     висит над нижней навигацией и перекрывает содержимое. */
  .sp-wrap { padding-bottom: 58px; }

  /* Переключатель и поиск в столбик: в одну строку на 390 пикселях
     поиск сжимается до пяти букв. */
  .sp-top { flex-wrap: wrap; }

  .sp-search { flex: 1 1 100%; }

  /* Шапка матча на телефоне ниже: название лиги прячем совсем (игрок только
     что видел его в списке), а минута остаётся в той же строке и уезжает
     вправо — она единственный её ребёнок на узком экране. Счёт при этом
     стоит в центре строки команд и никуда не девается. Токен живёт на
     `.sp-wrap`: его же читают табы рынков, а они шапке не потомки — значит,
     высоту надо объявлять там, где видят оба. */
  .sp-wrap,
  .sp-slip,
  .sp-league { --sp-mhead-h: 54px; }

  .sp-match-league { justify-content: flex-end; }
  .sp-match-league .sp-league-flag,
  .sp-match-league .sp-league-name { display: none; }

  /* Купон переезжает в выдвижную панель снизу.

     Колонка на телефоне невозможна: треть ширины под купон оставила бы
     линии 250 пикселей. Но и панель в потоке, после линии, бесполезна —
     в прематче это тридцать тысяч пикселей прокрутки до первой ставки, и
     до купона просто не доходят. Поэтому купон выезжает поверх линии по
     кнопке, а кнопка сразу показывает число выборов и общий коэффициент. */
  .sp-slip {
    position: fixed;
    left: 0;
    right: 0;
    /* Панель встаёт на нижнюю навигацию, как и кнопка входа в купон: она
       перекрыта навигацией по слоям, и нижняя полоса панели вместе с кнопкой
       ставки оказалась бы под ней. */
    bottom: calc(var(--bottom-h) + env(safe-area-inset-bottom, 0px));
    /* `top: auto` обязателен: выше задан `top: 12px` для липкой колонки на
       десктопе. С фиксированной панелью он превращается в переопределённую
       геометрию — панель прижимается к верху и висит, не доходя до низа
       экрана. Проверено замером: при `top: 12px` низ панели оказывался на
       89px выше кромки окна. */
    top: auto;
    z-index: 56;
    max-height: 88vh;
    display: flex;
    flex-direction: column;
    border-radius: 16px 16px 0 0;
    border-bottom: 0;
    box-shadow: 0 -14px 40px rgba(0, 0, 0, .45);
    transform: translateY(101%);
    /* Кривая выдвижной панели: панель уезжает вниз и «паркуется», а не
       обрывается на полупути, как это делает линейный ease. */
    transition: transform 280ms var(--ease-drawer);
  }

  .sp-slip.is-open { transform: none; }

  /* Пока панель ведут пальцем, переход обязан молчать: иначе она отстаёт от
     пальца на длину собственного хода. */
  .sp-slip.is-dragging { transition: none; }

  .sp-slip-head {
    padding-top: 15px;
    /* Шапка — ручка жеста: вертикальная протяжка по ней не должна
       прокручивать страницу под панелью. */
    touch-action: none;
    /* Выделение текста на ручке только мешает: протяжка по «Купон (3)»
       начинала бы выделение вместо сдвига панели. */
    user-select: none;
    cursor: grab;
  }

  .sp-slip.is-dragging .sp-slip-head { cursor: grabbing; }

  /* Полоска-подсказка: без неё панель просто «висит» и о том, что её можно
     смахнуть, знает только тот, кто попробует. */
  .sp-slip-head::before {
    content: "";
    position: absolute;
    top: 7px;
    left: 50%;
    width: 36px;
    height: 4px;
    border-radius: var(--sp-radius-pill);
    background: var(--line);
    transform: translateX(-50%);
  }

  .sp-slip-tools { display: flex; align-items: center; gap: 14px; }

  .sp-slip-close {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border: 0;
    border-radius: var(--sp-radius-sm);
    background: transparent;
    color: var(--muted);
    font: inherit;
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    transition: color var(--sp-t), transform var(--sp-t-fast);
  }

  /* Список выборов прокручивается внутри панели: в экспрессе их бывает
     десяток, и выталкивать кнопку ставки за пределы экрана нельзя. */
  .sp-slip-body {
    max-height: none;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  .sp-slip-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 55;
    background: rgba(0, 0, 0, .55);
  }

  .sp-slip-backdrop[hidden] { display: none; }

  /* Панель открыта — фон не прокручивается: иначе игрок листает линию
     под затемнением, а панель уезжает вместе с ней. Прокручивается тут
     `.shell-main`, потому что `overflow: hidden` на body не останавливает
     вложенный скроллер. Правило только для узкого экрана: на десктопе
     панели нет, и класс туда не попадает. */
  body.sp-slip-open .shell-main { overflow: hidden; }

  /* Кнопка входа в купон. Поднята над нижней навигацией Shell: иначе она
     легла бы поверх неё, и один из двух элементов стал бы недоступен. */
  .sp-slip-fab {
    display: flex;
    align-items: center;
    gap: 10px;
    position: fixed;
    left: 12px;
    right: 12px;
    bottom: calc(var(--bottom-h) + env(safe-area-inset-bottom, 0px) + 10px);
    z-index: 54;
    min-height: 48px;
    padding: 12px 16px;
    border: 0;
    border-radius: var(--sp-radius-pill);
    background: var(--accent);
    color: var(--ink);
    font: inherit;
    font-size: var(--sp-fs-lg);
    font-weight: 700;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .4);
    cursor: pointer;
    transition: opacity var(--sp-t), transform var(--sp-t-fast);
  }

  .sp-slip-fab-label { flex: 1; text-align: left; }

  .sp-slip-fab-count {
    min-width: 22px;
    padding: 1px 7px;
    border-radius: var(--sp-radius-pill);
    background: color-mix(in srgb, var(--ink) 22%, transparent);
    font-size: var(--sp-fs-sm);
    text-align: center;
    font-variant-numeric: tabular-nums;
  }

  .sp-slip-fab-odds { font-variant-numeric: tabular-nums; }

  /* Панель открыта — кнопка не нужна: она закрыла бы саму панель. */
  body.sp-slip-open .sp-slip-fab { opacity: 0; pointer-events: none; }

  /* Клавиатура. Мягкая клавиатура на iOS не сжимает layout viewport, поэтому
     фиксированная панель с `bottom: 0` остаётся под ней вместе с кнопкой
     ставки. Высоту клавиатуры пишет JS в `--sp-kb` (из visualViewport) —
     и только когда фокус в поле суммы: подмена `innerHeight` на сворачивании
     адресной строки дала бы подъём панели на ровном месте. */
  .sp-slip-foot {
    padding-bottom: calc(14px + var(--sp-kb, 0px) + env(safe-area-inset-bottom, 0px));
  }

  /* Ряд рынка: колонка под линию уже, кнопки получают её ширину. */
  .sp-mk-row {
    grid-template-columns: 46px minmax(0, 1fr);
    gap: 8px;
    padding: 5px 12px;
  }

  /* Кнопки ужимаем: на 390px строка всего ~356px, и каждый лишний пиксель
     котировок — это отрезанная буква в названии команды. Высота кнопки
     при этом остаётся комфортной для пальца. */
  .sp-odd { padding: 7px 8px; }

  /* На странице матча в ряду по-прежнему две колонки: у тотала исходов
     два, и третий столбец оставил бы по 60 пикселей на кнопку. */
  .sp-mk-row .sp-odds { gap: 6px; }
}

/* Палец вместо курсора: цель касания обязана быть не меньше 44px, иначе
   промах по котировке стоит игроку выбранного исхода. Высота приходит из
   токена, и его же видят заглушки скелетона — строка не дёргается. */
@media (pointer: coarse) {
  .sp-wrap,
  .sp-slip,
  .sp-league { --sp-odd-h: 44px; }
}

/* --- Наведение --------------------------------------------------------- */

/* Все состояния наведения живут в одном блоке и только под медиазапросом.
 *
 * На тачскрине :hover срабатывает от касания: палец уходит с кнопки, а
 * подсветка остаётся висеть на ней до следующего тапа. Это не косметика —
 * на линии из 260 событий десяток «залипших» кнопок читается как сбой.
 * Условие (hover: hover) and (pointer: fine) отсекает и тач, и гибридные
 * устройства с грубым указателем — там наведение не нужно вовсе. */
@media (hover: hover) and (pointer: fine) {
  .sp-tab:hover { color: var(--text); }

  .sp-search-clear:hover { color: var(--text); background: var(--surface-2); }

  .sp-back:hover { border-color: var(--surface-2); color: var(--text); }

  .sp-mk-tab:hover { border-color: var(--surface-2); color: var(--text); }

  .sp-league-head:not(.is-static):hover { color: var(--text); }

  /* Строка события не кликабельна целиком (ссылка только в названии), но
     подсветка строки нужна: она собирает команды и три кнопки в одну цель
     для глаза. */
  .sp-event:hover { background: color-mix(in srgb, var(--text) 3%, transparent); }

  .sp-odd:hover:not(:disabled) {
    border-color: var(--accent);
    background-color: color-mix(in srgb, var(--accent) 8%, var(--bg-deep));
  }

  .sp-slip-clear:hover { color: var(--danger); }

  .sp-pick-remove:hover { color: var(--danger); background: var(--surface-2); }

  .sp-quick button:hover {
    border-color: var(--accent);
    color: var(--accent);
    background: color-mix(in srgb, var(--accent) 8%, transparent);
  }

  .sp-place:hover:not(:disabled) { background: var(--accent-hover); }

  .sp-empty-action:hover { border-color: var(--accent); color: var(--accent); }

  .sp-cashout-btn:hover:not(:disabled) { filter: brightness(1.08); }
}

/* --- Клавиатура -------------------------------------------------------- */

/* Видимый фокус. Раньше его не было ни у одного элемента: игрок с клавиатуры
   (и любой, кто открыл линию на телевизоре или в вебвью с Tab-навигацией)
   не видел, где находится. Outline, а не box-shadow: кольцо рисуется поверх
   соседей без пересчёта вёрстки и не зависит от радиуса и рамки элемента.
 *
 * Селектор через :where() — чтобы правило не поднимало специфичность и не
 * мешало точечным правкам кольца ниже. */
:where(.sp-tab, .sp-mk-tab, .sp-back, .sp-odd, .sp-quick button,
       .sp-place, .sp-cashout-btn, .sp-slip-fab, .sp-slip-clear, .sp-slip-close,
       .sp-pick-remove, .sp-search-clear, .sp-league-head, .sp-empty-action,
       .sp-teams, .sp-stake, .sp-show-more):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* Табы рынков лежат в ленте с горизонтальной прокруткой, и кольцо наружу
   обрезалось бы её границей: у них кольцо внутри кнопки. */
.sp-mk-tab:focus-visible { outline-offset: -2px; }

/* --- Нажатие ----------------------------------------------------------- */

/* Отклик на палец и на клик: без него интерфейс не подтверждает, что
   касание дошло. 0.97 — предел, за которым кнопка начинает «прыгать»,
   а не подтверждать нажатие. */
:where(.sp-tab, .sp-mk-tab, .sp-back, .sp-odd, .sp-quick button, .sp-place,
       .sp-cashout-btn, .sp-slip-fab, .sp-slip-clear, .sp-slip-close,
       .sp-pick-remove, .sp-search-clear, .sp-empty-action):active {
  transform: scale(.97);
}

/* Токен времени нажатия не переобъявляем общим правилом: у каждого
   нажимаемого элемента переход уже объявлен под своими свойствами, и общий
   `transition` затёр бы смену цвета — осталась бы одна реакция на палец. */

/* Широкие строки масштабом не подтверждаем: полоса в 900px, сжатая на 3%,
   выглядит как сбой вёрстки, а текст внутри неё дёргается под пальцем.
   Здесь нажатие показываем фоном — он читается так же ясно и не двигает
   строку. Длительность короче обычной: отклик на палец ждём мгновенно. */
.sp-league-head:not(.is-static):active,
.sp-teams:active {
  transition-duration: var(--sp-t-fast);
  background-color: var(--surface-2);
}

/* --- Уменьшенное движение --------------------------------------------- */

/* Меньше движения — не значит меньше обратной связи. Цвет и прозрачность
   остаются (по ним игрок и понимает, что произошло), убираем сдвиг,
   масштаб и бесконечное мигание. */
@media (prefers-reduced-motion: reduce) {
  /* Мигающая точка лайва: это постоянное движение, и от него устают
     быстрее всего. Точка остаётся красной — статус читается цветом. */
  .sp-live-dot { animation: none; }

  /* Скелетон: бегущий блик снимаем, сам градиент-заглушка остаётся. */
  .sp-skel { animation: none; }

  .sp-list.is-enter { filter: none; opacity: .6; }

  .sp-slip,
  .sp-toast,
  .sp-list,
  .sp-odd,
  .sp-tab,
  .sp-mk-tab,
  .sp-quick button,
  .sp-place,
  .sp-cashout-btn,
  .sp-slip-fab,
  .sp-pick-remove,
  .sp-slip-close,
  .sp-search-clear { transition-property: opacity, color, background-color, border-color; }

  :where(.sp-tab, .sp-mk-tab, .sp-back, .sp-odd, .sp-quick button, .sp-place,
         .sp-cashout-btn, .sp-slip-fab, .sp-slip-clear, .sp-slip-close,
         .sp-pick-remove, .sp-search-clear, .sp-empty-action):active {
    transform: none;
  }

  /* Панель купона не выезжает: она появляется на месте. Ход при этом нужен
     как способ её СПРЯТАТЬ (`translateY(101%)`), поэтому снимаем переход,
     а не сам сдвиг — `transform: none` оставил бы закрытую панель поверх
     кнопки купона. */
  .sp-slip { transition: none; }
}

/* --- Тултип ----------------------------------------------------------- */

/* Заменяет нативный title: тот браузер рисует жёлтым прямоугольником под
   курсором, с задержкой и без связи с темой. Свой — приподнятая поверхность
   над целью, с мягким входом. Один узел на страницу, позицию пишет JS. */
.sp-tip {
  position: fixed;
  z-index: 70;
  max-width: 340px;
  padding: 8px 12px;
  border-radius: var(--sp-radius-sm);
  background: var(--surface-2);
  color: var(--text);
  font-size: var(--sp-fs-sm);
  font-weight: 600;
  line-height: 1.35;
  pointer-events: none;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity var(--sp-t-fast), transform var(--sp-t-fast);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .5);
}

.sp-tip.is-visible {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .sp-tip { transition: none; }
}

/* --- Переключатель формата коэффициентов ------------------------------ */

/* Компактный селект в строке фильтров, рядом с режимами «Лайв / Линия».
   Выбор переживает перезагрузку (localStorage) и мгновенно перерисовывает
   цены. Вид — из макета: подложка surface-2 и чуть более светлая рамка, чем
   у полей ввода, чтобы селект читался как выпадающий список, а не как поле. */
.sp-format {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  height: var(--sp-top-h);
  background: var(--surface-2);
  border: 1px solid #3a4350;
  border-radius: var(--sp-radius-sm);
  transition: border-color var(--sp-t);
}

.sp-format:focus-within { border-color: var(--accent); }

.sp-format select {
  height: 100%;
  padding: 0 8px 0 10px;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: var(--sp-fs-sm);
  font-weight: 700;
  cursor: pointer;
}

.sp-format select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 0;
  border-radius: var(--sp-radius-sm);
}

/* --- Быстрые рынки строки события ------------------------------------- */

/* Кнопка «+N» после трёх основных котировок: пунктирная рамка — это не
   котировка, а «ещё есть». В раскрытом состоянии рамка становится сплошной
   и акцентной. */
.sp-more {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 42px;
  min-height: var(--sp-odd-h);
  padding: 6px 10px;
  border: 1px dashed var(--line);
  border-radius: var(--sp-radius-sm);
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: var(--sp-fs-md);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: border-color var(--sp-t), color var(--sp-t), transform var(--sp-t-fast);
}

.sp-event.is-open .sp-more {
  border-style: solid;
  border-color: var(--accent);
  color: var(--accent);
}

/* Раскрытая панель быстрых рынков. Лежит внутри сетки события и занимает
   всю её ширину; показывается классом на строке. */
.sp-event-more {
  grid-column: 1 / -1;
  display: none;
  padding: 2px 0 6px;
}

.sp-event.is-open .sp-event-more {
  display: block;
  animation: sp-more-in var(--sp-t-list);
}

@keyframes sp-more-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

.sp-extra-row {
  display: grid;
  /* Та же колонка, что у строки события, и так же эластичная: быстрые рынки
     стоят под строкой, и их котировки должны быть с ней одной ширины. */
  grid-template-columns: minmax(0, 1fr) minmax(0, var(--sp-odds-w));
  align-items: center;
  gap: 12px;
  padding: 5px 0;
  border-top: 1px solid var(--line);
}

.sp-extra-name {
  min-width: 0;
  color: var(--muted);
  font-size: var(--sp-fs-sm);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- Модал подтверждения выкупа --------------------------------------- */

.sp-modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: rgba(0, 0, 0, .55);
}

.sp-modal {
  width: 100%;
  max-width: 360px;
  border: 1px solid var(--line);
  border-radius: var(--sp-radius);
  background: var(--surface);
  box-shadow: 0 16px 48px rgba(0, 0, 0, .5);
  overflow: hidden;
  animation: sp-modal-in var(--sp-t);
}

@keyframes sp-modal-in {
  from { opacity: 0; transform: translateY(8px) scale(.98); }
  to   { opacity: 1; transform: none; }
}

.sp-modal-head {
  padding: 14px var(--sp-pad-x);
  border-bottom: 1px solid var(--line);
  font-size: var(--sp-fs-lg);
  font-weight: 700;
}

.sp-modal-body {
  padding: 16px var(--sp-pad-x);
  color: var(--text);
  font-size: var(--sp-fs-md);
}

.sp-modal-note {
  margin-top: 10px;
  color: var(--muted);
  font-size: var(--sp-fs-sm);
}

.sp-modal-actions {
  display: flex;
  gap: 8px;
  padding: 0 var(--sp-pad-x) 16px;
}

.sp-modal-cancel,
.sp-modal-confirm {
  flex: 1;
  min-height: 42px;
  padding: 10px 14px;
  border-radius: var(--sp-radius-sm);
  font: inherit;
  font-size: var(--sp-fs-md);
  font-weight: 700;
  cursor: pointer;
  transition: background var(--sp-t), border-color var(--sp-t), filter var(--sp-t), transform var(--sp-t-fast);
}

.sp-modal-cancel {
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text);
}

.sp-modal-confirm {
  border: 0;
  background: var(--up);
  color: var(--ink);
}

.sp-modal-confirm:disabled {
  opacity: .6;
  cursor: default;
}

/* Фокус, нажатие и наведение для новых элементов — отдельным блоком, чтобы
   не править общие списки `:where(...)`. Специфичность нулевая и там, и тут,
   поэтому порядок объявления решает. */
.sp-more:focus-visible,
.sp-modal-cancel:focus-visible,
.sp-modal-confirm:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.sp-more:active,
.sp-modal-cancel:active,
.sp-modal-confirm:active {
  transform: scale(.97);
}

@media (hover: hover) and (pointer: fine) {
  .sp-more:hover {
    border-color: var(--accent);
    color: var(--accent);
  }

  .sp-modal-cancel:hover { border-color: var(--accent); }

  .sp-modal-confirm:hover:not(:disabled) { filter: brightness(1.08); }
}

@media (max-width: 900px) {
  /* В узкой строке быстрый рынок складывается в столбик: фиксированная
     колонка котировок (--sp-odds-w) на телефоне не переопределена. */
  .sp-extra-row {
    grid-template-columns: 1fr;
    gap: 6px;
    padding: 7px 0;
  }

  .sp-extra-name { white-space: normal; }

  .sp-more { min-width: 38px; padding: 6px 8px; }
}

@media (prefers-reduced-motion: reduce) {
  .sp-event.is-open .sp-event-more,
  .sp-modal { animation: none; }

  .sp-more,
  .sp-modal-cancel,
  .sp-modal-confirm { transition-property: opacity, color, background-color, border-color; }

  .sp-more:active,
  .sp-modal-cancel:active,
  .sp-modal-confirm:active { transform: none; }
}

/* --- Лента живых ставок ------------------------------------------------ */

/* Горизонтальная полоса под табами: поток последних ставок всех игроков.
   Чипы в одну строку с прокруткой; скроллбар скрыт, свайп естественный. */
.sp-live-feed {
  margin-bottom: var(--sp-gap);
  border: 1px solid var(--line);
  border-radius: var(--sp-radius);
  background: var(--surface);
  overflow: hidden;
}

.sp-live-feed-head {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  border-bottom: 1px solid var(--line);
}

.sp-live-feed-title {
  font-size: var(--sp-fs-sm);
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .04em;
}

.sp-live-feed-track {
  display: flex;
  gap: 8px;
  padding: 10px 12px;
  overflow-x: auto;
  scrollbar-width: none;
}

.sp-live-feed-track::-webkit-scrollbar { display: none; }

.sp-feed-chip {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface-2);
  font-size: var(--sp-fs-sm);
  white-space: nowrap;
}

.sp-feed-user { color: var(--muted); font-weight: 600; }

.sp-feed-stake { color: var(--text); font-weight: 700; font-variant-numeric: tabular-nums; }

.sp-feed-events { color: var(--text); }

.sp-feed-sep { color: var(--muted); margin: 0 2px; }

.sp-feed-odds { color: var(--accent); font-weight: 700; font-variant-numeric: tabular-nums; }

/* --- Визуализация матча (Euro365) ------------------------------------- */

/* Блок кнопок «Матч-трекер» / «Смотреть» под шапкой матча. Пустой — скрыт
   целиком, место под ним не резервируется: отсутствие визуализации не
   должно сдвигать роспись. */
.sp-visual {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: var(--sp-gap) 0 0;
}

.sp-visual-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: var(--sp-radius-sm);
  background: var(--surface-2);
  color: var(--text);
  font: inherit;
  font-size: var(--sp-fs-md);
  font-weight: 700;
  cursor: pointer;
  transition: border-color var(--sp-t), filter var(--sp-t), transform var(--sp-t-fast);
}

.sp-visual-ico { font-size: 1.1em; line-height: 1; }

.sp-visual-ico--live { color: var(--up); }

/* Модал медиа (трекер/видео) шире обычного: внутри живёт iframe, и окно
   под размер контента. Кнопка-крестик — в шапке, не отдельной строкой. */
.sp-modal--media { max-width: 860px; }

.sp-modal-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }

.sp-modal-x {
  border: 0;
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 0 2px;
  transition: color var(--sp-t);
}

.sp-modal-body--media { padding: 0; }

.sp-visual-frame {
  display: block;
  width: 100%;
  height: 62vh;
  max-height: 640px;
  border: 0;
  background: #000;
}

@media (hover: hover) and (pointer: fine) {
  .sp-visual-btn:hover { border-color: var(--accent); }
  .sp-modal-x:hover { color: var(--text); }
}

.sp-visual-btn:active,
.sp-modal-x:active { transform: scale(.96); }

.sp-visual-btn:focus-visible,
.sp-modal-x:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

@media (max-width: 900px) {
  .sp-visual-frame { height: 56vh; }
  .sp-visual-btn { flex: 1 1 auto; justify-content: center; }
}


/* =====================================================================
   Правая колонка: вкладки «Матч» и «Купон»
   =====================================================================
   До этого в колонке всегда жил купон: до первого выбора — пустой на 340px,
   а остальные рынки матча игрок видел только уйдя на отдельную страницу.
   Теперь колонка одна на две задачи, вкладками. */

.sp-col-tabs {
  display: flex;
  gap: 2px;
  padding: 8px 10px 0;
  border-bottom: 1px solid var(--line);
}

.sp-col-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
  transition: color .12s ease, border-color .12s ease;
}

.sp-col-tab:hover { color: var(--text); }
.sp-col-tab.is-on { color: var(--text); border-bottom-color: var(--accent); }

.sp-col-count {
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--accent);
  color: #0b0e11;
  font-size: 10px;
  font-weight: 800;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.sp-col-count[hidden] { display: none; }

.sp-col-pane[hidden] { display: none; }

/* Панель матча ограничена высотой экрана и прокручивается внутри себя.
   Без этого колонка вырастала выше вьюпорта, и липкость начинала работать
   против игрока: после клика по матчу он видел середину панели — шапку со
   счётом уносило вверх за край экрана. Внутренняя прокрутка держит и вкладки,
   и счёт на месте, а рынки листаются в панели. */
.sp-col-pane[data-sp-pane="match"] {
  max-height: calc(100vh - 190px);
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Панель матча: шапка со счётом, моментум, события и рынки. */
.sp-mpanel { padding: 12px; }

.sp-mpanel-head { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }

.sp-mpanel-team {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  font-weight: 700;
}

.sp-mpanel-team span { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sp-mpanel-team b { font-size: 18px; font-weight: 800; font-variant-numeric: tabular-nums; }

.sp-mpanel-live {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--muted);
}

.sp-mpanel-live .sp-live-dot { position: static; }

.sp-mpanel-title {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 12px 0 2px;
}

.sp-mpanel-all {
  display: block;
  margin-top: 10px;
  padding: 9px;
  border-radius: var(--sp-radius-sm);
  background: var(--bg);
  border: 1px solid var(--line);
  color: var(--muted);
  font-size: 12.5px;
  font-weight: 700;
  text-align: center;
  text-decoration: none;
}

.sp-mpanel-all:hover { color: var(--text); }

.sp-mpanel-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 40px 18px;
  text-align: center;
  color: var(--muted);
}

.sp-mpanel-empty b { color: var(--text); font-size: 13.5px; }
.sp-mpanel-empty span { font-size: 12px; line-height: 1.45; }

/* В панели рынки идут компактнее, чем на странице матча: ширина колонки
   вдвое меньше, и крупные отступы превращали бы список в простыню. */
.sp-mpanel .sp-league-head { padding: 8px 0; }
.sp-mpanel .sp-mk-row { padding: 6px 0; }
.sp-mpanel .sp-odd { min-width: 0; }

/* Телефон: колонки нет — купон выдвигается снизу, а вкладки и панель матча
   живут только на десктопе. */
@media (max-width: 1000px) {
  .sp-col-tabs { display: none; }
  .sp-col-pane[data-sp-pane="match"] { display: none; }
}

/* --- Плавающая кнопка купона: два понятных состояния ------------------- */

/* Пустой купон не показывает «0» и «0.00» — эти числа ничего не значат и
   читаются как поломка. Вместо них — подсказка, что делать. */
.sp-slip-fab-hint {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--muted);
  margin-left: 4px;
}

.sp-slip-fab.is-empty { background: var(--surface); border: 1px solid var(--line); }
.sp-slip-fab.is-empty .sp-slip-fab-label { color: var(--text); }

/* --- Подтверждение выбора: тост над купоном ---------------------------- */

/* Клик по коэффициенту менял только счётчик внизу экрана — на телефоне это
   вне взгляда, и игрок жал второй раз, решив, что не попал. Тост появляется
   там, где смотрят: над кнопкой купона. */
.sp-toast {
  position: fixed;
  left: 50%;
  transform: translateX(-50%) translateY(12px);
  bottom: calc(var(--bottom-h, 60px) + 84px);
  z-index: 60;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: calc(100vw - 32px);
  padding: 10px 14px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .5);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 700;
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s ease, transform .18s ease;
}

.sp-toast.is-on { opacity: 1; transform: translateX(-50%) translateY(0); }
.sp-toast b { color: var(--accent); }

@media (min-width: 1001px) {
  .sp-toast { bottom: 28px; left: auto; right: 28px; transform: translateY(12px); }
  .sp-toast.is-on { transform: translateY(0); }
}

/* --- Шаг ставки: поле суммы и подсказка -------------------------------- */

/* Раньше поле суммы стояло без подписи (только placeholder «Сумма ставки»),
   а быстрые кнопки несли валюту в каждой кнопке: «USD 10 · USD 25 · …».
   Подпись над полем убирает и то и другое: валюта называется один раз, а
   кнопки — просто числа. */

.sp-stake-wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 4px 12px 4px 0;
  border: 1px solid var(--line);
  border-radius: var(--sp-radius-sm);
  background: var(--bg);
}

.sp-stake-cap {
  padding-left: 12px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--muted);
  white-space: nowrap;
}

.sp-stake-wrap .sp-stake {
  border: 0;
  background: none;
  padding: 10px 0;
  width: 110px;
  text-align: right;
  font-size: 15px;
  font-weight: 800;
}

.sp-stake-wrap .sp-stake:focus { outline: none; }
.sp-stake-wrap:focus-within { border-color: var(--accent); }

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

.sp-rail {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 96px;
  padding: 6px;
  border: 1px solid var(--line);
  border-radius: var(--sp-radius);
  background: var(--surface);
  position: sticky;
  top: calc(12px - var(--sp-scroll-pad));
}

.sp-rail-i {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 8px 4px;
  border-radius: var(--sp-radius-sm);
  color: var(--muted);
  font-size: 10.5px;
  font-weight: 700;
  text-align: center;
  line-height: 1.25;
  text-decoration: none;
  transition: background .12s ease, color .12s ease;
}

.sp-rail-i em { font-style: normal; font-size: 17px; }
.sp-rail-i i { font-style: normal; font-size: 10px; font-weight: 700; color: var(--dim); font-variant-numeric: tabular-nums; }
.sp-rail-i:hover { background: var(--surface-2); color: var(--text); }
.sp-rail-i.is-on { background: var(--surface-2); color: var(--text); }
.sp-rail-i.is-on i { color: var(--accent); }

.sp-rail-div { height: 1px; margin: 6px 4px; background: var(--line); }

/* Три колонки: полоса видов спорта, линия и колонка справа (матч и купон).
   Модификатор, а не сам `.sp-wrap`: страница матча строится тем же классом, но
   полосы у неё нет — там детей двое, и в трёхколоночной сетке роспись уезжала
   в первую колонку шириной 96px, а купон растягивался на весь экран. */
.sp-wrap--rail { grid-template-columns: 96px minmax(0, 1fr) 340px; gap: var(--sp-gap); }

/*
 * Страница без колонок — история ставок: там нужна одна строка навигации,
 * а сетка из трёх колонок оставила бы под неё пустые области. Класс остаётся
 * на `.sp-wrap`, потому что токены отступов и радиусов объявлены именно там.
 */
.sp-wrap--plain { display: block; }

@media (max-width: 1239px) and (min-width: 901px) {
  .sp-wrap--rail { grid-template-columns: 96px minmax(0, 1fr) 320px; }
}

/* Планшет и телефон: полоса становится горизонтальной лентой над линией.
   Вертикальная колонка в 96px на 760px съедала бы четверть ширины. */
@media (max-width: 900px) {
  /* Одной колонкой: правило сетки рельса стоит выше и без медиазапроса, а по
     порядку в файле оно сильнее — без этого переопределения на телефоне
     остались бы три колонки. */
  .sp-wrap--rail { grid-template-columns: minmax(0, 1fr); }

  .sp-rail {
    flex-direction: row;
    width: auto;
    overflow-x: auto;
    scrollbar-width: none;
    padding: 6px 8px;
    position: static;
  }

  .sp-rail::-webkit-scrollbar { display: none; }
  .sp-rail-i { flex: 0 0 auto; flex-direction: row; gap: 6px; padding: 6px 10px; font-size: 12px; }
  .sp-rail-i em { font-size: 15px; }
  .sp-rail-div { width: 1px; height: auto; margin: 4px 6px; }
}

/* Строка фильтров: режимы слева, службы справа, между ними воздух — раскладка
   макета. Строка стоит в средней колонке, рядом с полосой видов спорта.
   Группа служб растягивается на свободное место (`flex: 1 1 auto`), а не
   прижимается вправо автоотступом: иначе поиск остаётся шириной в свой
   минимум, и подсказка «Поиск по команде или турниру» обрезается на
   «…или». Растянутая группа отдаёт это место полю поиска. */
.sp-top-right {
  display: flex;
  align-items: center;
  gap: var(--sp-gap);
  flex: 1 1 auto;
  /* min-width: 0 обязателен: без него группа не сжимается ниже суммы
     содержимого и строка выходит за край колонки. */
  min-width: 0;
}

@media (max-width: 900px) {
  /* Телефон: режимы строкой, под ними службы, поиск — своей строкой во всю
     ширину. Без `flex-wrap` на служебной группе поиск с базой 100% не
     переносился, а сжимался в огрызок 110px и вылезал за край экрана.
     Высоты здесь крупнее макетных: 30px — метрика мыши, палец в неё не
     попадает, а строка на телефоне не занята ничем другим. */
  /* На телефоне та же строка, но контролы выше: 38px — метрика мыши, палец в
     неё не попадает. Токен один, поэтому высоты снова совпадают. */
  .sp-wrap { --sp-top-h: 46px; }

  .sp-top-right { flex: 1 1 100%; flex-wrap: wrap; }
  .sp-tab { padding: 0 16px; }
  .sp-format { flex: 1 1 auto; }
  .sp-search { flex: 1 1 100%; min-width: 0; }
  .sp-search-clear { width: 30px; height: 30px; font-size: 18px; }
}

/* --- Порционная отдача линии ------------------------------------------- */

/* Кнопка «показать ещё». Стоит в конце списка лиг во всю ширину: это не
   действие над одной лигой, а продолжение списка, и узкая кнопка справа
   читалась бы как действие конкретной лиги.
 *
 * Высота 44px — минимум для касания (см. блок мобильных правил выше): по
 * этой кнопке попадают пальцем, часто на бегу, и промах означает, что
 * игрок не увидит остаток линии вовсе. */
.sp-show-more {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  min-height: 44px;
  margin: 10px 0 4px;
  padding: 10px 14px;
  border-radius: 10px;
  border: 1px dashed var(--line);
  background: transparent;
  color: var(--text);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.sp-show-more:hover { border-color: var(--accent); color: var(--accent); background: rgba(252,213,53,0.05); }
.sp-show-more:active { transform: scale(0.995); }
.sp-show-more-label { white-space: nowrap; }
.sp-show-more-count {
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* --- Лимиты приёма в купоне ------------------------------------------- */

/* Строка под быстрыми суммами: сколько можно поставить и почему именно
   столько. Стоит там, где игрок вводит сумму, а не в правилах раздела: лимит —
   это не справка, а число, которое он обязан увидеть перед нажатием.
 *
 * Максимум по купону выделен жирным и цветом: он меняется от коэффициентов, и
 * именно его игрок не может посчитать в уме. */
.sp-limits {
  margin: 0 0 12px;
  font-size: var(--sp-fs-xs);
  line-height: 1.45;
  color: var(--muted);
}

.sp-limits b {
  color: var(--text);
  font-weight: 700;
}

.sp-limits.is-tight b {
  color: var(--accent);
}

/* Кнопка быстрой суммы, которая для ЭТОГО купона слишком велика: не спрятана,
   а погашена — игрок должен видеть, что сумма существует, но недоступна
   именно здесь, иначе он решит, что кнопка сломана. */
.sp-quick button:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* Галка «принимать изменение коэффициента».

   Так работает приём у крупных контор, и это ответ на жалобу «жму — и ничего»:
   без согласия игрока расхождение цены означает отказ, а с ним ставка проходит
   по новой цене (и он видит её числами в сообщении).

   Читается как часть купона, а не как справка: стоит между лимитами и кнопкой,
   мелким шрифтом и с обычным для купона цветом подписи. Тач-таргет — вся
   строка целиком, а не квадратик чекбокса: на телефоне в квадратик 16 px
   не попасть. */
.sp-accept {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  margin: 0 0 10px;
  font-size: var(--sp-fs-xs);
  line-height: 1.35;
  color: var(--muted);
  cursor: pointer;
}

.sp-accept input {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Подсказка под галкой: видна только когда согласие дано, и говорит, ЧТО
   произойдёт. Название галки объясняет не всё: «принимать изменения» — это
   термин, а игроку нужно знать, что ставка пройдёт по новой цене и он её
   увидит. */
.sp-accept-hint {
  margin: -4px 0 10px 26px;
  font-size: var(--sp-fs-xs);
  line-height: 1.4;
  color: var(--muted);
}

/* Сумма выше предела или ниже минимума: число, которое игрок обязан увидеть
   до нажатия, и одна кнопка, которая приводит сумму в порядок. Подбор вручную
   — то место, где игрок уходит, не поставив. */
.sp-limit-over {
  color: var(--accent);
  font-weight: 700;
}

.sp-limit-fix {
  display: block;
  width: 100%;
  min-height: 40px;
  margin: 8px 0 0;
  padding: 8px 12px;
  border: 1px solid var(--accent);
  border-radius: var(--sp-radius-sm);
  background: transparent;
  color: var(--accent);
  font: inherit;
  font-size: var(--sp-fs-sm);
  font-weight: 700;
  cursor: pointer;
}

.sp-limit-fix:hover {
  background: var(--accent);
  color: var(--ink);
}

/* --- Матч-центр: счёт по периодам, ход матча, статистика ------------------ */

/* Блок стоит между липкой шапкой матча и рынками: сначала «что происходит»,
   потом «на что ставить». Роспись отвечает на второй вопрос, а игрок, который
   пришёл за тоталом, приходит с первым — к 68-й минуте он должен видеть, что
   голов уже три и есть карточка.

   Данные честные и с оговоркой: голы и карточки собираются из опроса линии,
   потому что фид истории не отдаёт. Минута точна до интервала опроса, автора
   события у нас нет — поэтому в ленте сторона и минута, без фамилий. */
.sp-centre {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 0 0 12px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--sp-radius);
}

/* Счёт по периодам: «1-й тайм 1:0». Чипы, а не строка — их читают по одному. */
.sp-centre-periods {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.sp-centre-period {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 4px 9px;
  background: var(--surface-2);
  border-radius: var(--sp-radius-sm);
  font-size: var(--sp-fs-xs);
  color: var(--muted);
}

.sp-centre-period em {
  font-style: normal;
}

.sp-centre-period b {
  color: var(--text);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.sp-centre-title {
  font-size: var(--sp-fs-xs);
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Лента событий — протокол одной колонкой: значок, минута, команда.
   Раскладка «хозяева слева, гости справа» оставляла посреди блока пустое поле:
   у нас нет ни автора события, ни счёта на момент события, и колонки нечем
   было заполнить. */
.sp-tl {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.sp-tl-row {
  display: grid;
  grid-template-columns: 20px 46px 1fr;
  align-items: center;
  gap: 8px;
  min-height: 30px;
  padding: 1px 2px;
  border-radius: var(--sp-radius-sm);
}

.sp-tl-min {
  font-size: var(--sp-fs-xs);
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.sp-tl-team {
  font-size: var(--sp-fs-xs);
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sp-tl-ic {
  font-size: 15px;
  line-height: 1;
  text-align: center;
  color: var(--text);
}

/* Карточка — прямоугольник цвета карточки, а не иконка: у футбольного
   болельщика «жёлтый прямоугольник» читается мгновенно, а любая иконка
   требует узнавания. */
.sp-tl-card {
  width: 11px;
  height: 15px;
  margin: 0 auto;
  border-radius: 2px;
}

.sp-tl-card.is-yellow {
  background: #f5c451;
}

.sp-tl-card.is-red {
  background: #e5484d;
}

/* Статистика: полосы сравнения. Ширина полосы — доля от суммы, а не от
   максимума: при 2:6 угловых это сразу видно, а от максимума обе полосы
   выглядели бы полными. */
.sp-centre-stats {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: 2px;
}

.sp-stat-row {
  display: grid;
  grid-template-columns: 22px 1fr auto 1fr 22px;
  align-items: center;
  gap: 8px;
}

.sp-stat-val {
  font-size: var(--sp-fs-xs);
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.sp-stat-label {
  font-size: var(--sp-fs-xs);
  color: var(--muted);
  white-space: nowrap;
}

.sp-stat-bar {
  display: block;
  height: 5px;
  background: var(--surface-2);
  border-radius: var(--sp-radius-pill);
  overflow: hidden;
}

.sp-stat-bar i {
  display: block;
  height: 100%;
  background: var(--accent);
  border-radius: var(--sp-radius-pill);
}

.sp-stat-bar.is-home {
  transform: scaleX(-1);
}

.sp-stat-bar.is-away i {
  background: var(--muted);
}

@media (max-width: 640px) {
  .sp-centre {
    padding: 10px 11px;
  }

  /* Протокол и на телефоне остаётся протоколом: значок и минута фиксированы,
     название команды забирает остаток. Растянуть колонку значка — значит
     развести значок и минуту по краям строки. */
  .sp-tl-row {
    grid-template-columns: 18px 42px 1fr;
    gap: 7px;
  }

  .sp-stat-row {
    grid-template-columns: 18px 1fr auto 1fr 18px;
    gap: 6px;
  }
}

/* =========================================================
   Полоса раздела: три равные кнопки
   =========================================================
   Поиск уехал в шапку сайта, и полоса осталась тем, чем и должна быть —
   переключателем раздела. Три равные доли по всей ширине: целиться в них
   пальцем проще, чем в подписи переменной ширины, а «где я» видно по заливке. */
@media (max-width: 760px) {
  /* Поиск — только на широком экране: на телефоне его работу делает поиск
     в шапке сайта (игры + матчи + рынки одним полем). */
  .sp-search { display: none; }

  .sp-tabs {
    display: flex;
    flex: 1 1 100%;
    gap: 4px;
    padding: 4px;
    background: var(--surface, #12161b);
    border: 1px solid var(--sp-line, rgba(255, 255, 255, 0.08));
    border-radius: 12px;
  }
  .sp-tab {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 38px;
    padding: 0 6px;
    border-radius: 9px;
    font-size: 12.5px;
    font-weight: 700;
    color: var(--muted);
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .sp-tab.is-active {
    background: rgba(252, 213, 53, 0.14);
    color: var(--accent);
  }
  .sp-tab-ico svg, .sp-live-dot { flex: 0 0 auto; }
}

/* В Telegram раскладка вертикальная — там поиск тоже живёт в шапке сайта. */
body.is-tg .sp-search { display: none; }
