/* =========================================================
   ACID UNO — FEATURE LAYER

   Свечение активного цвета вокруг карты на столе,
   крупный счётчик кластера +2/+4,
   таймер партии и кнопка звука.

   Базовый дизайн и токены — в style.css.
   ========================================================= */


/* =========================================================
   АУРА АКТИВНОГО ЦВЕТА

   Свечение живёт вокруг верхней карты сброса и всегда
   показывает цвет, которым сейчас ходят, а не цвет самой
   карты: после Wild аура окрашивается в выбранный цвет.
   ========================================================= */

.discardPile {
  --aura: var(--purple);
  --aura-strong: rgba(139, 61, 255, .70);
  --aura-soft: rgba(139, 61, 255, .26);
}

.discardPile[data-color="red"] {
  --aura: var(--red);
  --aura-strong: rgba(255, 49, 88, .78);
  --aura-soft: rgba(255, 49, 88, .30);
}

.discardPile[data-color="yellow"] {
  --aura: var(--yellow);
  --aura-strong: rgba(255, 232, 61, .70);
  --aura-soft: rgba(255, 232, 61, .26);
}

.discardPile[data-color="green"] {
  --aura: var(--green);
  --aura-strong: rgba(72, 255, 119, .74);
  --aura-soft: rgba(72, 255, 119, .28);
}

.discardPile[data-color="blue"] {
  --aura: var(--blue);
  --aura-strong: rgba(50, 168, 255, .78);
  --aura-soft: rgba(50, 168, 255, .30);
}


.discardPile::after {
  content: "";

  position: absolute;
  inset: -13px -11px -11px -13px;

  border-radius: 24px;

  z-index: -2;

  pointer-events: none;

  background:
    radial-gradient(
      ellipse at center,
      var(--aura-soft) 0%,
      rgba(0, 0, 0, 0) 72%
    );

  box-shadow:
    0 0 18px 2px var(--aura-strong),
    0 0 46px 12px var(--aura-soft);

  opacity: .95;

  transition:
    box-shadow .32s ease,
    background .32s ease;

  animation:
    acidAuraBreath 3.1s ease-in-out infinite;
}


@keyframes acidAuraBreath {
  0%,
  100% {
    transform: scale(1);
    opacity: .82;
  }

  50% {
    transform: scale(1.045);
    opacity: 1;
  }
}


/*
  Смена цвета — короткая вспышка ауры.
*/
.discardPile.aura-shift::after {
  animation:
    acidAuraShift .52s ease-out,
    acidAuraBreath 3.1s ease-in-out .52s infinite;
}

@keyframes acidAuraShift {
  0% {
    transform: scale(.86);
    opacity: .25;
  }

  55% {
    transform: scale(1.22);
    opacity: 1;
  }

  100% {
    transform: scale(1);
    opacity: .9;
  }
}


@media (prefers-reduced-motion: reduce) {
  .discardPile::after,
  .discardPile.aura-shift::after {
    animation: none;
  }
}


/* =========================================================
   КЛАСТЕР +2 / +4

   Крупное число: сколько карт заберёшь, если не покроешь.
   ========================================================= */

.stackHUD {
  position: absolute;

  left: 50%;
  top: 8px;

  transform: translateX(-50%);

  z-index: 9;

  display: grid;
  justify-items: center;
  gap: 2px;

  pointer-events: none;

  text-align: center;

  transition:
    opacity .22s ease,
    transform .22s ease;
}

.stackHUD.hidden {
  display: grid;

  opacity: 0;

  transform:
    translateX(-50%) scale(.7);
}

.stackHUDLabel {
  font-size: 11px;
  font-weight: 900;

  letter-spacing: .18em;

  color: rgba(255, 255, 255, .72);

  text-shadow:
    0 0 12px rgba(255, 43, 214, .8);
}

.stackHUDValue {
  font-size: 74px;
  line-height: .86;
  font-weight: 900;

  letter-spacing: -.03em;

  color: var(--white);

  text-shadow:
    0 0 10px rgba(255, 255, 255, .55),
    0 0 26px var(--magenta),
    0 0 58px rgba(255, 43, 214, .7);
}

.stackHUDCards {
  font-size: 11px;
  font-weight: 900;

  letter-spacing: .16em;

  color: rgba(255, 255, 255, .55);
}


/*
  Кластер вырос — число ударяет.
*/
.stackHUD.bump .stackHUDValue {
  animation: acidStackBump .42s cubic-bezier(.2, .9, .2, 1);
}

@keyframes acidStackBump {
  0% {
    transform: scale(.55);
    opacity: .2;
  }

  50% {
    transform: scale(1.32);
  }

  100% {
    transform: scale(1);
  }
}


/*
  Кластер направлен в тебя — число становится тревожным.
*/
.stackHUD.mine .stackHUDValue {
  color: #fff0f4;

  text-shadow:
    0 0 10px rgba(255, 255, 255, .6),
    0 0 26px var(--red),
    0 0 62px rgba(255, 49, 88, .8);
}

.stackHUD.mine .stackHUDLabel {
  color: #ffd8e0;

  text-shadow:
    0 0 12px rgba(255, 49, 88, .9);
}


/*
  В альбомной ориентации веер бота свисает на верхнюю кромку
  стола, поэтому счётчик уходит на свободное правое поле.
*/
@media (orientation: landscape) {

  .stackHUD {
    left: auto;
    right: 4%;

    top: 50%;

    transform: translateY(-50%);
  }

  .stackHUD.hidden {
    transform:
      translateY(-50%) scale(.7);
  }
}


@media (max-width: 520px),
       (max-height: 460px) {

  .stackHUDValue {
    font-size: 52px;
  }

  .stackHUD {
    top: 4px;
  }
}


@media (orientation: landscape) and (max-height: 460px) {

  .stackHUD {
    top: 50%;
  }

  .stackHUDValue {
    font-size: 46px;
  }
}


/* =========================================================
   ТАЙМЕР ПАРТИИ

   Появляется только за минуту до конца.
   ========================================================= */

/*
  Таймер стоит рядом с логотипом: по центру шапки на него
  наезжает веер бота.
*/
.topbarLead {
  display: flex;

  align-items: center;

  gap: 12px;

  min-width: 0;
}

.matchClock {
  padding: 5px 12px;

  border-radius: var(--ui-cut);

  border:
    1px solid var(--panel-line-purple);

  background: rgba(10, 5, 22, .72);

  backdrop-filter: blur(8px);

  font-size: 20px;
  font-weight: 900;

  letter-spacing: .06em;

  font-variant-numeric: tabular-nums;

  color: var(--white);

  text-shadow:
    0 0 14px rgba(183, 255, 36, .55);

  pointer-events: none;

  transition: opacity .3s ease;
}

.matchClock.hidden {
  display: none;
}

.matchClock.urgent {
  border-color: rgba(255, 49, 88, .6);

  color: #ffe4ea;

  text-shadow:
    0 0 16px rgba(255, 49, 88, .9);

  animation: acidClockPulse 1s steps(1) infinite;
}

@keyframes acidClockPulse {
  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: .45;
  }
}


/* =========================================================
   ЗВУК
   ========================================================= */

/*
  Кнопки справа держатся вместе: у .topbar
  justify-content: space-between, и одиночная кнопка
  уехала бы в центр.
*/
.topbarActions {
  display: flex;

  align-items: center;

  gap: 8px;
}

.soundButton {
  font-size: 17px;
}

.soundButton.muted {
  opacity: .42;
}


/* =========================================================
   ИТОГ ПО ОЧКАМ
   ========================================================= */

.endScore {
  display: grid;
  gap: 8px;

  margin: 12px 0 6px;

  font-size: 13px;
  font-weight: 800;

  letter-spacing: .1em;

  color: rgba(255, 255, 255, .74);
}

.endScore.hidden {
  display: none;
}

.endScoreRow {
  display: flex;

  align-items: baseline;
  justify-content: space-between;

  gap: 18px;
}

.endScoreRow b {
  font-size: 19px;

  color: var(--acid);

  text-shadow:
    0 0 14px rgba(183, 255, 36, .5);
}

.endScoreRow.lost b {
  color: var(--magenta);

  text-shadow:
    0 0 14px rgba(255, 43, 214, .5);
}


/* =========================================================
   Мелкая плашка «ШТРАФ +N» из топбара заменена крупным
   счётчиком над столом (.stackHUD) — оставлять обе значит
   показывать одно и то же дважды.
   ========================================================= */

.penalty {
  display: none;
}


/* =========================================================
   СОПЕРНИКИ

   Рассадка по дуге вокруг стола, как в макете v1.0: ты
   снизу, остальные разложены по верхней половине круга.
   У каждого настоящий веер рубашек — за столом количество
   карт читают по толщине веера, а не по цифре.

   Место задаётся единичным вектором --sx/--sy из JS,
   радиусы дуги — здесь: в альбоме шире и ниже, в портрете
   выше и уже.
   ========================================================= */

.opponents {
  position: absolute;

  inset: 0;

  z-index: 14;

  pointer-events: none;

  /*
    Центр дуги и радиусы. Верхний край дуги не должен
    заезжать под шапку с логотипом и кнопками, поэтому
    вертикальный радиус заметно меньше горизонтального.
  */
  --arc-x: 50%;
  --arc-y: 50%;
  --arc-rx: 39%;
  --arc-ry: 27%;
}

.opponents.hidden {
  display: none;
}


.opponent {
  position: absolute;

  left:
    calc(
      var(--arc-x) +
      var(--sx) * var(--arc-rx)
    );

  top:
    calc(
      var(--arc-y) +
      var(--sy) * var(--arc-ry)
    );

  transform: translate(-50%, -50%);

  width: 132px;

  padding: 0;

  display: grid;

  justify-items: center;

  gap: 4px;

  border: 0;

  background: none;

  color: var(--white);

  font-family: inherit;

  pointer-events: auto;

  cursor: pointer;

  transition: transform .25s ease;
}


/* веер рубашек */

.opponentFan {
  position: relative;

  display: block;

  width: 100%;

  height: 50px;
}

.opponentBack {
  position: absolute;

  left: 50%;
  top: 0;

  width: 30px;
  height: 44px;

  margin-left: -15px;

  border-radius: 4px;

  border:
    1px solid rgba(186, 73, 255, .65);

  background:
    linear-gradient(
      152deg,
      rgba(120, 45, 220, .95),
      rgba(38, 12, 70, .95)
    );

  box-shadow:
    0 2px 5px rgba(0, 0, 0, .5);

  /*
    Каждая рубашка сдвинута и повёрнута относительно
    середины веера: --i её номер, --fan общее число.
  */
  --half: calc((var(--fan) - 1) / 2);

  transform:
    translateX(
      calc((var(--i) - var(--half)) * var(--fan-step, 14px))
    )
    rotate(
      calc((var(--i) - var(--half)) * 7deg)
    );

  transform-origin: 50% 130%;
}


/* табличка с именем и числом */

.opponentPlate {
  display: flex;

  align-items: center;

  gap: 6px;

  padding: 5px 11px 5px 6px;

  border-radius: 14px;

  border:
    1px solid rgba(181, 93, 255, .45);

  background: rgba(12, 6, 26, .9);

  box-shadow:
    0 6px 16px rgba(0, 0, 0, .5);

  transition:
    border-color .25s ease,
    box-shadow .25s ease;
}

.opponentFace {
  font-size: 22px;

  line-height: 1;
}

.opponentName {
  font-size: 11px;
  font-weight: 900;

  letter-spacing: .1em;

  color: rgba(255, 255, 255, .6);

  white-space: nowrap;
}

.opponentCount {
  min-width: 22px;

  font-size: 20px;
  font-weight: 1000;

  line-height: 1;

  text-align: center;

  color: var(--acid);

  text-shadow:
    0 0 12px rgba(183, 255, 36, .55);
}


/* чей ход */

.opponent.is-active {
  transform:
    translate(-50%, -50%) scale(1.06);
}

.opponent.is-active .opponentPlate {
  border-color: rgba(183, 255, 36, .8);

  box-shadow:
    0 0 14px rgba(183, 255, 36, .4),
    0 6px 16px rgba(0, 0, 0, .5);
}

.opponent.is-active .opponentBack {
  border-color: rgba(183, 255, 36, .5);
}


/* осталась одна карта */

.opponent.is-low .opponentCount {
  color: var(--magenta);

  text-shadow:
    0 0 14px rgba(255, 43, 214, .85);
}


/* не сказал UNO — можно ловить */

.opponent.catchable .opponentPlate {
  border-color: rgba(255, 49, 88, .9);

  animation:
    acidCatchable .6s ease-in-out infinite;
}

@keyframes acidCatchable {
  0%,
  100% {
    box-shadow:
      0 0 10px rgba(255, 49, 88, .45);
  }

  50% {
    box-shadow:
      0 0 26px rgba(255, 49, 88, .95);
  }
}


/* тесный стол — значки мельче */

.opponents[data-count="5"],
.opponents[data-count="6"] {
  --arc-rx: 43%;
}

.opponents[data-count="5"] .opponent,
.opponents[data-count="6"] .opponent {
  width: 86px;
}

.opponents[data-count="5"] .opponentName,
.opponents[data-count="6"] .opponentName {
  display: none;
}


@media (max-width: 560px) {

  .opponents {
    /*
      Веер соперника рисуется над его плашкой и торчит вверх
      примерно на треть своей высоты. При прежних 33% он
      наезжал на кнопки шапки. Опущено ровно настолько,
      чтобы веер проходил под ними, низ дуги при этом всё
      равно далеко до руки.
    */
    --arc-y: 37%;
    --arc-rx: 38%;
    --arc-ry: 24%;
  }

  .opponent {
    width: 84px;
  }

  .opponentFan {
    height: 26px;
  }

  .opponentBack {
    width: 16px;
    height: 24px;

    margin-left: -8px;
  }

  .opponentName {
    display: none;
  }
}


/*
  Телефон в альбоме: стол широкий и низкий, дуга становится
  плоской, значки прижимаются к краям.
*/
@media (orientation: landscape) and (max-height: 560px) {

  .opponents {
    --arc-y: 46%;
    --arc-rx: 43%;
    --arc-ry: 30%;
  }

  .opponent {
    width: 74px;
  }

  .opponentFan {
    height: 22px;
  }

  .opponentBack {
    width: 14px;
    height: 20px;

    margin-left: -7px;
  }

  .opponentName {
    display: none;
  }

  .opponentPlate {
    padding: 3px 7px 3px 4px;
  }

  .opponentFace {
    font-size: 14px;
  }

  .opponentCount {
    font-size: 13px;
  }
}


/* =========================================================
   НАПРАВЛЕНИЕ ХОДА

   Кольцо со стрелкой вокруг центра стола, как в макете v1.0:
   маленький значок в углу читался как кнопка и терялся.
   Имеет смысл от трёх мест — на двоих разворот работает
   как пропуск.
   ========================================================= */

.direction {
  position: absolute;

  left: 50%;
  top: 50%;

  width: 336px;
  height: 336px;

  transform: translate(-50%, -50%);

  pointer-events: none;

  z-index: 3;

  transition: opacity .4s ease;
}

.direction.hidden {
  display: none;
}

.directionArt {
  display: block;

  width: 100%;
  height: 100%;

  fill: currentColor;
}

/* Лента бледнее наконечника: остриё должно читаться первым. */
.dirRibbon {
  opacity: .46;
}

.dirHead {
  opacity: .9;
}

