/**
 * PlayAwale — Mon espace : le tableau de bord et la page d'entrée
 * -----------------------------------------------------------------------------
 * Deux pages partagent cette feuille : register.php, où l'on donne son adresse,
 * et dashboard.php, où l'on est chez soi. Elles ont les mêmes champs, les mêmes
 * cartes et le même vocabulaire — ce sont deux moments d'une même chose.
 *
 * MOBILE D'ABORD, ET CE N'EST PAS UNE FORMULE
 * Tout ce qui est écrit ici vaut pour un téléphone. Les écrans plus larges
 * n'ajoutent que deux choses, plus bas : le menu passe en colonne à gauche, et
 * les cartes se mettent côte à côte. Rien ne se retire en descendant.
 *
 * LES CHAMPS FONT 16 PIXELS
 * En dessous, un iPhone grossit la page tout seul au moment où l'on tape, et
 * l'on se retrouve à faire glisser l'écran pour retrouver le bouton. Ce n'est
 * pas une question de goût : c'est la règle de Safari.
 *
 * LES CIBLES FONT 44 PIXELS
 * Chaque lien du menu, chaque case à cocher, chaque bouton. C'est la taille d'un
 * pouce, et c'est ce qui sépare un formulaire qu'on remplit d'un formulaire
 * qu'on abandonne.
 *
 * @package   PlayAwale
 * @version   2.0
 * @author    Nicolas Lion — Développeur web — https://nlion.fr
 * @copyright 2026 Nicolas Lion
 */


/* =============================================================================
   L'EN-TÊTE DE L'ESPACE
   ============================================================================= */

.dash-head {
  margin-bottom: var(--space-md);
  text-align: center;
}

.dash-head__title {
  margin-bottom: var(--space-2xs);
}

.dash-head__lead {
  margin: 0;
}


/* =============================================================================
   LA COQUE : LE MENU ET LE CONTENU
   -----------------------------------------------------------------------------
   Sur un téléphone, l'un sous l'autre. Le menu vient EN PREMIER dans le
   balisage : c'est la carte de l'espace, et on la lit avant d'entrer dans une
   rubrique — au clavier comme au doigt.
   ============================================================================= */

.dash-shell {
  display: grid;
  gap: var(--space-md);

  /* LA COQUE DOIT DIRE SA LARGEUR, ET NE PAS LA DEVINER
     « .account-page » est une colonne flex centrée : un enfant y prend la
     largeur de son CONTENU, pas celle de la page. Sans ces deux lignes, la
     grille se calait sur la plus longue phrase du contenu et poussait la page
     à 1 000 px de large sur un écran de 768. La largeur reprend celle des
     blocs du site — « min(94vw, 720px) » —, d'un cran plus large quand le menu
     prend sa colonne. */
  width: min(94vw, 720px);
}

@media (min-width: 62rem) {

  .dash-shell {
    width: min(94vw, 62rem);
  }
}


/* --- Le menu ---------------------------------------------------------------- */

/* « min-width: 0 » SUR LES DEUX COLONNES, ET C'EST INDISPENSABLE
   Un élément de grille prend par défaut la largeur de son contenu, et refuse de
   rétrécir en dessous : le menu, qui est une rangée de cinq rubriques, poussait
   la page à 576 px de large sur un téléphone de 390. On le voit à la barre de
   défilement horizontale — et on ne le voit qu'en mesurant. */
.dash-nav {
  min-width: 0;
}

.dash-nav__list {
  display: flex;
  gap: var(--space-2xs);

  margin: 0;
  padding: 0 0 var(--space-2xs);
  list-style: none;

  /* SUR UN TÉLÉPHONE, LE MENU DÉFILE DU DOIGT
     Cinq rubriques ne tiennent pas en largeur, et les replier sous un bouton
     cacherait la carte de l'espace. Elles défilent donc, et la dernière laisse
     voir son bord : c'est ce qui dit qu'il y en a d'autres. */
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
}

.dash-nav__link {
  display: flex;
  align-items: center;
  gap: var(--space-xs);

  /* 44 px de haut : la taille d'un pouce. */
  min-height: 44px;
  padding: var(--space-xs) var(--space-sm);

  font-family: var(--font-body);
  font-size: var(--font-size-sm);
  line-height: var(--line-height-tight);
  color: var(--color-text);
  text-decoration: none;
  white-space: nowrap;

  background-color: var(--color-sand-100);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);

  transition: background-color var(--duration-fast) ease;
}

.dash-nav__link:hover,
.dash-nav__link:focus-visible {
  background-color: var(--color-brand-amber-light);
}

.dash-nav__link:focus-visible {
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 2px;
}

/* LA RUBRIQUE OUVERTE NE SE DIT PAS QUE PAR LA COULEUR
   Un liseré d'ambre, un fond plus chaud, et « aria-current » dans le balisage :
   qui ne distingue pas les couleurs l'entend, et qui ne lit pas le voit. */
.dash-nav__link[aria-current='page'] {
  background-color: var(--color-brand-amber-light);
  box-shadow: inset 0 0 0 2px var(--color-brand-amber-deep), var(--shadow-sm);
  font-weight: 700;
}

.dash-nav__icon {
  display: flex;
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  color: var(--color-brand-dark);
}

.dash-nav__icon svg {
  width: 100%;
  height: 100%;
}

/* Une rubrique qui n'existe pas encore : plus pâle, mais ouvrable — elle
   explique ce qu'elle contiendra. */
.dash-nav__link--soon {
  color: var(--color-text-muted);
}

.dash-nav__link--soon .dash-nav__icon {
  opacity: 0.55;
}

.dash-nav__soon {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;

  padding: 0.1em 0.45em;
  color: var(--color-text-muted);
  background-color: rgba(60, 39, 35, 0.08);
  border-radius: var(--radius-full);
}


/* --- Le contenu ------------------------------------------------------------- */

.dash-main {
  display: grid;
  gap: var(--space-md);
  min-width: 0;
}

/* UN ESPACE DE TRAVAIL SE LIT À GAUCHE
   Les cartes du site sont centrées : elles présentent. Celles-ci contiennent des
   champs, des faits, des listes — on les parcourt, on n'y est pas accueilli. Le
   titre reste au centre sur un téléphone, où une carte étroite tient de l'affiche. */
.dash-page .dash-card,
.dash-page .dash-card .account-block__title,
.dash-page .dash-card .account-block__text {
  margin-left: 0;
  margin-right: 0;
  text-align: left;
}

/* UNE CARTE DE L'ESPACE PREND LA LARGEUR DE SA COLONNE, ET NON CELLE DU SITE
   « .account-block » vaut « min(94vw, 720px) » : posé seul au milieu d'une page,
   c'est la bonne largeur de lecture ; posé dans la colonne de droite d'un
   tableau de bord, c'est 720 px dans un espace qui n'en fait que 456, et la
   page déborde de deux cents pixels entre 768 et 1 000. Mesuré, corrigé. */
.dash-page .dash-card {
  width: 100%;
}

.dash-card {
  margin: 0;
}


/* =============================================================================
   LES TUILES DE L'ACCUEIL
   -----------------------------------------------------------------------------
   Une rubrique, ce qu'elle contient, un chevron. La même lecture que les entrées
   de l'accueil du site : on sait où l'on va avant de cliquer.
   ============================================================================= */

ul.dash-tiles {
  display: grid;
  gap: var(--space-xs);

  margin: var(--space-md) 0 0;
  padding: 0;
  list-style: none;
}

/* La même raison que pour le menu : sans « min-width: 0 », une tuile refuse de
   descendre sous la largeur de sa phrase, et pousse la page hors de l'écran. */
ul.dash-tiles > li,
.dash-tile {
  min-width: 0;
}

.dash-tile {
  display: flex;
  align-items: center;
  gap: var(--space-sm);

  min-height: 44px;
  padding: var(--space-sm);

  color: var(--color-text);
  text-decoration: none;

  background: var(--gradient-panel);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);

  transition: background-color var(--duration-fast) ease;
}

.dash-tile:hover,
.dash-tile:focus-visible {
  background-color: var(--color-brand-amber-light);
}

.dash-tile:focus-visible {
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 2px;
}

.dash-tile__icon {
  display: grid;
  place-items: center;
  flex: none;

  width: 2.4rem;
  height: 2.4rem;

  color: var(--color-brand-dark);
  background-color: rgba(60, 39, 35, 0.08);
  border-radius: var(--radius-full);
  box-shadow: var(--shadow-hollow);
}

.dash-tile__icon svg {
  width: 58%;
  height: 58%;
}

.dash-tile__words {
  display: flex;
  flex-direction: column;
  gap: 0.15em;
  min-width: 0;
}

.dash-tile__name {
  font-family: var(--font-display);
  font-size: 1.02rem;
  line-height: var(--line-height-tight);
}

.dash-tile__note {
  font-family: var(--font-body);
  font-size: var(--font-size-sm);
  line-height: var(--line-height-tight);
  color: var(--color-text-muted);
  text-wrap: pretty;
}

.dash-tile__go {
  flex: none;
  width: 1em;
  height: 1em;
  margin-inline-start: auto;
  color: var(--color-text-muted);
}


/* =============================================================================
   LES FORMULAIRES
   ============================================================================= */

.dash-form {
  display: grid;
  gap: var(--space-md);
  margin-top: var(--space-md);
}

.dash-form--inline {
  margin-top: var(--space-sm);
}

.dash-field {
  display: grid;
  gap: var(--space-2xs);
}

.dash-field__label {
  font-family: var(--font-body);
  font-size: var(--font-size-sm);
  font-weight: 700;
  color: var(--color-text);
}

.dash-field__input {
  width: 100%;
  min-height: 44px;
  padding: var(--space-xs) var(--space-sm);

  font-family: var(--font-body);

  /* 16 px, jamais moins : voir l'en-tête de cette feuille. */
  font-size: 1rem;
  color: var(--color-text);

  background-color: #fff;
  border: 2px solid rgba(60, 39, 35, 0.18);
  border-radius: var(--radius-sm);

  transition: border-color var(--duration-fast) ease;
}

.dash-field__input:hover {
  border-color: rgba(60, 39, 35, 0.32);
}

.dash-field__input:focus {
  border-color: var(--color-brand-amber-deep);
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 1px;
}

.dash-field__help {
  margin: 0;

  font-family: var(--font-body);
  font-size: var(--font-size-sm);
  line-height: var(--line-height-base);
  color: var(--color-text-muted);
  text-wrap: pretty;
}

/* -----------------------------------------------------------------------------
   UN CHAMP REFUSÉ
   -----------------------------------------------------------------------------
   Le nom qu'un joueur se donne s'affiche en face de son adversaire : certains
   mots y sont refusés — voir inc/game/forbidden_words.php. Quand cela arrive,
   l'avertissement se place SOUS LE CHAMP et non en haut du panneau : sur un
   téléphone, les deux ne tiennent pas dans le même écran, et un avertissement
   qu'il faut aller chercher n'avertit personne.

   LE CHAMP SE SIGNALE AUSSI, ET PAS SEULEMENT PAR LA COULEUR : « aria-invalid »
   l'annonce à un lecteur d'écran, et le curseur y est posé. Quelqu'un qui ne
   distingue pas le rouge du brun doit comprendre autant que les autres.
   ----------------------------------------------------------------------------- */

.dash-field__alert {
  margin: var(--space-xs) 0 0;
  text-align: left;
}

.dash-field__input[aria-invalid='true'] {
  border-color: var(--color-danger);
  box-shadow: 0 0 0 2px rgba(180, 67, 43, 0.22);
}

.dash-form__submit {
  /* Pleine largeur sur un téléphone : c'est le geste le plus sûr au pouce. */
  width: 100%;
  padding-inline: var(--space-lg);
}

/* Le piège à robots : hors de l'écran, hors du clavier. */
.dash-form__trap {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}


/* =============================================================================
   L'AVERTISSEMENT DE L'ADRESSE JETABLE
   -----------------------------------------------------------------------------
   Au-dessus du champ, jamais après le refus : dire « trop tard » est une leçon,
   dire « attention » est un service.
   ============================================================================= */

.dash-warning {
  display: flex;
  align-items: flex-start;
  gap: var(--space-xs);

  margin: var(--space-md) 0 0;
  padding: var(--space-sm);

  font-family: var(--font-body);
  font-size: var(--font-size-sm);
  line-height: var(--line-height-base);
  color: var(--color-text);
  text-wrap: pretty;

  background-color: var(--color-brand-amber-light);
  border-radius: var(--radius-sm);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6), var(--shadow-sm);
}

.dash-warning__icon {
  flex: none;
  width: 1.15em;
  height: 1.15em;
  margin-top: 0.15em;
  color: var(--color-brand-dark);
}


/* =============================================================================
   LES TROIS ÉTAPES DE L'ENTRÉE
   ============================================================================= */

ol.dash-steps {
  display: grid;
  gap: var(--space-sm);

  margin: var(--space-md) 0;
  padding: 0;
  list-style: none;
  counter-reset: none;
}

.dash-step {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);

  font-family: var(--font-body);
  font-size: var(--font-size-base);
  line-height: var(--line-height-base);
  color: var(--color-text);
  text-wrap: pretty;
}

.dash-step__rank {
  display: grid;
  place-items: center;
  flex: none;

  width: 1.7rem;
  height: 1.7rem;

  font-family: var(--font-display);
  font-size: 0.95rem;
  color: var(--color-brand-dark);

  background-color: var(--color-brand-amber);
  border-radius: var(--radius-full);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55);
}


/* =============================================================================
   LES FAITS DU COMPTE
   ============================================================================= */

.dash-facts {
  display: grid;
  gap: 1px;

  margin: var(--space-md) 0 0;

  font-family: var(--font-body);
  font-size: var(--font-size-sm);

  background-color: rgba(60, 39, 35, 0.12);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.dash-fact {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-2xs) var(--space-sm);

  padding: var(--space-xs) var(--space-sm);
  background-color: var(--color-sand-100);
}

