html,
body {
  height: 100%;
  margin: 0;
}

body {
  width: 100%;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* Ce que la page dépense AUTOUR du cadre : deux marges, l'espace qui
     le sépare du bandeau des génies, et le bandeau lui-même. C'est
     autant de moins pour le cadre, dont la hauteur est bornée par ce qui
     reste — d'où des valeurs serrées, pour ne laisser du décor étoilé
     qu'un liseré. Mesuré à 1600×900 : 91 px de dépense avant, 52 après.
     Le bandeau, lui, garde sa taille : il doit rester lisible. */
  gap: 1vh;
  box-sizing: border-box;
  padding: 0.8vh 0;
  background-image: url("/images/giphy2.gif");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  font-family: "Arial";
  overflow: hidden;
}

/* Cadre de jeu : ratio d'image verrouillé à 16/9 (ratio des images de
   fond du jeu) et toujours entièrement visible ("letterboxé"), quelle
   que soit la forme de l'écran (mobile portrait, tablette, desktop
   ultra-large...). "container-type: size" transforme le cadre en
   repère pour les unités "cqw"/"cqh" utilisées par ses enfants : leur
   taille reste ainsi une fraction fixe du cadre lui-même, à n'importe
   quelle taille d'écran, sans avoir besoin d'un fichier CSS différent
   par résolution (l'ancien système à base de "zoom").

   LE RATIO 16/9 NE SE LIBÈRE JAMAIS, quelle que soit la place qu'on
   croirait y gagner : les positions des œufs sont des pourcentages de ce
   cadre, la détection de collision mesure le rendu réel, et les cinq
   décors de jeu sont des images 16/9. Ce qui se règle, ce sont les deux
   bornes ci-dessous — jamais la forme.

   Bornes poussées à la demande d'Erwan, pour ne laisser du fond étoilé
   qu'un liseré. Elles ne mordent pas sur les mêmes écrans : sur un 16/9
   c'est la hauteur qui retient le cadre, sur un 16/10 c'est la largeur.
   Mesures de couverture de l'écran, avant puis après :

     1600×900 (16/9)   81,0 %  ->  86,5 %
     1920×1200 (16/10) 79,5 %  ->  86,4 %

   93dvh et pas davantage : sous le cadre vivent le bandeau des génies et
   les marges du "body", et "overflow: hidden" ne préviendrait pas — le
   bandeau serait simplement coupé. Le calcul de ce qui reste est au-dessus
   du "body". Toucher à l'un sans l'autre casse la page. */
.cadre {
  position: relative;
  width: min(98vw, calc(93vh * 16 / 9));
  width: min(98vw, calc(93dvh * 16 / 9));
  aspect-ratio: 16 / 9;
  max-width: 1900px;
  container-type: size;
  font-size: 0.85cqw;
  background-image: url("/images/background-menu.jpg");
  background-size: cover;
  background-position: center;
  border: 0px solid rgb(0, 0, 0);
  border-radius: 25px;
}

/* Titre du jeu, en haut du cadre. Centré sur le CADRE et non sur la
   fenêtre, et dimensionné en "cqw" comme le reste du menu : il garde
   ainsi exactement la même place dans le décor à n'importe quelle taille
   d'écran. Le bouton des règles occupe le coin haut gauche, le titre
   prend le centre.
   "pointer-events: none" : le titre est du décor, il ne doit jamais
   intercepter un clic destiné à ce qui se trouve dessous. */
.titre-jeu {
  position: absolute;
  top: 2.5%;
  left: 50%;
  transform: translateX(-50%);
  z-index: 20;
  margin: 0;
  color: #ffffff;
  font-family: Verdana, sans-serif;
  font-size: clamp(18px, 4.4cqw, 62px);
  font-weight: bold;
  letter-spacing: 0.16em;
  line-height: 1.1;
  white-space: nowrap;
  /* Le mot « Calcul » tombe pile sur le rayon de lumière du décor, une
     zone presque blanche où du texte blanc simplement ombré se noyait.
     D'où ces deux protections :
     - un contour sombre complet (huit décalages autour de la lettre),
       exprimé en "em" pour qu'il grossisse avec le titre ;
     - un voile sombre en dégradé radial, qui éteint le fond juste
       derrière le titre. Le dégradé s'efface avant les bords : pas de
       rectangle visible, et rien ne se voit du côté sombre du cadre.
     Le halo bleu, lui, reste là pour l'allure, pas pour la lisibilité. */
  text-shadow:
    0.035em 0 0.02em #060a14,
    -0.035em 0 0.02em #060a14,
    0 0.035em 0.02em #060a14,
    0 -0.035em 0.02em #060a14,
    0.025em 0.025em 0.02em #060a14,
    -0.025em 0.025em 0.02em #060a14,
    0.025em -0.025em 0.02em #060a14,
    -0.025em -0.025em 0.02em #060a14,
    0 0.04em 0.14em rgba(0, 0, 0, 0.9),
    0 0 0.55em rgba(121, 187, 255, 0.85);
  background: radial-gradient(
    ellipse at center,
    rgba(4, 8, 18, 0.62) 0%,
    rgba(4, 8, 18, 0.42) 45%,
    rgba(4, 8, 18, 0) 75%
  );
  /* Un peu plus de marge à gauche qu'à droite : l'espacement des
     lettres n'ajoute du vide qu'après le dernier caractère, et le titre
     paraîtrait décalé sans cette compensation. */
  padding: 0.22em 1.1em 0.28em 1.26em;
  pointer-events: none;
}

/* Choix de la langue : coin haut DROIT du cadre, en face du bouton des
   règles, de part et d'autre du titre. Codes à deux lettres plutôt que
   drapeaux : un drapeau désigne un pays, pas une langue, et quatre
   pastilles restent lisibles là où quatre drapeaux minuscules ne le
   seraient pas. */
.choix-langue {
  position: absolute;
  top: 3%;
  right: 3%;
  z-index: 40;
  display: flex;
  gap: clamp(3px, 0.5cqw, 7px);
}

.langue {
  padding: clamp(3px, 0.4cqh, 6px) clamp(5px, 0.7cqw, 10px);
  border: 1px solid #337bc4;
  border-radius: 8px;
  background: rgba(20, 18, 25, 0.65);
  color: #ffffff;
  font-family: Verdana, sans-serif;
  font-weight: bold;
  font-size: max(10px, 1.15cqw);
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s ease;
}

.langue:hover {
  background: rgba(121, 187, 255, 0.5);
}

.langue:focus-visible {
  outline: 2px solid #79bbff;
  outline-offset: 2px;
}