/*
  Разворот зеркалит стрелки, а не докручивает кольцо:
  повёрнутое на 180° кольцо выглядит точно так же, и смены
  направления никто бы не заметил.
*/
.direction.reversed .directionArt {
  transform: scaleX(-1);
}


@media (max-width: 560px) {

  .direction {
    width: 296px;
    height: 296px;
  }
}

@media (orientation: landscape) and (max-height: 560px) {

  .direction {
    /*
      Стол в альбоме широкий и низкий. Круг, который обошёл бы
      карты по бокам, вылез бы за стол сверху, поэтому кольцо
      становится эллипсом. Вращать эллипс нельзя — он качается,
      и это сразу видно.
    */
    width: 304px;
    height: 186px;
  }
}


/* =========================================================
   ЛОББИ
   ========================================================= */

/* =========================================================
   СТАРТОВОЕ МЕНЮ

   Раньше всё в окне весило одинаково: сетка чисел, галочка и
   три кнопки одного размера — глазу не за что зацепиться и
   непонятно, что тут выбирают, а что нажимают.

   Теперь два яруса. Сверху настройка в рамке с подписями,
   снизу действия: главное — залитое, второе — контурное,
   «как играть» вообще уходит в текстовую ссылку.
   ========================================================= */

.lobbySetup {
  margin: 16px 0 18px;

  border-radius: 18px;

  border:
    1px solid rgba(181, 93, 255, .22);

  background: rgba(255, 255, 255, .02);

  overflow: hidden;
}

.lobbyRow {
  padding: 12px 13px 13px;
}

.lobbyRow + .lobbyRow {
  border-top:
    1px solid rgba(181, 93, 255, .18);
}

.lobbyLabel {
  display: block;

  margin-bottom: 9px;

  font-size: 9px;
  font-weight: 900;

  letter-spacing: .2em;

  color: rgba(255, 255, 255, .38);
}


/* число игроков — одной строкой, а не сеткой */
.seatPicker {
  display: grid;

  grid-template-columns:
    repeat(6, 1fr);

  gap: 5px;
}

.seatPick {
  height: 40px;

  border-radius: 11px;

  border:
    1px solid rgba(181, 93, 255, .35);

  background: rgba(255, 255, 255, .03);

  color: rgba(255, 255, 255, .62);

  font-family: inherit;
  font-size: 16px;
  font-weight: 1000;

  cursor: pointer;

  transition:
    border-color .2s ease,
    box-shadow .2s ease,
    color .2s ease,
    background .2s ease;
}

.seatPick.chosen {
  border-color: rgba(183, 255, 36, .85);

  background: rgba(183, 255, 36, .12);

  color: var(--acid);

  box-shadow:
    0 0 10px rgba(183, 255, 36, .25);
}


.clockToggle {
  width: 100%;

  display: flex;

  align-items: center;

  gap: 9px;

  padding: 9px 11px;

  border-radius: 11px;

  border:
    1px solid rgba(181, 93, 255, .3);

  background: rgba(255, 255, 255, .03);

  color: rgba(255, 255, 255, .7);

  font-family: inherit;
  font-size: 10px;
  font-weight: 900;

  letter-spacing: .1em;

  cursor: pointer;

  transition:
    border-color .2s ease,
    color .2s ease;
}

.clockToggleBox {
  width: 16px;
  height: 16px;

  flex: none;

  border-radius: 5px;

  border:
    1px solid rgba(181, 93, 255, .6);
}

.clockToggle.on {
  border-color: rgba(183, 255, 36, .7);

  color: var(--acid);
}

.clockToggle.on .clockToggleBox {
  border-color: rgba(183, 255, 36, .9);

  background: var(--acid);

  box-shadow:
    0 0 10px rgba(183, 255, 36, .55);
}


.lobbyNote {
  margin: 9px 0 0;

  min-height: 13px;

  font-size: 10px;
  font-weight: 800;

  letter-spacing: .12em;

  color: rgba(255, 255, 255, .5);
}


/*
  Кнопка запуска повторяет #again из style.css:
  на экранах итога и лобби главное действие выглядит одинаково.
*/
#lobbyStart {
  width: 100%;

  padding: 14px;

  border-radius: 16px;

  border:
    1px solid rgba(255, 255, 255, .65);

  background:
    linear-gradient(
      90deg,
      #7e2cff,
      #e527d9
    );

  color: var(--white);

  font-family: inherit;
  font-size: 12px;
  font-weight: 1000;

  letter-spacing: 1px;

  cursor: pointer;

  box-shadow:
    0 0 20px rgba(211, 39, 255, .34);
}


/* =========================================================
   ПРАВИЛА

   Карты внутри — настоящие, из cardHTML(): объяснение
   всегда совпадает с тем, что игрок видит на столе.
   ========================================================= */

.rulesOpen {
  width: 100%;

  margin-bottom: 10px;

  padding: 11px;

  border-radius: 14px;

  border:
    1px solid rgba(32, 234, 255, .38);

  background: rgba(32, 234, 255, .06);

  color: var(--cyan);

  font-family: inherit;
  font-size: 11px;
  font-weight: 900;

  letter-spacing: .16em;

  cursor: pointer;
}


.rulesWindow {
  width:
    min(
      420px,
      calc(100vw - 28px)
    );

  max-height:
    calc(100vh - var(--safe-top) - var(--safe-bottom) - 44px);

  max-height:
    calc(100dvh - var(--safe-top) - var(--safe-bottom) - 44px);

  display: flex;

  flex-direction: column;

  text-align: left;
}

.rulesWindow .windowEyebrow,
.rulesWindow h2 {
  text-align: center;
}


.rulesBody {
  flex: 1;

  min-height: 0;

  margin: 14px 0;

  padding-right: 6px;

  overflow-y: auto;

  overscroll-behavior: contain;

  -webkit-overflow-scrolling: touch;
}


.rulesSection {
  padding: 14px 0;

  border-top:
    1px solid rgba(181, 93, 255, .18);
}

.rulesSection:first-child {
  padding-top: 0;

  border-top: 0;
}

.rulesSection h3 {
  margin: 0 0 8px;

  font-size: 12px;
  font-weight: 1000;

  letter-spacing: .18em;

  color: var(--acid);

  text-shadow:
    0 0 14px rgba(183, 255, 36, .4);
}

.rulesSection p {
  margin: 0 0 7px;

  font-size: 12.5px;
  line-height: 1.5;
  font-weight: 600;

  color: rgba(255, 255, 255, .76);
}

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


.rulesCards {
  --card-w: 42px;
  --card-h: 63px;

  display: flex;

  flex-wrap: wrap;

  align-items: flex-start;

  gap: 12px;

  margin: 4px 0 12px;
}

.rulesCard {
  display: grid;

  justify-items: center;

  gap: 5px;
}

.rulesCard .card {
  border-width: 1px;
}

.rulesCard .card .value {
  font-size: 18px;

  letter-spacing: -1px;
}

.rulesNote {
  font-size: 8px;
  font-weight: 900;

  letter-spacing: .1em;

  color: rgba(255, 255, 255, .42);

  white-space: nowrap;
}


#rulesClose {
  width: 100%;

  padding: 13px;

  border-radius: 16px;

  border:
    1px solid rgba(255, 255, 255, .65);

  background:
    linear-gradient(
      90deg,
      #7e2cff,
      #e527d9
    );

  color: var(--white);

  font-family: inherit;
  font-size: 12px;
  font-weight: 1000;

  letter-spacing: 1px;

  cursor: pointer;

  box-shadow:
    0 0 20px rgba(211, 39, 255, .34);
}


/*
  Экран правил всегда поверх лобби.
*/
#rules {
  z-index: 20010;
}


/* =========================================================
   УЧЕБНЫЙ ТУР

   Отдельная мини-партия поверх лобби. Карты настоящие, но
   стол компактный: подсказка и единственное нужное действие
   помещаются на первом экране телефона.
   ========================================================= */

#tutorial {
  z-index: 20020;
}

.tourWindow {
  width:
    min(
      440px,
      calc(100vw - 28px)
    );

  text-align: center;
}

.tourWindow h2 {
  margin-bottom: 8px;
}

.tutorialHint {
  min-height: 2.8em;

  margin: 0;

  color: var(--acid);

  font-size: 13px;
  font-weight: 1000;
  letter-spacing: .1em;
  line-height: 1.35;
}

.tutorialTable {
  display: grid;

  justify-items: center;

  gap: 6px;

  margin: 14px 0 12px;

  padding: 12px;

  border:
    1px solid rgba(32, 234, 255, .2);

  border-radius: 18px;

  background: rgba(32, 234, 255, .04);
}

.tutorialRow {
  display: grid;

  justify-items: center;

  gap: 6px;

  color: rgba(255, 255, 255, .45);

  font-size: 9px;
  font-weight: 1000;
  letter-spacing: .16em;
}

.tutorialTop {
  --card-w: 54px;
  --card-h: 80px;
}

.tutorialPenalty {
  min-height: 1.1em;

  color: var(--pink);

  font-size: 12px;
  font-weight: 1000;
  letter-spacing: .14em;
}

.tutorialHandTitle {
  margin-bottom: 7px;

  color: rgba(255, 255, 255, .46);

  font-size: 9px;
  font-weight: 1000;
  letter-spacing: .16em;
}

.tutorialHand {
  --card-w: 52px;
  --card-h: 78px;

  display: flex;

  justify-content: center;

  flex-wrap: wrap;

  gap: 8px;

  min-height: 80px;
}

.tutorialCard {
  display: block;

  width: var(--card-w);
  height: var(--card-h);

  padding: 0;

  border: 0;

  border-radius: 8px;

  background: transparent;

  cursor: pointer;

  transition: transform .15s ease, filter .15s ease;
}

.tutorialCard:active {
  transform: translateY(3px) scale(.96);
}

.tutorialCard .card {
  width: 100%;
  height: 100%;
}

.tutorialStatus {
  min-height: 1.4em;

  margin: 12px 0 8px;

  color: var(--cyan);

  font-size: 11px;
  font-weight: 900;
  letter-spacing: .07em;
  line-height: 1.35;
}

.tutorialActions {
  display: grid;

  grid-template-columns: 1fr 1fr;

  gap: 8px;
}

.tutorialActions button,
#tutorialFinish {
  min-height: 46px;

  padding: 10px;

  border-radius: 14px;

  border:
    1px solid rgba(32, 234, 255, .38);

  background: rgba(32, 234, 255, .07);

  color: var(--cyan);

  font-family: inherit;
  font-size: 10px;
  font-weight: 1000;
  letter-spacing: .08em;
}

#tutorialUno,
#tutorialFinish {
  border-color: rgba(183, 255, 36, .68);

  background: linear-gradient(90deg, #7e2cff, #e527d9);

  color: var(--white);
}

#tutorialFinish {
  width: 100%;
}

@media (min-width: 780px) {

  .tourWindow {
    width: min(440px, calc(100vw - 28px));
  }
}


/* =========================================================
   КОМНАТА ПО ССЫЛКЕ
   ========================================================= */

.lobbyOnline {
  width: 100%;

  margin-top: 9px;

  padding: 13px;

  border-radius: 16px;

  border:
    1px solid rgba(32, 234, 255, .5);

  background: rgba(32, 234, 255, .07);

  color: var(--cyan);

  font-family: inherit;
  font-size: 12px;
  font-weight: 1000;

  letter-spacing: 1px;

  cursor: pointer;
}


.roomPanel.hidden,
#lobbyMain.hidden {
  display: none;
}


.roomCode {
  margin: 10px 0 14px;

  font-size: 44px;
  font-weight: 1000;

  letter-spacing: .14em;

  color: var(--acid);

  text-shadow:
    0 0 18px rgba(183, 255, 36, .5);
}


.roomCopy {
  width: 100%;

  padding: 12px;

  border-radius: 14px;

  border:
    1px solid rgba(181, 93, 255, .45);

  background: rgba(255, 255, 255, .04);

  color: var(--white);

  font-family: inherit;
  font-size: 10px;
  font-weight: 900;

  letter-spacing: .1em;

  word-break: break-all;

  cursor: pointer;
}


.roomPlayers {
  display: grid;

  gap: 6px;

  margin: 14px 0 10px;
}

.roomSeat {
  display: flex;

  align-items: center;
  justify-content: space-between;

  padding: 9px 13px;

  border-radius: 13px;

  border:
    1px dashed rgba(181, 93, 255, .35);

  font-size: 11px;
  font-weight: 900;

  letter-spacing: .12em;

  color: rgba(255, 255, 255, .4);
}

.roomSeat b {
  font-size: 13px;

  opacity: .5;
}

.roomSeat.taken {
  border-style: solid;

  border-color: rgba(181, 93, 255, .6);

  color: rgba(255, 255, 255, .82);
}

.roomSeat.mine {
  border-color: rgba(183, 255, 36, .7);

  color: var(--acid);
}


.roomLeave {
  width: 100%;

  margin-top: 4px;

  padding: 11px;

  border-radius: 14px;

  border:
    1px solid rgba(255, 255, 255, .18);

  background: transparent;

  color: rgba(255, 255, 255, .45);

  font-family: inherit;
  font-size: 10px;
  font-weight: 900;

  letter-spacing: .12em;

  cursor: pointer;
}


/* кнопки стола в комнате */

.roomTools {
  display: grid;

  grid-template-columns: 1fr 1fr;

  gap: 8px;

  margin-bottom: 8px;
}

.roomTools.hidden {
  display: none;
}

.roomTool {
  padding: 11px;

  border-radius: 13px;

  border:
    1px solid rgba(181, 93, 255, .45);

  background: rgba(255, 255, 255, .04);

  color: var(--white);

  font-family: inherit;
  font-size: 11px;
  font-weight: 900;

  letter-spacing: .1em;

  cursor: pointer;
}

.roomTool:disabled {
  opacity: .3;

  cursor: default;
}


.roomStart {
  width: 100%;

  padding: 13px;

  border-radius: 16px;

  border:
    1px solid rgba(183, 255, 36, .7);

  background: rgba(183, 255, 36, .1);

  color: var(--acid);

  font-family: inherit;
  font-size: 12px;
  font-weight: 1000;

  letter-spacing: 1px;

  cursor: pointer;
}

.roomStart:disabled {
  opacity: .3;

  cursor: default;
}

.roomStart.hidden {
  display: none;
}


.roomSeat.bot {
  border-style: solid;

  border-color: rgba(32, 234, 255, .45);

  color: rgba(32, 234, 255, .8);
}


/* =========================================================
   ПОДСКАЗКИ НА ИКОНКАХ

   Иконка без подписи ничего не объясняет, а нативный
   title выглядит чужеродно на неоновом экране. Подсказка
   рисуется своя и только по наведению — на телефоне
   наведения нет, там подписи дают лобби и экран правил.
   ========================================================= */

[data-tip] {
  position: relative;
}

[data-tip]::after {
  content: attr(data-tip);

  position: absolute;

  top: calc(100% + 8px);
  right: 0;

  z-index: 60;

  padding: 6px 10px;

  border-radius: 10px;

  border:
    1px solid var(--panel-line-purple);

  background: rgba(10, 5, 22, .95);

  color: rgba(255, 255, 255, .82);

  font-size: 9px;
  font-weight: 900;

  letter-spacing: .12em;

  white-space: nowrap;

  opacity: 0;

  transform: translateY(-4px);

  pointer-events: none;

  transition:
    opacity .16s ease,
    transform .16s ease;
}

@media (hover: hover) {

  [data-tip]:hover::after,
  [data-tip]:focus-visible::after {
    opacity: 1;

    transform: translateY(0);
  }
}


