:root {
  /* Couleur d'IDENTITÉ (thème). Ces sept variables sont les seules que l'écran
     d'administration « Identité » peut redéfinir : elles portent l'identité de
     l'association qui déploie, pas une signification.
     Ne thématiser NI le bleu des liens (--bleu), NI le vert / rouge / orange
     ci-dessous, NI le violet des blocs « programme » du planning : ce sont des
     significations (dépôt, erreur, attention, catégorie d'animation), elles
     doivent rester identiques quelle que soit la couleur choisie. */
  --primaire: #2a2724;          /* anthracite chaud */
  --primaire-survol: #4b4640;   /* teinte et saturation conservées, L + 12 points */
  --primaire-clair: #af9e8d;    /* L 62 % — décoratif SEULEMENT : ~2,6:1 sur blanc */
  --primaire-fond: #f5f0eb;     /* L 94 % */
  --primaire-fond-leger: #faf7f5;/* L 97 % */
  --primaire-texte: #fff;       /* texte posé sur --primaire — ici 14,9:1 */
  /* --primaire employée COMME texte ou contour sur un fond clair (numéro du
     transfert, chiffres, puces, aide en ligne, focus). Calculée par
     app/services.py::couleur_lisible_sur_clair : la couleur elle-même si elle
     atteint 4,5:1 sur tous les fonds clairs du site, assombrie sinon. Jamais
     --primaire nue sur fond clair : un thème pâle y tombait à 1,2:1. */
  --primaire-lisible: #2a2724;

  --vert: #1f7a3d;
  --vert-clair: #e6f4ea;
  --rouge: #b3261e;
  --rouge-clair: #fce8e6;
  --orange: #8a5a00;
  --orange-clair: #fff4e0;
  /* Bleu des liens et du retour : 4,68:1 sur le bleu pâle de .resultat-info,
     4,82:1 sur le gris de la page. L'ancien #1a73e8 n'atteignait 4,5:1 que
     sur blanc pur (4,05:1 dans le pied de page, 3,93:1 sur #e8f0fe). */
  --bleu: #1967d2;
  --gris: #5f6368;
  /* Deux bordures : --bord sépare (cartes, lignes de tableau) et reste
     décoratif ; --bord-champ DÉLIMITE un élément qu'on doit trouver pour s'en
     servir (champ de saisie, bouton blanc sur carte blanche) et atteint donc
     les 3:1 d'un composant d'interface — 3,05:1 sur blanc. Foncer --bord
     partout aurait alourdi chaque carte sans rien rendre plus utilisable. */
  --bord: #dadce0;
  --bord-champ: #909498;
  --texte: #202124;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color: var(--texte);
  background: #f1f3f4;
  line-height: 1.5;
}

/* Regroupe le bandeau formation (optionnel) + le bandeau habituel : ensemble
   sticky en haut d'écran, pour que les deux restent visibles au défilement
   sans se chevaucher (au lieu de rendre chacun sticky séparément). */
.bandeau-groupe {
  position: sticky;
  top: 0;
  z-index: 100;            /* reste au-dessus du contenu lors du défilement */
}

.bandeau {
  background: var(--primaire);
  padding: 12px 16px;
}
.bandeau-titre {
  color: var(--primaire-texte);
  font-weight: 700;
  font-size: 1.1rem;
  text-decoration: none;
}

/* Menu bénévole (fragment partagé bandeau / dashboard admin) */
.menu-benevole { display: flex; flex-wrap: wrap; gap: 8px 16px; }
.menu-benevole a { color: var(--bleu); text-decoration: none; font-weight: 600; }
.menu-benevole a:hover { text-decoration: underline; }
/* Sur le bandeau coloré, les liens passent en --primaire-texte. */
.bandeau .menu-benevole { margin-top: 8px; }
.bandeau .menu-benevole a { color: var(--primaire-texte); opacity: 0.95; }

/* Menu du bandeau : replié par défaut (mobile-first — le menu à plat prenait
   jusqu'à 3 lignes au-dessus du contenu sur petit écran, ex. iPhone 13 mini).
   Repose sur <details>/<summary> natifs (aucun JS). DEUX rendus séparés du
   même contenu (base.html inclut le fragment de liens deux fois) plutôt
   qu'un unique <details> qu'on tenterait de "forcer ouvert" en CSS sur grand
   écran : cette dernière approche s'est révélée peu fiable (menu resté
   invisible sur ordinateur — certains moteurs de rendu appliquent un
   `content-visibility` interne aux <details> fermés que l'auteur ne peut pas
   surcharger simplement via `display`). Ici, bascule pure entre deux blocs
   distincts via `display:none/block` — comportement standard, sans piège. */
.menu-bandeau { border: none; }
.menu-bandeau > summary {
  cursor: pointer;
  color: var(--primaire-texte);
  font-weight: 700;
  margin-top: 8px;
  list-style: revert;
}
.menu-bandeau > summary::marker { color: var(--primaire-texte); }
.menu-bandeau-large { display: none; }
@media (min-width: 640px) {
  .menu-bandeau { display: none; }
  .menu-bandeau-large { display: block; }
}

.contenu {
  max-width: 540px;
  margin: 0 auto;
  padding: 16px;
}

/* Pages riches en tableau (grille du planning) : conteneur élargi sur grand
   écran pour éviter le défilement horizontal, tout en restant fluide sur mobile. */
.contenu-large { max-width: min(1180px, 96vw); }

.carte {
  background: #fff;
  border: 1px solid var(--bord);
  border-radius: 12px;
  padding: 20px;
  margin-bottom: 16px;
}

h1 { font-size: 1.5rem; margin: 0 0 12px; }

/* États */
.etat {
  display: inline-block;
  font-weight: 700;
  padding: 4px 12px;
  border-radius: 999px;
  margin: 0 0 8px;
}
.etat-dispo { background: var(--vert-clair); color: var(--vert); }
.etat-sorti { background: var(--rouge-clair); color: var(--rouge); }
.dispo-titre { color: var(--gris); margin-top: 0; }

