/*
  Lexik -- styles de l'application.

  REGLE : aucune couleur, taille de police, espacement ou rayon en dur ici.
  Tout vient des tokens (design-system/tokens/tokens.css, dans ce meme dossier src/).

  Cadre unique : .screen porte le pattern en fond, chaque ecran est une .card.
  Mobile-first ; un seul palier (min-width: 640px) elargit sur grand ecran.
*/

/* ---- Reset minimal ---- */
*,
*::before,
*::after { box-sizing: border-box; }
[hidden] { display: none !important; }

/*
  Surbrillance de toucher des navigateurs mobiles.

  Au doigt, Chrome et Safari dessinent d'office un rectangle semi-transparent
  par-dessus l'element touche. Il ignore la forme reelle : sur nos boutons en
  pilule, il apparait carre, et il est fugace au point de ressembler a un
  defaut d'affichage plutot qu'a une reponse.

  On ne le retire QUE parce qu'un remplacement existe deja : tous les elements
  interactifs s'enfoncent en `scale(0.97)` au toucher (voir RETOUR TACTILE).
  Sans ce remplacement, l'interface deviendrait muette au doigt, ce qui serait
  bien pire qu'un rectangle mal dessine.
*/
html { -webkit-tap-highlight-color: transparent; }

body {
  margin: 0;
  background: var(--background-inverse); /* fond clair : le canvas anime se dessine dessus */
  color: var(--text-inverse);
  font-family: var(--font-body), system-ui, sans-serif;
  font-size: var(--font-size-body);
  -webkit-font-smoothing: antialiased;
}
h1, h2, p, ul { margin: 0; }
ul { padding: 0; list-style: none; }
img { display: block; max-width: 100%; }

/*
  Focus clavier : le seul reperage de qui navigue sans souris.
  `:focus-visible` ne se declenche PAS au clic a la souris, uniquement
  au clavier : on peut donc etre franc sans gener personne.
  `:where()` ne pese rien en specificite, un composant peut surcharger.
*/
:where(button, a, [tabindex]):focus-visible {
  outline: var(--focus-ring-width) solid var(--background-accent);
  outline-offset: var(--focus-ring-offset);
}

/*
  Reserve aux lecteurs d'ecran : invisible a l'oeil, mais bien present dans
  la page, donc lu a voix haute. `display: none` le retirerait aussi des
  lecteurs d'ecran, ce qui serait l'inverse du but recherche.
  Recette standard, ses valeurs sont techniques et non des choix de design.
*/
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Pas d'ascenseur visible sur mobile (toute la page defile) */
@media (max-width: 639px) {
  html { scrollbar-width: none; }
  html::-webkit-scrollbar { display: none; }
}

/*
  "Reduire les animations" est un reglage systeme, souvent active pour des
  raisons vestibulaires : le mouvement a l'ecran donne des vertiges ou la
  nausee. On ne supprime pas les transitions (un changement instantane peut
  etre plus brutal encore), on les rend quasi immediates, et on coupe les
  deplacements et les changements d'echelle, qui sont les vrais responsables.
*/
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;
    transition-duration: 1ms !important;
  }
  .letter.is-new,
  .letter-chip.is-current {
    transform: none !important;
  }
}

/* =========================================================
   CADRE : fond anime derriere (#bg-canvas), cartes par-dessus
   ========================================================= */

/* Fond anime : canvas plein ecran, fixe, derriere toutes les cartes */
#bg-canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  display: block;
  touch-action: none; /* attraper/lancer au doigt sans declencher le scroll */
}

/*
  Le referentiel est le seul ecran vraiment long. Le fond continue d'y flotter,
  mais il devient INERTE : sans ca, `touch-action: none` capte le geste et
  un scroll demarre dans la bande du haut attrape une lettre au lieu de defiler.
  Le canvas ne recevant plus le pointeur, c'est le `touch-action` de la page
  qui s'applique : le scroll redevient normal.
*/
body[data-view="catalog"] #bg-canvas {
  pointer-events: none;
  touch-action: auto;
}

