/* Tokens de docs/DESIGN.md. */
:root {
  /* Couleurs */
  --sakura: #E77F9A;
  --sakura-pale: #F9C9D4;
  --sakura-fonce: #C9607C;
  --vermillon: #E0533D;           /* réservé au mot mystère */
  --matcha: #C8E2B8;
  --matcha-fonce: #8FC27A;
  --yuzu: #FBE3A1;
  --sora: #BFDDF2;
  --fuji: #DCD0F0;
  --papier: #FBF6EE;
  --carte: #FFFDF8;
  --creme: #FFF9F1;
  --trait: #E8DFD0;
  --encre-douce: #6B6575;
  --encre: #2D2A35;
  --trait-mochi: #4A4250;
  --succes: #5E9E6E;
  --erreur: #D2554B;
  --succes-pale: #EAF4EC;

  /* Typographie */
  --police-titre: "Fraunces", Georgia, serif;
  --police-texte: "DM Sans", system-ui, sans-serif;
  --police-japonais: "Zen Maru Gothic", "Hiragino Maru Gothic ProN", sans-serif;

  /* Espacements (base 4 px) */
  --esp-2xs: 2px;
  --esp-xs: 4px;
  --esp-sm: 8px;
  --esp-md: 16px;
  --esp-lg: 24px;
  --esp-xl: 32px;
  --esp-2xl: 48px;
  --esp-3xl: 64px;

  /* Arrondis */
  --rayon-sm: 6px;
  --rayon-md: 12px;
  --rayon-lg: 20px;
  --rayon-plein: 9999px;

  /* Mouvement */
  --rebond: cubic-bezier(.3, 1.6, .5, 1);
  --court: .2s;
  --moyen: .32s;
}

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--papier) radial-gradient(rgba(45, 42, 53, .035) 1px, transparent 1px) 0 0 / 4px 4px;
  color: var(--encre);
  font-family: var(--police-texte);
  font-size: 16px;
  line-height: 1.5;
}

.page {
  max-width: 1040px;
  margin: 0 auto;
  padding: var(--esp-sm) var(--esp-sm) 0;
}

h1 {
  font-family: var(--police-titre);
  font-variation-settings: "SOFT" 100;
  font-weight: 600;
  font-size: 40px;
  margin: 0;
}

h2 {
  font-family: var(--police-titre);
  font-variation-settings: "SOFT" 100;
  font-weight: 600;
  margin: 0;
}

[lang="ja"] { font-family: var(--police-japonais); }
[hidden] { display: none !important; }
.num { font-variant-numeric: tabular-nums; }

/* En-tête */
.entete { display: flex; align-items: center; gap: var(--esp-sm); padding: var(--esp-sm) var(--esp-xs) var(--esp-md); }
.marque { font: 600 22px var(--police-titre); font-variation-settings: "SOFT" 100; color: inherit; text-decoration: none; }
.entete .actions { margin-left: auto; display: flex; gap: var(--esp-sm); }
.entete .niveau { font: 700 13px var(--police-japonais); color: var(--sakura); margin-left: 2px; }
.entete h1 { font-size: 26px; }
/* « Imprimer » n'existe qu'en largeur ordinateur : on n'imprime pas depuis un téléphone. */
.entete .imprimer { display: none; }
@media (min-width: 800px) { .entete .imprimer { display: inline-flex; } }

/* Boutons « Mochi » : un libellé ne se coupe jamais. */
.btn {
  font: 600 16px var(--police-texte); color: var(--encre); white-space: nowrap;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--esp-sm);
  min-height: 44px; padding: 11px 22px; cursor: pointer; text-decoration: none;
  background: var(--sakura-pale); border: 2.5px solid var(--trait-mochi); border-radius: var(--rayon-plein);
  box-shadow: inset 0 -5px 0 rgba(231, 127, 154, .45), 0 2px 0 rgba(74, 66, 80, .15);
  transition: transform .18s var(--rebond);
}
.btn:active { transform: scale(1.04, .92); }
.btn.secondaire { background: var(--creme); box-shadow: inset 0 -5px 0 rgba(232, 223, 208, .9); }
.btn.discret { background: none; border-color: transparent; box-shadow: none; color: var(--encre-douce); padding-inline: var(--esp-sm); }
.btn svg { width: 20px; height: 20px; flex: none; }
.btn:disabled { opacity: .5; cursor: default; }
.btn:active:disabled { transform: none; }
/* Une action qui détruit (spec 011) : même bouton, contour et texte en rouge erreur, sur papier. */
.btn.danger { background: var(--papier); color: var(--erreur); border-color: var(--erreur); box-shadow: inset 0 -5px 0 rgba(210, 85, 75, .14); }
.btn.petit { min-height: 36px; padding: 6px 14px; font-size: 14px; border-width: 2px; }
.icone {
  width: 44px; height: 44px; display: inline-grid; place-items: center; flex: none;
  border-radius: var(--rayon-plein); background: var(--creme); color: var(--trait-mochi);
  border: 2px solid var(--trait-mochi); box-shadow: inset 0 -3px 0 rgba(232, 223, 208, .9);
  transition: transform .18s var(--rebond);
}
.icone:active { transform: scale(1.06, .9); }
.icone svg { width: 22px; height: 22px; }
:focus-visible { outline: 3px solid var(--sakura); outline-offset: 2px; }