/* =========================================================
   ЧИТАЕМОСТЬ РУКИ

   На телефоне карты перекрывают друг друга сильнее, чем на
   десктопе, и середина карты — там, где нарисован номинал —
   закрыта соседкой. Угловые индексы становятся основным
   способом прочитать руку, поэтому они крупнее и с подложкой.
   ========================================================= */

.hand.is-crowded .handCard .cardCorner {
  display: block;

  min-width: 24px;

  padding: 2px 4px;

  border-radius: 7px;

  background: rgba(12, 6, 24, .82);

  font-size: 17px;

  -webkit-text-stroke: 0;

  text-shadow:
    0 0 6px rgba(0, 0, 0, .9);
}

.hand.is-crowded .handCard .cardCornerTop {
  top: 5px;
  left: 5px;
}

/*
  Нижний угол в веере всегда перекрыт соседней картой —
  показываем только верхний.
*/
.hand.is-crowded .handCard .cardCornerBottom {
  display: none;
}


/* =========================================================
   ЧЕМ МОЖНО ХОДИТЬ

   Раньше подходящая карта просто чуть светилась, и на ярком
   веере разница терялась. Теперь работает контраст: лишние
   карты приглушаются, и глаз сам находит доступные.
   ========================================================= */

#hand .handCard.v9-unplayable {
  /*
    Приглушения здесь больше нет: разницу делает свет от
    играбельной карты. Правило оставлено ради перехода.
  */
  filter: none;

  transition: filter .18s ease;
}

#hand .handCard.v9-playable,
#hand .handCard.playable {
  filter:
    brightness(1.03)
    drop-shadow(0 0 5px rgba(207, 255, 42, .42));

  transition: filter .18s ease;
}


/* =========================================================
   СКОЛЬКО КАРТ У СОПЕРНИКА

   Одного числа мало: за столом видно не цифру, а толщину
   веера. Рубашки за значком показывают её физически.
   ========================================================= */

.opponentStack {
  position: absolute;

  inset: 5px 8px auto 8px;

  height: 20px;

  border-radius: 7px;

  pointer-events: none;

  opacity: 0;

  transition: opacity .25s ease;
}

.opponent[data-stack="1"] .opponentStack,
.opponent[data-stack="2"] .opponentStack,
.opponent[data-stack="3"] .opponentStack,
.opponent[data-stack="4"] .opponentStack,
.opponent[data-stack="5"] .opponentStack {
  opacity: 1;

  border:
    1px solid rgba(186, 73, 255, .55);

  background:
    linear-gradient(
      150deg,
      rgba(139, 61, 255, .55),
      rgba(255, 43, 214, .3)
    );
}

.opponent[data-stack="2"] .opponentStack {
  box-shadow:
    3px -3px 0 -1px rgba(139, 61, 255, .42);
}

.opponent[data-stack="3"] .opponentStack {
  box-shadow:
    3px -3px 0 -1px rgba(139, 61, 255, .42),
    6px -6px 0 -2px rgba(139, 61, 255, .32);
}

.opponent[data-stack="4"] .opponentStack {
  box-shadow:
    3px -3px 0 -1px rgba(139, 61, 255, .42),
    6px -6px 0 -2px rgba(139, 61, 255, .32),
    9px -9px 0 -3px rgba(139, 61, 255, .24);
}

.opponent[data-stack="5"] .opponentStack {
  box-shadow:
    3px -3px 0 -1px rgba(139, 61, 255, .42),
    6px -6px 0 -2px rgba(139, 61, 255, .32),
    9px -9px 0 -3px rgba(139, 61, 255, .24),
    12px -12px 0 -4px rgba(139, 61, 255, .18);
}


/* =========================================================
   ДЕЙСТВИЯ В СТАРТОВОМ МЕНЮ

   Три кнопки одного веса не говорят, какая из них главная.
   Здесь порядок: залитая — начать, контурная — позвать,
   текстовая ссылка — справка.
   ========================================================= */

#lobbyStart {
  margin-bottom: 9px;
}

.lobbyOnline {
  margin-top: 0;

  padding: 12px;

  font-size: 11px;
}

.rulesOpen {
  width: auto;

  margin: 14px auto 0;

  padding: 4px 2px;

  display: block;

  border: 0;

  background: none;

  color: rgba(255, 255, 255, .38);

  font-size: 11px;
  font-weight: 700;

  letter-spacing: .08em;

  text-transform: none;

  text-decoration: underline;

  text-underline-offset: 4px;

  cursor: pointer;
}

.rulesOpen:hover {
  color: var(--cyan);
}


/* =========================================================
   ТЕЛЕФОН В АЛЬБОМЕ

   По высоте здесь тесно: стол занимал 254px из 390, и рука
   налезала на него на сорок с лишним пикселей — карты
   лежали поверх сброса. Стол поджимается и поднимается,
   чтобы под ним осталась полоса для руки.
   ========================================================= */

@media (orientation: landscape) and (max-height: 560px) {

  #table {
    top: 37%;

    height:
      min(48vh, 196px);

    width:
      min(calc(100vw - 210px), 470px);
  }

  .actionHUD {
    bottom: auto;

    top: 58%;
  }
}


/* =========================================================
   ПЕРЕКРАСКА — ВАРИАНТ 1

   Компоновка карты остаётся классической: цветное поле,
   светлый овал, крупный номинал, индексы по углам. Меняется
   палитра — кислотный неон вместо ярмарочных красного,
   жёлтого, зелёного и синего.

   Фиолетовый в мастях не участвует: он держит фон, стол и
   интерфейс, и карта того же цвета сливалась бы со столом.

   Имена мастей (red/yellow/green/blue) остаются прежними —
   на них завязаны правила, тесты и сохранённые партии.
   Меняется только то, как они выглядят.
   ========================================================= */

:root {
  /* малиновый вместо красного */
  --red: #ff2d78;
  --red-light: #ff74a8;
  --red-deep: #a3004b;

  /* кислотный жёлтый */
  --yellow: #f5d020;
  --yellow-light: #ffe97e;
  --yellow-deep: #dba400;

  /* кислотный зелёный — основной цвет игры */
  --green: #a6f42a;
  --green-light: #ccff74;
  --green-deep: #4b8a00;

  /* холодная бирюза вместо синего */
  --blue: #22d3ee;
  --blue-light: #8beeff;
  --blue-deep: #00697f;
}


.card.red,
.handCard.red,
.flyingCard.red {
  background:
    radial-gradient(
      circle at 30% 18%,
      var(--red-light),
      var(--red) 35%,
      var(--red-deep) 100%
    );

  box-shadow:
    inset 0 0 22px rgba(255, 255, 255, .12),
    0 0 7px rgba(255, 45, 120, .75),
    0 0 18px rgba(255, 45, 120, .32),
    0 11px 18px rgba(0, 0, 0, .42);
}

.card.yellow,
.handCard.yellow,
.flyingCard.yellow {
  background:
    radial-gradient(
      circle at 30% 18%,
      var(--yellow-light),
      var(--yellow) 55%,
      var(--yellow-deep) 100%
    );

  box-shadow:
    inset 0 0 22px rgba(255, 255, 255, .12),
    0 0 7px rgba(245, 208, 32, .7),
    0 0 18px rgba(245, 208, 32, .3),
    0 11px 18px rgba(0, 0, 0, .42);
}

.card.green,
.handCard.green,
.flyingCard.green {
  background:
    radial-gradient(
      circle at 30% 18%,
      var(--green-light),
      var(--green) 35%,
      var(--green-deep) 100%
    );

  box-shadow:
    inset 0 0 22px rgba(255, 255, 255, .12),
    0 0 7px rgba(166, 244, 42, .72),
    0 0 18px rgba(166, 244, 42, .32),
    0 11px 18px rgba(0, 0, 0, .42);
}

.card.blue,
.handCard.blue,
.flyingCard.blue {
  background:
    radial-gradient(
      circle at 30% 18%,
      var(--blue-light),
      var(--blue) 35%,
      var(--blue-deep) 100%
    );

  box-shadow:
    inset 0 0 22px rgba(255, 255, 255, .12),
    0 0 7px rgba(34, 211, 238, .72),
    0 0 18px rgba(34, 211, 238, .32),
    0 11px 18px rgba(0, 0, 0, .42);
}


/* чёрная карта показывает все четыре масти */

.card.wild,
.handCard.wild,
.flyingCard.wild {
  background:
    conic-gradient(
      from -30deg,
      var(--red),
      var(--red) 24%,
      var(--yellow) 25%,
      var(--yellow) 49%,
      var(--green) 50%,
      var(--green) 74%,
      var(--blue) 75%,
      var(--blue) 100%
    );

  box-shadow:
    0 0 7px rgba(255, 255, 255, .7),
    0 0 22px rgba(166, 244, 42, .5),
    0 11px 18px rgba(0, 0, 0, .42);
}


/* аура активного цвета вокруг сброса */

.discardPile[data-color="red"] {
  --aura: var(--red);
  --aura-strong: rgba(255, 45, 120, .78);
  --aura-soft: rgba(255, 45, 120, .3);
}

.discardPile[data-color="yellow"] {
  --aura: var(--yellow);
  --aura-strong: rgba(245, 208, 32, .72);
  --aura-soft: rgba(245, 208, 32, .27);
}

.discardPile[data-color="green"] {
  --aura: var(--green);
  --aura-strong: rgba(166, 244, 42, .76);
  --aura-soft: rgba(166, 244, 42, .3);
}

.discardPile[data-color="blue"] {
  --aura: var(--blue);
  --aura-strong: rgba(34, 211, 238, .78);
  --aura-soft: rgba(34, 211, 238, .3);
}


/* реакция стола на текущий цвет */

.tableInner.color-red {
  box-shadow:
    inset 0 0 50px rgba(255, 45, 120, .15),
    0 0 10px rgba(255, 45, 120, .5),
    0 0 34px rgba(150, 45, 255, .34),
    0 25px 60px rgba(0, 0, 0, .62);
}

.tableInner.color-yellow {
  box-shadow:
    inset 0 0 50px rgba(245, 208, 32, .13),
    0 0 10px rgba(245, 208, 32, .45),
    0 0 34px rgba(150, 45, 255, .34),
    0 25px 60px rgba(0, 0, 0, .62);
}

.tableInner.color-green {
  box-shadow:
    inset 0 0 50px rgba(166, 244, 42, .14),
    0 0 10px rgba(166, 244, 42, .5),
    0 0 34px rgba(150, 45, 255, .34),
    0 25px 60px rgba(0, 0, 0, .62);
}

.tableInner.color-blue {
  box-shadow:
    inset 0 0 50px rgba(34, 211, 238, .16),
    0 0 10px rgba(34, 211, 238, .5),
    0 0 34px rgba(150, 45, 255, .34),
    0 25px 60px rgba(0, 0, 0, .62);
}


/* =========================================================
   КОЛОДА — ВАРИАНТ 2, «КИСЛОТНАЯ»

   Другая карта, а не перекраска: тёмное поле, неоновая
   рамка со срезанными углами, номинал светится цветом масти,
   спецкарты подписаны именами.

   Включается атрибутом data-deck="acid" на <html>, поэтому
   обе колоды живут рядом и переключаются в лобби.
   ========================================================= */

/* подпись показывается только в кислотной колоде */
html[data-deck="acid"] .card,
html[data-deck="acid"] .handCard,
html[data-deck="acid"] .flyingCard {
  border: 0;

  border-radius: 13px;

  /* срезанные углы — «механическая эстетика» макета */
  clip-path:
    polygon(
      16% 0%, 84% 0%, 100% 11%,
      100% 89%, 84% 100%, 16% 100%,
      0% 89%, 0% 11%
    );
}


/*
  Светлый овал классической карты превращается в тёмное
  поле: в кислотной колоде цвет несёт рамка и свечение,
  а не заливка.
*/
html[data-deck="acid"] .card::before,
html[data-deck="acid"] .handCard::before,
html[data-deck="acid"] .flyingCard::before {
  inset: 0;

  left: 0;
  top: 0;

  width: 100%;
  height: 100%;

  border-radius: 0;

  transform: none;

  background:
    radial-gradient(
      ellipse at 50% 22%,
      rgba(18, 10, 30, .92),
      rgba(6, 3, 12, .98) 70%
    );

  box-shadow: none;
}


/* рамка внутри среза */
html[data-deck="acid"] .card::after,
html[data-deck="acid"] .handCard::after,
html[data-deck="acid"] .flyingCard::after {
  inset: 3px;

  border-radius: 9px;

  border: 2px solid currentColor;

  opacity: .9;
}


/*
  Настоящий неон светится белым ядром с цветным ореолом.
  Цифра, залитая цветом масти, на чёрном читается плоско и
  тускло — именно так и вышло с первого раза.
*/
html[data-deck="acid"] .card .value,
html[data-deck="acid"] .handCard .value,
html[data-deck="acid"] .flyingCard .value {
  color: #fff;

  font-size: 44px;

  text-shadow:
    0 0 3px #fff,
    0 0 9px var(--suit),
    0 0 20px var(--suit),
    0 0 38px var(--suit);
}


html[data-deck="acid"] .cardCorner {
  color: #fff;

  font-size: 19px;

  -webkit-text-stroke: 0;

  text-shadow:
    0 0 3px #fff,
    0 0 10px var(--suit);
}


/*
  Масть задаёт currentColor — от него кормятся и рамка,
  и номинал, и подпись.
*/
/*
  --suit кормит и рамку, и ореол цифры, и подпись.
  color оставляем ему же: от него живут рамка и имя карты.
*/
html[data-deck="acid"] .red { --suit: var(--red); color: var(--red); }
html[data-deck="acid"] .yellow { --suit: var(--yellow); color: var(--yellow); }
html[data-deck="acid"] .green { --suit: var(--green); color: var(--green); }
html[data-deck="acid"] .blue { --suit: var(--blue); color: var(--blue); }
html[data-deck="acid"] .wild { --suit: var(--magenta); color: var(--acid); }


html[data-deck="acid"] .card.red,
html[data-deck="acid"] .handCard.red,
html[data-deck="acid"] .flyingCard.red,
html[data-deck="acid"] .card.yellow,
html[data-deck="acid"] .handCard.yellow,
html[data-deck="acid"] .flyingCard.yellow,
html[data-deck="acid"] .card.green,
html[data-deck="acid"] .handCard.green,
html[data-deck="acid"] .flyingCard.green,
html[data-deck="acid"] .card.blue,
html[data-deck="acid"] .handCard.blue,
html[data-deck="acid"] .flyingCard.blue,
html[data-deck="acid"] .card.wild,
html[data-deck="acid"] .handCard.wild,
html[data-deck="acid"] .flyingCard.wild {
  background:
    linear-gradient(
      158deg,
      rgba(20, 11, 32, .98),
      rgba(7, 4, 14, .98)
    );

  box-shadow:
    0 0 8px currentColor,
    0 0 22px rgba(0, 0, 0, .6),
    0 11px 18px rgba(0, 0, 0, .5);
}


/* чёрная карта переливается всеми мастями */
html[data-deck="acid"] .card.wild::after,
html[data-deck="acid"] .handCard.wild::after,
html[data-deck="acid"] .flyingCard.wild::after {
  border: 0;

  background:
    conic-gradient(
      from -30deg,
      var(--red),
      var(--yellow) 25%,
      var(--green) 50%,
      var(--blue) 75%,
      var(--red) 100%
    );

  /* оставляем только ободок */
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);

  -webkit-mask-composite: xor;

  mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);

  mask-composite: exclude;

  padding: 2px;

  border-radius: 9px;
}