.langue.actif {
  background: linear-gradient(to bottom, #79bbff 5%, #378de5 100%);
  border-color: #ffffff;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.35);
}

/* Les commandes, une par ligne, sans ligne vide entre elles. */
.regles-commandes span {
  display: block;
}

/* Bouton "Règles du jeu" : ancré dans le coin haut GAUCHE du cadre de jeu
   lui-même (le cadre est le repère de positionnement), donc toujours
   parfaitement aligné avec son bord. Côté gauche pour ne jamais croiser
   le bouton "Jouer", qui est du côté droit. Taille en "cqw" (bornée par
   clamp()) : elle suit fidèlement la taille du cadre à tout écran. */
.box {
  position: absolute;
  top: 3%;
  left: 3%;
  right: auto;
  color: #ffffff;
  width: clamp(150px, 15cqw, 320px);
  height: clamp(38px, 2.7cqw, 56px);
  font-size: clamp(0.8rem, 1.05cqw, 1.35rem);
  box-sizing: border-box;
  background: rgba(20, 18, 25, 0.65);
  border: 2px solid #b17b64;
  border-radius: 25px;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.5);
  cursor: pointer;
  z-index: 30;
  transition: background 0.2s ease, box-shadow 0.2s ease;
}

.box:hover {
  background: rgba(35, 30, 45, 0.9);
  box-shadow: 0 3px 14px rgba(0, 0, 0, 0.65);
}

/* Le bouton est un lien : ni soulignement, ni couleur de lien visité.
   Le texte est centré dans la pastille par le flex, et non par une
   "line-height" calquée sur la hauteur — celle-ci se décalait dès que le
   libellé passait sur deux lignes.

   Il portait autrefois une animation : quatre traits qui se dessinaient
   au survol, et le libellé qui glissait pour laisser place à un message
   d'accueil. Elle est retirée. Les traits étaient à angles droits sur
   une pastille arrondie de 25 px, et l'écart se voyait aux coins ; mais
   surtout, elle annonçait un panneau qui s'ouvrait au survol, alors que
   ce bouton mène désormais à une page. Une animation qui promet autre
   chose que ce qui arrive vaut mieux retirée que corrigée. */
.box {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 0.8em;
  text-align: center;
  font-weight: 600;
  text-decoration: none;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Bas du cadre : le menu d'avant-partie et le bouton "Jouer", empilés.
   Le bloc est ancré au BAS du cadre ("bottom") et non par le haut : il
   grandit donc vers le haut quand le menu s'allonge, et conserve le même
   pied de page à toute taille d'écran. C'est aussi ce qui garantit que
   le bouton ne sort jamais du cadre — il était auparavant placé à 78 %
   du haut, une hauteur qui ne laissait plus la place de l'afficher en
   entier sur un cadre aplati. */
.bas-de-cadre {
  position: absolute;
  left: 70%;
  bottom: 5%;
  transform: translateX(-50%);
  /* Un bloc en absolu ancré à "left: 70 %" ne peut, par défaut, occuper
     que la place restant à sa droite — 30 % du cadre. Le menu tombait
     pile sur ce plafond à 1200 px de large, mais le dépassait en dessous :
     les pastilles d'opérations débordaient alors de leurs colonnes et se
     chevauchaient deux à deux. "max-content" lui rend sa largeur
     naturelle, que le centrage répartit de part et d'autre de l'axe. */
  width: max-content;
  max-width: 94cqw;
  z-index: 40;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(8px, 1.6cqh, 20px);
}

/* Menu d'avant-partie : opérations à travailler et niveau de départ.
   Mêmes codes visuels que le panneau des règles — fond sombre
   translucide et filet cuivré — pour qu'il se lise comme un élément du
   jeu et non comme un ajout. */
.menu-partie {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(6px, 1cqh, 12px);
  padding: clamp(8px, 1.4cqh, 16px) clamp(12px, 1.6cqw, 22px);
  background: rgba(15, 14, 20, 0.82);
  border: 1px solid #b17b64;
  border-radius: 12px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);
  text-align: center;
}

.menu-bloc {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(4px, 0.8cqh, 10px);
}

.menu-titre {
  color: #ffffff;
  font-family: Verdana, sans-serif;
  font-weight: bold;
  font-size: max(11px, 1.5cqw);
  letter-spacing: 0.04em;
}

/* Les quatre opérations sur deux colonnes : en une seule ligne, le
   panneau deviendrait plus large que le cadre sur un écran étroit. */
.menu-operations {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(4px, 0.7cqw, 10px);
}

/* Chaque opération est une pastille cochable. La case elle-même est
   masquée (mais toujours présente et focalisable, donc utilisable au
   clavier et annoncée par un lecteur d'écran) : c'est la pastille qui
   montre l'état, via ":has". */
/* Largeur fixée, et non déduite du mot le plus long : sans ça, le menu
   changeait de taille d'une langue à l'autre — « Multiplicaciones » est
   plus large que « Multiplikation ». En "em", elle suit la taille du
   texte, donc celle du cadre. */
.operation {
  position: relative;
  width: 10.7em;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.5em;
  padding: clamp(4px, 0.5cqw, 8px) clamp(8px, 0.9cqw, 14px);
  border: 1px solid #337bc4;
  border-radius: 999px;
  background: rgba(55, 141, 229, 0.25);
  color: #ffffff;
  font-family: Verdana, sans-serif;
  font-size: max(10px, 1.25cqw);
  line-height: 1;
  cursor: pointer;
  user-select: none;
  transition: background 0.15s ease;
}

.operation:hover {
  background: rgba(121, 187, 255, 0.5);
}

.operation-case {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  margin: 0;
  pointer-events: none;
}

/* Le nom ne passe jamais à la ligne : il occupe la place qui reste dans
   la pastille, et serait tronqué plutôt que de la faire grandir. */
.operation-nom {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.operation-symbole {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6em;
  height: 1.6em;
  flex: 0 0 auto;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.35);
  font-weight: bold;
}

/* Opération retenue : même dégradé que le bouton "Jouer", pour que
   "coché" se voie d'un coup d'oeil et pas seulement à la nuance de
   fond. */