/*
  HAUTEUR DE L'ECRAN : `dvh` et pas `svh`.

  Sur telephone, la hauteur visible change selon que la barre d'adresse est
  la ou non. Trois unites la decrivent :
    svh  la plus PETITE (barre visible)
    lvh  la plus GRANDE (barre retractee)
    dvh  la hauteur REELLE a chaque instant

  Avec `svh`, des que la barre se retracte au defilement, l'ecran reel devient
  plus grand que le cadre : une bande claire apparait sous la carte, la ou vit
  la barre de gestes du telephone. Avec `dvh`, le cadre suit et la carte reste
  collee au bas de l'ecran.
*/
.screen {
  position: relative;
  z-index: 1;              /* au-dessus du canvas */
  min-height: 100vh;       /* secours pour les navigateurs sans dvh */
  min-height: 100dvh;
  background: transparent;  /* laisse voir le fond anime */
  pointer-events: none;     /* les clics dans le vide vont au canvas... */
  display: flex;
  flex-direction: column;
  justify-content: flex-end; /* mobile : carte en bas */
  align-items: stretch;
}

/*
  Bande de fond anime au-dessus de la carte.

  Sa taille de DEPART est 72px, et `flex-grow` l'etale sur toute la place
  restante quand le contenu est court. C'est l'inverse d'un plancher haut :
  on ne reserve que le minimum, et le decor prend ce qui reste.

  Pourquoi pas un `flex-basis` de 148px avec compression : `.screen` a un
  `min-height`, pas une hauteur fixe. Quand le contenu deborde, le conteneur
  GRANDIT au lieu de contraindre ses enfants. Il n'y a donc aucune
  compression a repartir, et `flex-shrink` ne s'applique jamais. La bande
  imposerait 148px sur les ecrans charges, et forcerait a defiler alors que
  tout aurait tenu.
*/
.screen::before {
  content: "";
  flex: 1 1 72px;
}

.card {
  position: relative;
  pointer-events: auto;     /* ...mais la carte reste cliquable */
  background: var(--background-primary);
  color: var(--text-primary);
  /* Le navy descend jusqu'au bord physique de l'ecran (viewport-fit=cover),
     mais le CONTENU s'arrete au-dessus de la barre de gestes du telephone.
     `env(...)` vaut 0 partout ailleurs, la regle est donc sans effet sur
     desktop comme sur les telephones a boutons. */
  padding: var(--space-48) var(--space-24)
           calc(var(--space-32) + env(safe-area-inset-bottom, 0px));
  text-align: left;
  /* La carte epouse son contenu (hug) ; le fond anime occupe le reste. */
  display: flex;
  flex-direction: column;
  /* Mobile : coins hauts arrondis (remplace l'ancienne vague) */
  border-radius: var(--radius-l) var(--radius-l) 0 0;
}

/* Accueil : carte compacte, centree, a la hauteur de son contenu */
.card--home {
  min-height: auto;
  text-align: center;
}

/*
  ETIREMENT DE LA CARTE.

  Chaque ecran a sa propre hauteur, et sur desktop sa propre largeur. Sans
  rien, la zone navy sauterait d'une taille a l'autre. main.js mesure la
  taille AVANT et APRES le changement, puis fait passer la carte de l'une a
  l'autre (technique dite FLIP).

  AUCUN FONDU ici, et c'est deliberé : les ecrans sont des elements
  DIFFERENTS, l'un disparait pendant que l'autre arrive. Leur ajouter une
  entree en opacite donne l'impression que la carte s'efface puis revient,
  au lieu d'une seule zone qui s'etire. Seule la TAILLE bouge.

  `height`/`width` sont couteuses a animer (le navigateur recalcule la mise
  en page a chaque image) mais ce sont les seules qui produisent cet effet.
  `will-change` le previent pour qu'il s'y prepare.

  `overflow: hidden` le temps du trajet, sinon le contenu deborde de la
  carte pendant qu'elle grandit.
*/
.card.is-morphing {
  overflow: hidden;
  will-change: height, width;
  transition: height var(--duration-slow) var(--ease-out),
              width var(--duration-slow) var(--ease-out);
}

/* =========================================================
   ACCUEIL (contenu)
   ========================================================= */
/* Le logo vit seul : rien ne vient lui disputer le haut de l'ecran. */
.landing-logo { width: 200px; height: auto; margin: 0 auto var(--space-56); }

