/* ============================================================
   BLACKJACK — styles specifiques.
   A charger APRES styles.css, dont cette page reutilise toute la
   charpente : barre laterale, menus de choix graphiques, cartes
   (.card, --card-w, --card-bg-size, --card-border), fenetres
   modales, barres de defilement, bascule de langue.
   ============================================================ */

/* Le solitaire calait la largeur du plateau sur son contenu ; ici les
   rangees doivent occuper toute la largeur pour rester centrees. */
/* ---------- FORME DE LA TABLE ----------
   Cote croupier droit, cote joueur arrondi : la silhouette classique d'une
   table de blackjack vue du dessus. Le cadre en bois suit la meme courbe. */
#board {
  /* Une table de blackjack est une demi-lune : bord droit du cote du croupier,
     grand arc du cote des joueurs. Son rapport est donc fixe, et elle se
     contente de la place que lui laisse la plus courte des deux dimensions,
     au lieu de s'etirer avec la fenetre. Le rapport 3/2 est celui qui loge
     le croupier, les inscriptions et les joueurs sans que rien n'empiete :
     plus plate, la table etrangle les inscriptions ; plus ronde, elle
     retrecit. L'arc du bas, a 66 % de la hauteur, donne la silhouette. */
  width: auto;
  height: min(90vh, 56vw);
  aspect-ratio: 7 / 5;
  min-height: 0;
  max-width: 100%;
  border-radius: 16px 16px 50% 50% / 16px 16px 66% 66%;
}

/* Fenetre courte : la hauteur de la table est plafonnee par l'ecran, et le
   rapport devient le seul levier. Les totaux et les plaques de nom gardant
   leur taille en pixels, ils mangent d'autant plus la bande que la table est
   petite. On resserre donc la table, qui se fait plus ronde, plutot que de
   laisser les inscriptions se reduire a rien. */
@media (max-height: 820px) {
  #board { aspect-ratio: 13 / 10; }
}

/* Le pourtour du plateau est resserre : chaque pixel rendu ici elargit la
   table, dont la hauteur commande la largeur par le rapport. La marge de la
   banquette est reglee avec le reste de #controls, plus bas. */
#game-area { padding: 12px; }

/* Le tapis devient une colonne et #board-inner en occupe toute la hauteur.
   Sans cela, la hauteur du bloc dependait de son contenu et le croupier
   flottait plus ou moins bas selon la taille de la fenetre. */
#board-felt {
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-radius: 10px 10px 50% 50% / 10px 10px 66% 66%;
  /* Une carte qui s'envole du sabot etend brievement la zone de defilement,
     ce qui faisait apparaitre une barre horizontale sous le tapis. Rien ici
     n'a vocation a defiler : la mise en page tient dans le cadre. */
  overflow: hidden;
}

#board-inner {
  /* Flexible dans le feutre, il ne descendrait pas sous son contenu sans
     cela, et le debordait par le bas. La hauteur du plateau est desormais
     donnee par le rapport de la table, non par un plancher en vh. */
  min-height: 0;
  /* La largeur suit celle du plateau, mais la hauteur la borne : sur une
     fenetre large et basse, des cartes calees sur la seule largeur faisaient
     descendre le cadre du croupier jusque sur l'arc peint du tapis. */
  --card-w: clamp(36px, min(8cqw, 10vh), 86px);
  flex: 1;
  width: 100%;
  /* Reference de positionnement du sabot. Sans elle, il se calait sur
     #game-area, donc hors du tapis. */
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}

#board-inner > * {
  position: relative;
  z-index: 1;
}

/* Les inscriptions occupent la place laissee entre le croupier et les joueurs,
   au lieu d'etre peintes sur un calque de taille fixe. Posees en fond absolu,
   elles suivaient leurs propres proportions et venaient chevaucher le total du
   croupier ou les emplacements des machines des que la fenetre changeait de
   format. */
/* La zone de jeu doit pouvoir se resserrer pour laisser la place au pied de
   page : sans cela elle se calait sur son contenu et poussait la mention hors
   de l'ecran, obligeant a defiler pour voir ses jetons. */
#main-content > #game-area { min-height: 0; }

/* La boite prend la place laissee entre le croupier et les joueurs ; le calque
   s'y etire. Pose directement dans le flux, le SVG reclamait la hauteur que lui
   donne son viewBox et rallongeait le plateau au point qu'il fallait defiler
   pour voir la banquette. */
#markings-slot {
  flex: 1 1 0;
  width: 100%;
  min-height: 0;
  position: relative;
  z-index: 0;
  pointer-events: none;
}