/* Mochi */
.mochi { display: inline-block; line-height: 0; flex: none; }
.mochi svg { width: 100%; height: auto; overflow: visible; }
.dit { display: flex; gap: 10px; align-items: flex-end; }
.dit .mochi { width: 48px; }
.dit p { margin: 0; background: var(--papier); border: 1.5px solid var(--trait-mochi); border-radius: 14px 14px 14px 4px; padding: 10px 14px; font-size: 15px; }
/* Par-dessus la page : son apparition ne déplace pas la grille sous le doigt. Fond trait, d'un cran
   plus foncé que le papier de la page, pour s'en détacher (#78) ; la bulle reste papier. */
.message { position: fixed; z-index: 30; top: var(--esp-sm); left: 50%; transform: translateX(-50%); width: min(520px, calc(100% - 16px)); flex-wrap: wrap;
  padding: var(--esp-sm); background: var(--trait); border-radius: var(--rayon-lg); box-shadow: 0 6px 20px -8px rgba(45, 42, 53, .35); }
.message p { flex: 1 1 220px; }

/* Bienvenue (E-1) : Mochi salue, trois cartes de niveau. */
.bienvenue { max-width: 460px; margin: 0 auto; padding: var(--esp-xl) var(--esp-sm); text-align: center; }
.bienvenue .mochi { width: 150px; }
.bienvenue h1 { font-size: 44px; margin-top: var(--esp-sm); }
.bienvenue h1 span { display: block; font: 700 20px var(--police-japonais); color: var(--sakura); letter-spacing: .12em; margin-top: 4px; }
.question { font: 600 22px var(--police-titre); font-variation-settings: "SOFT" 100; margin: var(--esp-xl) 0 var(--esp-md); }
.choix-niveau { display: grid; gap: 12px; }
.carte-niveau {
  display: flex; align-items: center; gap: 14px; padding: 16px 18px; text-align: left; cursor: pointer;
  font: inherit; color: inherit; background: var(--carte); border: 2.5px solid var(--trait-mochi); border-radius: var(--rayon-lg);
  box-shadow: inset 0 -5px 0 rgba(232, 223, 208, .9); transition: transform .18s var(--rebond);
}
.carte-niveau:active { transform: scale(1.02, .95); }
.carte-niveau .pastille { flex: none; width: 52px; height: 52px; border-radius: 16px; display: grid; place-items: center; font: 700 18px var(--police-titre); background: var(--sakura-pale); white-space: nowrap; }
.carte-niveau:nth-child(2) .pastille { background: var(--matcha); }
.carte-niveau:nth-child(3) .pastille { background: var(--yuzu); font-size: 14px; }
.carte-niveau b { display: block; font-size: 17px; }
.carte-niveau small { color: var(--encre-douce); font-size: 14px; }
.carte-niveau .exemple { margin-left: auto; font-size: 15px; color: var(--encre-douce); white-space: nowrap; }
.rassure { color: var(--encre-douce); font-size: 14px; margin-top: var(--esp-lg); }

