/* =============================================================================
   cards.css — rendu des cartes : 100 % CSS/SVG, aucune image bitmap.

   Le vocabulaire visuel est celui d'une carte réellement imprimée (§6.0) :
   encres pleines en aplat, léger grain de papier, tranches nettes. Chaque
   dimension est dérivée de --card-w : la même carte est juste dans l'éventail,
   sur la pile, ou en grand dans la maquette.
   ============================================================================= */

/* -------------------------------------------------------------------- carte */

.card {
  position: relative;
  display: block;
  inline-size: var(--card-w);
  aspect-ratio: var(--card-ratio);
  border-radius: var(--radius-card);
  background: var(--paper);
  /* La tranche : un liseré plus sombre en bas et à droite donne l'épaisseur. */
  box-shadow:
    inset calc(var(--card-edge) * -0.5) calc(var(--card-edge) * -1) 0 var(--paper-edge),
    var(--shadow-raised);
  padding: calc(var(--card-w) * 0.055);
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  border: 0;
  color: var(--ink-glyph);
  font-family: var(--font-card);
}

.card__face {
  position: relative;
  block-size: 100%;
  inline-size: 100%;
  border-radius: calc(var(--radius-card) * 0.66);
  background: var(--ink);
  overflow: hidden;
  display: grid;
  place-items: center;
  isolation: isolate;
}

/* Grain de papier — un seul filtre SVG en data-URI, statique, 4 % d'opacité.
   Pas de fichier image, pas d'animation : coût nul après la première peinture. */
.card__face::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: 0.09;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90' height='90'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='90' height='90' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}

/* Cartouches haut-gauche / bas-droite : le système de formes du §6.3 —
   l'accessibilité n'est pas un ajout, c'est l'identité graphique.

   Écart assumé au §6.3, qui prescrivait « à l'encre profonde sur l'aplat » : cette
   combinaison plafonne à 2.0:1 sur le rouge et 2.1:1 sur le bleu, sous le seuil de
   3:1 des éléments graphiques porteurs d'information — donc invisible pour le
   lecteur même que la forme est censée servir. La forme est posée sur un petit
   plat de papier, comme l'index d'une carte réellement imprimée : 7:1 partout. */
.card__corner {
  position: absolute;
  z-index: 2;
  display: grid;
  place-items: center;
  min-inline-size: calc(var(--card-w) * 0.24);
  aspect-ratio: 1;
  padding: calc(var(--card-w) * 0.015);
  border-radius: calc(var(--card-w) * 0.07);
  background: var(--paper);
  font-size: calc(var(--card-w) * var(--card-corner-ratio));
  line-height: 1;
  color: var(--ink-glyph);
}

.card__corner--tl { inset-block-start: 4%; inset-inline-start: 5%; }
.card__corner--br { inset-block-end: 4%; inset-inline-end: 5%; transform: rotate(180deg); }

/* L'ovale crème, incliné : c'est lui qui porte le chiffre, et c'est ce qui rend
   le contraste ≥ 7:1 possible (encre glyphe sur papier, jamais sur l'aplat). */
.card__oval {
  position: relative;
  z-index: 2;
  display: grid;
  place-items: center;
  inline-size: 118%;
  aspect-ratio: 1.6;
  border-radius: 50%;
  background: var(--paper);
  transform: rotate(-22deg);
  box-shadow: 0 0 0 calc(var(--card-w) * 0.012) rgb(0 0 0 / 0.12);
}

.card__glyph {
  transform: rotate(22deg);
  font-size: calc(var(--card-w) * var(--card-glyph-ratio));
  font-variation-settings: 'wdth' 110, 'wght' 800;
  font-weight: 800;
  line-height: 1;
  color: var(--ink-glyph);
  letter-spacing: -0.02em;
}

/* Les symboles d'action sont plus étroits que les chiffres : on les rattrape. */
.card[data-kind='reverse'] .card__glyph,
.card[data-kind='skip'] .card__glyph { font-size: calc(var(--card-w) * 0.42); }
.card[data-kind='draw1'] .card__glyph,
.card[data-kind='wildDraw2'] .card__glyph { font-size: calc(var(--card-w) * 0.36); }

/* ------------------------------------------------------------------ jokers */

/* Un joker n'a pas d'encre : il les a toutes. Quatre quadrants, quatre formes. */
.card--wild .card__face {
  background: var(--paper-back);
}

.card__quads {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: grid;
  grid-template: 1fr 1fr / 1fr 1fr;
}

/* Même règle que les cartouches : la forme est sur du papier, jamais sur l'aplat. */
.card__quad {
  display: grid;
  place-items: center;
  font-size: calc(var(--card-w) * 0.17);
  line-height: 1;
}

.card__quad > span {
  display: grid;
  place-items: center;
  inline-size: 1.5em;
  aspect-ratio: 1;
  border-radius: calc(var(--card-w) * 0.05);
  background: var(--paper);
}

.card__quad--red    { background: var(--ink-red); }
.card__quad--yellow { background: var(--ink-yellow); }
.card__quad--green  { background: var(--ink-green); }
.card__quad--blue   { background: var(--ink-blue); }
.card__quad--red    > span { color: var(--ink-red-glyph); }
.card__quad--yellow > span { color: var(--ink-yellow-glyph); }
.card__quad--green  > span { color: var(--ink-green-glyph); }
.card__quad--blue   > span { color: var(--ink-blue-glyph); }

/* Le joker n'a pas d'ovale crème central : ses quatre quadrants suffisent à le
   rendre lisible, et un rond blanc par-dessus n'ajoutait qu'un artefact visuel.
   Le glyphe (★ / +2) flotte directement sur les quadrants ; un contour épais
   dans l'encre du support garantit sa lisibilité quelle que soit la couleur
   derrière chaque partie du tracé (§6.3 : l'information ne doit pas dépendre
   d'un seul aplat de couleur). */