html[data-deck="acid"] .card.wild .value,
html[data-deck="acid"] .handCard.wild .value,
html[data-deck="acid"] .flyingCard.wild .value {
  color: #fff;

  text-shadow:
    0 0 6px #fff,
    0 0 20px var(--magenta);
}


/* угловые индексы в тесной руке */
html[data-deck="acid"] .hand.is-crowded .handCard .cardCorner {
  background: rgba(6, 3, 12, .9);

  color: currentColor;
}


/* выбор колоды в лобби */

.deckPicker {
  display: grid;

  grid-template-columns: 1fr 1fr;

  gap: 6px;
}

.deckPick {
  height: 36px;

  border-radius: 11px;

  border:
    1px solid rgba(181, 93, 255, .35);

  background: rgba(255, 255, 255, .03);

  color: rgba(255, 255, 255, .6);

  font-family: inherit;
  font-size: 10px;
  font-weight: 900;

  letter-spacing: .12em;

  cursor: pointer;

  transition:
    border-color .2s ease,
    color .2s ease,
    background .2s ease;
}

.deckPick.chosen {
  border-color: rgba(183, 255, 36, .85);

  background: rgba(183, 255, 36, .1);

  color: var(--acid);
}


/* =========================================================
   КОЛЬЦО НАПРАВЛЕНИЯ — ЦВЕТ И ВРАЩЕНИЕ

   Кольцо красится текущим цветом и медленно крутится в ту
   сторону, куда идёт ход. Так и цвет, и направление видно
   не переводя взгляд с центра стола.
   ========================================================= */

.direction {
  color: var(--turn, var(--cyan));

  filter:
    drop-shadow(
      0 0 14px
      color-mix(in srgb, var(--turn, var(--cyan)) 50%, transparent)
    );

  /* оборот за сорок секунд: движение заметно, но не мельтешит */
  animation: acidTurnSpin 40s linear infinite;
}

.direction.reversed {
  animation-direction: reverse;
}

/*
  В альбоме кольцо — эллипс (см. геометрию выше), а вращать
  эллипс нельзя: он качается. Правило стоит здесь, а не рядом
  с размерами, иначе объявление анимации выше его перебивает.
*/
@media (orientation: landscape) and (max-height: 560px) {

  .direction {
    animation: none;
  }
}

@keyframes acidTurnSpin {
  to {
    transform:
      translate(-50%, -50%) rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .direction {
    animation: none;
  }
}


/* =========================================================
   КОЛОДА ТОЛЩИНОЙ ПО ЧИСЛУ КАРТ
   ========================================================= */

#deck {
  transition: box-shadow .4s ease;
}

/*
  Толщина стопок. Смещения намеренно мелкие: колода — это
  пачка карт, а не лесенка. Прежние восемь точек на слой
  превращали её в развёрнутый веер сбоку.

  Стопки разведены в разные стороны: колода толстеет
  влево-вниз, сброс — вправо-вниз, иначе одна прячется под
  другой. Слои живут на самой видимой карте: у колоды это
  рубашка, у сброса — подложка, потому что ауру цвета трогать
  нельзя.
*/
html #deck[data-thick="1"] .deckBack {
  box-shadow:
    -4px 3px 0 -1px rgba(176, 128, 255, 0.69);
}

html #deck[data-thick="2"] .deckBack {
  box-shadow:
    -4px 3px 0 -1px rgba(176, 128, 255, 0.69),
    -8px 6px 0 -1px rgba(176, 128, 255, 0.58);
}

html #deck[data-thick="3"] .deckBack {
  box-shadow:
    -4px 3px 0 -1px rgba(176, 128, 255, 0.69),
    -8px 6px 0 -1px rgba(176, 128, 255, 0.58),
    -12px 9px 0 -1px rgba(138, 82, 232, 0.47);
}

html #deck[data-thick="4"] .deckBack {
  box-shadow:
    -4px 3px 0 -1px rgba(176, 128, 255, 0.69),
    -8px 6px 0 -1px rgba(176, 128, 255, 0.58),
    -12px 9px 0 -1px rgba(138, 82, 232, 0.47),
    -16px 12px 0 -1px rgba(138, 82, 232, 0.36);
}

html #deck[data-thick="5"] .deckBack {
  box-shadow:
    -4px 3px 0 -1px rgba(176, 128, 255, 0.69),
    -8px 6px 0 -1px rgba(176, 128, 255, 0.58),
    -12px 9px 0 -1px rgba(138, 82, 232, 0.47),
    -16px 12px 0 -1px rgba(138, 82, 232, 0.36),
    -20px 15px 0 -1px rgba(138, 82, 232, 0.25);
}

.discardPile[data-thick="1"]::before {
  box-shadow:
    4px 3px 0 -1px rgba(255, 255, 255, 0.51);
}

.discardPile[data-thick="2"]::before {
  box-shadow:
    4px 3px 0 -1px rgba(255, 255, 255, 0.51),
    8px 6px 0 -1px rgba(255, 255, 255, 0.42);
}

.discardPile[data-thick="3"]::before {
  box-shadow:
    4px 3px 0 -1px rgba(255, 255, 255, 0.51),
    8px 6px 0 -1px rgba(255, 255, 255, 0.42),
    12px 9px 0 -1px rgba(255, 255, 255, 0.33);
}

.discardPile[data-thick="4"]::before {
  box-shadow:
    4px 3px 0 -1px rgba(255, 255, 255, 0.51),
    8px 6px 0 -1px rgba(255, 255, 255, 0.42),
    12px 9px 0 -1px rgba(255, 255, 255, 0.33),
    16px 12px 0 -1px rgba(255, 255, 255, 0.24);
}

.discardPile[data-thick="5"]::before {
  box-shadow:
    4px 3px 0 -1px rgba(255, 255, 255, 0.51),
    8px 6px 0 -1px rgba(255, 255, 255, 0.42),
    12px 9px 0 -1px rgba(255, 255, 255, 0.33),
    16px 12px 0 -1px rgba(255, 255, 255, 0.24),
    20px 15px 0 -1px rgba(255, 255, 255, 0.15);
}

/* =========================================================
   ЛОГОТИП

   Был мелкой подписью в углу. Игра называется ACID UNO —
   это должно быть видно.
   ========================================================= */

.logoAcid {
  font-size: 30px;

  background:
    linear-gradient(
      170deg,
      var(--acid),
      #6ee7ff
    );

  -webkit-background-clip: text;
  background-clip: text;

  -webkit-text-fill-color: transparent;

  filter:
    drop-shadow(0 0 10px rgba(183, 255, 36, .55));
}

.logoUno {
  font-size: 30px;

  color: var(--white);

  text-shadow:
    0 0 8px rgba(255, 255, 255, .55),
    0 0 22px var(--magenta);
}

@media (max-width: 560px) {

  .logoAcid,
  .logoUno {
    font-size: 24px;
  }
}

@media (orientation: landscape) and (max-height: 560px) {

  .logoAcid,
  .logoUno {
    font-size: 21px;
  }
}


/* =========================================================
   ПОЯСНЕНИЯ В СТАРТОВОМ МЕНЮ

   Заголовков мало: «ИГРОКОВ» не говорит, считать ли себя,
   а две кнопки внизу молчат о том, чем отличаются. Каждая
   строка объясняет себя одной фразой.
   ========================================================= */

.lobbyLabel em {
  display: block;

  margin-top: 3px;

  font-size: 9px;
  font-style: normal;
  font-weight: 600;

  letter-spacing: .04em;

  text-transform: none;

  color: rgba(255, 255, 255, .3);
}

.lobbyHint {
  margin: 2px 0 8px;

  font-size: 9px;
  font-weight: 900;

  letter-spacing: .18em;

  color: rgba(255, 255, 255, .32);
}

#lobbyStart em,
.lobbyOnline em {
  display: block;

  margin-top: 3px;

  font-size: 9px;
  font-style: normal;
  font-weight: 700;

  letter-spacing: .04em;

  text-transform: none;

  opacity: .72;
}

#lobbyStart {
  line-height: 1.25;
}

.lobbyOnline {
  line-height: 1.25;
}


/* =========================================================
   ТЕСНАЯ РУКА: ЧИТАЕМ УГОЛ, А НЕ ПРИЗРАК

   Базовый стиль гасил центральный номинал до 48%, когда
   включались угловые индексы. На неоновой карте это читается
   не как «отошло на второй план», а как сбой отрисовки —
   тусклая цифра поверх чёрного поля.

   Убираем совсем: раз читаем угол, пусть он и будет крупным.
   Подписи спецкарт тоже прячем — соседняя карта всё равно
   срезает их на полуслове.
   ========================================================= */

/*
  Номинал в середине не прячем.

  Сначала я его убрал, потому что базовый стиль гасил его до
  48% и он висел призраком за угловым индексом. Но у кислотной
  карты нет светлого овала, и без цифры она превращалась в
  пустую рамку — карты буквально пропали с руки.

  Правильно иначе: цифра всегда на месте и в полную силу,
  соседняя карта просто закрывает её край. Ровно так и
  устроен веер настоящих карт, а угол дублирует номинал для
  тех, что закрыты целиком.
*/
.hand.is-crowded .handCard .value {
  opacity: 1;
}

.hand.is-crowded .handCard .cardCorner {
  font-size: 21px;

  min-width: 27px;

  padding: 3px 5px;
}

html[data-deck="acid"] .hand.is-crowded .handCard .cardCorner {
  font-size: 22px;
}


/* =========================================================
   НА ГЛАВНУЮ

   Игра лежит в подкаталоге сайта, и уйти из неё было некуда,
   кроме кнопки «назад» браузера.
   ========================================================= */

#homeLink {
  display: grid;

  place-items: center;

  grid-auto-flow: column;

  gap: 5px;

  min-width: 44px;

  width: 94px;

  min-height: 44px;

  padding: 0 10px;

  font-size: 12px;

  font-weight: 800;

  letter-spacing: .06em;

  white-space: nowrap;

  line-height: 1;

  text-decoration: none;
}


/*
  Лобби — полноэкранный overlay. Дверь «НА САЙТ» должна
  оставаться выше него: до начала партии она выводит сразу,
  а в партии уже спрашивает о прогрессе. Остальные кнопки
  верхней панели в лобби не поднимаем, чтобы не появлялись
  лишние действия поверх выбора стола.
*/
body.lobby-open .topbar {
  z-index: 20001;
}

body.lobby-open .topbarActions > :not(#homeLink) {
  visibility: hidden;

  pointer-events: none;
}


/* =========================================================
   ПРОКРУТКА В ПРАВИЛАХ

   macOS показывает полосу только во время самой прокрутки —
   её ширина ноль, и правила выглядят обрезанными. Рисуем
   свою: она видна всегда, а затемнение у нижней кромки
   гаснет, когда докрутили до конца.
   ========================================================= */

.rulesScroller {
  position: relative;

  flex: 1;

  min-height: 0;

  display: flex;
}

.rulesBody {
  flex: 1;

  margin: 14px 0;

  padding-right: 16px;

  scrollbar-width: none;
}

.rulesBody::-webkit-scrollbar {
  display: none;
}

.rulesRail {
  position: absolute;

  top: 14px;
  bottom: 14px;
  right: 0;

  width: 4px;

  border-radius: 2px;

  background: rgba(255, 255, 255, .07);

  pointer-events: none;

  transition: opacity .25s ease;
}

.rulesThumb {
  position: absolute;

  left: 0;
  right: 0;

  border-radius: 2px;

  background: rgba(183, 255, 36, .6);

  box-shadow:
    0 0 8px rgba(183, 255, 36, .45);
}

.rulesFade {
  position: absolute;

  left: 0;
  right: 10px;
  bottom: 14px;

  height: 46px;

  border-radius: 0 0 10px 10px;

  background:
    linear-gradient(
      to top,
      rgba(15, 8, 28, .96),
      rgba(15, 8, 28, 0)
    );

  pointer-events: none;

  transition: opacity .25s ease;
}


/* =========================================================
   ОБЪЯВЛЕНИЕ ЦВЕТА

   После чёрной карты цвет меняется на выбранный, и точки
   сбоку для этого мало. В мобильном UNO выбранный цвет
   пишут словом поверх стола — понятно с одного взгляда.
   ========================================================= */

.colorFlash {
  position: absolute;

  left: 50%;

  /* над сбросом, а не поверх него */
  top: 15%;

  z-index: 8;

  transform:
    translate(-50%, -50%) scale(.85);

  font-size: 40px;
  font-weight: 1000;

  letter-spacing: .04em;

  white-space: nowrap;

  color: var(--flash, var(--white));

  text-shadow:
    0 0 4px rgba(255, 255, 255, .85),
    0 0 18px var(--flash, var(--white)),
    0 0 44px var(--flash, var(--white));

  opacity: 0;

  pointer-events: none;

  transition:
    opacity .22s ease,
    transform .22s ease;
}

.colorFlash.show {
  opacity: 1;

  transform:
    translate(-50%, -50%) scale(1);
}

@media (max-width: 560px) {
  .colorFlash {
    font-size: 30px;
  }
}


/* =========================================================
   МЕТКА UNO НАД СОПЕРНИКОМ

   Одна карта на руках — событие, а не оттенок цифры.
   ========================================================= */

.opponent[data-uno="1"] .opponentPlate::after {
  content: "UNO";

  position: absolute;

  top: -13px;
  right: -8px;

  padding: 2px 6px;

  border-radius: 7px;

  background: var(--magenta);

  color: #fff;

  font-size: 9px;
  font-weight: 1000;

  letter-spacing: .1em;

  box-shadow:
    0 0 12px rgba(255, 43, 214, .8);

  animation:
    acidUnoTag .9s ease-in-out infinite;
}

.opponentPlate {
  position: relative;
}

@keyframes acidUnoTag {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.12); }
}

@media (prefers-reduced-motion: reduce) {
  .opponent[data-uno="1"] .opponentPlate::after {
    animation: none;
  }
}


/* =========================================================
   СТАРТОВОЕ МЕНЮ — ДВЕ ДВЕРИ

   Прежнее меню было одной колонкой: настройки, а под ними
   две почти одинаковые кнопки. С кем ты вообще играешь,
   становилось понятно только из мелкой подписи.

   Теперь первым делом выбирается дверь — боты или живые, —
   и настройки стола переезжают внутрь выбранной. На телефоне
   закрытая дверь сворачивается в одну строку, на большом
   экране двери стоят рядом.
   ========================================================= */

.lobbyHead {
  text-align: center;
}

.doors {
  display: flex;

  flex-direction: column;

  gap: 12px;

  margin-top: 16px;

  text-align: left;
}

.door {
  border: 1px solid rgba(181, 93, 255, .28);

  border-radius: 20px;

  padding: 16px;

  background:
    linear-gradient(
      180deg,
      rgba(139, 61, 255, .10),
      rgba(12, 6, 25, .55)
    );

  transition:
    border-color .2s ease,
    box-shadow .2s ease,
    opacity .2s ease;
}

.door.chosen {
  border-color: rgba(255, 43, 214, .6);

  box-shadow:
    0 0 0 1px rgba(255, 43, 214, .2),
    0 16px 44px rgba(255, 43, 214, .14);
}

.door[data-door="live"].chosen {
  border-color: rgba(32, 234, 255, .55);

  box-shadow:
    0 0 0 1px rgba(32, 234, 255, .18),
    0 16px 44px rgba(32, 234, 255, .12);
}

.doorPick {
  display: block;

  width: 100%;

  padding: 0;

  border: 0;

  background: none;

  color: inherit;

  text-align: left;

  cursor: pointer;

  font: inherit;
}