/* Le calque remplit la bande, "meet" retenant la plus petite des deux
   echelles. C'est le rapport de la table, plafonne plus haut, qui garantit a
   la bande de quoi le loger sans le rapetisser.

   Le releve des inscriptions se fait dans le dessin lui-meme, non ici : voir
   le groupe qui porte l'arc dore, l'annonce du paiement et le ruban. */
#table-markings {
  position: absolute;
  /* Une marge laterale, sinon les grands ecrans, ou la bande est large,
     poussent les inscriptions jusque sur le bord courbe, qui les rogne. */
  top: 0;
  left: 6%;
  width: 88%;
  height: 100%;
}

.table-arc {
  fill: none;
  stroke: rgba(243, 234, 105, 0.42);
  stroke-width: 3;
}

.table-text {
  fill: rgba(243, 234, 105, 0.5);
  font-family: "Book Antiqua", "Palatino Linotype", Palatino, Georgia, serif;
  font-weight: bold;
  letter-spacing: 0.16em;
}

.table-text.pays { font-size: 34px; }

.table-text.rule {
  font-size: 19px;
  font-weight: normal;
  font-style: italic;
  letter-spacing: 0.06em;
  fill: rgba(255, 255, 255, 0.38);
}

.table-text.insurance {
  /* Le chemin suit le milieu du ruban : c'est le centrage sur la ligne, et
     non un decalage chiffre, qui pose le texte a mi-hauteur, quelle que soit
     la taille du texte ou l'echelle du calque. */
  dominant-baseline: central;
  font-size: 23px;
  letter-spacing: 0.24em;
  fill: rgba(255, 255, 255, 0.6);
}

/* Cadre de la zone d'assurance : un ruban courbe peint sur le feutre. */
.insurance-box {
  fill: none;
  stroke: rgba(255, 255, 255, 0.5);
  stroke-width: 2;
  stroke-linejoin: round;
}

/* ---------- RANGEES ---------- */
.table-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

/* Le croupier occupe le haut du tapis, sans marge au-dessus. */
#dealer-area { padding-top: 0; }

/* Le croupier ne mise pas : la place que .hand reserve au-dessus des cartes
   pour les jetons ne lui sert a rien, et coutait une cinquantaine de pixels
   pris sur la bande des inscriptions. La marque peinte se cale sur cette
   meme reserve : elle doit remonter d'autant, sans quoi les cartes ne
   tombent plus dessus. */
#dealer-hand { padding-top: 0; }
#dealer-hand::before { top: 0; }

/* Les places sont repoussees contre le bord courbe. */
#player-area {
  padding-bottom: 4px;
}

/* ---------- MAINS ---------- */
/* ---------- PLACES ---------- */
/* ---------- EVENTAIL DES PLACES ----------
   Les trois places sont posees en pourcentage de la largeur du tapis, et non
   a distance fixe : l'ecartement suit donc la taille de l'ecran sans jamais
   se casser ni deborder. Les deux places exterieures sont un peu plus hautes
   pour epouser la courbe de la table. */
#seats {
  position: relative;
  width: 100%;
  height: calc(var(--card-w) * 244 / 168 + 128px);
}

.seat {
  position: absolute;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  transform: translate(-50%, var(--seat-lift, 0));
}

/* Place de gauche.
   Le relevement suit le bord courbe du tapis, qui monte vers les cotes, et
   s'exprime en cqw, donc proportionnel a la largeur. */
.seat:nth-child(1) {
  left: 20%;
  --seat-lift: -9cqw;
}

/* Place du joueur, au centre */
.seat:nth-child(2) { left: 50%; }

/* Place de droite */
.seat:nth-child(3) {
  left: 80%;
  --seat-lift: -9cqw;
}

.seat-hands {
  display: flex;
  align-items: flex-start;
  gap: 16px;
}

/* Plaque du nom : le feutre est trop charge, en texture comme en inscriptions,
   pour qu'un texte clair s'y detache seul. */
.seat-label {
  margin-top: 10px;
  padding: 4px 12px 5px;
  border-radius: 5px;
  background: rgba(0,0,0,0.42);
  border: 1px solid rgba(255,255,255,0.12);
  box-shadow: 0 2px 6px rgba(0,0,0,0.35);
  text-align: center;
}

/* Depart et arrivee d'un joueur automatique ruine. */
.seat.leaving,
.seat.arriving { transition: opacity 0.55s ease, transform 0.55s ease; }

.seat.leaving {
  opacity: 0;
  transform: translate(-50%, calc(var(--seat-lift, 0px) + 14px));
}

.seat.arriving {
  animation: seatArrive 0.6s ease forwards;
}

@keyframes seatArrive {
  from { opacity: 0; transform: translate(-50%, calc(var(--seat-lift, 0px) - 12px)); }
  to { opacity: 1; transform: translate(-50%, var(--seat-lift, 0)); }
}