.operation:has(.operation-case:checked) {
  background: linear-gradient(to bottom, #79bbff 5%, #378de5 100%);
  border-color: #ffffff;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.35);
}

.operation:has(.operation-case:focus-visible) {
  outline: 2px solid #79bbff;
  outline-offset: 2px;
}

/* Choix du personnage : le dessin lui-même sert de pastille, avec son
   nom dessous. Voir la tête qu'on va incarner en dit plus long qu'une
   étiquette « Neutre / Garçon / Fille ». */
.menu-personnages {
  display: flex;
  gap: clamp(4px, 0.7cqw, 10px);
}

/* Largeur fixée pour la même raison que les pastilles d'opérations : sans
   elle, une pastille mesurait 54 px en turc (« Kız ») et 104 px en russe
   (« Нейтральный »), et les trois cases changeaient de taille d'une langue
   à l'autre. En "em", elle suit la taille du texte, donc celle du cadre. */
.personnage {
  width: 8.5em;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3em;
  padding: clamp(3px, 0.4cqw, 6px) clamp(5px, 0.6cqw, 10px);
  border: 1px solid #337bc4;
  border-radius: 10px;
  background: rgba(55, 141, 229, 0.25);
  color: #ffffff;
  font-family: Verdana, sans-serif;
  font-size: max(9px, 1.05cqw);
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s ease;
}

/* Hauteur exprimée en "cqh" comme le personnage dans le jeu : la
   vignette garde la même proportion vis-à-vis du cadre à tout écran.
   "aspect-ratio" (celui des trois dessins) réserve la largeur avant même
   que l'image ne soit chargée : sans lui, les vignettes naissent larges
   de zéro et le menu se réorganise sous le curseur au chargement — un
   clic lancé au mauvais moment tombait à côté du bouton visé. */
.personnage img {
  display: block;
  height: max(40px, 7cqh);
  width: auto;
  aspect-ratio: 4 / 5;
}

/* Le nom ne passe jamais à la ligne : il serait tronqué plutôt que de
   faire grandir la pastille — sinon la hauteur redeviendrait tributaire
   de la langue. */
.personnage span {
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  /* La pastille pose "line-height: 1" pour que sa hauteur ne dépende pas
     de la langue. Appliqué au nom, ce réglage donne une boîte haute comme
     la police elle-même : les jambages passaient dessous et "overflow:
     hidden" les coupait — le « g » d'« Origine » était rogné. Une
     interligne en "em" ne rend pas la hauteur tributaire de la langue,
     elle laisse seulement la place aux lettres qui descendent. */
  line-height: 1.25;
}

.personnage:hover {
  background: rgba(121, 187, 255, 0.5);
}

.personnage:focus-visible {
  outline: 2px solid #79bbff;
  outline-offset: 2px;
}

.personnage.actif {
  background: linear-gradient(to bottom, #79bbff 5%, #378de5 100%);
  border-color: #ffffff;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.35);
}

.menu-niveaux {
  display: flex;
  gap: clamp(4px, 0.7cqw, 10px);
}

/* Les pastilles de niveau reprennent le dégradé du bouton "Jouer", en
   plus sobre : c'est lui qui doit rester l'action principale. */
.niveau {
  width: max(26px, 3.1cqw);
  height: max(26px, 3.1cqw);
  border-radius: 50%;
  border: 1px solid #337bc4;
  background: rgba(55, 141, 229, 0.25);
  color: #ffffff;
  font-family: Verdana, sans-serif;
  font-weight: bold;
  font-size: max(11px, 1.5cqw);
  cursor: pointer;
  padding: 0;
  line-height: 1;
  transition: background 0.15s ease, transform 0.15s ease;
}

.niveau:hover {
  background: rgba(121, 187, 255, 0.5);
}

.niveau:focus-visible {
  outline: 2px solid #79bbff;
  outline-offset: 2px;
}

.niveau.actif {
  background: linear-gradient(to bottom, #79bbff 5%, #378de5 100%);
  border-color: #ffffff;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.35);
}

.menu-note {
  color: #d8c3b5;
  font-family: Verdana, sans-serif;
  font-size: max(9px, 1.05cqw);
  max-width: 26cqw;
  line-height: 1.35;
  /* Deux lignes réservées : la phrase en tient deux en français, en
     espagnol et en allemand, mais une seule en anglais. Sans cette
     réserve, tout le menu remontait de 17 px en passant à l'anglais. */
  min-height: 2.7em;
}

/* Page de création de compte. Elle reprend le cadre, le titre et les
   pastilles de langue de l'accueil ; seul le panneau du formulaire lui
   est propre. Il est centré dans le cadre et non ancré en bas, n'ayant
   pas de bouton « Jouer » sous lui. */
.panneau-compte {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 40;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: clamp(6px, 1cqh, 12px);
  width: min(30cqw, 92cqw);
  min-width: 260px;
  max-height: 76cqh;
  overflow-y: auto;
  padding: clamp(10px, 1.6cqh, 20px) clamp(14px, 1.8cqw, 26px);
  background: rgba(15, 14, 20, 0.86);
  border: 1px solid #b17b64;
  border-radius: 12px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);
  color: #ffffff;
  font-family: Verdana, sans-serif;
}

/* L'inscription est le plus long des formulaires : pseudo, adresse, mot
   de passe, sa redite, date de naissance. À 76cqh il se mettait à
   défiler — mesuré à 1280×720 : 556 px de contenu pour 492 de place.
   Il lui en faut donc 86 ; on lui en donne 88, et le panneau reste bien
   à l'intérieur du cadre (65 px au-dessus, 29 en dessous).

   Sélecteur qualifié plutôt que règle déplacée : ".panneau-compte" est
   juste au-dessus, et à spécificité égale c'est l'ordre qui trancherait —
   le genre de chose qui se casse au premier bloc remué. */
.panneau-compte.panneau-inscription {
  max-height: 88cqh;
}

.panneau-titre {
  margin: 0 0 0.2em;
  text-align: center;
  font-size: max(13px, 1.9cqw);
  letter-spacing: 0.04em;
}

.champ {
  display: flex;
  flex-direction: column;
  gap: 0.25em;
}

.champ-nom {
  font-size: max(10px, 1.15cqw);
  font-weight: bold;
}

.champ input {
  width: 100%;
  box-sizing: border-box;
  padding: clamp(5px, 0.7cqh, 9px) clamp(6px, 0.7cqw, 10px);
  border: 1px solid #337bc4;
  border-radius: 8px;
  background: rgba(20, 18, 25, 0.75);
  color: #ffffff;
  font-family: Verdana, sans-serif;
  font-size: max(11px, 1.2cqw);
}

/* Enveloppe du champ de mot de passe : elle sert de repère au petit
   oeil, posé à l'intérieur du champ, à droite. */
.champ-mot-de-passe {
  position: relative;
  display: block;
}

/* La place de l'oeil est retirée au texte, sinon un long mot de passe
   passerait dessous. */
.champ-mot-de-passe input {
  padding-right: max(30px, 3cqw);
}

.oeil {
  position: absolute;
  right: 0;
  top: 0;
  height: 100%;
  width: max(30px, 3cqw);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  background: none;
  color: #d8c3b5;
  cursor: pointer;
}

.oeil:hover {
  color: #ffffff;
}

.oeil:focus-visible {
  outline: 2px solid #79bbff;
  outline-offset: -2px;
  border-radius: 6px;
}

/* Traits seuls, sans remplissage : le dessin reste lisible à 14 px comme
   à 24. "currentColor" le fait suivre la couleur du bouton, donc le
   survol. */
.oeil svg {
  width: max(15px, 1.5cqw);
  height: max(15px, 1.5cqw);
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.champ input:focus-visible {
  outline: 2px solid #79bbff;
  outline-offset: 1px;
}

/* Un champ refusé se signale par le trait ET par le message dessous :
   la couleur seule ne dirait rien à qui la distingue mal. */
.champ input.en-erreur {
  border-color: #ff8f8f;
  box-shadow: 0 0 0 1px rgba(255, 143, 143, 0.6);
}

/* Zone commune à l'aide et au message d'erreur, sous chaque champ. Sa
   hauteur est réservée, et elle est présente même là où il n'y a rien à
   dire — sans quoi les champs sans aide se collaient au suivant : les
   écarts mesuraient 32, 6 et 31 px d'un champ à l'autre.
   Deux lignes, parce que ces textes en prennent deux dans certaines
   langues et une seule dans d'autres : la hauteur ne doit dépendre ni de
   la langue, ni de la présence d'une erreur. */
.champ-note {
  display: block;
  min-height: 2.6em;
  font-size: max(9px, 1cqw);
  line-height: 1.3;
}

/* L'erreur prend la place de l'aide au lieu de s'ajouter dessous : rien
   ne se décale quand elle apparaît. */
.champ:has(.champ-erreur:not(:empty)) .champ-aide {
  display: none;
}

.champ-aide {
  color: #d8c3b5;
}

.champ-erreur {
  color: #ffb3b3;
}

.champ-erreur:empty {
  display: none;
}

.compte-message {
  margin: 0;
  text-align: center;
  font-size: max(10px, 1.1cqw);
  line-height: 1.35;
}

.compte-message:empty {
  display: none;
}

.compte-message.en-echec {
  color: #ffb3b3;
}

.compte-message.en-reussite {
  color: #9ce8b0;
  font-weight: bold;
}

/* Compte créé : il ne reste que le message et le retour à l'accueil. */
.compte-cree .champ,
.compte-cree .panneau-titre,
.compte-cree .myButton {
  display: none;
}

/* Le bouton reprend l'allure de celui de l'accueil mais pas sa largeur
   fixe : « Jouer » tient en un mot, « Créer mon compte » en trois, et le
   libellé passait sur deux ou trois lignes selon la langue — le panneau
   changeait alors de hauteur. Il occupe donc toute la largeur du panneau,
   et son texte tient sur une ligne quelle que soit la langue. */
/* Sélecteur qualifié à dessein : ".myButton" est déclaré plus bas dans
   ce fichier et l'emporterait à spécificité égale, imposant sa largeur
   fixe. */
.panneau-compte .bouton-compte {
  align-self: stretch;
  width: auto;
  margin-top: 0.3em;
  white-space: nowrap;
}

.lien-retour {
  align-self: center;
  color: #d8c3b5;
  font-size: max(9px, 1.05cqw);
  text-decoration: underline;
}

.lien-retour:hover {
  color: #ffffff;
}

/* Case « rester connecté » : la case elle-même reste visible, à la
   différence des pastilles d'opérations — c'est un réglage ordinaire de
   formulaire, pas un bouton du jeu. */
.champ-case {
  display: flex;
  align-items: center;
  gap: 0.5em;
  font-size: max(10px, 1.1cqw);
  cursor: pointer;
}

.champ-case input {
  width: max(13px, 1.2cqw);
  height: max(13px, 1.2cqw);
  accent-color: #378de5;
  cursor: pointer;
}

/* Phrase d'explication en tête de formulaire. */
.compte-intro {
  margin: 0 0 0.4em;
  color: #d8c3b5;
  font-size: max(9px, 1.05cqw);
  line-height: 1.4;
  text-align: center;
  /* Trois lignes réservées : cette phrase en tient trois dans les six
     langues à la largeur habituelle du panneau, mais deux seulement sur
     un écran plus large. Sans la réserve, le panneau changerait de
     hauteur selon la langue et selon l'écran. */
  min-height: 4.2em;
}

/* Ligne du bas des formulaires : « Pas encore de compte ? » et son lien. */
.compte-bas {
  margin: 0;
  text-align: center;
  color: #d8c3b5;
  font-size: max(9px, 1.05cqw);
  line-height: 1.4;
}

.compte-bas a {
  color: #ffffff;
  text-decoration: underline;
}

.compte-bas a:hover {
  color: #79bbff;
}

/* COLONNE DU JOUEUR, à gauche : qui il est, ce qu'il porte, et les trois
   portes qui s'ouvrent depuis le menu.

   Elle fait pendant au menu de partie, ancrée de la même façon — même
   bas, même largeur naturelle, axe symétrique (30 % contre 70 %) — pour
   que les deux colonnes se lisent comme une paire et non comme un bloc
   plus un reste. Tout ce qu'elle contient était auparavant éparpillé :
   la salutation sous le titre, la tenue dans le menu de partie, les trois
   accès dans un bandeau au ras du bas. */
.colonne-joueur {
  position: absolute;
  left: 30%;
  bottom: 5%;
  transform: translateX(-50%);
  /* Largeur FIXÉE, et non "max-content" : la colonne est centrée sur son
     axe, si bien qu'une largeur dictée par le texte déplacerait ses deux
     bords à chaque changement de langue. Mesuré avant de la fixer : de
     179 px en anglais à 214 en turc, sur un cadre de 1488. La valeur
     tient la plus bavarde des six, et le plancher en pixels garde les
     libellés lisibles sur un petit cadre. */
  width: max(150px, 15cqw);
  max-width: 44cqw;
  z-index: 40;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(6px, 1cqh, 12px);
  padding: clamp(8px, 1.4cqh, 16px) clamp(12px, 1.6cqw, 22px);
  background: rgba(15, 14, 20, 0.82);
  border: 1px solid #b17b64;
  border-radius: 12px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);
  text-align: center;
}

/* Les trois accès, l'un sous l'autre et à la même largeur : en ligne,
   ils fixaient la largeur de toute la colonne sur la langue la plus
   bavarde. Empilés, c'est le plus long des trois qui décide, et les
   autres s'y alignent. */
.bandeau-joueur {
  align-self: stretch;
  display: flex;
  flex-direction: column;
  gap: clamp(4px, 0.6cqh, 8px);
}

/* Salutation, en tête de la colonne. Elle vivait auparavant en absolu
   sous le titre du jeu ; c'est la colonne qui la place désormais. */
.bonjour {
  margin: 0;
  color: #ffffff;
  font-family: Verdana, sans-serif;
  font-size: max(10px, 1.4cqw);
  font-weight: bold;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.85);
  white-space: nowrap;
  pointer-events: none;
}

/* Solde d'étoiles, une ligne sous la salutation. */
.solde-etoiles {
  /* Un peu plus discret que la salutation : c'est une information, pas un
     accueil. La hauteur de ligne est fixe pour que la mise en page ne
     bouge pas d'une langue à l'autre — « Étoiles », « Yıldız » et
     « Звёзды » n'ont pas la même longueur, mais occupent la même place. */
  font-size: max(9px, 1.15cqw);
  font-weight: normal;
  opacity: 0.9;
}

/* Bouton de déconnexion. Il ne porte QUE son allure : c'est le bandeau
   qui le place. Il gardait auparavant le positionnement absolu du lien
   isolé qu'il a remplacé, si bien qu'il sortait du bandeau et se posait
   par-dessus la salutation. */
.acces-compte {
  padding: clamp(5px, 0.8cqh, 10px) clamp(8px, 1.1cqw, 16px);
  border: 1px solid #b17b64;
  border-radius: 8px;
  background: rgba(20, 18, 25, 0.72);
  color: #ffffff;
  font-family: Verdana, sans-serif;
  font-size: max(10px, 1.1cqw);
  text-decoration: none;
  transition: background 0.15s ease;
}

.acces-compte:hover {
  background: rgba(121, 187, 255, 0.5);
}

.acces-compte:focus-visible {
  outline: 2px solid #79bbff;
  outline-offset: 2px;
}

/* Sur un cadre peu haut (téléphone, ou fenêtre très aplatie), le menu ne
   tient plus entre la planète et le bouton « Jouer ». On le resserre :
   les deux blocs passent côte à côte, les opérations se réduisent à leur
   symbole sur une seule ligne, et la note disparaît — la règle des
   génies reste énoncée dans le panneau des règles.
   Une "container query" plutôt qu'un media query : ce qui compte est la
   place disponible dans le cadre, pas la taille de l'écran. */
@container (max-height: 320px) {
  /* Le haut du cadre ne peut pas porter à la fois le bouton des règles
     (150 px au minimum, soit près de la moitié de la largeur), le titre
     et les quatre langues. Les langues descendent donc juste sous le
     bouton des règles, dans la bande restée libre au-dessus du menu. */
  .choix-langue {
    top: 25%;
    right: auto;
    left: 3%;
    gap: 3px;
  }

  .langue {
    padding: 2px 4px;
    font-size: 10px;
  }

  /* La colonne du joueur est haute : salutation, étoiles, vignette de
     tenue et trois accès empilés ne tiennent pas dans un cadre aplati.
     Elle se resserre au lieu de se déplacer — les trois accès repassent
     en ligne, et la vignette disparaît : elle ne règle rien, et la tenue
     portée se voit de toute façon dès le début de la partie. */
  .colonne-joueur {
    /* Le bas du cadre est entièrement occupé par le menu de partie : la
       colonne y passerait dessous et deviendrait inatteignable. Elle
       rejoint la bande restée libre sous le titre, à droite — les
       pastilles de langue occupent le côté gauche de cette bande. */
    left: auto;
    right: 3%;
    /* Sous le titre, qui passe à droite lui aussi sur un cadre aplati et
       descend jusqu'à 15 % de la hauteur — mesuré. */
    top: 17%;
    bottom: auto;
    transform: none;
    width: max-content;
    max-width: 46cqw;
    gap: 2px;
    /* Plus de panneau ici, seulement l'empilement : entre le titre et le
       menu de partie il ne reste que 55 px sur un cadre de 207, et le
       cadre du panneau — bordure, ombre, marges intérieures — en coûtait
       20 à lui seul. Mesuré : 73 px avec, 53 sans. */
    padding: 0;
    background: none;
    border: 0;
    box-shadow: none;
  }

  .colonne-joueur .menu-bloc {
    display: none;
  }

  .bandeau-joueur {
    align-self: auto;
    flex-direction: row;
    gap: 5px;
  }

  .bonjour {
    font-size: 10px;
  }

  .solde-etoiles {
    font-size: 9px;
  }

  .acces-compte {
    padding: 2px 5px;
    font-size: 10px;
  }

  /* Le bouton des règles ne descend pas en dessous de 150 px de large :
     sur un cadre étroit il occupe déjà près de la moitié du haut, et un
     titre centré viendrait le percuter. Le titre passe donc à droite,
     dans le coin resté libre au-dessus du menu. */
  .titre-jeu {
    left: auto;
    right: 3%;
    transform: none;
    font-size: max(13px, 4.4cqw);
    letter-spacing: 0.1em;
  }

  .bas-de-cadre {
    /* Recentré sur le cadre : disposé en ligne, le menu est trop large
       pour rester aligné sur l'axe du bouton « Jouer » (70 %) sans
       dépasser le bord droit. */
    left: 50%;
    bottom: 4%;
    gap: 6px;
  }

  .menu-partie {
    max-width: 92cqw;
    flex-direction: row;
    align-items: center;
    gap: 6px;
    padding: 5px 7px;
  }

  .menu-note {
    display: none;
  }

  .menu-titre {
    font-size: 10px;
    max-width: 8em;
    line-height: 1.15;
    /* Trois lignes réservées : resserrés à 8 em, ces titres tiennent sur
       une à trois lignes selon la langue — « Действия для тренировки » en
       prend trois là où « Character » n'en prend qu'une. Sans cette
       réserve, le menu changeait de hauteur en passant au russe. */
    min-height: 3.45em;
  }

  /* Colonnes dimensionnées sur leur contenu ("auto"), et blocs qui ne
     se laissent pas comprimer : en fractions égales de la largeur
     restante, les quatre pastilles tombaient à 13 px de large et les
     symboles débordaient les uns sur les autres. */
  .menu-bloc {
    flex: 0 0 auto;
  }

  .menu-operations {
    grid-template-columns: repeat(4, auto);
    gap: 4px;
  }

  .operation {
    width: auto;
    padding: 2px;
    font-size: 11px;
  }

  .personnage {
    width: auto;
    padding: 2px 3px;
  }

  .personnage img {
    height: 22px;
  }

  /* Trois groupes de boutons sur une seule ligne, dans un cadre qui peut
     ne faire que 350 px de large : les pastilles de niveau et les écarts
     se resserrent, faute de quoi le menu touche les deux bords. */
  .menu-niveaux,
  .menu-personnages {
    gap: 3px;
  }

  .niveau {
    width: 22px;
    height: 22px;
    font-size: 10px;
  }

  /* Seuls les dessins et les symboles restent : ce sont eux qui
     identifient le choix, et les noms en toutes lettres restent
     lisibles par un lecteur d'écran. */
  .personnage span,
  .operation-nom {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* Cadre minuscule — un téléphone tenu debout, où le 16/9 ne laisse que
   207 px de haut. La bande libre entre le titre et le menu de partie n'y
   fait plus que 55 px, et la colonne du joueur en demande 57 même
   dépouillée de son panneau. La salutation s'efface : le joueur sait
   comment il s'appelle, tandis que son solde d'étoiles et les trois
   accès, eux, servent à quelque chose. */
@container (max-height: 240px) {
  #bonjour {
    display: none;
  }
}

/* Bouton "Jouer" : simplement posé sous le menu, dans le bloc du bas,
   qui se charge du centrage (les réglages en absolu qu'il portait
   auparavant obligeaient à tenir à la main sa position ET celle du
   menu, à deux endroits différents du fichier). */
.myButton {
  width: clamp(120px, 12.5cqw, 170px);
  box-shadow: 3px 4px 0px 0px #1564ad;
  background: linear-gradient(to bottom, #79bbff 5%, #378de5 100%);
  background-color: #79bbff;
  border-radius: 5px;
  border: 1px solid #337bc4;
  display: inline-block;
  cursor: pointer;
  color: #ffffff;
  font-family: Verdana;
  font-size: clamp(15px, 2.1cqw, 28px);
  font-weight: bold;
  /* Marges latérales resserrées. Elles valaient 3,2cqw, soit 38 px de
     chaque côté d'un bouton large de 150 : il ne restait que 73 px au
     texte. « Play » (60 px) y tenait, mais « Jouer » et « Jugar » (79 px)
     débordaient de 4 px vers la droite et « Spielen » (104 px) de 17 px —
     le mot n'était plus centré, il était poussé hors de sa boîte. La
     largeur du bouton, elle, ne change pas d'un pixel : "border-box" fait
     que ces marges se prennent dedans. */
  padding: clamp(6px, 0.9cqw, 12px) clamp(6px, 1.2cqw, 16px);
  text-decoration: none;
  text-shadow: 0px 1px 0px #528ecc;
  box-sizing: border-box;
}
.myButton:hover {
  background: linear-gradient(to bottom, #378de5 5%, #79bbff 100%);
  background-color: #378de5;
}
.myButton:active {
  /* Léger effet "enfoncé" au clic : un décalage via transform, pas via
     top/position, pour ne pas déplacer le bloc entier (ça faisait
     sauter le bouton et annulait le clic). */
  transform: translateY(1px);
}

/* Bandeau "Les génies sont" : élément indépendant du cadre (placé sous
   lui dans le flux flexbox de "body"), dimensionné en "vw" borné par
   clamp() pour rester lisible et ne jamais dépasser la largeur de
   l'écran, y compris sur mobile. */
#ticker {
  position: relative;
  background-color: #fff;
  overflow: hidden;
  height: clamp(24px, 3.2vh, 34px);
  line-height: clamp(24px, 3.2vh, 34px);
  vertical-align: middle;
  width: min(92vw, 700px);
  box-sizing: border-box;
  border-radius: 25px;
  font-size: clamp(13px, 1.6vw, 22px);
  flex-shrink: 0;
}
#ticker ul {
  display: block;
  padding: 0px;
  line-height: inherit;
  vertical-align: middle;
  margin: 0px;
  list-style: none;
  white-space: nowrap;
  animation: scroll 10s linear 0s infinite;
  animation-direction: alternate;
  position: absolute;
  border-radius: 25px;
  width: 100%;
}
#ticker ul li {
  display: inline-block;
  white-space: normal;
  margin-left: 20px;
}
#ticker .title {
  background-color: rgb(1, 176, 207);
  color: #fff;
  position: absolute;
  left: 0;
  font-weight: bold;
  border-right: 2px solid #fff;
  top: 0;
  display: block;
  height: 100%;
  vertical-align: middle;
  line-height: inherit;
  padding-left: 10px;
  padding-right: 10px;
  z-index: 10;
  box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.8);
  border-radius: 10px;
  box-sizing: border-box;
}
@keyframes scroll {
  from {
    transform: translate(100%, 0);
  }

  to {
    transform: translate(-150%, 0);
  }
}

