/* Déboîter — la feuille de style.
   Copyright (c) 2026 Tristan Cazenave. Tous droits réservés — voir LICENSE.

   PAS D'IMAGES. Un mur est un carré, un bloc un rectangle posé dessus, la
   porte une entaille dans le mur. Tout tient dans `--c`, la taille d'une case ;
   le reste en découle, et le plateau se met à l'échelle en changeant un seul
   nombre.

   La palette est celle de Sokoban, son frère aîné : qui passe de l'un à
   l'autre doit se sentir chez lui. Une couleur s'ajoute, et c'est celle qui
   fait le jeu — le rouge du bloc qu'il faut sortir. */

:root {
  color-scheme: light dark;
  --fond: #f4f1ea; --surface: #fffdf8; --surface-2: #efeadf;
  --ink: #1d2126; --ink-2: #4a525c; --ink-3: #7b838d; --line: #d9d2c5;
  --accent: #2c4e7e; --accent-2: #24406a; --bad: #a6402f; --bon: #2f6b45;
  --sol: #e6dfd0; --mur: #6b6152; --mur-haut: #7d7362;
  --bloc: #b07c3f; --bloc-haut: #c8944f;
  --rouge: #b7382b; --rouge-haut: #cf5243;
  --porte: #2f6b45; --homme: #2c4e7e;
}
@media (prefers-color-scheme: dark) {
  :root {
    --fond: #14171b; --surface: #1c2026; --surface-2: #242932;
    --ink: #e8eaed; --ink-2: #b3bac3; --ink-3: #868e98; --line: #333a44;
    --accent: #7aa2d6; --accent-2: #9dbce5; --bad: #e08b7c; --bon: #7fc79c;
    --sol: #2a2f36; --mur: #454d58; --mur-haut: #525b68;
    --bloc: #8d6333; --bloc-haut: #a2753f;
    --rouge: #a33a2e; --rouge-haut: #bd4d3f;
    --porte: #4f8c5e; --homme: #7aa2d6;
  }
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--fond); color: var(--ink);
  font: 16px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-text-size-adjust: 100%;
  padding-bottom: env(safe-area-inset-bottom);
}
.page { max-width: 1060px; margin: 0 auto; padding: 10px 12px 28px; }