.seat.human .seat-label {
  background: rgba(0,0,0,0.5);
  border-color: rgba(243,234,105,0.35);
}

.seat-name {
  font-size: 14px;
  letter-spacing: 0.05em;
  color: rgba(255,255,255,0.72);
}

.seat.human .seat-name {
  color: rgba(243, 234, 105, 0.95);
  font-weight: 600;
}

.seat-stack {
  margin-top: 1px;
  font-size: 12px;
  color: rgba(255,255,255,0.45);
}

/* Les jetons de mise sont la cave : sous chaque bouton s'empile ce qui reste
   a poser de cette valeur. Le bouton est le jeton du dessus. */
.chip-pile {
  position: relative;
  /* Les jetons se recouvrent : chacun ne laisse voir qu'une partie de sa
     tranche, comme dans une pile serree. La tranche entiere les faisait
     paraitre poses les uns au-dessus des autres, sans se toucher. */
  --pile-step: calc(var(--chip-h, 45px) * 0.15);
  display: flex;
  align-items: flex-end;
  isolation: isolate;
}

.chip-under {
  position: absolute;
  left: 0;
  width: 40px;
  height: 45px;
  background: transparent center / contain no-repeat;
  /* Meme marge basse que le bouton : sans elle, la zone de fond differait et
     le jeton du sommet paraissait decale par rapport a la pile. */
  padding-bottom: calc(var(--chip-h, 45px) * 0.143);
  pointer-events: none;
}

/* Chaque pile reprend le jeton de son bouton. */
.chip-pile:has(.chip[data-value="5"]) .chip-under { background-image: var(--chip-5); }
.chip-pile:has(.chip[data-value="25"]) .chip-under { background-image: var(--chip-25); }
.chip-pile:has(.chip[data-value="100"]) .chip-under { background-image: var(--chip-100); }

/* Resultat de la manche, a cote de la cave. Il ne vit que le temps ou les
   cartes restent sur le tapis. */
.seat-delta {
  margin-left: 5px;
  font-weight: 600;
}