.dash-fact dt {
  color: var(--color-text-muted);
}

.dash-fact__value {
  margin: 0;
  font-weight: 700;

  /* Une adresse longue ne doit pas pousser la carte hors de l'écran. */
  min-width: 0;
  overflow-wrap: anywhere;
}


/* =============================================================================
   CE QUI DÉTRUIT
   -----------------------------------------------------------------------------
   La terre cuite du soutien, et non l'ambre : l'ambre DÉSIGNE ce qu'on veut
   qu'on fasse. Ici, on veut être sûr que personne ne le fasse par mégarde.
   ============================================================================= */

.dash-danger {
  --danger: #b4432b;

  border: 2px solid rgba(180, 67, 43, 0.35);
}

.dash-danger .account-block__title {
  color: var(--danger);
}

.dash-danger__list {
  display: grid;
  gap: var(--space-2xs);

  margin: var(--space-sm) 0 0;
  padding-left: 1.2em;

  font-family: var(--font-body);
  font-size: var(--font-size-sm);
  line-height: var(--line-height-base);
  color: var(--color-text);
  text-wrap: pretty;
}

/* La case à cocher : grande, et son texte cliquable avec elle. */
.dash-check {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);

  min-height: 44px;
  padding: var(--space-xs) 0;

  font-family: var(--font-body);
  font-size: var(--font-size-sm);
  line-height: var(--line-height-base);
  color: var(--color-text);
  text-wrap: pretty;
  cursor: pointer;
}

/* LA COULEUR DE LA COCHE N'EST PAS TOUJOURS CELLE DU DANGER
   Cette règle est globale, mais « --danger » n'est défini que sur .dash-danger :
   partout ailleurs — la case « je fais confiance à cet appareil », par exemple —
   la déclaration ne valait rien et le navigateur posait SON bleu par défaut, au
   milieu d'un site de sable et d'ambre. La coche prend donc la couleur du site,
   et le bloc de suppression la repeint en terre cuite par sa propre variable. */
.dash-check__box {
  flex: none;
  width: 1.35rem;
  height: 1.35rem;
  margin-top: 0.1em;
  accent-color: var(--danger, var(--color-brand-amber-deep));
  cursor: pointer;
}

.dash-danger__submit {
  width: 100%;
  color: #fff;
  background-color: var(--danger);
  background-image: none;
}

.dash-danger__submit:hover,
.dash-danger__submit:focus-visible {
  background-color: #98361f;
}

/* Une rubrique qui n'existe pas encore : la carte reste, le ton descend. */
.dash-card--soon .account-block__title {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs);
}


/* =============================================================================
   LA PORTE DU COMPTE, SUR LE CARREFOUR
   -----------------------------------------------------------------------------
   Elle porte l'adresse e-mail de qui est connecté. Une adresse n'a ni espace ni
   trait d'union : sur un téléphone, elle poussait la page de trente pixels hors
   de l'écran. Elle se coupe donc où il faut.
   ============================================================================= */

.account-doors .mode-note {
  overflow-wrap: anywhere;
}


/* =============================================================================
   LES MESSAGES
   ============================================================================= */

.account-message--ok,
.account-message--error {
  display: flex;
  align-items: flex-start;
  gap: var(--space-xs);

  padding: var(--space-sm);

  font-family: var(--font-body);
  font-size: var(--font-size-sm);
  line-height: var(--line-height-base);
  text-align: left;
  text-wrap: pretty;

  border-radius: var(--radius-sm);
}

.account-message--ok {
  color: var(--color-text);
  background-color: rgba(106, 153, 78, 0.16);
}

.account-message--error {
  color: #8a2f1c;
  background-color: rgba(180, 67, 43, 0.12);
}

.account-message__icon {
  flex: none;
  width: 1.15em;
  height: 1.15em;
  margin-top: 0.15em;
  color: var(--color-online);
}


/* =============================================================================
   DÈS QU'IL Y A LA PLACE — 48 rem
   -----------------------------------------------------------------------------
   Le menu passe en colonne à gauche, et il y reste : c'est la carte de l'espace,
   elle ne doit pas disparaître quand on entre dans une rubrique.
   ============================================================================= */

@media (min-width: 48rem) {

  .dash-head {
    text-align: left;
  }

  .dash-shell {
    grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
    gap: var(--space-lg);
    align-items: start;
  }

  .dash-nav__list {
    flex-direction: column;
    gap: var(--space-2xs);

    padding: 0;
    overflow: visible;
  }

  .dash-nav__link {
    font-size: var(--font-size-base);
  }

  /* Le libellé d'une rubrique à venir passe à la ligne plutôt que de serrer. */
  .dash-nav__soon {
    margin-inline-start: auto;
  }

  ul.dash-tiles {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .dash-form__submit,
  .dash-danger__submit {
    width: auto;
    justify-self: start;
  }
}


/* =============================================================================
   MOUVEMENT RÉDUIT
   ============================================================================= */

@media (prefers-reduced-motion: reduce) {

  .dash-nav__link,
  .dash-tile,
  .dash-field__input {
    transition: none;
  }
}


/* =============================================================================
   LA DERNIÈRE MARCHE — la page atteinte par le lien de suppression
   -----------------------------------------------------------------------------
   Une page à elle seule : ni menu, ni rubrique, ni raccourci. Quelqu'un qui
   s'apprête à tout perdre n'a pas à choisir entre deux choses.

   La liste de ce qu'on perd y est PLUS GROSSE qu'ailleurs : dans l'espace, c'est
   un avertissement qu'on relit ; ici, c'est la dernière chose qu'on lit avant de
   cliquer.
   ============================================================================= */

.dash-losses {
  display: grid;
  gap: var(--space-xs);

  margin: var(--space-sm) 0 var(--space-md);
  padding-left: 1.2em;

  font-family: var(--font-body);
  font-size: var(--font-size-base);
  line-height: var(--line-height-base);
  color: var(--color-text);
  text-wrap: pretty;
}

.dash-losses li::marker {
  color: var(--danger);
}


/* -----------------------------------------------------------------------------
   « Je fais confiance à cet appareil »

   Une case qui porte DEUX lignes : l'intitulé, et ce qu'il implique. La seconde
   est la plus importante — « je fais confiance » ne dit rien à qui ne sait pas
   ce que le site en fera. Elle explique donc, en une phrase, ce qui se passe
   quand on ferme le navigateur, et pourquoi on décocherait.
   -------------------------------------------------------------------------- */

.dash-check--trust {
  align-items: flex-start;
  margin-bottom: var(--space-sm);

  padding: var(--space-sm) var(--space-md);
  background-color: rgba(255, 255, 255, 0.35);
  border: 1px solid rgba(60, 39, 35, 0.14);
  border-radius: var(--radius-md);
}

.dash-check--trust .dash-check__text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.dash-check__title {
  font-family: var(--font-display);
  font-size: var(--font-size-base);
  color: var(--color-text);
}

.dash-check__note {
  font-size: var(--font-size-sm);
  line-height: var(--line-height-base);
  color: var(--color-text-muted);
  text-wrap: pretty;
}

/* Le texte s'aligne sur la coche, à gauche. Centré à côté d'une case, il flotte
   — le même défaut que les cartes de la clé de sage, corrigé le même jour. */
.dash-check--trust .dash-check__text {
  text-align: left;
}


/* =============================================================================
   L'ESPACE REJOINT LA MATIÈRE DU SITE
   -----------------------------------------------------------------------------
   Il ne la parlait pas. Partout ailleurs, ce qui se clique est un OBJET posé sur
   une table — arête claire au sommet, tranche sombre en bas, ombre qui le
   décolle du sable, et le pictogramme logé dans un creux. Ici, tout était plat :
   des pastilles pâles et une grande carte presque vide.

   Quatre corrections, et pas une de neuve : ce sont les jetons de tokens.css,
   ceux-là mêmes qui font l'accueil, la boutique et la clé de sage.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   1. LE JETON DE L'IDENTITÉ

   Un espace personnel doit commencer par la personne. Il n'y en avait aucune :
   ni qui l'on est, ni sous quelle adresse.

   IL A PORTÉ UNE INITIALE, GRAVÉE DANS LE SABLE, tant que le visage appartenait
   à la seule clé de sage : l'emprunter alors aurait promis une chose qui n'était
   pas vraie. Elle l'est : tout compte porte un profil de joueur, donc un visage.
   Le jeton le montre, et l'initiale a disparu avec sa raison d'être.
   -------------------------------------------------------------------------- */

/* LE JETON : UN VISAGE DANS UN CREUX, ET SON DRAPEAU EN PASTILLE
   -----------------------------------------------------------------------------
   Il portait l'initiale du nom. Il porte le visage du joueur — celui que son
   adversaire voit en face de lui — et, posé dessus, le drapeau du lieu d'où il
   se connecte.

   LA MESURE NE BOUGE PAS : 76 px, comme du temps de l'initiale. Un jeton plus
   gros pousserait le titre et l'adresse vers le bas sur un téléphone, et la
   bande du haut n'a rien à y gagner.

   « position: relative » est ici pour une seule raison : donner son point
   d'ancrage à la pastille du drapeau, qui est en absolu. Sans lui, elle se
   poserait par rapport à la page. */
.dash-badge {
  position: relative;

  width: 76px;
  height: 76px;
  margin: 0 auto var(--space-sm);

  background-color: var(--color-surface);
  background-image: var(--gradient-surface-raised);
  border-radius: 50%;
  box-shadow: var(--shadow-raised);
}

/* Le portrait remplit le rond et n'en sort pas. « object-fit » n'a rien à faire
   ici — le dessin est un carré —, mais le « border-radius » est indispensable :
   le SVG a des coins, et sans lui ils dépasseraient du creux. */
.dash-badge__face {
  display: block;

  width: 100%;
  height: 100%;

  border-radius: 50%;
}

/* LA PASTILLE DU DRAPEAU
   -----------------------------------------------------------------------------
   En bas à droite, à cheval sur le bord du jeton : c'est la place que prend une
   pastille de statut partout ailleurs, et l'œil la lit sans qu'on l'explique.

   Le liseré clair la détache du portrait. Sans lui, un drapeau sombre sur des
   cheveux sombres se fondrait dans le visage.

   Les drapeaux du site sont RONDS — collection circle-flags —, ce qui tombe
   bien : un rectangle dans un rond aurait demandé un masque. */
.dash-badge__flag {
  position: absolute;
  right: -2px;
  bottom: -2px;

  display: block;

  width: 26px;
  height: 26px;

  background-color: var(--color-surface);
  border-radius: 50%;
  box-shadow: 0 0 0 2px var(--color-surface), var(--shadow-raised);
}

.dash-badge__flag img {
  display: block;

  width: 100%;
  height: 100%;

  border-radius: 50%;
}

/* IL EST ATTEIGNABLE AU CLAVIER, DONC IL DOIT SE VOIR QUAND ON L'ATTEINT
   Il porte « tabindex » pour que son infobulle — « France — le lieu de votre
   connexion » — ne soit pas réservée à la souris. Un élément qu'on peut
   atteindre sans voir où l'on est n'est pas atteignable. */
.dash-badge__flag:focus-visible {
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 2px;
}

/* -----------------------------------------------------------------------------
   LE CODE AMI, SOUS LE BONJOUR

   Trois objets sur une ligne : ce que c'est, sa valeur, et de quoi l'emporter.
   Ils se replient dès que la place manque — « flex-wrap », et non trois blocs
   qui s'empilent toujours : sur un écran large la ligne est courte et se lit
   d'un coup d'œil.

   LA VALEUR NE SE COUPE PAS N'IMPORTE OÙ. Vingt-deux signes sans espace
   déborderaient d'un téléphone ; « overflow-wrap: anywhere » les laisse passer
   à la ligne, mais « user-select: all » fait que le clic en prend la TOTALITÉ —
   un code à moitié sélectionné est un code faux, et c'est l'erreur qu'on ferait
   justement sur un code coupé en deux.
   -------------------------------------------------------------------------- */

.dash-head__code {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs) var(--space-xs);

  /* LA PLACE DU BOUTON EST PRISE AVANT QU'IL N'ARRIVE.
     Il vient du serveur caché et n'apparaît qu'une fois le presse-papiers
     reconnu — donc APRÈS le premier dessin. Mesuré : il est plus haut que le
     texte de trois pixels, et la ligne les gagnait en cours de route, poussant
     tout le reste de la page vers le bas. Une hauteur plancher, et les deux
     états occupent exactement la même bande. */
  min-height: 1.6rem;

  margin: var(--space-2xs) 0 0;

  font-family: var(--font-body);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.dash-head__code-label {
  font-weight: 700;
}

/* La même main que les identifiants de l'espace d'audience : une chasse fixe,
   parce qu'on y cherche un signe précis et qu'on le recopie. */
.dash-head__code-value {
  font-family: ui-monospace, Consolas, monospace;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--color-text);

  overflow-wrap: anywhere;
  user-select: all;
}

/* Il se tait : c'est une commodité, pas le sujet de la page. */
.dash-head__code-copy {
  padding: var(--space-2xs) var(--space-xs);
  font-size: var(--font-size-sm);
}

/* -----------------------------------------------------------------------------
   2. LE MENU DEVIENT DES OBJETS

   Des pastilles plates avec une ombre de trois pixels. Elles prennent le relief
   du site, le pictogramme passe dans son creux, et l'entrée ouverte se soulève
   au lieu de changer simplement de couleur.
   -------------------------------------------------------------------------- */

.dash-nav__link {
  background-image: var(--gradient-surface-raised);
  box-shadow: var(--shadow-raised);
  transition: transform var(--duration-fast) ease, box-shadow var(--duration-fast) ease,
              background-color var(--duration-fast) ease;
}

@media (hover: hover) {
  .dash-nav__link:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-raised-hover);
  }
}

@media (prefers-reduced-motion: reduce) {
  .dash-nav__link {
    transition: none;
  }

  .dash-nav__link:hover {
    transform: none;
  }
}

