/* КвизON поверх Pico: сцена квиза. Тёмный зал, лучи прожекторов, вывески с лампами.
   Цвета — только палитра ниже, их прозрачности и смеси */

@font-face {
  font-family: "Product Sans";
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/ProductSans-Regular.ttf") format("truetype");
}

@font-face {
  font-family: "Product Sans";
  font-weight: 500;
  font-display: swap;
  src: url("/static/fonts/ProductSans-Medium.ttf") format("truetype");
}

@font-face {
  font-family: "Product Sans";
  font-weight: 700;
  font-display: swap;
  src: url("/static/fonts/ProductSans-Bold.ttf") format("truetype");
}

/* Токены */

[data-theme="dark"] {
  --q-navy: #182a3e;
  --q-surface: #1f354b;
  --q-deep: #0a1221;
  --q-gold: #e0ac59;
  --q-gold-light: #f4da6a;
  --q-muted: rgba(255, 255, 255, 0.64);
  --q-danger: #ef4444;
  /* смеси палитры */
  --q-danger-text: #f58f8f; /* 60% danger + 40% белого */
  --q-danger-soft: #f9b4b4; /* 40% danger + 60% белого */
  --q-danger-deep: #c13a3d; /* 80% danger + 20% deep: белый текст 5.3:1 */
  --q-danger-deeper: #aa353a; /* 70% danger + 30% deep */

  --q-radius: 0.5rem;
  --q-radius-s: 0.25rem;

  /* лампы вывески: горит, погашена, перегорела. Это стопы radial-gradient */
  --bulb-on: #fff 0 0.05rem, var(--q-gold-light) 0.1rem, var(--q-gold) 0.17rem, rgba(224, 172, 89, 0.35) 0.2rem,
    rgba(224, 172, 89, 0) 0.48rem;
  --bulb-off: rgba(255, 255, 255, 0.07) 0 0.13rem, rgba(255, 255, 255, 0.24) 0.14rem 0.19rem,
    rgba(255, 255, 255, 0) 0.21rem;
  --bulb-dead: rgba(255, 255, 255, 0.03) 0 0.13rem, rgba(255, 255, 255, 0.12) 0.14rem 0.19rem,
    rgba(255, 255, 255, 0) 0.21rem;

  --pico-font-family: "Product Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --pico-font-family-sans-serif: var(--pico-font-family);
  --pico-background-color: var(--q-navy);
  --pico-color: #fff;
  --pico-h1-color: #fff;
  --pico-h2-color: #fff;
  --pico-h3-color: #fff;
  --pico-muted-color: var(--q-muted);
  --pico-muted-border-color: rgba(255, 255, 255, 0.1);
  --pico-border-radius: var(--q-radius-s);
  --pico-text-selection-color: rgba(224, 172, 89, 0.35);
  --pico-form-label-font-weight: 500;

  --pico-primary: var(--q-gold);
  --pico-primary-underline: rgba(224, 172, 89, 0.5);
  --pico-primary-hover: var(--q-gold-light);
  --pico-primary-hover-underline: var(--q-gold-light);
  --pico-primary-focus: rgba(244, 218, 106, 0.45);
  /* все кнопки Pico — золотые плашки с тёмным текстом */
  --pico-primary-background: var(--q-gold);
  --pico-primary-border: var(--q-gold);
  --pico-primary-inverse: var(--q-deep);
  --pico-primary-hover-background: var(--q-gold-light);
  --pico-primary-hover-border: var(--q-gold-light);

  --pico-card-background-color: var(--q-surface);
  --pico-card-sectioning-background-color: var(--q-navy);
  --pico-card-border-color: rgba(255, 255, 255, 0.08);
  --pico-card-box-shadow: none;

  --pico-form-element-background-color: var(--q-deep);
  --pico-form-element-selected-background-color: var(--q-deep);
  /* рамка поверх тёмного поля: 3.9:1 к фону страницы */
  --pico-form-element-border-color: rgba(255, 255, 255, 0.48);
  --pico-form-element-color: #fff;
  --pico-form-element-placeholder-color: rgba(255, 255, 255, 0.5);
  --pico-form-element-active-background-color: var(--q-deep);
  --pico-form-element-active-border-color: var(--q-gold-light);
  --pico-form-element-focus-color: rgba(244, 218, 106, 0.35);
  --pico-form-element-invalid-border-color: var(--q-danger);
  /* поле с ошибкой в фокусе меняет рамку на золотую, как обычное: ошибку и дальше видно по кольцу и тексту */
  --pico-form-element-invalid-active-border-color: var(--q-gold-light);
  --pico-form-element-invalid-focus-color: rgba(239, 68, 68, 0.35);
  --pico-del-color: var(--q-danger-text);
  --pico-ins-color: var(--q-gold-light);

  --pico-table-border-color: rgba(255, 255, 255, 0.08);
  --pico-table-row-stripped-background-color: rgba(255, 255, 255, 0.025);
  --pico-modal-overlay-background-color: rgba(10, 18, 33, 0.78);

  /* значки Pico в цветах палитры: календарь золотой, ошибка красная */
  --pico-icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23e0ac59' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
  --pico-icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23ef4444' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");
}

/* Основа */

html {
  scrollbar-color: rgba(224, 172, 89, 0.6) var(--q-deep);
}

/* подвал прижат к низу и на короткой странице входа.
   Колонка не шире экрана: иначе широкая таблица участников раздвигает всю страницу на телефоне */
body {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
  min-height: 100dvh;
}