/* Caractéristiques */
.caracteristiques {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 16px;
  margin: 16px 0;
}
.caracteristiques dt { color: var(--gris); }
.caracteristiques dd { margin: 0; font-weight: 600; }
.descriptif { color: #3c4043; }

/* Boutons d'action (grandes cibles tactiles) */
.bouton {
  display: block;
  width: 100%;
  border: none;
  border-radius: 12px;
  padding: 20px;
  margin: 12px 0;
  font-size: 1.3rem;
  font-weight: 700;
  cursor: pointer;
  color: #fff;
}
.bouton-sous {
  display: block;
  font-size: 0.85rem;
  font-weight: 400;
  opacity: 0.9;
  margin-top: 4px;
}
.bouton-principal { background: var(--vert); }
.bouton-secondaire { background: #fff; color: var(--gris); border: 2px solid var(--bord-champ); }
/* Bouton désactivé (générique, tout usage) : avant cette règle, chaque écran
   qui en avait besoin réinventait son propre gris en style inline
   (voir admin_fonctionnalites.html) faute de composant partagé. */
.bouton:disabled { opacity: .5; cursor: not-allowed; filter: none; }

/* --- Accessibilité & micro-interactions (tout le site) --- */

/* Lien d'évitement (E1, docs/audit-ux-2026-07-18.md) : premier élément du
   document, hors écran par défaut, ramené visible au focus clavier — motif
   standard, pour ne pas obliger à traverser le bandeau (menu + jusqu'à deux
   bandeaux formation/rangement) à chaque page. */
.saut-contenu {
  position: absolute;
  top: -40px;
  left: 8px;
  z-index: 1000;
  background: #fff;
  color: var(--texte);
  padding: 10px 16px;
  border-radius: 8px;
  border: 2px solid var(--primaire-lisible);
  text-decoration: none;
  font-weight: 600;
}
.saut-contenu:focus {
  top: 8px;
}

/* Focus clavier visible et homogène (sans gêner le clic souris). */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--primaire-lisible);
  outline-offset: 2px;
  border-radius: 6px;
}
/* Sur une surface colorée, le contour prend la couleur du TEXTE de cette
   surface : posé en --primaire-lisible sur le bandeau, il était de la couleur
   même du fond, donc invisible (ACC-01). --primaire-texte est garantie à
   4,5:1 au moins sur --primaire, quelle que soit la couleur réglée. Le
   bandeau du mode rangement porte, lui, du blanc sur son bleu fixe. */
.bandeau :focus-visible { outline-color: var(--primaire-texte); }
.rangement-bandeau-global :focus-visible { outline-color: currentColor; }
/* Champs de saisie : liseré coloré au focus (souris comme clavier).
   Comme les deux règles ci-dessus, ces marqueurs de focus prennent
   --primaire-lisible et non --primaire-clair : une teinte à 62 % de luminosité
   ne donne qu'environ 2,6:1 sur blanc, sous le minimum de 3:1 attendu d'un
   indicateur de focus. */
.champ input:focus,
.champ select:focus,
.champ textarea:focus { border-color: var(--primaire-lisible); }

/* Retour visuel à l'appui sur les boutons et puces. */
.bouton, .bouton-filtrer, .chip-filtre { transition: filter .12s ease, transform .06s ease, background .12s ease; }
.bouton:hover { filter: brightness(.96); }
/* Le bouton primaire s'éclaircit au survol au lieu de s'assombrir : sur une
   couleur d'identité sombre, brightness(.96) ne se voit pas. */
.bouton-filtrer:hover { background: var(--primaire-survol); }
.bouton:active, .bouton-filtrer:active, .chip-filtre:active { transform: translateY(1px); }

/* Ouverture animée des panneaux <details class="recherche"> (léger). */
@keyframes recherche-ouverture {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
.recherche[open] > *:not(summary),
.aide-inline[open] > *:not(summary) {
  animation: recherche-ouverture .18s ease-out;
}
.recherche > summary { transition: color .12s ease; }

/* Aide contextuelle repliée (S4, docs/idees-ux.md) : même langage visuel que
   .recherche (bordure, résumé cliquable, <details> natif, sans JS), teinte de
   fond différente pour ne jamais être confondue avec un panneau de filtre. Un
   <details class="aide-inline"><summary>❓ …</summary>…</details> par écran
   dense, 2-3 phrases + lien vers la page d'aide complète quand elle existe. */
.aide-inline {
  border: 1px solid var(--bord);
  border-radius: 8px;
  padding: 8px 12px;
  margin: 12px 0;
  background: var(--primaire-fond-leger);
}
.aide-inline > summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--primaire-lisible);
  transition: color .12s ease;
}
.aide-inline p:last-child { margin-bottom: 0; }

/* Aperçu, en admin, du bandeau d'annonce réellement affiché sur l'écran de
   salle (/live, point C) : mêmes couleurs que .bandeau-annonce dans
   live.html (ambre soutenu, texte clair, puce 📣) pour que l'admin voie
   fidèlement ce que projette la salle, plutôt qu'un style admin générique. */
.apercu-annonce-salle {
  display: flex;
  align-items: baseline;
  gap: 0.6em;
  background: #b45309;
  color: #fff7ed;
  border-radius: 8px;
  padding: 10px 14px;
  font-weight: 700;
  margin: 8px 0;
}
.apercu-annonce-salle .apercu-annonce-puce { font-size: 1.1em; }
/* Variante « alerte de tournoi » du même aperçu : le rouge de
   `--alerte-fond` dans live.html, pour qu'un coup d'oeil suffise à
   distinguer la consigne minutée de l'information du bureau. */