.card--wild .card__oval { background: transparent; box-shadow: none; }
.card--wild .card__glyph {
  color: var(--paper);
  -webkit-text-stroke: calc(var(--card-w) * 0.02) var(--ink);
  paint-order: stroke fill;
}

/* Un joker posé porte la couleur choisie : la pile reste lisible comme un
   historique (§6.4), sans que la carte cesse d'être un joker. */
.card--wild[data-chosen] .card__oval { box-shadow: 0 0 0 calc(var(--card-w) * 0.035) var(--ink); }

/* --------------------------------------------------------------- dos de carte */

.card--back .card__face {
  background: var(--paper-back);
}

.card__rosace {
  position: relative;
  z-index: 2;
  inline-size: 62%;
  aspect-ratio: 1;
  display: grid;
  grid-template: 1fr 1fr / 1fr 1fr;
  place-items: center;
  font-size: calc(var(--card-w) * 0.19);
  line-height: 1;
  transform: rotate(-12deg);
}

.card__rosace > :nth-child(1) { color: var(--ink-red); }
.card__rosace > :nth-child(2) { color: var(--ink-yellow); }
.card__rosace > :nth-child(3) { color: var(--ink-green); }
.card__rosace > :nth-child(4) { color: var(--ink-blue); }

/* ------------------------------------------------------- états de jouabilité */

/* On voit ses options avant même de lire les chiffres (§6.5). */
.card--playable {
  transform: translate3d(0, calc(var(--card-lift) * -1), 0);
  box-shadow:
    inset calc(var(--card-edge) * -0.5) calc(var(--card-edge) * -1) 0 var(--paper-edge),
    var(--shadow-thrown);
  cursor: pointer;
}

.card--muted {
  opacity: var(--card-muted-opacity);
  filter: saturate(var(--card-muted-saturation));
  box-shadow: inset calc(var(--card-edge) * -0.5) calc(var(--card-edge) * -1) 0 var(--paper-edge);
  cursor: default;
}

/* Premier tap : la carte se lève et s'élargit, les autres s'écartent. Le coup
   n'est jamais joué au premier contact (§6.5). */
.card--selected {
  z-index: 30;
  transform: translate3d(0, calc(var(--card-lift) * -3.4), 0) scale(1.16);
  box-shadow:
    inset calc(var(--card-edge) * -0.5) calc(var(--card-edge) * -1) 0 var(--paper-edge),
    var(--shadow-thrown);
}

.card:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
}

/* -------------------------------------------------------------------- piles */

/* La défausse est à la fois le plateau et l'historique : les six dernières
   cartes restent visibles, à des angles déterministes dérivés de leur id. */
.pile {
  position: relative;
  inline-size: var(--card-w);
  aspect-ratio: var(--card-ratio);
}

.pile .card {
  position: absolute;
  inset: 0;
  transform: rotate(calc(var(--tilt, 0) * 1deg));
}

.pile .card:not(:last-child) { pointer-events: none; }

.draw-pile {
  position: relative;
  inline-size: var(--card-w);
  aspect-ratio: var(--card-ratio);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

/* Deux cartes fantômes derrière le dos : la pioche a une épaisseur. */
.draw-pile::before,
.draw-pile::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: var(--radius-card);
  background: var(--paper-back);
  box-shadow: 0 1px 0 var(--table-line);
}
.draw-pile::before { transform: translate3d(3px, 3px, 0) rotate(2deg); }
.draw-pile::after  { transform: translate3d(6px, 6px, 0) rotate(-1.5deg); }

.draw-pile .card { position: relative; z-index: 2; }
.draw-pile:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

/* ---------------------------------------------------------------- mouvement */

/* Uniquement transform et opacity — jamais top, width ou box-shadow animés. */
.card,
.pile .card {
  transition:
    transform var(--d-turn) var(--e-ui),
    opacity var(--d-fade) linear,
    filter var(--d-fade) linear;
  will-change: auto;
}

.hand .card { transition-duration: var(--d-draw); }

@keyframes card-throw {
  from {
    transform: translate3d(var(--throw-x, 0), var(--throw-y, 50vh), 0) rotate(0deg) scale(1.05);
  }
  to {
    transform: translate3d(0, 0, 0) rotate(calc(var(--tilt, 0) * 1deg)) scale(1);
  }
}

.card--thrown {
  animation: card-throw var(--d-throw) var(--e-throw) both;
  will-change: transform;
}

@keyframes card-deal {
  from { transform: translate3d(var(--deal-x, 0), var(--deal-y, -40vh), 0) scale(0.8); opacity: 0; }
  to   { transform: translate3d(0, 0, 0) scale(1); opacity: 1; }
}

.card--dealt {
  animation: card-deal var(--d-throw) var(--e-throw) both;
  animation-delay: calc(var(--deal-i, 0) * var(--d-deal));
}

@media (prefers-reduced-motion: reduce) {
  .card,
  .pile .card,
  .hand .card {
    transition-duration: var(--d-fade);
    transition-property: opacity, filter;
  }

  .card--playable,
  .card--selected {
    transform: none;
  }

  /* Une carte jouable doit rester distinguable sans translation. */
  .card--playable { outline: 2px solid var(--text-hi); outline-offset: 1px; }
  .card--selected { outline: 3px solid var(--text-hi); outline-offset: 2px; }

  .card--thrown,
  .card--dealt {
    animation-name: fade-in;
    animation-duration: var(--d-fade);
  }
}

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