/**
 * PlayAwale — Plateau de jeu : structure
 * -----------------------------------------------------------------------------
 * Géométrie, dimensions, positions et animations du plateau. Cette feuille est
 * la même quel que soit l'aspect choisi.
 *
 * SÉPARATION STRUCTURE / APPARENCE
 * Aucune couleur, aucune matière n'est écrite ici : tout passe par des
 * variables définies dans assets/css/themes/board/<thème>.css. Proposer un
 * autre plateau — pierre, nuit, contrasté — revient à fournir un second
 * fichier de thème, sans toucher à cette feuille ni au HTML.
 *
 * TAILLE DU PLATEAU
 * Le diamètre d'un trou est fixé une seule fois, par --hole-size, et tout le
 * reste en découle. Une seule valeur à ajuster par taille d'écran.
 *
 * @package   PlayAwale
 * @version   2.0
 * @author    Nicolas Lion — Développeur web — https://nlion.fr
 * @copyright 2026 Nicolas Lion
 */

/* =============================================================================
   DIMENSIONS
   ============================================================================= */

.board-container {
  /* Place que le plateau ne doit PAS occuper, réservée par la page à ce qui
     l'entoure : portraits, scores, boutons. Nulle par défaut — le plateau
     dispose alors de tout l'écran —, la page la redéfinit selon l'endroit où
     elle a posé ces éléments.

     C'est ainsi que le plateau cesse d'être recouvert sans que cette feuille
     ait à savoir ce qui l'entoure. */
  --board-reserve-x: 0px;
  --board-reserve-y: 0px;

  /* Diamètre d'un trou : mesure de référence de tout le plateau.

     TROIS LIMITES, LA PLUS BASSE L'EMPORTE
     1. une valeur fluide — plancher, valeur idéale, plafond — qui donne au
        plateau sa taille naturelle ;
     2. la largeur disponible, réserve déduite ;
     3. la hauteur disponible, réserve déduite.

     Les deux dernières manquaient, et c'est ce qui rendait le jeu inutilisable
     sur un téléphone couché : le plateau y suivait la largeur, très grande, et
     débordait d'une hauteur soudain très faible. Les portraits et les boutons,
     posés aux quatre coins, se retrouvaient par-dessus.

     LES DEUX FACTEURS SONT LES PROPORTIONS DU PLATEAU LUI-MÊME
     Largeur : six trous, cinq écarts de 0,16667 et deux marges de 0,25, soit
     7,33333 fois le trou. Hauteur : deux rangées avec leurs décalages, un
     écart et deux marges, soit 2,6 fois le trou. Relevés à la mesure sur le
     rendu — 880 × 312 pour un trou de 120. */
  --hole-size: min(
    clamp(44px, 11vw, 112px),
    (100vw - var(--board-reserve-x)) / 7.33333,
    (100vh - var(--board-reserve-y)) / 2.6
  );

  /* Espace entre deux trous, proportionnel à leur taille.
     20 / 120 — valeur de la version 1 pour un trou de 120 px. */
  --hole-gap: calc(var(--hole-size) * 0.16667);

  /* Marge intérieure du plateau autour des trous. 30 / 120. */
  --board-padding: calc(var(--hole-size) * 0.25);

  /* Amplitude de la secousse d'un trou capturé. 1 / 120 : les images clés en
     emploient un et trois fois cette valeur. */
  --shake: calc(var(--hole-size) / 120);

  position: relative;
  margin: 0 auto var(--space-lg);

  /* Le plateau ne dépasse jamais la largeur de l'écran. */
  max-width: 100%;
}


/* =============================================================================
   PLATEAU
   ============================================================================= */

.board {
  /* Deux rangées de six trous : la grille suffit, sans balise intermédiaire. */
  display: grid;
  grid-template-columns: repeat(6, var(--hole-size));
  gap: var(--hole-gap);
  justify-content: center;

  padding: var(--board-padding);
  position: relative;

  background-color: var(--board-base-color);
  background-image: var(--board-texture);
  background-blend-mode: var(--board-blend-mode);
  border-radius: var(--board-radius);
  box-shadow: var(--board-shadow);
}

/* Rainure centrale : la ligne de pliage de la boîte.
   Élément décoratif, donc en pseudo-élément plutôt qu'en balise. */
.board::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: calc(var(--hole-size) / 24);   /* 5 / 120 */
  background-color: var(--board-groove-color);
  transform: translateY(-50%);
  z-index: 1;
}


/* =============================================================================
   CHARNIÈRES
   Deux ferrures posées sur la rainure, de part et d'autre du plateau.
   ============================================================================= */