/* --- Règles du jeu ---------------------------------------------------

   Même panneau que la boutique et « Mon compte », et pour la même raison
   qu'eux : hauteur FIXE, sans quoi il changerait de taille en passant de
   l'onglet des règles à celui des étoiles, qui n'ont pas la même longueur
   de texte. Plus large aussi — un règlement se lit mal en colonne
   étroite. Placé APRÈS ".panneau-compte", dont il reprend le sélecteur :
   à spécificité égale, c'est l'ordre qui tranche. */
.panneau-compte.panneau-regles {
  /* Plus LARGE que les autres panneaux, et c'est le vrai levier contre
     le défilement : un texte qui dispose de la largeur tient sur moins
     de lignes. Élargir de 46 à 58cqw fait plus pour la hauteur que
     n'importe quel réglage vertical. */
  width: min(58cqw, 94cqw);
  height: 78cqh;
  /* Même raison que « Mon compte » : passer sous le titre du jeu. */
  top: 56%;
}

/* Le texte défile DANS la section, et non dans le panneau : la barre
   d'onglets et le retour au menu restent ainsi en place, quel que soit
   l'onglet et quelle que soit la langue. */
.regles-section {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  font-size: max(9px, 1.05cqw);
  line-height: 1.6;
  color: #e8dcd4;
  text-align: left;
}