h1 {
  font-size: clamp(2rem, 1.2rem + 3vw, 2.75rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

:is(a, button, [role="button"], summary):focus-visible {
  outline: 3px solid var(--q-gold-light);
  outline-offset: 3px;
  box-shadow: none;
}

/* кольцо Pico на :focus появляется и от мыши; с клавиатуры фокус виден по :focus-visible выше */
:is(button, [role="button"]):focus:not(:focus-visible) {
  --pico-box-shadow: none;
}

button,
[role="button"] {
  border-radius: var(--q-radius-s);
  font-weight: 700;
}

/* тот же селектор, что у Pico: кольцо фокуса полей 3px вместо 1px */
:where(select, textarea),
input:not([type="submit"], [type="button"], [type="reset"], [type="checkbox"], [type="radio"], [type="file"]) {
  --pico-outline-width: 3px;
}

/* автозаполнение: браузер красит поле своим фоном (Safari — жёлтым) поверх любого !important.
   Закрываем его внутренней тенью цвета поля, кольцо фокуса Pico ложится второй тенью.
   none в --pico-box-shadow сломал бы список теней, поэтому прозрачная тень */
input:-webkit-autofill {
  --pico-box-shadow: 0 0 transparent;
  box-shadow: inset 0 0 0 100vmax var(--q-deep), var(--pico-box-shadow);
  caret-color: #fff;
  -webkit-text-fill-color: #fff;
}

/* выбранная часть даты и времени в новой игре: золото вместо системного голубого */
input::-webkit-datetime-edit-day-field:focus,
input::-webkit-datetime-edit-month-field:focus,
input::-webkit-datetime-edit-year-field:focus,
input::-webkit-datetime-edit-hour-field:focus,
input::-webkit-datetime-edit-minute-field:focus {
  border-radius: 2px;
  background-color: var(--q-gold);
  color: var(--q-deep);
}

label {
  font-size: 0.9375rem;
}

.req {
  color: var(--q-gold-light);
}

hgroup {
  margin-bottom: 1.5rem;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.nowrap {
  white-space: nowrap;
}

/* Зал: два луча прожекторов и затемнение по краям, стоят на месте при прокрутке */

body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    conic-gradient(from 149deg at 0% -10%, rgba(244, 218, 106, 0) 0deg, rgba(244, 218, 106, 0.055) 3deg 9deg, rgba(244, 218, 106, 0) 12deg),
    conic-gradient(from 199deg at 100% -10%, rgba(244, 218, 106, 0) 0deg, rgba(244, 218, 106, 0.055) 3deg 9deg, rgba(244, 218, 106, 0) 12deg),
    radial-gradient(120% 80% at 50% 10%, rgba(10, 18, 33, 0) 55%, rgba(10, 18, 33, 0.55) 100%);
}

/* на широком экране источники ниже углов и лучи положе: сходятся за первой вывеской */
@media (min-aspect-ratio: 1/1) {
  body::before {
    background:
      conic-gradient(from 126deg at 10% -25%, rgba(244, 218, 106, 0) 0deg, rgba(244, 218, 106, 0.05) 4deg 12deg, rgba(244, 218, 106, 0) 16deg),
      conic-gradient(from 218deg at 90% -25%, rgba(244, 218, 106, 0) 0deg, rgba(244, 218, 106, 0.05) 4deg 12deg, rgba(244, 218, 106, 0) 16deg),
      radial-gradient(120% 80% at 50% 10%, rgba(10, 18, 33, 0) 55%, rgba(10, 18, 33, 0.55) 100%);
  }
}

/* Шапка */

body > header.site-header {
  padding-block: 0.5rem 0;
}

.site-header nav li {
  padding-block: 0.375rem;
}

.brand img {
  display: block;
  width: auto;
  height: 2.75rem;
}

@media (min-width: 48rem) {
  .brand img {
    height: 4rem;
  }
}

.site-header form.inline {
  margin: 0;
}

/* пункты шапки: ссылки и кнопка «Выйти» выглядят одинаково */
.site-header .nav-action {
  display: inline-block;
  width: auto;
  margin: 0;
  padding: var(--pico-nav-link-spacing-vertical) var(--pico-nav-link-spacing-horizontal);
  border: 0;
  border-radius: var(--q-radius-s);
  background: none;
  box-shadow: none;
  color: rgba(255, 255, 255, 0.8);
  font-family: inherit;
  font-size: inherit;
  font-weight: 500;
  line-height: var(--pico-line-height);
  letter-spacing: 0;
  text-decoration: none;
  text-transform: none;
  transition: color 0.15s ease-out;
}

.site-header .nav-action:hover {
  background: none;
  color: var(--q-gold-light);
  text-decoration: underline;
  text-decoration-color: var(--q-gold);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.3em;
}

/* Афиша: предстоящие игры */

.playbill {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 2.5rem 2rem;
  margin-top: 0.5rem;
}

.playbill > .show:nth-child(2) {
  --d: 90ms;
}

.playbill > .show:nth-child(3) {
  --d: 180ms;
}

.playbill > .show:nth-child(n + 4) {
  --d: 270ms;
}

/* игра: вывеска с лампами, под ней на полу сцены факты и действие */
.show {
  --inset: 1.875rem;
  container: show / inline-size;
  flex: 1 1 22rem;
  min-width: 0;
  max-width: 36rem;
  margin: 0;
  padding: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
}

/* на ноутбуке вывески идут парами; последняя без пары не растягивается в широкую, а остаётся как пара над ней */
@media (min-width: 64rem) {
  .playbill > .show:last-child:nth-child(odd):not(:first-child) {
    flex-grow: 0;
    flex-basis: calc(50% - 1rem);
  }
}

/* Вывеска с лампами по краю. Лампы — два слоя без лишней разметки:
   ::before — фаза A, ::after — фаза B, по четыре градиента на каждый край.
   Углы принадлежат верхнему и нижнему ряду, боковые ряды отступают на шаг: фазы чередуются по всему кругу */

.marquee {
  --pitch: 1.125rem;
  --tile: calc(var(--pitch) * 2);
  --a: var(--bulb-off);
  --b: var(--bulb-off);
  position: relative;
  isolation: isolate;
  border-radius: var(--q-radius);
  background: var(--q-deep);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08);
}

.marquee::before,
.marquee::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  padding-block: var(--pitch);
  border-radius: inherit;
  pointer-events: none;
  background-size: var(--tile) var(--pitch), var(--tile) var(--pitch), var(--pitch) var(--tile), var(--pitch) var(--tile);
  background-position: left top, left bottom, left top, right top;
  background-repeat: round no-repeat, round no-repeat, no-repeat round, no-repeat round;
  background-origin: padding-box, padding-box, content-box, content-box;
  background-clip: padding-box, padding-box, content-box, content-box;
}