.doorPick b {
  display: block;

  font-size: 17px;
  font-weight: 900;

  letter-spacing: .06em;
}

.doorPick em {
  display: block;

  margin-top: 4px;

  font-size: 11px;
  font-style: normal;
  font-weight: 700;

  letter-spacing: .02em;

  color: rgba(248, 247, 255, .5);
}

.door[data-door="bots"].chosen .doorPick b {
  color: var(--magenta);
}

.door[data-door="live"].chosen .doorPick b {
  color: var(--cyan);
}

.doorBody {
  margin-top: 14px;
}

/*
  Закрытая дверь на телефоне — одна строка: иначе меню снова
  становится длинной лентой, по которой надо листать.
*/
.door:not(.chosen) .doorBody {
  display: none;
}

.doorText {
  margin: 0 0 14px;

  font-size: 12px;
  line-height: 1.5;

  color: rgba(248, 247, 255, .52);
}

.door .lobbySetup {
  margin: 0 0 14px;
}


/* большой экран: двери встают рядом и всё крупнеет */
@media (min-width: 780px) {

  .lobbyWindow {
    width:
      min(
        980px,
        calc(100vw - 64px)
      );

    padding: 34px 32px 28px;
  }

  .lobbyWindow h2 {
    font-size: 34px;
  }

  .doors {
    display: grid;

    grid-template-columns: 1fr 1fr;

    gap: 18px;

    align-items: start;

    margin-top: 24px;
  }

  /*
    Рядом стоящая закрытая дверь должна остаться читаемой:
    иначе про живую игру опять никто не узнает.
  */
  /*
    Двери одной высоты, а действие у каждой прижато к низу:
    иначе закрытая дверь выглядит огрызком рядом с открытой.
  */
  .door {
    padding: 22px;

    height: 100%;

    display: flex;

    flex-direction: column;
  }

  .doorBody {
    display: flex;

    flex-direction: column;

    flex: 1;
  }

  .doorBody #lobbyStart,
  .doorBody .lobbyOnline {
    margin-top: auto;
  }

  .door:not(.chosen) {
    opacity: .62;
  }

  /*
    Закрытая дверь на большом экране остаётся раскрытой, но
    без настроек — иначе про живую игру снова никто не узнает.
    Раскладка та же, чтобы действие стояло на одной высоте.
  */
  .door:not(.chosen) .doorBody {
    display: flex;
  }

  .doorPick b {
    font-size: 24px;
  }

  .doorPick em {
    font-size: 13px;
  }

  .doorText {
    font-size: 14px;
  }

  .lobbyLabel {
    font-size: 11px;
  }

  .lobbyLabel em {
    font-size: 12px;
  }

  .lobbyRow {
    padding: 16px 16px 17px;
  }

  #lobbyStart,
  .lobbyOnline {
    font-size: 17px;

    padding: 18px 20px;
  }

  #lobbyStart em,
  .lobbyOnline em {
    font-size: 12px;
  }

  .seatPick {
    width: 46px;
    height: 46px;

    font-size: 19px;
  }

  .rulesOpen {
    margin-top: 22px;

    font-size: 13px;
  }
}


/*
  Телефон: двери прибавили заголовок и поясняющую строку, и
  меню перестало влезать в экран. Пояснение здесь лишнее —
  название двери и так всё говорит, — а отступы ужимаются.
*/
@media (max-width: 779px) {

  .lobbyWindow {
    padding: 18px 16px 16px;
  }

  .doorText {
    display: none;
  }

  .doors {
    gap: 10px;

    margin-top: 12px;
  }

  .door {
    padding: 13px 14px;
  }

  .doorBody {
    margin-top: 11px;
  }

  .rulesOpen {
    margin-top: 12px;
  }
}


/*
  Окна поверх стола центрируются гридом. Когда содержимое выше
  экрана, центрирование срезает его сразу с двух сторон, и низ
  становится недостижим — прокрутки при этом нет. safe center
  на таком экране прижимает окно к верху, а не по центру.
*/
.overlay {
  place-items: safe center;

  overflow-y: auto;

  -webkit-overflow-scrolling: touch;
}


/*
  ПРАВИЛА НА БОЛЬШОМ ЭКРАНЕ

  Узкая колонка в 420 пикселей на мониторе превращала правила
  в длинную ленту, по которой надо долго крутить. Окно
  расширяется, а разделы встают в две колонки — читать
  становится нечего листать.
*/
@media (min-width: 780px) {

  .rulesWindow {
    width:
      min(
        920px,
        calc(100vw - 64px)
      );

    padding: 30px 28px 24px;
  }

  .rulesWindow h2 {
    font-size: 32px;
  }

  .rulesBody {
    display: grid;

    grid-template-columns: 1fr 1fr;

    gap: 4px 28px;

    align-items: start;
  }

  .rulesSection {
    break-inside: avoid;
  }

  .rulesSection p {
    font-size: 15px;
  }
}


/* =========================================================
   ЧЕЙ ХОД

   Прежняя подсветка жила в #playerTurnGlow, а он лежит в
   #playerArea нулевой ширины — то есть не показывалась
   никогда. У соперника подсветка была, но еле заметная:
   тонкая рамка через весь стол не читается.

   Теперь активное место обведено кольцом и медленно дышит,
   а на своём ходу светится сама рука.
   ========================================================= */

.opponent.is-active .opponentPlate {
  border-color: var(--acid);

  box-shadow:
    0 0 0 2px rgba(183, 255, 36, .5),
    0 0 22px rgba(183, 255, 36, .55),
    0 6px 18px rgba(0, 0, 0, .5);

  animation: acidTurnBreath 2.4s ease-in-out infinite;
}

.opponent.is-active .opponentName {
  color: var(--acid);
}

.opponent.is-active .opponentBack {
  border-color: rgba(183, 255, 36, .7);

  box-shadow: 0 0 10px rgba(183, 255, 36, .3);
}

@keyframes acidTurnBreath {
  50% {
    box-shadow:
      0 0 0 3px rgba(183, 255, 36, .32),
      0 0 34px rgba(183, 255, 36, .38),
      0 6px 18px rgba(0, 0, 0, .5);
  }
}

/* свой ход: подсвечивается веер в руке */
.hand.is-turn::before {
  content: "";

  position: absolute;

  left: 50%;
  bottom: -14%;

  /*
    Рука тянется во всю ширину экрана, а веер — нет. Пятно
    по ширине руки размазывается в ничто, поэтому оно жёстко
    ограничено размером самого веера.
  */
  width: min(46%, 560px);
  height: 74%;

  transform: translateX(-50%);

  border-radius: 50%;

  background:
    radial-gradient(
      closest-side,
      rgba(183, 255, 36, .46),
      rgba(183, 255, 36, .16) 52%,
      transparent 76%
    );

  filter: blur(6px);

  pointer-events: none;

  z-index: 0;

  animation: acidTurnBreath 2.4s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {

  .opponent.is-active .opponentPlate,
  .hand.is-turn::before {
    animation: none;
  }
}


/* =========================================================
   ШТРАФ ВИДЕН ПО КАРТЕ

   Число сверху легко пропустить: глаз в этот момент смотрит
   в центр стола. Пока штраф висит, аура сброса переключается
   с цвета хода на тревожную и начинает пульсировать — то
   есть подсвечивается ровно та карта, которая прилетела.
   ========================================================= */

.discardPile.is-penalty {
  --aura: var(--magenta);
  --aura-strong: rgba(255, 43, 214, .88);
  --aura-soft: rgba(255, 43, 214, .40);
}

.discardPile.is-penalty::after {
  animation: acidPenaltyPulse 1.05s ease-in-out infinite;
}

@keyframes acidPenaltyPulse {
  50% {
    opacity: .42;
  }
}

@media (prefers-reduced-motion: reduce) {

  .discardPile.is-penalty::after {
    animation: none;
  }
}


/* =========================================================
   СОПЕРНИКИ КРУПНЕЕ НА БОЛЬШОМ ЭКРАНЕ

   На мониторе значки соперников оставались телефонного
   размера: карты в веере читались как крошки.
   ========================================================= */

@media (min-width: 900px) {

  .opponent {
    width: 122px;
  }

  .opponentBack {
    width: 26px;
    height: 39px;
  }

  .opponentFace {
    font-size: 20px;
  }

  .opponentName {
    font-size: 12px;
  }

  .opponentCount {
    font-size: 20px;
  }

  .opponentPlate {
    padding: 7px 11px;
  }
}


/* =========================================================
   СПЕЦКАРТЫ — КАНОНИЧЕСКИЕ ЗНАКИ UNO

   Знаки те же, что на настоящих картах: перечёркнутый круг
   на пропуске, встречные стрелки на развороте, две карты на
   «+2», четыре цветные — на «+4», четырёхцветный круг на
   смене цвета. Своё здесь только исполнение: маска, залитая
   цветом масти, светится тем же неоном, что и цифры.

   Раньше тут были шприц и противогаз — красиво, но игрок
   опознаёт карту по знаку, который знает с детства.

   Номинал никуда не делся: он остаётся в обоих углах и в
   подписи под знаком.
   ========================================================= */

html[data-deck="acid"] .value[data-v="skip"],
html[data-deck="acid"] .value[data-v="reverse"],
html[data-deck="acid"] .value[data-v="+2"],
html[data-deck="acid"] .value[data-v="+4"],
html[data-deck="acid"] .value[data-v="wild"],
.cardFlash[data-v] {

  /* глиф прячется: его место занимает знак */
  font-size: 0;
  text-shadow: none;

  width: 56%;
  aspect-ratio: 1;

  background: var(--suit);

  /*
    Маска по яркости, а не по альфе: по альфе чёрные детали
    знака остаются непрозрачными и он слипается в пятно.
  */
  -webkit-mask-source-type: luminance;
  mask-mode: luminance;

  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;

  -webkit-mask-position: center;
  mask-position: center;

  -webkit-mask-size: contain;
  mask-size: contain;

  /*
    Три тени — предел: с четырьмя браузер перестаёт вывозить
    маску, и знак темнеет вместо того, чтобы светиться.
  */
  filter:
    drop-shadow(0 0 3px #fff)
    drop-shadow(0 0 10px var(--suit))
    drop-shadow(0 0 22px var(--suit));
}


/*
  Чёрные карты цветные по сути: смена цвета — это все четыре
  масти сразу. Один цвет заливки тут ничего не сказал бы,
  поэтому под маску кладётся конический градиент.
*/
html[data-deck="acid"] .value[data-v="wild"],
html[data-deck="acid"] .value[data-v="+4"],
.cardFlash[data-v="wild"],
.cardFlash[data-v="+4"] {
  background:
    conic-gradient(
      var(--red) 0 25%,
      var(--yellow) 25% 50%,
      var(--green) 50% 75%,
      var(--blue) 75% 100%
    );

  filter:
    drop-shadow(0 0 2px rgba(0, 0, 0, .8));
}

html[data-deck="acid"] .value[data-v="skip"],
.cardFlash[data-v="skip"] {
  -webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='8.4' fill='none' stroke='white' stroke-width='2.6'/><rect x='10.7' y='2.6' width='2.6' height='18.8' rx='1.3' fill='white' transform='rotate(45 12 12)'/></svg>");
  mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='8.4' fill='none' stroke='white' stroke-width='2.6'/><rect x='10.7' y='2.6' width='2.6' height='18.8' rx='1.3' fill='white' transform='rotate(45 12 12)'/></svg>");
}

html[data-deck="acid"] .value[data-v="reverse"],
.cardFlash[data-v="reverse"] {
  -webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M8.6 21.2V6.4' stroke='white' stroke-width='2.4' stroke-linecap='round' fill='none'/><path d='M8.6 2.8l4 5.2h-8z' fill='white'/><path d='M15.4 2.8v14.8' stroke='white' stroke-width='2.4' stroke-linecap='round' fill='none'/><path d='M15.4 21.2l-4-5.2h8z' fill='white'/></svg>");
  mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M8.6 21.2V6.4' stroke='white' stroke-width='2.4' stroke-linecap='round' fill='none'/><path d='M8.6 2.8l4 5.2h-8z' fill='white'/><path d='M15.4 2.8v14.8' stroke='white' stroke-width='2.4' stroke-linecap='round' fill='none'/><path d='M15.4 21.2l-4-5.2h8z' fill='white'/></svg>");
}

html[data-deck="acid"] .value[data-v="+2"],
.cardFlash[data-v="+2"] {
  -webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><rect x='2.2' y='5.4' width='10.6' height='13.6' rx='2' fill='white'/><rect x='9.4' y='2.2' width='13' height='17.4' rx='2.6' fill='black'/><rect x='11' y='3.8' width='10.6' height='15' rx='2' fill='white'/></svg>");
  mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><rect x='2.2' y='5.4' width='10.6' height='13.6' rx='2' fill='white'/><rect x='9.4' y='2.2' width='13' height='17.4' rx='2.6' fill='black'/><rect x='11' y='3.8' width='10.6' height='15' rx='2' fill='white'/></svg>");
}

html[data-deck="acid"] .value[data-v="+4"],
.cardFlash[data-v="+4"] {
  -webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><rect x='2.4' y='2.4' width='8.6' height='8.6' rx='1.8' fill='white'/><rect x='13' y='2.4' width='8.6' height='8.6' rx='1.8' fill='white'/><rect x='2.4' y='13' width='8.6' height='8.6' rx='1.8' fill='white'/><rect x='13' y='13' width='8.6' height='8.6' rx='1.8' fill='white'/></svg>");
  mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><rect x='2.4' y='2.4' width='8.6' height='8.6' rx='1.8' fill='white'/><rect x='13' y='2.4' width='8.6' height='8.6' rx='1.8' fill='white'/><rect x='2.4' y='13' width='8.6' height='8.6' rx='1.8' fill='white'/><rect x='13' y='13' width='8.6' height='8.6' rx='1.8' fill='white'/></svg>");
}

html[data-deck="acid"] .value[data-v="wild"],
.cardFlash[data-v="wild"] {
  -webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='10.4' fill='white'/></svg>");
  mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='10.4' fill='white'/></svg>");
}

/* =========================================================
   РУБАШКА КИСЛОТНОЙ КОЛОДЫ

   В макете рубашка — трилистник на чёрном, а не надпись на
   фиолетовом. Имя игры остаётся, но уходит вниз мелкой
   строкой: его читают один раз, знак — всю партию.
   ========================================================= */

html[data-deck="acid"] .deckBack {
  border-color: rgba(183, 255, 36, .55);

  background:
    radial-gradient(
      ellipse at 50% 34%,
      rgba(24, 14, 38, .96),
      rgba(6, 3, 12, .99) 72%
    );

  box-shadow:
    0 0 8px rgba(183, 255, 36, .45),
    0 0 22px rgba(139, 61, 255, .35),
    inset 0 0 20px rgba(255, 255, 255, .05);
}

html[data-deck="acid"] .deckBack::before {
  opacity: .07;
}

html[data-deck="acid"] .deckBack::after {
  content: "";

  position: absolute;

  top: 17%;

  width: 54%;
  aspect-ratio: 1;

  background: var(--acid);

  -webkit-mask-source-type: luminance;
  mask-mode: luminance;

  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;

  -webkit-mask-position: center;
  mask-position: center;

  -webkit-mask-size: contain;
  mask-size: contain;

  -webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='3' fill='white'/><path d='M 9.40 7.50 L 6.40 2.30 A 11.2 11.2 0 0 1 17.60 2.30 L 14.60 7.50 A 5.2 5.2 0 0 0 9.40 7.50 Z' fill='white'/><path d='M 17.20 12.00 L 23.20 12.00 A 11.2 11.2 0 0 1 17.60 21.70 L 14.60 16.50 A 5.2 5.2 0 0 0 17.20 12.00 Z' fill='white'/><path d='M 9.40 16.50 L 6.40 21.70 A 11.2 11.2 0 0 1 0.80 12.00 L 6.80 12.00 A 5.2 5.2 0 0 0 9.40 16.50 Z' fill='white'/></svg>");
  mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='3' fill='white'/><path d='M 9.40 7.50 L 6.40 2.30 A 11.2 11.2 0 0 1 17.60 2.30 L 14.60 7.50 A 5.2 5.2 0 0 0 9.40 7.50 Z' fill='white'/><path d='M 17.20 12.00 L 23.20 12.00 A 11.2 11.2 0 0 1 17.60 21.70 L 14.60 16.50 A 5.2 5.2 0 0 0 17.20 12.00 Z' fill='white'/><path d='M 9.40 16.50 L 6.40 21.70 A 11.2 11.2 0 0 1 0.80 12.00 L 6.80 12.00 A 5.2 5.2 0 0 0 9.40 16.50 Z' fill='white'/></svg>");

  filter:
    drop-shadow(0 0 3px #fff)
    drop-shadow(0 0 12px var(--acid))
    drop-shadow(0 0 26px var(--acid));

  pointer-events: none;
}

/* имя игры уходит под знак мелкой строкой */
html[data-deck="acid"] .deckAcid {
  position: relative;

  top: 32%;

  font-size: 8px;

  letter-spacing: .24em;

  background: none;

  -webkit-text-fill-color: currentColor;

  color: rgba(183, 255, 36, .75);

  text-shadow: 0 0 8px rgba(183, 255, 36, .45);
}

html[data-deck="acid"] .deckUno {
  display: none;
}


/* =========================================================
   АРЕНА ВМЕСТО СЕТКИ

   В макете стол — круглая арена с кольцами и подсветкой
   снизу, а не прямоугольник в клетку. Клетка остаётся, но
   уходит на второй план: поверх неё ложатся концентрические
   кольца и свет из центра.
   ========================================================= */

.tableGrid {
  opacity: .07;
}

.tableInner::before {
  content: "";

  position: absolute;

  left: 50%;
  top: 50%;

  width: 128%;
  aspect-ratio: 1;

  transform: translate(-50%, -50%);

  border-radius: 50%;

  pointer-events: none;

  z-index: 0;

  background:
    repeating-radial-gradient(
      circle at 50% 50%,
      transparent 0 26px,
      rgba(139, 61, 255, .16) 26px 27px,
      transparent 27px 54px
    );

  /*
    Кольца гаснут к краям стола: иначе видно, что круг больше
    прямоугольника и обрезается его углами.
  */
  -webkit-mask-image:
    radial-gradient(
      circle at 50% 50%,
      #000 34%,
      transparent 72%
    );

  mask-image:
    radial-gradient(
      circle at 50% 50%,
      #000 34%,
      transparent 72%
    );
}

.tableInner::after {
  content: "";

  position: absolute;

  left: 50%;
  bottom: -14%;

  width: 86%;
  height: 58%;

  transform: translateX(-50%);

  border-radius: 50%;

  pointer-events: none;

  z-index: 0;

  background:
    radial-gradient(
      closest-side,
      rgba(139, 61, 255, .22),
      rgba(139, 61, 255, .07) 52%,
      transparent 78%
    );

  filter: blur(10px);
}


/* =========================================================
   ЧИП ТЕКУЩЕГО ЦВЕТА

   Точка рядом со словом «цвет» не называет цвет — а именно
   его и надо знать после чёрной карты. В макете это плашка
   с названием, она же и красится.
   ========================================================= */

.currentColor {
  gap: 7px;

  padding: 5px 11px;

  border-radius: 999px;

  border: 1px solid color-mix(in srgb, var(--chip, var(--purple)) 55%, transparent);

  background: color-mix(in srgb, var(--chip, var(--purple)) 12%, transparent);

  box-shadow:
    0 0 10px color-mix(in srgb, var(--chip, var(--purple)) 30%, transparent);
}

.currentColor .colorName {
  font-size: 10px;
  font-weight: 900;

  letter-spacing: .14em;

  color: var(--chip, var(--purple));

  text-shadow: 0 0 8px color-mix(in srgb, var(--chip, var(--purple)) 60%, transparent);
}


/* =========================================================
   БЫСТРЫЙ ЧАТ

   Появляется только за живым столом: кнопку и лист создаёт
   room.js, когда игрок сел в комнату. С ботами говорить
   не с кем.
   ========================================================= */

#chatOpen {
  position: fixed;

  left: max(14px, env(safe-area-inset-left));

  bottom:
    max(
      118px,
      calc(env(safe-area-inset-bottom) + 94px)
    );

  z-index: 15000;

  width: 46px;
  height: 46px;

  padding: 0;

  font-size: 20px;

  border-radius: 50%;

  border: 1px solid rgba(32, 234, 255, .5);

  background: rgba(10, 5, 20, .82);

  cursor: pointer;

  box-shadow: 0 0 14px rgba(32, 234, 255, .28);
}

#chatSheet {
  position: fixed;

  left: max(14px, env(safe-area-inset-left));

  bottom:
    max(
      172px,
      calc(env(safe-area-inset-bottom) + 148px)
    );

  z-index: 15001;

  width: min(280px, calc(100vw - 28px));

  display: grid;

  grid-template-columns: 1fr 1fr;

  gap: 6px;

  padding: 10px;

  border-radius: 16px;

  border: 1px solid rgba(32, 234, 255, .32);

  background: rgba(8, 4, 16, .96);

  box-shadow: 0 18px 44px rgba(0, 0, 0, .6);
}

#chatSheet.hidden {
  display: none;
}