.seat-delta.plus { color: #4ade80; }
.seat-delta.minus { color: #f87171; }

/* Colonne pour pouvoir sortir le total du flux : il s'affiche au-dessus des
   cartes alors qu'il est ecrit apres elles dans le document. */
.hand {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  /* Place reservee a la mise, posee au-dessus en position absolue. */
  padding-top: calc(var(--bet-chip-h, 45px) + 4px);
}

/* Largeur figee, celle d'une carte : l'eventail deborde de part et d'autre.
   Une largeur suivant le nombre de cartes deplacait le bloc entier a chaque
   nouvelle carte, puisqu'il est centre. */
.hand-cards {
  position: relative;
  height: calc(var(--card-w) * 244 / 168);
  width: var(--card-w);
  margin: 0 auto;
}

.hand-cards .card {
  position: absolute;
  top: 0;
}

/* Emplacement de carte : une marque peinte sur le feutre. Elle reste en
   place, cartes ou non, et ne suit pas l'elargissement de la main. outline et
   non border, comme partout ailleurs sur le plateau. */
.card-slot {
  width: var(--card-w);
  aspect-ratio: 168 / 244;
  border-radius: 6px;
  outline: 1px solid rgba(255,255,255,0.3);
  outline-offset: -1px;
}

/* La marque est posee par rapport a la main, non au bloc de cartes : celui-ci
   s'elargit avec le nombre de cartes, et la marque se serait deplacee a chaque
   carte donnee ou ramassee. */
.hand::before {
  content: '';
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: calc(var(--bet-chip-h, 45px) + 4px);
  width: var(--card-w);
  aspect-ratio: 168 / 244;
  border-radius: 6px;
  outline: 1px solid rgba(255,255,255,0.3);
  outline-offset: -1px;
  pointer-events: none;
}

.hand.empty::before { top: 0; }

.hand-value {
  margin-top: 10px;
  min-width: 46px;
  padding: 3px 10px;
  border-radius: 12px;
  background: rgba(0,0,0,0.55);
  border: 1px solid rgba(255,255,255,0.3);
  font-size: 15px;
  font-weight: 600;
  color: #fff;
}

.hand-value.bust { color: #f87171; border-color: rgba(248,113,113,0.6); }
.hand-value.blackjack { color: #4ade80; border-color: rgba(74,222,128,0.6); }

/* L'assurance se pose sur le ruban peint du tapis, devant sa place, comme
   sur une vraie table. Sortie du bloc des places, elle est calee par le
   script sur l'arc : voir placeInsuranceBets. Le selecteur porte
   #board-inner, sans quoi la regle qui range ses enfants dans le flux
   l'emporterait. */
#board-inner > .insurance-bet {
  position: absolute;
  z-index: 2;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 5px;
}

/* Mise materialisee en piles de jetons, posee au-dessus des cartes. Elle est
   sortie du flux : sa largeur variant avec le montant, elle elargissait la
   main et faisait sauter les cartes voisines a chaque doublement. */
/* La mise en attente, hors de toute main, reste dans le flux : elle se pose
   au-dessus de l'emplacement, la ou ira celle de la main. */
.hand-bet.pending {
  /* relative, non static : l'element revient dans le flux sans renoncer a son
     contexte de positionnement, ce que le plateau proscrit. */
  position: relative;
  top: auto;
  left: auto;
  transform: none;
  margin: 0 auto 4px;
}

/* Place sans carte : rien a reserver au-dessus, la mise en attente occupe
   deja cette hauteur. */
.hand.empty { padding-top: 0; }

.hand-bet {
  position: absolute;
  /* Ancree par le bas de la reserve, la pile grandit vers le haut. Tenue par
     le haut, elle descendait sur le cadre de l'emplacement des le deuxieme
     jeton, la hauteur de .bet-stack suivant le nombre de jetons. */
  top: var(--bet-chip-h, 45px);
  left: 50%;
  transform: translate(-50%, -100%);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 5px;
  min-height: var(--bet-chip-h, 45px);
}

/* Ramassage de fin de manche. La courbe part lentement, accelere, puis se
   pose : un geste, pas un glissement a vitesse constante. La copie voyage
   par-dessus toute la page, le tapis rognant ce qui deborde de lui. */
.hand-bet.sweeping {
  z-index: 200;
  animation: betSweep 0.85s cubic-bezier(0.62, 0.02, 0.34, 1) forwards;
  pointer-events: none;
}

@keyframes betSweep {
  0% { transform: translate(0, 0); opacity: 1; }
  78% { opacity: 1; }
  100% {
    transform: translate(var(--sweep-x, 0px), var(--sweep-y, 0px));
    opacity: 0;
  }
}

/* La hauteur suit le nombre de jetons, sans quoi la pile deborderait sur
   la plaque du nom. */
.bet-stack {
  position: relative;
  width: var(--bet-chip-w, 40px);
  height: calc(var(--bet-chip-h, 45px)
               + (var(--stack-count, 1) - 1) * var(--bet-chip-step, 6px));
  transition: transform 0.12s ease;
}

.bet-stack.removable { cursor: pointer; }
.bet-stack.removable:hover { transform: translateY(-4px); }

.bet-chip {
  position: absolute;
  left: 0;
  /* 62x70 a la source */
  width: var(--bet-chip-w, 40px);
  height: var(--bet-chip-h, 45px);
  display: flex;
  align-items: center;
  justify-content: center;
  /* meme recentrage sur la face que les jetons de mise */
  padding-bottom: calc(var(--bet-chip-h, 45px) * 0.143);
  background: center / contain no-repeat;
  font-family: "Bodoni MT Black", "Bodoni MT", "Bodoni 72", "Didot", "Playfair Display", Georgia, "Times New Roman", serif;
  /* Meme corps que les jetons de mise : calculee depuis la largeur, la valeur
     du croupier tombait a 13 px alors que celle du joueur en faisait 17. */
  --chiffre: 17px;
  font-size: var(--chiffre);
  font-weight: 700;
  color: #14140f;
}

.bet-chip[data-value="5"] { background-image: var(--chip-5); }
.bet-chip[data-value="25"] { background-image: var(--chip-25); }
.bet-chip[data-value="100"] { background-image: var(--chip-100); }

/* Le resultat s'inscrit par-dessus les cartes : ecrit dessous, il decalait
   toute la main a l'instant ou il paraissait. */
.hand-outcome {
  position: absolute;
  left: 50%;
  top: calc(var(--bet-chip-h, 45px) + 12px + var(--card-w) * 244 / 168 * 0.4);
  transform: translateX(-50%);
  padding: 3px 10px 4px;
  border-radius: 4px;
  background: #0a0a0a;
  border: 1px solid rgba(255,255,255,0.28);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  /* Au-dessus de toutes les cartes : les leurs montent avec leur rang, et a
     partir de la troisieme elles passaient devant le texte. */
  z-index: 30;
}

.hand-outcome.win { color: #4ade80; }
.hand-outcome.lose { color: #f87171; }
.hand-outcome.push { color: #d8d8d8; }

/* ---------- RESERVE DU CROUPIER ----------
   Trois piles debout, cote croupier, batie comme celles du joueur. La boite
   garde son emprise : seule la hauteur des piles bouge. */
#board-inner > #dealer-bank {
  position: absolute;
  top: 14px;
  left: 18px;
  --bet-chip-w: 40px;
  --bet-chip-h: 45px;
  --bet-chip-step: 5px;
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  max-width: calc(var(--bet-chip-w) * 6.4);
  gap: 7px 8px;
}

.bank-pile {
  position: relative;
  width: var(--bet-chip-w);
  height: calc(var(--bet-chip-h) + (var(--stack-count, 1) - 1) * var(--bet-chip-step));
}

/* Pile pleine : le jeton de trop passe par-dessus la table et disparait. */
.bet-chip.overflowing {
  z-index: 40;
  animation: bankOverflow 0.85s cubic-bezier(0.5, 0, 0.4, 1) forwards;
  pointer-events: none;
}

@keyframes bankOverflow {
  0% { transform: translate(0, 0) scale(1); opacity: 1; }
  75% { opacity: 1; }
  100% {
    transform: translate(var(--over-x, 0px), var(--over-y, 0px)) scale(0.6);
    opacity: 0;
  }
}

/* ---------- SABOT ----------
   Un boitier de plastique noir, vu du dessus. Le dessus est ouvert : on voit
   le dos de la carte du dessus, le paquet reculant vers l'avant a mesure qu'il
   s'epuise. Un capot ferme l'arriere ; a l'avant, une porte percee d'une
   arche laisse voir la carte suivante, qui depasse par le bas.

   Le selecteur porte #board-inner : la regle generique qui donne
   position: relative aux enfants du plateau compte deux identifiants,
   #table-markings comptant dans le :not(). Un simple #shoe perdait, et le
   sabot retombait dans le flux, en haut a gauche. */
#board-inner > #shoe {
  position: absolute;
  /* Les cartes sont couchees dans le sabot : sa largeur est leur longueur. */
  --shoe-card: var(--card-w);
  --shoe-card-l: calc(var(--shoe-card) * 244 / 168);
  --shoe-w: calc(var(--shoe-card-l) * 1.14);
  --shoe-h: calc(var(--shoe-card) * 2.5);
  --shoe-pivot: calc((var(--shoe-h) - var(--shoe-w)) / 2);
  width: var(--shoe-w);
  height: var(--shoe-h);
  /* Couche sur le flanc, le boitier rend au coin la hauteur qu'il prenait
     debout, et la carte engagee depasse vers le croupier. La rotation ne
     deplace pas l'emprise de la boite, seulement son dessin : on retranche
     de quoi le ramener dans l'angle. */
  transform: rotate(90deg);
  top: calc(12px - var(--shoe-pivot));
  right: calc(16px + var(--shoe-pivot));
}

#shoe-body {
  position: absolute;
  inset: 0;
  border-radius: 5px;
  background: linear-gradient(158deg, #2b2b2d 0%, #121213 55%, #1e1e20 100%);
  border: 1px solid rgba(255,255,255,0.16);
  box-shadow: 0 7px 16px rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.14);
}

/* Le paquet a decouvert : la tranche de chaque carte, une ligne par carte.
   Les cartes sont couchees en travers du sabot, leurs tranches courent donc a
   l'horizontale. Le paquet recule vers la porte a mesure qu'il s'epuise. */
#shoe-deck {
  position: absolute;
  left: 7%;
  right: 7%;
  bottom: 26%;
  height: calc(56% * var(--shoe-fill));
  background: repeating-linear-gradient(180deg,
    #f4f1e8 0 1px,
    #8d8778 1px 2px);
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.5),
              0 -2px 3px rgba(0,0,0,0.5);
  transition: height 0.3s ease;
}

/* Capot avant : la plaque qui recouvre le bout du paquet, juste avant la
   porte. C'est sous elle que la carte s'engage. */
#shoe-hood {
  position: absolute;
  z-index: 1;
  left: 0;
  right: 0;
  bottom: 26%;
  height: 17%;
  /* Vu du dessus, a plat : un aplat, sans degrade qui simulerait une pente. */
  background: #202023;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.12), 0 2px 5px rgba(0,0,0,0.5);
}

/* Capot arriere, ferme. */
#shoe-back {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 18%;
  border-radius: 5px 5px 2px 2px;
  background: linear-gradient(180deg, #2f2f31, #171718);
  box-shadow: 0 2px 4px rgba(0,0,0,0.6);
}

/* Porte avant. Sa decoupe en arche est obtenue par une fenetre posee dessus :
   la porte reste pleine, la fenetre laisse passer la carte. */
/* L'avant du sabot est incline vers la table : la porte et la carte qu'elle
   laisse passer basculent ensemble, d'ou le conteneur commun. */
#shoe-front {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 26%;
  transform-origin: center top;
  transform: perspective(220px) rotateX(-38deg);
  transform-style: preserve-3d;
}