/*
  Titre d'accueil : le seul element qui domine. Porte par une surface slate,
  et arrondi comme les boutons juste en dessous : les trois blocs de l'accueil
  parlent la meme langue. Le citron reste reserve a l'action.
*/
.landing-title {
  /* La carte est un flex column : sans align-self, le badge serait etire
     sur toute la largeur. `center` le fait epouser son texte. */
  align-self: center;
  background: var(--background-secondary);
  color: var(--text-primary);
  border-radius: var(--radius-full); /* meme arrondi que les boutons */
  padding: var(--space-12) var(--space-24);
  font-family: var(--font-heading), sans-serif;
  font-weight: 600;
  font-size: var(--font-size-title-large);
  line-height: 1.2;
  margin-bottom: var(--space-16);
  /* Si le titre venait a passer sur deux lignes sur un petit ecran, elles
     seront de longueur proche au lieu d'une ligne pleine suivie d'un mot
     isole. Un badge colore rend cette asymetrie tres visible. */
  text-wrap: balance;
}

/*
  Le ton du jeu, en soutien du titre. A peine attenue : assez pour passer
  au second plan, pas assez pour virer au gris.
*/
.landing-pitch {
  font-family: var(--font-body), sans-serif;
  font-size: var(--font-size-body-large);
  font-weight: 400;
  color: var(--text-secondary);
  margin-bottom: var(--space-56);
}
.landing-actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-12);
}

/* =========================================================
   ICONES
   Les traces vivent dans index.html (un seul jeu, appele par <use>).
   Ici on ne decide que de leur presentation.
   ========================================================= */

/* Le jeu de traces ne s'affiche jamais : il sert de reserve. */
.icon-sprite { display: none; }

.ico {
  width: var(--icon-size);
  height: var(--icon-size);
  flex: none;
  fill: none;
  stroke: currentColor;   /* l'icone prend la couleur de son texte, comme un glyphe */
  stroke-width: var(--icon-stroke);
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Accompagne un libelle : plus petite, pour ne pas dominer le mot. */
.ico--s {
  width: var(--icon-size-s);
  height: var(--icon-size-s);
}

/* =========================================================
   BOUTONS (partages)
   ========================================================= */
.btn {
  border: none;
  border-radius: var(--radius-full);
  padding: var(--space-16) var(--space-24);
  font-family: var(--font-heading), sans-serif;
  font-size: var(--font-size-body);
  font-weight: 700;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out);
}
.btn-accent { background: var(--background-accent); color: var(--text-on-accent); }
.btn-accent:active { background: color-mix(in srgb, var(--background-accent), var(--text-on-accent) var(--state-pressed-on-light)); }
.btn-ghost { background: transparent; border: var(--border-width) solid var(--border-primary); color: var(--text-primary); }
.btn-ghost:active { background: color-mix(in srgb, transparent, var(--text-primary) var(--state-pressed)); }

/* =========================================================
   RETOUR (pilule)
   ========================================================= */
.back-btn {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: var(--space-8);
  background: var(--background-secondary);
  color: var(--text-primary);
  border: none;
  border-radius: var(--radius-full);
  padding: var(--space-8) var(--space-16);
  margin-bottom: var(--space-24);
  font-family: var(--font-body), sans-serif;
  font-size: var(--font-size-caption);
  font-weight: 700;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out);
}

/* =========================================================
   CHAMPS DE REGLAGE (nombre de categories, minuteur)
   ========================================================= */
.field { margin-bottom: var(--space-24); }
.field-label {
  display: block;
  font-family: var(--font-heading), sans-serif;
  font-weight: 700;
  font-size: var(--font-size-title);
  margin-bottom: var(--space-16);
}
.field-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.field-head .field-label { margin-bottom: 0; }
.field-hint {
  margin-top: var(--space-8);
  font-size: var(--font-size-caption);
  color: var(--text-muted);
}
/*
  Bloc de duree : s'ouvre en hauteur au lieu de surgir.
  `grid-template-rows: 0fr -> 1fr` est la seule facon d'animer une hauteur
  qu'on ne connait pas a l'avance, sans la coder en dur. L'enfant unique
  masque son debordement pendant que la ligne grandit.
  L'attribut `inert` (pose par main.js) sort le bloc ferme du parcours
  clavier et des lecteurs d'ecran : invisible ne suffit pas.
*/
.field-fold {
  display: grid;
  grid-template-rows: 0fr;
  margin-top: 0;
  opacity: 0;
  transition: grid-template-rows var(--duration-base) var(--ease-out),
              margin-top var(--duration-base) var(--ease-out),
              opacity var(--duration-base) var(--ease-out);
}
.field-fold-inner { overflow: hidden; }
.field-fold.is-open {
  grid-template-rows: 1fr;
  margin-top: var(--space-16);
  opacity: 1;
}