/* L'entrée ouverte : l'ambre, et sa propre tranche — un objet ne se pose pas sur
   un autre matériau que le sien. Elle garde son liseré et « aria-current » : la
   couleur ne porte jamais le sens toute seule. */
.dash-nav__link[aria-current='page'] {
  box-shadow: inset 0 0 0 2px var(--color-brand-amber-deep), var(--shadow-raised-amber);
}

@media (hover: hover) {
  .dash-nav__link[aria-current='page']:hover {
    box-shadow: inset 0 0 0 2px var(--color-brand-amber-deep), var(--shadow-raised-amber-hover);
  }
}

/* Le pictogramme dans son creux, comme les trous du plateau. */
.dash-nav__icon {
  place-items: center;
  width: 28px;
  height: 28px;

  background-color: rgba(60, 39, 35, 0.07);
  border-radius: 50%;
  box-shadow: var(--shadow-hollow);
}

.dash-nav__icon svg {
  width: 17px;
  height: 17px;
}

/* -----------------------------------------------------------------------------
   3. LES TROIS CHIFFRES DE L'ESPACE

   Le même objet que le jeton des chiffres de l'accueil : un seul bloc, des
   filets d'un pixel qui rangent sans découper. Trois textes flottants ne se
   voient pas ; un objet se voit.
   -------------------------------------------------------------------------- */

ul.dash-figures {
  display: flex;
  align-items: stretch;

  margin: var(--space-md) 0 0;
  padding: var(--space-sm) var(--space-xs);
  list-style: none;

  background-color: rgba(240, 225, 209, 0.5);
  background-image: var(--gradient-panel);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-raised);
}

.dash-figure {
  display: flex;
  flex: 1 1 0;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;

  min-width: 0;
  padding: 0 var(--space-xs);
  text-align: center;
}

.dash-figure + .dash-figure {
  border-left: 1px solid rgba(184, 169, 149, 0.55);
}

.dash-figure__value {
  font-family: var(--font-display);
  font-size: clamp(0.95rem, 2.6vw, 1.3rem);
  line-height: 1.1;
  color: var(--color-text);
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
  font-variant-numeric: tabular-nums;
}

.dash-figure__label {
  font-family: var(--font-body);
  font-size: clamp(0.64rem, 1.7vw, 0.78rem);
  line-height: 1.25;
  color: var(--color-text-muted);
  text-wrap: balance;
}

/* -----------------------------------------------------------------------------
   4. LES INTERTITRES D'UNE CARTE

   Une carte porte plusieurs sujets — les dates du compte, les parties jouées,
   le réseau en cours —, et il faut les séparer SANS rouvrir un cadre : le
   bandeau du titre appartient à la carte, et une boîte dans la boîte est
   justement ce que l'espace a retiré (voir 19.3).

   Un intertitre discret suffit : petites capitales, encre sourde, du blanc
   au-dessus. Il dit « on change de sujet » sans redessiner quoi que ce soit.

   IL S'APPELAIT « dash-soon__title »
   Il était né pour « Ce qui vient », rubrique disparue de l'accueil — le menu
   annonce déjà les tournois en gris, et la rubrique fermée l'explique quand on
   l'ouvre. Le dessin, lui, servait à trois endroits : il garde son rôle sous un
   nom qui ne parle plus d'un contenu qui n'existe plus.
   -------------------------------------------------------------------------- */

.dash-subtitle {
  margin: var(--space-lg) 0 var(--space-xs);

  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* -----------------------------------------------------------------------------
   5. « SE DÉCONNECTER » DOIT AVOIR L'AIR D'UN BOUTON

   Il n'en avait pas l'air : un texte gras centré, sans cadre ni relief, au
   milieu d'une carte. Règle « Input Affordance » du skill — un contrôle doit se
   voir comme un contrôle. C'est exactement le défaut relevé sur « Oublier la
   clé » dans sage.php, et corrigé de la même façon : le relief du site.
   -------------------------------------------------------------------------- */

.dash-form--inline .btn {
  min-height: 44px;
  padding-inline: var(--space-md);
  box-shadow: var(--shadow-raised);
}

@media (hover: hover) {
  .dash-form--inline .btn:hover {
    box-shadow: var(--shadow-raised-hover);
  }
}


/* =============================================================================
   L'EN-TÊTE, LE MENU ET LE MESSAGE — seconde passe
   ============================================================================= */

/* -----------------------------------------------------------------------------
   1. L'EN-TÊTE DEVIENT UNE BANDE

   Le jeton, le titre et l'adresse s'empilaient au centre : beaucoup de hauteur
   pour dire un nom. Dès qu'il y a la place, ils se rangent côte à côte — comme
   le panneau d'un joueur dans une partie. Sur un téléphone, ils reprennent la
   colonne : c'est la même bande, pliée.
   -------------------------------------------------------------------------- */

.dash-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);

  width: min(94vw, 720px);
  margin-bottom: var(--space-md);
  text-align: center;
}

.dash-head__words {
  min-width: 0;
}

.dash-head__title {
  margin: 0;

  /* Un cran sous le titre d'une page ordinaire : ici, le sujet est le jeton et
     le nom ensemble, pas le mot seul. */
  font-size: clamp(1.6rem, 4.5vw, 2.4rem);
}

.dash-badge {
  margin: 0;
}

@media (min-width: 48rem) {

  .dash-head {
    flex-direction: row;
    align-items: center;
    gap: var(--space-md);

    width: min(94vw, 62rem);
    text-align: left;
  }

  /* LE TITRE SUIT L'EN-TÊTE, ET NON LA PAGE

     « .account-title » centre son texte, ce qui est juste pour les titres des
     pages du compte : ils coiffent une colonne centrée. Ici, l'en-tête est
     aligné À GAUCHE dès qu'il passe en rangée — et le titre restait centré
     dans une boîte plus large que lui. Mesuré : le « B » de Bonjour tombait
     19,9 px à droite du « C » de Code ami. Le décalage existait déjà du temps
     de l'adresse e-mail ; une adresse en bas de casse le cachait mieux.

     DEUX CLASSES, ET C'EST EXPRÈS : « .account-title » en pèse une, et une
     règle d'un même poids ne l'emporterait que par son ordre dans les
     feuilles — un ordre qui peut changer sans que personne y pense. Celle-ci
     gagne par le sélecteur, ce qui ne dépend de rien. */
  .dash-head .dash-head__title {
    text-align: left;
  }

  /* L'en-tête passe en rangée et se cale à gauche : la ligne du code suit,
     sinon elle resterait centrée sous un titre qui ne l'est plus. */
  .dash-head__code {
    justify-content: flex-start;
    margin-top: var(--space-2xs);
  }
}

/* -----------------------------------------------------------------------------
   2. LE MENU : un nom, et une frontière

   Une colonne qui flotte sans intitulé n'est pas un menu, c'est une pile de
   boutons. Et les rubriques ouvertes ne sont pas de même nature que celles qui
   attendent : un filet les sépare, au lieu de laisser croire qu'on a grisé deux
   entrées au hasard.
   -------------------------------------------------------------------------- */

.dash-nav__title {
  /* Caché sur téléphone : la rangée qui défile se comprend d'elle-même, et
     chaque ligne s'y paie cher. */
  display: none;
}

.dash-nav__rule {
  display: none;
}

/* Le repère « vous êtes ici » : une barre d'ambre au bord de l'entrée ouverte.
   Elle s'ajoute à l'ambre du fond, au liseré et à « aria-current » — quatre
   signaux pour une même chose, dont trois survivent à l'absence de couleur. */
.dash-nav__link[aria-current='page'] {
  position: relative;
}

.dash-nav__link[aria-current='page']::before {
  content: '';
  position: absolute;
  left: 4px;
  top: 50%;
  transform: translateY(-50%);

  width: 3px;
  height: 56%;

  background-color: var(--color-brand-dark);
  border-radius: var(--radius-full);
  opacity: 0.55;
}

/* La mention « bientôt » respire, et cesse de coller au libellé. */
.dash-nav__soon {
  margin-left: auto;
  flex: none;
}

/* -----------------------------------------------------------------------------
   LA PASTILLE DES DEMANDES D'AMI

   Un chiffre au bout de la ligne « Mes amis ». Elle n'est écrite que s'il y a
   quelque chose à compter — une pastille à zéro est un reproche permanent.

   ELLE RESTE VISIBLE QUAND LE MENU EST REPLIÉ, et c'est toute sa raison d'être :
   repliée, la colonne ne montre que des pictogrammes, et c'est précisément là
   qu'on a besoin de savoir que quelqu'un attend. Le nom se cache, elle non — elle
   passe sur le coin du pictogramme.
   -------------------------------------------------------------------------- */

.dash-nav__badge {
  flex: none;
  margin-left: auto;

  min-width: 1.35rem;
  padding: 0 var(--space-2xs);

  font-family: var(--font-body);
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.35rem;
  text-align: center;
  font-variant-numeric: tabular-nums;

  color: #fff;
  background: var(--color-danger);
  border-radius: var(--radius-full);
}

@media (min-width: 48rem) {

  .dash-nav__title {
    display: block;
    margin: 0 0 var(--space-xs);
    padding-left: var(--space-2xs);

    font-family: var(--font-body);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-text-muted);
  }

  .dash-nav__rule {
    display: block;
    height: 1px;
    margin: var(--space-2xs) var(--space-xs);

    background: linear-gradient(to right, transparent, rgba(60, 39, 35, 0.3), transparent);
  }
}

/* -----------------------------------------------------------------------------
   3. LE MESSAGE CESSE D'ÊTRE UNE ALERTE

   C'était le seul élément du site qui ressemblait à une boîte d'avertissement
   d'un cadre tout fait : un rectangle vert pâle, plat, sans matière. Il devient
   un OBJET comme les autres — surface de sable, arête, tranche, ombre — et la
   couleur passe du FOND à la TRANCHE : elle désigne au lieu de remplir.

   Le sens ne repose toujours pas sur elle seule : le pictogramme reste, et le
   texte dit ce qui s'est passé.
   -------------------------------------------------------------------------- */

/* LA LARGEUR NE VAUT QUE POUR LE MESSAGE POSÉ SUR LA PAGE
   Écrite sans le « .dash-page > », elle s'appliquait AUSSI au message de
   register.php, qui vit à l'intérieur d'une carte : 992 px dans un bloc de 720,
   soit 296 px de débordement à droite. Mesuré. Un message dans une carte prend
   la largeur de sa carte, et n'a rien à dire de la sienne. */
.dash-page > .account-message--ok,
.dash-page > .account-message--error {
  width: min(94vw, 720px);
  margin-left: auto;
  margin-right: auto;
}

.account-message--ok,
.account-message--error {
  align-items: center;
  gap: var(--space-sm);

  padding: var(--space-sm) var(--space-md);

  font-size: var(--font-size-base);
  color: var(--color-text);

  background-image: var(--gradient-surface-raised);
  border-left: 4px solid;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-raised);
}

.account-message--ok {
  background-color: var(--color-surface);
  border-left-color: var(--color-online);
}

.account-message--error {
  background-color: var(--color-danger-surface);
  border-left-color: var(--color-danger);
  color: #7a2a18;
}

/* Le pictogramme dans son creux, comme partout ailleurs sur le site. */
.account-message__icon {
  width: 30px;
  height: 30px;
  margin-top: 0;
  padding: 6px;

  background-color: rgba(60, 39, 35, 0.06);
  border-radius: 50%;
  box-shadow: var(--shadow-hollow);
}

@media (min-width: 48rem) {

}


/* =============================================================================
   LA FENÊTRE ENTIÈRE, ET LE MENU QUI SE REPLIE
   -----------------------------------------------------------------------------
   Mesuré sur un écran de 1 920 px : l'espace n'occupait que 808 pixels. Plus de
   la moitié de la fenêtre était du décor. Une page de lecture a raison de se
   tenir à une largeur de lecture ; un ESPACE DE TRAVAIL, non — on y range des
   champs, des faits, des listes, et la place qu'on lui refuse, il la rend en
   hauteur.

   Trois paliers, et rien entre les deux extrêmes :
     · téléphone      une colonne, le menu en rangée qui défile ;
     · 48 rem         deux colonnes, menu à gauche — la tablette ;
     · 75 rem         la coque s'élargit jusqu'à 82 rem, et « ce qui vient »
                      passe sur deux colonnes plutôt que de s'étirer.
   ============================================================================= */

@media (min-width: 75rem) {

  .dash-shell {
    width: min(96vw, 82rem);
    grid-template-columns: minmax(0, 16rem) minmax(0, 1fr);
    gap: var(--space-xl);
  }

  /* Le message et l'en-tête suivent la coque : trois largeurs différentes sur
     une même page se verraient immédiatement. */
  .dash-head,
  .dash-page > .account-message--ok,
  .dash-page > .account-message--error {
    width: min(96vw, 82rem);
  }

  /* Les champs du profil aussi : trois champs empilés dans 1 000 px de large
     laissaient un vide à droite de chacun. Le formulaire devient une grille de
     deux colonnes, et le bouton reprend toute la largeur sous eux.

     « .dash-form » et non « .dash-fields » : ce dernier n'existe pas — je
     l'avais écrit d'après l'idée que je me faisais du balisage, sans le lire. */
  .dash-page .dash-form {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 var(--space-md);
    align-items: start;
  }

  .dash-page .dash-form > .dash-form__submit,
  .dash-page .dash-form > .dash-check {
    grid-column: 1 / -1;
  }
}

/* -----------------------------------------------------------------------------
   LE MENU REPLIÉ — le rail

   Comme dans WordPress : la colonne tombe sur ses pictogrammes, et les mots
   s'effacent. Le bouton reste, et dit ce qu'il fera au prochain clic.

   LES MOTS NE SONT PAS SUPPRIMÉS, ILS SONT CACHÉS À L'ŒIL SEUL : « clip-path »
   plutôt que « display: none », pour qu'un lecteur d'écran continue d'annoncer
   « Mon profil » et non « lien ». Un menu replié reste un menu.
   -------------------------------------------------------------------------- */

