/* Экран для зрителей: телевизор в кафе и телефон в кармане — одна вёрстка.
 *
 * Своя таблица стилей, а не skisport.css: у сайта светлые страницы для
 * чтения, а это тёмная картинка, на которую смотрят с пяти метров и полминуты.
 * Размеры — в vmin, потому что один и тот же адрес открывают и на телевизоре,
 * и на ноутбуке у финиша.
 *
 * Телефон — не отдельный шаблон, а вторая раскладка той же страницы: у
 * родителя на склоне и у зрителя в кафе перед глазами одно и то же, только
 * разложенное по-разному.
 */
:root {
  --screen-ink: #f2f8ff;
  --screen-muted: #93accd;
  --screen-gold: #fbbf24;
  --screen-accent: #38bdf8;
  --screen-ok: #4ade80;
  --screen-bad: #f87171;
  --screen-glass: rgba(255, 255, 255, .055);
  --screen-line: rgba(255, 255, 255, .11);
  --u: 1vmin;
}

/* Летом — трава и солнце, зимой — лёд: тот же сезон, что у программы
   (sportorg/season.py). Класс ставит сервер, а не браузер: сезон должен быть
   один на все экраны соревнования. */
html[data-season="summer"] {
  --screen-accent: #34d399;
  --screen-ink: #f4fbf4;
  --screen-muted: #9fc2a8;
}