#chatSheet button {
  padding: 10px 8px;

  font-size: 10px;
  font-weight: 900;

  letter-spacing: .06em;

  color: var(--white);

  border-radius: 10px;

  border: 1px solid rgba(181, 93, 255, .34);

  background: rgba(255, 255, 255, .03);

  cursor: pointer;
}

/*
  Реплика висит у сказавшего. Плашка соперника мелкая, поэтому
  пузырь уводится над ней и не растягивает саму плашку.
*/
.chatBubble {
  position: absolute;

  left: 50%;
  bottom: 100%;

  transform: translate(-50%, -8px);

  z-index: 30;

  max-width: 160px;

  padding: 6px 10px;

  border-radius: 12px;

  font-size: 10px;
  font-weight: 900;

  letter-spacing: .06em;

  white-space: nowrap;

  color: var(--white);

  border: 1px solid rgba(32, 234, 255, .5);

  background: rgba(8, 4, 16, .96);

  box-shadow: 0 0 16px rgba(32, 234, 255, .3);

  pointer-events: none;

  animation: acidChatIn .22s ease-out;
}

@keyframes acidChatIn {
  from {
    opacity: 0;
    transform: translate(-50%, 2px);
  }
}


/* =========================================================
   НИЗКИЙ МОНИТОР

   Ноутбук с открытыми панелями браузера оставляет под
   страницу шестьсот-семьсот точек, а меню из двух дверей
   выросло до восьмисот. Прокрутка есть, но стартовый экран
   листать не должен: он весь обязан быть виден сразу.

   Поэтому на низких экранах меню ужимается, а не режется.
   ========================================================= */

@media (min-width: 780px) and (max-height: 860px) {

  .lobbyWindow {
    padding: 20px 22px 18px;
  }

  .lobbyWindow h2 {
    font-size: 25px;
  }

  .lobbyWindow .windowEyebrow {
    font-size: 9px;
  }

  .doors {
    gap: 14px;

    margin-top: 16px;
  }

  .door {
    padding: 15px 16px;
  }

  .doorPick b {
    font-size: 19px;
  }

  .doorPick em {
    font-size: 11px;

    margin-top: 3px;
  }

  .doorBody {
    margin-top: 11px;
  }

  .doorText {
    font-size: 12px;

    margin-bottom: 11px;
  }

  .door .lobbySetup {
    margin-bottom: 11px;
  }

  .lobbyRow {
    padding: 9px 11px 10px;
  }

  .lobbyLabel {
    font-size: 9px;

    margin-bottom: 6px;
  }

  .lobbyLabel em {
    font-size: 10px;
  }

  .seatPick {
    width: 36px;
    height: 36px;

    font-size: 15px;
  }

  .deckPick,
  .clockToggle {
    padding: 8px 10px;

    font-size: 10px;
  }

  .lobbyNote {
    font-size: 9px;

    margin-top: 6px;
  }

  #lobbyStart,
  .lobbyOnline {
    padding: 12px 16px;

    font-size: 14px;
  }

  #lobbyStart em,
  .lobbyOnline em {
    font-size: 10px;
  }

  .rulesOpen {
    margin-top: 12px;

    font-size: 11px;
  }
}


/* =========================================================
   СОПЕРНИКИ ПОД РАЗМЕР ЭКРАНА

   Карты в руке на мониторе уже вырастают (правила в
   style.css), а значки соперников оставались телефонными:
   между большими картами внизу и крошечными плашками сверху
   стол выглядел кривым.

   Размер привязан к высоте окна, а не к ширине: стол
   упирается именно в высоту. Нижняя граница выше прежней —
   даже на низком ноутбуке соперник перестаёт быть крошкой.
   ========================================================= */

@media (min-width: 1000px) {

  :root {
    --table-max-w: 1240px;
    --table-max-h: 700px;
  }

  /*
    На мониторе соперники сидели прямо на игровом поле:
    дуга проходила внутри стола. Между шапкой и столом есть
    свободная полоса — туда их и поднимаем.
  */
  .opponents {
    /*
      Верх дуги должен пройти под шапкой: при пяти-семи местах
      кто-то садится точно в её вершину, и веер над плашкой
      торчит ещё на два десятка точек вверх. Разница
      arc-y минус arc-ry — это и есть высота вершины.
    */
    --arc-y: 42%;
    --arc-ry: 30%;
  }

  /*
    Чем больше соперников, тем выше забирается тот, кто сидит
    в вершине дуги. На пяти-шести местах вершину приходится
    опускать, иначе веер лезет под шапку.
  */
  .opponents[data-count="5"] {
    --arc-ry: 28%;
  }

  .opponents[data-count="6"] {
    --arc-ry: 26%;
  }

  /*
    Размер зависит от того, сколько их за столом: втроём места
    вдоволь и соперник должен быть крупным, всемером дуга
    забита и значки обязаны ужаться, иначе налезут друг на
    друга.
  */
  .opponent {
    width: clamp(206px, 25vh, 280px);
  }

  .opponentBack {
    width: clamp(62px, 7.6vh, 88px);
    height: clamp(93px, 11.4vh, 132px);

    /*
      Шаг раскладки растёт вместе с картой: при прежних
      четырнадцати точках крупные рубашки складывались почти
      в одну и веер переставал показывать количество.
    */
    --fan-step: clamp(26px, 3.1vh, 36px);

    margin-left: calc(clamp(62px, 7.6vh, 88px) / -2);
  }

  .opponents[data-count="4"] .opponent {
    width: clamp(178px, 21vh, 236px);
  }

  .opponents[data-count="4"] .opponentBack {
    width: clamp(52px, 6.4vh, 74px);
    height: clamp(78px, 9.6vh, 111px);

    --fan-step: clamp(22px, 2.6vh, 30px);

    margin-left: calc(clamp(52px, 6.4vh, 74px) / -2);
  }

  .opponents[data-count="5"] .opponent,
  .opponents[data-count="6"] .opponent {
    width: clamp(150px, 17vh, 190px);
  }

  .opponents[data-count="5"] .opponentBack,
  .opponents[data-count="6"] .opponentBack {
    width: clamp(42px, 5.1vh, 58px);
    height: clamp(63px, 7.7vh, 87px);

    --fan-step: clamp(17px, 2vh, 23px);

    margin-left: calc(clamp(42px, 5.1vh, 58px) / -2);
  }

  .opponentFace {
    font-size: clamp(23px, 2.8vh, 32px);
  }

  .opponentName {
    font-size: clamp(13px, 1.7vh, 18px);
  }

  .opponentCount {
    font-size: clamp(22px, 2.8vh, 32px);
  }

  .opponentPlate {
    padding: clamp(8px, 1.1vh, 13px) clamp(13px, 1.7vh, 20px);
  }
}


/* =========================================================
   СВОЙ ХОД ВИДЕН НА СВОЁМ ИМЕНИ

   У соперника имя загоралось, у себя — нет: на своём ходу
   подсвечен оказывался никто. Здесь подсветка сильнее, чем
   у соперника: это твоя очередь, и заметить её надо первым.
   ========================================================= */

.playerHUD {
  transition:
    color .25s ease,
    text-shadow .25s ease;
}

.playerHUD.is-turn .youLabel {
  color: var(--acid);

  text-shadow:
    0 0 6px rgba(255, 255, 255, .8),
    0 0 16px var(--acid),
    0 0 34px var(--acid);

  animation: acidTurnBreath 2.2s ease-in-out infinite;
}

.playerHUD.is-turn .youLabel::after {
  content: " · ТВОЙ ХОД";

  letter-spacing: .18em;
}

.playerHUD .youLabel,
.playerHUD #playerCount {
  padding: 4px 10px;
  border: 1px solid rgba(183, 255, 36, .18);
  border-radius: 10px;
  background: rgba(8, 4, 18, .84);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}

.playerHUD.is-turn .youLabel {
  border-color: rgba(183, 255, 36, .6);
  box-shadow: 0 0 18px rgba(183, 255, 36, .3);
  text-shadow: 0 1px 2px rgba(0, 0, 0, .9);
}

@media (prefers-reduced-motion: reduce) {

  .playerHUD.is-turn .youLabel {
    animation: none;
  }
}


/* =========================================================
   КАКОЙ КАРТОЙ МОЖНО ПОЙТИ

   Подсветку однажды сделали слабее по просьбе — и стало
   непонятно вовсе. Теперь наоборот: играбельная карта
   выглядит обычной картой, а неиграбельная явно гасится и
   отходит вниз. Разница читается по всему вееру сразу, а не
   по свечению одной карты.
   ========================================================= */

/*
  Карты, которыми ходить нельзя, не гасятся вовсе. Разницу
  делает свет от играбельной карты, а не темнота от остальных:
  затемнение половины веера читается как поломка, а не как
  подсказка.
*/
#hand .handCard.v9-unplayable {
  filter: none;

  opacity: 1;

  transition: filter 90ms ease, box-shadow 90ms ease;
}

/*
  Пока карту тащат, гашение снимается совсем: в этот момент
  игрок смотрит на стол, а тёмный веер под рукой только мешает.
  Вернётся сразу, как отпустит.
*/
body:has(#animationLayer .v91-dragging) #hand .handCard.v9-unplayable {
  filter: none;

  opacity: 1;
}

/*
  Играбельная карта светится сама.

  Свечение обязано быть drop-shadow, а не box-shadow: у
  кислотной карты срезаны углы через clip-path, а он обрезает
  и тень — контур просто не рисовался, и подсветки не было
  видно вовсе, сколько её ни усиливай. drop-shadow идёт по
  силуэту после обрезки.
*/
#hand .handCard.v9-playable,
#hand .handCard.playable {
  filter: brightness(1.14) saturate(1.1);
  z-index: 20;

  opacity: 1;
}