.dash-rail {
  display: none;
}

@media (min-width: 48rem) {

  .dash-rail {
    display: flex;
    align-items: center;
    gap: var(--space-xs);

    width: 100%;
    min-height: 44px;
    margin-top: var(--space-sm);
    padding: var(--space-xs) var(--space-sm);

    font-family: var(--font-body);
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    text-align: left;

    background: none;
    border: 0;
    border-top: 1px solid rgba(60, 39, 35, 0.14);
    border-radius: 0;
    cursor: pointer;

    transition: color var(--duration-fast) ease;
  }

  .dash-rail:hover,
  .dash-rail:focus-visible {
    color: var(--color-text);
  }

  .dash-rail__icon {
    display: flex;
    flex: none;
    width: 1.1rem;
    height: 1.1rem;

    /* Le chevron pointe vers la gauche — le sens du repli — et se retourne
       quand la colonne est déjà repliée. */
    transform: rotate(180deg);
    transition: transform var(--duration-fast) ease;
  }

  .dash-rail__icon svg {
    width: 100%;
    height: 100%;
  }

  .dash-shell--rail .dash-rail__icon {
    transform: rotate(0deg);
  }

  /* --- La colonne repliée ------------------------------------------------- */

  .dash-shell--rail {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .dash-shell--rail .dash-nav__title,
  .dash-shell--rail .dash-nav__soon,
  .dash-shell--rail .dash-rail__word {
    /* Hors de l'œil, pas hors de la page : un lecteur d'écran les lit encore. */
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .dash-shell--rail .dash-nav__name {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* LA PASTILLE SURVIT AU REPLI, sur le coin du pictogramme. Le nom disparaît,
     elle reste : une demande qui attend doit se voir quelle que soit la largeur
     de la colonne — c'est le seul endroit du site qui le dise. */
  .dash-shell--rail .dash-nav__link {
    position: relative;
  }

  .dash-shell--rail .dash-nav__badge {
    position: absolute;
    top: 2px;
    right: 2px;

    margin: 0;
    min-width: 1.05rem;
    padding: 0 2px;

    font-size: 0.62rem;
    line-height: 1.05rem;
  }

  .dash-shell--rail .dash-nav__link {
    justify-content: center;
    gap: 0;
    padding-left: var(--space-xs);
    padding-right: var(--space-xs);
  }

  /* La barre « vous êtes ici » n'a plus la place de se loger au bord d'une
     pastille de 48 px : l'ambre et le liseré suffisent, et « aria-current »
     reste. */
  .dash-shell--rail .dash-nav__link[aria-current='page']::before {
    display: none;
  }

  .dash-shell--rail .dash-rail {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
  }
}

/* -----------------------------------------------------------------------------
   L'ÉTIQUETTE DU RAIL

   Replié, le menu ne montre que des pictogrammes : « un dossier », « une
   silhouette », « une coupe » — on devine, on ne sait pas. WordPress fait
   apparaître le nom à côté au survol ; c'est ce qui rend le repli utilisable
   plutôt que malin.

   LE MOT EST DÉJÀ LÀ, il est seulement caché à l'œil : on le remet en vue sur
   l'entrée survolée ou atteinte au clavier. Rien n'est dupliqué, donc rien ne
   peut diverger — et un lecteur d'écran, lui, l'a toujours lu.
   -------------------------------------------------------------------------- */

@media (min-width: 48rem) {

  .dash-shell--rail .dash-nav__link {
    position: relative;
  }

  .dash-shell--rail .dash-nav__link:hover .dash-nav__name,
  .dash-shell--rail .dash-nav__link:focus-visible .dash-nav__name {
    position: absolute;
    left: calc(100% + var(--space-2xs));
    top: 50%;
    transform: translateY(-50%);

    width: auto;
    height: auto;
    overflow: visible;
    clip-path: none;
    z-index: 3;

    padding: var(--space-2xs) var(--space-sm);

    font-family: var(--font-body);
    font-size: var(--font-size-sm);
    color: var(--color-brand-cream);

    background-color: var(--color-surface-dark);
    border-radius: var(--radius-sm);
    box-shadow: 0 6px 16px rgba(60, 39, 35, 0.3);
    pointer-events: none;
  }

  /* La mention « bientôt » suit son nom : une rubrique fermée doit le dire même
     quand le menu est replié, sans quoi on clique pour rien. */
  .dash-shell--rail .dash-nav__link--soon:hover .dash-nav__name::after,
  .dash-shell--rail .dash-nav__link--soon:focus-visible .dash-nav__name::after {
    content: ' · ' attr(data-soon);
    opacity: 0.75;
  }

  /* Le pictogramme reprend sa taille de cible : 44 px, même seul. */
  .dash-shell--rail .dash-nav__link {
    min-width: 44px;
  }
}

/* -----------------------------------------------------------------------------
   LES TRÈS GRANDS ÉCRANS

   À 82 rem, un écran de 1 920 px n'était employé qu'aux deux tiers. Un palier de
   plus le porte à 96 rem — quatre cinquièmes de la fenêtre.

   ET PAS DAVANTAGE : au-delà, ce ne sont plus des blocs qui s'élargissent, ce
   sont des LIGNES DE TEXTE qui s'allongent. Une phrase de cent quatre-vingts
   signes ne se lit pas : l'œil perd le début de la ligne suivante. La règle vaut
   pour un espace de travail comme pour une page de lecture — c'est la même
   rétine.
   -------------------------------------------------------------------------- */

@media (min-width: 100rem) {

  .dash-shell,
  .dash-head,
  .dash-page > .account-message--ok,
  .dash-page > .account-message--error {
    width: min(96vw, 96rem);
  }

  .dash-shell {
    grid-template-columns: minmax(0, 17rem) minmax(0, 1fr);
  }
}

/* -----------------------------------------------------------------------------
   ON ÉLARGIT LES BLOCS, PAS LES PHRASES

   Défaut mesuré aussitôt après avoir élargi la coque : les paragraphes suivaient
   docilement, et atteignaient 148 SIGNES PAR LIGNE sur un écran de 1 600 px. La
   règle en demande 65 à 75 : au-delà, l'œil perd le début de la ligne suivante
   et relit la même deux fois.

   Les CARTES gardent leur largeur — elles portent des formulaires, des tableaux,
   des chiffres, qui gagnent à respirer. Le TEXTE, lui, s'arrête à 70 signes.
   -------------------------------------------------------------------------- */

.dash-page .dash-card .account-block__text,
.dash-page .dash-empty,
.dash-page .account-leave__note,
.dash-page .dash-danger__list,
.dash-page .dash-losses,
.dash-page .dash-field__help,
.dash-page .dash-check__text {
  max-width: 70ch;
}


/* =============================================================================
   LE RAIL A LE DERNIER MOT
   -----------------------------------------------------------------------------
   Écrit avant les paliers de largeur, il était écrasé par eux : « .dash-shell »
   dans une requête de média pèse autant que « .dash-shell--rail », et c'est la
   dernière déclarée qui gagne. Le menu se repliait donc — les mots
   disparaissaient — mais la colonne gardait ses 17 rem : des pastilles vides et
   larges, et pas un pixel rendu au contenu.

   C'est la QUATRIÈME fois de la journée qu'une règle écrite plus haut est
   annulée par une requête de média écrite plus bas (voir 45 pour la boutique, et
   deux fois dans ce chapitre). La parade est toujours la même : déclarer APRÈS
   ce qui doit gagner.
   ============================================================================= */

@media (min-width: 48rem) {

  .dash-shell--rail {
    grid-template-columns: auto minmax(0, 1fr);
  }
}


/* =============================================================================
   TROIS RÉGLAGES D'AFFICHAGE
   ============================================================================= */

/* -----------------------------------------------------------------------------
   1. LE MESSAGE EST DANS LA COLONNE — voir dashboard.php

   Il n'a plus de largeur à lui : il est devenu un élément de la seconde
   colonne de la grille, et prend donc exactement celle des cartes, dans les
   deux états du menu comme à toutes les largeurs.

   Une première version le décalait par un calcul — largeur de la coque moins
   celle du menu, puis un « translateX » de la moitié. Elle supposait le menu
   DÉPLOYÉ et se trompait de 180 px dès qu'il était replié. L'arithmétique ne
   sait pas où commence une colonne ; la grille, si.
   -------------------------------------------------------------------------- */

.dash-main > .account-message--ok,
.dash-main > .account-message--error {
  width: 100%;
  margin: 0;
}

/* -----------------------------------------------------------------------------
   2. LES PICTOGRAMMES SONT CENTRÉS DANS LEUR CREUX

   « place-items » ne fait rien sur une boîte en « flex » : il faut le dire avec
   les deux propriétés de la flexbox. Les dessins tiraient donc vers le haut et
   vers la gauche de leur rond, d'un ou deux pixels — assez pour qu'une colonne
   de cinq pictogrammes paraisse mal rangée sans qu'on sache pourquoi.
   -------------------------------------------------------------------------- */

.dash-nav__icon {
  align-items: center;
  justify-content: center;
}

.dash-nav__icon svg {
  display: block;
}


/* =============================================================================
   LE NOM DANS LA CARTE D'ACCUEIL
   -----------------------------------------------------------------------------
   Les autres chiffres de cette rangée sont courts par nature — une date, un
   compte. Celui-ci est un NOM, et il peut aller jusqu'à quarante signes :
   « Jean-Baptiste Poquelin de Molière » tient à l'aise sur un écran large et
   déborderait d'un téléphone.

   Trois précautions, et pas une de plus :
     · il se coupe s'il le faut — « anywhere », parce qu'un nom peut n'avoir
       aucune espace où se couper proprement ;
     · il garde la police d'affichage mais descend d'un cran : un nom long en
       très grand corps écrase la date à côté de lui ;
     · il ne dépasse jamais sa colonne.

   PLACÉ EN FIN DE FEUILLE, comme toutes les règles qui doivent gagner : une
   règle de même poids déclarée après l'emporte, et « .dash-figure__value » est
   écrite plus haut.
   ============================================================================= */

.dash-figure__value--name {
  max-width: 100%;

  font-size: var(--font-size-button);
  overflow-wrap: anywhere;
  text-wrap: balance;
}


/* =============================================================================
   14. LA MATIÈRE DE L'ESPACE — refonte
   -----------------------------------------------------------------------------
   REPROCHE : « c'est très chargé et pas très design ».

   Le diagnostic, en regardant la page plutôt que la feuille :

     · DEUX GRANDES DALLES DE CRÈME PLEINE, bord à bord, du haut au bas de
       l'écran. Elles enterrent la photographie de village sur laquelle tout le
       site est posé — le fond n'existe plus, et l'espace du compte devient le
       seul endroit du site qui ressemble à un formulaire d'administration ;

     · DES TITRES CENTRÉS SUR DU CONTENU ALIGNÉ À GAUCHE. Ce n'était pas voulu :
       la feuille écrit « text-align: left » sur ces titres depuis toujours, mais
       « .account-block__title » est en « display: flex » avec
       « justify-content: center », et text-align n'a aucune prise sur une boîte
       en flex. L'intention était juste, elle n'était pas appliquée ;

     · DES LIGNES DE FAITS LARGES DE MILLE TROIS CENTS PIXELS, étiquette à
       gauche et valeur à droite : l'œil traverse tout l'écran pour relier deux
       mots qui vont ensemble ;

     · UN BLOC « SUPPRIMER » AUSSI PRÉSENT QUE LE RESTE — même dalle, même
       relief, titre rouge en grand. Une action irréversible qui crie plus fort
       que ce qu'on vient faire.

   LE FOND N'A PAS À ÊTRE UNI, et il ne l'est plus : les cartes deviennent du
   verre dépoli. C'est la matière que le site emploie déjà pour le jeton flottant
   des pages de jeu — voir components/player-space.css. On voit le village au
   travers, adouci ; l'objet reste posé sur la table, mais la table se voit.

   CETTE SECTION EST EN FIN DE FEUILLE, ET C'EST VOULU : elle doit gagner sur les
   règles écrites plus haut, qu'elle corrige sans les effacer — leur commentaire
   raconte l'histoire, et la relire garde son intérêt.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   14.1 Les cartes : du verre, et non de la pierre
   -------------------------------------------------------------------------- */

.dash-page .dash-card {
  /* Le fond translucide laisse passer la photographie ; le flou l'adoucit assez
     pour qu'un texte reste lisible par-dessus. Deux préfixes : Safari ne connaît
     « backdrop-filter » que sous le sien, et c'est justement là que la matière
     compte le plus — un iPhone montre la photographie en grand. */
  background-color: rgba(253, 248, 240, 0.72);
  background-image: none;

  backdrop-filter: blur(14px) saturate(115%);
  -webkit-backdrop-filter: blur(14px) saturate(115%);

  /* UN LISERÉ CLAIR EN HAUT, UNE OMBRE DOUCE EN BAS
     C'est ce qui fait qu'une plaque de verre paraît posée et non collée. Le
     liseré tient lieu de tranche éclairée ; l'ombre, d'appui sur la table. */
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: var(--radius-md);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.6) inset,
    0 10px 28px -14px rgba(60, 39, 35, 0.4);

  /* DE L'AIR. Le reproche premier était la densité : la carte respirait moins
     que son contenu. */
  padding: var(--space-lg) var(--space-lg) var(--space-xl);
}

/* Deux cartes à la suite ne se touchent pas : chacune est un objet. */
.dash-page .dash-card + .dash-card {
  margin-top: var(--space-lg);
}

/* -----------------------------------------------------------------------------
   14.2 Les titres s'alignent sur ce qu'ils titrent

   « text-align: left » ne peut rien sur une boîte en flex : c'est
   « justify-content » qui range, et il valait « center ». D'où des titres
   centrés au-dessus d'un contenu aligné à gauche — la dissonance qu'on lisait
   sans savoir la nommer.
   -------------------------------------------------------------------------- */

.dash-page .dash-card .account-block__title {
  justify-content: flex-start;

  margin-bottom: var(--space-xs);

  /* Un titre de rubrique n'a pas besoin d'être aussi gros qu'un titre de page :
     il y en a un par carte, et le jeton du haut porte déjà le nom. */
  font-size: var(--font-size-lg);
}

/* Le filet sous le titre remplace le blanc qui séparait le titre du texte : il
   dit « ce qui suit appartient à ce titre », et il ne coûte pas de hauteur.
   Né et mort dans le fond, comme tous les filets du site. */
.dash-page .dash-card .account-block__title::after {
  content: '';

  flex: 1;
  height: 1px;
  margin-left: var(--space-sm);

  background-image: linear-gradient(
    to right,
    rgba(60, 39, 35, 0.18),
    rgba(60, 39, 35, 0)
  );
}

/* La phrase d'introduction est une PHRASE : elle s'arrête à une largeur de
   lecture, même quand la carte fait mille pixels. */
.dash-page .dash-card .account-block__text {
  max-width: 62ch;
  color: var(--color-text-muted);
}

/* -----------------------------------------------------------------------------
   14.3 Les faits deviennent des tuiles

   Étiquette au-dessus, valeur en dessous, et trois de front dès qu'il y a la
   place. On lit un fait d'un seul coup d'œil au lieu de traverser l'écran pour
   relier son étiquette à sa valeur.
   -------------------------------------------------------------------------- */

.dash-page .dash-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--space-sm);

  margin-top: var(--space-md);

  /* Le fond et le liseré de l'ancienne liste n'ont plus lieu d'être : ce ne sont
     plus des lignes séparées par des traits, ce sont des objets distincts. */
  background-color: transparent;
  border-radius: 0;
  overflow: visible;
}

