/* ==========================================================================
   Игральные карты.

   Карты рисуются целиком на CSS: масти — юникодные символы, рубашка —
   градиенты и повторяющийся узор. Ни одной внешней картинки, поэтому скины
   меняются мгновенно подменой переменных.
   ========================================================================== */

.card {
  position: relative;
  flex: none;
  width: var(--card-w);
  height: var(--card-h);
  border-radius: min(var(--card-radius), 6px);
  /* Три слоя: узор скина поверх заливки лица карты */
  background-image: var(--card-pattern, none), linear-gradient(168deg, var(--card-face), var(--card-face-edge));
  background-size: var(--card-pattern-size, auto), auto;
  color: var(--card-ink);
  /* Без свечения вокруг карты: неоновые колоды владелец убрал (26.10.2026),
     и чужое --card-glow из старого оформления сюда больше не попадает */
  box-shadow: var(--shadow-card);
  font-family: var(--card-index-font, var(--font-body));
  /* У части шрифтов колод одно начертание (Prata, Forum): им скин ставит 400,
     иначе браузер дорисует жирный сам и буква расплывётся */
  font-weight: var(--card-index-weight, 800);
  overflow: hidden;
  user-select: none;
  /* Анимируем только transform: тень и фильтр меняются мгновенно — их
     анимация перерисовывает карту в каждом кадре и роняет fps на Android */
  transition: transform var(--dur) var(--ease-spring);
}

/* Колода-картинка: скин с --card-sheet рисует лицо карты целиком из спрайта
   13 × 4 (достоинство — столбец, масть — строка), а свои индексы, масти и
   рисунки прячет: на картинке они уже нарисованы. Рубашку это не трогает */
.card:not(.card--back) {
  background-image:
    var(--card-sheet, none),
    var(--card-pattern, none),
    linear-gradient(168deg, var(--card-face), var(--card-face-edge));
  background-size: 1300% 400%, var(--card-pattern-size, auto), auto;
  background-position:
    calc(var(--sheet-col, 0) * 100% / 12) calc(var(--sheet-row, 0) * 100% / 3),
    0 0,
    0 0;
}

.card:not(.card--back) > .card__frame,
.card:not(.card--back) > .card__index,
.card:not(.card--back) > .card__pip,
.card:not(.card--back) > .card__art {
  /* По умолчанию — inherit, а не visible: стол прячет карту на время полёта
     (visibility: hidden на самой карте), и явное visible у детей оставляло
     на сукне рамку, буквы и рисунок без карты — «следы» после «Бито» */
  visibility: var(--card-own-face, inherit);
}

/* Внутренняя рамка. Её толщина, цвет, отступ и скругление задаются скином —
   именно она сильнее всего отличает одну колоду от другой. */
.card__frame {
  position: absolute;
  inset: var(--card-frame-inset, 3px);
  border: var(--card-frame-width, 0) solid var(--card-frame-color, transparent);
  border-radius: var(--card-frame-radius, 4px);
  pointer-events: none;
}

/* Уголки-засечки в духе ар-деко: появляются только если скин задал цвет */
.card__frame::before,
.card__frame::after {
  content: "";
  position: absolute;
  width: var(--card-corner-size, 0);
  height: var(--card-corner-size, 0);
  border: 1px solid var(--card-corner-color, transparent);
}

.card__frame::before {
  top: -1px;
  left: -1px;
  border-right: 0;
  border-bottom: 0;
}

.card__frame::after {
  right: -1px;
  bottom: -1px;
  border-left: 0;
  border-top: 0;
}

/* Индекс в верхнем левом и (перевёрнутый) в нижнем правом углу:
   достоинство и под ним масть — как на настоящей карте */
.card__index {
  position: absolute;
  display: grid;
  justify-items: center;
  gap: 1px;
  line-height: 0.95;
  font-size: calc(var(--card-w) * 0.3);
  letter-spacing: -0.04em;
}

.card__index--tl {
  top: 4px;
  left: 4px;
}

.card__index--br {
  right: 4px;
  bottom: 4px;
  transform: rotate(180deg);
}