/* Réglages (E-4) : sections titrées, contenu en cartes. */
.section-titre { font: 600 12px/1 var(--police-texte); letter-spacing: .12em; text-transform: uppercase; color: var(--encre-douce); margin: var(--esp-lg) var(--esp-xs) var(--esp-sm); }
.carte { background: var(--carte); border: 1px solid var(--trait); border-radius: var(--rayon-lg); padding: var(--esp-md); }
.carte.liste-reglages { padding: 2px var(--esp-md); }
.ligne-reglage { display: flex; align-items: center; justify-content: space-between; gap: var(--esp-md); padding: 14px 0; border-bottom: 1px solid var(--trait); }
.ligne-reglage:last-child { border-bottom: 0; }
.ligne-reglage small { display: block; color: var(--encre-douce); font-size: 13px; }
.seg { display: inline-flex; flex: none; background: var(--papier); border: 1px solid var(--trait); border-radius: var(--rayon-plein); padding: 3px; }
.seg button {
  font: 14px var(--police-texte); color: var(--encre-douce); white-space: nowrap; cursor: pointer;
  min-height: 36px; padding: 6px 11px; background: none; border: 0; border-radius: var(--rayon-plein);
}
.seg button[aria-pressed="true"] { background: var(--carte); color: var(--encre); font-weight: 600; box-shadow: 0 1px 3px rgba(45, 42, 53, .12); }
.switch { flex: none; width: 48px; height: 28px; padding: 0; cursor: pointer; border: 0; border-radius: var(--rayon-plein); background: var(--trait); position: relative; }
.switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, .2); transition: left var(--court) var(--rebond); }
.switch[aria-checked="true"] { background: var(--sakura); }
.switch[aria-checked="true"]::after { left: 23px; }
.credits { font-size: 13px; color: var(--encre-douce); line-height: 1.6; }
.credits p { margin: 0 0 var(--esp-sm); }
.credits p:last-child { margin-bottom: 0; }
.credits a { color: inherit; }
.note-grille { margin: var(--esp-sm) var(--esp-xs) 0; }
.lien-ligne { display: flex; align-items: center; justify-content: space-between; padding: 14px 0; color: inherit; text-decoration: none; }
button.lien-ligne { width: 100%; font: inherit; text-align: left; background: none; border: 0; cursor: pointer; }
.lien-ligne.remise { color: var(--encre-douce); }
.liste-reglages > .lien-ligne:not(:last-child) { border-bottom: 1px solid var(--trait); } /* même trait que .ligne-reglage */
.lien-ligne .chevron { color: var(--encre-douce); font-size: 20px; }
.compteur-pastille { background: var(--papier); border: 1px solid var(--trait); border-radius: var(--rayon-plein); padding: 1px 9px; font-size: 13px; margin-left: var(--esp-sm); color: var(--encre-douce); }

/* Mots écartés (E-6) : une ligne par mot, la date sur toute la largeur. */
.intro { color: var(--encre-douce); margin: 0 var(--esp-xs) var(--esp-md); }
.ecarte { display: grid; grid-template-columns: 92px 1fr auto; align-items: center; column-gap: var(--esp-md); row-gap: 6px; padding: 12px 0; border-bottom: 1px solid var(--trait); }
.ecarte:last-child { border-bottom: 0; }
.ecarte .jp { font: 700 20px var(--police-japonais); overflow-wrap: anywhere; }
.ecarte .jp small { display: block; font: 500 12px var(--police-japonais); color: var(--encre-douce); }
.ecarte .date { grid-column: 1 / -1; font-size: 12px; color: var(--encre-douce); }
.vide { text-align: center; padding: var(--esp-xl) var(--esp-md); }
.vide .mochi { width: 160px; }
.vide h2 { font-size: 26px; margin-top: var(--esp-md); }
.vide p { color: var(--encre-douce); max-width: 320px; margin: var(--esp-sm) auto 0; }

/* Progression (E-7) : le nombre de grilles, une jauge à deux tons par niveau, les mots difficiles. */
.haut { display: flex; align-items: center; gap: var(--esp-md); margin: 0 var(--esp-xs) var(--esp-sm); }
.haut .mochi { width: 110px; }
.grand-chiffre { font: 600 44px/1 var(--police-titre); font-variation-settings: "SOFT" 100; }
.haut small { display: block; color: var(--encre-douce); font-size: 14px; margin-top: 4px; }
.niveau-prog { padding: 14px 0; border-bottom: 1px solid var(--trait); }
.niveau-prog:last-child { border-bottom: 0; }
.niveau-prog .tete { display: flex; justify-content: space-between; align-items: baseline; gap: var(--esp-sm); margin-bottom: 8px; }
.niveau-prog .tete b { font: 600 18px var(--police-titre); }
.niveau-prog .tete span { font-size: 14px; color: var(--encre-douce); }
.jauge { position: relative; height: 14px; border-radius: var(--rayon-plein); background: var(--papier); border: 1.5px solid var(--trait-mochi); overflow: hidden; }
.jauge i { position: absolute; left: 0; top: 0; bottom: 0; border-radius: var(--rayon-plein); }
.jauge .vus { background: var(--matcha); }
.jauge .acquis { background: var(--matcha-fonce); }
.legende { display: flex; flex-wrap: wrap; gap: 4px var(--esp-md); font-size: 13px; color: var(--encre-douce); margin: var(--esp-sm) var(--esp-xs) 0; }
.legende span::before { content: ""; display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 6px; vertical-align: -1px; }
.legende .l-acquis::before { background: var(--matcha-fonce); }
.legende .l-vus::before { background: var(--matcha); }
.difficile { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 2px var(--esp-md); padding: 12px 0; border-bottom: 1px solid var(--trait); }
.difficile:last-child { border-bottom: 0; }
.difficile .jp { font: 700 20px var(--police-japonais); overflow-wrap: anywhere; }
.difficile .jp small { font: 500 13px var(--police-japonais); color: var(--encre-douce); margin-left: 6px; }
.difficile .fr { color: var(--encre-douce); font-size: 15px; }
.difficile .aides { grid-row: 1 / 3; grid-column: 2; font-size: 13px; color: var(--sakura-fonce); background: var(--sakura-pale); border-radius: var(--rayon-plein); padding: 3px 10px; white-space: nowrap; }
.vide .btn { margin-top: var(--esp-lg); }