.dash-page .dash-fact {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);

  padding: var(--space-sm) var(--space-md);

  background-color: rgba(255, 255, 255, 0.4);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-hollow);
}

.dash-page .dash-fact dt {
  font-size: var(--font-size-sm);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* La valeur est ce qu'on vient chercher : police d'affichage, texte plein, et
   elle se coupe si elle est longue — une adresse e-mail peut l'être. */
.dash-page .dash-fact dd {
  margin: 0;

  font-family: var(--font-display);
  font-size: var(--font-size-base);
  line-height: var(--line-height-tight);
  color: var(--color-text);
  overflow-wrap: anywhere;
}

/* -----------------------------------------------------------------------------
   14.4 Les figures : même matière que les faits

   Elles étaient déjà en rangée ; elles reprennent le creux des tuiles pour que
   l'accueil et « Mon compte » aient la même main.
   -------------------------------------------------------------------------- */

.dash-page .dash-figures {
  gap: var(--space-sm);
}

.dash-page .dash-figure {
  padding: var(--space-md);

  background-color: rgba(255, 255, 255, 0.4);
  border: 0;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-hollow);
}

/* -----------------------------------------------------------------------------
   14.5 La zone qui efface se tait

   Une action irréversible ne doit pas crier plus fort que ce qu'on vient faire.
   Elle portait la même dalle, le même relief, et un titre rouge en grand : elle
   dominait « Votre compte », qui est la raison de la page.

   Elle devient CREUSE — enfoncée dans la table plutôt que posée dessus —, avec
   un liseré rouge ténu pour la borne. Le rouge ne reste franc que là où il
   compte : sur le bouton, au moment du geste.
   -------------------------------------------------------------------------- */

.dash-page .dash-danger {
  background-color: rgba(190, 74, 60, 0.05);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);

  border: 1px solid rgba(190, 74, 60, 0.2);
  box-shadow: var(--shadow-hollow);
}

.dash-page .dash-danger .account-block__title {
  font-size: var(--font-size-base);
  color: var(--color-text);
}

.dash-page .dash-danger .account-block__title::after {
  background-image: linear-gradient(
    to right,
    rgba(190, 74, 60, 0.25),
    rgba(190, 74, 60, 0)
  );
}


/* =============================================================================
   15. LE VERRE DÉPOLI A UN REPLI

   « backdrop-filter » n'est pas partout, et un fond translucide SANS flou
   laisserait lire la photographie à travers le texte. Là où le navigateur ne
   sait pas flouter, la carte redevient opaque : moins jolie, toujours lisible.

   C'est la règle à garder en tête si l'on touche à la section 14 — la beauté
   passe après le fait de pouvoir lire.
   ============================================================================= */

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {

  .dash-page .dash-card {
    background-color: var(--color-surface);
    background-image: var(--gradient-surface-raised);
  }

  .dash-page .dash-danger {
    background-color: var(--color-surface);
    background-image: none;
  }
}


/* =============================================================================
   16. SANS ANIMATION, ET SANS FLOU

   Le flou de fond coûte cher à dessiner sur une machine modeste, et « réduire
   les animations » est la façon dont un système dit « ménagez ma machine ».
   On le retire, et l'on rend le fond opaque pour garder la lisibilité.
   ============================================================================= */

@media (prefers-reduced-motion: reduce) {

  .dash-page .dash-card,
  .dash-page .dash-danger {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;

    background-color: var(--color-surface);
  }
}


/* =============================================================================
   17. UN BOUTON A LA LARGEUR DE CE QU'IL DIT
   -----------------------------------------------------------------------------
   DÉFAUT MESURÉ : « Se déconnecter de cet appareil » s'étirait sur 697 px, soit
   toute la colonne. La feuille prévoyait pourtant le contraire dès 48 rem — mais
   la règle ne visait que « .dash-form__submit » et « .dash-danger__submit », et
   ce bouton-là porte « btn btn--quiet ». Il n'était donc jamais atteint, et
   « .dash-form » étant une grille, il s'étirait comme tout élément de grille.

   On vise désormais le CONTENEUR plutôt que la liste des boutons qu'on espère
   avoir nommés tous : dans une carte de l'espace, un bouton se range à gauche et
   prend la largeur de son texte.

   SUR UN TÉLÉPHONE, RIEN NE CHANGE : pleine largeur, c'est le geste le plus sûr
   au pouce — et c'est pourquoi cette règle est dans une requête de média et non
   au-dessus d'elle.
   ============================================================================= */

@media (min-width: 48rem) {

  .dash-page .dash-card .dash-form > .btn,
  .dash-page .dash-card .dash-form > button {
    width: auto;
    justify-self: start;
  }
}


/* =============================================================================
   18. TOUT S'ALIGNE SUR LA MÊME MARGE
   -----------------------------------------------------------------------------
   « .account-actions » centre ses boutons, et c'est juste là où elle est née :
   sur une page en colonne, posée seule au milieu de l'écran.

   Dans une carte de l'espace, tout le reste est aligné à gauche — le titre, la
   phrase, les tuiles. Deux boutons centrés au milieu de tout cela flottent sans
   raison, et l'œil doit chercher où commence la ligne suivante.

   UNE SEULE MARGE DE DÉPART pour tout ce qu'une carte contient : c'est ce qui
   fait qu'une page se lit sans effort.
   ============================================================================= */

.dash-page .dash-card .account-actions {
  justify-content: flex-start;
}


/* =============================================================================
   19. UN SEUL BLOC PAR SECTION, ET UN BANDEAU DE TITRE
   -----------------------------------------------------------------------------
   TROIS REPROCHES, ET LEUR RÉPONSE COMMUNE

     1. « des blocs dans des blocs, ça charge trop » — l'accueil empilait une
        carte, des tuiles dedans, un item creux encore dedans : trois peaux pour
        dire deux dates, et l'œil compte les cadres avant de lire ;

     2. « beaucoup trop gros, un bloc avec un fond c'est moche : épure » — les
        tuiles faisaient 716 × 78 px pour une date et un nom ;

     3. « tu as trop réduit, tu peux mettre un fond sur les titres, mais pas
        empiler les blocs. Le dashboard doit être design. »

   La réponse aux trois est la même, et c'est un patron connu :

       UN SEUL BLOC PAR SECTION, dont le TITRE est un bandeau plein qui va d'un
       bord à l'autre, et dont le CORPS ne contient plus aucun cadre.

   Le bandeau donne au bloc la présence qu'une épure lui avait retirée — on voit
   où commence une section, et le nom de cette section a du poids. Le corps reste
   nu : les faits y sont des paires étiquette/valeur séparées par un filet, et
   non des boîtes dans une boîte.

   UN CADRE, ET UN SEUL, entre la photographie du fond et le mot qu'on lit.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   19.1 Le bloc : du verre posé sur la table

   Le remplissage passe en propriété séparée par côté : le bandeau doit pouvoir
   déborder à gauche et à droite jusqu'aux bords, et il lui faut pour cela la
   valeur exacte du remplissage à annuler.
   -------------------------------------------------------------------------- */

.dash-page .dash-card {
  --dash-gouttiere: var(--space-lg);

  padding: 0 var(--dash-gouttiere) var(--space-lg);
  overflow: hidden;
}

/* -----------------------------------------------------------------------------
   19.2 Le bandeau du titre

   Il va d'un bord à l'autre du bloc — d'où les marges négatives, qui annulent la
   gouttière — et s'arrête au filet qui le sépare du corps. Les coins du haut
   suivent ceux de la carte : un bandeau à angles droits dans une carte arrondie
   dépasserait de deux pixels à chaque coin, ce qui se voit.
   -------------------------------------------------------------------------- */

.dash-page .dash-card .account-block__title {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  justify-content: flex-start;

  margin: 0 calc(-1 * var(--dash-gouttiere)) var(--space-lg);
  padding: var(--space-sm) var(--dash-gouttiere);

  font-family: var(--font-display);
  font-size: var(--font-size-lg);
  font-weight: 400;
  text-align: left;
  color: var(--color-text);

  /* Un sable un peu plus dense que le verre de la carte : le bandeau se pose
     dessus sans jamais devenir une seconde carte — il n'a ni relief, ni coin
     bas arrondi, ni ombre. */
  background-image: linear-gradient(
    to bottom,
    rgba(240, 225, 209, 0.9),
    rgba(240, 225, 209, 0.62)
  );
  border-bottom: 1px solid rgba(60, 39, 35, 0.12);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
}

/* Le filet qui prolongeait le titre n'a plus lieu d'être : le bandeau va déjà
   jusqu'au bord, et deux traits pour une même séparation font du bruit. */
.dash-page .dash-card .account-block__title::after {
  content: none;
}

/* -----------------------------------------------------------------------------
   19.3 Le corps ne contient AUCUN cadre

   C'est la règle qui répond à « pas empiler les blocs », et elle vaut pour tout
   ce qu'une section peut contenir : les faits de « Mon compte », les figures de
   l'accueil et de « Mes parties », les lignes de « ce qui vient ».
   -------------------------------------------------------------------------- */

.dash-page .dash-card .dash-facts,
.dash-page .dash-card .dash-figures {
  background-color: transparent;
  background-image: none;

  border: 0;
  border-radius: 0;
  box-shadow: none;
  overflow: visible;
}

.dash-page .dash-card .dash-fact,
.dash-page .dash-card .dash-figure {
  padding: 0;

  background-color: transparent;
  background-image: none;

  backdrop-filter: none;
  -webkit-backdrop-filter: none;

  border: 0;
  box-shadow: none;
}

/* -----------------------------------------------------------------------------
   19.4 Les faits et les figures : des colonnes, pas des boîtes

   Étiquette au-dessus, valeur en dessous, et un filet vertical entre deux
   colonnes. C'est la lecture gagnée aux passes précédentes, sans le cadre qui
   l'alourdissait.

   « align-items » ET NON « text-align » : sur une boîte en flex, text-align n'a
   aucune prise — c'est le piège rencontré TROIS FOIS dans ce chantier, aux
   titres, aux figures, et ici.
   -------------------------------------------------------------------------- */

.dash-page .dash-card .dash-fact,
.dash-page .dash-card .dash-figure {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;

  text-align: left;
}

.dash-page .dash-card .dash-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--space-md);

  margin-top: 0;
}

.dash-page .dash-card .dash-figures {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md) var(--space-2xl);

  margin-top: 0;
}

.dash-page .dash-card .dash-figure {
  flex: 0 0 auto;
}

/* L'étiquette est une étiquette : petite, espacée, en retrait. La valeur est ce
   qu'on vient lire : police d'affichage, texte plein, à la mesure du texte
   courant — 20,8 px pour une date était un titre déguisé. */