/* слои: верх, низ, левый край, правый край.
   --glow — свет ламп на стене вокруг вывески: его рисует ::before, поэтому он вспыхивает вместе с фазой A */
.marquee::before {
  box-shadow: var(--glow, none);
  background-image:
    radial-gradient(circle at 25% 50%, var(--a)),
    radial-gradient(circle at 75% 50%, var(--a)),
    radial-gradient(circle at 50% 75%, var(--a)),
    radial-gradient(circle at 50% 25%, var(--a));
}

.marquee::after {
  background-image:
    radial-gradient(circle at 75% 50%, var(--b)),
    radial-gradient(circle at 25% 50%, var(--b)),
    radial-gradient(circle at 50% 25%, var(--b)),
    radial-gradient(circle at 50% 75%, var(--b));
}

/* регистрация открыта — горят все лампы, в резерв — половина; число на вывеске горит в обоих случаях.
   --day и --day-glow — цвет и ореол числа, см. .show__day */
.show--open .show__sign,
.outcome--ok.marquee {
  --a: var(--bulb-on);
  --b: var(--bulb-on);
  --glow: 0 0 2.5rem -0.5rem rgba(224, 172, 89, 0.4);
  --day: var(--q-gold-light);
  --day-glow: 0 0 0.12em rgba(224, 172, 89, 0.35);
  box-shadow: 0 0 0 1px rgba(224, 172, 89, 0.4);
}

.show--reserve .show__sign,
.outcome--reserve.marquee {
  --a: var(--bulb-on);
  --glow: 0 0 2rem -0.5rem rgba(224, 172, 89, 0.25);
  --day: var(--q-gold-light);
  --day-glow: 0 0 0.12em rgba(224, 172, 89, 0.35);
  box-shadow: 0 0 0 1px rgba(224, 172, 89, 0.25);
}

.show--finished .show__sign {
  --a: var(--bulb-dead);
  --b: var(--bulb-dead);
}

/* на странице регистрации вывеска горит по состоянию игры, как на афише. После отправки htmx меняет только #registration,
   и вывеску подстраивают под итог правила ниже: по одному на итог, браузер без :has() выбросил бы весь список селекторов.
   initial возвращает переменной значение по умолчанию из var() */
.booth:has(.outcome--ok) .booth__game .show__sign {
  --a: var(--bulb-on);
  --b: var(--bulb-on);
  --glow: 0 0 2.5rem -0.5rem rgba(224, 172, 89, 0.4);
  --day: var(--q-gold-light);
  --day-glow: 0 0 0.12em rgba(224, 172, 89, 0.35);
  box-shadow: 0 0 0 1px rgba(224, 172, 89, 0.4);
}

.booth:has(.outcome--reserve) .booth__game .show__sign {
  --a: var(--bulb-on);
  --b: var(--bulb-off);
  --glow: 0 0 2rem -0.5rem rgba(224, 172, 89, 0.25);
  --day: var(--q-gold-light);
  --day-glow: 0 0 0.12em rgba(224, 172, 89, 0.35);
  box-shadow: 0 0 0 1px rgba(224, 172, 89, 0.25);
}

/* мест не осталось или регистрация ещё не открылась — свет гаснет */
.booth:has(.outcome--closed, .outcome--waiting) .booth__game .show__sign {
  --a: var(--bulb-off);
  --b: var(--bulb-off);
  --glow: initial;
  --day: initial;
  --day-glow: initial;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08);
}

/* форму открыли до начала игры, а отправили после — лампы перегорели */
.booth:has(.outcome--finished) .booth__game .show__sign {
  --a: var(--bulb-dead);
  --b: var(--bulb-dead);
  --glow: initial;
  --day: initial;
  --day-glow: initial;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08);
}

/* Вывеска игры */

.show__sign {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 1.25rem 1.5rem;
  padding: 2rem var(--inset) var(--inset);
}

/* дата: большое число, справа месяц и день недели; время сюда не входит.
   В разметке дата идёт после названия, чтобы читалась вместе с ним, а на вывеске стоит первой */
.show__date {
  display: grid;
  flex: none;
  order: -1;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: 1fr auto;
  grid-template-areas: "day month" "day weekday";
  column-gap: 0.75rem;
  margin: 0;
}

.show__date > time {
  display: contents;
}

/* число на погашенной вывеске серое; на горящей — сплошное золото с ореолом, как у ламп (--day и --day-glow).
   Заливка сплошная, без точек: ряд точек, обрезанный по глифу, ломал контур цифр */
.show__day {
  grid-area: day;
  align-self: end;
  margin-left: -0.04em;
  color: var(--day, rgba(255, 255, 255, 0.5));
  font-size: 4.5rem;
  font-size: clamp(4.5rem, 30cqi, 6.5rem);
  font-weight: 700;
  line-height: 0.8;
  letter-spacing: -0.04em;
  white-space: nowrap;
  text-shadow: var(--day-glow, none);
}

.show__month {
  grid-area: month;
  align-self: end;
  color: #fff;
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.01em;
}

.show__weekday {
  grid-area: weekday;
  margin-top: 0.2rem;
  color: var(--q-muted);
  font-size: 1rem;
  line-height: 1.3;
}

.show__head {
  flex: 1 0 100%;
  min-width: 0;
}