#shoe-gate {
  position: absolute;
  z-index: 2;
  inset: 0;
  border-radius: 2px 2px 5px 5px;
  background: linear-gradient(180deg, #232325, #121213);
  box-shadow: 0 -2px 5px rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.12);
  /* L'arche est un trou dans la porte, ouvert vers le bas : le cercle deborde
     du bord inferieur, la carte passe dessous et ressort a plat. */
  -webkit-mask-image: radial-gradient(circle at 50% 96%, #0000 0 46%, #000 46%);
  mask-image: radial-gradient(circle at 50% 96%, #0000 0 46%, #000 46%);
}

/* La carte engagee, couchee et entiere : elle glisse sous la porte et sort a
   plat par le bas. Rien ne la decoupe, c'est la porte qui est percee. */
/* La carte engagee, couchee et entiere : elle glisse sous la porte et sort a
   plat par le bas. Rien ne la decoupe, c'est la porte qui est percee. */
#shoe-exit {
  position: absolute;
  left: 50%;
  bottom: 0;
  width: var(--shoe-card);
  height: calc(var(--shoe-card) * 244 / 168);
  background: center / contain no-repeat;
  transform: translate(-50%, 58%) rotate(90deg);
  z-index: 1;
}

/* ---------- MESSAGE CENTRAL ---------- */
/* L'annonce est posee par-dessus le tapis, hors du flux : dans la pile elle
   prenait sa part de hauteur, prise sur la bande des inscriptions, qui n'en a
   deja guere. Elle passe devant les cartes comme devant les inscriptions. */