/* #hand в селекторе обязателен: без него базовое правило с
   идентификатором перебивает это по специфичности */
#hand.is-turn .handCard.v9-playable,
#hand.is-turn .handCard.playable {
  filter:
    brightness(1.14)
    saturate(1.1)
    drop-shadow(0 0 5px rgba(183, 255, 36, .9))
    drop-shadow(0 0 16px rgba(183, 255, 36, .5));
}


/* После удачного UNO ответ виден на самом игроке, а не теряется
   среди текста статуса. Метка держится, пока состояние партии
   помнит объявление, и сбрасывается вместе с ростом руки. */
.playerHUD.uno-called::after {
  content: "UNO!";
  position: absolute;
  left: 50%;
  bottom: calc(100% + 8px);
  transform: translateX(-50%) rotate(-7deg);
  min-width: 64px;
  padding: 7px 10px;
  border: 2px solid #ecff69;
  border-radius: 12px;
  background: #a6f42a;
  color: #09020c;
  font: 900 22px/1 system-ui, sans-serif;
  letter-spacing: .06em;
  text-align: center;
  box-shadow: 0 0 12px rgba(183, 255, 36, .95), 0 0 28px rgba(183, 255, 36, .52);
  animation: acidPlayerUno .72s ease-in-out infinite alternate;
  pointer-events: none;
  z-index: 30;
}

@keyframes acidPlayerUno {
  from { transform: translateX(-50%) rotate(-7deg) scale(.94); }
  to { transform: translateX(-50%) rotate(-7deg) scale(1.08); }
}


/* =========================================================
   ЗНАК СПЕЦКАРТЫ НА ВЕСЬ СТОЛ

   Ход соперника длится доли секунды, и по маленькой карте в
   центре не успеваешь понять, что случилось. В мобильном UNO
   спецкарта разворачивает свой знак во весь стол — здесь то
   же самое, знаком нашей колоды.

   Размер, маски и заливка берутся у карты: одна и та же
   картинка, только больше.
   ========================================================= */

.cardFlash {
  position: absolute;

  left: 50%;
  top: 46%;

  transform: translate(-50%, -50%) scale(.72);

  /*
    Под картами, а не поверх: вспышка должна сообщать, что
    случилось, а не закрывать стол. Поверх она читается как
    сбой отрисовки — карты пропадают на секунду.
  */
  z-index: 2;

  opacity: 0;

  pointer-events: none;
}

.cardFlash.show {
  animation: acidCardFlash 1.05s cubic-bezier(.16, .84, .28, 1) forwards;
}

/* лучи из-под знака */
.cardFlash::after {
  content: "";

  position: absolute;

  left: 50%;
  top: 50%;

  width: 200%;
  aspect-ratio: 1;

  transform: translate(-50%, -50%);

  border-radius: 50%;

  z-index: -1;

  background:
    radial-gradient(
      closest-side,
      color-mix(in srgb, var(--suit, var(--purple)) 34%, transparent),
      transparent 70%
    );

  filter: blur(14px);
}

@keyframes acidCardFlash {

  0% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(.62);
  }

  22% {
    opacity: .6;
    transform: translate(-50%, -50%) scale(1.04);
  }

  58% {
    opacity: .42;
    transform: translate(-50%, -50%) scale(1);
  }

  100% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(1.16);
  }
}

@media (prefers-reduced-motion: reduce) {

  .cardFlash.show {
    animation-duration: .3s;
  }
}


/*
  Ширина задаётся с тем же весом, что и общее правило знака:
  иначе выигрывают его 56% и вспышка занимает весь стол.
*/
.cardFlash[data-v] {
  width: min(30vh, 23vw);

  aspect-ratio: 1;
}


/* =========================================================
   ПОЛНОЭКРАННАЯ НАДПИСЬ НА МОНИТОРЕ

   На телефоне она во весь экран уместна, на мониторе тем же
   кеглем занимает половину поля и мешает смотреть на стол.
   Здесь она меньше и держится дольше — прочитать успеваешь
   именно за счёт времени, а не размера.
   ========================================================= */

@media (min-width: 1000px) {

  #v9Burst {
    font-size: clamp(26px, 3.4vh, 40px);

    padding: 10px 20px;

    letter-spacing: .06em;
  }
}


/* =========================================================
   ВЫБОР ЦВЕТА — БАРАБАН

   Было четыре плоских кнопки в ряд: по ним приходится
   прицеливаться, и с самой картой они никак не связаны.
   Стало то же кольцо из четырёх мастей, что нарисовано на
   чёрной карте, — ведёшь пальцем, сектор разгорается, в
   центре пишется название. Порядок секторов тот же, что в
   градиенте знака: розовый сверху, жёлтый справа, зелёный
   снизу, голубой слева.
   ========================================================= */

.colorWindow .colors {
  display: none;
}

.colorWheel {
  position: relative;

  width: min(64vw, 42vh, 320px);

  aspect-ratio: 1;

  margin: 18px auto 6px;

  border-radius: 50%;

  overflow: hidden;

  box-shadow:
    0 0 0 2px rgba(255, 255, 255, .12),
    0 0 34px rgba(139, 61, 255, .35),
    inset 0 0 40px rgba(0, 0, 0, .55);

  transition: transform .3s ease, opacity .3s ease;
}

.colorWheel .pick {
  position: absolute;

  inset: 0;

  width: auto;
  height: auto;

  margin: 0;
  padding: 0;

  border: 0;
  border-radius: 0;

  cursor: pointer;

  transition: filter .16s ease;

  filter: brightness(.82) saturate(1);
}

.colorWheel .pick.red {
  background: var(--red);

  clip-path: polygon(50% 50%, 0 0, 100% 0);
}

.colorWheel .pick.yellow {
  background: var(--yellow);

  clip-path: polygon(50% 50%, 100% 0, 100% 100%);
}

.colorWheel .pick.green {
  background: var(--green);

  clip-path: polygon(50% 50%, 100% 100%, 0 100%);
}

.colorWheel .pick.blue {
  background: var(--blue);

  clip-path: polygon(50% 50%, 0 100%, 0 0);
}

/*
  :hover здесь намеренно нет: наведение читается как сделанный
  выбор, хотя выбором является только нажатие.
*/
.colorWheel .pick:active,
.colorWheel .pick.hot {
  filter: brightness(1.22) saturate(1.1);

  outline: none;
}

/* ступица с названием — она же перекрывает стык секторов */
.wheelHub {
  position: absolute;

  left: 50%;
  top: 50%;

  transform: translate(-50%, -50%);

  width: 46%;
  aspect-ratio: 1;

  display: grid;
  place-items: center;

  border-radius: 50%;

  background:
    radial-gradient(
      circle at 50% 34%,
      rgba(24, 14, 38, .97),
      rgba(6, 3, 12, .99) 72%
    );

  box-shadow:
    0 0 0 2px rgba(255, 255, 255, .1),
    0 0 22px rgba(0, 0, 0, .6);

  font-size: clamp(11px, 2.4vh, 16px);
  font-weight: 900;

  letter-spacing: .16em;

  text-align: center;

  color: var(--hub, rgba(248, 247, 255, .55));

  text-shadow: 0 0 12px color-mix(in srgb, var(--hub, transparent) 70%, transparent);

  pointer-events: none;

  transition: color .16s ease;
}

/* выбрал — барабан схлопывается в центр стола */
.colorWheel.collapsing {
  transform: scale(.14);

  opacity: 0;
}


/* =========================================================
   РУБАШКИ СОПЕРНИКОВ — ПОД КИСЛОТНУЮ КОЛОДУ

   Колода в центре стала тёмной со знаком, а рубашки в руках
   соперников остались лиловыми от прежней колоды. Из-за этого
   с тёмной колоды летели чужие фиолетовые карты — рубашка
   обязана совпадать с той, что лежит в центре.
   ========================================================= */

html[data-deck="acid"] .opponentBack,
html[data-deck="acid"] #botCards .v9-bot-card {
  border-color: rgba(183, 255, 36, .5);

  background:
    radial-gradient(
      ellipse at 50% 32%,
      rgba(26, 15, 40, .97),
      rgba(7, 4, 14, .99) 74%
    );

  box-shadow:
    0 0 6px rgba(183, 255, 36, .22),
    0 2px 6px rgba(0, 0, 0, .55);
}

html[data-deck="acid"] .opponentBack::after,
html[data-deck="acid"] #botCards .v9-bot-card::after {
  content: "";

  position: absolute;

  left: 50%;
  top: 50%;

  width: 58%;
  aspect-ratio: 1;

  transform: translate(-50%, -50%);

  background: var(--acid);

  opacity: .72;

  -webkit-mask-source-type: luminance;
  mask-mode: luminance;

  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;

  -webkit-mask-position: center;
  mask-position: center;

  -webkit-mask-size: contain;
  mask-size: contain;

  -webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='3' fill='white'/><path d='M 9.40 7.50 L 6.40 2.30 A 11.2 11.2 0 0 1 17.60 2.30 L 14.60 7.50 A 5.2 5.2 0 0 0 9.40 7.50 Z' fill='white'/><path d='M 17.20 12.00 L 23.20 12.00 A 11.2 11.2 0 0 1 17.60 21.70 L 14.60 16.50 A 5.2 5.2 0 0 0 17.20 12.00 Z' fill='white'/><path d='M 9.40 16.50 L 6.40 21.70 A 11.2 11.2 0 0 1 0.80 12.00 L 6.80 12.00 A 5.2 5.2 0 0 0 9.40 16.50 Z' fill='white'/></svg>");
  mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='3' fill='white'/><path d='M 9.40 7.50 L 6.40 2.30 A 11.2 11.2 0 0 1 17.60 2.30 L 14.60 7.50 A 5.2 5.2 0 0 0 9.40 7.50 Z' fill='white'/><path d='M 17.20 12.00 L 23.20 12.00 A 11.2 11.2 0 0 1 17.60 21.70 L 14.60 16.50 A 5.2 5.2 0 0 0 17.20 12.00 Z' fill='white'/><path d='M 9.40 16.50 L 6.40 21.70 A 11.2 11.2 0 0 1 0.80 12.00 L 6.80 12.00 A 5.2 5.2 0 0 0 9.40 16.50 Z' fill='white'/></svg>");

  pointer-events: none;
}


/* =========================================================
   СВЕЧЕНИЕ КАРТЫ — С СЕРЕДИНЫ НА КРАЯ

   Номинал полыхал так, что каждая карта в руке выглядела
   подсвеченной, и понять, какой из них можно ходить, было
   нельзя. Свет с цифры убавлен, а по кромке карты добавлено
   ровное свечение мастью — карта читается целиком, но не
   спорит с зелёным ореолом играбельной.
   ========================================================= */

html[data-deck="acid"] .card .value,
html[data-deck="acid"] .handCard .value,
html[data-deck="acid"] .flyingCard .value {
  text-shadow:
    0 0 2px rgba(255, 255, 255, .9),
    0 0 7px var(--suit);
}

html[data-deck="acid"] .card::after,
html[data-deck="acid"] .handCard::after,
html[data-deck="acid"] .flyingCard::after {
  box-shadow:
    inset 0 0 10px color-mix(in srgb, var(--suit) 45%, transparent),
    inset 0 0 22px color-mix(in srgb, var(--suit) 18%, transparent);
}


/* =========================================================
   БАРАБАН: НАВЕДЕНИЕ ПОДСВЕЧИВАЕТ, НО НЕ ВЫБИРАЕТ

   Совсем без отклика сектор выглядит неживым. Наведение
   слегка поднимает сектор, но название масти в ступице
   появляется только при нажатии — выбор по-прежнему делает
   лишь клик или тап.
   ========================================================= */

.colorWheel .pick:hover {
  filter: brightness(1.04) saturate(1.06);
}


/* =========================================================
   ПЯТЬ МАТЕРИАЛОВ КАРТЫ

   Каркас у карты один — восьмиугольник, неоновая рамка, знак
   мастью. Меняется то, из чего карта как будто сделана.
   Материал выбирается случайно на партию: за вечер стол ни
   разу не повторяется, а правила и раскладка не меняются.

   Атрибут data-skin ставится на <html> при старте партии.
   ========================================================= */

/* ---------- ПЛЁНКА: голографическая фольга ---------- */

html[data-skin="film"] .card::before,
html[data-skin="film"] .handCard::before,
html[data-skin="film"] .flyingCard::before {
  background:
    linear-gradient(
      118deg,
      transparent 0 16%,
      color-mix(in srgb, var(--suit) 36%, transparent) 29%,
      transparent 43%,
      color-mix(in srgb, var(--cyan) 24%, transparent) 57%,
      transparent 69%,
      color-mix(in srgb, var(--magenta) 26%, transparent) 83%,
      transparent 95%
    ),
    radial-gradient(
      ellipse at 50% 20%,
      rgba(20, 11, 32, .96),
      rgba(5, 2, 10, .99) 74%
    );
}

html[data-skin="film"] .card .value,
html[data-skin="film"] .handCard .value,
html[data-skin="film"] .flyingCard .value {
  color: #fff;

  /* расщепление по краям — так печатают на фольге */
  text-shadow:
    1.6px 0 0 color-mix(in srgb, var(--magenta) 75%, transparent),
    -1.6px 0 0 color-mix(in srgb, var(--cyan) 75%, transparent),
    0 0 14px var(--suit);
}


/* ---------- СТЕКЛО: матовая пластина ---------- */

html[data-skin="glass"] .card::before,
html[data-skin="glass"] .handCard::before,
html[data-skin="glass"] .flyingCard::before {
  background:
    linear-gradient(
      160deg,
      rgba(255, 255, 255, .12),
      rgba(255, 255, 255, .02) 46%,
      rgba(255, 255, 255, .08)
    ),
    radial-gradient(
      ellipse at 50% 62%,
      color-mix(in srgb, var(--suit) 34%, transparent),
      transparent 68%
    ),
    rgba(12, 7, 22, .66);
}

html[data-skin="glass"] .card::after,
html[data-skin="glass"] .handCard::after,
html[data-skin="glass"] .flyingCard::after {
  border-color: rgba(255, 255, 255, .34);
}

html[data-skin="glass"] .card .value,
html[data-skin="glass"] .handCard .value,
html[data-skin="glass"] .flyingCard .value {
  color: #fff;

  text-shadow:
    0 0 18px var(--suit),
    0 2px 0 rgba(0, 0, 0, .35);
}


/* ---------- ПЛАТА: печатная плата ---------- */