/* Barre de reglage (- valeur +) sur surface slate.
   Pilule, comme le segmented juste en dessous : les deux reglages de
   l'ecran parlent la meme langue. */
.stepper {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  background: var(--background-secondary);
  border-radius: var(--radius-full);
  padding: var(--space-12) var(--space-16);
}
.stepper-value {
  flex: 1;
  text-align: center;
  font-family: var(--font-heading), sans-serif;
  font-weight: 700;
  font-size: var(--font-size-headline);
  color: var(--text-primary);
  line-height: 1;
}
.stepper-btn {
  flex: none;
  width: 46px;
  height: 46px;
  border-radius: var(--radius-full);
  border: var(--border-width) solid var(--border-muted);
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-heading), sans-serif;
  font-size: var(--font-size-title-large);
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out);
  display: flex;
  align-items: center;
  justify-content: center;
}
.stepper-btn:disabled { opacity: 0.4; cursor: not-allowed; }

/* =========================================================
   PISTE A CHOIX UNIQUE  --  le segmented (duree du minuteur)
   et les onglets du jeu partagent exactement la meme mecanique.

   Un SEUL bloc citron se deplace, au lieu de s'allumer case par case :
   c'est ce qui raconte qu'on choisit DANS une serie, et pas qu'on active
   des cases independantes.

   La position choisie arrive par --track-index, posee par main.js : le CSS
   ne peut pas savoir quelle option est la 3e.

   La largeur d'un cran se deduit de la geometrie du conteneur :
     espace pris par les marges = 2 paddings + (n - 1) gaps, tous en --space-4
     donc pour 5 options : 6 x --space-4 ; pour 2 options : 3 x --space-4
   ========================================================= */
.segmented,
.play-tabs-inner {
  position: relative;
  display: flex;
  gap: var(--space-4);
  padding: var(--space-4);
  background: var(--background-secondary);
  border-radius: var(--radius-full);
}

.segmented::before,
.play-tabs-inner::before {
  content: "";
  position: absolute;
  top: var(--space-4);
  bottom: var(--space-4);
  left: var(--space-4);
  border-radius: var(--radius-full);
  background: var(--background-accent);
  /* 100% = la largeur de l'indicateur lui-meme, donc un cran exactement */
  transform: translateX(calc(var(--track-index, 0) * (100% + var(--space-4))));
  transition: transform var(--duration-base) var(--ease-in-out);
}
/* 5 options : 2 paddings + 4 gaps = 6 x --space-4 */
.segmented::before          { width: calc((100% - 6 * var(--space-4)) / 5); }
/* 3 options : 2 paddings + 2 gaps = 4 x --space-4 */
.segmented--3::before       { width: calc((100% - 4 * var(--space-4)) / 3); }
/* 2 options : 2 paddings + 1 gap  = 3 x --space-4 */
.play-tabs-inner::before    { width: calc((100% - 3 * var(--space-4)) / 2); }