#message {
  position: absolute;
  /* Valeur de repli : le script recale l'annonce sur l'emplacement des cartes
     du joueur des le premier rendu. Voir placeMessage. */
  top: 42%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 50;
  max-width: 88%;
  /* La plaque epouse le texte au lieu de barrer le tapis : le message est
     court et centre, une bande pleine largeur ferait bandeau. */
  width: fit-content;
  padding: 8px 34px 10px;
  border-radius: 999px;
  background: #0a0a0a;
  border: 1px solid rgba(255,255,255,0.2);
  box-shadow: 0 4px 14px rgba(0,0,0,0.55);
  text-align: center;
  font-size: 34px;
  font-weight: 600;
  color: #fff;
  text-shadow: 0 2px 6px rgba(0,0,0,0.6);
}

/* Entre deux annonces le texte est vide : sans cela il resterait une pastille
   noire au milieu du tapis. */
#message:empty {
  padding: 0;
  background: none;
  border-color: transparent;
  box-shadow: none;
}

#message.win { color: #4ade80; }
#message.lose { color: #f87171; }

/* ---------- COMMANDES ---------- */
/* Banquette : hors du tapis, sous la table. Une seule rangee, les jetons puis
   les commandes ; le placement reste relatif, chacun poussant l'autre plutot
   que d'occuper une colonne fixe. L'emprise minimale ne bouge pas d'une phase
   a l'autre. La marge est comptee au plus juste : ce qui est rendu ici revient
   a la table, dont la hauteur commande la largeur. */
#controls {
  position: relative;
  width: 100%;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 28px;
  min-height: 104px;
  margin-top: 12px;
}

#actions, /* Les piles descendent sous les boutons et debordent de leur boite : posees
   dans le flux, elles couvraient Distribuer quoi qu'on fasse. Elles sont donc
   sorties du flux, calees a gauche de la banquette. */
#bet-controls {
  display: flex;
  gap: 16px;
}

/* Emprise fixe : les commandes ne se deplacent pas d'une phase a l'autre.
   Distribuer se superpose a la case de Carte, en haut a gauche. */
#command-zone {
  position: relative;
  display: grid;
}

#command-zone > #btn-deal {
  position: absolute;
  top: 0;
  left: 0;
}

/* Carte et Rester sur la premiere ligne, Doubler et Separer sous elles : les
   deux gestes courants d'abord, les deux gestes rares ensuite. Le selecteur
   porte #controls pour passer devant la regle groupee qui met les deux
   rangees de commandes en flex. */
#controls #actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px 10px;
  width: max-content;
}

/* Les deux blocs se superposent : la zone garde la taille du plus grand. */
#command-zone > #actions,
#command-zone > #insurance-actions { grid-area: 1 / 1; }

/* Les deux reponses a l'assurance tombent la ou sont Carte et Rester. */
#insurance-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px 10px;
  width: max-content;
  align-self: start;
}