.show__title {
  margin: 0;
  color: #fff;
  font-size: 1.25rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.show__name {
  margin: 0.25rem 0 0;
  color: var(--q-muted);
  font-size: 1rem;
  line-height: 1.35;
}

/* Факты под вывеской: место и время начала */

.show__facts {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.25rem 1.25rem;
  margin: 0;
  padding: 1rem var(--inset) 0;
}

.show__facts > div {
  display: grid;
  align-content: start;
  gap: 0.25rem;
}

.show__facts > div:last-child {
  text-align: right;
}

.show__facts dt {
  margin: 0;
  color: var(--q-muted);
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.01em;
}

.show__facts dd {
  margin: 0;
  color: #fff;
  font-size: 1.0625rem;
  font-weight: 500;
  line-height: 1.3;
  text-wrap: balance;
}

.show__facts > div:last-child dd {
  color: var(--q-gold-light);
  font-size: 1.75rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

/* Действие по состоянию */

/* на афише карточка — колонка: вывеска, факты, плашка. Карточки в одном ряду одной высоты,
   и плашка забирает остаток: если у соседней игры плашка перенеслась в две строки, обе плашки одинаковые */
.playbill > .show {
  display: flex;
  flex-direction: column;
}

.playbill > .show > .show__cta {
  flex-grow: 1;
}

/* подпись слева, значение (отсчёт, «мест нет») справа; не влезают в строку — значение уходит под подпись,
   и строки стоят по центру плашки */
.show__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  align-content: center;
  justify-content: space-between;
  gap: 0.25rem 1rem;
  margin: 1.25rem 0 0;
  padding: 1rem var(--inset) 1.0625rem;
  border-radius: var(--q-radius-s);
  font-size: 1.125rem;
  font-weight: 700;
  line-height: 1.25;
  text-decoration: none;
}

a.show__cta {
  border: 1px solid var(--q-gold);
  background-color: var(--q-gold);
  color: var(--q-deep);
  transition:
    background-color 0.15s ease-out,
    border-color 0.15s ease-out,
    color 0.15s ease-out;
}

a.show__cta:hover {
  border-color: var(--q-gold-light);
  background-color: var(--q-gold-light);
  color: var(--q-deep);
}

a.show__cta:active {
  box-shadow: inset 0 0.125rem 0 rgba(10, 18, 33, 0.28);
}

.show--reserve a.show__cta {
  border-color: rgba(224, 172, 89, 0.6);
  background-color: rgba(224, 172, 89, 0.14);
  color: var(--q-gold-light);
}

/* после резерва: у организатора своя ссылка в любом состоянии */
.show--admin a.show__cta {
  border-color: rgba(224, 172, 89, 0.6);
  background-color: transparent;
  color: var(--q-gold-light);
}

.show--reserve a.show__cta:hover,
.show--admin a.show__cta:hover {
  border-color: var(--q-gold);
  background-color: var(--q-gold);
  color: var(--q-deep);
}

/* регистрация ещё не открыта или закрыта — та же плашка, что и кнопка, только погашенная:
   низ у вывесок всегда одинаковый, а состояние видно по свету, как у ламп */
.show__cta--off {
  border: 1px solid rgba(255, 255, 255, 0.14);
  background-color: rgba(10, 18, 33, 0.55);
  color: rgba(255, 255, 255, 0.8);
  font-weight: 500;
}

.show--closed .show__cta--off {
  color: rgba(255, 255, 255, 0.86);
  font-weight: 700;
}

/* «мест нет» у закрытой регистрации — пояснение, тише подписи */
.show__cta-value {
  color: var(--q-muted);
  font-weight: 500;
}

.show__status {
  margin: 1.25rem 0 0;
  padding: 0 var(--inset);
  color: rgba(255, 255, 255, 0.8);
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1.4;
}

.show__status + .show__cta {
  margin-top: 0.75rem;
}

/* Обратный отсчёт: цифры шрифта разной ширины, поэтому у отсчёта постоянная ширина,
   а текст прижат влево — сдвигаются только последние цифры.
   min-width меряет сам текст, без полей и рамки: «через ЧЧ:ММ:СС» занимает до 7.42em */

.countdown {
  box-sizing: content-box;
  font-weight: 700;
  white-space: nowrap;
}

/* в погашенной плашке отсчёт — золотые цифры того же размера, что подпись: высота как у кнопки */
.show__cta--off .countdown {
  min-width: 7.6em;
  color: var(--q-gold-light);
  text-align: left;
}

:is(.show__status, .outcome) .countdown {
  display: inline-block;
  min-width: 7.6em;
  padding: 0 0.35em;
  border-radius: 0.2rem;
  background: rgba(224, 172, 89, 0.12);
  color: var(--q-gold-light);
  text-align: left;
}

/* Широкая вывеска: одна игра на ноутбуке или планшете. rem в условии — настоящий корень Pico, 17–21px */

@container show (min-width: 34rem) {
  .playbill .show > * {
    --inset: 2.25rem;
  }

  .playbill .show__sign {
    padding-block: 2.25rem 2rem;
  }

  .playbill .show__day {
    font-size: clamp(5rem, 20cqi, 7rem);
  }

  .playbill .show__month {
    font-size: 1.625rem;
  }

  .playbill .show__head {
    flex: 1 1 0;
    text-align: right;
  }

  .playbill .show__title {
    font-size: 1.375rem;
  }

  .playbill .show__facts > div:last-child dd {
    font-size: 2rem;
  }
}

/* Телефон: вывеска ниже, чтобы с шапкой на первый экран помещались и факты, и кнопка.
   Число слева во всю высоту, справа столбиком месяц, день недели, название и лига.
   Высота — четыре шага ламп (144px): по бокам три пары ламп того же шага, что сверху и снизу */
@media (max-width: 35.99rem) {
  .playbill .show {
    --inset: 1.625rem;
  }

  .playbill .show__sign {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas: "day month" "day weekday" "day head";
    align-content: center;
    gap: 0 0.75rem;
    min-height: calc(var(--tile) * 4);
    padding: 1.5rem var(--inset);
  }

  /* число, месяц и день недели встают в сетку вывески рядом с названием */
  .playbill .show__date {
    display: contents;
  }

  /* до 7.25rem число не выше столбика справа; на 320px остаётся место для «КвизON №128» */
  .playbill .show__day {
    font-size: 4.5rem;
    font-size: clamp(4.5rem, 33cqi, 7.25rem);
  }

  .playbill .show__month {
    font-size: 1.25rem;
  }

  .playbill .show__weekday {
    margin-top: 0.125rem;
    font-size: 0.9375rem;
  }

  .playbill .show__head {
    grid-area: head;
    margin-top: 0.5rem;
  }

  .playbill .show__title {
    font-size: 1.125rem;
  }

  .playbill .show__name {
    margin-top: 0.125rem;
    font-size: 0.9375rem;
  }
}

/* Прошедшие игры: тихий список под афишей */

.archive {
  max-width: 48rem;
  margin: 3.5rem auto 0;
}

.empty + .archive {
  margin-top: 3rem;
}

.archive > h2 {
  margin: 0 0 0.75rem;
  color: rgba(255, 255, 255, 0.86);
  font-size: 1.375rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.archive__list {
  margin: 0;
  padding: 0;
  border-top: 1px solid rgba(224, 172, 89, 0.3);
}

.archive__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "date teams" "name teams";
  align-items: center;
  gap: 0.125rem 1rem;
  margin: 0;
  padding: 0.875rem 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  list-style: none;
}

.archive__date {
  grid-area: date;
  margin: 0;
  color: var(--q-muted);
  font-size: 1rem;
  line-height: 1.35;
}

/* дата с годом не рвётся: узкой строке остаётся перенос после запятой, перед днём недели */
.archive__date time {
  color: rgba(255, 255, 255, 0.86);
  font-weight: 700;
  white-space: nowrap;
}

.archive__name {
  grid-area: name;
  margin: 0;
  color: var(--q-muted);
  font-size: 0.9375rem;
  line-height: 1.35;
}

.archive__teams {
  grid-area: teams;
  color: var(--q-gold);
  font-size: 0.9375rem;
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.archive__teams:hover {
  color: var(--q-gold-light);
}

/* колонка дат по самой длинной дате с днём недели: «30 сентября 2030, понедельник» — 14.86em */
@media (min-width: 48rem) {
  .archive__row {
    grid-template-columns: 15rem minmax(0, 1fr) auto;
    grid-template-areas: "date name teams";
    align-items: baseline;
  }
}

/* Пустая афиша — погашенная вывеска */

.empty {
  max-width: 30rem;
  margin: 1.5rem auto 0;
  padding: 3rem 2.25rem 2.5rem;
  text-align: center;
}

.empty h2 {
  margin: 0 0 0.75rem;
  color: #fff;
  font-size: 1.75rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

.empty p {
  color: var(--q-muted);
}

.empty [role="button"] {
  margin-top: 0.25rem;
  padding: 0.75rem 1.5rem;
}

/* ссылки внутри текста подчёркнуты: золото и белый различаются не только цветом */
:is(.empty p, .outcome, .agreement) a {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

:is(.empty p, .outcome) a {
  color: var(--q-gold);
}

.agreement a {
  color: var(--q-gold-light);
}

:is(.empty p, .outcome, .agreement) a:hover {
  color: var(--q-gold-light);
  text-decoration-thickness: 2px;
}

/* Страница регистрации: та же вывеска, что на афише, и форма рядом */

.booth {
  display: grid;
  grid-template-areas: "title" "game" "note" "form";
  gap: 1.25rem;
  max-width: 36rem;
  margin-inline: auto;
}

.booth__title {
  grid-area: title;
  margin: 0;
}

.booth__game {
  grid-area: game;
}

.booth__form {
  grid-area: form;
}

.booth__note {
  display: flex;
  grid-area: note;
  align-items: flex-start;
  gap: 0.625rem;
  margin: 0;
  color: rgba(255, 255, 255, 0.86);
  font-size: 0.9375rem;
  line-height: 1.4;
}

.booth__note svg {
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  fill: var(--q-gold);
}

/* на телефоне вывеска компактная: до формы недалеко листать.
   Высота — целое число шагов ламп, как у вывесок на афише: по бокам лампы стоят с тем же шагом, что сверху и снизу.
   Лишняя высота делится поровну над и под надписями */
.booth__game > * {
  --inset: 1.625rem;
}

.booth__game .show__sign {
  align-content: center;
  gap: 0.5rem 1.25rem;
  min-height: calc(var(--tile) * 4);
  padding: 1.5rem var(--inset);
}

.booth__game .show__day {
  font-size: 3.5rem;
  font-size: clamp(3.5rem, 14cqi, 4.5rem);
}

.booth__game .show__month {
  font-size: 1.125rem;
}

.booth__game .show__weekday {
  margin-top: 0.125rem;
  font-size: 0.9375rem;
}

.booth__game .show__title {
  font-size: 1rem;
}

.booth__game .show__name {
  margin-top: 0.125rem;
  font-size: 0.9375rem;
}

/* на телефонах 360–375px название остаётся под датой: рядом ему хватало меньше 110px, и слова рвались.
   Рядом с датой вывеска ниже — три шага ламп */
@container show (min-width: 22rem) {
  .booth__game .show__sign {
    min-height: calc(var(--tile) * 3);
  }

  .booth__game .show__head {
    flex: 1 1 0;
    text-align: right;
  }
}

/* на ноутбуке вывеска слева и не уезжает, пока заполняют форму */
@media (min-width: 64rem) {
  .booth {
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    grid-template-rows: auto auto 1fr;
    grid-template-areas: "game title" "game note" "game form";
    align-items: start;
    column-gap: 3.5rem;
    max-width: 56rem;
  }

  .booth__game {
    position: sticky;
    top: 1.5rem;
  }

  .booth__game > * {
    --inset: 1.875rem;
  }

  .booth__game .show__sign {
    gap: 1.25rem 1.5rem;
    min-height: calc(var(--tile) * 6);
    padding: 2rem var(--inset) var(--inset);
  }

  .booth__game .show__day {
    font-size: 4.5rem;
    font-size: clamp(4.5rem, 26cqi, 6rem);
  }

  .booth__game .show__month {
    font-size: 1.5rem;
  }

  .booth__game .show__weekday {
    margin-top: 0.2rem;
    font-size: 1rem;
  }

  .booth__game .show__title {
    font-size: 1.25rem;
  }

  .booth__game .show__name {
    margin-top: 0.25rem;
    font-size: 1rem;
  }

  .booth__game .show__head {
    flex: 1 0 100%;
    text-align: left;
  }
}

/* Формы */

.agreement {
  margin: 1rem 0 0;
  color: var(--q-muted);
  font-size: 0.8125rem;
  line-height: 1.45;
}

/* большие кнопки только в формах; «Выйти» в шапке и удаление в таблице живут по своим правилам */
:is(.booth__form, .sheet) button[type="submit"] {
  margin: 0.5rem 0 0;
  padding: 0.875rem 1rem;
  font-size: 1.125rem;
  line-height: 1.25;
}

:is(.booth__form, .sheet) button[type="submit"]:active {
  transform: translateY(1px);
}

/* пока htmx отправляет форму, по низу кнопки бегут огоньки.
   Курсор — на форме: отключённая кнопка у Pico не ловит указатель */
.booth__form form.htmx-request {
  cursor: progress;
}

.booth__form form.htmx-request button[type="submit"] {
  background-image: radial-gradient(circle, rgba(10, 18, 33, 0.6) 0 0.12rem, rgba(10, 18, 33, 0) 0.16rem);
  background-position: 0 calc(100% - 0.35rem);
  background-size: 0.75rem 0.5rem;
  background-repeat: repeat-x;
}

.form-error {
  margin-bottom: 1rem;
  padding: 0.75rem 1rem;
  border-left: 3px solid var(--q-danger);
  border-radius: var(--q-radius-s);
  background: rgba(239, 68, 68, 0.14);
  color: var(--q-danger-soft);
}

/* вход и новая игра: заголовок на погашенной вывеске, форма под ней прямо на сцене */
.sheet {
  max-width: 32rem;
  margin: 0 auto;
}

.sheet.narrow {
  max-width: 22rem;
}

.sheet > h1,
.sheet > hgroup {
  margin-bottom: 1.5rem;
}

/* высота вывески — целое число шагов ламп, тогда по бокам лампы стоят с тем же шагом, что сверху и снизу */
.sheet__sign {
  display: grid;
  align-content: center;
  min-height: calc(var(--tile) * 3);
  padding: 1.375rem 1.875rem;
  text-align: center;
}

/* у входа под заголовком подпись, вывеска на шаг выше */
hgroup.sheet__sign {
  gap: 0.375rem;
  min-height: calc(var(--tile) * 4);
}

/* Итог регистрации */

.outcome {
  padding: 1.5rem 1.5rem 1.25rem;
  border-radius: var(--q-radius);
  background: var(--q-deep);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1);
}

.outcome h2 {
  margin: 0 0 0.75rem;
  color: #fff;
  font-size: 1.375rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

/* app.js ставит фокус на заголовок итога после htmx-замены, чтобы его прочитал экранный диктор; рамка тут не нужна */
.outcome h2[tabindex="-1"]:focus {
  outline: none;
}

.outcome p:last-child {
  margin-bottom: 0;
}

.outcome time {
  white-space: nowrap;
}

/* зарегистрировались — вокруг итога зажигаются лампы */
.outcome.marquee {
  padding: 2.25rem 1.875rem 2rem;
}

.outcome--ok h2 {
  color: var(--q-gold-light);
  font-size: 1.75rem;
}

.outcome--reserve h2 {
  color: var(--q-gold-light);
  font-size: 1.5rem;
}

/* на ноутбуке лампы зажигаются на вывеске слева, итог — обычная панель */
@media (min-width: 64rem) {
  .booth .outcome.marquee {
    padding: 1.5rem 1.5rem 1.25rem;
  }

  .booth .outcome.marquee::before,
  .booth .outcome.marquee::after {
    content: none;
  }
}

/* Участники: табло */

.wide hgroup {
  margin-bottom: 1.5rem;
}

#teams {
  overflow: hidden;
  border: 1px solid rgba(224, 172, 89, 0.28);
  border-radius: 0.375rem;
  background: var(--q-deep);
}

#teams > p {
  margin: 0;
  padding: 1.25rem 1rem;
  color: var(--q-muted);
}

/* прокрутка таблицы — опора для абсолютно позиционированного содержимого. Без неё скрытая подпись колонки
   удаления (.visually-hidden) привязывается к документу и стоит у правого края таблицы, около 700px:
   на телефоне документ становится шире экрана, браузер растягивает под него область фиксированных элементов,
   и окно удаления уезжает вправо вниз */
#teams .overflow-auto {
  position: relative;
}

/* над таблицей счётчик, места из настроек игры и выгрузка */
.teams-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1rem;
  margin: 0;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.teams-bar p {
  margin: 0;
  color: var(--q-gold-light);
  font-size: 1.25rem;
  font-weight: 700;
}

/* места из настроек игры: на телефоне и узком планшете отдельной строкой под счётчиком и кнопкой выгрузки.
   Подпись и число — как в фактах под вывеской */
.teams-places {
  display: flex;
  flex-basis: 100%;
  order: 1;
  gap: 1rem;
  margin: 0;
}

.teams-places > div {
  display: grid;
  gap: 0.125rem;
}

.teams-places dt {
  color: var(--q-muted);
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.01em;
}

.teams-places dd {
  margin: 0;
  color: var(--q-gold-light);
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
}

/* от 768px всё в одну строку: места сразу за счётчиком, кнопка справа. Меньше 768px строка не помещается,
   и кнопка осталась бы одна во втором ряду. «Команд: N», числа мест и надпись на кнопке — на одной базовой линии.
   Черта отделяет места от счётчика, иначе числа подряд читаются как «3 2 1» */
@media (min-width: 48rem) {
  .teams-bar {
    align-items: last baseline;
  }

  .teams-places {
    flex-basis: auto;
    order: 0;
    margin-right: auto;
    padding-left: 1rem;
    border-left: 1px solid rgba(255, 255, 255, 0.12);
  }
}

/* auto слева держит кнопку справа, даже если она перенесётся в свой ряд */
.teams-bar [role="button"] {
  width: auto;
  margin: 0 0 0 auto;
  padding: 0.45rem 0.9rem;
  border-width: 1px;
  font-size: 0.875rem;
}

/* плотнее, чем у Pico: на 14-дюймовом ноутбуке Pico даёт контейнеру 1200px и шрифт 20px,
   и с его отступами ячеек десять колонок туда не влезали */
.teams-table {
  --pico-background-color: transparent;
  margin: 0;
  font-size: 0.8125rem;
}

.teams-table th,
.teams-table td {
  padding: 0.5rem 0.55rem;
}

.teams-table th:first-child,
.teams-table td:first-child {
  padding-left: 1rem;
}

.teams-table th:last-child,
.teams-table td:last-child {
  padding-right: 0.75rem;
}

.teams-table thead th {
  --pico-font-weight: 500;
  border-bottom: 2px solid rgba(224, 172, 89, 0.55);
  background-color: var(--q-surface);
  color: var(--q-gold);
  font-size: 0.75rem;
  line-height: 1.25;
  vertical-align: bottom;
}

.teams-table thead th:first-child {
  text-align: right;
}

/* номер в основе — с горящей лампой слева */
.teams-table td:first-child {
  width: 1%;
  background-image: radial-gradient(circle at 0.6rem 50%, var(--q-gold-light) 0 0.14rem, rgba(244, 218, 106, 0.35) 0.17rem, rgba(244, 218, 106, 0) 0.34rem);
  background-repeat: no-repeat;
  color: var(--q-gold-light);
  font-size: 1.0625rem;
  font-weight: 700;
  line-height: 1.2;
  text-align: right;
  white-space: nowrap;
}

.teams-table td:nth-child(2) {
  font-weight: 700;
}

/* длинные названия и ники переносятся, а не растягивают таблицу */
.teams-table td:is(:nth-child(2), :nth-child(3), :nth-child(5)) {
  overflow-wrap: anywhere;
}

.teams-table.striped tbody tr:not(.is-deleted):hover > td {
  background-color: rgba(224, 172, 89, 0.07);
}

.teams-table tr.is-reserve td {
  color: rgba(255, 255, 255, 0.72);
}

/* в резерве лампа не горит: одно кольцо */
.teams-table tr.is-reserve td:first-child {
  background-image: radial-gradient(circle at 0.6rem 50%, rgba(224, 172, 89, 0) 0 0.12rem, rgba(224, 172, 89, 0.75) 0.13rem 0.19rem, rgba(224, 172, 89, 0) 0.21rem);
  color: rgba(224, 172, 89, 0.75);
}

/* граница между основным составом и резервом, на ней ярлык */
.teams-table tr.reserve-start > td {
  border-top: 2px solid var(--q-gold);
}

.teams-table tr.reserve-start > td:first-child {
  position: relative;
}

.teams-table tr.reserve-start > td:first-child::before {
  content: "резерв";
  content: "резерв" / "";
  position: absolute;
  top: 0;
  left: 0.75rem;
  padding: 0.05rem 0.4rem;
  border-radius: 2px;
  background: var(--q-gold);
  color: var(--q-deep);
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1.4;
  white-space: nowrap;
  pointer-events: none;
  transform: translateY(-50%);
}

/* удалённая команда: тусклее резерва, без номера и лампы, название зачёркнуто */
.teams-table tr.is-deleted td {
  color: rgba(255, 255, 255, 0.5);
}

.teams-table tr.is-deleted td:nth-child(2) {
  font-weight: 500;
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}

.teams-table tr.is-deleted td:first-child {
  background-image: none;
}

.teams-table tr.is-deleted td:first-child::before {
  content: "—";
  content: "—" / "";
  color: rgba(255, 255, 255, 0.35);
  font-size: 0.8125rem;
  font-weight: 400;
}

.row-action {
  margin: 0;
}

.row-action .icon-button {
  display: block;
  width: auto;
  margin: 0;
  padding: 0.25rem;
  border: 0;
  border-radius: var(--q-radius-s);
  background: none;
  box-shadow: none;
  color: var(--q-muted);
  transition:
    background-color 0.15s ease-out,
    color 0.15s ease-out;
}

.row-action .icon-button:hover {
  background: rgba(239, 68, 68, 0.16);
  color: var(--q-danger-text);
}

.row-action .icon-button:focus-visible {
  outline-offset: 2px;
}

.icon-button svg {
  display: block;
  width: 1.25rem;
  height: 1.25rem;
  fill: currentColor;
}

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

/* пока окно открыто, страница под ним не прокручивается */
:root:has(dialog[open]) {
  overflow: hidden;
}

/* окно — погашенная вывеска: гнёзда ламп по краю, кнопки внутри вывески.
   Фон окна и затемнение вокруг почти одного цвета, край держит красная кайма: 3.4:1 к затемнению */
.confirm > article {
  max-width: 26rem;
  padding: 2rem 1.875rem 1.875rem;
  border: 0;
  border-radius: var(--q-radius);
  background: var(--q-deep);
  box-shadow:
    0 0 0 1px rgba(239, 68, 68, 0.8),
    0 1.5rem 3rem rgba(10, 18, 33, 0.6);
}

.confirm h2 {
  margin: 0 0 0.75rem;
  color: #fff;
  font-size: 1.3rem;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

.confirm p {
  margin: 0 0 1.5rem;
  color: var(--q-muted);
}

/* подвал Pico — полоса другого цвета во всю ширину, она легла бы на нижний ряд ламп */
.confirm > article > footer {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
}

.confirm form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem;
  margin: 0;
}

/* (0,2,2) — сильнее отступа Pico у второй кнопки в подвале окна (0,1,4): кнопки равной ширины */
.confirm > article > footer :is(.confirm__cancel, .confirm__danger) {
  width: 100%;
  margin: 0;
  padding: 0.75rem 1rem;
  border-width: 1px;
  border-style: solid;
  border-radius: var(--q-radius-s);
  box-shadow: none;
  font-weight: 700;
}

.confirm .confirm__cancel {
  border-color: rgba(255, 255, 255, 0.4);
  background: transparent;
  color: #fff;
}

.confirm .confirm__cancel:hover {
  border-color: #fff;
}

.confirm .confirm__danger {
  border-color: var(--q-danger-deep);
  background: var(--q-danger-deep);
  color: #fff;
}

.confirm .confirm__danger:hover {
  border-color: var(--q-danger-deeper);
  background: var(--q-danger-deeper);
}

/* Подвал: край сцены с рампой */

.site-footer {
  position: relative;
  margin-top: 4rem;
  padding-block: 2.5rem 2rem;
  border-top: 1px solid rgba(224, 172, 89, 0.25);
  background: var(--q-deep);
  text-align: center;
}

.site-footer::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 0.75rem;
  pointer-events: none;
  background: radial-gradient(circle, rgba(244, 218, 106, 0.75) 0 0.08rem, rgba(224, 172, 89, 0.22) 0.14rem, rgba(224, 172, 89, 0) 0.3rem) left center / 1.5rem 0.75rem round no-repeat;
  transform: translateY(-50%);
}