/* Serveur injoignable (E-2, et le même écran ailleurs) : Mochi endormie à la place du contenu. */
.hors-ligne .page > :not(.entete, .injoignable) { display: none; }
.injoignable { text-align: center; padding: var(--esp-2xl) var(--esp-md); }
.injoignable .mochi { width: 170px; }
.injoignable h2 { font-size: 26px; margin-top: var(--esp-md); }
.injoignable p { color: var(--encre-douce); max-width: 340px; margin: var(--esp-sm) auto var(--esp-lg); }

/* Écran de jeu : une colonne, puis grille à gauche et liste à droite. */
/* Ni rebond de défilement ni « glisser pour revenir » du navigateur sur la page de jeu. */
html:has(.jeu), html:has(.jeu) body { overscroll-behavior: none; }
.jeu { display: grid; gap: var(--esp-md); }
.bandeau { display: flex; align-items: center; justify-content: space-between; gap: var(--esp-sm); padding: 0 var(--esp-xs); min-height: 44px; }
.compte { font-size: 14px; color: var(--encre-douce); }
.compte b { color: var(--encre); font-size: 16px; }
.zone-grille { padding-top: 22px; } /* place pour les oreilles de Mochi */


/* Grille */
.grille {
  position: relative; width: 100%; max-width: 480px; aspect-ratio: 1; margin: 0 auto;
  background: var(--carte); border: 1px solid var(--trait); border-radius: var(--rayon-md);
  touch-action: none; user-select: none; -webkit-user-select: none;
}
.cases { position: absolute; inset: 0; display: grid; grid-template-columns: repeat(var(--taille), 1fr); grid-template-rows: repeat(var(--taille), 1fr); }
.cases span {
  position: relative; z-index: 2; display: grid; place-items: center;
  font: 500 clamp(17px, 5.4vw, 24px)/1 var(--police-japonais); cursor: pointer;
  border-right: 1px dashed rgba(232, 223, 208, .8); border-bottom: 1px dashed rgba(232, 223, 208, .8);
}
.cases span.bord-droit { border-right: 0; }
.cases span.bord-bas { border-bottom: 0; }
.traits { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; --epaisseur-trait: .74; } /* lue aussi par jeu.js (contour) */
.traits line { stroke: var(--surligneur); stroke-linecap: round; stroke-width: var(--epaisseur-trait); stroke-opacity: .85; }
.traits line.dessine { stroke-dasharray: 1; animation: dessine var(--court) ease-out both; }
@keyframes dessine { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
.traits line.selection { stroke: var(--encre); stroke-opacity: .14; stroke-dasharray: .01 .22; transition: opacity var(--court) ease-in; }
.traits line.selection.efface { opacity: 0; }
/* Spec 015 : le contour de surligneur, une gélule vide en pointillé (admin). Il clignote deux
   secondes quand on vient de le demander depuis l'aide, puis reste. */
.traits rect.contour { fill: none; stroke: var(--encre-douce); stroke-width: .05; stroke-dasharray: .14 .1; pointer-events: none; }
.traits rect.contour.clignote { animation: clignote .5s ease-in-out 4 alternate; }
@keyframes clignote { to { opacity: .1; } }
/* Les cinq surligneurs : le trait d'un mot trouvé, et le fond de son étiquette. */
.hl-0 { --surligneur: var(--sakura-pale); } .hl-1 { --surligneur: var(--matcha); } .hl-2 { --surligneur: var(--yuzu); }
.hl-3 { --surligneur: var(--sora); } .hl-4 { --surligneur: var(--fuji); }
.cases span.mystere { color: var(--vermillon); font-weight: 700; }
.cases span.mystere::before { content: ""; position: absolute; inset: 3px; z-index: -1; background: #fff; border: 2px solid var(--vermillon); border-radius: var(--rayon-sm); }
.cases span.allume { animation: allume .5s var(--rebond) both; }
@keyframes allume { from { transform: scale(.5); opacity: 0; } }
/* Mot trouvé : son étiquette part une fois le trait dessiné, rebondit, reste, puis s'envole en
   fondu. Placée par jeu.js ; jamais sous le doigt. */
.etiquette {
  position: absolute; z-index: 3; pointer-events: none; text-align: center; white-space: nowrap;
  padding: 3px 12px 5px; background: var(--surligneur); color: var(--encre);
  border: 2px solid var(--trait-mochi); border-radius: 14px; box-shadow: 0 4px 12px -6px rgba(45, 42, 53, .45);
  animation: etiquette 1s var(--court) both;
}
.etiquette b { display: block; font: 700 24px/1.2 var(--police-japonais); }
.etiquette span { display: block; font: 500 13px/1.2 var(--police-texte); }
@keyframes etiquette {
  0% { opacity: 0; transform: translateY(8px) scale(.9); animation-timing-function: var(--rebond); }
  18% { opacity: 1; transform: none; }
  82% { opacity: 1; transform: none; animation-timing-function: ease-in; }
  100% { opacity: 0; transform: translateY(-14px); }
}
@keyframes etiquette-fondu { 0%, 100% { opacity: 0; } 18%, 82% { opacity: 1; } }
.grille .cachee { position: absolute; right: 8%; top: -28px; width: 58px; z-index: 0; pointer-events: none; }

/* Liste des mots : à trouver d'abord, trouvés barrés en fin. */
.liste { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--esp-sm); }
.mot { font-size: 15px; padding: 7px 13px; background: var(--carte); border: 1px solid var(--trait); border-radius: var(--rayon-plein); }
/* Un trouvé n'a plus de contour : sans réduire son espace intérieur, sa pastille invisible
   l'isolait sur sa ligne dans la colonne étroite de l'ordinateur. */
.mot.trouve { font-size: 13px; padding: 2px 8px; text-decoration: line-through; text-decoration-thickness: 1.5px; color: var(--encre-douce); border-color: transparent; background: none; }
.mot .japonais { display: inline-block; text-decoration: none; margin-left: 4px; }
button.mot { font-family: inherit; color: inherit; cursor: pointer; }
.mot.aide { border-color: var(--sakura); }
.mot.aide b { font: 700 14px var(--police-japonais); color: var(--sakura-fonce); margin-left: 6px; }
.mot.nouveau { animation: arrive var(--moyen) ease-out both; }
@keyframes arrive { from { opacity: 0; transform: translateY(8px); } }
/* La pastille des trouvés (téléphone seulement) : de la famille des pastilles, en matcha — la couleur
   de la réussite ; le sakura et le rouge se lisaient comme une erreur. */
.pastille-trouves { display: none; }
.mot.trouves { background: var(--matcha); border-color: var(--matcha-fonce); color: var(--encre); font-weight: 600; }
.pastille-trouves.nouveau { animation: arrive var(--moyen) ease-out both; }

/* Le panneau des trouvés : une ligne par mot, la couleur de son surligneur en pastille. */
.liste-trouves { list-style: none; margin: var(--esp-md) 0 0; padding: 0; }
.liste-trouves li { display: flex; align-items: baseline; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--trait); }
.liste-trouves li:last-child { border-bottom: 0; }
.liste-trouves i { flex: none; width: 12px; height: 12px; border-radius: 50%; background: var(--surligneur); border: 1.5px solid var(--trait-mochi); align-self: center; }
.liste-trouves .japonais { font: 700 18px var(--police-japonais); }
.liste-trouves .fr { margin-left: auto; padding-left: var(--esp-sm); color: var(--encre-douce); font-size: 15px; text-align: right; }