.action-btn {
  padding: 9px 20px;
  border: 1px solid #ccc;
  border-radius: 4px;
  background: rgba(0,0,0,0.5);
  color: #fff;
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.action-btn:hover:not(:disabled) { background: rgba(255,255,255,0.15); border-color: #fff; }

.action-btn:disabled {
  opacity: 0.35;
  cursor: default;
}

.action-btn.primary {
  background: #1d6b3a;
  border-color: #4ade80;
}

.action-btn.primary:hover:not(:disabled) { background: #248046; }

/* ---------- JETONS ----------
   Redessines d'apres le 2D Poker Pack de Screaming Brain Studios (CC0). Les
   planches d'origine sont des images matricielles de 62x70 ; les fichiers de
   chips/ en reprennent la geometrie relevee au pixel (quasi-cercle vu de
   trois quarts, tranche de 8, anneau a quatre encoches) et les couleurs
   exactes, mais en trace, donc nets a toute taille.

   Le prefixe ../ tient a ce qu'une url() se resout depuis la feuille, non
   depuis la page : cette feuille vit dans blackjack/, les jetons un cran
   au-dessus. */
:root {
  --chip-5: url('../chips/chip-red.svg');
  --chip-25: url('../chips/chip-green.svg');
  --chip-100: url('../chips/chip-blue.svg');
}

.chip {
  /* 62x70 a la source : la hauteur suit la largeur pour ne pas ecraser le jeton */
  --chip-h: 45px;
  width: 40px;
  height: var(--chip-h);
  /* Le jeton est dessine avec son epaisseur en dessous : la face claire est
     centree 7,1 % plus haut que l'image. Un padding bas du double recentre le
     chiffre sur la face, et non sur la boite. */
  padding-bottom: calc(var(--chip-h) * 0.143);
  border: none;
  background: transparent center / contain no-repeat;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #14140f;
  /* Grasse et contrastee, elle tient le chiffre sur le fond charge du jeton.
     Bodoni MT Black n'est installee que sur une partie des machines : on la
     fait suivre de substituts didones, puis d'une serif de systeme. */
  font-family: "Bodoni MT Black", "Bodoni MT", "Bodoni 72", "Didot", "Playfair Display", Georgia, "Times New Roman", serif;
  --chiffre: 17px;
  font-size: var(--chiffre);
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  transition: transform 0.12s ease;
}

.chip:hover:not(:disabled) { transform: translateY(-4px); }
.chip:disabled { cursor: default; }

/* Trois chiffres ne tiennent pas dans le disque blanc au corps des autres
   valeurs : le 100 mordait sur l'anneau. Le rapport suit le corps, quelle que
   soit la taille du jeton. */
.chip[data-value="100"],
.bet-chip[data-value="100"] {
  font-size: calc(var(--chiffre) * 0.82);
}

.chip[data-value="5"] { background-image: var(--chip-5); }
.chip[data-value="25"] { background-image: var(--chip-25); }
.chip[data-value="100"] { background-image: var(--chip-100); }

#bet-readout {
  font-size: 16px;
  font-weight: 600;
  color: #fff;
  min-width: 120px;
  text-align: center;
}

/* ---------- BARRE LATERALE ---------- */
#bankroll-line {
  font-family: "Book Antiqua", "Palatino Linotype", Palatino, "URW Palladio L", "Palatino LT STD", Georgia, "Times New Roman", serif;
  font-weight: bold;
  font-size: 30px;
  line-height: 1.2;
  color: #fff;
  margin-bottom: 18px;
}

#bankroll-box { position: relative; display: inline-block; }

#bankroll-delta-layer {
  position: absolute;
  left: 100%;
  top: 0;
  width: 0;
  height: 0;
}

/* Meme principe que les etiquettes de score du solitaire : strictement
   immobiles, seule l'opacite varie. */
.bankroll-delta {
  position: absolute;
  left: 10px;
  top: 0;
  font-size: 22px;
  font-weight: bold;
  white-space: nowrap;
  pointer-events: none;
  animation: bankrollFade 1.4s ease-out forwards;
}