/* Les libelles passent au-dessus de l'indicateur. */
.segmented-option,
.play-tab {
  position: relative;
  z-index: 1;
  flex: 1;
  border: none;
  background: transparent;
  color: var(--text-primary);
  border-radius: var(--radius-full);
  font-family: var(--font-heading), sans-serif;
  font-size: var(--font-size-body);
  font-weight: 700;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
.segmented-option { padding: var(--space-12) var(--space-8); line-height: 1; }
.play-tab { padding: var(--space-12); }


/* L'option choisie ne porte plus de fond : l'indicateur est venu sous elle.
   Son survol reste transparent, sinon un voile clair passerait sur le citron. */
.segmented-option.is-active,
.play-tab.is-active { color: var(--text-on-accent); }

/* Interrupteur (minuteur on/off) */
.toggle {
  position: relative;
  flex: none;
  width: 52px;
  height: 30px;
  border: none;
  padding: 0;
  border-radius: var(--radius-full);
  background: var(--background-secondary);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out);
}
.toggle[aria-checked="true"] { background: var(--background-accent); }
.toggle-knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 24px;
  height: 24px;
  border-radius: var(--radius-full);
  background: var(--background-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform var(--duration-fast) var(--ease-out), background var(--duration-fast) var(--ease-out);
}
.toggle[aria-checked="true"] .toggle-knob {
  transform: translateX(22px);
  /* le rond reste bleu nuit, la coche est blanche pour ressortir sur le jaune */
}
/*
  Icone du bouton : 12px pour tenir dans un rond de 24.
  A cette taille, le trace de la grille 24 est reduit de moitie, et son trait
  avec : on le repaissit pour retrouver l'epaisseur PERCUE des autres icones.
*/
.toggle-ico {
  width: 12px;
  height: 12px;
  stroke-width: 4;
  color: var(--text-primary);
}
.toggle[aria-checked="true"] .toggle-ico--off { display: none; }
.toggle[aria-checked="false"] .toggle-ico--on { display: none; }

/* 32px entre le contenu du reglage et son bouton principal */
#btn-start { margin-top: var(--space-32); }

/* =========================================================
   ECRANS INTERNES (titre, listes, jeu)
   ========================================================= */
.panel-title {
  font-family: var(--font-heading), sans-serif;
  font-size: var(--font-size-title);
  font-weight: 700;
  margin-bottom: var(--space-16);
}

.actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
}
/* Selection (mobile) : toute la page defile, les boutons restent fixes en bas d'ecran */
#view-selection {
  padding-bottom: var(--footer-clear, 190px); /* place pour le pied fixe + 32px */
}
#view-selection .actions {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 20;
  background: var(--background-primary);
  padding: var(--space-16) var(--space-24)
           calc(var(--space-24) + env(safe-area-inset-bottom, 0px));
}

/* Selection : grille de barres slate avec bouton "Relancer" */
.category-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-8);
}
/*
  Padding asymetrique, et c'est voulu : a droite le bouton "Relancer" a le
  meme arrondi que la barre, leurs courbes s'emboitent et 16px suffisent.
  A gauche le libelle est plat contre une courbe, il lui faut plus d'air
  pour paraitre a la meme distance du bord. Alignement optique, pas
  geometrique.
*/
.category-item {
  display: flex;
  align-items: center;
  gap: var(--space-12);
  padding: var(--space-12) var(--space-16) var(--space-12) var(--space-24);
  border-radius: var(--radius-full);
  background: var(--background-secondary);
}
.category-label {
  flex: 1;
  min-width: 0;
  font-size: var(--font-size-body);
  font-weight: 700;
}

/*
  Relance : seul le LIBELLE change, la ligne ne bouge pas. Sur "Relancer tout",
  --swap-delay (pose par main.js) decale chaque ligne d'un cran, ce qui rend
  lisible le fait que tout a change plutot qu'une seule categorie.
*/
@keyframes label-swap {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.category-label.is-swapped {
  animation: label-swap var(--duration-fast) var(--ease-out) var(--swap-delay, 0ms) both;
}
/*
  Relancer : un bouton rond a icone seule.

  Le mot "Relancer" repete sur chaque ligne saturait l'ecran pour une action
  identique partout. L'icone suffit des lors qu'elle est comprehensible, et
  le libelle survit dans `aria-label` : un lecteur d'ecran annonce toujours
  "Relancer la categorie Sport".

  Fond navy sur la barre slate : le bouton se creuse au lieu de ressortir,
  et le citron reste la couleur de l'action.
*/
.category-reroll {
  flex: none;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--background-primary);
  color: var(--background-accent);
  border: none;
  border-radius: var(--radius-full);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out);
}

/* Referentiel et categories figees : pastilles en ligne, pas de grille */
.category-list--locked,
.category-list--catalog {
  display: flex;
  flex-wrap: wrap;
}
.category-item--locked,
.category-item--catalog {
  padding: var(--space-12) var(--space-16);
  font-size: var(--font-size-body);
  font-weight: 700;
}

/* Referentiel : une liste qu'on parcourt, elle reste en retrait. */
.category-item--catalog { background: var(--background-secondary); }