/* Panneau du bas : dans le flux et collé au bas de l'écran, la grille reste visible au-dessus. */
#panneau { display: contents; } /* le panneau colle au bas de la page entière, pas de son conteneur */
.panneau {
  position: sticky; bottom: 0; z-index: 21; max-width: 520px; margin: var(--esp-lg) auto 0;
  background: var(--carte); border: 1.5px solid var(--trait-mochi); border-bottom: 0; border-radius: 24px 24px 0 0;
  padding: var(--esp-lg) var(--esp-md); box-shadow: 0 -10px 30px -12px rgba(45, 42, 53, .3);
  animation: monte var(--moyen) ease-out both;
}
/* La poignée ne va qu'aux panneaux qui se ferment (spec 010, comportement 6) : ils suivent le doigt
   vers le bas, et le navigateur ne doit pas prendre ce geste pour un défilement. */
.panneau.fermable { touch-action: none; }
.panneau.fermable::before { content: ""; display: block; width: 40px; height: 4px; margin: -10px auto 14px; border-radius: 4px; background: var(--trait); }
@keyframes monte { from { transform: translateY(40px); opacity: 0; } }
.voile { position: fixed; inset: 0; z-index: 20; background: rgba(45, 42, 53, .28); }
.voile.flou { -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px); } /* #77, première aide */
.panneau .actions { display: flex; flex-wrap: wrap; gap: var(--esp-sm); margin-top: var(--esp-md); }
/* Hors de la grille (E-4), le panneau se pose sur le bas de l'écran, la page défile dessous. */
.panneau.flottant {
  position: fixed; left: 0; right: 0; bottom: 0; margin: 0 auto; max-height: calc(100dvh - 48px); overflow-y: auto;
  border-bottom: 0; border-radius: 24px 24px 0 0; padding-bottom: calc(var(--esp-lg) + env(safe-area-inset-bottom));
}
.panneau .garde { margin: var(--esp-md) 0 0; color: var(--encre-douce); font-size: 15px; }
.panneau .actions .btn { flex: 1 0 auto; } /* s'il manque de place, le bouton passe entier à la ligne */
.panneau .actions.discretes { margin-top: var(--esp-sm); }
.panneau .actions .btn.oeil { flex: none; padding-inline: var(--esp-md); } /* spec 015, admin : à côté de « Je le cherche » */
.panneau .actions.suite { margin-top: var(--esp-xs); }
.panneau .actions.discretes .btn { flex: 0 1 auto; }