.dash-page .dash-card .dash-fact dt,
.dash-page .dash-card .dash-figure__label {
  font-family: var(--font-body);
  font-size: var(--font-size-sm);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.dash-page .dash-card .dash-fact dd,
.dash-page .dash-card .dash-figure__value {
  margin: 0;

  font-family: var(--font-display);
  font-size: var(--font-size-base);
  line-height: var(--line-height-tight);
  color: var(--color-text);
  overflow-wrap: anywhere;
}

/* Le filet est à GAUCHE, et non dessous : les faits sont côte à côte, et un
   trait vertical dit « colonne suivante » mieux qu'un blanc. Le premier n'en a
   pas — on ne borne pas ce qui commence. Sur un téléphone ils s'empilent, et un
   trait à gauche n'aurait plus de sens : d'où la requête de média. */
@media (min-width: 48rem) {

  .dash-page .dash-card .dash-facts {
    gap: var(--space-lg);
  }

  .dash-page .dash-card .dash-fact + .dash-fact {
    padding-left: var(--space-lg);
    border-left: 1px solid rgba(60, 39, 35, 0.14);
  }
}

/* Ce qui suit les faits n'a plus de cadre pour s'en séparer : mesuré, le
   paragraphe commençait au pixel exact où ils finissaient et se lisait comme la
   suite du premier. C'est le blanc qui sépare, désormais. */
.dash-page .dash-facts + *,
.dash-page .dash-figures + * {
  margin-top: var(--space-lg);
}

/* -----------------------------------------------------------------------------
   19.5 Les intertitres d'une carte
   -------------------------------------------------------------------------- */

.dash-page .dash-card .dash-subtitle {
  margin-top: var(--space-xl);

  font-family: var(--font-body);
  font-size: var(--font-size-sm);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}


/* -----------------------------------------------------------------------------
   19.6 Le bandeau de la zone qui efface

   Il prend la teinte du danger — assez pour qu'on voie d'un coup d'œil que cette
   section n'est pas comme les autres, pas assez pour crier. Le rouge franc reste
   où il compte : sur le bouton, au moment du geste.

   Déclaré APRÈS le bandeau ordinaire, sans quoi celui-ci l'emporterait : même
   poids de sélecteur, dernier servi.
   -------------------------------------------------------------------------- */

.dash-page .dash-danger .account-block__title {
  background-image: linear-gradient(
    to bottom,
    rgba(190, 74, 60, 0.16),
    rgba(190, 74, 60, 0.07)
  );
  border-bottom-color: rgba(190, 74, 60, 0.22);
}


/* =============================================================================
   20. LE MENU PASSE AU-DESSUS DU CONTENU
   -----------------------------------------------------------------------------
   DÉFAUT SIGNALÉ, ET REPRODUIT : menu replié, l'étiquette qui paraît au survol
   d'un pictogramme — « Mon profil » — disparaissait SOUS la première carte. Elle
   n'était lisible que sur les deux ou trois pixels qui dépassaient du rail.

   LA CAUSE N'EST PAS LE « z-index » DE L'ÉTIQUETTE : il valait déjà 3.
   C'est « backdrop-filter », posé sur les cartes en même temps que le verre
   dépoli. Il crée un CONTEXTE D'EMPILEMENT, et une carte en crée donc un par
   section — peint après le menu, qui le précède dans le document.

   C'est le prix du verre, et il se paie une fois : le menu est remonté dans son
   propre plan, au-dessus de la colonne de droite. L'étiquette y monte avec lui,
   sans qu'on ait à toucher à son z-index — elle vit dans ce plan.

   UNE LEÇON À GARDER : « backdrop-filter », « filter », « transform » et
   « opacity » créent tous un contexte d'empilement. Poser l'un d'eux sur un
   grand bloc, c'est décider que rien de ce qui le précède ne pourra plus passer
   par-dessus — à moins de remonter ce qui doit passer.
   ============================================================================= */

.dash-page .dash-nav {
  position: relative;
  z-index: 2;
}


/* =============================================================================
   21. CE QUE VOUS AVEZ JOUÉ — trois modes, trois barres
   -----------------------------------------------------------------------------
   Une ligne par mode : son nom, son compte, une barre, son taux. Quatre colonnes
   qui s'alignent d'une ligne à l'autre — c'est l'alignement qui rend la
   comparaison possible, et c'est tout l'objet de ce bloc.

   AUCUN CADRE, comme partout dans une carte : un filet horizontal sépare les
   lignes, et rien d'autre. La barre est le seul objet coloré, parce qu'elle est
   la seule chose qu'on lit sans lire.

   LA BARRE PORTE LE TAUX DE VICTOIRES, PAS LA PART DU MODE
   On vient voir comment on s'en sort ; la part se lit déjà dans les nombres à
   côté. Sans partie jouée il n'y a pas de taux : la barre reste vide plutôt que
   de montrer un zéro, qui serait un jugement et non une mesure.

   LA GRILLE PLUTÔT QUE LE FLEX
   Quatre colonnes dont deux se dimensionnent sur leur contenu le plus long,
   toutes lignes confondues : seule une grille sait le faire. En flex, chaque
   ligne se serait rangée pour elle-même, et les taux n'auraient pas été l'un
   sous l'autre.
   ============================================================================= */

/* LA GRILLE SE SERRE SUR SON CONTENU, elle ne s'étale pas sur la carte.
   Avec une colonne en « 1fr », le taux partait à mille pixels de son nom : on ne
   compare bien que ce qui tient dans un regard. La jauge a donc une largeur
   bornée, et « justify-content: start » ramène le tout à gauche. */
ul.dash-modes {
  display: grid;
  grid-template-columns: auto auto minmax(3rem, 14rem) auto;
  justify-content: start;
  gap: 0 var(--space-sm);

  margin: var(--space-sm) 0 0;
  padding: 0;
  list-style: none;
}

.dash-mode {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  align-items: center;

  padding: var(--space-xs) 0;
}

.dash-mode + .dash-mode {
  border-top: 1px solid rgba(184, 169, 149, 0.4);
}

.dash-mode__name {
  font-family: var(--font-display);
  font-size: var(--font-size-sm);
  color: var(--color-text);
}

.dash-mode__count,
.dash-mode__rate {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.dash-mode__rate {
  color: var(--color-text);
}

/* LA JAUGE EST UN SVG, ET CE N'EST PAS UN CAPRICE
   -----------------------------------------------------------------------------
   La politique de sécurité du site refuse les styles en ligne — « style-src
   'self' », sans « unsafe-inline ». Une largeur écrite dans un attribut « style »
   est alors SILENCIEUSEMENT ignorée : mesurée, la barre était pleine à 47 %
   comme à 100 %, et rien n'apparaissait en console.

   Une largeur d'ATTRIBUT SVG n'est pas un style en ligne. C'est la réponse que
   le site emploie déjà pour ses jauges — voir awale_audience_gauge() et l'en-tête
   de pages/audience.css, qui l'écrit noir sur blanc.

   LE RAIL GARDE SA PLACE MÊME VIDE : c'est lui qui aligne les taux les uns sous
   les autres. Il est BORNÉ en largeur — une jauge de mille pixels ne se compare
   pas mieux qu'une de deux cents, elle éloigne seulement le chiffre de son nom.
   -------------------------------------------------------------------------- */

.dash-mode__bar {
  display: block;

  width: 100%;
  max-width: 14rem;
  min-width: 3rem;
  height: 6px;
}

.dash-mode__track {
  fill: rgba(60, 39, 35, 0.1);
}

.dash-mode__fill {
  fill: var(--color-brand-amber-deep);
}

/* SUR UN TÉLÉPHONE, LA BARRE S'EN VA
   Quatre colonnes dans 320 px, ce sont quatre colonnes illisibles. Le nom et le
   compte restent en haut, le taux passe à droite, et le rail disparaît : il
   n'apportait qu'une comparaison, que les chiffres donnent déjà. */
@media (max-width: 30rem) {

  ul.dash-modes {
    grid-template-columns: 1fr auto;
  }

  .dash-mode__bar {
    display: none;
  }

  .dash-mode {
    grid-template-columns: 1fr auto;
    gap: 0 var(--space-xs);
  }

  .dash-mode__count {
    grid-column: 1;
  }

  .dash-mode__name {
    grid-column: 1;
  }

  .dash-mode__rate {
    grid-row: 1 / 3;
    grid-column: 2;
  }
}


/* =============================================================================
   22. EN RÉSEAU, MAINTENANT
   -----------------------------------------------------------------------------
   Une ligne par partie en cours : son code, son état, et de quoi y retourner.
   La liste est écrite par le navigateur — elle vit dans SON stockage, et son
   état vit sur le relais ; le serveur n'en sait rien. Voir dashboard.php.

   ELLE RESSEMBLE AUX LIGNES DE MODE, ET CE N'EST PAS UN HASARD
   Même carte, même absence de cadre, même filet entre les lignes. Ce qui change
   est ce qu'on peut en faire : ici, il y a un bouton au bout.
   ============================================================================= */

/* BORNÉE, comme la grille des modes juste au-dessus : sans cela, « Reprendre »
   partait à mille quatre cents pixels du code qu'il reprend, et l'œil devait
   traverser la carte pour relier les deux. La mesure est celle des lignes de
   mode, aux mots près — les deux blocs se répondent. */
ul.dash-net {
  display: grid;
  gap: 0;

  max-width: 44rem;
  margin: var(--space-sm) 0 0;
  padding: 0;
  list-style: none;
}

.dash-net__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs) var(--space-sm);

  padding: var(--space-xs) 0;
}

.dash-net__row + .dash-net__row {
  border-top: 1px solid rgba(184, 169, 149, 0.4);
}

/* Le code est une valeur qu'on dicte : lettres espacées, et gras. Exactement le
   dessin qu'il a au salon — un même objet doit se reconnaître d'une page à
   l'autre. Voir « .net-game__code » dans pages/net.css. */
.dash-net__code {
  font-family: var(--font-body);
  font-size: var(--font-size-sm);
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--color-text);
}

.dash-net__state {
  flex: 1 1 8rem;

  min-width: 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

/* La pastille de présence : allumée quand l'adversaire est là en ce moment. Elle
   n'est écrite que dans ce cas — une pastille éteinte ne dirait rien que l'état
   juste à côté ne dise déjà.

   Les MÊMES jetons de couleur qu'au salon, et la même mesure en « em » : elle
   suit la taille du texte à côté duquel elle se pose. Voir « .net-game__peer »
   dans pages/net.css — c'est le même objet, il doit avoir le même œil. */
.dash-net__peer {
  flex: none;
  width: 0.7em;
  height: 0.7em;

  background-color: var(--color-online);
  border-radius: var(--radius-full);
  box-shadow: 0 0 0 2px var(--color-online-halo);
}

.dash-net__go {
  flex: none;
  margin-left: auto;
}

/* Une partie que le relais ne connaît plus : la ligne s'efface sans disparaître.
   Le joueur doit voir ce qu'il perd — c'est la règle déjà tenue au salon. */
.dash-net__row--gone .dash-net__code,
.dash-net__row--gone .dash-net__state {
  opacity: 0.55;
}


/* =============================================================================
   23. QUAND IL N'Y A RIEN À MONTRER
   -----------------------------------------------------------------------------
   Il reste UNE phrase de vide sur cette carte : celle des parties en réseau,
   qui n'en sont pas des chiffres mais une liste — une liste vide ne dit rien
   d'elle-même, là où un tableau de zéros, lui, se lit très bien.

   Le tableau des parties, lui, ne se remplace plus par une phrase : il affiche
   des zéros. Voir 24.6.
   ============================================================================= */

.dash-empty {
  margin: var(--space-sm) 0 0;

  font-size: var(--font-size-sm);
  line-height: var(--line-height-base);
  color: var(--color-text-muted);
  text-wrap: pretty;
}

/* UN LIEN, ET NON UN BOUTON
   « Jouer solo » et « Aller au salon » étaient deux boutons. L'ambre du site
   désigne CE QU'ON VIENT FAIRE sur une page, et on ne vient jouer ni sur son
   tableau de bord ni dans ses réglages : ce sont des chemins, pas des gestes.
   Une ligne de texte, sous ce qu'elle prolonge. */
.dash-go {
  margin: var(--space-md) 0 0;
  font-size: var(--font-size-sm);
}

/* IL DOIT AVOIR L'AIR D'UN LIEN
   La remise à zéro du site retire le soulignement de TOUS les « a » — les
   boutons et les jetons n'en veulent pas. Un lien de texte, lui, ne se reconnaît
   qu'à ça : sans soulignement, « Jouer solo » se lisait comme une étiquette
   morte au bas du tableau. Le trait est celui du pied de page, et l'ambre du
   site répond au survol. */
.dash-go a {
  color: var(--color-text);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  transition: color var(--duration-base) ease;
}

.dash-go a:hover,
.dash-go a:focus-visible {
  color: var(--color-brand-amber-deep);
}


/* =============================================================================
   24. L'ACCUEIL REDESSINÉ — reproche : « l'interface est horrible »
   -----------------------------------------------------------------------------
   Et c'était vrai. Mesuré plutôt que ressenti, voici ce qu'on voyait sur un
   écran de 1 920 px :

     · la carte faisait 1 460 px de large et TOUT tenait dans ses 600 px de
       gauche — deux tiers de sable vide, et une page qui semblait inachevée ;
     · les chiffres du jeu plafonnaient à 1,3 rem, soit moins que le texte
       courant du site : un tableau de bord dont les nombres ne se voient pas ;
     · tout était de la même encre sourde et du même corps — intertitres,
       étiquettes, comptes, dates : aucune hiérarchie, donc aucun chemin pour
       l'œil ;
     · et deux dates immobiles pesaient autant que « 1 284 parties jouées ».

   QUATRE CORRECTIONS, ET AUCUN CADRE DE PLUS
   La règle de 19.3 tient : le corps d'une carte ne contient aucune boîte. Ce qui
   change est le RYTHME — la largeur occupée, le corps des nombres, l'encre, et
   les blancs.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   24.1 Les deux dates passent en légende

   Elles disent l'âge du compte et qu'il vit. On les vérifie, on ne les cherche
   pas : petites, en ligne, juste sous le bandeau du titre.
   -------------------------------------------------------------------------- */

.dash-page .dash-card .dash-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs) var(--space-lg);

  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.dash-meta__item {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-2xs);
}

.dash-meta__value {
  font-family: var(--font-display);
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}

/* Le fuseau, en plus petit que l heure qu il qualifie : on le lit une fois, et
   on ne le relit plus. Sans lui, « 11:24 » serait faux pour qui lit la page
   depuis un autre fuseau — et le site est servi en dix langues. */
.dash-meta__zone {
  font-size: 0.82em;
  color: var(--color-text-muted);
}

/* -----------------------------------------------------------------------------
   24.2 Deux colonnes : ce qui est passé, ce qui est en cours

   Le partage est LOGIQUE et non décoratif : à gauche ce qu'on a joué — des
   totaux, rien à faire —, à droite ce qui attend un coup, avec un bouton au
   bout. Les deux se répondent au lieu de se suivre, et la carte cesse d'être
   vide sur sa moitié droite.

   UN FILET, PAS UN CADRE : la séparation est une bordure de 1 px sur la seconde
   colonne, et rien d'autre. Sous 64 rem les colonnes s'empilent, et le filet
   passe au-dessus — il sépare toujours les deux, dans l'autre sens.
   -------------------------------------------------------------------------- */

