/* ============================================================================
   cardgen.ru — КАРТЫ НА СУКНЕ
   ----------------------------------------------------------------------------
   Задача. Карта лежит на столе рубашкой вверх. Зритель смотрит на неё под
   очень острым углом — 16° к плоскости стола. Игрок берёт правый нижний
   уголок и тянет ВВЕРХ-К СЕБЕ: бумага подгибается, и на изнанке подгиба
   видны ранг и масть. Вокруг карты — сукно.

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

   Как устроено:

     .cg3d                 плоскость карты, наклонена к зрителю на 74°
       .cg3d__back         рубашка (графит с золотой гильошью)
       .cg3d__face-full    лицо целиком — для режима «открыто»
       .cg3d__fold-shadow  тень, которую подгиб бросает на карту
       .cg3d__peel         подгиб: треугольник в правом нижнем углу
         .cg3d__rank       ранг и масть на изнанке подгиба
       .cg3d__gloss        блик лампы
       .cg3d__grab         зона жеста

   Состояние подгиба — переменная --peel (0…1) на .cg3d.
   ========================================================================== */

/* ============================================================================
   1. СУКНО
   ========================================================================== */

.felt-surface {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background:
    radial-gradient(58% 44% at 46% 12%, rgba(74, 178, 138, .16) 0%, transparent 62%),
    radial-gradient(92% 82% at 50% 38%, #0C4736 0%, #083326 40%, #04211A 72%, #02130F 100%);
  box-shadow:
    inset 0 0 70px rgba(0, 0, 0, .55),
    inset 0 2px 14px rgba(0, 0, 0, .45);
}

/* волокно сукна */
.felt-surface::before {
  content: "";
  position: absolute;
  inset: 0;
  opacity: .8;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(37deg, rgba(255, 255, 255, .018) 0 1px, transparent 1px 2px),
    repeating-linear-gradient(-37deg, rgba(0, 0, 0, .045) 0 1px, transparent 1px 2px),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, .012) 0 1px, transparent 1px 4px);
}

/* неровность окраски */
.felt-surface::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .5;
  background-image:
    radial-gradient(ellipse 22% 18% at 18% 24%, rgba(255, 255, 255, .035), transparent 70%),
    radial-gradient(ellipse 30% 22% at 78% 68%, rgba(0, 0, 0, .12), transparent 72%),
    radial-gradient(ellipse 16% 14% at 62% 18%, rgba(255, 255, 255, .025), transparent 70%),
    radial-gradient(ellipse 26% 20% at 34% 82%, rgba(0, 0, 0, .1), transparent 72%);
}

/* ============================================================================
   2. СЦЕНА
   ========================================================================== */

.felt-scene {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  transform-style: preserve-3d;
}

/* ============================================================================
   3. КАРТА
   ========================================================================== */

.cg3d {
  --w: 120px;
  --tilt: 74deg;      /* 90° − 16°: карта почти плашмя */
  --peel: 0;          /* 0 — закрыта, 1 — уголок поднят */

  position: relative;
  width: var(--w);
  aspect-ratio: 5 / 7;
  flex: none;
  transform-style: preserve-3d;
  transform: rotateX(var(--tilt)) rotateZ(var(--spin, 0deg));
  transform-origin: 50% 50%;
  transition: transform 420ms var(--ease-out);
  will-change: transform;
}

/* ── тень: карта лежит на сукне ─────────────────────────────────────────── */

.cg3d::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 6px;
  box-shadow:
    0 2px 4px rgba(0, 0, 0, .5),
    0 10px 24px rgba(0, 0, 0, .45),
    0 22px 50px rgba(0, 0, 0, .3);
  transform: translateZ(-1px);
  pointer-events: none;
}

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