.card__mini {
  display: block;
  width: calc(var(--card-w) * 0.22);
  height: calc(var(--card-w) * 0.22);
}

/* Крупная масть по центру */
.card__pip {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  opacity: var(--card-pip-opacity, 0.9);
}

.card__pip .suit {
  width: calc(var(--card-w) * var(--card-pip-scale, 0.52));
  height: calc(var(--card-w) * var(--card-pip-scale, 0.52));
}

/* Рисунок картинки (валет, дама, король) — между угловыми буквами.
   Рисунок двуглавый, поэтому поля слева и справа одинаковые: под букву
   сверху слева и под перевёрнутую снизу справа. Поле с запасом: крупная
   масть рисунка не должна прилипать к букве */
.card__art {
  position: absolute;
  top: calc(var(--card-h) * var(--art-inset-y, 0.05));
  left: calc(var(--card-w) * var(--art-inset-x, 0.24));
  /* У svg свой размер по умолчанию (300×150): left+right его не растягивают */
  width: calc(var(--card-w) * (1 - 2 * var(--art-inset-x, 0.24)));
  height: calc(var(--card-h) * (1 - 2 * var(--art-inset-y, 0.05)));
  pointer-events: none;
}

/* На картинке крупная масть уже нарисована в углу рисунка — маленькая под
   буквой её только повторяла бы */
.card[data-court] .card__mini {
  display: none;
}

/* Буква картинки чуть мельче: рядом с ней крупная масть рисунка, и между
   ними должен оставаться зазор даже на маленьких картах */
.card[data-court] .card__index {
  font-size: calc(var(--card-w) * 0.26);
}

/* Какую из колод-рисунков показать, решает скин: --art-atlas / --art-english
   принимают inline или none. Без скина — атласная, как в русской колоде */
.card__art-deck--atlas {
  display: var(--art-atlas, inline);
}

.card__art-deck--english {
  display: var(--art-english, none);
}

/* Масть наследует цвет карты, поэтому скины из магазина работают как раньше */
.suit {
  display: block;
  width: 100%;
  height: 100%;
  fill: currentColor;
}

.card[data-color="red"] {
  color: var(--card-red);
}

/* Козырь ничем не выделяется — как в классическом «Дураке»: рамку-подсказку
   владелец попросил убрать (27.10.2026), козырь и так виден по масти */
.card--trump {
  box-shadow: var(--shadow-card);
}

.card--playable {
  cursor: pointer;
}

.card--playable:active {
  transform: translateY(-4px) scale(1.04);
}

/* Подсветка допустимых ходов — подсказка, а не разрешение:
   сервер всё равно перепроверяет каждый ход */
.card--legal {
  filter: none;
}

/* Карты, которыми сейчас не сходить, не затемняем: рука всегда читается
   одинаково, а неверный ход объяснит вибрация и «Не ваш ход» */
.card--illegal {
  filter: none;
  opacity: 1;
}

.card--selected {
  transform: translateY(-16px) scale(1.06);
  box-shadow: var(--shadow-card), 0 0 0 2px var(--accent);
  z-index: 2;
}

/* Карта в руке у пальца: приподнята и идёт за движением.

   ``pointer-events: none`` обязателен: иначе под пальцем всегда оказывается
   сама карта, и попадание в стол не определяется — перетаскивание выглядит
   сломанным. */
.card--dragging {
  transform: translate(var(--drag-x, 0), var(--drag-y, 0)) scale(1.06);
  box-shadow: var(--shadow-lg);
  z-index: 30;
  transition: none;
  pointer-events: none;
}