.dash-split {
  display: grid;
  gap: var(--space-xl);
  margin-top: var(--space-lg);
}

.dash-split__part {
  min-width: 0;
}

@media (min-width: 64rem) {

  .dash-split {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: var(--space-2xl);
  }

  .dash-split__part + .dash-split__part {
    padding-left: var(--space-2xl);
    border-left: 1px solid rgba(184, 169, 149, 0.45);
  }
}

@media (max-width: 63.9375rem) {

  .dash-split__part + .dash-split__part {
    padding-top: var(--space-lg);
    border-top: 1px solid rgba(184, 169, 149, 0.45);
  }
}

/* -----------------------------------------------------------------------------
   24.3 Les chiffres se voient enfin

   Un tableau de bord se lit de loin : le nombre d'abord, son mot ensuite. Le
   corps suit la fenêtre, et il est BORNÉ des deux côtés — en dessous parce
   qu'un chiffre de tableau de bord ne descend pas au corps du texte courant, au
   dessus parce que « 25 503 » en très grand déborderait de sa colonne.

   Déclaré après 19.4, qui met les figures à plat : même poids de sélecteur,
   dernier servi.
   -------------------------------------------------------------------------- */

/* Les trois figures se serrent sur leur contenu — 19.4 leur a retiré le
   « flex: 1 », et c'est heureux : « 1 284 », « 613 » et « 48 % » n'ont pas la
   même largeur, et les étaler à parts égales creuserait des trous irréguliers
   entre elles. Elles forment un groupe, séparé par du blanc — qu'il faut donc
   large, sans quoi les nombres se touchent au corps où ils sont désormais. */
.dash-page .dash-card .dash-figures {
  gap: var(--space-2xl);
  margin-top: var(--space-sm);
}

.dash-page .dash-card .dash-figure {
  align-items: flex-start;
  gap: 0;
  text-align: left;
}

.dash-page .dash-card .dash-figure + .dash-figure {
  border-left: 0;
}

.dash-page .dash-card .dash-figure__value {
  font-size: clamp(1.75rem, 3.4vw, 2.5rem);
  line-height: 1;
  letter-spacing: -0.01em;
}

.dash-page .dash-card .dash-figure__label {
  margin-top: var(--space-2xs);

  font-size: var(--font-size-sm);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: none;
  color: var(--color-text-muted);
}

/* -----------------------------------------------------------------------------
   24.4 Les lignes de mode respirent, et se lisent

   Le nom passe au corps du texte et à l'encre pleine — c'est lui qu'on cherche.
   Le compte reste sourd, la jauge s'allonge, le taux prend la police
   d'affichage : trois poids pour trois rôles, sur une ligne.
   -------------------------------------------------------------------------- */

.dash-page .dash-card .dash-modes {
  grid-template-columns: auto auto minmax(4rem, 1fr) auto;
  gap: 0 var(--space-md);
  margin-top: var(--space-md);
}

.dash-page .dash-card .dash-mode {
  padding: var(--space-sm) 0;
}

.dash-page .dash-card .dash-mode__name {
  font-size: var(--font-size-base);
}

/* La jauge remplit sa colonne au lieu de s'arrêter à 14 rem : dans une demi-carte
   elle n'a plus rien d'immense, et le taux restait sinon à deux cents pixels de
   la barre qu'il chiffre. La borne de 21 valait pour une carte pleine largeur. */
.dash-page .dash-card .dash-mode__bar {
  max-width: none;
}

.dash-page .dash-card .dash-mode__rate {
  font-family: var(--font-display);
  font-size: var(--font-size-base);
}

/* -----------------------------------------------------------------------------
   24.5 Une partie en réseau est un objet, pas une ligne de texte

   Le code devient un JETON — la matière des petits jetons du site, sable
   translucide et arête claire —, parce que c'est une valeur qu'on dicte au
   téléphone et qu'on doit retrouver d'un coup d'œil. L'état se range à côté, et
   le bouton ferme la ligne.

   Trois colonnes : le jeton, ce qu'il en est, le geste. Elles s'alignent d'une
   ligne à l'autre.
   -------------------------------------------------------------------------- */

.dash-page .dash-card .dash-net {
  max-width: none;
  margin-top: var(--space-md);
}

.dash-page .dash-card .dash-net__row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--space-sm);

  padding: var(--space-sm) 0;
}

.dash-page .dash-card .dash-net__code {
  padding: 0.35em 0.7em;

  font-size: var(--font-size-base);

  background-color: rgba(240, 225, 209, 0.72);
  background-image: var(--gradient-surface-raised);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-raised);
}

/* L'état PORTE sa pastille, il ne l'a pas pour voisine : elle fait partie de la
   phrase qu'elle éclaire, et la grille garde ses trois colonnes.

   En flex, parce qu'un « span » est « inline » par défaut et qu'une pastille
   inline n'a pas de largeur — mesurée, elle faisait zéro pixel et ne se voyait
   pas du tout. */
.dash-page .dash-card .dash-net__state {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--space-2xs);
}

.dash-page .dash-card .dash-net__go {
  margin-left: 0;
}

/* -----------------------------------------------------------------------------
   24.6 Le vide n'est pas un trou

   LE TABLEAU DES PARTIES NE DISPARAÎT PLUS quand il n'y a rien : il affiche des
   zéros. Un zéro DIT qu'on n'a pas encore joué, et il le dit à l'endroit exact
   où le chiffre apparaîtra — là où une phrase à la place du tableau obligeait la
   page à changer de forme en cours de route.

   Reste la liste du réseau, qui est une LISTE : vide, elle ne dit rien d'elle-
   même, et sa phrase garde donc sa place.
   -------------------------------------------------------------------------- */

.dash-page .dash-card .dash-empty {
  max-width: 44ch;
  margin-top: var(--space-md);
}

.dash-page .dash-card .dash-go {
  margin-top: var(--space-lg);
}

/* -----------------------------------------------------------------------------
   24.7 Sur un téléphone, la carte reprend le dessus

   PIÈGE DE SPÉCIFICITÉ, ET IL AURAIT ÉCHAPPÉ À L'ŒIL
   Le repli des lignes de mode est écrit en 21 sous « ul.dash-modes » — poids
   (0,1,0). Les règles de 24.4 portent « .dash-page .dash-card .dash-modes » —
   poids (0,3,0) — et n'ont AUCUNE borne de largeur : sur un téléphone, elles
   battaient le repli, et les quatre colonnes restaient. Une media query ne pèse
   rien dans la cascade ; seul le sélecteur compte.

   Le repli est donc réécrit ici au même poids que ce qu'il doit battre, et sous
   la même borne. La leçon est la même que pour les corrections de fin de
   feuille : ce n'est pas l'ordre qui décide, c'est le poids — puis l'ordre.
   -------------------------------------------------------------------------- */

@media (max-width: 30rem) {

  .dash-page .dash-card .dash-modes {
    grid-template-columns: 1fr auto;
    gap: 0 var(--space-xs);
  }

  .dash-page .dash-card .dash-mode__bar {
    display: none;
  }

  /* La ligne du réseau se plie aussi : le jeton et l'état en haut, le bouton
     sous eux, plutôt que trois colonnes dans trois cent cinquante pixels. */
  .dash-page .dash-card .dash-net__row {
    grid-template-columns: auto 1fr;
  }

  .dash-page .dash-card .dash-net__go {
    grid-column: 1 / -1;
    justify-self: start;
  }
}


/* =============================================================================
   25. « QUI VOUS ÊTES » — un champ, et un bouton à sa taille
   -----------------------------------------------------------------------------
   SIGNALÉ : « le bouton enregistrer est beaucoup trop gros ».

   Mesuré, il l'était : 184 × 59 px, à 24 px de corps dans la police
   d'affichage — pour un champ facultatif de 46 px de haut. Il était PLUS GRAND
   que ce qu'il enregistre, et portait la matière des grands boutons du site,
   celle de « Jouer Solo » : une décision d'écran, pas un petit enregistrement.

   La carte, elle, faisait 1 460 px et tout tenait dans ses 800 px de gauche.

   UN FORMULAIRE D'UN SEUL CHAMP SE LIT COMME UNE PHRASE
   Voici le champ, voici ce qu'on en fait. Les deux vont donc sur la même ligne,
   et le bouton prend EXACTEMENT la hauteur du champ — c'est « align-items:
   stretch » qui le lui donne, sans qu'aucune hauteur ne soit écrite nulle part :
   le jour où le champ grandit, le bouton suit.

   IL RESTE AMBRE, ET C'EST VOULU
   Sur le tableau de bord, l'ambre a été retiré de « Jouer solo » parce qu'on ne
   vient pas jouer sur son tableau de bord. Ici, enregistrer EST ce qu'on vient
   faire sur cette carte : le ton reste, seule la taille change.
   ============================================================================= */

.dash-field__row {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: var(--space-sm);

  margin-top: var(--space-2xs);
}

/* Le champ occupe la place, sans s'étendre jusqu'au bord : un nom fait quarante
   signes au plus, et une ligne de saisie de mille pixels pour quarante signes
   se lit comme une erreur de mise en page. */
.dash-field__row .dash-field__input {
  flex: 1 1 18rem;
  max-width: 26rem;
  margin-top: 0;
}

/* -----------------------------------------------------------------------------
   25.1 Le bouton à la taille de sa ligne

   Le corps du texte courant au lieu du corps d'affichage, la gouttière au lieu
   des 75 px du bouton de plein écran, et aucune hauteur : il prend celle du
   champ. Déclaré après « .dash-form__submit », qui le veut pleine largeur sur un
   téléphone — ici, c'est la ligne qui décide de sa largeur.
   -------------------------------------------------------------------------- */

.dash-page .dash-card .dash-form__submit--inline {
  flex: none;
  width: auto;
  padding: 0 var(--space-lg);

  font-size: var(--font-size-base);
  white-space: nowrap;
}

/* SUR UN TÉLÉPHONE, LE BOUTON REPREND TOUTE LA LARGEUR
   Le champ et le bouton ne tiennent pas côte à côte sous 30 rem : « flex-wrap »
   les empile déjà, et le bouton redevient alors ce qu'il doit être au pouce —
   une cible pleine largeur. */
@media (max-width: 30rem) {

  .dash-page .dash-card .dash-form__submit--inline {
    width: 100%;
  }
}

/* L'aide passe sous la ligne entière, et non sous le seul champ : elle parle de
   ce qu'on écrit, pas de ce qu'on clique. Bornée à sa mesure de lecture. */
.dash-page .dash-card .dash-field__row + .dash-field__help {
  max-width: 46ch;
  margin-top: var(--space-xs);
}


/* =============================================================================
   26. « SUPPRIMER MON COMPTE » RENTRE DANS LE RANG
   -----------------------------------------------------------------------------
   Reproche : cette section ne ressemblait pas au reste de la page. Mesuré, elle
   ne lui ressemblait en effet sur aucun point :

     · la CARTE ENTIÈRE était lavée de rouge — fond, bordure et bandeau —, quand
       partout ailleurs le bandeau porte la couleur et le corps reste neutre ;
     · le BOUTON faisait 449 × 59 px à 24 px de corps, en rouge plein : l'objet
       le plus imposant de tout l'espace était celui qui efface, alors que la
       feuille écrit trois fois qu'il doit « se taire » ;
     · les trois faits étaient une LISTE À PUCES, la seule de l'espace, où les
       autres cartes alignent des paires étiquette/valeur ou des lignes réglées ;
     · et la case à cocher flottait au-dessus du bouton sans lien visible, alors
       que c'est elle qui le déverrouille.

   CE QUI CHANGE, ET CE QUI NE CHANGE PAS
   Le ton reste : c'est bien la zone qui détruit, et elle doit se reconnaître.
   Mais elle se reconnaît par son BANDEAU, comme les autres se reconnaissent par
   le leur — pas en criant sur toute sa hauteur.

   Le bouton reste ROUGE. Il ne devient pas un lien : ici, le clic engage, et
   c'est exactement ce qu'un bouton dit. Il prend seulement la taille des autres
   commandes de l'espace — celle de « Se déconnecter de cet appareil », mesurée
   à 47 px de haut.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   26.1 Le corps redevient neutre

   Seul le bandeau garde la teinte — il est déclaré en 19.6, et rien n'y touche.
   La carte reprend la matière de toutes les autres : du verre posé sur la table.
   Un liseré rouge ténu reste sur son pourtour, assez pour dire « pas comme les
   autres », pas assez pour crier.
   -------------------------------------------------------------------------- */

.dash-page .dash-danger {
  background-color: rgba(255, 255, 255, 0.28);
  border-color: rgba(190, 74, 60, 0.28);
}

/* -----------------------------------------------------------------------------
   26.2 Les trois faits deviennent des lignes réglées

   La même main que les lignes de mode du tableau de bord : pas de puce, un filet
   entre les faits, et rien d'autre.

   ILS S'ÉTALENT SUR LA LARGEUR, comme les trois faits de la carte « Votre
   compte » juste au-dessus : trois colonnes de 394 px contre ses trois de 378.
   Sans cela, la carte faisait 1 232 px et son texte s'arrêtait à 551 — un tiers
   écrit, deux tiers de sable.

   SEULEMENT ICI, ET C'EST DEMANDÉ : la page qu'ouvre le lien du courriel garde
   sa colonne étroite. C'est le dernier clic avant l'effacement ; on n'y étale
   pas, on y lit. Elle porte « .dash-losses », que ces règles ne visent pas.
   -------------------------------------------------------------------------- */

.dash-page .dash-danger .dash-danger__list {
  /* La mesure de lecture est posée SUR CHAQUE FAIT, et non sur la liste : posée
     sur la liste, elle la coupait à 551 px au milieu d'une carte de 1 232 px, et
     les filets s'arrêtaient en plein vide. */
  max-width: none;

  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 0;

  margin-top: var(--space-md);
  padding-left: 0;
  list-style: none;
}