header.tete { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.pousse { margin-left: auto; }

.langues {
  display: inline-flex; border: 1px solid var(--line); border-radius: 999px;
  overflow: hidden; background: var(--surface);
}
.langues button {
  font: inherit; font-size: 13px; line-height: 1; padding: 6px 10px;
  border: 0; background: none; color: var(--ink-2); cursor: pointer;
}
.langues button + button { border-left: 1px solid var(--line); }
.langues button[aria-pressed="true"] { background: var(--accent); color: #fff; }

.btn {
  font: inherit; font-size: 14px; color: var(--ink); background: var(--surface);
  border: 1px solid var(--line); border-radius: 9px; padding: 7px 12px; cursor: pointer;
}
.btn:hover:not(:disabled) { background: var(--surface-2); border-color: var(--accent); }
.btn:disabled { opacity: .45; cursor: default; }
.btn.primaire { background: var(--accent); color: #fff; border-color: var(--accent); }
.btn[aria-selected="true"] { background: var(--accent); color: #fff; border-color: var(--accent); }

.compteurs { font-size: 13.5px; color: var(--ink-3); min-width: 0; }
.compteurs > span { white-space: nowrap; }
.compteurs > span + span::before { content: ' · '; color: var(--ink-3); }
.compteurs b { color: var(--ink-2); font-weight: 600; }

.modes { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
/* `hidden` ne fait rien contre un `display: flex` : il faut le dire. Sur
   deboiter.com, les onglets et la barre du haut ne sont pas la du tout. */
.modes[hidden], .barre-haut[hidden] { display: none; }

/* Les pastilles des niveaux : un chiffre par niveau, et l'on voit d'un coup
   d'œil ceux qui sont faits. Vingt pastilles tiennent sur deux lignes d'un
   téléphone. */
.pastilles { display: flex; gap: 5px; flex-wrap: wrap; margin-bottom: 10px; }
.pastilles[hidden] { display: none; }
.pastille {
  font: inherit; font-size: 13px; line-height: 1;
  min-width: 30px; padding: 6px 4px; cursor: pointer;
  border: 1px solid var(--line); border-radius: 7px;
  background: var(--surface); color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.pastille.fait { background: var(--bon); border-color: var(--bon); color: #fff; }
.pastille[aria-current="true"] { outline: 2px solid var(--accent); outline-offset: 1px; }

/* La barre des séries dépouillées : deux listes, un compte, et de quoi parcourir
   les positions. Elle remplace les pastilles — on ne fait pas deux cent
   quatre-vingt-dix mille pastilles. */
.banque {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-bottom: 10px; font-size: 13.5px; color: var(--ink-2);
}
.banque[hidden] { display: none; }

/* L'invitation à se connecter : visible, mais pas criarde — elle accompagne des
   boutons éteints, elle ne les remplace pas. */
.invite {
  margin: 0 0 10px; padding: 9px 12px; font-size: 13.5px; color: var(--ink-2);
  background: var(--surface); border: 1px solid var(--line); border-radius: 9px;
}
.invite[hidden] { display: none; }
.invite a { color: var(--accent); font-weight: 600; }
.invite .ligne { display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  margin-top: 8px; }
.invite input {
  font: inherit; font-size: 14px; color: var(--ink); background: var(--fond);
  border: 1px solid var(--line); border-radius: 9px; padding: 7px 10px;
  min-width: 10ch; flex: 0 1 18ch;
}
.invite .apres { font-size: 13px; color: var(--ink-3); }
.invite .mauvais { color: var(--bad); }
.invite .bon { color: var(--bon); font-weight: 600; }
.banque .reglage { display: inline-flex; align-items: center; gap: 6px; }
.banque select {
  font: inherit; font-size: 14px; color: var(--ink); background: var(--surface);
  border: 1px solid var(--line); border-radius: 8px; padding: 5px 8px;
}
.banque .combien, .banque .rang { color: var(--ink-3); font-variant-numeric: tabular-nums; }
.banque .rang { min-width: 11ch; text-align: center; }
.btn-fin { padding: 5px 10px; line-height: 1; }

/* ------------------------------------------------------------------ le jeu */

.jeu { display: flex; gap: 22px; align-items: flex-start; flex-wrap: wrap; }

.plateau {
  /* LE PLATEAU PREND LA PLACE QU'IL Y A : la case est la plus petite de trois
     contraintes — la largeur qui reste à côté du tableau d'honneur, la hauteur
     qui reste sous l'en-tête, et un plafond, sans lequel une petite grille
     deviendrait un damier de pavés. */
  --large: calc((100vw - 400px) / var(--l));
  --haut: calc((100vh - 290px) / var(--h));
  --c: clamp(24px, min(var(--large), var(--haut)), 74px);
  position: relative;
  background: var(--surface-2);
  border: 1px solid var(--line); border-radius: 10px; padding: 6px;
  touch-action: manipulation;
}
.sol {
  display: grid;
  grid-template-columns: repeat(var(--l), var(--c));
  grid-template-rows: repeat(var(--h), var(--c));
}
.case { width: var(--c); height: var(--c); position: relative; }
.case.solx { background: var(--sol); cursor: pointer; }
.case.mur {
  background: linear-gradient(160deg, var(--mur-haut), var(--mur));
  border-radius: 3px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12);
}
/* La porte est une entaille dans le mur, et elle montre où l'on sort : une
   flèche, dans la couleur de ce qui doit passer. */
.case.porte { background: var(--sol); }
.case.porte::after {
  content: ''; position: absolute; inset: 22%;
  background: var(--porte);
  clip-path: polygon(0 32%, 52% 32%, 52% 8%, 100% 50%, 52% 92%, 52% 68%, 0 68%);
}
.case.porte.h::after { transform: rotate(-90deg); }
.case.porte.b::after { transform: rotate(90deg); }
.case.porte.g::after { transform: rotate(180deg); }

/* Les pièces sont posées PAR-DESSUS le décor, et ne prennent pas le clic : il
   traverse jusqu'à la case, qui sait où elle est. */
.pieces { position: absolute; inset: 6px; pointer-events: none; }
.piece {
  position: absolute;
  border-radius: 6px;
  background: linear-gradient(160deg, var(--bloc-haut), var(--bloc));
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, .18), 0 1px 2px rgba(0, 0, 0, .25);
  transition: left .09s linear, top .09s linear;
}
.piece.rouge {
  background: linear-gradient(160deg, var(--rouge-haut), var(--rouge));
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, .25), 0 1px 3px rgba(0, 0, 0, .3);
}
/* Le rouge coincé pour de bon se signale, sans qu'on ait rien demandé. */
.piece.rouge.coince { box-shadow: inset 0 0 0 3px var(--bad), 0 0 0 2px var(--bad); }
.piece.homme {
  border-radius: 50%;
  background: radial-gradient(circle at 38% 32%, #fff6, transparent 60%), var(--homme);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
}

/* ------------------------------------------------- le tableau d'honneur */

.cote { flex: 1 1 280px; min-width: 260px; }
.cote h2 { font-size: 16px; margin: 0 0 6px; }
.note { font-size: 13.5px; color: var(--ink-3); margin: 6px 0; }

.tableau { list-style: none; counter-reset: rang; margin: 0; padding: 0; }
.tableau li {
  counter-increment: rang;
  display: flex; align-items: baseline; gap: 8px;
  padding: 5px 8px; border-bottom: 1px solid var(--line); font-size: 14px;
}
.tableau li::before {
  content: counter(rang) '.'; color: var(--ink-3); min-width: 1.6em;
  font-variant-numeric: tabular-nums;
}
.tableau li.moi { background: var(--surface-2); border-radius: 6px; }
.tableau .nom { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tableau .score { margin-left: auto; white-space: nowrap; }
.tableau .pas { color: var(--ink-3); white-space: nowrap; font-size: 13px; }

.dit { min-height: 1.5em; margin: 10px 2px 0; font-size: 14.5px; color: var(--ink-2); }
.dit.bon { color: var(--bon); font-weight: 600; }
.dit.mauvais { color: var(--bad); }

.barre-haut { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin: 0 0 10px; }
.barre-bas { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 12px; }

/* ── LE RITUEL ─────────────────────────────────────────────────────────────
   La serie se lit avant de jouer, le panneau de fin apres avoir gagne. Le
   ruban est en chasse fixe : les carres doivent s'aligner en colonnes, sinon
   il ne ressemble a rien une fois colle ailleurs. */
.rituel {
  margin: 0 2px 10px; font-size: 13.5px; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.rituel[hidden] { display: none; }

.fin {
  margin: 14px 0 0; padding: 14px 16px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 14px;
  max-width: 460px;
}
.fin[hidden] { display: none; }
.fin h2 { margin: 0 0 2px; font-size: 19px; color: var(--bon); }
.fin .fin-numero { margin: 0; font-size: 13.5px; color: var(--ink-3); }
.fin .fin-score { margin: 8px 0 0; font-size: 15px; color: var(--ink); }
.fin .fin-serie { margin: 10px 0 0; font-size: 14.5px; color: var(--ink-2); font-weight: 600; }
.fin p { margin: 6px 0 0; }
.fin .apres { font-size: 13px; color: var(--ink-3); margin-left: 8px; }
.fin .apres.bon { color: var(--bon); }
.fin .apres.mauvais { color: var(--bad); }
.ruban {
  margin: 10px 0 0; font: 17px/1.25 ui-monospace, "Segoe UI Emoji", monospace;
  letter-spacing: 1px; white-space: pre-wrap; word-break: break-all;
}
.ruban:empty { display: none; }

.modale {
  position: fixed; inset: 0; background: rgba(10, 12, 16, .55);
  display: flex; align-items: center; justify-content: center; padding: 16px; z-index: 100;
}
.modale[hidden] { display: none; }
.boite {
  background: var(--surface); color: var(--ink); border: 1px solid var(--line);
  border-radius: 14px; padding: 20px; max-width: 560px; width: 100%;
  max-height: 84vh; overflow: auto;
}
.boite h2 { margin: 0 0 4px; font-size: 19px; }
.boite h3 { margin: 16px 0 4px; font-size: 15px; color: var(--ink-2); }
.boite p { margin: 4px 0; font-size: 14.5px; color: var(--ink-2); }
.boite textarea {
  width: 100%; min-height: 150px; font: 13px/1.4 ui-monospace, monospace;
  background: var(--fond); color: var(--ink);
  border: 1px solid var(--line); border-radius: 9px; padding: 8px;
}

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.cache { display: none !important; }

@media (max-width: 760px) {
  /* Le tableau d'honneur passe dessous : toute la largeur revient au plateau. */
  .plateau { --large: calc((100vw - 34px) / var(--l)); }
  .jeu { gap: 14px; }
}
@media (max-width: 520px) { .page { padding: 6px; } }