html, body { height: 100%; margin: 0; }
body.screen {
  color: var(--screen-ink);
  background:
    radial-gradient(1200px 700px at 80% -10%, rgba(56, 189, 248, .20), transparent 60%),
    radial-gradient(900px 600px at 10% 110%, rgba(59, 130, 246, .18), transparent 60%),
    linear-gradient(165deg, #08203a 0%, #0b2a4a 45%, #061426 100%);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-variant-numeric: tabular-nums;
  overflow: hidden;
}
html[data-season="summer"] body.screen {
  background:
    radial-gradient(1200px 700px at 80% -10%, rgba(250, 204, 21, .20), transparent 60%),
    radial-gradient(900px 600px at 10% 110%, rgba(52, 211, 153, .18), transparent 60%),
    linear-gradient(165deg, #0b2a1e 0%, #123524 45%, #071a12 100%);
}

.stage {
  height: 100%;
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: calc(var(--u) * 1.4);
  padding: calc(var(--u) * 1.8) calc(var(--u) * 2);
}

.screen-head { display: flex; align-items: center; gap: calc(var(--u) * 2); }
.screen-head h1 { margin: 0; font-size: calc(var(--u) * 3.2); font-weight: 800; }
.screen-head .sub {
  color: var(--screen-muted); font-size: calc(var(--u) * 1.6);
  margin-top: calc(var(--u) * .4);
}
.screen-head .chips { margin-left: auto; display: flex; gap: calc(var(--u) * .8); flex-wrap: wrap; justify-content: flex-end; }
/* Полоса прогресса дня и группы.
 *
 * «Проехали 30 из 35» — это два числа, которые надо вычесть в уме, стоя в
 * кафе с чашкой. Полоса отвечает на тот же вопрос мгновенно и издалека:
 * сколько дня осталось. Подпись при этом остаётся — точные числа нужны тем,
 * кто ждёт конкретного человека, и «почти всё» их не заменяет.
 */
.bar { display: flex; flex-direction: column; gap: calc(var(--u) * .3); min-width: calc(var(--u) * 16); }
/* Дорожка — ряд, а не стопка. Куски были обычными блоками и вставали друг под
   друга: проехавшие занимали всю высоту, а сошедшие уезжали на вторую
   «строку», которую дорожка обрезала. Красной заливки не было видно вовсе —
   при том, что в разметке она была. */
.bar__line {
  display: flex; height: calc(var(--u) * .8); border-radius: 999px;
  overflow: hidden; background: rgba(148, 163, 184, .22);
}
.bar__fill {
  display: block; height: 100%; width: 0; flex: 0 0 auto;
  background: linear-gradient(90deg, var(--screen-accent), #818cf8);
  transition: width .6s ease;
}
/* Сошедшие — красным продолжением той же дорожки: они тоже уже не поедут, но
   считать их проехавшими нельзя. Цвет плотный, а не полупрозрачный: сквозь
   прозрачный виден серый фон дорожки, и кусок читается как незаполненный. */
.bar__out {
  display: block; height: 100%; flex: 0 0 auto;
  background: var(--screen-bad); transition: width .6s ease;
}
.bar__cap {
  display: flex; gap: calc(var(--u) * .6); align-items: baseline;
  font-size: calc(var(--u) * 1.4); color: var(--screen-muted); white-space: nowrap;
}
.bar__cap b { color: var(--screen-fg, #e2e8f0); font-weight: 700; }
/* Подпись сошедших остаётся спокойной: красным говорит сама полоса, а красный
   текст рядом с красным куском — это второй раз об одном и том же. */
.bar__lost { color: var(--screen-muted); }

.chip {
  border: 1px solid var(--screen-line); background: var(--screen-glass);
  border-radius: 999px; padding: calc(var(--u) * .5) calc(var(--u) * 1.2);
  font-size: calc(var(--u) * 1.5); white-space: nowrap;
}
.chip b { color: var(--screen-muted); font-weight: 500; margin-right: calc(var(--u) * .5); }
.clock {
  font-size: calc(var(--u) * 3.4); font-weight: 700; letter-spacing: 1px;
  padding-left: calc(var(--u) * 1.6); border-left: 1px solid var(--screen-line);
}

main.screen-body { display: grid; grid-template-columns: 1.55fr 1fr; gap: calc(var(--u) * 1.4); min-height: 0; }
.card {
  background: var(--screen-glass); border: 1px solid var(--screen-line);
  border-radius: calc(var(--u) * 1.4); padding: calc(var(--u) * 1.4); min-height: 0;
}
.card h3 {
  margin: 0 0 calc(var(--u) * .9); font-size: calc(var(--u) * 1.4);
  text-transform: uppercase; letter-spacing: 1px; color: var(--screen-muted); font-weight: 700;
}

.board { display: flex; flex-direction: column; min-height: 0; }
.board-head { display: flex; align-items: baseline; gap: calc(var(--u) * 1.2); }
.board-head h2 { margin: 0; font-size: calc(var(--u) * 2.6); font-weight: 800; }
.board-head .cnt { color: var(--screen-muted); font-size: calc(var(--u) * 1.5); margin-left: auto; }
/* Полоса поворота — лыжня.
 *
 * Это две колеи, которые «прокладывает» время до следующей группы. Раньше
 * здесь была одна полоска, и двигалась она рывками: ширину ей меняли пять раз
 * в секунду, и глаз читал это как подёргивание. Теперь ход плавный (переход в
 * стилях, а не шаг в скрипте), а сама полоса нарисована двумя тонкими
 * колеями — как след, оставленный на склоне.
 */
.rot {
  position: relative; height: calc(var(--u) * 1.1);
  margin: calc(var(--u) * .8) 0; overflow: hidden;
  /* Две колеи: тонкие светлые линии на всю ширину — то, что ещё не пройдено. */
  background:
    linear-gradient(rgba(255, 255, 255, .10), rgba(255, 255, 255, .10))
      0 35% / 100% 2px no-repeat,
    linear-gradient(rgba(255, 255, 255, .10), rgba(255, 255, 255, .10))
      0 65% / 100% 2px no-repeat;
}
.rot i {
  display: block; height: 100%; width: 0;
  /* Пройденная часть — те же две колеи, но яркие и с лёгким свечением на
     конце: видно, где «лыжник» сейчас. */
  background:
    linear-gradient(90deg, rgba(56, 189, 248, .25), var(--screen-accent))
      0 35% / 100% 2px no-repeat,
    linear-gradient(90deg, rgba(129, 140, 248, .25), #818cf8)
      0 65% / 100% 2px no-repeat;
  transition: width .22s linear;
}
/* Кончик лыжни: короткая засветка на переднем крае колеи. */
.rot i::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: calc(var(--u) * 1.6);
  right: 0; transform: translateX(50%);
  background: radial-gradient(closest-side, rgba(56, 189, 248, .55), transparent);
}

/* Лето — те же старты на роликах, и полоса другая: не лыжня, а дорожка, по
   которой катится колесо. Колеи схлопываются в одну линию асфальта, а на
   переднем крае едет ролик — он и вращается, потому что катится. */
html[data-season="summer"] .rot {
  background:
    linear-gradient(rgba(255, 255, 255, .10), rgba(255, 255, 255, .10))
      0 50% / 100% 2px no-repeat;
}
html[data-season="summer"] .rot i {
  background:
    linear-gradient(90deg, rgba(52, 211, 153, .25), var(--screen-accent))
      0 50% / 100% 2px no-repeat;
}
html[data-season="summer"] .rot i::after {
  width: calc(var(--u) * 1.1); height: calc(var(--u) * 1.1);
  top: 50%; bottom: auto; right: 0;
  transform: translate(50%, -50%);
  border-radius: 50%;
  background: var(--screen-accent);
  /* Спицы: по ним и видно, что колесо катится, а не едет юзом. */
  box-shadow: inset 0 0 0 1.5px rgba(6, 45, 30, .55);
  animation: roll 1.1s linear infinite;
}
@keyframes roll {
  from { transform: translate(50%, -50%) rotate(0deg); }
  to { transform: translate(50%, -50%) rotate(360deg); }
}
/* Спица нарисована фоном, иначе вращение не видно у ровного круга. */
html[data-season="summer"] .rot i::after {
  background:
    linear-gradient(var(--screen-accent), var(--screen-accent)) 50% 50% / 100% 100% no-repeat,
    linear-gradient(rgba(6, 45, 30, .5), rgba(6, 45, 30, .5)) 50% 50% / 2px 100% no-repeat;
}

/* Кому анимация мешает — тому её нет: колесо крутится ради красоты, а не
   ради смысла. */
@media (prefers-reduced-motion: reduce) {
  html[data-season="summer"] .rot i::after { animation: none; }
  .rot i { transition: none; }
}
.rows { flex: 1; overflow: hidden; display: flex; }
/* Крупнее прежнего: экран висит в кафе, и читают его через зал, а не с
   рабочего расстояния. Строк в группе показывается двенадцать, высоты на них
   хватает с запасом — размер упирался не в место, а в привычку верстать под
   монитор. */
table.screen { width: 100%; height: 100%; border-collapse: collapse; font-size: calc(var(--u) * 2.3); }
table.screen th {
  text-align: left; font-size: calc(var(--u) * 1.2); text-transform: uppercase;
  letter-spacing: .8px; color: var(--screen-muted); font-weight: 600;
  padding: 0 calc(var(--u) * .8) calc(var(--u) * .6);
}
table.screen td { padding: calc(var(--u) * .75) calc(var(--u) * .8); border-top: 1px solid rgba(255, 255, 255, .07); }
table.screen td.pl { font-weight: 800; width: calc(var(--u) * 4); color: var(--screen-muted); }
table.screen td.bib { color: var(--screen-accent); font-weight: 700; width: calc(var(--u) * 6); }
table.screen td.tm { text-align: right; font-weight: 700; white-space: nowrap; }
table.screen td.gp { text-align: right; color: var(--screen-muted); white-space: nowrap; width: calc(var(--u) * 9); }
table.screen td.st { color: var(--screen-bad); }
table.screen tr.lead td { background: rgba(251, 191, 36, .10); }
table.screen tr.lead td:first-child { box-shadow: inset calc(var(--u) * .35) 0 0 var(--screen-gold); }
table.screen tr.lead td.pl, table.screen tr.lead td.tm { color: var(--screen-gold); }
table.screen tr.ooc td { color: var(--screen-muted); }
/* Клуб — своей строкой под фамилией, а не следом за ней: при крупном шрифте
   он всё равно переносился, и половина строк была двухэтажной, а половина
   нет. Ровные строки читаются через зал, рваные — нет. */
table.screen .team {
  color: var(--screen-muted); font-size: calc(var(--u) * 1.5);
  display: block; margin-top: calc(var(--u) * .1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Фамилия — то единственное, что на экране ищут глазами. Заглавными и чуть
   плотнее, имя рядом остаётся строчным. */
.fam { text-transform: uppercase; font-weight: 800; letter-spacing: .01em; }
table.screen tr.just td { animation: sweep 2.4s ease-out 1; }
@keyframes sweep { 0% { background: rgba(56, 189, 248, .5); } 100% { background: transparent; } }

/* «Только что», последние финиши, кто на старте, лидеры групп. Первые три
   ростом по содержимому, лидеры добирают остаток: их список длиннее всех и
   единственный, который не жалко подрезать. */
aside.screen-side {
  display: grid; grid-template-rows: auto auto auto 1fr;
  gap: calc(var(--u) * 1.2); min-height: 0;
}
.hero { border-color: rgba(56, 189, 248, .45); background: rgba(56, 189, 248, .10); position: relative; overflow: hidden; }
.hero.new { animation: pop .8s cubic-bezier(.2, .9, .25, 1.15) 1; }
@keyframes pop {
  0% { transform: scale(.94); box-shadow: 0 0 0 0 rgba(56, 189, 248, .7); }
  60% { transform: scale(1.015); box-shadow: 0 0 calc(var(--u) * 5) 0 rgba(56, 189, 248, .35); }
  100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(56, 189, 248, 0); }
}
.hero .who { display: flex; align-items: baseline; gap: calc(var(--u) * 1.2); }
.hero .bib { font-size: calc(var(--u) * 3.4); font-weight: 800; color: var(--screen-accent); }
.hero .nm { font-size: calc(var(--u) * 2.4); font-weight: 700; }
.hero .meta { color: var(--screen-muted); font-size: calc(var(--u) * 1.4); margin-top: calc(var(--u) * .3); }
.hero .big { display: flex; align-items: baseline; gap: calc(var(--u) * 1.4); margin-top: calc(var(--u) * .8); }
.hero .time { font-size: calc(var(--u) * 5.4); font-weight: 800; line-height: 1; }
.hero .place { font-size: calc(var(--u) * 2); font-weight: 800; color: var(--screen-gold); }
.hero .gap { font-size: calc(var(--u) * 1.9); color: var(--screen-muted); }
.hero .empty { color: var(--screen-muted); font-size: calc(var(--u) * 1.7); }
.ribbon {
  position: absolute; top: calc(var(--u) * 1.1); right: calc(var(--u) * -6);
  transform: rotate(28deg); background: var(--screen-gold); color: #1b1300;
  font-weight: 800; font-size: calc(var(--u) * 1.3); letter-spacing: 1px;
  padding: calc(var(--u) * .4) calc(var(--u) * 6);
}

/* Последние финиши и ближайшие стартующие. Строка одна и та же: номер,
   фамилия, справа время или группа. */
.recent, .oncourse { overflow: hidden; }
.recent .row, .oncourse .row {
  display: flex; align-items: baseline; gap: calc(var(--u) * 1);
  padding: calc(var(--u) * .45) 0; border-top: 1px solid rgba(255, 255, 255, .07);
  font-size: calc(var(--u) * 1.7);
}
.recent .row:first-child, .oncourse .row:first-child { border-top: 0; }
.recent .b, .oncourse .b {
  color: var(--screen-accent); font-weight: 700;
  min-width: calc(var(--u) * 3.5); text-align: right;
}
.recent .n, .oncourse .n { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.recent .p { color: var(--screen-muted); min-width: calc(var(--u) * 2); text-align: right; }
.recent .t { font-weight: 800; min-width: calc(var(--u) * 7); text-align: right; }
.recent .t.st { color: var(--screen-bad); font-weight: 700; }
.recent .row.just { animation: sweep 2.4s ease-out 1; }
.oncourse .g { color: var(--screen-muted); font-size: calc(var(--u) * 1.4); }
.recent .empty, .oncourse .empty { color: var(--screen-muted); font-size: calc(var(--u) * 1.5); }

.leaders { overflow: hidden; }
.leaders .row {
  display: flex; align-items: baseline; gap: calc(var(--u) * 1);
  padding: calc(var(--u) * .5) 0; border-top: 1px solid rgba(255, 255, 255, .07);
  font-size: calc(var(--u) * 1.6);
}
.leaders .row:first-child { border-top: 0; }
.leaders .g { color: var(--screen-muted); min-width: 38%; }
.leaders .n { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.leaders .t { font-weight: 800; color: var(--screen-gold); }
.leaders .empty { color: var(--screen-muted); font-size: calc(var(--u) * 1.5); }

footer.ticker { border-top: 1px solid var(--screen-line); padding-top: calc(var(--u) * .9); overflow: hidden; white-space: nowrap; }
footer.ticker .track {
  display: inline-block; padding-left: 100%;
  font-size: calc(var(--u) * 1.6); color: var(--screen-muted);
  animation: crawl 46s linear infinite;
}
footer.ticker b { color: var(--screen-ink); font-weight: 700; }
footer.ticker .sep { color: var(--screen-accent); margin: 0 calc(var(--u) * 1.6); }
@keyframes crawl { from { transform: translateX(0); } to { transform: translateX(-100%); } }

.state {
  position: fixed; bottom: calc(var(--u) * 1.2); right: calc(var(--u) * 1.6);
  border-radius: 999px; padding: calc(var(--u) * .4) calc(var(--u) * 1.2);
  font-size: calc(var(--u) * 1.4); display: none; z-index: 3;
}
.state.on { display: block; }
.state.quiet { background: rgba(148, 163, 184, .16); border: 1px solid rgba(148, 163, 184, .5); color: #e2e8f0; }
.state.lost { background: rgba(248, 113, 113, .16); border: 1px solid rgba(248, 113, 113, .5); color: #fecaca; }

/* Кнопка голоса — в шапке, сразу за часами: это второе, на что там смотрят,
   и единственное на экране, что вообще нажимают. Значок без подписи: экран
   смотрят с десяти метров, и слов там ровно столько, сколько нужно для
   результатов. Прячется она только тогда, когда голоса в браузере нет вовсе —
   обещать то, чего не будет, хуже, чем не предлагать. */
.speak {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: calc(var(--u) * 4); height: calc(var(--u) * 4);
  border: 1px solid var(--screen-line); background: var(--screen-glass);
  border-radius: 999px; color: var(--screen-muted); cursor: pointer; padding: 0;
}
.speak svg {
  width: calc(var(--u) * 2.4); height: calc(var(--u) * 2.4);
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
/* Перечёркнутый — молчит, обычный — объявляет. Виден всегда ровно один. */
.speak .on { display: none; }
.speak[aria-pressed="true"] { color: var(--screen-accent); border-color: var(--screen-accent); }
.speak[aria-pressed="true"] .on { display: block; }
.speak[aria-pressed="true"] .off { display: none; }
.speak:disabled { display: none; }

/* Панель настроек голоса. Висит под кнопкой, в том же углу, и живёт ровно
   столько, сколько выбирают: щелчок мимо или Esc её закрывают. */
.speak-menu {
  position: fixed; top: calc(var(--u) * 6); right: calc(var(--u) * 2);
  min-width: calc(var(--u) * 18); max-width: 90vw;
  max-height: 70vh; overflow-y: auto;
  background: var(--screen-glass); border: 1px solid var(--screen-line);
  border-radius: calc(var(--u) * 1); padding: calc(var(--u) * .6);
  display: flex; flex-direction: column; gap: 2px; z-index: 5;
  backdrop-filter: blur(8px);
}
.speak-menu[hidden] { display: none; }
.speak-menu__head {
  color: var(--screen-muted); font-size: calc(var(--u) * 1.2);
  padding: calc(var(--u) * .4) calc(var(--u) * .8) calc(var(--u) * .2);
  text-transform: uppercase; letter-spacing: .08em;
}
.speak-menu__item {
  font: inherit; font-size: calc(var(--u) * 1.4); text-align: left;
  padding: calc(var(--u) * .5) calc(var(--u) * .8);
  border: 0; border-radius: calc(var(--u) * .6);
  background: transparent; color: var(--screen-fg, #e2e8f0); cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.speak-menu__item:hover { background: rgba(148, 163, 184, .18); }
.speak-menu__item[aria-current="true"] { color: var(--screen-accent); }
.speak-menu__item[aria-current="true"]::before { content: "✓ "; }
.speak:focus-visible { outline: 2px solid var(--screen-accent); outline-offset: 2px; }

.preview {
  position: fixed; top: 0; left: 0; right: 0; text-align: center;
  background: var(--screen-gold); color: #1b1300; font-weight: 700;
  font-size: calc(var(--u) * 1.5); padding: calc(var(--u) * .5); z-index: 4;
}

/* Телефон. Родитель держит его в варежке на морозе: одна колонка, крупные
   цифры, никакой бегущей строки — её на четырёх дюймах не прочитать. */
@media (max-width: 780px) {
  :root { --u: 1.1vw; }
  body.screen { overflow: auto; }
  .stage { height: auto; min-height: 100%; grid-template-rows: auto auto auto; padding: 14px; gap: 12px; }
  .screen-head { flex-wrap: wrap; gap: 8px; }
  /* Заголовок занимает свою строку целиком и умеет сжиматься: без min-width:0
     блок с длинным названием соревнования держит ширину по самому длинному
     слову, и страница уезжает вправо вместе с таблицей. Экран открывают с
     телефона на склоне, где горизонтальная прокрутка — это потерянный
     результат. */
  .screen-head > div:first-child { flex: 1 1 100%; min-width: 0; }
  .screen-head h1 { overflow-wrap: anywhere; }
  /* Полоса на телефоне занимает то, что осталось, а подпись переносится. */
  .bar { min-width: 0; flex: 1 1 auto; }
  .bar__cap { font-size: 11px; white-space: normal; }
  .board-head .cnt { flex: 1 1 auto; min-width: 0; }
  .recent .row, .oncourse .row { font-size: 12px; }
  .recent .t { min-width: 54px; }
  /* Ячейки сетки по умолчанию не сжимаются ниже своего содержимого, и таблица
     группы — где времена и отставания нельзя переносить — распирала всю
     страницу до 447 точек при окне в 375. Здесь она сжимается, а если всё
     равно не влезает, прокручивается сама, не утаскивая за собой страницу. */
  main.screen-body, .board, aside.screen-side, .card { min-width: 0; }
  .recent .n, .oncourse .n, .leaders .n { min-width: 0; }
  /* Часам на телефоне отдельная строка: иначе они прижимаются к краю и
     наезжают на чипы. */
  .screen-head .clock { border-left: 0; padding-left: 0; margin-left: auto; }
  .screen-head h1 { font-size: 22px; }
  .screen-head .sub { font-size: 13px; }
  .chip { font-size: 12px; padding: 3px 10px; }
  .clock { font-size: 20px; padding-left: 10px; }
  .speak { width: 30px; height: 30px; }
  .speak svg { width: 18px; height: 18px; }
  main.screen-body { grid-template-columns: 1fr; grid-template-rows: auto auto auto; }
  /* Порядок для телефона: сначала «только что», потом лидеры, потом группа —
     сверху вниз по убыванию того, ради чего страницу открыли. */
  aside.screen-side { order: -1; grid-template-rows: auto auto; }
  .card { padding: 12px; border-radius: 12px; }
  .card h3 { font-size: 11px; margin-bottom: 8px; }
  .board-head h2 { font-size: 18px; }
  .board-head .cnt { font-size: 12px; }
  .rows { overflow: visible; }
  table.screen { font-size: 15px; height: auto; }
  table.screen th { font-size: 10px; }
  table.screen td { padding: 7px 6px; }
  table.screen td.gp { width: auto; }
  /* Столбцы, у которых на телевизоре своя ширина, на телефоне отдают её
     фамилии: 375 точек — это ровно на неё и время. Без этого таблица держала
     минимальную ширину в 398 точек, страница уезжала вбок, и с телефона на
     склоне читался обрезанный экран. */
  /* Шапка таблицы на телефоне уходит: слово «ОТСТАВАНИЕ» само по себе шире
     столбца, который подписывает, и держало таблицу в 398 точек при экране в
     375. Столбцы и без подписей очевидны — место, номер, фамилия, время,
     отставание, — а на телевизоре, где место есть, шапка осталась. */
  table.screen thead { display: none; }
  table.screen td.pl, table.screen td.bib { width: auto; padding-right: 2px; }
  table.screen td.tm { padding-left: 2px; }
  .fam { letter-spacing: 0; }
  /* Команда на телефоне не помещается и ломает строку на три: фамилия важнее,
     а команда видна в карточке «только что» и в полных результатах. */
  table.screen .team { display: none; }
  .hero .bib { font-size: 28px; }
  .hero .nm { font-size: 20px; }
  .hero .time { font-size: 40px; }
  .hero .place, .hero .gap { font-size: 15px; }
  .leaders .row { font-size: 14px; }
  footer.ticker { display: none; }
  .state { font-size: 12px; }
}

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