/*
  En session, les categories comptent autant que la lettre : elles prennent
  donc le meme bleu qu'elle. Texte en navy, l'off-white sur ce bleu ne donne
  que 2,6:1 (voir --text-on-accent dans le README).
*/
.category-item--locked {
  background: var(--background-accent-secondary);
  color: var(--text-on-accent);
}
/* Le referentiel suit une legende, pas un titre : on lui remet 16px au-dessus */
.category-list--catalog { margin-top: var(--space-16); }

/* Referentiel : titre + sous-texte forment un bloc d'en-tete serre (4px),
   puis 16px classiques jusqu'aux tags (via .category-list--catalog). */
#view-catalog .panel-title { margin-bottom: var(--space-4); }
#catalog-count { margin-top: 0; }

/* =========================================================
   JEU
   ========================================================= */
.play-columns {
  display: flex;
  flex-direction: column;
  gap: var(--space-16);
}
.play-col {
  display: flex;
  flex-direction: column;
}
/* Espacement des blocs de la colonne lettre (16px, hors bouton d'action) */
.play-col .timer-bar,
.play-col .play-box { margin-top: var(--space-16); }

/* Mobile : seul l'onglet actif est visible ; place reservee pour la barre fixe */
#view-play[data-tab="letter"] #play-panel-categories { display: none; }
#view-play[data-tab="categories"] #play-panel-letter { display: none; }
#view-play { padding-bottom: var(--footer-clear, 120px); }

/*
  Etiquette de section de l'ecran de jeu : "Lettre de la manche", "Timer",
  "Lettres deja jouees". Un seul style pour les trois, defini ici, sinon ils
  divergent au fil des retouches. Seule la marge est propre a chacun.
*/
.letter-label,
.play-label,
.timer-bar-label {
  font-size: var(--font-size-body);
  font-weight: 400;
  color: var(--text-muted);
}
.play-label { margin-bottom: var(--space-16); }

/* Cartes slate (lettre, historique) */
.letter-panel,
.play-box {
  background: var(--background-secondary);
  color: var(--text-primary);
  border-radius: var(--radius-l);
  padding: var(--space-24);
}
.letter-panel {
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-16);
}
/*
  La zone de la lettre garde TOUJOURS la meme hauteur, quel que soit son
  contenu : une lettre, un mot, rien. Sans cela le panneau se contracterait
  a chaque fois, et toute la colonne remonterait sous les yeux du joueur.
  `min-height` vaut la taille de la lettre : avec `line-height: 1`, une
  ligne de texte occupe exactement sa taille de police.
*/
.letter {
  align-self: stretch;
  min-height: var(--font-size-display);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-heading), sans-serif;
  font-weight: 700;
  font-size: var(--font-size-display);
  line-height: 1;
  color: var(--background-accent-secondary); /* la lettre en bleu cornflower */
  letter-spacing: 0.04em;
}

/* Avant le premier tirage : meme place, meme couleur, meme graisse que la
   lettre. Seule la taille change, parce qu'un mot est plus large qu'une lettre. */
.letter.is-waiting {
  font-size: var(--font-size-display-small);
}

/*
  Le tirage : le seul moment du jeu qui merite d'etre appuye.
  Trois etapes plutot qu'une courbe, pour maitriser exactement le depassement :
  la lettre arrive petite, depasse legerement sa taille, puis se pose.
  Classe posee puis retiree par main.js a chaque nouvelle lettre.
*/
@keyframes letter-in {
  from { opacity: 0; transform: scale(0.86); }
  60%  { opacity: 1; transform: scale(1.04); }
  to   { opacity: 1; transform: scale(1); }
}
.letter.is-new {
  animation: letter-in var(--duration-slow) var(--ease-out) both;
}

/* Le chip de la manche s'allume en meme temps que la lettre. */
@keyframes chip-in {
  from { opacity: 0; transform: scale(0.7); }
  to   { opacity: 1; transform: scale(1); }
}
.letter-chip.is-current {
  animation: chip-in var(--duration-base) var(--ease-out) both;
}