/* Aide d'un mot (E-2) */
.aide-detail { display: flex; gap: var(--esp-md); align-items: center; }
.aide-detail .mochi { width: 84px; }
.aide-detail .fr { color: var(--encre-douce); font-size: 15px; }
.aide-detail .forme { font: 700 34px/1.2 var(--police-japonais); }
.aide-detail .lecture { font: 500 15px var(--police-japonais); color: var(--encre-douce); }

/* Corriger la traduction (E-5) */
.panneau h2 { font-size: 24px; }
.mot-jp { display: flex; align-items: baseline; gap: 10px; margin: 6px 0 var(--esp-md); }
.mot-jp b { font: 700 30px var(--police-japonais); }
.mot-jp span { font: 500 15px var(--police-japonais); color: var(--encre-douce); }
label.champ { display: block; font-size: 13px; color: var(--encre-douce); margin-bottom: 6px; }
input[type="text"], input[type="password"] { width: 100%; font: 17px var(--police-texte); padding: 12px 14px; border-radius: var(--rayon-md); border: 1.5px solid var(--trait); background: var(--carte); color: var(--encre); }
input[type="text"]:focus, input[type="password"]:focus { border-color: var(--sakura); box-shadow: 0 0 0 4px rgba(231, 127, 154, .18); outline: none; }
input.erreur { border-color: var(--erreur); }
.msg-erreur { color: var(--erreur); font-size: 13px; margin: 6px 0 0; }
.msg-erreur:empty { display: none; }
.origine { font-size: 13px; color: var(--encre-douce); margin: var(--esp-sm) 0 0; }
.lien { font: inherit; color: var(--encre); text-decoration: underline; background: none; border: 0; padding: 0; cursor: pointer; }

.tete-panneau { display: flex; gap: var(--esp-md); align-items: center; }
.tete-panneau .mochi { width: 92px; }
.tete-panneau h2 { font-size: 26px; line-height: 1.1; }
.tete-panneau p { margin: 4px 0 0; color: var(--encre-douce); font-size: 15px; }
/* Un mot, donc une seule ligne, centrée (#87, #89) : trop long pour la largeur, ses cases
   rapetissent avec leurs lettres. `--lettres` est posé par jeu.js. */
.cases-mystere { display: flex; justify-content: center; gap: 6px; margin: var(--esp-md) 0 2px; container-type: inline-size; }
.cases-mystere span {
  --case: min(46px, (100cqw - (var(--lettres) - 1) * 6px) / var(--lettres));
  flex: none; width: var(--case); height: var(--case); display: grid; place-items: center;
  font: 700 calc(var(--case) * .52) var(--police-japonais);
  background: #fff; color: var(--vermillon); border: 2px solid var(--vermillon); border-radius: var(--rayon-md);
  animation: allume .5s var(--rebond) both;
}
.choix { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: var(--esp-md); }
.choix button {
  font: 500 17px var(--police-texte); color: var(--encre); padding: 14px 8px; cursor: pointer;
  background: var(--carte); border: 2px solid var(--trait); border-radius: var(--rayon-md);
  transition: transform .18s var(--rebond);
}
.choix button:active:enabled { transform: scale(1.04, .92); }
.choix button:disabled { cursor: default; }
.choix button.bon { border-color: var(--succes); background: var(--succes-pale); font-weight: 700; opacity: 1; }
.choix button.faux { border-color: var(--erreur); color: var(--erreur); text-decoration: line-through; }
.choix button.eteint { opacity: .45; }
.choix button.solution { border-style: dashed; border-color: var(--encre-douce); } /* #81, admin : comme le contour des solutions */
.bilan { display: flex; flex-wrap: wrap; gap: var(--esp-sm) var(--esp-lg); margin-top: var(--esp-md); font-size: 14px; color: var(--encre-douce); }
.bilan b { display: block; font: 600 22px var(--police-titre); color: var(--encre); }