/* Un filet vertical entre les faits. « :first-child » ne suffirait pas à savoir
   qui ouvre une rangée — il n'en couvrirait qu'un sur trois : on borde donc TOUS
   les faits à gauche, et on retire le trait du tout premier. Les colonnes étant
   égales, le compte tombe juste. */
.dash-page .dash-danger .dash-danger__list li {
  max-width: 40ch;
  padding: var(--space-xs) var(--space-md);
  border-left: 1px solid rgba(190, 74, 60, 0.18);
}

.dash-page .dash-danger .dash-danger__list li:first-child {
  border-left: 0;
  padding-left: 0;
}

/* Empilés, le filet passe au-dessus : il sépare toujours, dans l'autre sens. */
@media (max-width: 52rem) {

  .dash-page .dash-danger .dash-danger__list li {
    padding: var(--space-sm) 0;
    border-left: 0;
  }

  .dash-page .dash-danger .dash-danger__list li + li {
    border-top: 1px solid rgba(190, 74, 60, 0.18);
  }
}

/* -----------------------------------------------------------------------------
   26.3 La case et le bouton sont un seul geste

   Cocher DÉVERROUILLE : les deux vont donc sur la même ligne, la case d'abord,
   le bouton au bout — on lit « je comprends », puis on demande. Sous 40 rem ils
   s'empilent, et le bouton reprend toute la largeur : au pouce, c'est la cible
   la plus sûre.
   -------------------------------------------------------------------------- */

.dash-page .dash-danger .dash-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm) var(--space-lg);

  margin-top: var(--space-md);
}

/* Elle ne s ÉTIRE PAS : sinon son étiquette pousse le bouton au bord de la
   carte, à mille pixels de la case qui le déverrouille. Elle prend la largeur
   de sa phrase, et le bouton la suit. */
.dash-page .dash-danger .dash-check {
  flex: 0 1 auto;
  max-width: 46ch;
  min-height: 0;
  padding: 0;
}

/* -----------------------------------------------------------------------------
   26.4 Le bouton qui DEMANDE prend la taille des autres commandes

   Le corps du texte courant au lieu du corps d'affichage, et la gouttière au
   lieu des 75 px du bouton de plein écran. Il garde son rouge : c'est la seule
   chose qui doit rester franche.

   IL VISE « .dash-form », ET C'EST TOUT L'ARBITRAGE
   Deux boutons rouges existent dans l'espace, et ils ne font pas la même chose :
   celui-ci DEMANDE — il envoie un lien, rien n'est effacé —, tandis que
   « Supprimer définitivement », sur la page qu'ouvre ce lien, EFFACE. Le second
   garde donc sa pleine présence : c'est le dernier clic, et il doit peser ce
   qu'il vaut. Il vit dans un formulaire nu, sans « .dash-form » : le sélecteur
   les sépare sans qu'on ait eu à inventer une classe.

   Déclaré après « .dash-danger__submit », qui le veut pleine largeur.
   -------------------------------------------------------------------------- */

.dash-page .dash-danger .dash-form .dash-danger__submit {
  flex: none;
  width: auto;
  padding: var(--space-sm) var(--space-lg);

  font-size: var(--font-size-base);
  white-space: nowrap;
}

@media (max-width: 40rem) {

  .dash-page .dash-danger .dash-form .dash-danger__submit {
    width: 100%;
  }
}

/* La note sous le bouton : elle dit que ce clic n'efface rien, et c'est la
   phrase la plus rassurante de la carte. Elle reste près de lui. */
.dash-page .dash-danger .dash-form + .account-block__text {
  margin-top: var(--space-sm);
}



/* =============================================================================
   27. « MES AMIS » — un visage, un nom, un pays, un geste
   -----------------------------------------------------------------------------
   Trois colonnes qui s'alignent d'une ligne à l'autre : le visage, qui l'on est,
   ce qu'on peut faire. C'est l'alignement qui fait qu'une liste se parcourt d'un
   regard au lieu de se lire ligne à ligne — la même raison qu'au bloc 21, et la
   même construction : une grille sur la liste, « subgrid » sur chaque ligne.

   AUCUN CADRE, comme partout dans une carte : un filet horizontal entre les
   lignes, et rien d'autre.

   SUR UN TÉLÉPHONE, LES BOUTONS PASSENT DESSOUS. Garder trois colonnes sur
   360 px écraserait le nom à deux mots par ligne pour laisser la place à deux
   boutons ; le visage et le nom gardent leur rangée, les gestes prennent la
   leur, alignés à gauche sous le nom.
   ========================================================================== */

.dash-friends__list {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;

  margin: var(--space-sm) 0 0;
  padding: 0;
  list-style: none;
}

.dash-friends__row {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  align-items: center;
  gap: 0 var(--space-sm);

  padding: var(--space-sm) 0;
}

.dash-friends__row + .dash-friends__row {
  border-top: 1px solid rgba(184, 169, 149, 0.4);
}

/* LE VISAGE ARRIVE ANONYME ET SE DESSINE ENSUITE — voir avatar/faces.js. Sa
   taille est posée ici ET dans l'attribut de l'image : la place est prise avant
   que le portrait n'arrive, sinon toute la liste se décalerait à son arrivée. */
.dash-friends__face {
  width: 48px;
  height: 48px;
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.45);
}

.dash-friends__who {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.dash-friends__name {
  font-family: var(--font-display);
  font-size: var(--font-size-base);
  color: var(--color-text);
  overflow-wrap: anywhere;
}

/* Le pays, d'où vient la demande, depuis quand : tout ce qui n'est pas le nom
   tient sur une seule ligne grise, et se replie si la place manque. */
.dash-friends__note {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2xs);

  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.dash-friends__flag {
  width: 18px;
  height: 18px;
  border-radius: var(--radius-full);
}

.dash-friends__acts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2xs);
}

/* LES BOUTONS D'UNE LISTE NE SONT PAS CEUX D'UNE PAGE. Ils se répètent à chaque
   ligne : à la taille ordinaire, une liste de dix amis deviendrait un mur de
   boutons. Ils prennent donc la mesure d'une commande de liste — c'est la même
   décision qu'au bouton « Demander la suppression », qui n'efface rien. */
.dash-friends__btn {
  padding: var(--space-2xs) var(--space-sm);
  font-size: var(--font-size-sm);
}

/* ARMÉ : le premier clic sur « Retirer » ne retire rien, il demande à être
   confirmé. Le bouton le DIT — il change de mot — et le montre : sans la
   couleur, un lecteur d'écran entendrait le nouveau mot, et un daltonien ne
   verrait rien changer. Les deux, donc. */
.dash-friends__btn--armed {
  color: var(--color-danger);
  font-weight: 700;
}

/* L'état d'une demande envoyée : « En attente », « Demande close ». Ce n'est pas
   un bouton, et il ne doit pas en avoir l'air — on ne clique pas dessus. */
.dash-friends__state {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  white-space: nowrap;
}

/* Une demande close a été répondue : la ligne s'efface un peu, sans disparaître.
   Elle reste lisible — c'est une information, pas une punition. */
.dash-friends__row--closed .dash-friends__face,
.dash-friends__row--closed .dash-friends__name {
  opacity: 0.6;
}

@media (max-width: 34rem) {

  /* Deux colonnes, et les gestes sur leur propre rangée sous le nom. */
  .dash-friends__list {
    grid-template-columns: auto 1fr;
  }

  .dash-friends__acts {
    grid-column: 2;
    margin-top: var(--space-2xs);
  }
}

/* -----------------------------------------------------------------------------
   AJOUTER UN AMI — le champ du code

   Le code fait vingt-deux signes de base64url, majuscules et minuscules mêlées :
   une chasse fixe pour qu'on puisse VÉRIFIER ce qu'on a collé, signe à signe.
   C'est la même main que le code ami de l'en-tête, et pour la même raison.
   -------------------------------------------------------------------------- */

.dash-friends-add__input {
  font-family: ui-monospace, Consolas, monospace;
  letter-spacing: 0.02em;
}

/* Le mot qui répond — « la demande est partie », « aucun joueur ne porte ce
   code » — se pose sous le champ, pas sous la carte entière. */
.dash-page .dash-card .dash-friends-add__message {
  margin: var(--space-sm) 0 0;
}


/* =============================================================================
   28. AMIS EN LIGNE — à côté des parties en réseau
   -----------------------------------------------------------------------------
   Une ligne par ami présent : son visage, son nom, et de quoi lui proposer une
   partie. La même main que la liste « Mes amis », en plus serré — ce bloc vit
   dans une colonne, à côté d'une autre liste.

   LE VISAGE PORTE DEUX PASTILLES, et elles ne disent pas la même chose : le
   DRAPEAU dit d'où l'ami se connecte, le POINT VERT dit qu'il est là. Elles sont
   posées sur deux coins différents pour qu'on ne les confonde jamais.
   ========================================================================== */

.dash-live {
  display: flex;
  flex-direction: column;

  margin: var(--space-sm) 0 0;
  padding: 0;
  list-style: none;
}

.dash-live__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2xs) var(--space-sm);

  padding: var(--space-xs) 0;
}

.dash-live__row + .dash-live__row {
  border-top: 1px solid rgba(184, 169, 149, 0.4);
}

/* Le cadre du visage porte les deux pastilles : il est donc le repère de leur
   position, et sa taille est posée ici ET sur l'image — la place est prise
   avant que le portrait ne soit dessiné, sinon la ligne sauterait. */
.dash-live__face {
  position: relative;
  flex: none;
  width: 40px;
  height: 40px;
  margin: 0;
}

.dash-live__portrait {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.45);
}

/* D'OÙ IL SE CONNECTE — en bas à gauche, comme le drapeau du jeton du haut. */
.dash-live__flag {
  position: absolute;
  left: -2px;
  bottom: -2px;

  width: 18px;
  height: 18px;
  border-radius: var(--radius-full);
  box-shadow: 0 0 0 2px var(--color-surface);
}

/* QU'IL EST LÀ — en haut à droite, à l'opposé, et d'un vert qui ne ressemble à
   aucun drapeau du site. Le cerne le détache de n'importe quel portrait. */
.dash-live__dot {
  position: absolute;
  right: -1px;
  top: -1px;

  width: 12px;
  height: 12px;
  border-radius: var(--radius-full);

  background: var(--color-online);
  box-shadow: 0 0 0 2px var(--color-surface);
}

.dash-live__who {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  flex: 1 1 8rem;
}

.dash-live__name {
  font-family: var(--font-display);
  font-size: var(--font-size-sm);
  color: var(--color-text);
  overflow-wrap: anywhere;
}

/* « vous propose une partie » : c'est ce qui distingue une invitation d'une
   simple présence, et cela doit se lire avant le bouton. */
.dash-live__note {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

/* Le geste tient à sa place : ce bloc est une colonne, pas une page. */
.dash-live__go {
  flex: none;
  padding: var(--space-2xs) var(--space-sm);
  font-size: var(--font-size-sm);
  text-decoration: none;
}

/* Le titre du second bloc de la colonne respire : deux listes collées se
   liraient comme une seule. */
.dash-subtitle--spaced {
  margin-top: var(--space-lg);
}

/* =============================================================================
   29. LA PASTILLE DE PRÉSENCE DANS « MES AMIS »
   -----------------------------------------------------------------------------
   LE MÊME SIGNE AU MÊME ENDROIT QUE DANS LE BLOC DES AMIS EN LIGNE : un point
   vert en haut à droite du visage. Deux écrans montrent la présence, et ils ne
   doivent pas l'écrire de deux façons — on n'apprend pas deux fois la même
   chose.

   Le cadre est posé sur TOUS les visages, présent ou non : sans lui, la liste se
   décalerait selon qui est connecté au moment du chargement.
   ========================================================================== */

.dash-friends__portrait {
  position: relative;
  display: block;
  flex: none;
  width: 48px;
  height: 48px;
}

/* Le liseré de la couleur du fond détache le point du portrait, quelle que soit
   la couleur du visage dessous — sans lui, un point vert sur un habit vert
   disparaît. */
.dash-friends__dot {
  position: absolute;
  right: -1px;
  top: -1px;

  width: 13px;
  height: 13px;
  border-radius: var(--radius-full);

  background: var(--color-online);
  box-shadow: 0 0 0 2px var(--color-surface);
}


/* =============================================================================
   30. LES AUTORISATIONS DONNÉES AUX AMIS
   -----------------------------------------------------------------------------
   Deux lignes à cocher, et rien d'autre. Chaque ligne est un <label> entier :
   toute sa surface répond, ce qui compte sur un téléphone où viser une case de
   16 px est pénible.
   ========================================================================== */

.dash-rights {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.dash-rights__line {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);

  padding: var(--space-sm);
  border: 1px solid rgba(184, 169, 149, 0.55);
  border-radius: var(--radius-md);

  cursor: pointer;
}

/* LE FOYER SE VOIT SUR LA LIGNE ENTIÈRE, et non sur la seule case : c'est la
   ligne qu'on parcourt au clavier, et un liseré de 16 px au milieu d'une bande
   de 300 px se cherche. */
.dash-rights__line:focus-within {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

.dash-rights__line:hover {
  background: rgba(255, 255, 255, 0.45);
}

/* La case garde sa taille de confort : 18 px est le minimum sous lequel elle
   devient difficile à viser, et « accent-color » lui donne la couleur du site
   sans qu'on ait à la redessiner — un contrôle natif reste un contrôle natif. */
.dash-rights__box {
  flex: none;
  width: 18px;
  height: 18px;
  margin-top: 2px;

  accent-color: var(--color-brand-amber-deep);
  cursor: pointer;
}

.dash-rights__words {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.dash-rights__name {
  font-family: var(--font-display);
  font-size: var(--font-size-base);
  color: var(--color-text);
}

.dash-rights__note {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.dash-rights__act {
  margin: var(--space-xs) 0 0;
}