/* Ferrure : une petite plaque portant quatre rivets.
   Sa taille se déduit de son contenu — deux rivets et leur espacement, plus
   un cerne régulier — au lieu d'être fixée à l'avance. La plaque reste ainsi
   ajustée à ses rivets quelle que soit la taille du plateau.

   La version 1 déclarait 40 × 20 px avec un rembourrage gauche de 12 px et
   aucun « box-sizing: border-box » : la plaque rendue faisait 57 × 30 px, avec
   les rivets repoussés sur la droite et une zone vide à gauche. Ce
   décentrement était accidentel ; il n'est pas repris. */
.board-hinge {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;

  /* Plaque nettement couchée — deux fois plus large que haute — pour qu'on y
     reconnaisse une ferrure et non un simple bouton. */
  width: calc(var(--hole-size) * 0.5);        /* 60 / 120 */
  height: calc(var(--hole-size) * 0.25);      /* 30 / 120 */

  background-color: var(--board-hinge-color);
  border-radius: calc(var(--hole-size) * 0.06667);

  /* Les quatre rivets, centrés dans la plaque sur les deux axes.
     Les deux colonnes sont largement écartées — bien plus que les rangées —
     pour que les rivets occupent la longueur de la ferrure au lieu de se
     tasser en son milieu. Le cerne reste identique à gauche et à droite. */
  display: grid;
  grid-template-columns: repeat(2, auto);
  grid-template-rows: repeat(2, auto);
  row-gap: calc(var(--hole-size) / 30);     /*  4 / 120 */
  column-gap: calc(var(--hole-size) * 0.16667);  /* 20 / 120 */
  place-content: center;
}

.board-hinge span {
  width: calc(var(--hole-size) * 0.06667);  /* 8 / 120 */
  height: calc(var(--hole-size) * 0.06667);
  background-color: var(--board-hinge-dot-color);
  border-radius: 50%;
}

.board-hinge--left  { left: 14%; }
.board-hinge--right { right: 14%; }


/* =============================================================================
   TROUS
   ============================================================================= */

.hole {
  /* Côté d'une graine. Déclaré ici, et non sur la graine elle-même, parce que
     la disposition en a besoin : c'est de cette mesure que découle la hauteur
     à laquelle la première rangée doit se poser. Deux déclarations séparées
     finiraient par diverger, et les graines cesseraient d'être centrées.

     Proportionnelle au trou, mais jamais en dessous de 6 px : sur un petit
     écran, des graines plus fines cesseraient d'être dénombrables. */
  --seed-size: max(6px, calc(var(--hole-size) * 0.13333));  /* 16 / 120 */

  /* Écart entre deux graines, dans les deux sens. */
  --seed-gap: calc(var(--hole-size) / 24);                  /* 5 / 120 */

  width: var(--hole-size);
  height: var(--hole-size);
  border-radius: 50%;

  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;

  box-shadow: var(--hole-shadow);
  transition: background-color var(--duration-base) ease;

  /* Le plateau se manipule au doigt : ni surlignage au toucher, ni menu
     contextuel sur appui long, ni sélection de texte intempestive. */
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  user-select: none;
}

/* Décalages verticaux des deux rangées.
   Ils creusent l'écart autour de la rainure centrale : le plateau paraît plié
   en son milieu, et les deux camps se distinguent au premier coup d'œil.

   Les rapports reprennent les valeurs de la version 1 pour un trou de 120 px :
   −14 px pour les deux rangées, et surtout +20 px au-dessus de la rangée du
   joueur, qui l'écarte de la rainure. Sans cette marge, le plateau perd 22 px
   de hauteur et les deux rangées se rapprochent visiblement. */
.hole--ai {
  margin-top: calc(var(--hole-size) * -0.11667);
}

.hole--player {
  margin-top: calc(var(--hole-size) * 0.16667);
  margin-bottom: calc(var(--hole-size) * -0.11667);
}

/* Seuls les trous jouables réagissent au survol : c'est le seul indice visuel
   de ce sur quoi on peut cliquer.

   LA CONDITION TIENT DANS « is-playable », ET NULLE PART AILLEURS
   Le sélecteur exigeait auparavant le tour du joueur et le camp du bas. C'était
   redondant : l'affichage ne pose « is-playable » que sur un trou dont c'est le
   tour, tenu par un humain, et dont le coup est légal. La règle vaut donc
   telle quelle pour les deux camps d'une partie à deux, sans rien y ajouter. */
.hole.is-playable {
  cursor: pointer;
}

.hole.is-playable:hover {
  background-color: var(--hole-hover-color);
}