.bankroll-delta.plus { color: #4ade80; }
.bankroll-delta.minus { color: #f87171; }

@keyframes bankrollFade {
  0% { opacity: 0; }
  10% { opacity: 1; }
  55% { opacity: 1; }
  100% { opacity: 0; }
}

#record {
  color: #bbb;
  font-size: 17px;
  margin-bottom: 10px;
}

/* ---------- ANIMATIONS DE DISTRIBUTION ---------- */
/* La carte part de la position du sabot : le decalage est calcule par le
   script et pose en ligne (--dx, --dy), le mouvement reste en CSS. */
/* Trajet et retournement sont deux animations separees, portees par deux
   proprietes qui se composent. Reunies en une seule suite d'images, la courbe
   s'appliquait a chaque segment et la carte marquait un arret a mi-chemin. */
/* La carte quitte le sabot couchee, comme elle y etait rangee, et se redresse
   en arrivant sur le tapis. */
@keyframes cardDeal {
  from { translate: var(--dx, 0px) var(--dy, 0px); rotate: -90deg; }
  to { translate: 0 0; rotate: 0deg; }
}

@keyframes cardTurn {
  0%, 100% { scale: 1 1; }
  50% { scale: 0.04 1; }
}

/* Un peu plus lente qu'avant : la carte doit se voir partir du sabot. */
.card-deal {
  animation: cardDeal 0.62s cubic-bezier(0.2, 0.7, 0.3, 1),
             cardTurn 0.62s linear;
}

.card-flip { transition: transform 0.16s linear; }
.card-flip.folded { transform: scaleX(0); }

/* ---------- REGLES ---------- */
/* ---------- ONGLETS DES REGLES ----------
   Les regles tiennent sur quatre volets plutot qu'en une seule colonne : le
   joueur qui cherche la regle des paires n'a pas a traverser tout le reste.

   Seul le corps defile : le titre, les onglets et le bouton restent en place,
   sans quoi changer d'onglet deplacerait la barre sous le curseur. */
/* Taille figee, independante du volet affiche. Sans cela la fenetre se
   redimensionne d'un onglet a l'autre : etant centree, elle emporte la barre
   d'onglets avec elle et le curseur se retrouve a cote. La largeur tient la
   rangee d'onglets sur une seule ligne, y compris en anglais. */
#rules-dialog {
  flex-direction: column;
  overflow-y: hidden;
  width: min(94vw, 620px);
  max-width: none;
  height: min(90vh, 780px);
}

#rules-dialog .rules-tabs { flex-wrap: nowrap; }

#rules-dialog.open { display: flex; }

#rules-dialog .rules-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  text-align: left;
}

#rules-dialog h2,
#rules-dialog .rules-tabs,
#rules-dialog .modal-actions { flex-shrink: 0; }

.rules-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 14px 0 0;
  border-bottom: 1px solid rgba(255,255,255,0.15);
}

.rules-tab {
  padding: 7px 14px;
  border: none;
  border-bottom: 2px solid transparent;
  background: none;
  font-family: inherit;
  font-size: 14px;
  color: #999;
  cursor: pointer;
  transition: color 0.12s ease, border-color 0.12s ease;
}

.rules-tab:hover { color: #ddd; }

.rules-tab.active {
  border-bottom-color: rgba(243, 234, 105, 0.8);
  color: #fff;
}

.rules-panel { display: none; }
.rules-panel.active { display: block; }

/* Main illustree : les cartes, puis la mise dessous, comme sur le tapis. */
.fig-hand {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.fig-hand-cards {
  display: flex;
  justify-content: center;
  gap: 6px;
}

/* Dans les illustrations, la mise revient dans le flux : hors du tapis, elle
   n'a aucun conteneur positionne sous la main et se calait sur la page, tout
   en haut de la fenetre. relative et non static, que le plateau proscrit. */
.rules-panel .hand-bet {
  position: relative;
  top: auto;
  left: auto;
  transform: none;
  margin-top: 8px;
}

/* Le premier titre d'un volet n'a pas a se decoller des onglets. */
.rules-panel > h3:first-child { margin-top: 6px; }

.bj-rules-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 6px;
  color: #ccc;
}

.bj-rules-table td {
  padding: 4px 0;
  border-bottom: 1px solid rgba(255,255,255,0.12);
}

.bj-rules-table td:last-child {
  text-align: right;
  font-weight: bold;
  color: #fff;
  white-space: nowrap;
}

@media (max-width: 820px) {
  /* Etroit : la table reprend la hauteur de son contenu. Le rapport fixe n'a
     plus de sens ici, ou la largeur ne suffit pas a loger trois places et le
     croupier : impose, il ecrasait la bande et poussait les places hors du
     bord courbe. */
  #board {
    width: 100%;
    height: auto;
    aspect-ratio: auto;
    border-radius: 16px 16px 50% 50% / 16px 16px 18% 18%;
  }
  #board-inner { min-height: calc(60vh - 80px); }
  /* Ecran etroit : la courbe du tapis s'aplatit, le relevement suit, et on
     rentre un peu les places pour qu'elles ne touchent pas le cadre. */
  .seat:nth-child(1) { left: 25%; --seat-lift: -4cqw; }
  .seat:nth-child(3) { left: 75%; --seat-lift: -4cqw; }
  #board-felt { border-radius: 10px 10px 50% 50% / 10px 10px 18% 18%; }
  .chip { width: 36px; --chip-h: 40px; }
  .chip-under { width: 36px; height: 40px; }
  .chip, .bet-chip { --chiffre: 14px; }
  #message { font-size: 26px; padding: 6px 22px 8px; }
  .table-text.pays { font-size: 40px; }
  .table-text.rule { font-size: 22px; }
}