.apercu-annonce-salle.apercu-alerte-salle { background: #b91c1c; color: #fef2f2; }

/* Boutons de durée rapide sous le champ "annonce_duree" (point I). */
.duree-rapide { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
.duree-rapide .bouton-filtrer { padding: 6px 14px; font-size: 0.9rem; }
.apercu-annonce-salle .apercu-annonce-label {
  font-weight: 400;
  font-size: 0.75em;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  opacity: 0.85;
}

/* Respect des préférences système : on coupe tout mouvement. */
@media (prefers-reduced-motion: reduce) {
  .jeu, .bouton, .bouton-filtrer, .chip-filtre { transition: none; }
  .jeu:hover, .bouton:active, .bouton-filtrer:active, .chip-filtre:active { transform: none; }
  .recherche[open] > *:not(summary),
  .aide-inline[open] > *:not(summary) { animation: none; }
  .recherche > summary, .aide-inline > summary { transition: none; }
}

/* Page d'accueil */
.accueil { text-align: center; }
.accueil-dispo { font-size: 1.2rem; margin: 8px 0 20px; }
.accueil-dispo strong { font-size: 1.6rem; color: var(--vert); }
.accueil-dispo-total { color: var(--gris); font-size: 0.95rem; }
.accueil-outils { display: flex; flex-wrap: wrap; gap: 12px; }
.accueil-outils .bouton { flex: 1 1 200px; margin: 0; }

/* Résultat d'action */
.resultat {
  border-radius: 12px;
  padding: 20px;
  margin-bottom: 16px;
  text-align: center;
}
.resultat-ok { background: var(--vert-clair); border: 2px solid var(--vert); }
.resultat-info { background: #e8f0fe; border: 2px solid var(--bleu); }
.resultat-attention { background: var(--orange-clair); border: 2px solid var(--orange); color: var(--orange); }
.resultat-libelle { margin: 0; font-size: 1.1rem; color: var(--vert); }
.pochette-num {
  margin: 4px 0;
  font-size: 5rem;
  font-weight: 800;
  line-height: 1;
  color: var(--vert);
}
/* Retour d'un jeu : même gabarit que le prêt, numéro en BLEU pour distinguer
   d'un coup d'œil « je récupère » (retour) de « je dépose » (prêt, vert). */
.pochette-num--retour { color: var(--bleu); }
/* Transfert de pochette (docs/conception-transfert-pochette.md §8) : ni vert
   (glissez la PI) ni bleu (récupérez-la) — une troisième couleur pour dire
   NE TOUCHEZ PAS À LA POCHETTE. Réutilise la couleur d'IDENTITÉ du site
   (déjà .bouton-filtrer, theme-color), qui ne porte par ailleurs aucun sens
   de dépôt/retrait sur cet écran — voir docs/ui-composants.md §16.
   ⚠️ Depuis que cette couleur est réglable, c'est la seule signification
   portée par --primaire : une association qui choisirait un vert ou un bleu
   proches de ceux du prêt et du retour affaiblirait la distinction. */
.pochette-num--transfert { color: var(--primaire-lisible); }
.resultat-consigne { margin: 0; font-weight: 600; }

/* Code personnel (fiche D4, docs/audit-ux-2026-07-18.md) : code de
   désinscription tournoi, code de modification planning — même besoin
   (perdre le code = perdre la main sur son inscription/sa réponse), même
   classe. Remplace deux traitements sans rapport : côté tournoi, .pochette-num
   était DÉTOURNÉE (elle désigne officiellement le numéro de pochette depuis
   D3, docs/vocabulaire.md — un détournement trompeur pour qui modifierait un
   jour le style des numéros de pochette) ; côté planning, .pl-code (préfixe
   propre au module planning) faisait déjà l'essentiel du travail (chasse
   fixe : lève l'ambiguïté 0/O et 1/l, utile pour un code recopié à la main)
   mais était trop petite pour porter seule l'attention sur un écran de
   confirmation. Promue et agrandie plutôt que dupliquée. */
.code-personnel {
  font-family: ui-monospace, monospace;
  font-size: 2.4rem;
  font-weight: 800;
  letter-spacing: .08em;
  margin: 4px 0;
}

.lien { color: var(--bleu); }
.lien-fiche { margin: 16px 0 0; text-align: center; }

/* Catalogue */
.logo-catalogue { display: block; max-width: 180px; height: auto; margin: 0 auto 12px; }

/* Aperçu du logo sur l'écran d'administration « Identité » : ce qu'un
   visiteur voit aujourd'hui, à sa taille réelle d'affichage — un aperçu plus
   grand que le rendu final tromperait sur le résultat. Le damier discret
   derrière rend visible un fond transparent, qu'un aperçu sur fond blanc
   ferait passer pour du blanc plein. */
.logo-apercu {
  display: block;
  max-width: 180px;
  height: auto;
  margin: 8px 0 12px;
  padding: 8px;
  border: 1px solid var(--bord);
  border-radius: 6px;
  background-color: #fff;
  background-image:
    linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%),
    linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%);
  background-size: 16px 16px;
  background-position: 0 0, 8px 8px;
}

/* Catalogue — recherche / filtres */
.recherche {
  border: 1px solid var(--bord);
  border-radius: 8px;
  padding: 8px 12px;
  margin-bottom: 8px;
}
.recherche > summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--primaire-lisible);
}
.recherche-form {
  display: grid;
  gap: 12px;
  margin-top: 12px;
}
.champ { display: flex; flex-direction: column; gap: 4px; }
/* Réglage de couleur (/admin/identite) : le sélecteur natif et le code
   hexadécimal sur une même ligne — deux façons de saisir UNE valeur, pas deux
   réglages. Le champ texte prend la place restante : c'est lui qui fait foi. */
.champ-couleur { display: flex; align-items: stretch; gap: 8px; }
.champ-couleur input[type="color"] {
  flex: 0 0 auto;
  width: 52px;
  min-height: 44px;          /* même cible tactile que les autres champs */
  padding: 2px;
  border: 1px solid var(--bord-champ);
  border-radius: 8px;
  background: #fff;
  cursor: pointer;
}
.champ-couleur input[type="text"] { flex: 1 1 auto; font-family: monospace; }
/* Couleurs tirées du logo (/admin/identite) : une rangée de boutons qui
   reprennent chacun une couleur dans le champ ci-dessus. Le fond de l'aperçu
   n'est PAS une couleur en dur : il vient du logo déposé, posé par le gabarit.
   Le bouton choisi se distingue par un trait épais, pas par la seule couleur. */
.suggestions-couleur { margin-top: 6px; }
.suggestions-couleur-liste {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 6px 0 0;
  padding: 0;
  list-style: none;
}
.suggestion-couleur {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  min-height: 44px;
  padding: 6px 10px 6px 6px;
  border: 1px solid var(--bord-champ);
  border-radius: 8px;
  background: #fff;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.suggestion-couleur[aria-pressed="true"] {
  border: 3px solid var(--primaire-lisible);
  padding: 4px 8px 4px 4px;
}
.suggestion-couleur-apercu {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 32px;
  border-radius: 6px;
  font-weight: bold;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);
}
.suggestion-couleur small { flex-basis: 100%; color: var(--gris); }
.champ label { color: var(--gris); font-size: 0.9rem; }
.champ input, .champ select {
  padding: 10px;
  border: 1px solid var(--bord-champ);
  border-radius: 8px;
  font-size: 1rem;
  background: #fff;
}
.recherche-actions { display: flex; align-items: center; gap: 16px; }
.bouton-filtrer {
  background: var(--primaire);
  color: var(--primaire-texte);
  border: none;
  border-radius: 12px;
  padding: 10px 20px;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
}
/* M7 (docs/idees-ux.md) : bouton flottant qui ramène au panneau de recherche
   du catalogue (600 titres, un seul long défilement) -- pur CSS (position
   fixed + ancre #haut), aucun JS, aucune pagination. Réutilise l'habillage
   de .bouton-filtrer (couleur, transitions déjà mutualisées plus bas). */
.bouton-haut {
  position: fixed;
  bottom: 16px;
  right: 16px;
  z-index: 20;
  display: inline-block;
  text-decoration: none;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .3);
}

.catalogue-compte { color: var(--gris); margin: 12px 0 0; }
.derniers-achats { margin: 8px 0 0; padding-left: 20px; }
.derniers-achats li { margin: 4px 0; display: flex; justify-content: space-between; gap: 12px; }
.achat-date { color: var(--gris); font-size: 0.85rem; white-space: nowrap; }