/* Sur écran tactile, l'état de survol resterait « collé » après le toucher. */
@media (hover: none) {
  .hole.is-playable:hover {
    background-color: transparent;
  }
}


/* =============================================================================
   GRAINES
   ============================================================================= */

/* -----------------------------------------------------------------------------
   Les graines dans leur trou
   -----------------------------------------------------------------------------
   Quatre par rangée, et CHAQUE GRAINE A SA PLACE, décidée par son seul rang.
   Aucune ne bouge quand une autre arrive.

   POURQUOI CELA COMPTE
   La version 1 centrait le bloc des seules rangées occupées. Chaque rangée
   nouvelle faisait donc remonter toutes les précédentes d'une demi-graine : à
   chaque graine semée, le contenu du trou sautait. Et à quatre graines — la
   position de départ de toute partie — le bloc n'était pas centré mais posé
   haut, les espacements des rangées vides comptant encore dans sa hauteur.

   L'ORDRE DE REMPLISSAGE : LE MILIEU, PUIS LE DESSOUS, PUIS LE DESSUS
   La première rangée est celle du MILIEU. C'est elle qui porte les quatre
   graines du début de partie, et elle tombe donc au centre du trou. La
   cinquième graine ouvre la rangée du DESSOUS, la neuvième celle du DESSUS,
   la treizième s'en va plus bas encore.

   LE BLOC SE RECENTRE À CHAQUE RANGÉE NOUVELLE
   Tant qu'une rangée se remplit, rien ne bouge. Quand la suivante s'ouvre,
   l'ensemble se replace au milieu du trou : un contenu qui pendrait d'un côté
   se remarquerait bien davantage qu'un recentrage, lequel n'arrive que trois
   fois dans la vie d'un trou.

   Le placement de chaque graine — sa rangée et sa colonne — est décidé par
   assets/js/game/board-view.js, qui seul connaît le nombre de graines : c'est
   lui qui détermine combien de rangées sont occupées, et donc où chacune se
   pose. Cette feuille ne fait que déclarer les pistes et centrer le tout.
   -------------------------------------------------------------------------- */
.hole .seeds {
  display: grid;

  /* Quatre colonnes ; les rangées naissent au fur et à mesure, et se centrent
     d'elles-mêmes puisqu'elles restent contiguës. */
  grid-template-columns: repeat(4, auto);
  gap: var(--seed-gap);

  place-content: center;

  position: absolute;
  inset: 0;
  padding: calc(var(--hole-size) / 12);   /* 10 / 120 */
}

.seed {
  width: var(--seed-size);
  height: var(--seed-size);

  border-radius: 50%;
  background: var(--seed-fill);
  box-shadow: var(--seed-shadow);
}


/* =============================================================================
   REPÈRES DE JEU
   ============================================================================= */

/* Pastille du nombre de graines, affichée dès que le trou est trop rempli
   pour être lu d'un coup d'œil. */
.seed-count {
  position: absolute;
  top: calc(var(--hole-size) * -0.08);
  right: calc(var(--hole-size) * -0.08);
  z-index: 3;

  min-width: calc(var(--hole-size) * 0.28);
  padding: calc(var(--hole-size) / 60) calc(var(--hole-size) * 0.05);   /* 2 / 120, 6 / 120 */

  background-color: var(--seed-count-bg);
  color: var(--seed-count-color);
  border-radius: var(--radius-full);

  /* Police d'affichage, héritée du corps de page comme en version 1. */
  font-family: var(--font-display);
  font-size: calc(var(--hole-size) * 0.107);
  font-weight: bold;
  text-align: center;

  /* Masquée par défaut ; le jeu l'affiche quand elle est utile. */
  display: none;
}

.hole.is-crowded .seed-count {
  display: block;
}

/* Graines restant en main pendant le semis, affichées sur le trou en cours. */
.seed-counter {
  position: absolute;
  top: 80%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 10;

  padding: calc(var(--hole-size) / 30) calc(var(--hole-size) / 12);   /* 4 / 120, 10 / 120 */
  background-color: var(--seed-counter-bg);
  color: var(--seed-counter-color);
  border-radius: var(--radius-full);

  font-family: var(--font-display);
  font-size: calc(var(--hole-size) * 0.133);
  font-weight: bold;

  opacity: 0;
  transition: opacity var(--duration-base) ease-in-out;
}

.seed-counter.is-visible {
  opacity: 1;
}


/* =============================================================================
   ÉTATS TRANSITOIRES
   Marques posées puis retirées par le moteur de jeu au fil du tour.
   ============================================================================= */

/* Trou qui vient de recevoir une graine. */
.hole.is-receiving {
  outline: var(--hole-distribution-outline);
  border-radius: 50%;
}