.site-footer__logo {
  width: 90px;
  height: auto;
}

.socials {
  display: flex;
  justify-content: center;
  gap: 3rem;
  max-width: 24rem;
  margin: 1.25rem auto;
  padding: 0 0 1.25rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}

.socials li {
  margin: 0;
  list-style: none;
}

.socials a {
  display: block;
  color: var(--q-muted);
  transition: color 0.15s ease-out;
}

.socials a:hover {
  color: var(--q-gold-light);
}

.socials svg {
  display: block;
  width: 1.75rem;
  height: 1.75rem;
  fill: currentColor;
}

.site-footer p {
  margin: 0 0 0.5rem;
  color: rgba(255, 255, 255, 0.5);
  font-size: 0.8125rem;
  font-weight: 500;
}

.site-footer p a {
  color: var(--q-muted);
  text-decoration: underline;
  text-decoration-color: rgba(255, 255, 255, 0.3);
  text-underline-offset: 0.2em;
}

.site-footer p a:hover {
  color: var(--q-gold-light);
  text-decoration-color: currentColor;
}

/* Движение. Ключевые кадры описывают только начало, конец — объявленное состояние:
   без анимаций (prefers-reduced-motion) всё сразу на месте, лампы горят */

@media (prefers-reduced-motion: no-preference) {
  /* свет в зале */
  body::before {
    animation: fade-in 1.2s cubic-bezier(0.4, 0, 0.2, 1) 0.1s backwards;
  }

  /* афиша: вывески проявляются, лампы вспыхивают фазой A, через 120 мс фазой B, число загорается последним.
     Вывеска на странице регистрации загорается так же, как первая на афише */
  .playbill > .show {
    animation: fade-in 0.5s ease-out calc(200ms + var(--d, 0ms)) backwards;
  }

  .playbill > :is(.show--open, .show--reserve) > .show__sign::before,
  .booth__game:is(.show--open, .show--reserve) > .show__sign::before {
    animation: power-on 0.9s linear calc(550ms + var(--d, 0ms)) backwards;
  }

  .playbill > .show--open > .show__sign::after,
  .booth__game.show--open > .show__sign::after {
    animation: power-on 0.9s linear calc(670ms + var(--d, 0ms)) backwards;
  }

  .playbill > :is(.show--open, .show--reserve) .show__day,
  .booth__game:is(.show--open, .show--reserve) .show__day {
    animation: number-on 0.5s ease-out calc(900ms + var(--d, 0ms)) backwards;
  }

  .empty {
    animation: fade-in 0.5s ease-out 0.2s backwards;
  }

  .archive {
    animation: fade-in 0.5s ease-out 0.45s backwards;
  }

  .booth__game {
    animation: fade-in 0.5s ease-out 0.2s backwards;
  }

  /* #teams переживает htmx-замену содержимого, поэтому после удаления не мигает */
  #teams {
    animation: fade-in 0.4s ease-out 0.1s backwards;
  }

  .outcome {
    animation: fade-in 0.45s ease-out backwards;
  }

  /* зарегистрировались: лампы вокруг итога вспыхивают и трижды бегут по кругу */
  .outcome--ok.marquee::before {
    animation:
      power-on 0.9s linear 0.15s backwards,
      chase 0.5s linear 1.05s 3;
  }

  .outcome--ok.marquee::after {
    animation:
      power-on 0.9s linear 0.27s backwards,
      chase 0.5s linear 1.3s 3;
  }

  .outcome--reserve.marquee::before {
    animation: power-on 0.9s linear 0.15s backwards;
  }

  /* на ноутбуке то же самое делает вывеска слева. Уже горевшая с загрузки не вспыхивает заново:
     power-on с тем же именем браузер продолжает, а не запускает снова, и лампы просто бегут по кругу */
  @media (min-width: 64rem) {
    .booth:has(.outcome--ok) .booth__game .show__sign::before {
      animation:
        power-on 0.9s linear 0.15s backwards,
        chase 0.5s linear 1.05s 3;
    }

    .booth:has(.outcome--ok) .booth__game .show__sign::after {
      animation:
        power-on 0.9s linear 0.27s backwards,
        chase 0.5s linear 1.3s 3;
    }

    .booth:has(.outcome--reserve) .booth__game .show__sign::before {
      animation: power-on 0.9s linear 0.15s backwards;
    }
  }

  .booth__form form.htmx-request button[type="submit"] {
    animation: march 0.45s steps(3) infinite;
  }

  .confirm > article {
    animation: confirm-in 0.16s ease-out;
  }
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
}