/* Жест принадлежит игре, а не прокрутке страницы */
.hand,
.hand__card {
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

/* Куда сейчас целится палец */
/* Цель под пальцем чуть приподнимается — без рамок и заливок */
.table-field__slot--aim {
  transform: translateY(-4px) scale(1.04);
  transition: transform var(--dur-fast) var(--ease-out);
}

/* Подсказка при касании карты: какую карту на столе она побьёт — красная
   обводка, как в классическом «Дураке» */
.table-field__slot--hint > .card:first-child {
  box-shadow:
    0 0 0 2px #ff5a6e,
    0 0 14px 2px rgba(255, 70, 95, 0.55),
    var(--shadow-sm);
  transition: box-shadow 120ms ease-out;
}

/* Рубашка */
.card--back {
  /* Узор на ровном фоне. Яркое пятно цвета акцента в середине убрано:
     на голубых и белых акцентах оно светилось неоном (26.10.2026) */
  background-image:
    var(--back-pattern),
    linear-gradient(160deg, var(--back-base), var(--back-base));
  background-size: var(--back-pattern-size, auto);
  background-position: center;
  border: 2px solid var(--back-edge, var(--card-face));
  color: transparent;
}

.card--back::before,
.card--back::after,
.card--back .card__pip {
  content: none;
  display: none;
}

.card--back .card__frame {
  inset: var(--back-frame-inset, 3px);
  border: var(--back-frame-width, 0) solid var(--back-frame-color, transparent);
  border-radius: var(--back-frame-radius, 3px);
}

/* --------------------------------------------------------------- рука игрока */

.hand {
  position: relative;
  z-index: var(--z-hand);
  display: flex;
  justify-content: center;
  align-items: flex-end;
  min-height: calc(var(--card-h) + 22px);
  padding: 0 var(--gap-3);
}

/* Рука веером-дугой: наклон и опускание карты задаёт JS по её месту в руке */
.hand__card {
  margin-left: var(--overlap, -18px);
  transform-origin: 50% 100%;
  transform: translateY(var(--shift-y, 0)) rotate(var(--shift-turn, 0deg));
  transition: transform var(--dur-fast) var(--ease-out);
}

.hand__card.card--selected {
  transform: translateY(calc(var(--shift-y, 0) - 26px)) rotate(var(--shift-turn, 0deg)) scale(1.05);
  z-index: 2;
}

/* Карта у пальца идёт за ним без веерного наклона и сразу приподнята на
   14px — видно, что её взяли */
.hand__card.card--dragging {
  transform: translate(var(--drag-x, 0), calc(var(--drag-y, 0px) - 14px)) scale(1.06);
}

/* Подсказок «этой картой можно ходить» нет (просьба владельца 27.10.2026):
   все карты руки стоят ровно, неверный ход объяснит вибрация и сообщение */

/* Движущимся картам — свой слой, но только на время движения */
.is-moving,
.card--dragging {
  will-change: transform;
}

/* В ленте с прокруткой веера нет: карты стоят ровно */
.hand--scroll .hand__card {
  transform: none;
}

.hand__card:first-child {
  margin-left: 0;
}

/* Карт так много, что от каждой осталась бы полоска: рука становится лентой,
   которую листают пальцем вбок. Карту по-прежнему тянут вверх, на стол */
.hand--scroll {
  justify-content: flex-start;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  /* Место сверху под приподнятую выбранную карту: иначе её срежет край ленты */
  padding-top: 22px;
  margin-top: -22px;
}

.hand--scroll::-webkit-scrollbar {
  display: none;
}

.hand--scroll,
.hand--scroll .card {
  touch-action: pan-x;
}

/* ------------------------------------------------------------------ стол */

.table-field {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-content: center;
  /* Не больше трёх пар в ряду: дальше карты уходят на вторую строку, иначе
     на телефоне они сжимаются в нечитаемую ленту */
  flex-wrap: wrap;
  width: 100%;
  /* Пары стоят свободно: отбивающая карта сдвинута и не закрывает
     атакующую, а соседние пары не налезают друг на друга */
  max-width: calc((var(--card-w) + 20px) * 3 + var(--gap-5) * 2 + var(--gap-3) * 2);
  margin: 0 auto;
  column-gap: var(--gap-5);
  row-gap: var(--gap-4);
  min-height: calc(var(--card-h) + var(--gap-5));
  padding: var(--gap-3);
  border-radius: var(--radius-lg);
  transition: background var(--dur), border-color var(--dur);
}


.table-field__slot {
  position: relative;
  width: calc(var(--card-w) + 20px);
  height: calc(var(--card-h) + var(--defend-shift, 26px));
}

.table-field__slot .card {
  position: absolute;
  top: 0;
  left: 0;
}

/* Отбивающая карта ложится поверх со сдвигом */
.table-field__slot .card:nth-child(2) {
  top: var(--defend-shift, 26px);
  left: 20px;
}

/* Карту, которую можно отбить, ничем не обводим: подсказка — подсветка
   подходящих карт в руке. Выбранной картой бьют по чуть приподнятой */
.table-field__slot--pick {
  transform: translateY(-4px);
  transition: transform var(--dur-fast) var(--ease-out);
}

/* ------------------------------------------------------------------ полёты */

/* Слой для призраков карт: они летят поверх стола и руки, но под шторками
   и тостами. Сам слой клики не ловит */
.flight-layer {
  position: fixed;
  inset: 0;
  z-index: var(--z-flight);
  pointer-events: none;
  overflow: hidden;
}

.flight {
  position: absolute;
  top: 0;
  left: 0;
  will-change: transform;
}

.flight .card {
  box-shadow: var(--shadow-lg);
}

/* Пока картой двигает GSAP, CSS-переход не должен догонять каждый кадр */
.is-moving {
  transition: none !important;
}

/* ------------------------------------------------------------------ колода */

/* Колода и отбой лежат у самых краёв и видны наполовину: середина стола
   принадлежит картам, а не служебным стопкам */
.deck {
  position: relative;
  width: calc(var(--card-w) + 26px);
  height: var(--card-h);
  margin-left: calc(var(--card-w) / -2 - var(--gap-3));
}

/* Козырная карта лежит под колодой поперёк — её видно наполовину,
   как и за настоящим столом */
.deck__trump {
  position: absolute;
  top: 50%;
  left: 20px;
  transform: translateY(-50%) rotate(90deg);
  transform-origin: center;
  box-shadow: var(--shadow-sm);
}

.deck__pile {
  position: absolute;
  top: 0;
  left: 0;
}

.deck__count {
  position: absolute;
  right: -6px;
  bottom: -6px;
  min-width: 22px;
  padding: 1px 5px;
  border-radius: var(--radius-pill);
  background: var(--bg-sunken);
  border: 1px solid var(--border);
  font-size: var(--step--2);
  font-weight: 800;
  text-align: center;
}

.discard {
  position: relative;
  width: var(--card-w);
  height: var(--card-h);
  /* Бито почти целиком за правым краем: видна узкая полоска рубашек, как в
     классическом «Дураке» — карты на сукне не перекрываются */
  margin-right: calc(var(--card-w) * -0.82 - var(--gap-3));
  border-radius: min(var(--card-radius), 6px);
  display: grid;
  place-items: center;
  font-size: var(--step--2);
  font-weight: 800;
  color: var(--text-dim);
  transition: transform var(--dur) var(--ease-spring);
}

/* Бито лежит россыпью вдоль правого края, как брошенные на сукно карты:
   каждая со своим наклоном и местом. Сдвиги — доли размера карты, поэтому
   россыпь одинакова на любом экране. Сколько карт ушло, не пишем — за
   настоящим столом бито тоже не пересчитывают */
.discard__card {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--card-w);
  height: var(--card-h);
  transform: translate(
      calc(var(--card-w) * var(--shift-x, 0)),
      calc(var(--card-h) * var(--shift-y, 0))
    )
    rotate(var(--shift-turn, 0));
}

/* Пока в отбой ничего не ушло — место пустое, без контуров */
.discard--empty {
  visibility: hidden;
}

/* Масть козыря, когда колода кончилась: она остаётся на виду по правилам */
.deck__suit {
  display: grid;
  place-items: center;
  width: var(--card-w);
  height: var(--card-h);
  border-radius: min(var(--card-radius), 6px);
  border: 1px dashed var(--border);
  font-size: var(--step-2);
  color: var(--brass-400);
}