.catalogue-liste { list-style: none; margin: 0; padding: 0; }
.jeu {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: #fff;
  border: 1px solid var(--bord);
  border-radius: 10px;
  padding: 12px 16px;
  margin-bottom: 8px;
}
.jeu-lien { text-decoration: none; color: var(--texte); flex: 1; }
.jeu-nom { display: block; font-weight: 600; }
.jeu-categorie { display: block; font-size: 0.85rem; color: var(--gris); }
.badge {
  flex-shrink: 0;
  font-size: 0.8rem;
  font-weight: 700;
  padding: 4px 10px;
  border-radius: 999px;
  white-space: nowrap;
}
.badge-dispo { background: var(--vert-clair); color: var(--vert); }
.badge-sorti { background: var(--rouge-clair); color: var(--rouge); }
/* Réutilisées pour l'état des bases en supervision (tableau admin) : une
   pastille compacte se lit mieux dans une cellule qu'une bannière .resultat
   pleine largeur (padding 20px, prévue pour les écrans de prêt/retour). */
.badge-ok { background: var(--vert-clair); color: var(--vert); }
.badge-attention { background: var(--orange-clair); color: var(--orange); }

/* Survol des cartes de jeu (léger relief) */
.jeu {
  transition: box-shadow .15s ease, transform .15s ease, border-color .15s ease;
}
.jeu:hover {
  box-shadow: 0 3px 12px rgba(0, 0, 0, .12);
  border-color: var(--primaire-clair);
  transform: translateY(-1px);
}

/* Puces de filtres actifs (chacune retire son filtre au clic) */
.filtres-actifs { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 12px 0 0; }
.filtres-actifs .fa-label { color: var(--gris); font-size: .9rem; }
.chip-filtre {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--primaire-fond); color: var(--primaire-lisible);
  border-radius: 999px; padding: 4px 12px;
  font-size: .85rem; font-weight: 600; text-decoration: none;
}
/* Survol : assombrissement relatif plutôt qu'une teinte figée, pour suivre
   --primaire-fond quelle que soit la couleur réglée (transition mutualisée
   plus haut avec les boutons). */
.chip-filtre:hover { filter: brightness(.95); }
.chip-filtre .croix { font-weight: 700; opacity: .7; }