.regles-section p {
  margin: 0 0 0.9em;
}

.regles-section p:last-child {
  margin-bottom: 0;
}

/* Le barème, tel qu'il est réellement appliqué : le tableau est construit
   à partir de bareme.js, le fichier que lit aussi le serveur. */
.bareme {
  width: 100%;
  margin: 0 0 0.9em;
  border-collapse: collapse;
  text-align: center;
}

.bareme caption {
  margin-bottom: 0.4em;
  color: #ffd97a;
  font-weight: bold;
  text-align: left;
}

.bareme th,
.bareme td {
  padding: 0.35em 0.2em;
  border: 1px solid rgba(177, 123, 100, 0.55);
}

.bareme thead th {
  background: rgba(177, 123, 100, 0.22);
  color: #ffffff;
}

.bareme tbody th {
  color: #ffffff;
}

.bareme tbody td {
  color: #ffd97a;
}

/* --- Boutique -------------------------------------------------------

   L'étal reprend le panneau des formulaires de compte, élargi : six
   tenues ne tiennent pas dans la largeur d'un champ de saisie. Les règles
   qui suivent sont volontairement placées APRÈS ".panneau-compte" — à
   spécificité égale, c'est la dernière qui l'emporte, et deux corrections
   ont déjà été annulées silencieusement pour avoir été écrites plus haut
   dans ce fichier. */