/* Coups envisagés par l'ordinateur. */
.hole.is-candidate {
  outline: var(--hole-candidate-outline);
  border-radius: 50%;
}

/* Coup finalement retenu par l'ordinateur, montré avant d'être joué. */
.hole.is-chosen {
  outline: var(--hole-chosen-outline);
  border-radius: 50%;
  transition: outline var(--duration-base);
}

/* =============================================================================
   AIDE AU SURVOL
   Sur les niveaux d initiation, survoler un de ses trous montre où les graines
   vont tomber et ce qu elles rapporteraient. Les anneaux sont dessinés en
   débordement du trou, pour ne rien masquer de son contenu.
   ============================================================================= */

/* Trou qui recevra une graine. */
.hole.is-target::after {
  content: '';
  position: absolute;
  inset: calc(var(--hole-size) * -0.05);
  border-radius: 50%;
  border: var(--hint-path-outline);
  pointer-events: none;
}

/* Trou qui serait capturé : la même forme, une autre couleur. */
.hole.is-capture-target::after {
  border: var(--hint-capture-outline);
}

/* Nombre de graines que la prise rapporterait, posé une seule fois sur le
   dernier trou raflé plutôt que répété sur chacun. */
.capture-badge {
  position: absolute;
  top: calc(var(--hole-size) * -0.14);
  left: 50%;
  transform: translateX(-50%);
  z-index: 4;

  padding: 1px calc(var(--hole-size) * 0.06);
  background: var(--hint-badge-bg);
  color: var(--hint-badge-color);
  border-radius: var(--radius-full);

  font-family: var(--font-body);
  font-size: calc(var(--hole-size) * 0.13);
  font-weight: bold;
  white-space: nowrap;
  pointer-events: none;
}


/* Trou dont les graines viennent d'être capturées : une secousse brève
   attire l'œil sur la prise. */
.hole.is-captured {
  animation: hole-shake 0.5s ease-in-out 1;
}

@keyframes hole-shake {
  0%, 100% { transform: translate(var(--shake), calc(var(--shake) * -1)) rotate(-1deg); }
  20%      { transform: translate(calc(var(--shake) * -3), 0) rotate(1deg); }
  40%      { transform: translate(var(--shake), calc(var(--shake) * -1)) rotate(1deg); }
  60%      { transform: translate(calc(var(--shake) * -3), var(--shake)) rotate(0deg); }
  80%      { transform: translate(calc(var(--shake) * -1), calc(var(--shake) * -1)) rotate(1deg); }
}


/* =============================================================================
   BARRES DE TOUR
   Deux bandeaux de part et d'autre du plateau : celui du camp au trait
   s'allume. Repère de couleur ET de position, lisible sans distinguer les
   teintes.
   ============================================================================= */

.turn-bar {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);

  width: 90%;
  height: calc(var(--hole-size) / 12);          /* 10 / 120 */
  border-radius: calc(var(--hole-size) / 24);   /*  5 / 120 */

  /* Masquée par défaut : le moteur révèle celle du camp au trait. */
  visibility: hidden;
  transition: background-color var(--duration-base) ease;
}

.turn-bar--ai {
  top: calc(var(--hole-size) / -24);   /* la moitié de son épaisseur */
  background-color: var(--turn-bar-ai-color);
}

.turn-bar--player {
  bottom: calc(var(--hole-size) / -24);   /* la moitié de son épaisseur */
  background-color: var(--turn-bar-player-color);
}

.turn-bar.is-active {
  visibility: visible;
}


/* =============================================================================
   LE COUP ANNONCÉ, DANS LE LECTEUR DE PARTIES
   -----------------------------------------------------------------------------
   Le lecteur montre chaque trou avant de le semer : sans cela, les graines
   partent d'un trou qu'on n'a pas eu le temps de repérer, et l'on passe la
   partie à reconstituer après coup d'où venait la main.

   DEUX COULEURS, PARCE QU'IL Y A DEUX CAMPS
   Rouge pour la rangée du haut, vert pour celle du bas. La couleur vient de la
   RANGÉE et non du camp, et c'est ce qu'il faut : en réseau, la rangée du bas
   est celle de qui regarde, quel que soit le camp qu'il tenait. Le vert veut
   donc toujours dire « moi ».

   L'anneau rouge est celui que le jeu pose déjà sur le coup retenu par
   l'ordinateur — toujours en haut : rien ne change pour lui.
   ============================================================================= */

.hole--player.is-chosen {
  outline: var(--hole-chosen-mine-outline, var(--hole-chosen-outline));
}