/* Statistiques */
.stats-chiffres { display: flex; flex-wrap: wrap; gap: 16px; }
.chiffre { flex: 1; min-width: 120px; text-align: center; background: var(--primaire-fond-leger); border-radius: 10px; padding: 14px; }
.chiffre-val { display: block; font-size: 1.8rem; font-weight: 800; color: var(--primaire-lisible); }
.chiffre-lib { color: var(--gris); font-size: 0.85rem; }
.stats-bascule { color: var(--gris); }
.palmares { margin: 8px 0 20px; padding-left: 24px; }
.palmares li { margin: 4px 0; }
.palmares-nom { font-weight: 600; }
.palmares-val { color: var(--gris); }
.palmares-val small { color: #6b7075; }
.histo { list-style: none; margin: 0; padding: 0; }
.histo-ligne { display: flex; align-items: center; gap: 8px; margin: 3px 0; }
.histo-label { flex-shrink: 0; width: 84px; font-size: 0.85rem; color: var(--gris); }
.histo-barre { height: 16px; background: var(--primaire-clair); border-radius: 4px; min-width: 2px; }
.histo-val { font-size: 0.85rem; font-weight: 600; }
.stats-note { color: #6b7075; font-size: 0.8rem; }
/* Rappel du nom de l'événement sous un titre de page (accueil, programme,
   tournois). C'est un RAPPEL, pas le sujet de la page : il ne concurrence
   jamais le <h1> qui le précède. Plus lisible que .stats-note, qui est réservée
   aux notes explicatives de bas de champ. Voir docs/ui-composants.md §15. */
.rappel-evenement {
  color: var(--gris);
  font-size: 0.95rem;
  font-weight: 600;
  margin: -4px 0 16px;
}
/* Orientation qui REMPLACE le bouton « S'inscrire » quand le bureau a réservé
   les inscriptions aux bénévoles (page publique d'un tournoi). Ni une note de
   bas de champ (.stats-note, trop discrète : elle prend la place d'un appel à
   l'action), ni un badge d'état (.etat, prévu pour un mot, pas une phrase),
   d'où cette règle plutôt qu'un détournement de l'une des deux. */
.inscription-comptoir {
  color: var(--gris);
  font-weight: 600;
  margin: 16px 0;
}
.stats-export { font-weight: 600; }
/* Groupe de boutons radio : un <fieldset class="champ champ-groupe"> se
   présente comme n'importe quel .champ (le navigateur ajoute sinon une
   bordure et des marges qui le distinguent du reste du formulaire), et sa
   <legend> reprend l'apparence d'un libellé de champ. */
.champ-groupe { border: 0; padding: 0; margin: 0; min-width: 0; }
.champ-groupe legend { padding: 0; color: var(--gris); font-size: 0.9rem; }

.case { display: flex; align-items: center; gap: 8px; font-weight: 500; }
.case input { width: auto; }
/* Tableau de données dense (lecture) : .detail (stats/tournois) et
   .admin-table (admin) sont le même composant, apparu à deux moments du
   projet sous deux noms (voir docs/ui-composants.md §9). Règles fusionnées :
   .detail hérite au passage du correctif anti-débordement mobile
   (vertical-align/word-break) qui n'existait jusqu'ici que pour .admin-table
   (retour terrain iPhone 13 mini). */
.detail, .admin-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
.detail th, .detail td,
.admin-table th, .admin-table td {
  text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--bord);
  vertical-align: top; word-break: break-word;
}
.detail th, .admin-table th { color: var(--gris); }

/* Classe d'accessibilité : contenu réservé aux lecteurs d'écran (libellé d'un
   bouton radio sans texte visible, libellé de cellule en mode cartes…).
   ⚠️ Elle était employée par admin_fonctionnalites.html SANS jamais avoir été
   définie ici : les quatre libellés d'états s'affichaient donc en toutes
   lettres à côté de chaque bouton radio. Écart corrigé au lot agora-5, au
   moment d'en ajouter un second usage. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Variante OPT-IN du tableau de données : sous 640 px, chaque ligne devient
   une carte empilée (docs/ui-composants.md §9).
   POURQUOI UNE VARIANTE, et pas une retouche de .admin-table : neuf gabarits
   l'utilisent, dont huit écrans de bureau qui n'ont pas ce besoin. Seul le
   carnet de maintenance est posé au comptoir, sur un téléphone.
   POURQUOI DES CARTES, et pas un défilement horizontal : le geste « faire
   défiler pour atteindre le bouton » est mauvais sur un écran d'action
   répétée. Précédent suivi : .planning-grille, plus haut dans ce fichier.
   ⚠️ NE PAS retirer `word-break: break-word` des règles partagées ci-dessus
   pour régler la césure du bouton : il a été ajouté exprès en correctif
   anti-débordement (retour terrain iPhone 13 mini). Ce qu'on traite ici,
   c'est la mise en page — une cellule pleine largeur n'a plus rien à couper. */
.cartes-libelle { display: none; }

@media (max-width: 640px) {
  /* `display: block` sur les éléments de tableau efface la sémantique de
     tableau pour les lecteurs d'écran : les en-têtes de colonnes ne sont plus
     annoncés. D'où `.cartes-libelle`, un vrai libellé DANS le document (et
     non un `content:` de CSS, que l'on ne peut ni sélectionner ni garantir
     lu) devant chaque valeur. */
  .admin-table--cartes,
  .admin-table--cartes tbody,
  .admin-table--cartes tr,
  .admin-table--cartes td { display: block; width: auto; }
  .admin-table--cartes thead { display: none; }
  .admin-table--cartes tr {
    border: 1px solid var(--bord);
    border-radius: 12px;
    padding: 12px 14px;
    margin-bottom: 12px;
  }
  .admin-table--cartes td {
    border-bottom: 0;
    padding: 2px 0;
    font-size: 0.95rem;
  }
  .admin-table--cartes .cartes-libelle {
    display: inline;
    color: var(--gris);
    font-size: 0.85rem;
  }
  .admin-table--cartes .cartes-libelle::after { content: " : "; }
  /* Le nom du jeu porte la carte : c'est par lui qu'on la reconnaît. */
  .admin-table--cartes .cartes-titre {
    font-weight: 700;
    font-size: 1.05rem;
    padding-bottom: 4px;
  }
  /* Le bouton d'action prend toute la largeur, en bas de la carte, à portée
     de pouce — c'est le défaut que ce lot corrige. */
  .admin-table--cartes .cartes-action { padding-top: 10px; }
  .admin-table--cartes .cartes-action .rangement-form-inline { display: block; margin: 0; }
  .admin-table--cartes .cartes-action .bouton-filtrer { display: block; width: 100%; }
}

.admin-menu { list-style: none; margin: 0; padding: 0; }
.admin-menu li { margin: 10px 0; font-size: 1.1rem; }
.admin-menu li a { display: flex; align-items: center; }

/* Icône des liens du menu "Gérer" : agrandie pour rester repérable au premier
   coup d'œil même quand le libellé texte est raccourci (voir .admin-menu li a
   title="..." pour le détail complet, affiché au survol sur bureau). */
.admin-icone { font-size: 1.25em; margin-right: 8px; line-height: 1; }

/* Rangement (admin, /admin/rangement) : plusieurs petits formulaires par
   ligne de tableau (renommer / monter / descendre / archiver / supprimer).
   Un <form>/<button> est en bloc par défaut -> les rend inline pour qu'ils
   se posent côte à côte dans une cellule au lieu de s'empiler. */
.rangement-form-inline { display: inline-flex; align-items: center; gap: 6px; margin: 2px 6px 2px 0; }
.rangement-form-inline input[type="text"] {
  padding: 4px 8px; border: 1px solid var(--bord-champ); border-radius: 6px;
  font-size: 0.85rem; width: 140px;
}
.rangement-ordre, .rangement-actions { display: flex; flex-wrap: wrap; gap: 4px; }

/* Mode rangement au scanner (bandeau d'état persistant, /scanner) : même
   teinte bleue que .resultat-info / .pochette-num--retour (identité visuelle
   "rangement" cohérente, y compris avec le futur bloc "où ranger" au retour).
   Plus compact que .resultat (pas son padding 20px) : pensé pour rester
   affiché en permanence au-dessus de la caméra, pas pour un message ponctuel. */
.rangement-bandeau {
  background: #e8f0fe; border: 2px solid var(--bleu); color: var(--bleu);
  border-radius: 10px; padding: 10px 14px; margin-bottom: 12px;
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px;
  font-weight: 600;
}
.rangement-bandeau form, .rangement-bandeau details { display: inline; margin: 0; }
.rangement-bandeau summary { cursor: pointer; text-decoration: underline; }

/* Bloc "🗄️ Où ranger le jeu" au retour (pret.html, résultats rendu/
   rendu_tournoi) : même esprit que .pochette-num (libellé + valeur en gros),
   mais dimensionné pour un texte parfois long (nom d'étagère, description
   libre) plutôt qu'un numéro à 1-3 chiffres — 5rem déborderait/serait
   illisible. Même teinte bleue que .resultat-info / le bandeau du mode
   rangement au scanner (identité "rangement" cohérente sur tout le site). */
.rangement-valeur {
  margin: 4px 0; font-size: 1.8rem; font-weight: 800; line-height: 1.25;
  color: var(--bleu);
}

/* Édition à l'unité du rangement sur la fiche admin (admin_fiche.html, §4.c) :
   les deux formulaires (événement / local) empilés sous chaque étiquette. */
.rangement-edition { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.rangement-edition label { font-size: 0.85rem; color: var(--gris); }
.rangement-edition select {
  padding: 4px 8px; border: 1px solid var(--bord-champ); border-radius: 6px; font-size: 0.85rem;
}

/* Sous-groupes du menu "Gérer" (Jeux & étiquettes / Données & accès / Événement /
   Configuration). Le titre de groupe est masqué par défaut (mobile = référence
   inchangée : les items s'enchaînent comme une seule liste, .admin-menu n'ayant
   pas de marge de ul propre) et n'apparaît qu'à partir du breakpoint bureau,
   où les groupes passent en grille 2 colonnes (voir media query) — la marge
   verticale entre groupes est donc gérée par la bordure de la 2e rangée, pas
   par la marge du titre (mise à 0 pour éviter tout cumul). */
.admin-groupe-titre {
  display: none;
  margin: 0 0 4px;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--gris);
}

/* Tableau de bord admin : une seule colonne (comportement de référence, cartes
   empilées via leur marge habituelle .carte) sous le breakpoint bureau ; deux
   colonnes (menu + supervision en direct) au-delà — voir la media query. */
.admin-dashboard-col-supervision { display: none; }

@media (min-width: 900px) {
  .admin-dashboard-grille {
    display: grid;
    grid-template-columns: 1.3fr 1fr;
    align-items: start;
    gap: 16px;
  }
  .admin-dashboard-col-supervision { display: block; }

  /* Sur le tableau de bord, la supervision est déjà visible dans la colonne de
     droite : le lien vers la page dédiée dans le menu "Gérer" devient redondant. */
  .admin-menu-lien-supervision { display: none; }

  /* Cartes du tableau de bord un peu plus compactes qu'ailleurs (padding et
     espacement resserrés) pour limiter la hauteur totale de la page. Scopé à
     .admin-dashboard-grille pour ne pas toucher .carte sur les autres écrans
     larges (stats, planning, tournois...). */
  .admin-dashboard-grille .carte { padding: 16px 20px; margin-bottom: 12px; }
  .admin-dashboard-grille h1 { font-size: 1.3rem; margin: 0 0 8px; }
  .admin-dashboard-grille h2 { font-size: 1.1rem; margin: 0 0 6px; }
  /* Sous-titres de la colonne supervision (Bases de données, Espace disque...) :
     même resserrage. Scopé à la colonne supervision (pas .admin-dashboard-grille
     h3) pour ne jamais entrer en conflit de spécificité avec .admin-groupe-titre. */
  .admin-dashboard-col-supervision h3 { font-size: 0.95rem; margin: 12px 0 4px; }
  .admin-dashboard-col-supervision p { margin: 4px 0; }

  /* Sous-groupes du menu "Gérer" sur 2 colonnes (au lieu d'empiler 4 groupes) :
     divise la hauteur du menu par ~2. La 2e rangée (3e/4e groupe) reçoit une
     bordure haute pour marquer la séparation entre rangées. */
  .admin-groupes { display: grid; grid-template-columns: 1fr 1fr; column-gap: 28px; }
  .admin-groupe-titre { display: block; }
  .admin-groupe:nth-of-type(n+3) { border-top: 1px solid var(--bord); padding-top: 8px; margin-top: 6px; }

  .admin-menu li { margin: 4px 0; font-size: 1rem; }
  .admin-menu li a { padding: 5px 8px; margin: 0 -8px; border-radius: 8px; }
  .admin-menu li a:hover { background: var(--vert-clair); text-decoration: none; }
  .admin-icone { font-size: 1.4em; }
}

/* Écrans d'administration denses : deux colonnes sur grand écran (le conteneur
   passe en .contenu-large via conteneur_extra). Sous 900px : rien ne change,
   les cartes s'empilent comme avant (mobile-first préservé). Même point de
   rupture que .admin-dashboard-grille pour la cohérence. */
/* 3a. Répartition « maçonnerie » de cartes indépendantes en 2 colonnes.
   CSS multi-colonnes : aucune restructuration HTML lourde, l'ordre source est
   conservé (colonne 1 remplie, puis colonne 2). break-inside évite qu'une
   carte soit coupée en deux entre les colonnes. */
@media (min-width: 900px) {
  .admin-cols { column-count: 2; column-gap: 20px; }
  .admin-cols > .carte { break-inside: avoid; margin-top: 0; }
}
/* 3b. Rangée de deux cartes côte à côte (grille explicite, pour des cartes
   qu'on veut réellement alignées sur une même ligne). */
@media (min-width: 900px) {
  .admin-duo { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
  .admin-duo > .carte { margin-bottom: 0; }
}
/* 3c. Formulaire de saisie en 2 colonnes de champs (pour les formulaires longs).
   Le champ « pleine largeur » (textarea, bouton) reçoit .champ-large. */
@media (min-width: 900px) {
  .form-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 20px; align-items: start; }
  .form-2col .champ-large { grid-column: 1 / -1; }
}
/* 3d. Liste de jeux (/admin/jeux) en grille 2 colonnes. Classe additionnelle
   posée à côté de .catalogue-liste (partagée avec le catalogue public) pour
   isoler ce changement à cet écran admin — .catalogue-liste/.jeu ne sont pas
   modifiées directement. */
@media (min-width: 900px) {
  .catalogue-grille { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px 16px; }
  .catalogue-grille .jeu { margin-bottom: 0; }
}

/* Légende des états de fonctionnalités */
.fonct-legende { display: grid; grid-template-columns: auto 1fr; gap: 4px 16px; margin: 0 0 20px; }
.fonct-legende dt { font-weight: 700; white-space: nowrap; }
.fonct-legende dd { margin: 0; color: var(--gris); font-size: 0.92rem; }
.etiquette-bloc { padding: 12px 16px; }
.etiquette-entete { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 8px; }
.etiquette-apercu { display: block; width: 100%; max-width: 360px; height: auto; border: 1px solid var(--bord); border-radius: 6px; }
.champ textarea { padding: 10px; border: 1px solid var(--bord-champ); border-radius: 8px; font-size: 1rem; font-family: inherit; }
.copie-ok { color: var(--vert); font-weight: 600; margin-left: 8px; }

/* Partage du lien d'activation : pastilles colorées par canal */
.partage-titre { font-weight: 600; margin-bottom: 6px; }
.partage { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  border: none; border-radius: 999px;
  padding: 8px 14px; font-size: 0.95rem; font-weight: 600;
  color: #fff; text-decoration: none; cursor: pointer;
}
.chip-wa { background: #25d366; }       /* WhatsApp */
.chip-mail { background: #5f6368; }     /* E-mail */
.chip-sms { background: var(--bleu); }      /* SMS */
.chip-discord { background: #5865f2; }  /* Discord (couleur Blurple) */

/* Impression d'étiquettes en lot */
.grille-params { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px 16px; }
.grille-params label { display: flex; flex-direction: column; gap: 2px; font-size: 0.9rem; color: var(--gris); }
.grille-params input { padding: 6px 8px; border: 1px solid var(--bord-champ); border-radius: 6px; }
.compteur { font-weight: 700; color: var(--primaire-lisible); margin: 10px 0; }
.filtre-cat { margin-bottom: 12px; }
/* Réglage STOCKÉ « code de la boîte sur l'étiquette » : encadré à part, entre
   les avertissements et le formulaire de génération. Il ne décrit pas la
   planche en cours (il vaut aussi pour les réimpressions individuelles), d'où
   un bloc distinct plutôt qu'un champ de plus dans .grille-params. */
.reglage-etiquette {
  border: 1px solid var(--bord);
  border-radius: 8px;
  padding: 12px;
  margin-bottom: 16px;
}
.reglage-etiquette .stats-note { margin: 6px 0 10px; }
.select-actions { display: flex; gap: 12px; margin-bottom: 8px; }
.lien-bouton { background: none; border: none; color: var(--bleu); font-weight: 600; cursor: pointer; padding: 0; }
.liste-jeux { list-style: none; margin: 0 0 16px; padding: 0; max-height: 360px; overflow-y: auto; border: 1px solid var(--bord); border-radius: 8px; }
.liste-jeux li { padding: 6px 12px; border-bottom: 1px solid #eee; }
.liste-jeux .case { display: flex; align-items: center; gap: 8px; font-weight: 400; }
.jeu-nb { margin-left: auto; color: var(--gris); font-size: 0.85rem; white-space: nowrap; }

/* Scanner */
.scanner-cadre { background: #000; border-radius: 12px; overflow: hidden; }
.scanner-video { display: block; width: 100%; height: auto; }
.scanner-statut { font-weight: 600; }
.scanner-aide { color: var(--gris); font-size: 0.9rem; }
/* Ligne de mesure du mode diagnostic (/scanner?debug=1), créée par
   scanner.js. Chiffres alignés en chasse fixe, plus petits que le statut :
   c'est un outil de mise au point, il ne doit pas concurrencer « Visez un QR
   code… » du regard. */
.scanner-diagnostic {
  color: var(--gris);
  font-size: 0.8rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  margin: 0.2rem 0 0;
}
.saisie-manuelle { display: grid; gap: 12px; margin-top: 8px; }
.saisie-manuelle .bouton-filtrer { width: 100%; }
/* Ligne du clavier, entre le champ et le bouton : porte du lien de bascule
   vers le clavier complet, ou le rappel qu'on y est déjà. Marges annulées —
   l'écart vient du `gap` de la grille, sinon la ligne se décolle deux fois. */
.saisie-clavier { margin: 0; }

.pied {
  max-width: 540px;
  margin: 8px auto 24px;
  padding: 0 16px;
  text-align: center;
  color: var(--gris);
  font-size: 0.85rem;
}

/* Numéro de version rappelé à côté de la licence : utile pour un dépannage
   (« quelle version tourne ? ») sans jamais attirer l'oeil du visiteur. */
.pied-version {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* --- Module tournois --- */
a.bouton { text-align: center; text-decoration: none; box-sizing: border-box; }
/* Bouton d'action discret rendu comme un lien (ex. « Retirer » un participant). */
button.lien {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  cursor: pointer;
  text-decoration: underline;
}

/* --- Planning des tournois (page d'accueil, façon agenda) --- */
:root { --slot-h: 1.8rem; --gutter-w: 3rem; }   /* hauteur d'un créneau 30 min ; largeur gouttière heures */
.planning-jour-titre { margin: 20px 0 8px; font-size: 1.05rem; }

/* Grand écran : frise calendrier (gouttière d'heures + couloirs en colonnes). */
.planning-grille {
  display: grid;
  position: relative;
  isolation: isolate;      /* confine le z-index interne des blocs (pas de débordement sur le bandeau) */
  column-gap: 6px;
  row-gap: 0;
  margin-bottom: 8px;
}
/* Filets horizontaux à chaque heure (fond), sur toute la largeur. */
.planning-ligne {
  grid-column: 1 / -1;
  border-top: 1px solid var(--bord);
  z-index: 0;
}
/* Étiquette d'heure, alignée sur le filet. */
.planning-heure {
  grid-column: 1;
  font-size: 0.72rem;
  color: var(--gris);
  white-space: nowrap;
  transform: translateY(-0.55rem);
  z-index: 1;
}
/* Carte d'un tournoi. */
.planning-bloc {
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 0;
  overflow: hidden;
  text-decoration: none;
  color: var(--texte);
  background: #eef3fe;
  border-left: 4px solid var(--bleu);
  border-radius: 8px;
  box-shadow: 0 1px 2px rgba(0,0,0,.08);
  padding: 3px 8px;
  margin: 1px 0;
  font-size: 0.78rem;
  line-height: 1.15;
  /* Hauteur mini = ~2 lignes (heure + titre) pour les tournois courts (≤ 30 min) ;
     la hauteur reste proportionnelle pour les tournois plus longs. */
  min-height: 2.2rem;
}
.planning-bloc:hover { box-shadow: 0 2px 6px rgba(0,0,0,.16); }
.planning-bloc--lance   { background: var(--orange-clair); border-left-color: var(--orange); }
.planning-bloc--termine { background: #f1f3f4; border-left-color: #6b7075; color: var(--gris); }
/* Élément de PROGRAMME (animation, atelier…) : teinte distincte du bleu des
   tournois, dans la même famille visuelle. Ce bloc n'est pas cliquable (pas
   de page de détail) — d'où l'absence de curseur main et de relief au survol. */
.planning-bloc--programme { background: #f3edfb; border-left-color: #7b1fa2; }
.planning-bloc--programme:hover { box-shadow: 0 1px 2px rgba(0,0,0,.08); }
.planning-bloc-heure { font-weight: 700; font-size: 0.72rem; color: var(--gris); }
.planning-bloc-nom { font-weight: 700; }
.planning-bloc-meta { color: var(--gris); font-size: 0.72rem; }

/* Mobile : agenda empilé (cartes chronologiques pleine largeur). */
@media (max-width: 640px) {
  .planning-grille { display: flex; flex-direction: column; gap: 8px; }
  .planning-ligne, .planning-heure { display: none; }
  .planning-bloc {
    grid-column: auto !important;
    grid-row: auto !important;
    font-size: 0.92rem;
    padding: 8px 12px;
  }
  .planning-bloc-heure, .planning-bloc-meta { font-size: 0.82rem; }
}

/* ===================================================================
   Module PLANNING BÉNÉVOLE (classes préfixées pl-* pour éviter toute
   collision avec la frise « planning des tournois » de l'accueil).
   =================================================================== */
.pl-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 8px 0; }
.pl-grille { border-collapse: collapse; width: 100%; font-size: 0.85rem; }
.pl-grille th, .pl-grille td {
  border: 1px solid var(--bord); padding: 5px 7px; vertical-align: top; text-align: left;
}
.pl-grille thead th { background: var(--vert-clair); color: var(--vert); white-space: nowrap; }
.pl-horaire { white-space: nowrap; background: #fafafa; color: var(--gris); font-weight: 700; }
.pl-grise { background: repeating-linear-gradient(45deg,#eee,#eee 6px,#e3e3e3 6px,#e3e3e3 12px); }
.pl-nom {
  display: inline-flex; align-items: center; gap: 3px;
  background: var(--vert-clair); color: var(--vert);
  border-radius: 6px; padding: 1px 6px; margin: 1px; font-size: 0.8rem; white-space: nowrap;
}
.pl-verrou { background: var(--orange-clair); color: var(--orange); }
.pl-compte { display: inline-block; color: var(--gris); font-size: 0.72rem; margin-left: 2px; }
.pl-add { display: inline-flex; gap: 2px; margin-top: 3px; }
.pl-add select { font-size: 0.75rem; max-width: 110px; }

/* Petits boutons inline (ajouter, retirer, verrou). */
.pl-inline-form { display: inline; margin: 0; }
.pl-mini, .pl-x {
  border: none; background: transparent; cursor: pointer; font-size: 0.8rem;
  padding: 0 2px; line-height: 1;
}
.pl-x { color: var(--rouge); }

/* Listes de trame (postes / créneaux) et formulaires d'ajout. */
.pl-inline-liste { list-style: none; padding: 0; margin: 6px 0; }
.pl-inline-liste li {
  display: flex; align-items: center; gap: 6px; padding: 3px 0; border-bottom: 1px solid var(--bord);
}
.pl-recherche { display: flex; flex-wrap: wrap; gap: 8px; align-items: end; margin: 8px 0; }
.pl-recherche input[type="text"], .pl-recherche input[type="number"] {
  padding: 8px; border: 1px solid var(--bord-champ); border-radius: 8px; font-size: 0.95rem;
}
.pl-check { display: inline-flex; align-items: center; gap: 4px; color: var(--gris); font-size: 0.9rem; }
.pl-besoin { width: 3rem; text-align: center; padding: 4px; border: 1px solid var(--bord-champ); border-radius: 6px; }
.pl-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 10px; }
.pl-actions form { margin: 0; }

/* Tag d'état + code de modification + cases de disponibilité. */
.pl-tag {
  display: inline-block; background: #eef; color: #334; border-radius: 10px;
  padding: 1px 8px; font-size: 0.75rem; text-transform: uppercase; letter-spacing: .03em;
}
.pl-cases { display: flex; flex-wrap: wrap; gap: 8px; margin: 6px 0 14px; }
.pl-case-dispo {
  display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--bord);
  border-radius: 8px; padding: 6px 10px; font-size: 0.9rem; cursor: pointer;
}
.pl-prefs { border-collapse: collapse; margin: 6px 0 14px; }
.pl-prefs th, .pl-prefs td { border: 1px solid var(--bord); padding: 5px 9px; text-align: center; }
.pl-prefs tbody th { text-align: left; }
.pl-liste-ev, .pl-mon-liste { list-style: none; padding: 0; }
.pl-liste-ev li { display: flex; gap: 8px; align-items: center; padding: 6px 0; border-bottom: 1px solid var(--bord); }
.pl-mon-liste li { padding: 6px 0; border-bottom: 1px solid var(--bord); }

/* Planning — couleurs par ÉTAT de case (grille de gestion) + cases cliquables. */
.pl-etat-grise     { background: repeating-linear-gradient(45deg,#eee,#eee 6px,#e3e3e3 6px,#e3e3e3 12px); }
.pl-etat-trou      { background: var(--rouge-clair); }
.pl-etat-partiel   { background: var(--orange-clair); }
.pl-etat-complet   { background: var(--vert-clair); }
.pl-etat-surcharge { background: #e8eefc; }            /* trop de monde : bleu doux */

.pl-case-lien {
  display: block; text-decoration: none; color: inherit; min-height: 1.6rem;
  padding: 2px; border-radius: 6px;
}
.pl-case-lien:hover { outline: 2px solid var(--vert); outline-offset: -2px; }
.pl-horaire-lien { text-decoration: none; color: var(--gris); white-space: nowrap; }
.pl-horaire-lien:hover { color: var(--vert); }

/* --- Round robin : tableau des confrontations --- */
.rr-scroll { overflow-x: auto; }                 /* défilement horizontal si beaucoup de joueurs */
.rr-table { min-width: max-content; }
.rr-table th, .rr-table td { text-align: center; white-space: nowrap; }
.rr-table .rr-nom { text-align: left; font-weight: 600; }
.rr-table td { font-weight: 700; }
.rr-v { background: var(--vert-clair); color: var(--vert); }
.rr-d { background: var(--rouge-clair); color: var(--rouge); }
.rr-n { background: #e8f0fe; color: var(--bleu); }
.rr-vide { color: #6b7075; }
.rr-self { background: #f1f3f4; }

/* ---------------------------------------------------------------------
   MODE FORMATION (voir app/config.py + docs/mode-formation.md)
   Bandeau fixe très visible + filigrane diagonal en fond, uniquement quand
   MODE_FORMATION=1. Couleur volontairement différente du bandeau
   habituel (--primaire) pour ne jamais confondre les deux instances au premier
   coup d'œil.
   ------------------------------------------------------------------- */
.formation-bandeau {
  background: #e65100;
  color: #fff;
  font-weight: 700;
  text-align: center;
  padding: 8px 12px;
  letter-spacing: 0.02em;
}

/* Bandeau GLOBAL du mode rangement (fiche B1) — même traitement que le
   bandeau de formation ci-dessus (bande pleine largeur dans .bandeau-groupe,
   donc sticky avec lui). Reprend le BLEU de l'identité « rangement » du site
   (cf. .rangement-valeur / .rangement-bandeau), distinct de la couleur du
   bandeau habituel et de l'orange de formation : les trois coexistent sans se
   confondre. Contrairement au bandeau de formation, celui-ci porte une
   action (quitter), d'où la mise en ligne flex.
   ⚠️ Nom volontairement distinct de `.rangement-bandeau` (ligne ~415), qui
   est le PANNEAU détaillé de /scanner — deux composants différents. */
.rangement-bandeau-global {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
  background: var(--bleu);      /* bleu = identité "rangement" du site */
  color: #fff;
  font-weight: 700;
  text-align: center;
  padding: 8px 12px;
}
.rangement-bandeau-global form { margin: 0; }
.rangement-quitter {
  background: transparent;
  color: #fff;
  border: 2px solid rgba(255, 255, 255, 0.7);
  border-radius: 8px;
  padding: 2px 10px;
  font-size: 0.9rem;
  font-weight: 700;
  cursor: pointer;
}
.rangement-quitter:hover { background: rgba(255, 255, 255, 0.15); }

/* Filigrane : texte « FORMATION » répété en diagonale, en surimpression très
   légère sur tout le contenu (pointer-events: none -> n'intercepte aucun clic).
   Pur CSS (image de fond SVG encodée en donnée), aucun JavaScript. */
body.mode-formation::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='280' height='140'%3E%3Ctext x='140' y='80' font-size='24' font-family='sans-serif' font-weight='bold' fill='%23e65100' fill-opacity='0.12' text-anchor='middle' transform='rotate(-30 140 80)'%3EFORMATION%3C/text%3E%3C/svg%3E");
  background-repeat: repeat;
}

/* Ne jamais imprimer le bandeau ni le filigrane (gaspillage d'encre, gêne la
   lecture d'une page imprimée depuis une instance de formation). */
@media print {
  .formation-bandeau { display: none; }
  .rangement-bandeau-global { display: none; }
  body.mode-formation::after { display: none; }
  .bouton-haut { display: none; }
  .saut-contenu { display: none; }
}