.cg3d__back {
  position: absolute;
  inset: 0;
  border-radius: 6px;
  overflow: hidden;
  backface-visibility: hidden;
  transform: translateZ(.4px);

  background:
    radial-gradient(78% 62% at 42% 26%, #243447 0%, #16212E 44%, #0B131C 100%);
  box-shadow:
    inset 0 0 0 .5px rgba(0, 0, 0, .6),
    inset 0 0 0 1.4px rgba(205, 169, 98, .30),
    inset 0 1px 0 rgba(255, 255, 255, .12);
}

/* гильош */
.cg3d__back::before {
  content: "";
  position: absolute;
  inset: 6px;
  border: .5px solid rgba(205, 169, 98, .34);
  border-radius: 3px;
  background-image:
    repeating-linear-gradient(45deg, rgba(205, 169, 98, .15) 0 .5px, transparent .5px 5px),
    repeating-linear-gradient(-45deg, rgba(205, 169, 98, .15) 0 .5px, transparent .5px 5px);
}

/* медальон */
.cg3d__back::after {
  content: "CG";
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: 30%;
  aspect-ratio: 1;
  border: .5px solid rgba(205, 169, 98, .55);
  border-radius: 50%;
  font-family: var(--font-sans);
  font-size: calc(var(--w) * .085);
  font-weight: 700;
  letter-spacing: .04em;
  color: rgba(226, 197, 137, .9);
  background: radial-gradient(circle, rgba(11, 19, 28, .92), rgba(11, 19, 28, .6));
}

/* ── блик ───────────────────────────────────────────────────────────────── */

.cg3d__gloss {
  position: absolute;
  inset: 0;
  border-radius: 6px;
  pointer-events: none;
  transform: translateZ(.5px);
  background:
    linear-gradient(168deg,
      rgba(255, 255, 255, .14) 0%,
      rgba(255, 255, 255, .03) 12%,
      transparent 26%,
      transparent 74%,
      rgba(0, 0, 0, .12) 100%);
  mix-blend-mode: overlay;
}

/* ============================================================================
   4. ПОДГИБ УГОЛКА
   ----------------------------------------------------------------------------
   Уголок — квадрат в правом нижнем углу карты. Его размер растёт вместе с
   протяжкой: --size = --peel × 46% ширины карты.

   Форму треугольника задаёт clip-path на самом уголке. Ранг лежит ВНУТРИ
   уголка, поэтому обрезается той же диагональю — и всегда оказывается на
   бумаге, никогда на рубашке.

   Почему не 3D-поворот вокруг диагонали: под perspective элемент уходил из
   плоскости карты, «отрывался» от неё и по-разному вёл себя в браузерах.
   Плоская техника предсказуема и читается как настоящая бумага за счёт
   тени складки, световой кромки и зерна.
   ========================================================================== */

.cg3d__peel {
  --corner: 46%;

  position: absolute;
  right: 0;
  bottom: 0;
  /* размер уголка = доля карты × величина подгиба */
  width: calc(var(--peel) * var(--corner));
  height: calc(var(--peel) * var(--corner));

  /* В preserve-3d порядок слоёв задаётся осью Z, а НЕ z-index: рубашка
     с translateZ(.4px) перекрывала подгиб. Поднимаем подгиб над рубашкой. */
  transform: translateZ(1px);

  /* треугольник: правый нижний угол */
  clip-path: polygon(100% 0, 100% 100%, 0 100%);

  /* изнанка карты — бумага */
  background:
    radial-gradient(130% 130% at 30% 20%, #FFFEFB 0%, #F9F5ED 42%, #F0EADD 74%, #E4DDCD 100%);
  color: var(--suit-black);
  box-shadow: inset 0 0 0 .5px rgba(0, 0, 0, .14);

  /* появляется сразу, как только начали тянуть */
  opacity: clamp(0, calc(var(--peel) * 8), 1);
  transition: width 60ms linear, height 60ms linear;
  pointer-events: none;
}

/* дуга изгиба: тень у складки, свет на поднятом крае */
.cg3d__peel::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(135deg,
      rgba(40, 28, 14, .52) 0%,
      rgba(40, 28, 14, .2) 10%,
      transparent 28%,
      rgba(255, 255, 255, .26) 70%,
      rgba(255, 255, 255, .1) 100%);
  mix-blend-mode: multiply;
  pointer-events: none;
}

/* бумажное зерно */
.cg3d__peel::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: .38;
  mix-blend-mode: multiply;
  background-image:
    repeating-linear-gradient(93deg, rgba(120, 105, 80, .05) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(5deg, rgba(120, 105, 80, .04) 0 1px, transparent 1px 4px);
  pointer-events: none;
}

/* ── ранг и масть на изнанке ────────────────────────────────────────────── */

.cg3d__rank {
  position: absolute;
  right: 9%;
  bottom: 7%;
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: .8;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -.04em;
  color: var(--suit-black);
  text-shadow:
    0 1px 0 rgba(255, 255, 255, .8),
    0 -1px 1px rgba(0, 0, 0, .1);
  /* размер — от ширины карты и величины подгиба: номинал растёт вместе
     с уголком и всегда остаётся внутри бумаги */
  font-size: calc(var(--w) * var(--peel) * .17);
}

.cg3d__peel.is-red .cg3d__rank { color: var(--suit-red); }

.cg3d__rank b { font-size: 1em; font-weight: 700; line-height: .82; }

.cg3d__rank i { font-size: .72em; line-height: .82; margin-top: .06em; }

/* ── тень, которую подгиб бросает на карту ──────────────────────────────── */

.cg3d__fold-shadow {
  position: absolute;
  right: 0;
  bottom: 0;
  width: calc(var(--peel) * 58%);
  height: calc(var(--peel) * 58%);
  transform: translateZ(.6px);
  pointer-events: none;
  opacity: clamp(0, calc(var(--peel) * 1.1), 1);
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
  background: linear-gradient(135deg,
    rgba(0, 0, 0, .55) 0%,
    rgba(0, 0, 0, .2) 26%,
    transparent 58%);
  filter: blur(1.5px);
  transition: width 60ms linear, height 60ms linear;
}

/* ============================================================================
   5. ЗОНА ЖЕСТА
   ========================================================================== */

.cg3d__grab {
  position: absolute;
  right: -4%;
  bottom: -4%;
  width: 62%;
  height: 62%;
  z-index: 7;
  cursor: grab;
  touch-action: none;
  transform: translateZ(1.2px);
}

.cg3d__grab:active { cursor: grabbing; }

/* стрелка «тяни вверх» */
.cg3d__grab::after {
  content: "";
  position: absolute;
  right: 18%;
  bottom: 16%;
  width: 20%;
  aspect-ratio: 1;
  border-top: 1.5px solid rgba(226, 197, 137, .55);
  border-right: 1.5px solid rgba(226, 197, 137, .55);
  transform: rotate(-45deg);
  opacity: calc(.85 - var(--peel) * 2.4);
  animation: grab-hint 2600ms var(--ease-in-out) infinite;
}

@keyframes grab-hint {
  0%, 100% { transform: rotate(-45deg) translate(0, 0); opacity: .7; }
  50% { transform: rotate(-45deg) translate(-2px, -2px); opacity: .25; }
}

/* ============================================================================
   6. РЕЖИМ «ОТКРЫТО»
   ========================================================================== */

.cg3d__face-full {
  position: absolute;
  inset: 0;
  border-radius: 6px;
  overflow: hidden;
  opacity: 0;
  transform: translateZ(.2px);
  transition: opacity 260ms var(--ease-out);
  background:
    radial-gradient(120% 100% at 30% 20%, #FFFEFB 0%, #F9F5ED 42%, #F0EADD 74%, #E4DDCD 100%);
  color: var(--suit-black);
  box-shadow:
    inset 0 0 0 .5px rgba(0, 0, 0, .2),
    inset 0 0 20px rgba(150, 130, 100, .12);
}

.cg3d__face-full.is-red { color: var(--suit-red); }

/* лицом вверх: рубашка и подгиб скрыты */
.cg3d--faceup .cg3d__back,
.cg3d--faceup .cg3d__peel,
.cg3d--faceup .cg3d__fold-shadow { display: none; }

.cg3d--faceup .cg3d__face-full { opacity: 1; }

/* лицо в режиме «открыто» на устройстве */
.felt-scene[data-mode="open"] .cg3d__back,
.felt-scene[data-mode="open"] .cg3d__peel,
.felt-scene[data-mode="open"] .cg3d__fold-shadow { display: none; }

.felt-scene[data-mode="open"] .cg3d__face-full { opacity: 1; }

.felt-scene[data-mode="open"] .cg3d__grab { display: none; }

/* ── номинал на лице: читаемость при малом размере ──────────────────────── */

.cg3d__face-full .cgcard__corner--tl { top: 4%; left: 5%; }
.cg3d__face-full .cgcard__corner--br { bottom: 4%; right: 5%; }

.cg3d__face-full .cgcard__corner b { font-size: calc(var(--w) * .18); line-height: .9; }
.cg3d__face-full .cgcard__corner i { font-size: calc(var(--w) * .135); }
.cg3d__face-full .cgcard__pip { font-size: calc(var(--w) * .13); }
.cg3d__face-full .cgcard__ace-suit { font-size: calc(var(--w) * .42); }
.cg3d__face-full .cgcard__court-letter { font-size: calc(var(--w) * .26); }

/* ============================================================================
   7. ПУСТОЙ СЛОТ
   ========================================================================== */

.cg3d--empty .cg3d__back,
.cg3d--empty .cg3d__peel,
.cg3d--empty .cg3d__fold-shadow,
.cg3d--empty .cg3d__gloss { display: none; }

.cg3d--empty::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 6px;
  background: rgba(2, 20, 15, .32);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, .45);
}

/* ============================================================================
   8. АНИМАЦИЯ РАЗДАЧИ
   ========================================================================== */

@keyframes cg3d-deal {
  0% {
    opacity: 0;
    transform: rotateX(var(--tilt)) translateY(-40px) translateZ(60px) rotateZ(var(--spin, 0deg)) scale(.86);
  }
  60% { opacity: 1; }
  100% {
    opacity: 1;
    transform: rotateX(var(--tilt)) rotateZ(var(--spin, 0deg)) scale(1);
  }
}

.cg3d--deal {
  animation: cg3d-deal 620ms var(--ease-out) backwards;
  animation-delay: var(--deal-delay, 0ms);
}

/* ============================================================================
   9. ДОСТУПНОСТЬ
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .cg3d { animation: none !important; transition: none !important; }
  .cg3d__grab::after { animation: none; }
}