/* C'EST L'ÉTAL QUI DÉFILE, PAS LE PANNEAU. Le commentaire de
   ".panneau-boutique" l'annonçait sans que rien ne l'applique : le
   panneau, à hauteur fixe, se mettait à défiler dès que les cartes
   grandissaient — la pièce de monnaie l'a fait une fois, les noms sur
   deux lignes une seconde. À chaque fois il fallait rehausser la valeur,
   et le panneau se rapprochait du bas du cadre.

   La grille prend désormais la place qui reste et défile seule. La barre
   d'onglets et le retour au menu ne bougent plus, et le catalogue peut
   s'allonger sans qu'on ait à retoucher quoi que ce soit. */
.panneau-boutique #etal {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.panneau-boutique .boutique-etal {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

/* La garde-robe reprend l'étal de la boutique — mêmes cartes, même
   grille — mais pas sa hauteur fixe : elle ne montre que ce qu'on
   possède, et n'a pas d'onglets entre lesquels rester stable. */
.panneau-personnages {
  width: min(56cqw, 94cqw);
}

.panneau-boutique {
  width: min(56cqw, 94cqw);
  /* HAUTEUR FIXE, comme « Mon compte » : les deux onglets n'ont pas le
     même nombre d'articles — dix tenues contre un service — et le panneau
     changeait de taille en passant de l'un à l'autre. Une hauteur imposée
     règle la question une fois pour toutes, y compris le jour où le
     catalogue s'allongera : c'est l'étal qui défilera, pas le panneau qui
     grandira.

     70cqh suffisaient tant que les prix s'écrivaient en toutes lettres ;
     la pièce a fait grandir chaque ligne de prix, et l'étal demandait 41
     px de plus qu'il n'en avait. La valeur rejoint donc celle de « Mon
     compte » — ces deux panneaux ont désormais la même géométrie, ce qui
     vaut mieux que deux réglages voisins et différents. */
  height: 76cqh;
  /* Descendu sous le titre du jeu, comme « Mon compte » et les règles :
     centré, son bord haut tombait sur le titre, qui descend à 14,3 %. */
  top: 56%;
}

/* Le solde porte un nombre qui change de longueur ; il est centré et sur
   sa propre ligne, donc rien ne bouge autour de lui. */
.boutique-solde {
  margin: 0;
  font-size: max(11px, 1.4cqw);
  color: #ffd97a;
}