html[data-skin="pcb"] .card::before,
html[data-skin="pcb"] .handCard::before,
html[data-skin="pcb"] .flyingCard::before {
  background:
    linear-gradient(
      90deg,
      transparent 0 49.3%,
      color-mix(in srgb, var(--suit) 36%, transparent) 49.3% 50.7%,
      transparent 50.7%
    ),
    linear-gradient(
      0deg,
      transparent 0 49.3%,
      color-mix(in srgb, var(--suit) 22%, transparent) 49.3% 50.7%,
      transparent 50.7%
    ),
    repeating-linear-gradient(
      45deg,
      color-mix(in srgb, var(--suit) 9%, transparent) 0 1px,
      transparent 1px 13px
    ),
    radial-gradient(ellipse at 50% 30%, #0d1410, #050806 76%);
}

html[data-skin="pcb"] .card .value,
html[data-skin="pcb"] .handCard .value,
html[data-skin="pcb"] .flyingCard .value {
  color: var(--suit);

  text-shadow:
    0 0 2px #fff,
    0 0 12px var(--suit);
}


/* ---------- ТРУБКА: неоновая вывеска ---------- */

html[data-skin="tube"] .card::before,
html[data-skin="tube"] .handCard::before,
html[data-skin="tube"] .flyingCard::before {
  background:
    radial-gradient(
      ellipse at 50% 46%,
      color-mix(in srgb, var(--suit) 15%, transparent),
      transparent 66%
    ),
    radial-gradient(
      ellipse at 50% 24%,
      rgba(14, 8, 24, .98),
      rgba(3, 1, 7, .99) 76%
    );
}

/*
  Цифра — полая трубка, а не залитый знак: контур толстый,
  внутри пусто, вокруг ореол. Тонкая обводка выглядела просто
  бледной цифрой, поэтому здесь она заметно жирнее.
*/
html[data-skin="tube"] .card .value,
html[data-skin="tube"] .handCard .value,
html[data-skin="tube"] .flyingCard .value {
  color: transparent;

  -webkit-text-stroke: 3.4px var(--suit);

  text-shadow: none;

  filter:
    drop-shadow(0 0 2px #fff)
    drop-shadow(0 0 10px var(--suit))
    drop-shadow(0 0 26px var(--suit));
}

/* знаки светятся сильнее обычного — на трубке свет несёт всё */
html[data-skin="tube"] .value[data-v] {
  filter:
    drop-shadow(0 0 3px #fff)
    drop-shadow(0 0 14px var(--suit))
    drop-shadow(0 0 32px var(--suit));
}

html[data-skin="tube"] .card::after,
html[data-skin="tube"] .handCard::after,
html[data-skin="tube"] .flyingCard::after {
  opacity: .55;
}


/* ---------- ЭЛТ: кинескоп ---------- */

html[data-skin="crt"] .card::before,
html[data-skin="crt"] .handCard::before,
html[data-skin="crt"] .flyingCard::before {
  background:
    /*
      Апертурная решётка: на кинескопе пиксель — это три
      цветные полоски, и вблизи их видно. Без них «строчки»
      читаются просто как полосатая карта.
    */
    repeating-linear-gradient(
      90deg,
      rgba(255, 40, 90, .16) 0 2px,
      rgba(60, 255, 130, .16) 2px 4px,
      rgba(70, 140, 255, .16) 4px 6px
    ),
    /* строчная развёртка */
    repeating-linear-gradient(
      0deg,
      rgba(0, 0, 0, .46) 0 2px,
      rgba(255, 255, 255, .04) 2px 4px
    ),
    /* свечение люминофора вокруг номинала */
    radial-gradient(
      ellipse at 50% 44%,
      color-mix(in srgb, var(--suit) 26%, transparent),
      transparent 72%
    ),
    radial-gradient(ellipse at 50% 30%, #0e0818, #040209 78%);
}

/* виньетка и блик стекла */
html[data-skin="crt"] .card::after,
html[data-skin="crt"] .handCard::after,
html[data-skin="crt"] .flyingCard::after {
  box-shadow:
    inset 0 0 26px rgba(0, 0, 0, .8),
    inset 0 0 10px color-mix(in srgb, var(--suit) 40%, transparent);

  background:
    linear-gradient(
      152deg,
      rgba(255, 255, 255, .08) 0 22%,
      transparent 44%
    );
}

html[data-skin="crt"] .card .value,
html[data-skin="crt"] .handCard .value,
html[data-skin="crt"] .flyingCard .value {
  font-family: "Courier New", ui-monospace, monospace;

  color: var(--suit);

  /* люминофор растекается: ядро белое, вокруг цветной ореол */
  text-shadow:
    0 0 2px #fff,
    0 0 9px var(--suit),
    0 0 24px var(--suit),
    0 0 46px color-mix(in srgb, var(--suit) 60%, transparent);
}

html[data-skin="crt"] .value[data-v] {
  filter:
    drop-shadow(0 0 2px #fff)
    drop-shadow(0 0 12px var(--suit))
    drop-shadow(0 0 30px var(--suit));
}


/* =========================================================
   ЧЕТЫРЕ ЭФФЕКТА СТОЛА

   Ход длится доли секунды, и по одной карте в центре трудно
   понять, что случилось. Эффекты дают это понять боковым
   зрением: волна называет масть, помехи — что карта особая,
   тряска — что штраф крупный.
   ========================================================= */

/* ---------- ИМПУЛЬС ПО КОЛЬЦАМ ---------- */

.ringPulse {
  position: absolute;

  left: 50%;
  top: 50%;

  width: 26%;
  aspect-ratio: 1;

  transform: translate(-50%, -50%) scale(.2);

  border-radius: 50%;

  border: 2px solid var(--wave, var(--purple));

  opacity: 0;

  pointer-events: none;

  z-index: 1;
}

.ringPulse.go {
  animation: acidRingPulse .9s cubic-bezier(.2, .7, .3, 1) forwards;
}

@keyframes acidRingPulse {

  0% {
    opacity: .85;
    transform: translate(-50%, -50%) scale(.2);
    border-width: 3px;
  }

  100% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(5.2);
    border-width: 1px;
  }
}


/* ---------- ПОМЕХИ НА СПЕЦКАРТЕ ---------- */

/*
  Стол на долю секунды рвёт разверткой и уводит цвет — как
  плохой сигнал. Держать дольше нельзя: помехи, которые видно,
  раздражают, а не сообщают.
*/
.tableInner.glitch,
#discard .card.glitch {
  animation: acidGlitch .26s steps(2, end) 2;
}

@keyframes acidGlitch {

  0% {
    filter: none;
    transform: translate(0, 0);
  }

  22% {
    filter:
      hue-rotate(14deg)
      drop-shadow(3px 0 0 rgba(255, 43, 214, .55))
      drop-shadow(-3px 0 0 rgba(32, 234, 255, .55));

    transform: translate(-3px, 1px);

    clip-path:
      polygon(
        0 0, 100% 0, 100% 42%, 0 46%,
        0 52%, 100% 48%, 100% 100%, 0 100%
      );
  }

  55% {
    filter:
      hue-rotate(-10deg)
      drop-shadow(-2px 0 0 rgba(255, 43, 214, .45))
      drop-shadow(2px 0 0 rgba(32, 234, 255, .45));

    transform: translate(2px, -1px);

    clip-path: none;
  }

  100% {
    filter: none;
    transform: translate(0, 0);
  }
}


/* ---------- ТРЯСКА НА КРУПНОМ ШТРАФЕ ---------- */

.tableInner.jolt {
  animation: acidJolt .34s cubic-bezier(.36, .07, .19, .97);
}

@keyframes acidJolt {
  10%  { transform: translate(-5px, 2px)  rotate(-.35deg); }
  30%  { transform: translate(6px, -3px)  rotate(.4deg); }
  50%  { transform: translate(-4px, 3px)  rotate(-.25deg); }
  70%  { transform: translate(3px, -2px)  rotate(.15deg); }
  100% { transform: translate(0, 0)       rotate(0); }
}


/* ---------- СЛЕД ЛЕТЯЩЕЙ КАРТЫ ---------- */

.cardTrail {
  position: fixed;

  height: 3px;

  transform-origin: 0 50%;

  border-radius: 3px;

  z-index: 9000;

  pointer-events: none;

  background:
    linear-gradient(
      90deg,
      transparent,
      color-mix(in srgb, var(--trail, var(--purple)) 80%, transparent)
    );

  filter: blur(1.5px);

  animation: acidTrail .52s ease-out forwards;
}

@keyframes acidTrail {

  0% {
    opacity: .85;
    height: 5px;
  }

  100% {
    opacity: 0;
    height: 1px;
  }
}


@media (prefers-reduced-motion: reduce) {

  .ringPulse.go,
  .tableInner.glitch,
  .tableInner.jolt,
  .cardTrail {
    animation: none;
  }
}


/* =========================================================
   АРЕНА — КООРДИНАТНАЯ ПЛОСКОСТЬ

   Стол лежит не в пустоте, а на уходящей в туман сетке, как
   в заставках восьмидесятых. Слой лежит под всей игрой и
   ничего не перехватывает: горизонт, плоскость в перспективе,
   дымка и пятно света под столом.
   ========================================================= */

.arena {
  position: fixed;

  inset: 0;

  /*
    Ноль, а не минус один: арена лежит первым ребёнком #game
    и должна быть над его фоном, но под всем содержимым.
    Отрицательный слой уводил её под сам #game, а он занимает
    весь экран — арену просто не было видно.
  */
  z-index: 0;

  overflow: hidden;

  pointer-events: none;

  /*
    Своей заливки нет: под ней уже лежит атмосфера #game, и
    сплошной фон её бы стёр. Арена добавляет только горизонт,
    плоскость, дымку и пятно света.
  */
  background: none;
}

.arenaHorizon {
  position: absolute;

  left: 0;
  right: 0;
  top: 46%;

  height: 1px;

  background: var(--cyan);

  box-shadow:
    0 0 14px var(--cyan),
    0 0 44px rgba(32, 234, 255, .55);

  opacity: .8;
}

/*
  Плоскость шире экрана и наклонена перспективой: линии должны
  сходиться за краем, иначе видно, что сетка кончается.
*/
.arenaFloor {
  position: absolute;

  left: -40%;
  right: -40%;
  top: 46%;
  bottom: -6%;

  background:
    repeating-linear-gradient(
      90deg,
      rgba(139, 61, 255, .5) 0 1px,
      transparent 1px 72px
    ),
    repeating-linear-gradient(
      0deg,
      rgba(139, 61, 255, .42) 0 1px,
      transparent 1px 30px
    );

  transform: perspective(280px) rotateX(62deg);

  transform-origin: top center;

  opacity: .7;
}

.arenaFog {
  position: absolute;

  left: 0;
  right: 0;
  top: 32%;

  height: 28%;

  background:
    linear-gradient(
      180deg,
      transparent,
      rgba(139, 61, 255, .22),
      transparent
    );

  filter: blur(8px);
}

/* пятно света под столом */
.arenaDisc {
  position: absolute;

  left: 50%;
  top: 54%;

  width: min(70vw, 900px);
  aspect-ratio: 2.6;

  transform: translate(-50%, -50%);

  border-radius: 50%;

  background:
    radial-gradient(
      closest-side,
      rgba(183, 255, 36, .12),
      transparent 72%
    );

  filter: blur(6px);
}

/*
  Собственный фон стола становится почти прозрачным: под ним
  теперь сетка, и заливка её бы перекрыла.
*/
.tableInner {
  background: rgba(8, 4, 16, .42);
}

.tableGrid {
  opacity: 0;
}
/* =========================================================
   ЛИЦО СОПЕРНИКА — ЭКРАН С ОСЦИЛЛОГРАММОЙ

   Вместо портрета маленький монитор: у каждого своя форма
   волны, и соперников различаешь не читая имя. Эмодзи были
   плохи вдвойне — на каждой платформе рисуются по-своему.
   ========================================================= */

.opponentFace {
  position: relative;

  display: block;

  width: 2.5em;
  height: 1.35em;

  overflow: hidden;

  border-radius: 4px;

  border: 1px solid color-mix(in srgb, var(--wave, var(--acid)) 45%, transparent);

  background:
    radial-gradient(ellipse at 50% 40%, #0d1220, #05070f 78%);

  box-shadow:
    0 0 8px color-mix(in srgb, var(--wave, var(--acid)) 25%, transparent);
}

/* строчная развёртка поверх волны */
.opponentFace::after {
  content: "";

  position: absolute;

  inset: 0;

  background:
    repeating-linear-gradient(
      0deg,
      rgba(0, 0, 0, .45) 0 1px,
      transparent 1px 3px
    );

  pointer-events: none;
}

.opponentFace svg {
  display: block;

  width: 100%;
  height: 100%;
}

.opponentFace polyline {
  fill: none;

  stroke: var(--wave, var(--acid));

  stroke-width: 2;

  stroke-linejoin: round;

  filter:
    drop-shadow(0 0 3px var(--wave))
    drop-shadow(0 0 8px var(--wave));
}

.opponentFace[data-face="0"] { --wave: var(--cyan); }
.opponentFace[data-face="1"] { --wave: var(--acid); }
.opponentFace[data-face="2"] { --wave: var(--magenta); }
.opponentFace[data-face="3"] { --wave: var(--yellow); }
.opponentFace[data-face="4"] { --wave: var(--orange); }

/* на своём ходу экран разгорается */
.opponent.is-active .opponentFace {
  border-color: var(--wave);

  box-shadow:
    0 0 12px color-mix(in srgb, var(--wave) 55%, transparent);
}

/* Редкая реакция соперника на +4: оживает его готовый портрет,
   а не весь стол и не поток текстовых подсказок. */
.opponent.v91-reacting .opponentPlate {
  animation: v91PersonaReact .62s ease-out;
}

@keyframes v91PersonaReact {
  0% { transform: translateY(0) scale(1); }
  34% {
    transform: translateY(-5px) scale(1.06);
    box-shadow: 0 0 0 2px rgba(255, 61, 126, .72), 0 0 28px rgba(255, 61, 126, .66);
  }
  100% { transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .opponent.v91-reacting .opponentPlate { animation: none; }
}


/* =========================================================
   РИСОВАННЫЕ КАРТИНКИ

   Всё, что лежит в assets/, главнее нарисованного кодом.
   Файлов может не быть — тогда работает прежний вариант, и
   ни одно из этих правил не включается.
   ========================================================= */

/* ---------- фон арены ---------- */

.arena[data-art="1"] {
  background-size: cover;

  /*
    Сдвиг вверх, а не по центру: у всех четырёх фонов свет,
    трубы и вывески живут в верхней трети, а низ — пустой пол.
    При 62% в кадр попадал только он, и картинки будто не было.
  */
  background-position: center 42%;

  background-repeat: no-repeat;
}

/*
  Поверх рисованной арены сетка выглядит разметкой на
  фотографии, поэтому от неё остаётся только намёк.
*/
.arena[data-art="1"] .arenaFloor {
  opacity: .12;
}

.arena[data-art="1"] .arenaHorizon,
.arena[data-art="1"] .arenaFog {
  opacity: .18;
}

/* стол на рисованном полу должен читаться как стол */
.arena[data-art="1"] ~ #table .tableInner,
.arena[data-art="1"] + #table .tableInner {
  background: rgba(6, 3, 13, .5);
}


/* ---------- портрет соперника ---------- */

.opponentFace[data-art="1"] {
  width: 2.1em;
  height: 2.1em;

  border-radius: 50%;

  background-size: cover;
  background-position: center 22%;
}

/* волна прячется, но остаётся в разметке про запас */
.opponentFace[data-art="1"] svg {
  display: none;
}

.opponentFace[data-art="1"]::after {
  background: none;

  box-shadow:
    inset 0 0 12px rgba(0, 0, 0, .7);
}


/* ---------- рубашка ---------- */

html[data-back-art="1"] .deckBack {
  background-image: var(--card-back);

  background-size: cover;

  background-position: center;
}

html[data-back-art="1"] .deckAcid,
html[data-back-art="1"] .deckBack::after,
html[data-back-art="1"] .deckBack::before {
  display: none;
}

html[data-back-art="1"] .opponentBack {
  background-image: var(--card-back);

  background-size: cover;

  background-position: center;
}

html[data-back-art="1"] .opponentBack::after {
  display: none;
}

html[data-back-art="1"] #botCards .v9-bot-card {
  background-image: var(--card-back);

  background-size: cover;

  background-position: center;
}

html[data-back-art="1"] #botCards .v9-bot-card::after {
  display: none;
}