/* Barre du minuteur */
.timer-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-12);
  background: var(--background-secondary);
  border-radius: var(--radius-m);
  padding: var(--space-16) var(--space-24);
}
/*
  Le decompte, en gros : c'est ce que le joueur surveille.

  Hauteur CONSTANTE, dans les deux etats. Le padding vertical et le rayon
  sont poses en permanence, meme sans fond visible : seule la couleur
  apparait quand le temps expire. Sinon le tag d'alerte pousserait la barre
  vers le bas en surgissant, et toute la colonne bougerait sous les yeux.
  Le `min-height` se deduit des tokens (la taille du texte plus ses marges),
  il ne sort pas d'un reglage a l'oeil.
*/
.timer-bar-value {
  display: flex;
  align-items: center;
  min-height: calc(var(--font-size-title-large) + 2 * var(--space-8));
  padding-block: var(--space-8);
  border-radius: var(--radius-full); /* meme arrondi que les boutons */
  font-family: var(--font-heading), sans-serif;
  font-weight: 700;
  font-size: var(--font-size-title-large);
  line-height: 1;
}

/* Temps ecoule : le fond apparait, la geometrie ne bouge pas.
   Texte plus petit que le decompte : c'est une phrase, pas un nombre,
   et elle doit tenir sur une ligne meme sur un petit telephone. */
.timer-bar-value.is-expired {
  background: var(--background-alert);
  color: var(--text-inverse);
  padding-inline: var(--space-16);
  font-size: var(--font-size-body);
}

/* Historique des lettres : pastilles rondes pleines */
.letter-history { display: flex; flex-wrap: wrap; gap: var(--space-8); }
.letter-chip {
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
  background: var(--background-primary);
  color: var(--text-primary);
  font-family: var(--font-heading), sans-serif;
  font-weight: 700;
  font-size: var(--font-size-body);
}
.letter-chip.is-current {
  background: var(--background-accent-secondary); /* lettre courante en cornflower */
  color: var(--text-on-accent); /* navy : l'off-white sur ce bleu ne passait pas (2,6:1) */
}

/* Bouton "Nouvelle session" en haut de colonne : pilule bordee compacte avec fleche */
.play-newsession {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: var(--space-8);
  background: transparent;
  border: var(--border-width) solid var(--border-primary);
  color: var(--text-primary);
  border-radius: var(--radius-full);
  padding: var(--space-12) var(--space-16);
  margin-bottom: var(--space-16);
  font-family: var(--font-heading), sans-serif;
  font-size: var(--font-size-body);
  font-weight: 700;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out);
}

/* Onglets (mobile) : barre fixe en bas d'ecran */
.play-tabs {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 20;
  background: var(--background-primary);
  padding: var(--space-16) var(--space-24)
           calc(var(--space-24) + env(safe-area-inset-bottom, 0px));
}
/* Le style des onglets vit avec celui du segmented : meme mecanique,
   voir la section "PISTE A CHOIX UNIQUE" plus haut. */

/* =========================================================
   SURVOL  --  regroupe ici, et protege du tactile.

   `@media (hover: hover) and (pointer: fine)` limite ces regles aux
   appareils qui ont un vrai pointeur. Sans ce garde, un ecran tactile
   applique le survol au tap et le laisse COLLE jusqu'au tap suivant :
   un bouton resterait agrandi apres avoir ete touche.

   PAS d'agrandissement au survol : `transform: scale()` sur un element qui
   contient du texte le rend FLOU. Le navigateur ne redessine pas les glyphes
   a la nouvelle taille, il etire l'image deja tracee. Sur un survol, qui dure
   tant que la souris reste la, le texte reste flou : c'est intenable. Au clic
   c'est different, l'etat ne dure que le temps de l'appui.

   Le survol passe donc par la couleur seule. Sur le citron, l'intensite est
   doublee (--state-hover-on-light) : melanger 8% de sombre dans du quasi-blanc
   ne se voit presque pas.
   ========================================================= */