/* Un montant : la pièce puis le nombre, sur une ligne, centrés ensemble.
   La classe est posée par monnaie.js, et vaut partout où un montant
   s'affiche — solde du menu, prix de l'étal, compteur de la partie. Le
   "gap" tient l'écart plutôt qu'un espace dans le texte : celui-ci
   disparaîtrait au retour à la ligne. */
.montant {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.3em;
}

/* La pièce de monnaie du jeu. Sa hauteur est donnée en "em" : elle suit
   la taille du texte à côté duquel elle se pose, du solde en grand aux
   prix en petit, sans avoir de règle par emplacement.

   "flex-shrink: 0" parce qu'une pièce écrasée n'est plus ronde : dans
   une carte étroite, la grille la comprimait avant de rogner le nombre. */
.monnaie {
  height: 1.15em;
  width: auto;
  flex-shrink: 0;
  /* Pour les endroits où la pièce se pose dans une ligne de texte plutôt
     que dans un montant — le titre du tableau du barème : sans ce
     décalage, elle repose sur la ligne de base et dépasse par le haut. */
  vertical-align: -0.25em;
}

/* Grille plutôt que rangée souple : le nombre de colonnes suit la largeur
   disponible, et les cartes gardent toutes la même taille quelle que soit
   la longueur du nom traduit.

   La taille de police est posée ICI, sur la grille, et non seulement sur
   les cartes : le "9em" de la colonne se mesure sur cet élément-ci. Sans
   elle, il héritait de la police minuscule du cadre (3 px), la colonne
   minimale tombait à 29 px et l'étal s'affichait sur un téléphone en six
   colonnes de 38 px, tous les noms tronqués. */
.boutique-etal {
  display: grid;
  /* "auto-fill" et non "auto-fit" : ce dernier fait disparaître les
     colonnes vides, si bien qu'une section n'ayant qu'un seul article
     voyait sa carte s'étirer sur toute la largeur. Avec "auto-fill", les
     colonnes restent en place et la carte garde sa taille. */
  grid-template-columns: repeat(auto-fill, minmax(9em, 1fr));
  gap: clamp(6px, 0.9cqw, 12px);
  font-size: max(9px, 1cqw);
}

/* Aucune dimension ne dépend du texte : c'est ce qui garantit que l'étal
   a la même allure en russe et en turc qu'en français. */
.boutique-tenue {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35em;
  padding: clamp(4px, 0.6cqw, 9px);
  border: 1px solid #337bc4;
  border-radius: 10px;
  background: rgba(55, 141, 229, 0.25);
  font-family: Verdana, sans-serif;
  /* Héritée de la grille, et non redéclarée : les deux doivent rester
     égales, sinon la largeur des colonnes ne correspond plus à celle des
     cartes qu'elles contiennent. */
  font-size: inherit;
  line-height: 1;
}

.boutique-tenue.actif {
  border-color: #ffffff;
  background: rgba(121, 187, 255, 0.4);
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.35);
}

/* Même précaution que pour les vignettes de personnage : "aspect-ratio"
   réserve la place avant que l'image ne soit chargée, sinon l'étal se
   réorganise sous le curseur et un clic tombe à côté du bouton visé. */
.boutique-tenue img {
  display: block;
  height: max(38px, 6.5cqh);
  width: auto;
  aspect-ratio: 4 / 5;
}

/* Le nom ne passe jamais à la ligne : il serait tronqué plutôt que de
   faire grandir la carte — sinon la hauteur redeviendrait tributaire de
   la langue. */
/* Le nom d'une TENUE tient sur une ligne : « Azur », « Or », « Spectre »
   sont courts dans les six langues, et une seconde ligne réservée pour
   rien ferait défiler la grille des dix tenues. */
.boutique-nom {
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: #ffffff;
}

/* Le nom d'un SERVICE, lui, a droit à deux lignes. « Changement de
   pseudo » s'affichait « Changement de p… » en français comme en turc.
   La réserve est posée par type d'article et non pour tout l'étal : les
   cartes doivent avoir la même hauteur À L'INTÉRIEUR d'un onglet, pas
   d'un onglet à l'autre, et les tenues n'ont pas besoin de cette place.

   Deux lignes réservées, et non une hauteur qui s'adapte : sans la
   réserve, une carte au nom court serait plus basse que sa voisine dès
   qu'un second service s'ajoutera. */
.boutique-bonus .boutique-nom {
  min-height: 2.4em;
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: normal;
  line-height: 1.2;
  overflow-wrap: anywhere;
}

/* La ligne du prix reste en place même vide, une fois la tenue acquise :
   sans cette hauteur réservée, les cartes achetées seraient plus courtes
   que les autres et la grille sauterait à chaque achat. */
.boutique-prix {
  /* Réservée sur la hauteur de la pièce, et non sur celle du texte : la
     ligne est vide pour une tenue déjà acquise, et sans cette réserve
     les cartes n'auraient pas toutes la même hauteur. */
  min-height: 1.15em;
  color: #ffd97a;
}

