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

   LE PLATEAU EST UNE GRILLE, ET RIEN D'AUTRE. Pas d'images : un mur est un
   carré, une caisse un carré posé dessus, un but un creux. 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. */

: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;
  --but: #c9a227; --caisse: #b07c3f; --caisse-haut: #c8944f;
  --posee: #4f8c5e; --posee-haut: #63a473; --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;
    --but: #b9932a; --caisse: #8d6333; --caisse-haut: #a2753f;
    --posee: #3f7050; --posee-haut: #4f875f; --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); }

/* LES COMPTEURS PEUVENT REVENIR À LA LIGNE. Ils portent maintenant le nom du
   problème du jour — « Problème du jour — 2026-09-22 · Poussées 0 · Pas 0 »,
   soit près de quatre cents pixels : un `nowrap` les faisait déborder de tout
   téléphone. Chaque morceau reste insécable, la ligne non. */
.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; }

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

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

.plateau {
  /* LE PLATEAU PREND LA PLACE QU'IL Y A. Une taille de case figee laissait un
     niveau de sept cases perdu au milieu d'un grand ecran vide, et debordait
     sur un petit. La case est donc la plus petite de trois contraintes : la
     largeur qui reste a cote du tableau d'honneur, la hauteur qui reste sous
     l'en-tete, et un plafond — sans lui, deux caisses dans un grand ecran
     deviendraient des paves. */
  --large: calc((100vw - 400px) / var(--l));
  --haut: calc((100vh - 250px) / var(--h));
  /* Le plafond était à 64 quand un niveau pouvait faire dix cases de large.
     Les grilles du 5×5 en font sept, mur compris : sur un grand écran, 64
     laissait un plateau de 462 pixels perdu au milieu du vide. */
  --c: clamp(22px, min(var(--large), var(--haut)), 82px);
  display: grid;
  grid-template-columns: repeat(var(--l), var(--c));
  grid-template-rows: repeat(var(--h), var(--c));
  gap: 0; background: var(--surface-2);
  border: 1px solid var(--line); border-radius: 10px; padding: 6px;
  touch-action: manipulation;
}
.case { width: var(--c); height: var(--c); position: relative; }
.case.sol { 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);
}

/* Un but est un creux dans le sol : on doit le voir sous une caisse posée
   dessus, sinon on ne sait plus ce qui est fait et ce qui reste. */
.case.but::before {
  content: ''; position: absolute; inset: 34%;
  border-radius: 50%; background: var(--but); opacity: .75;
}

.case.caisse::after {
  content: ''; position: absolute; inset: 9%;
  border-radius: 5px;
  background: linear-gradient(160deg, var(--caisse-haut), var(--caisse));
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, .18), 0 1px 2px rgba(0, 0, 0, .25);
}
.case.caisse.posee::after {
  background: linear-gradient(160deg, var(--posee-haut), var(--posee));
}
/* Une caisse coincée se signale, et rien de plus : c'est la seule aide. */
.case.coincee::after { box-shadow: inset 0 0 0 2px var(--bad), 0 1px 2px rgba(0,0,0,.25); }

.case.homme::after {
  content: ''; position: absolute; inset: 18%;
  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-bas { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 12px; }

.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); }

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

/* Le plateau suit l'écran : un niveau de neuf cases de large doit tenir sur un
   téléphone sans qu'on ait à le faire glisser. */
@media (max-width: 760px) {
  /* Le tableau d'honneur est passe dessous : toute la largeur revient au
     plateau, et il n'y a plus de colonne a lui reserver. */
  .plateau { --large: calc((100vw - 34px) / var(--l)); }
  .jeu { gap: 14px; }
}
@media (max-width: 520px) { .page { padding: 6px; } }

/* ------------------------------------------------------- le choix d'une série
   Cent quarante-cinq classes, cinquante-trois millions de positions : deux
   listes déroulantes et un compte. Le reste de la page est le même plateau que
   partout ailleurs — une position du 5×5 se joue comme un niveau. */

.choix { max-width: 760px; }
.choix h1 { font-size: 21px; margin: 6px 0 10px; }
.reglages {
  display: flex; gap: 14px; align-items: flex-end; flex-wrap: wrap;
  margin: 16px 0 12px;
}
.reglage { display: flex; flex-direction: column; gap: 4px; font-size: 13px;
           color: var(--ink-3); }
.reglage select {
  font: inherit; font-size: 15px; color: var(--ink);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 9px; padding: 7px 10px; min-width: 88px;
}
.combien { font-size: 14px; color: var(--ink-2); padding-bottom: 8px; }
.choix .note { font-size: 14px; color: var(--ink-3); line-height: 1.5;
               max-width: 68ch; }
.barre-bas[hidden], .compteurs[hidden], .jeu[hidden] { display: none; }