@media (hover: hover) and (pointer: fine) {
  /* Fonds : une intensite appliquee sur la couleur de base (voir README). */
  .btn-accent:hover { background: color-mix(in srgb, var(--background-accent), var(--text-on-accent) var(--state-hover-on-light)); }
  .btn-ghost:hover { background: color-mix(in srgb, transparent, var(--text-primary) var(--state-hover)); }
  .back-btn:hover { background: color-mix(in srgb, var(--background-secondary), var(--text-primary) var(--state-hover)); }
  .stepper-btn:not(:disabled):hover { background: color-mix(in srgb, transparent, var(--text-primary) var(--state-hover)); }
  .category-reroll:hover { background: color-mix(in srgb, var(--background-primary), var(--text-primary) var(--state-hover)); }
  .play-newsession:hover { background: color-mix(in srgb, transparent, var(--text-primary) var(--state-hover)); }

  .segmented-option:hover,
  .play-tab:hover { background: color-mix(in srgb, transparent, var(--text-primary) var(--state-hover)); }

  /* L'option choisie a deja l'indicateur citron sous elle : un voile
     clair par-dessus le ternirait. */
  .segmented-option.is-active:hover,
  .play-tab.is-active:hover { background: transparent; }
}

/* =========================================================
   RETOUR TACTILE  --  regroupe ici volontairement.

   Sur mobile il n'y a pas de survol : l'enfoncement est le SEUL signal
   qui confirme que le clic a ete recu. Assez leger pour etre ressenti
   sans etre remarque.

   Cette regle est placee apres les composants pour l'emporter a
   specificite egale : elle complete leur `transition` au lieu de la
   remplacer, sans avoir a modifier huit declarations.
   ========================================================= */
.btn,
.back-btn,
.stepper-btn,
.segmented-option,
.toggle,
.category-reroll,
.play-newsession,
.play-tab {
  transition: background var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--ease-out);
}

.btn:active,
.back-btn:active,
.stepper-btn:not(:disabled):active,
.segmented-option:active,
.toggle:active,
.category-reroll:active,
.play-newsession:active,
.play-tab:active {
  transform: scale(0.97);
}

/* =========================================================
   GRAND ECRAN : cartes flottantes centrees
   ========================================================= */
@media (min-width: 640px) {
  .screen {
    justify-content: center;
    align-items: center;
    padding: var(--space-32);
  }
  .screen::before { display: none; } /* pas de header flexible en desktop */
  .card {
    width: 100%;
    max-width: var(--card-max-s);
    min-height: auto;      /* hauteur de contenu */
    border-radius: var(--radius-xl); /* desktop : coins arrondis sur les 4 cotes */
    padding: var(--space-48);
  }

  /* La selection a besoin de plus de largeur pour ses deux colonnes */
  #view-selection {
    max-width: var(--card-max-m);
    padding-bottom: var(--space-48); /* pied en flux, pas de pied fixe */
  }

  /*
    Le referentiel etale ses tags sur toute la largeur disponible.

    Il a droit au palier le plus large parce que son contenu est une LISTE a
    parcourir des yeux, pas un texte a lire ligne apres ligne. Plus il y a de
    tags par rangee, moins il faut defiler. Les ecrans de jeu, eux, restent a
    1200px : au-dela, les deux colonnes s'eloignent trop l'une de l'autre.

    La largeur reste fluide : la carte prend toute la place jusqu'a 1800px,
    et les 32px de marge de `.screen` empechent qu'elle touche les bords.
  */
  #view-catalog {
    max-width: var(--card-max-xl);
    padding-bottom: var(--space-48);
  }

  /* 32px entre le contenu et les boutons d'action */
  #btn-start { margin-top: var(--space-32); }
  #view-selection .actions {
    position: static;
    margin-top: var(--space-32);
    padding: 0;
    background: transparent;
  }

  .actions { flex-direction: row; }
  .actions .btn { flex: 1; }
  .category-list {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-12);
    align-items: center;
  }
  /* Nombre impair de categories : la derniere occupe toute la largeur */
  #category-list .category-item:last-child:nth-child(odd) { grid-column: 1 / -1; }

  /* Jeu : 1200px, deux colonnes cote a cote, pas d'onglets */
  #view-play {
    max-width: var(--card-max-l);
    padding-bottom: var(--space-48);
  }
  .play-columns {
    flex-direction: row;
    align-items: flex-start;
    gap: var(--space-32);
  }
  .play-col { flex: 1; }
  #view-play[data-tab="letter"] #play-panel-categories,
  #view-play[data-tab="categories"] #play-panel-letter { display: flex; }
  .play-tabs { display: none; }
  .play-newsession-letter { display: none; }
}