.boutique-action {
  width: 100%;
  padding: 0.45em 0.2em;
  border: 1px solid #337bc4;
  border-radius: 8px;
  background: linear-gradient(to bottom, #79bbff 5%, #378de5 100%);
  color: #ffffff;
  font-family: inherit;
  font-size: inherit;
  line-height: 1;
  cursor: pointer;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.boutique-action:hover:not(:disabled) {
  background: linear-gradient(to bottom, #a3d1ff 5%, #4f9bea 100%);
}

.boutique-action:focus-visible {
  outline: 2px solid #79bbff;
  outline-offset: 2px;
}

/* Trop cher, ou déjà portée : le bouton reste lisible mais visiblement
   inerte. Le masquer laisserait croire que la tenue n'existe pas. */
.boutique-action:disabled {
  background: rgba(120, 120, 130, 0.5);
  border-color: #6b6b76;
  color: #d8d8de;
  cursor: default;
}

.boutique-action-portee {
  background: rgba(121, 187, 255, 0.45);
  border-color: #ffffff;
  color: #ffffff;
}

/* --- Validation de l'adresse ---------------------------------------- */

/* L'adresse à laquelle le message est parti. Centrée et sur sa propre
   ligne : elle est longue et varie, rien ne doit bouger autour d'elle. */
.validation-adresse {
  margin: 0;
  text-align: center;
  font-family: Verdana, sans-serif;
  font-size: max(10px, 1.15cqw);
  color: #ffd97a;
  overflow-wrap: anywhere;
}

/* Le lien donné à l'écran tant qu'aucun courriel ne part réellement. Il
   disparaît le jour où l'envoi devient vrai — c'est le serveur qui en
   décide, cette règle ne fait que l'habiller. */
.validation-local {
  margin: 0;
  padding: clamp(6px, 0.9cqh, 12px);
  border: 1px dashed #b17b64;
  border-radius: 8px;
  background: rgba(20, 18, 25, 0.5);
  font-family: Verdana, sans-serif;
  font-size: max(9px, 1cqw);
  color: #d8d8de;
  text-align: center;
}

.validation-local a {
  display: block;
  margin-top: 0.4em;
  color: #79bbff;
  overflow-wrap: anywhere;
}

/* Un bouton qui doit avoir l'air d'un lien : la déconnexion, action
   secondaire au bas de la page. */
.lien-nu {
  padding: 0;
  border: 0;
  background: none;
  color: #79bbff;
  font-family: inherit;
  font-size: inherit;
  text-decoration: underline;
  cursor: pointer;
}

/* Onglets — l'étal de la boutique (tenues, services) et les sections de
   « Mon compte » (pseudo, adresse, mot de passe). Écrits une fois pour
   les deux : le second usage ne devait pas recopier quarante lignes.
   Largeur fixée en "em", pour la même raison que les pastilles du menu :
   sans elle, la barre changerait de taille d'une langue à l'autre. */
.onglets {
  display: flex;
  justify-content: center;
  gap: clamp(4px, 0.6cqw, 9px);
  margin-bottom: clamp(6px, 0.9cqh, 12px);
}

/* Trois onglets ne tiennent pas en 8em chacun dans la largeur du panneau
   de « Mon compte ». Ils s'y partagent donc la largeur en parts égales :
   c'est encore plus stable que le "em" d'une langue à l'autre, puisque
   c'est le panneau — et non le texte — qui décide. */
.onglets-egaux .onglet {
  width: auto;
  flex: 1 1 0;
  min-width: 0;
}

.onglet {
  width: 8em;
  padding: 0.5em 0.2em;
  border: 1px solid #337bc4;
  border-radius: 8px 8px 0 0;
  border-bottom-width: 2px;
  background: rgba(20, 18, 25, 0.6);
  color: #d8d8de;
  font-family: Verdana, sans-serif;
  font-size: max(10px, 1.15cqw);
  font-weight: bold;
  line-height: 1;
  cursor: pointer;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  transition: background 0.15s ease;
}

.onglet:hover:not(.actif) {
  background: rgba(121, 187, 255, 0.35);
}

.onglet:focus-visible {
  outline: 2px solid #79bbff;
  outline-offset: 2px;
}

.onglet.actif {
  background: linear-gradient(to bottom, #79bbff 5%, #378de5 100%);
  border-color: #ffffff;
  color: #ffffff;
}

/* Un bonus n'a pas de dessin : une icône tient la place, à la même
   hauteur qu'une vignette pour que les deux grilles s'accordent. */
.boutique-icone {
  display: flex;
  align-items: center;
  justify-content: center;
  height: max(38px, 6.5cqh);
  aspect-ratio: 4 / 5;
  font-size: max(20px, 3.5cqh);
  line-height: 1;
  color: #ffd97a;
}

/* Combien on en possède. La ligne reste en place à zéro, sans quoi les
   cartes n'auraient pas toutes la même hauteur. */
.boutique-combien {
  min-height: 1em;
  color: #9fd3a0;
}

/* Un bonus se rachète : sa carte ne prend jamais l'état « portée ». */
.boutique-bonus {
  border-color: #b17b64;
  background: rgba(177, 123, 100, 0.18);
}

/* --- Mon compte ------------------------------------------------------ */

/* Le pseudo et l'adresse d'aujourd'hui : des valeurs, centrées sur leur
   propre ligne pour que rien ne bouge autour d'elles quand elles
   changent de longueur. */
.compte-ligne {
  margin: 0;
  text-align: center;
  font-family: Verdana, sans-serif;
  font-size: max(10px, 1.1cqw);
  color: #ffd97a;
  overflow-wrap: anywhere;
}

/* HAUTEUR FIXE du panneau, demandée par Erwan : les trois onglets n'ont
   pas le même nombre de champs — un pour le pseudo, deux pour l'adresse,
   trois pour le mot de passe — et le panneau changeait de taille sous le
   curseur en passant de l'un à l'autre. Il garde désormais la même,
   celle du plus fourni (mesuré à 1280×720 : 49,0cqh de section, 75,1 de
   panneau) ; les onglets plus courts laissent du vide sous eux, ce qui
   vaut mieux qu'un panneau qui saute.

   Une hauteur et non une réserve sur les sections : le jour où un champ
   s'ajoutera quelque part, c'est cette seule valeur qui sera à revoir. */
.panneau-compte.panneau-mon-compte {
  height: 76cqh;
  /* DESCENDU sous le titre du jeu, qui descend jusqu'à 14,3 % de la
     hauteur du cadre : centré, un panneau de cette taille commençait à
     10,3 % et mordait dessus. Le panneau étant centré sur son axe, c'est
     l'axe qu'on déplace — 56 % pose son bord haut à 16,3 %. */
  top: 56%;
}

/* Une section d'onglet : pseudo, adresse, ou mot de passe. Elle reprend
   l'empilement du panneau, dont elle n'est qu'un morceau.

   Ce qui est vérifié par ailleurs, et qui compte autant : une même
   section fait la MÊME hauteur dans les six langues — mesuré à 1280×720,
   identique du français au russe. */
.compte-section {
  display: flex;
  flex-direction: column;
  gap: clamp(6px, 1cqh, 12px);
}

/* Indispensable : ".compte-section" pose "display: flex", qui l'emporte
   sur le "display: none" que le navigateur applique de lui-même à un
   élément "hidden". Sans cette ligne, les trois sections s'afficheraient
   toutes en même temps. Placée APRÈS, à spécificité supérieure. */
.compte-section[hidden] {
  display: none;
}

/* Ce que coûte le prochain changement. Le ton change avec la situation :
   informatif quand c'est possible, plus sourd quand il faut attendre. */
.compte-cout {
  margin: 0;
  text-align: center;
  font-family: Verdana, sans-serif;
  font-size: max(9px, 1cqw);
  line-height: 1.4;
  color: #9fd3a0;
}

.compte-cout.en-attente {
  color: #d8b48c;
}

/* La date et l'heure du prochain changement gratuit, quand celui du mois
   est déjà pris. En ROUGE, à la demande d'Erwan : c'est la seule ligne de
   la page qui annonce une porte fermée, et elle doit se distinguer de la
   ligne de coût juste au-dessus.

   Le même rouge que les erreurs de saisie — clair et non saturé, il reste
   lisible sur le panneau sombre là où un rouge pur vibrerait.

   Vide, la ligne ne prend aucune place : le panneau est à hauteur fixe,
   rien ne bouge autour d'elle quand elle paraît ou disparaît. */
.compte-prochain {
  color: #ffb3b3;
  font-weight: bold;
}

.compte-prochain:empty {
  display: none;
}

/* Le choix « payer plutôt que d'user mon changement gratuit ». Il se lit
   comme une précision sur le prix, pas comme une saisie : même taille et
   même couleur que la ligne de coût qu'il complète. */
.compte-choix {
  align-self: center;
  font-size: max(9px, 1cqw);
  line-height: 1.4;
  color: #9fd3a0;
  text-align: left;
}

/* Indispensable, et pour la même raison que ".compte-section[hidden]" :
   ".champ-case" pose "display: flex", qui l'emporte sur le "display:
   none" du navigateur. Sans cette ligne, la case s'afficherait même
   quand le choix n'a pas lieu d'être. */
.compte-choix[hidden] {
  display: none;
}