/* Téléphone et tablette : une liste compacte, pour en voir davantage sans faire défiler. Le titre
   s'efface (le compteur dit déjà les mots ; il nomme la liste pour les lecteurs d'écran) ; les
   trouvés, en fin de liste, plus petits et plus pâles. */
@media (max-width: 799px) {
  .jeu { gap: var(--esp-sm); }
  /* La ligne du compteur et « Nouvelle grille » se resserre : de la hauteur pour la grille et la liste. */
  .entete { padding-bottom: var(--esp-xs); }
  .bandeau { min-height: 36px; }
  .bandeau .btn { min-height: 36px; padding-block: 2px; }
  /* La grille se tient à 24 px au moins des bords (8 px de page + 16) : un glisser parti de la
     première colonne commence hors de la zone du geste retour du téléphone (spec 010, comp. 7). */
  .zone-grille { padding-inline: var(--esp-md); }
  .liste { gap: 6px 5px; }
  .mot { font-size: 14px; line-height: 1.2; padding: 6px 10px; min-height: 32px; }
  .mot.aide b { font-size: 13px; margin-left: 4px; }
  .mot.trouve { font-size: 12px; min-height: 0; padding: 2px 6px; opacity: .75; }

  /* Partie en cours : la page tient dans la hauteur de l'écran (spec 010, comportement 8). La
     liste prend la hauteur qui reste sous la grille, ses pastilles en autant de rangées qu'il en
     tient (jeu.js en règle la largeur), et défile de côté au-delà. Elle garde au moins deux rangées : si l'écran est trop bas pour cela,
     la page défile, plutôt que de cacher la liste. */
  body:not(.hors-ligne) > .page:has(> .jeu.en-cours:not([hidden])) {
    height: 100dvh; display: flex; flex-direction: column;
    padding-bottom: calc(var(--esp-sm) + env(safe-area-inset-bottom));
  }
  .jeu.en-cours { flex: 1 1 0; min-height: 0; grid-template-rows: auto auto minmax(calc(2 * 32px + 6px), 1fr); }
  /* La liste garde les marges de la grille : un défilement de côté ne part pas du bord de l'écran,
     où le téléphone le prendrait pour le geste retour (comportement 7). */
  .jeu.en-cours .zone-liste {
    min-height: 0; margin-inline: var(--esp-md);
    overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain; touch-action: pan-x;
    scrollbar-width: none;
  }
  .jeu.en-cours .zone-liste::-webkit-scrollbar { display: none; }
  .jeu.en-cours .zone-liste.suite { mask-image: linear-gradient(to left, transparent, #000 32px); }
  .liste > .trouve { display: none; }
  .pastille-trouves { display: block; }
  /* Les panneaux se posent par-dessus le bas de l'écran, hors du flux qui n'a plus de place. */
  .jeu.en-cours .panneau, .jeu.fin.ajustee .panneau {
    position: fixed; left: 0; right: 0; bottom: 0; margin: 0 auto; max-height: calc(100dvh - 48px); overflow-y: auto;
    padding-bottom: calc(var(--esp-lg) + env(safe-area-inset-bottom));
  }
  /* Le panneau des trouvés (#52) : quand elle déborde (classe `defile`, posée par jeu.js), sa liste
     défile seule, au doigt, sans passer à la page ; la poignée et le titre, au-dessus, gardent le
     glissement qui ferme le panneau. Sans débordement, elle ne défile pas et le glissement ferme
     aussi depuis elle. */
  .jeu.en-cours .panneau:has(> .liste-trouves) { display: flex; flex-direction: column; overflow: hidden; }
  .jeu.en-cours .liste-trouves { min-height: 0; overflow-y: hidden; }
  .jeu.en-cours .liste-trouves.defile { overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y; }

  /* Fin de grille (#83) : le panneau du mot mystère, puis du résultat, se pose sur le bas de
     l'écran (règle des panneaux ci-dessus), et la grille rapetisse en douceur jusqu'à tenir entière
     au-dessus (jeu.js mesure la place dans --grille-fin) ; ses caractères suivent sa largeur. Si
     elle y serait trop petite, jeu.js ne pose pas `ajustee` : panneau dans le flux, page qui défile. */
  /* #85 : la grille remonte dans la place des oreilles de Mochi, cachée en fin de grille, et le
     panneau monte du bas de l'écran en la poussant : même durée, même courbe pour les trois. */
  .jeu { --pousse: .5s cubic-bezier(.25, .8, .3, 1); }
  /* Transitions à l'entrée seulement, comme la largeur : à la sortie (nouvelle grille, rotation),
     la grille reprend sa place d'un coup. Le panneau garde la même animation avec ou sans
     `ajustee`, pour qu'une rotation ne la relance pas. */
  .jeu.fin.ajustee .zone-grille { padding-top: 0; transition: padding-top var(--pousse); }
  .jeu.fin .panneau { animation: pousse var(--pousse) both; }
  @keyframes pousse { from { transform: translateY(100%); } }
  .jeu.fin.ajustee .grille { max-width: min(480px, var(--grille-fin, 480px)); container-type: inline-size; transition: max-width var(--pousse); }
  .jeu.fin.ajustee .cases span { font-size: min(24px, calc(100cqw / var(--taille) * .6)); }
}

/* Ordinateur : grille à gauche ; liste ou panneau à droite. */
@media (min-width: 820px) {
  .jeu { grid-template-columns: minmax(0, 480px) 1fr; align-items: start; column-gap: var(--esp-xl); }
  .bandeau { grid-column: 1 / -1; }
  .zone-grille { grid-area: 2 / 1; }
  .zone-liste { grid-area: 2 / 2; padding-top: 22px; }
  .panneau { grid-area: 2 / 2; position: relative; margin: 22px 0 0; border-bottom: 1.5px solid var(--trait-mochi); border-radius: 24px; }
}

/* Mouvement réduit : plus de rebond ni de déplacement, un simple fondu. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; }
  .btn:active, .icone:active, .choix button:active:enabled { transform: none; }
  .panneau, .mot.nouveau, .cases span.allume, .cases-mystere span, .traits line.dessine { animation: fondu var(--court) ease-out both !important; stroke-dasharray: none; }
  .traits rect.contour.clignote { animation: fondu var(--court) ease-out both; } /* garde son pointillé */
  .etiquette { animation-name: etiquette-fondu; }
  @keyframes fondu { from { opacity: 0; } }
}

/* E-9 Connexion (spec 014) : la carte de bienvenue, un formulaire au lieu du choix du niveau. */
.connexion { max-width: 420px; margin: 0 auto; padding: var(--esp-xl) var(--esp-sm); }
.connexion > .mochi { display: block; width: 120px; margin: 0 auto; }
.connexion h1 { font-size: 40px; text-align: center; margin-top: var(--esp-sm); }
.connexion h1 span { display: block; font: 700 18px var(--police-japonais); color: var(--sakura); letter-spacing: .12em; margin-top: 4px; }
.connexion .rassure { text-align: center; margin: var(--esp-md) 0 var(--esp-lg); }
.connexion .dit { margin: var(--esp-md) 0 var(--esp-lg); }
.formulaire { display: grid; padding: var(--esp-lg) var(--esp-md); }
.formulaire input:not([type="hidden"]) + label.champ { margin-top: var(--esp-md); }
.formulaire .btn { margin-top: var(--esp-lg); justify-self: stretch; }
.liens-dev, form.deconnexion { display: flex; flex-wrap: wrap; gap: var(--esp-sm); }
/* E-10 et le changement depuis « Mon compte » (#58) : la même carte que E-9. */
.connexion h1.titre-court { font-size: 28px; }
.connexion.sans-titre { padding-top: 0; }
.connexion.sans-titre .rassure { text-align: left; margin-top: 0; }
.formulaire .credits { margin: var(--esp-sm) 0 0; }
.connexion > form.deconnexion { justify-content: center; margin-top: var(--esp-md); }
/* E-11 Comptes (#60) : une ligne par compte, chaque action dans le panneau du bas. */
.creer-compte { width: 100%; margin-bottom: var(--esp-md); }
.compte-ligne { gap: var(--esp-md); border-bottom: 1px solid var(--trait); }
.compte-ligne:last-child { border-bottom: 0; }
.compte-ligne > span:first-child { min-width: 0; overflow-wrap: anywhere; }
.compte-ligne b { display: block; font-weight: 600; }
.compte-ligne small { display: block; color: var(--encre-douce); font-size: 13px; }
.compte-ligne.eteint b { color: var(--encre-douce); }
.formulaire-panneau { display: grid; margin-top: var(--esp-md); }
.formulaire-panneau input + label.champ { margin-top: var(--esp-md); }
.provisoire { font: 600 30px/1.2 ui-monospace, "SF Mono", Menlo, Consolas, monospace; letter-spacing: .08em; text-align: center;
  margin: var(--esp-md) 0 0; padding: var(--esp-md) var(--esp-sm); background: var(--papier); border: 1px solid var(--trait);
  border-radius: var(--rayon-md); user-select: all; overflow-wrap: anywhere; }