/* лампа накаливания: вспышка, провал, дрожание, ровный свет */
@keyframes power-on {
  0% {
    opacity: 0;
  }

  6% {
    opacity: 1;
  }

  11% {
    opacity: 0.15;
  }

  18% {
    opacity: 0.9;
  }

  24% {
    opacity: 0.3;
  }

  34%,
  100% {
    opacity: 1;
  }
}

@keyframes number-on {
  from {
    opacity: 0.35;
  }
}

@keyframes chase {
  0%,
  42% {
    opacity: 1;
  }

  50%,
  92% {
    opacity: 0.2;
  }

  100% {
    opacity: 1;
  }
}

@keyframes march {
  to {
    background-position: 0.75rem calc(100% - 0.35rem);
  }
}

@keyframes confirm-in {
  from {
    opacity: 0;
    transform: translateY(0.75rem) scale(0.98);
  }
}

/* Режим высокой контрастности: тени и градиенты пропадают, поэтому границы — настоящие рамки */

@media (forced-colors: active) {
  .marquee,
  .outcome,
  #teams,
  a.show__cta,
  .show__cta--off {
    border: 1px solid CanvasText;
  }

  .confirm > article {
    border: 2px solid CanvasText;
  }

  /* фокус полей у Pico — тень, а теней в этом режиме нет */
  :where(input, select, textarea):focus-visible {
    outline: 2px solid Highlight;
    outline-offset: 2px;
  }

  body::before,
  .marquee::before,
  .marquee::after,
  .site-footer::before {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition: none !important;
    animation: none !important;
    scroll-behavior: auto !important;
  }
}
