/* =========================================================================
   Le Lieu — feuille de style principale
   Palette : sauge très clair en fond, vert profond en primaire, doré en
   accent — clin d'œil discret à un lieu de musique et d'arts vivants.
   ========================================================================= */

:root {
  --couleur-fond: #F4F4F4;
  --couleur-surface: #FFFFFF;
  --couleur-primaire: #333333;
  --couleur-primaire-clair: #4D4D4D;
  --couleur-accent: #8A8A8A;
  --couleur-accent-clair: #B0B0B0;
  --couleur-texte: #1A1A1A;
  --couleur-texte-att: #666666;
  --couleur-bordure: #E0E0E0;
  --couleur-erreur: #B3261E;
  --couleur-erreur-fond: #FBEAEA;
  /* Bandeau du site (07/09/2026) : noir, distinct du gris plus clair des
     bandeaux de titre de page (--couleur-primaire) — hiérarchie visuelle
     voulue par Bruno ("noir le fond du bandeau du site... gris assez
     foncés pour les fonds de bandeau titre des pages"), suite à la
     fourniture du logo (noir et blanc). Les couleurs SÉMANTIQUES
     (--couleur-erreur ci-dessus, orange "champ obligatoire" en dur dans
     .champ-erreur, rose "sans professeur", vert accepté/rouge refusé,
     ambre "verrou perdu") sont volontairement CONSERVÉES telles quelles
     dans tout ce fichier : elles portent une information fonctionnelle
     (état, validation) que le passage au gris ferait perdre — seule la
     palette structurelle/de marque (fond, surface, primaire, accent,
     texte, bordure) passe au gris.
     */
  --couleur-bandeau-app: #161616;
  /* Bandeaux de titre de page (07/09/2026, ajusté) : plus clair que
     --couleur-primaire (#333333, resté pour les boutons/liens) pour une
     vraie nuance avec le bandeau du site (--couleur-bandeau-app,
     #161616) — Bruno : "pas assez de nuance". */
  --couleur-bandeau-page: #4A4A4A;
  /* Écart entre le bandeau du site et le bandeau de titre de la page
     (29/09/2026, demande de Bruno, SYNTHESE section 236) : conservé au
     défilement sur PC (voir .entete-liste / .bandeau-fiche). Même valeur
     que la marge haute de .contenu-liste-adherents / .contenu-formulaire ;
     0 sur téléphone, où le titre de page reste collé au bandeau du site
     (voir fin de fichier). */
  --ecart-bandeaux: 14px;

  --police-affichage: "Fraunces", Georgia, serif;
  --police-texte: "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  --rayon: 10px;
  --ombre: 0 1px 2px rgba(27, 36, 32, 0.06), 0 8px 24px rgba(27, 36, 32, 0.06);
}

* { box-sizing: border-box; }

/* Garantit que l'attribut "hidden" l'emporte toujours sur toute autre règle
   de display définie plus bas (ex. .champ-valeur-figee { display: flex }),
   qui aurait sinon la même spécificité et pourrait l'emporter selon l'ordre
   des règles — bug classique. */
[hidden] { display: none !important; }

/* Champ obligatoire manquant/incorrect (façon Excel) : fond orange clair,
   redevient normal dès que le champ est correctement renseigné. */
.champ-erreur,
.table-lignes .champ-erreur,
fieldset input.champ-erreur,
fieldset select.champ-erreur {
  background: #FDEBD3 !important;
  border-color: #E0A339 !important;
}

/* Discipline/professeur reconduits à la réinscription mais introuvables
   dans le catalogue de la nouvelle saison (renommés/retirés — voir
   sql/14_disciplines_par_saison_2627.sql et resoudreDisciplineLignePour
   Saison() dans assets/formulaire.js, 31/08/2026) : rouge plutôt que
   l'orange de .champ-erreur, volontairement — ce n'est pas une erreur de
   saisie qui bloque l'enregistrement, juste un signal informationnel pour
   le trésorier (comportement historique d'Excel, repris sur demande de
   Bruno pour ne pas le dérouter). */
.table-lignes .champ-discipline-obsolete {
  background: var(--couleur-erreur-fond) !important;
  border-color: var(--couleur-erreur) !important;
  color: var(--couleur-erreur) !important;
}
/* color est une propriété héritée : sans cette ligne, TOUTES les <option>
   de la liste déroulante héritent du rouge du <select> (visible seulement
   liste ouverte, signalé par Bruno sur capture) — on la réinitialise
   explicitement pour qu'elles restent lisibles normalement, seule la case
   fermée du select doit apparaître en rouge. */
.table-lignes .champ-discipline-obsolete option {
  color: var(--couleur-texte);
}

/* Cours en préinscription : professeur pas encore affecté (06/09/2026,
   demande de Bruno) — rose clair, couleur EXACTE demandée (#DA9EC6),
   volontairement distincte du rouge "discipline obsolète" ci-dessus et de
   l'orange ".champ-erreur" : ce n'est ni une erreur ni un signal de
   catalogue, juste "en attente d'affectation pédagogique", et ça doit le
   rester visuellement tant que la case reste vide (pas seulement le temps
   d'une validation). */
.table-lignes .cours-sans-professeur {
  background: #DA9EC6 !important;
  border-color: #B5709E !important;
  color: #401F32 !important;
}
.table-lignes .cours-sans-professeur option {
  color: var(--couleur-texte);
}

/* Ligne grisée (06/09/2026) : inscription pas encore pédagogiquement
   validée, dans la file trésorerie de la page Validations — reste visible
   (pas filtrée) mais visuellement en retrait, pour que le trésorier priorise
   naturellement les lignes déjà prêtes. */
.ligne-grisee {
  opacity: 0.5;
}

/* Colonne Réduction (€) réservée à admin/trésorier (07/09/2026) — masque
   l'en-tête ET chaque cellule via une classe portée par le tableau
   entier, pour couvrir automatiquement toute ligne de cours ajoutée
   après coup sans avoir à la masquer une par une côté JS. */
.masquer-colonne-reduction #entete-colonne-reduction,
.masquer-colonne-reduction .cellule-colonne-reduction {
  display: none;
}

body {
  margin: 0;
  font-family: var(--police-texte);
  color: var(--couleur-texte);
  background: var(--couleur-fond);
  -webkit-font-smoothing: antialiased;
}

/* ---------------------------------------------------------------------
   Page de connexion
   --------------------------------------------------------------------- */

.page-connexion {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background:
    radial-gradient(circle at 15% 10%, rgba(22, 66, 60, 0.05), transparent 45%),
    radial-gradient(circle at 85% 90%, rgba(201, 162, 39, 0.08), transparent 40%),
    var(--couleur-fond);
}

.carte-connexion {
  width: 100%;
  max-width: 380px;
  background: var(--couleur-surface);
  border: 1px solid var(--couleur-bordure);
  border-radius: var(--rayon);
  box-shadow: var(--ombre);
  padding: 40px 32px 32px;
}

.entete-connexion { margin-bottom: 28px; }

.repere {
  display: inline-block;
  font-family: var(--police-texte);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--couleur-accent);
  margin-bottom: 10px;
}

/* Logo (07/09/2026, remplace .repere texte "Le Lieu") — un peu plus
   généreux ici que dans le bandeau applicatif, la carte de connexion
   étant plus spacieuse. */
.logo-connexion { display: block; height: 44px; width: auto; margin-bottom: 14px; }

.entete-connexion h1 {
  font-family: var(--police-texte);
  font-weight: 700;
  font-size: 1.5rem;
  line-height: 1.25;
  margin: 0 0 8px;
  color: var(--couleur-primaire);
}

.sous-titre {
  margin: 0;
  color: var(--couleur-texte-att);
  font-size: 0.92rem;
}

form { display: flex; flex-direction: column; }

label {
  font-size: 0.85rem;
  font-weight: 500;
  margin: 14px 0 6px;
  color: var(--couleur-texte);
}

input[type="email"],
input[type="password"],
input[type="text"],
input[type="search"] {
  font-family: var(--police-texte);
  font-size: 1rem;
  padding: 10px 12px;
  border: 1px solid var(--couleur-bordure);
  border-radius: 8px;
  background: var(--couleur-fond);
  color: var(--couleur-texte);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

input:focus-visible {
  outline: none;
  border-color: var(--couleur-primaire-clair);
  box-shadow: 0 0 0 3px rgba(22, 66, 60, 0.15);
}

button {
  font-family: var(--police-texte);
  font-size: 0.98rem;
  font-weight: 600;
  cursor: pointer;
  border: none;
  border-radius: 8px;
  padding: 12px 16px;
  transition: background-color 0.15s ease, transform 0.05s ease;
}

button:active { transform: translateY(1px); }

#bouton-connexion {
  margin-top: 22px;
  background: var(--couleur-primaire);
  color: white;
}
#bouton-connexion:hover { background: var(--couleur-primaire-clair); }
#bouton-connexion:disabled { opacity: 0.6; cursor: not-allowed; }

.message-erreur {
  margin: 14px 0 0;
  padding: 10px 12px;
  border-radius: 8px;
  background: var(--couleur-erreur-fond);
  color: var(--couleur-erreur);
  font-size: 0.88rem;
}

.message-succes {
  margin: 14px 0 0;
  padding: 10px 12px;
  border-radius: 8px;
  background: #E6F2E9;
  color: #1F6B3A;
  font-size: 0.88rem;
}

.lien-mot-de-passe-oublie {
  margin: 14px 0 0;
  text-align: center;
  font-size: 0.82rem;
}
.lien-mot-de-passe-oublie a { color: var(--couleur-primaire-clair); }

/* ---------------------------------------------------------------------
   Application (après connexion)
   --------------------------------------------------------------------- */

/* v67 (30/08/2026) : la barre n'utilise plus justify-content: space-between
   (qui ne gérait bien que 3 enfants) mais une structure explicite en 4
   zones : [logo+nav] [recherche, flex:1 — absorbe tout l'espace libre et
   pousse ce qui suit à droite] [bouton Nouvel adhérent, optionnel]
   [infos-utilisateur]. */
.barre-app {
  position: sticky;
  /* 29/09/2026 (section 236) : sous le bandeau rayé de l'environnement de
     TEST quand il y en a un (hauteur publiée par ajusterHauteurBandeau(),
     assets/entete.js) ; 0 en PROD. */
  top: var(--hauteur-bandeau-env, 0px);
  z-index: 10;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 18px;
  row-gap: 10px;
  padding: 8px 24px;
  background: var(--couleur-bandeau-app);
  color: white;
}

/* v70/v71 posaient flex-wrap à chaque niveau imbriqué, mais ça ne suffisait
   toujours pas (constaté par Bruno le 31/08/2026 sur Galaxy S8+ 360px —
   "Import" toujours coupé). Cause réelle, plus subtile : un conteneur flex
   avec flex-wrap ne fait passer ses enfants à la ligne que si SA PROPRE
   largeur est contrainte. Sans max-width, .barre-app-gauche se dimensionne
   à la largeur qu'aurait son contenu SANS retour à la ligne (comportement
   par défaut d'un item flex-shrink:0 à base "auto") — donc rien ne force
   jamais nav-app à réellement wrapper, quel que soit le flex-wrap posé sur
   elle. max-width:100% (qui se résout par rapport à .barre-app, son
   conteneur flex parent) impose enfin cette contrainte, et déclenche le
   wrap en cascade jusqu'aux liens de nav. */
.barre-app-gauche { display: flex; flex-wrap: wrap; align-items: center; gap: 18px; row-gap: 6px; flex-shrink: 0; max-width: 100%; min-width: 0; position: relative; }

/* Logo image (07/09/2026, remplace le texte "Le Lieu") — deux tailles
   fournies par Bruno, PC (34px de haut) et mobile (26px), une seule
   affichée à la fois selon la largeur d'écran (voir @media plus bas). */
.logo-app-lien { display: inline-flex; align-items: center; line-height: 0; }
.logo-app-image { display: block; height: 34px; width: auto; }
.logo-app-mobile { display: none; }

/* "Inscriptions" (07/09/2026) : nom de ce module/outil, à côté du logo. */
.libelle-app {
  font-family: var(--police-affichage);
  font-weight: 600;
  font-size: 1.1rem;
  color: white;
}

.barre-app .infos-utilisateur {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  row-gap: 6px;
  font-size: 0.85rem;
  flex-shrink: 0;
  max-width: 100%;
  min-width: 0;
  margin-left: auto;
}

.barre-app button.lien-deconnexion {
  background: transparent;
  color: white;
  border: 1px solid rgba(255,255,255,0.35);
  padding: 5px 11px;
  font-weight: 500;
  font-size: 0.8rem;
}
.barre-app button.lien-deconnexion:hover { background: rgba(255,255,255,0.1); }

/* Bouton "+ Nouvel adhérent" : historique — v67 dans le panneau de liste,
   v67-v74 dans le bandeau global du site, v75 déplacé dans le bandeau de
   titre de chaque page concernée (Formulaire, Liste adhérents), aux côtés
   de Réinscrire/Dupliquer — voir .bouton-action-fiche plus bas et SYNTHESE
   section 9. */

.contenu-app {
  /* 1360px -> 1600px le 09/09/2026 (demande de Bruno) : le bloc COURS de
     la fiche (Cours/Groupe/Durée/Professeur/Début/Fin/Tarif/Réduc/Total)
     avait trop peu de place, rendant les colonnes Tarif/Réduc/Total mal
     lisibles. Élargi de façon cohérente sur .contenu-formulaire et
     .contenu-liste-adherents également, plus bas dans ce fichier. */
  max-width: 1600px;
  margin: 24px auto;
  padding: 0 20px;
}

.contenu-app h1 {
  font-family: var(--police-texte);
  font-weight: 600;
  font-size: 1.25rem;
  color: var(--couleur-primaire);
}

/* ---------------------------------------------------------------------
   Navigation dans la barre d'app
   --------------------------------------------------------------------- */

.nav-app {
  display: none;
  position: fixed;
  top: calc(var(--hauteur-bandeau-app, 52px) + 8px);
  right: 14px;
  left: auto;
  min-width: 220px;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
  background: var(--couleur-bandeau-app);
  border: 1px solid rgba(255,255,255,0.2);
  border-radius: 8px;
  padding: 6px;
  box-shadow: 0 6px 16px rgba(0,0,0,0.2);
  z-index: 20;
}
.nav-app.ouvert { display: flex; }
.nav-app a { padding: 9px 12px; }
.nav-app a {
  color: rgba(255,255,255,0.75);
  text-decoration: none;
  font-size: 0.84rem;
  font-weight: 500;
  padding: 5px 11px;
  border-radius: 6px;
}
.nav-app a:hover { background: rgba(255,255,255,0.08); color: white; }
.nav-app a.actif { background: rgba(255,255,255,0.14); color: white; }
/* Petit point d'alerte répété sur le lien du menu concerné (07/09/2026,
   demande de Bruno) — même information que la cloche, redondance
   volontaire pour qu'elle reste visible même une fois le menu ouvert
   (la cloche seule n'est plus visible sur l'écran une fois le menu
   déroulé par-dessus). */
.nav-app a.a-des-alertes::after {
  content: '';
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: #DA9EC6;
  margin-left: 7px;
  vertical-align: middle;
}

/* Icône "Tableau de bord" (maison, remplace le libellé texte depuis le
   30/08/2026 — voir SYNTHESE section 9) : même comportement actif/hover que
   les autres liens de nav, mais carrée et centrée sur l'icône plutôt que sur
   du texte. */
.nav-icone-accueil { display: inline-flex; align-items: center; justify-content: flex-start; padding: 9px 12px; }
.nav-icone-accueil svg { display: block; }
/* Libellé texte de l'icône maison : masqué sur PC (l'icône seule suffit,
   comme avant), affiché uniquement dans le menu déroulant mobile où elle
   côtoie des liens en texte — voir @media plus bas (31/08/2026). */
.libelle-nav-mobile { display: inline; margin-left: 8px; }
/* Lien "Se déconnecter" dans le menu mobile, masqué par défaut (PC) — voir
   @media (max-width: 700px) plus bas pour l'affichage et le style complet. */
.lien-deconnexion-nav {
  display: block;
  margin-top: 4px;
  padding-top: 13px;
  border-top: 1px solid rgba(255,255,255,0.15);
}
/* Le bouton "Se déconnecter" autonome devient redondant : le menu (toujours
   présent depuis le 07/09/2026) contient déjà son propre lien. */
.infos-utilisateur #bouton-deconnexion { display: none; }

/* Bouton "menu" (hamburger) — unifié PC/mobile le 07/09/2026 (demande de
   Bruno, auparavant mobile uniquement). Toujours affiché, à droite du
   bandeau ; nav-app reste dans le DOM sous barre-app-gauche mais s'ouvre
   ici via position:fixed (voir plus bas), indépendamment de sa position
   réelle. margin-left:auto (07/09/2026, correctif) : pousse ce bouton —
   et tout ce qui le suit dans le DOM (cloche, nom) — jusqu'au bord droit
   du bandeau ; sans lui, rien ne comblait l'espace entre la recherche
   (capée à 320px) et ce groupe, qui flottait au milieu du bandeau au lieu
   de longer le bord droit. */
.bouton-menu-mobile {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: transparent;
  color: white;
  border: 1px solid rgba(255,255,255,0.35);
  border-radius: 6px;
  padding: 6px 10px;
  font-family: var(--police-texte);
  font-size: 0.84rem;
  font-weight: 500;
}
.bouton-menu-mobile:hover { background: rgba(255,255,255,0.1); }

/* "Menu" à côté de l'icône hamburger, PC uniquement (09/09/2026, demande
   de Bruno) — masqué par défaut (mobile, où la place manque), révélé dans
   le même bloc @media (min-width: 781px) que la recherche centrée
   (voir plus bas dans ce fichier), pour rester le pendant exact du
   @media (max-width: 780px) déjà utilisé partout ailleurs dans ce
   bandeau. */
.libelle-menu-pc { display: none; }

/* Cloche d'alerte (07/09/2026) — juste à côté du bouton menu. */
.bouton-cloche-alerte {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  background: transparent;
  color: white;
  border: 1px solid rgba(255,255,255,0.35);
  border-radius: 6px;
  width: 32px;
  height: 32px;
  padding: 0;
}
.bouton-cloche-alerte:hover { background: rgba(255,255,255,0.1); }
.pastille-alerte {
  display: none;
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 16px;
  height: 16px;
  padding: 0 3px;
  border-radius: 999px;
  background: #DA9EC6;
  color: #401F32;
  font-size: 0.65rem;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}
.pastille-alerte.visible { display: block; }

/* ---------------------------------------------------------------------
   Recherche globale d'adhérent, dans le bandeau du site (30/08/2026)
   --------------------------------------------------------------------- */

/* Libellé court sur mobile, réutilisable pour tout futur libellé trop long
   (ex. "Code postal" -> "CP" — voir formulaire.php). Doit impérativement
   être défini AVANT les @media qui le réaffichent : à spécificité égale,
   une règle sans condition de media passée APRÈS un bloc @media reprend le
   dessus même quand la condition du @media est vraie — c'est exactement ce
   qui rendait "CP" invisible sur mobile (constaté par Bruno le 31/08/2026),
   cette règle était placée bien plus bas dans le fichier. */
.libelle-court { display: none; }

/* Sur petit écran (30/08/2026, corrige un bug signalé par Bruno : le bouton
   "+ Nouvel adhérent" se retrouvait poussé hors de l'écran visible). Cause
   racine : .barre-app-gauche / .bouton-nouveau-bandeau / .infos-utilisateur
   avaient tous flex-shrink:0 et .barre-app n'avait pas de flex-wrap — rien
   ne pouvait rétrécir NI passer à la ligne, donc la barre débordait purement
   et simplement hors du viewport. flex-wrap (posé plus haut sur .barre-app)
   est le vrai correctif : il garantit qu'aucun élément ne peut plus finir
   hors écran, quel que soit le contenu futur du bandeau. */

/* Recherche toujours visible et centrée en PC (09/09/2026, demande de
   Bruno) — retirée le 19/09/2026 (remplacée par des champs de recherche
   propres à chaque page). */
@media (min-width: 781px) {
  .libelle-menu-pc { display: inline; }
}

/* ---------------------------------------------------------------------
   Mobile (31/08/2026) : menu hamburger — voir SYNTHESE section 9.
   Le reste des ajustements mobiles (cadres réduits, titre de page collé
   au bandeau) est regroupé en fin de fichier : ces règles surchargent
   .panneau-formulaire/.entete-liste/etc., définies plus bas — les
   regrouper là-bas évite l'erreur d'ordre de cascade qui les a rendues
   inopérantes en v73 (une règle sans condition de media, définie APRÈS un
   bloc @media dans le fichier, reprend le dessus même quand la condition
   du @media est vraie).
   --------------------------------------------------------------------- */
@media (max-width: 700px) {
  /* "Code postal" -> "CP" : le libellé complet passait sur deux lignes et
     déformait la grille de champs sur petit écran. */
  .libelle-long { display: none; }
  .libelle-court { display: inline; }

  /* Logo : version mobile plus compacte, "Inscriptions" masqué pour
     gagner de la place (07/09/2026). */
  .logo-app-pc { display: none; }
  .logo-app-mobile { display: block; }
  .libelle-app { display: none; }
}

/* ---------------------------------------------------------------------
   Pages Formulaire et Liste adhérents (30/08/2026)
   --------------------------------------------------------------------- */

/* Anciennement une seule page à deux colonnes (.contenu-adherents,
   360px liste | 1fr formulaire) — scindée en deux pages distinctes, chacune
   avec un conteneur simple centré (voir SYNTHESE section 9). */

.contenu-formulaire {
  max-width: 1600px; /* 1360px -> 1600px le 09/09/2026, voir .contenu-app plus haut */
  margin: 14px auto;
  padding: 0 14px 30px;
}

.contenu-liste-adherents {
  max-width: 1600px; /* 1360px -> 1600px le 09/09/2026, voir .contenu-app plus haut */
  margin: 14px auto;
  padding: 0 14px 30px;
}

.panneau-liste {
  background: var(--couleur-surface);
  border: 1px solid var(--couleur-bordure);
  border-radius: 8px;
  /* Pas de padding ici, comme .panneau-formulaire : le bandeau de titre doit
     occuper toute la largeur pour aller bord-à-bord (coins arrondis inclus).
     Le padding est porté par .corps-liste. */
}

.corps-liste { padding: 14px; }
/* Panneaux de page consécutifs (page Validations : 2 panneaux l'un sous
   l'autre) — 29/09/2026 (section 236) : séparés du même écart que celui
   qui sépare le bandeau du site du bandeau de titre (0 sur téléphone,
   inchangé), au lieu d'être collés. Nécessaire aussi pour que le cache
   au-dessus du bandeau de titre (.entete-liste::before) ne recouvre pas
   le bas du panneau précédent. */
.panneau-liste + .panneau-liste { margin-top: var(--ecart-bandeaux, 0px); }

/* Titre de page homogénéisé avec .entete-formulaire (31/08/2026, sur
   demande de Bruno : "même format que celui du formulaire" — à reprendre
   pour toute future page du portail, par souci de cohérence visuelle
   d'ensemble). Reste "collant" au défilement (11/09/2026, demande de
   Bruno sur la page Membres du CA — étendu à .entete-liste en général,
   partagée avec la Liste adhérents, pour un comportement cohérent sur
   toutes les pages qui l'utilisent) : même mécanisme que .bandeau-fiche
   du Formulaire, ancré juste sous la barre de navigation du site via la
   même variable CSS --hauteur-bandeau-app (assets/entete.js
   ajusterHauteurBandeau()), qui reste juste tant même si cette barre
   passe sur plusieurs lignes (recherche pleine largeur, menu hamburger
   sur mobile...). */
.entete-liste {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  background: var(--couleur-bandeau-page);
  border-radius: 8px 8px 0 0;
  position: sticky;
  /* 29/09/2026 (demande de Bruno, SYNTHESE section 236) : + l'écart entre
     les 2 bandeaux, pour qu'il reste identique au défilement au lieu que
     le titre de page vienne se coller au bandeau du site. */
  top: calc(var(--hauteur-bandeau-app, 52px) + var(--ecart-bandeaux, 0px));
  z-index: 9;
}
/* Cache opaque de la couleur du fond de page dans l'écart au-dessus du
   bandeau de titre (29/09/2026, section 236) : sans lui, le contenu qui
   défile passerait visiblement dans cet espace entre les 2 bandeaux.
   Déborde de 15 px à gauche et à droite pour couvrir aussi la bordure du
   panneau (1 px) et la marge latérale de la page (14 px) — pas plus, sinon
   la page entière prend une barre de défilement horizontale. Inutile sur
   téléphone (pas d'écart, voir fin de fichier). Voir aussi .bandeau-fiche. */
.entete-liste::before,
.bandeau-fiche::before {
  content: '';
  position: absolute;
  left: -15px;
  right: -15px;
  bottom: 100%;
  height: var(--ecart-bandeaux, 0px);
  background: var(--couleur-fond);
  pointer-events: none;
}
.entete-liste h1 {
  font-family: var(--police-texte);
  font-weight: 700;
  color: white;
  margin: 0;
  font-size: 1.15rem;
}
/* Fiche en cours d'édition, entre parenthèses à côté du titre de page
   (20/09/2026, demande de Bruno — page Formulaire uniquement pour
   l'instant) : plus petit, moins appuyé que le titre lui-même. */
.titre-details-petit { font-size: 0.85rem; font-weight: 500; opacity: 0.85; margin-left: 6px; }
.panneau-formulaire {
  background: var(--couleur-surface);
  border: 1px solid var(--couleur-bordure);
  border-radius: 8px;
  /* Pas de padding ici : le bandeau sticky doit occuper toute la largeur
     sans marge négative (les marges négatives cassent le calcul de
     position sticky). Le padding est porté par .corps-formulaire. */
}

.corps-formulaire { padding: 14px; }

.filtres-liste { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.filtres-liste select, .filtres-liste input {
  font-family: var(--police-texte);
  padding: 6px 8px;
  border: 1px solid var(--couleur-bordure);
  border-radius: 6px;
  font-size: 0.85rem;
}
/* Page Membres du CA (11/09/2026, demande de Bruno) : sélecteur de saison
   et bascule d'affichage (Cartes/Liste, descendue du bandeau de titre où
   elle prenait trop de place sur mobile) sur une même ligne — responsive,
   repli automatique l'un sous l'autre si l'espace manque (flex-wrap),
   sans media query dédiée (même principe que .ligne-filtres-validation
   plus bas). Redéfinit .filtres-liste en ligne pour cette seule page (elle
   reste en colonne partout ailleurs, ex. Liste adhérents, inchangée). */
.filtres-liste-ca { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 10px; }
.filtres-liste-ca select { flex: 1 1 200px; min-width: 160px; margin: 0; }
.filtres-liste-ca input[type="search"] { flex: 1 1 220px; min-width: 160px; margin: 0; }
.filtres-liste .case-filtre {
  font-size: 0.78rem;
  color: var(--couleur-texte-att);
  padding: 2px 2px 0;
}
/* Regroupe "Paiement(s) à valider" et "En attente de validation du prof"
   côte à côte en vue PC (09/09/2026, demande de Bruno) — repli automatique
   en colonne si l'espace manque (mobile), sans media query dédiée. */
.ligne-filtres-validation { display: flex; flex-wrap: wrap; gap: 4px 20px; }

.table-scroll { overflow-x: auto; overflow-y: visible; border: 1px solid var(--couleur-bordure); border-radius: 6px; background: white; }
/* 25/09/2026 (demande de Bruno, encapsulation des blocs de Configuration
   de saison dans un cadre au fond gris #EEF0EA comme les fieldset de
   Formulaire — voir .bloc-configuration-saison plus bas) : fond blanc
   explicite ajouté ici pour que le tableau continue à se détacher du
   cadre qui l'entoure, comme les champs blancs se détachent du fond gris
   d'un fieldset. Sans cette ligne, .table-lignes th (fond #EEF0EA lui
   aussi, voir plus bas) se fondrait visuellement dans le nouveau cadre
   gris. Sans risque ailleurs dans l'appli : .table-scroll n'est utilisée
   que dans des conteneurs à fond blanc (.panneau-liste, --couleur-surface
   #FFFFFF) — jamais directement sur le fond de page --couleur-fond
   #F4F4F4. */
/* Hauteur limitée à 66vh avec défilement interne retirée (19/09/2026,
   demande de Bruno — "joli mais inutile", le tableau doit s'étendre
   librement en hauteur et défiler avec la page, pas dans sa propre
   boîte). Le défilement HORIZONTAL (overflow-x) reste nécessaire pour
   les tableaux larges sur petit écran. */
/* Scrollbar horizontale toujours visible et stylée (10/09/2026, suite au
   signalement de Bruno : colonnes Réduc/Total qui "disparaissent" sur le
   bloc Cours à largeur intermédiaire). Le défilement fonctionnait déjà
   (min-width sur #table-disciplines/#table-prestations/#table-paiements
   + overflow:auto ci-dessus), mais restait invisible : par défaut, macOS
   (Chrome/Safari/Edge) affiche une scrollbar "overlay", masquée tant
   qu'on ne survole pas ou ne défile pas activement — rien ne signalait à
   l'utilisateur que du contenu supplémentaire existait hors champ. Les
   règles ci-dessous forcent une scrollbar "classique", toujours visible
   dès que le contenu déborde, sans rien changer aux largeurs de colonnes
   ni au comportement de défilement lui-même. */
/* Barres de défilement élargies sur tout le site (17/09/2026, demande de
   Bruno — "peu visibles pour l'instant"), sur TOUT élément défilant.
   29/09/2026 (demande de Bruno, SYNTHESE section 237 — "trop étroites
   pour être clairement visibles" sur PC) : les propriétés standard
   scrollbar-width / scrollbar-color (posées ici, dont un "thin" sur
   .table-scroll) prennent le pas, depuis Chrome/Edge 121 (début 2024),
   sur toute la mise en forme ::-webkit-scrollbar : les 16 px prévus
   n'étaient donc plus appliqués, le navigateur affichait sa barre fine
   par défaut. Correction :
   - Chrome / Edge / Safari : ::-webkit-scrollbar seul, 18 px, curseur
     plus foncé (lisible sur fond blanc comme sur fond gris), réservé aux
     souris (pointer: fine) — sur téléphone/tablette, les barres
     natives, discrètes, restent inchangées ;
   - Firefox (pas de ::-webkit-scrollbar) : scrollbar-width: auto +
     couleurs, via @supports, pour ne jamais gêner les autres navigateurs.
   NE PLUS poser scrollbar-width / scrollbar-color ailleurs dans ce
   fichier : cela désactiverait de nouveau la mise en forme élargie. */
@media (pointer: fine) {
  *::-webkit-scrollbar { height: 18px; width: 18px; }
  *::-webkit-scrollbar-track { background: #ECECEC; border-radius: 9px; }
  *::-webkit-scrollbar-thumb { background: #9A9A9A; border-radius: 9px; border: 3px solid #ECECEC; min-height: 40px; min-width: 40px; }
  *::-webkit-scrollbar-thumb:hover { background: #6E6E6E; }
  *::-webkit-scrollbar-thumb:active { background: #555555; }
  *::-webkit-scrollbar-corner { background: #ECECEC; }
}
@supports not selector(::-webkit-scrollbar) {
  * { scrollbar-width: auto; scrollbar-color: #9A9A9A #ECECEC; }
}

.table-adherents { width: auto; min-width: 100%; border-collapse: collapse; font-size: 0.82rem; }
.table-adherents th {
  position: sticky; top: 0;
  background: #EEF0EA;
  text-align: left;
  padding: 6px 8px;
  font-weight: 700;
  border-bottom: 1px solid var(--couleur-bordure);
}
.table-adherents td { padding: 5px 8px; border-bottom: 1px solid var(--couleur-bordure); }
.table-adherents tbody tr { cursor: pointer; background: var(--couleur-surface); }
.table-adherents tbody tr:nth-child(even) { background: #FAFBF8; }
.table-adherents tbody tr:hover { background: #EFF3EC; }
.table-adherents tbody tr.ligne-selectionnee {
  background: rgba(22, 66, 60, 0.09);
  box-shadow: inset 3px 0 0 var(--couleur-primaire);
}
/* Inscription "payée par un autre adhérent" annoncée mais non encore
   désignée (voir validerFormulaire() dans formulaire.js, et rafraichirListe()
   dans liste_adherents.js) : liseré doré discret + icône, pour la repérer
   sans la confondre avec une vraie erreur (rouge, réservé à
   .champ-erreur/.message-erreur). */
.table-adherents tbody tr.ligne-payeur-a-preciser {
  box-shadow: inset 3px 0 0 var(--couleur-accent);
}
.indicateur-payeur-a-preciser { font-size: 0.78rem; }
.table-adherents .col-montant { text-align: right; }
.table-adherents td.col-montant { text-align: right; font-variant-numeric: tabular-nums; }
/* Âges (19/09/2026, demande de Bruno) : même alignement à droite que
   les montants, sans être des montants. */
.table-adherents .col-nombre { text-align: right; }
.table-adherents td.col-nombre { text-align: right; font-variant-numeric: tabular-nums; }
/* "Ajouté/Modifié le" de Liste adhérents (29/09/2026, section 238) :
   date et heure sur une seule ligne, chiffres alignés. */
.table-adherents td.col-date-heure { white-space: nowrap; font-variant-numeric: tabular-nums; }
.etat-vide { text-align: center; color: var(--couleur-texte-att); padding: 20px 10px; font-size: 0.85rem; }

/* Cartes tactiles de Liste adhérents (30/08/2026 — .liste-cartes-adherents,
   .carte-adherent...) retirées le 27/09/2026 (demande de Bruno, SYNTHESE
   section 222) : remplacées sur téléphone par le tableau lui-même, avec
   n° de ligne et en-tête figés (voir .table-scroll-entete-figee). */

/* Page "Membres du CA" (10/09/2026, demande de Bruno) — bascule Cartes/
   Liste MANUELLE et mémorisée (voir assets/membres_ca.js), volontairement
   indépendante du type d'appareil, contrairement à .liste-cartes-adherents
   ci-dessus (qui, elle, bascule automatiquement selon pointer:coarse).
   11/09/2026 : la page passe de deux conteneurs uniques (table/cartes) à
   plusieurs BLOCS DE REGROUPEMENT générés dynamiquement (Membres du
   Bureau / Professeurs / Autres membres) — la bascule ne pose donc plus
   l'attribut `hidden` sur un élément fixe, mais une classe
   `mode-cartes`/`mode-liste` sur le conteneur parent #groupes-membres-ca,
   qui recouvre tous les blocs générés en une fois. */
.entete-liste-titre { display: flex; align-items: center; gap: 8px; }
.bascule-affichage { display: inline-flex; border: 1px solid var(--couleur-bordure); border-radius: 6px; overflow: hidden; }
.bouton-bascule-affichage {
  background: white; border: none; padding: 6px 13px; font-size: 0.8rem; font-weight: 600;
  color: var(--couleur-texte-att); cursor: pointer;
}
.bouton-bascule-affichage + .bouton-bascule-affichage { border-left: 1px solid var(--couleur-bordure); }
.bouton-bascule-affichage:hover { background: var(--couleur-fond); }
.bouton-bascule-affichage.actif { background: var(--couleur-primaire); color: white; }
.bouton-bascule-affichage.actif:hover { background: var(--couleur-primaire-clair); }

/* Blocs de regroupement (11/09/2026, demande de Bruno) : même présentation
   visuelle que les fieldsets du Formulaire (bordure, fond gris clair,
   titre en majuscules) sans réutiliser l'élément <fieldset> lui-même —
   volontaire, pour ne pas retomber dans le piège du min-width implicite
   du navigateur déjà rencontré et corrigé sur le bloc Cours (voir
   SYNTHESE sections 39-41) : un <section> classique n'a pas ce
   comportement, plus sûr pour un contenu qui doit rester pleinement
   responsive (grille de cartes à l'intérieur). */
.bloc-groupe-ca {
  border: 1px solid var(--couleur-bordure);
  border-radius: 6px;
  padding: 12px 14px;
  margin-bottom: 14px;
  background: #EEF0EA;
}
.bloc-groupe-ca:last-child { margin-bottom: 0; }
.bloc-groupe-ca-titre { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
.bloc-groupe-ca-titre h2 {
  font-family: var(--police-texte);
  font-weight: 700;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--couleur-primaire);
  margin: 0;
}

/* Vue Liste (tableau) : spécificité ID+classes pour rester prioritaire sur
   ".panneau-liste .table-scroll { display:none }" du bloc
   "@media (pointer:coarse)" plus bas, qui sinon masquerait les tableaux
   de cette page sur tablette/smartphone MÊME quand l'utilisateur a
   explicitement choisi "Liste" — cette page ne doit pas suivre cette
   bascule automatique (déjà le cas depuis le v158, adapté ici aux blocs
   multiples). */
#groupes-membres-ca.mode-liste .bloc-ca-vue-liste.table-scroll { display: block; }
#groupes-membres-ca.mode-cartes .bloc-ca-vue-liste { display: none; }
#groupes-membres-ca.mode-liste .bloc-ca-vue-cartes { display: none; }
.col-action-ca { width: 1%; white-space: nowrap; text-align: right; }
/* .table-adherents pose cursor:pointer sur toutes les lignes (pertinent
   pour la Liste adhérents, où cliquer une ligne ouvre la fiche) — cette
   page n'a pas cette action (seul le bouton "Voir la fiche" navigue),
   annulé ici pour ne pas laisser croire que la ligne entière est cliquable. */
.bloc-groupe-ca tbody tr { cursor: default; }
/* Email/Téléphone en toutes lettres dans le tableau aussi (11/09/2026,
   demande de Bruno), icône + valeur côte à côte dans la cellule. */
.cellule-contact-ca { display: inline-flex; align-items: center; gap: 6px; }

/* Vue Cartes (11/09/2026, demande de Bruno) : même présentation que les
   tuiles du Tableau de bord — grille responsive à cartes de largeur ET
   hauteur égales par ligne (voir .grille-tableau-bord plus haut, repris
   ici à l'identique), plutôt que l'empilement vertical du premier jet. */
.liste-cartes-membres-ca {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 280px));
  justify-content: center;
  gap: 14px;
}
.carte-membre-ca {
  border: 1px solid var(--couleur-bordure);
  border-radius: 8px;
  padding: 14px 16px;
  background: var(--couleur-surface);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
/* Ordre demandé par Bruno : 1. Prénom NOM, 2. Email, 3. Téléphone,
   4. Fonctions (ou Cours enseignés dans le bloc Professeurs) — voir le
   HTML généré par assets/membres_ca.js. */
.carte-membre-ca-nom { font-weight: 700; font-size: 0.92rem; margin: 0; }
/* Email/Téléphone/Fonctions : même taille de police pour les trois
   (demande de Bruno), icône + valeur alignées sur une ligne. */
.carte-membre-ca-ligne { display: flex; align-items: center; gap: 6px; margin: 0; font-size: 0.8rem; color: var(--couleur-texte-att); }
.carte-membre-ca-fonctions { color: var(--couleur-texte); }
.carte-membre-ca-actions { margin-top: 6px; }

/* Icônes email/téléphone "actives/inactives" (11/09/2026, demande de
   Bruno : mêmes icônes que la page Formulaire — voir #lien-p-email et
   .resp-lien-tel dans formulaire.php) — même principe que
   .lien-action-champ : grisées et non cliquables si l'information
   n'existe pas. Standalone (pas de positionnement absolu à l'intérieur
   d'un champ de saisie, contrairement à .lien-action-champ). Utilisées
   aussi bien en vue Cartes qu'en vue Liste (tableau), et — variante
   .icone-email-titre — dans le bandeau de titre de page et de chaque bloc
   pour l'email groupé. */
.icone-email-membre, .icone-tel-membre {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0;
  text-decoration: none; color: var(--couleur-primaire);
  background: var(--couleur-fond);
}
.icone-email-membre:hover, .icone-tel-membre:hover { background: rgba(22, 66, 60, 0.12); }
.icone-email-membre[aria-disabled="true"], .icone-tel-membre[aria-disabled="true"] {
  opacity: 0.35; pointer-events: none; color: var(--couleur-texte-att);
}
/* Icône téléphone : PC/Mobile dans les deux modes, mais téléphone
   seulement sur Mobile (demande de Bruno) — le numéro en toutes lettres
   reste affiché sur PC, seule l'icône cliquable disparaît (peu utile
   sans écran tactile). Seuil 700px : même seuil que la bascule Cours/
   Prestations/Paiements en cartes plus haut, déjà établi comme seuil
   "Mobile" dans le reste du site. */
.icone-tel-membre { display: none; }
@media (max-width: 700px) {
  .icone-tel-membre { display: inline-flex; }
}
/* Icônes email GROUPÉES (bandeau de titre de page + titre de chaque
   bloc, "Envoyer un email à tous les membres du bloc/de la page") :
   affichées partout, PC et Mobile (11/09/2026, demande de Bruno — retour
   en arrière après un essai de masquage sur PC). Sur Mobile, lien
   mailto: classique inchangé (fonctionne bien). Sur PC, le comportement
   au clic diffère : copie de la liste dans le presse-papier + explication
   à l'utilisateur, SANS tenter d'ouvrir le client mail (voir
   gererClicEmailGroupeCA() dans assets/membres_ca.js — l'ouverture du
   client mail via mailto: faisait planter Outlook, malgré 3 correctifs
   tentés successivement, voir SYNTHESE sections 49-51). La distinction
   PC/Mobile se fait en JS (largeur de fenêtre, même seuil 700px que
   .icone-tel-membre ci-dessus), pas en CSS : ces icônes n'ont donc plus
   besoin d'être masquées/affichées selon la largeur d'écran. */
/* Icône email "tous les membres du bloc / de la page" (11/09/2026) : fond
   blanc sur .bloc-groupe-ca (gris clair, comme les autres icônes ci-
   dessus), mais fond clair semi-transparent sur le bandeau de titre
   coloré (.entete-liste) où la variante par défaut serait peu lisible. */
.icone-email-titre { background: rgba(255,255,255,0.16); color: white; width: 26px; height: 26px; }
.icone-email-titre:hover { background: rgba(255,255,255,0.3); }

@media (pointer: coarse) and (max-width: 820px) {
  /* .table-scroll est réutilisée telle quelle dans formulaire.php
     (Disciplines/Prestations/Paiements) — sans ce scope à .panneau-liste
     (qui n'existe que sur cette page), cette règle masquait aussi ces
     tableaux sur tout appareil tactile, donc systématiquement sur mobile.
     C'est LA cause du bug "Disciplines/Paiements ne s'affichent pas sur
     mobile" signalé à plusieurs reprises par Bruno (31/08/2026) — la
     table SE MASQUAIT, elle ne débordait pas et n'était pas mal dimensionnée. */
  /* 27/09/2026 (signalé par Bruno, capture sur téléphone) : cette règle
     visait à l'origine ".panneau-liste .table-scroll" — or .panneau-liste
     est devenu le cadre commun de nombreuses pages (Configuration de
     saison, Gestion des droits, Cours des élèves, Paye Professeurs...),
     dont AUCUNE n'a de cartes de remplacement : sur tout écran tactile de
     moins de 820px, leurs tableaux disparaissaient entièrement, laissant
     des blocs vides. Même famille de bug que le 31/08/2026 ci-dessus.
     Désormais ciblée sur la seule classe .table-scroll-avec-cartes, posée
     uniquement sur le tableau de Liste adhérents (liste_adherents.php). */
  /* 27/09/2026 (section 222) : les cartes de Liste adhérents ont été
     retirées — plus aucun tableau n'est masqué ici. */

  /* Page Validations (06/09/2026) : réutilise .panneau-liste pour le style
     visuel de base, mais n'a PAS d'équivalent "cartes" comme la liste
     adhérents — sans cette règle, ses tableaux (Cours en attente,
     Trésorerie) se retrouvaient masqués sur mobile par la règle
     ci-dessus, sans aucun remplacement (signalé par Bruno). Même
     spécificité CSS que la règle qu'elle neutralise : gagne parce qu'elle
     vient après dans le fichier. */
  .panneau-validations .table-scroll { display: block; }
}

/* Formulaire — sections plus compactes, moins "cartes", plus "feuille de calcul" */
fieldset {
  border: 1px solid var(--couleur-bordure);
  border-radius: 6px;
  padding: 12px 14px;
  margin: 0 0 10px;
  background: #EEF0EA; /* #FCFCFA -> #EEF0EA le 09/09/2026 (demande de Bruno) : gris très clair, déjà utilisé pour
                          les en-têtes de tableau (.table-lignes th) — pour que les champs blancs se détachent. */
}
legend {
  font-family: var(--police-texte);
  font-weight: 700;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--couleur-primaire);
  padding: 0 6px;
}

/* Configuration de saison (25/09/2026, demande de Bruno) : "Encapsuler
   chaque bloc [...] comme le bloc Réglages de la saison et reproduire
   fidèlement le style de bloc adopté dans la page Formulaire." Les 5
   blocs de la page (Réglages de la saison, Disciplines et tarifs, Modes
   de paiement, Durées de cours et coefficients, Autres prestations)
   partagent désormais ce cadre gris, copié trait pour trait du couple
   fieldset/legend ci-dessus (même fond #EEF0EA, même rayon, même casse/
   taille de titre) -- une classe dédiée plutôt que les éléments fieldset/
   legend eux-mêmes : cette page n'a pas de <form> englobant (le
   comportement natif "disabled en cascade" de fieldset n'a donc aucune
   utilité ici). La carte "Suppression de {libellé}"
   (.carte-parametre.carte-zone-danger) n'est PAS concernée : hors
   périmètre de cette demande, son style rouge/alerte distinct sert
   justement à la distinguer des réglages normaux.
   25/09/2026 (bis, retour de Bruno) : "Reproduire le positionnement des
   titres des blocs de la page Formulaire" -- un <legend> natif chevauche
   TOUJOURS la bordure haute de son <fieldset> (comportement du
   navigateur, aucun CSS particulier sur Formulaire). Reproduit ici avec
   .titre-bloc-configuration-saison en position absolute (plutôt qu'un
   <legend> natif, écarté à dessein -- voir plus haut) : le bloc passe en
   position:relative avec un padding-top augmenté pour laisser la place
   au titre qui chevauche sa bordure, le titre lui-même récupère le fond
   du bloc (#EEF0EA) pour "percer" visuellement la bordure exactement
   comme un legend natif (dont le fond transparent laisse voir le fond du
   fieldset -- ici opaque puisque le bloc n'est pas à fond blanc). */
.bloc-configuration-saison {
  position: relative;
  border: 1px solid var(--couleur-bordure);
  border-radius: 6px;
  background: #EEF0EA;
  padding: 26px 16px 14px;
  margin-top: 20px;
}
/* Le tout premier bloc de la page (Réglages de la saison) suit
   directement le sélecteur de saison de l'entête, sans avoir besoin du
   même espacement que les blocs suivants entre eux. */
.bloc-configuration-saison:first-of-type { margin-top: 22px; }
.titre-bloc-configuration-saison {
  position: absolute;
  top: -10px;
  left: 12px;
  margin: 0;
  background: #EEF0EA;
  padding: 0 6px;
  font-family: var(--police-texte);
  font-weight: 700;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--couleur-primaire);
}
/* 25/09/2026 (livraison 206, demande de Bruno) : "rapprocher [le texte
   d'avertissement/d'explication] du titre du bloc (même espacement qu'entre
   les blocs)" -- le padding-top de .bloc-configuration-saison (26px)
   suffit déjà à lui seul à dégager le titre (qui chevauche la bordure,
   voir plus haut) ; le premier paragraphe (.aide-champ ou .message-erreur,
   selon le bloc) ajoutait par-dessus sa propre marge habituelle (10-14px),
   creusant un vide bien plus large que les 20px qui séparent les blocs
   entre eux. Ciblé via le sélecteur de frère adjacent (le titre est
   toujours le tout premier enfant du bloc) plutôt que par bloc : s'applique
   uniformément aux 5 blocs de la page, présent ou futur, sans dépendre
   d'une classe ou d'un id particulier sur le paragraphe. */
.titre-bloc-configuration-saison + .aide-champ,
.titre-bloc-configuration-saison + .message-erreur {
  margin-top: 0;
}

/* 25/09/2026 (ter, demande de Bruno) : retire les flèches natives
   d'incrémentation/décrémentation des champs numériques de cette page
   ("peu lisible") -- scopé à .bloc-configuration-saison (donc aux 5
   blocs de cette page uniquement, sans toucher aux input[type=number]
   des autres pages, dont certaines s'appuient volontairement dessus,
   ex. .bloc-prelevement-echeances). Les champs monétaires et le
   coefficient de durée passent par ailleurs en input[type=text] pour
   permettre l'affichage en virgule (voir plus bas) : cette règle reste
   utile pour les champs numériques restants (Nombre de semaines, Seuil
   de rentabilité, Profs rémunérés). */
.bloc-configuration-saison input[type="number"]::-webkit-inner-spin-button,
.bloc-configuration-saison input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.bloc-configuration-saison input[type="number"] { -moz-appearance: textfield; }

/* Bandeau flottant : nom/n° dossier uniquement, toujours visible au défilement.
   --hauteur-bandeau-app (31/08/2026, voir assets/entete.js ajusterHauteurBandeau())
   remplace un ancien "top: 52px" codé en dur, faux dès que le bandeau du site
   passe sur plusieurs lignes (recherche pleine largeur, menu hamburger...) —
   Bruno avait signalé que ce bandeau ne restait plus fixé/visible au défilement
   sur mobile pour cette raison. */
.bandeau-fiche {
  position: sticky;
  /* 29/09/2026 (section 236) : même écart que .entete-liste (était +8px). */
  top: calc(var(--hauteur-bandeau-app, 52px) + var(--ecart-bandeaux, 0px));
  z-index: 9;
  box-shadow: 0 2px 8px rgba(27, 36, 32, 0.1);
  background: var(--couleur-fond); /* 09/09/2026 : filet de sécurité — ce
    conteneur n'a que .entete-formulaire comme enfant visible (déjà opaque),
    mais un fond explicite ici évite tout aperçu du contenu de la fiche en
    dessous pendant le défilement si jamais la hauteur mesurée du bandeau du
    site (--hauteur-bandeau-app) est momentanément inexacte. */
}

/* Traçabilité de la saisie (08/09/2026) — discrète, sous le bandeau de
   titre du formulaire, alignée à droite. */
.ligne-saisie-par {
  text-align: right;
  font-size: 0.72rem;
  color: var(--couleur-texte-att);
  font-style: italic;
  margin: 4px 14px 0 0;
}

.entete-formulaire {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 14px;
  background: var(--couleur-bandeau-page);
  border-radius: 8px 8px 0 0;
}
.entete-formulaire h2 {
  font-family: var(--police-texte); font-weight: 700; color: white;
  margin: 0; font-size: 1.02rem;
  white-space: nowrap; overflow: hidden;
  flex-shrink: 1; min-width: 60px;
}
.badge-num-dossier {
  font-size: 0.8rem; font-weight: 700; color: white;
  background: rgba(255,255,255,0.16); padding: 3px 9px; border-radius: 999px;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.groupe-boutons-entete { margin-left: auto; display: flex; align-items: center; gap: 8px; position: relative; flex-shrink: 0; }

/* État de validation, dans le bandeau de titre (09/09/2026, demande du
   trésorier) : discret (petit, blanc atténué), entre le n° de dossier et
   les boutons d'action — visible uniquement tant que la fiche n'est pas
   entièrement validée (pédagogique + financière). Voir
   actualiserEtatValidationFormulaire() dans assets/formulaire.js. */
.etat-validation-formulaire {
  font-size: 0.72rem; color: rgba(255,255,255,0.75); font-style: italic;
  white-space: nowrap; flex-shrink: 1; overflow: hidden; text-overflow: ellipsis;
}

/* Champ Professeur en attente de validation pédagogique (09/09/2026,
   demande du trésorier) — couleur uniquement, l'info-bulle native du
   titre "En attente de validation du professeur" s'affiche au survol. */
.champ-professeur-en-attente { color: var(--couleur-erreur); font-weight: 600; }

/* Boutons d'action du bandeau de fiche (+ Nouvel adhérent, Réinscrire,
   Dupliquer) : version compacte du bouton secondaire habituel — trois
   boutons doivent tenir aux côtés du titre, réduits sur demande de Bruno
   (31/08/2026). */
.bouton-action-fiche { padding: 5px 10px; font-size: 0.76rem; white-space: nowrap; }
/* 09/09/2026 : Enregistrer/Supprimer, remontés dans ce bandeau, combinent
   .bouton-action-fiche avec .bouton-principal/.bouton-danger — sélecteur
   composé pour que la taille compacte l'emporte malgré leur ordre dans ce
   fichier (règles de base plus bas, donc normalement gagnantes à
   spécificité égale). */
.bouton-principal.bouton-action-fiche,
.bouton-danger.bouton-action-fiche {
  padding: 5px 10px;
  font-size: 0.76rem;
}
/* Enregistrer : gris tant que le formulaire n'est pas complet, vert dès
   qu'il l'est (09/09/2026, demande de Bruno) — reste un vrai bouton
   cliquable dans les deux cas (jamais `disabled`), voir
   actualiserEtatBoutonEnregistrer() et afficherToastErreurs() dans
   assets/formulaire.js pour la logique. Ciblé par ID : l'emporte sur
   .bouton-principal sans avoir besoin d'un sélecteur composé de plus. */
#bouton-enregistrer {
  background: #9CA3AF;
  cursor: not-allowed;
}
#bouton-enregistrer:hover { background: #9CA3AF; }
#bouton-enregistrer.bouton-formulaire-pret {
  background: #1B7F4C;
  cursor: pointer;
}
#bouton-enregistrer.bouton-formulaire-pret:hover { background: #15693D; }

/* Bouton kebab (⋮), mobile uniquement — regroupe les 3 actions ci-dessus en
   menu déroulant. Masqué sur PC : .menu-actions-fiche y reste affichée en
   ligne, comme avant. Même mécanique que le menu hamburger du bandeau du
   site (voir assets/entete.js, initialiserMenuMobile()), dupliquée ici
   volontairement plutôt que généralisée : les actions concernées (fiche vs.
   navigation globale) et leur logique d'affichage (etat.inscriptionCourante)
   sont propres à assets/formulaire.js. */
.bouton-kebab-fiche {
  display: none;
  align-items: center; justify-content: center;
  width: 30px; height: 30px;
  padding: 0; /* sans ça, hérite du padding:12px 16px de la règle générique
                 "button" — avec box-sizing:border-box, ce padding dévore la
                 totalité d'une boîte fixée à 30x30px, écrasant l'icône SVG à
                 zéro (cause exacte du "cadre vide, pas d'icône" signalé par
                 Bruno). */
  background: transparent; color: white;
  border: 1px solid rgba(255,255,255,0.35); border-radius: 6px;
}
.bouton-kebab-fiche:hover { background: rgba(255,255,255,0.1); }
.menu-actions-fiche { display: flex; align-items: center; gap: 8px; }
/* Sépare visuellement les boutons de navigation (Nouvel adhérent,
   Réinscrire, Dupliquer) des boutons d'action (Vider, Valider, Supprimer,
   Enregistrer) remontés dans ce même bandeau (09/09/2026, demande de
   Bruno) — trait vertical en PC (ligne), horizontal en mobile (colonne,
   voir @media plus bas). */
.separateur-menu-actions-fiche { width: 1px; align-self: stretch; background: rgba(255,255,255,0.25); margin: 2px 0; }

@media (max-width: 700px) {
  .bouton-kebab-fiche { display: inline-flex; }
  .menu-actions-fiche {
    display: none;
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    min-width: 210px;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    background: var(--couleur-bandeau-app);
    border: 1px solid rgba(255,255,255,0.2);
    border-radius: 8px;
    padding: 6px;
    box-shadow: 0 6px 16px rgba(0,0,0,0.2);
    z-index: 20;
  }
  .menu-actions-fiche.ouvert { display: flex; }
  .menu-actions-fiche .bouton-action-fiche { text-align: left; }
  .separateur-menu-actions-fiche { width: auto; height: 1px; align-self: stretch; margin: 4px 2px; }
}

/* Calculatrice de paiements (Total dû / Montant engagé / Reste à engager /
   Total payé / Reste dû, 09/09/2026) — volontairement discrète, à la
   différence du bandeau flottant */
.recapitulatif-totaux {
  display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px;
  background: var(--couleur-fond); border: 1px solid var(--couleur-bordure);
  border-radius: 6px; padding: 8px 12px; margin-bottom: 12px;
}
.recapitulatif-totaux div { display: flex; flex-direction: column; gap: 0; }
.recapitulatif-totaux span { font-size: 0.66rem; color: var(--couleur-texte-att); text-transform: uppercase; letter-spacing: 0.02em; font-weight: 600; }
.recapitulatif-totaux strong { font-size: 0.82rem; color: var(--couleur-texte); font-weight: 600; font-variant-numeric: tabular-nums; }

@media (max-width: 640px) {
  .recapitulatif-totaux { grid-template-columns: repeat(2, 1fr); }
}

.grille-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 6px; }

/* 25/09/2026, "Réglages de la saison" (Configuration de saison, retour
   de Bruno) : les 2 champs + le bouton Enregistrer sur une seule ligne,
   alignés verticalement au milieu -- à la place de la grille 2 colonnes
   + bouton en dessous utilisée partout ailleurs (.grille-2 ci-dessus).
   margin:0 sur les <label> de cette ligne : neutralise le
   margin:14px 0 6px du sélecteur générique "label" (voir plus bas dans
   ce fichier), qui décale sinon les champs vers le bas et empêche
   l'alignement vertical avec le bouton. */
.ligne-reglages-saison { display: flex; align-items: center; flex-wrap: wrap; gap: 16px; margin-top: 4px; }
.ligne-reglages-saison label { display: flex; flex-direction: column; gap: 4px; margin: 0; }
/* 25/09/2026 (livraison 207, demande de Bruno) : Date de fin (calculée
   automatiquement) affichait un texte visiblement plus grand que Date de
   début -- #saison-date-fin est un input[type=text] (voir plus bas), donc
   couvert par la règle générique 1rem de input[type="text"] en tête de ce
   fichier, alors que #saison-date-debut (input[type=date], comme partout
   ailleurs dans l'appli, ex. Formulaire) n'a jamais eu de font-size dédié
   nulle part et hérite donc du gabarit natif du sélecteur de date du
   navigateur, plus petit.
   26/09/2026 (livraison 208, retour de Bruno -- "tous les champs du bloc
   Réglages dans la même taille de police et la même hauteur de champ") :
   généralisé aux 5 champs de la ligne (au lieu du seul #saison-date-debut
   scopé par id en 207). Date de début (type=date) et Nombre de semaines
   (type=number) ne sont couverts par AUCUNE règle générique de ce fichier
   (celle-ci ne cible que type="text"/"email"/"password"/"search", voir en
   tête de fichier) : sans padding/bordure/police explicites, ils
   gardaient le gabarit natif du navigateur -- visiblement plus bas et
   dans une police différente que Date de fin/Prix adhésion/Tarif horaire
   (type=text, déjà couverts). Cette règle leur donne explicitement le
   même habillage que cette règle générique (police, taille, padding,
   bordure, rayon), pour une hauteur de champ identique sur les 5 -- sans
   toucher aux autres input[type="date"]/[type="number"] de l'appli
   (Formulaire notamment), non concernés par cette demande.
   26/09/2026 (bis) : même police/padding/bordure ne suffisait pas à
   égaliser la HAUTEUR -- Chrome rend nativement input[type="date"]
   ~2px plus haut qu'un input[type="text"] à padding/bordure identiques
   (widget interne du sélecteur de date, en dehors du contrôle CSS
   classique). Hauteur figée explicitement (box-sizing:border-box global,
   voir tête de fichier) pour garantir des champs à hauteur strictement
   identique quel que soit le type. */
.ligne-reglages-saison label input {
  width: 190px;
  height: 42px;
  font-family: var(--police-texte);
  font-size: 1rem;
  padding: 10px 12px;
  border: 1px solid var(--couleur-bordure);
  border-radius: 8px;
  background: var(--couleur-fond);
  color: var(--couleur-texte);
}

/* 25/09/2026 (lot "Créer/Modifier une saison" en bandeau) : réutilise
   cette même ligne pour le bloc à 2 lignes Date de début/Nombre de
   semaines/Date de fin + Prix adhésion/Tarif horaire (voir
   configuration_saison.php) -- 2 nuances visuelles distinctes :
     - #saison-date-fin : TOUJOURS en lecture seule (calculée), même
       gabarit grisé que .table-lignes input[readonly]/fieldset
       input[readonly] ailleurs dans l'appli.
     - #saison-date-debut/#saison-nb-semaines : grisés seulement quand
       verrouillés par des inscriptions déjà enregistrées (voir
       afficherChampsSaison() dans assets/configuration_saison.js) --
       simple opacité, même principe que input.input-mois-professeur:disabled. */
#saison-date-fin[readonly] { background: #EEF0EA; color: var(--couleur-texte-att); cursor: default; }
/* 25/09/2026 (bis, livraison 206, verrouillage généralisé) : Prix de
   l'adhésion et Tarif horaire rejoignent Date de début/Nombre de semaines
   dans ce même grisage -- voir afficherChampsSaison(), même verrou
   désormais partagé par les 4 champs (s.nb_inscriptions > 0). */
#saison-date-debut:disabled, #saison-nb-semaines:disabled,
#saison-prix-adhesion:disabled, #saison-tarif-horaire:disabled { opacity: 0.6; }

/* 02/10/2026 (section 244) : bloc « Bulletin d'inscription » du
   Configurateur -- textes sur toute la largeur du bloc, même gabarit de
   champ que les Réglages ci-dessus (bordure, rayon, police). */
.grille-bulletin-saison { display: flex; flex-direction: column; gap: 12px; margin-top: 4px; }
.grille-bulletin-saison > label { display: flex; flex-direction: column; gap: 4px; margin: 0; }
.grille-bulletin-saison textarea,
.grille-bulletin-saison > label input {
  width: 100%;
  font-family: var(--police-texte);
  font-size: 0.87rem;
  line-height: 1.4;
  padding: 8px 10px;
  border: 1px solid var(--couleur-bordure);
  border-radius: 8px;
  background: var(--couleur-fond);
  color: var(--couleur-texte);
}
.grille-bulletin-saison textarea { resize: vertical; min-height: 44px; }
.grille-bulletin-saison > label input { height: 42px; }
.ligne-reglages-saison label input.champ-bulletin-email { width: 300px; max-width: 100%; }
.grille-bulletin-saison textarea:disabled,
.grille-bulletin-saison input:disabled { opacity: 0.6; }
/* Chaque case à cocher et son bloc de recherche partagent la même
   colonne (09/09/2026, demande de Bruno — restructuration HTML, voir
   formulaire.php) : alignement garanti par construction, plus besoin de
   faire correspondre deux grilles séparées. */
.colonne-paiement .bloc-paye-pour { margin-top: 8px; }
/* Champs regroupés par 3/4 sur une ligne (09/09/2026, demande de Bruno,
   suite à l'élargissement des pages en v144 : moins de défilement, vision
   plus globale de la fiche). Volontairement distinctes de .grille-3
   ci-dessous, qui réserve 2fr à sa première colonne pour Adresse/Ville/CP
   — ici les colonnes sont égales. Repli en une seule colonne sur mobile,
   voir @media (max-width: 780px) plus bas dans ce fichier. */
.grille-3-egale { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 6px; }
.grille-4-egale { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 6px; }
.grille-3 { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 10px; margin-bottom: 6px; }
.grille-3 .col-large { grid-column: span 1; }
fieldset label { font-size: 0.76rem; font-weight: 600; margin: 0 0 3px; display: block; color: var(--couleur-texte-att); }
/* Hauteur et interligne fixés explicitement (31/08/2026, signalé par Bruno) :
   le champ Email paraissait plus haut que Date de naissance (visible surtout
   en mobile, mais déjà vrai en version PC). Cause : chaque navigateur rend le
   "chrome" interne de certains types natifs (date notamment, avec son icône
   de calendrier) avec une hauteur intrinsèque différente d'un champ texte
   classique, même à padding/font-size identiques en CSS. Fixer height +
   line-height explicitement force tous les types de champ à la même boîte,
   quel que soit leur rendu natif. */
fieldset input:not([type="checkbox"]):not([type="radio"]), fieldset select {
  width: 100%;
  height: 34px;
  line-height: 1.2;
  font-family: var(--police-texte);
  padding: 6px 8px;
  border: 1px solid var(--couleur-bordure);
  border-radius: 5px;
  font-size: 0.87rem;
  background: white;
}
/* Cases à cocher/radio : la règle ci-dessus les étirait en grands
   rectangles blancs (width:100%; height:34px), particulièrement visible
   sur la case "Payé" du tableau Paiements — signalé "disproportionnée et
   bleue" par Bruno (31/08/2026). Taille native cohérente à la place,
   couleur de coche alignée sur l'identité visuelle du site
   (--couleur-primaire) plutôt que le bleu système par défaut. */
fieldset input[type="checkbox"],
fieldset input[type="radio"] {
  width: 16px;
  height: 16px;
  accent-color: var(--couleur-primaire);
  flex-shrink: 0;
}
fieldset input[type="checkbox"]:disabled,
fieldset input[type="radio"]:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
/* Pilotée en JS par ajusterTaillePoliceChamp() (assets/entete.js,
   31/08/2026) quand le texte du placeholder ne tiendrait pas dans le champ
   à la taille normale — ex. "Rechercher le référent famille pour cette
   saison…" sur un champ étroit en mobile. Hérite de la taille du champ par
   défaut (inchangé tant que le JS ne fixe rien). */
fieldset input::placeholder,
.champ-recherche-personne input::placeholder {
  font-size: var(--taille-police-placeholder, inherit);
}
.case-a-cocher { display: flex; align-items: center; gap: 7px; font-weight: 600; font-size: 0.84rem; color: var(--couleur-texte); }
.case-a-cocher input { width: auto; }

.champ-recherche-personne { position: relative; margin-bottom: 10px; }
/* Les champs Adresse/Ville/Code postal utilisent la même taille de police
   que les autres champs d'identité (Email, Téléphone, Prénom, Nom...) —
   déjà le cas via la règle générale "fieldset input" ci-dessus, réaffirmé
   ici explicitement à la demande de Bruno (30/08/2026), au cas où un futur
   ajout de style viendrait la faire dévier par erreur. */
#p-adresse, #p-ville, #p-cp { font-size: 0.87rem; }
/* Remarques (09/09/2026, demande de Bruno) : seul <textarea> du
   formulaire — la règle générique "fieldset input:not(...):not(...)"
   plus haut ne cible que <input>, pas <textarea>, d'où ce style dédié. */
.fieldset-remarques textarea {
  width: 100%;
  min-height: 60px;
  resize: vertical;
  font-family: var(--police-texte);
  font-size: 0.87rem;
  line-height: 1.35;
  padding: 8px;
  border: 1px solid var(--couleur-bordure);
  border-radius: 5px;
  background: white;
}
.liste-suggestions {
  list-style: none; margin: 4px 0 0; padding: 4px;
  position: absolute; z-index: 10; left: 0; right: 0;
  background: var(--couleur-surface); border: 1px solid var(--couleur-bordure);
  border-radius: 6px; box-shadow: var(--ombre); max-height: 220px; overflow: auto;
}
.liste-suggestions li { padding: 7px 9px; border-radius: 5px; cursor: pointer; font-size: 0.85rem; }
.liste-suggestions li:hover { background: var(--couleur-fond); }

/* 24/09/2026 : suggestions "Autres prestations" du Formulaire (voir
   creerSuggestionsAutresPrestations() dans assets/formulaire.js) -- même
   habillage visuel que .liste-suggestions ci-dessus, mais en position:fixed
   et insérée directement dans <body> plutôt que dans la cellule du
   tableau : le tableau "Autres prestations" défile horizontalement
   (.table-scroll), une liste positionnée à l'intérieur d'une cellule y
   aurait été tronquée verticalement par ce défilement. */
.suggestions-autres-prestations {
  list-style: none; margin: 0; padding: 4px;
  position: fixed; z-index: 30;
  background: var(--couleur-surface); border: 1px solid var(--couleur-bordure);
  border-radius: 6px; box-shadow: var(--ombre); max-height: 220px; overflow: auto;
}
.suggestions-autres-prestations li { padding: 7px 9px; border-radius: 5px; cursor: pointer; font-size: 0.85rem; }
.suggestions-autres-prestations li:hover { background: var(--couleur-fond); }

/* Champ à valeur figée (référent famille, responsable) : même gabarit qu'un
   champ de saisie normal, mais en lecture seule avec une croix pour retirer. */
.champ-valeur-figee {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  height: 34px; box-sizing: border-box;
  padding: 6px 8px; margin-top: 3px;
  background: #EEF0EA; border: 1px solid var(--couleur-bordure); border-radius: 5px;
  font-size: 0.87rem; color: var(--couleur-texte);
}

/* Croix-bouton unifiée pour tous les éléments supprimables (lignes de
   tableau, champs à valeur figée) : même forme, alignée avec son champ. */
.bouton-croix {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; flex-shrink: 0;
  background: white; border: 1px solid var(--couleur-bordure); border-radius: 5px;
  color: var(--couleur-erreur); cursor: pointer; font-size: 0.85rem; line-height: 1; padding: 0;
}
.bouton-croix:hover { background: var(--couleur-erreur-fond); border-color: rgba(179,38,30,0.3); }
/* 25/09/2026 (livraison 206, verrouillage généralisé) : case de suppression
   grisée quand la ligne est déjà utilisée par une inscription (voir
   bouton-supprimer-discipline dans assets/configuration_saison.js). */
.bouton-croix:disabled { opacity: 0.4; cursor: not-allowed; }
.bouton-croix:disabled:hover { background: white; border-color: var(--couleur-bordure); }

/* Bouton "Dupliquer" par ligne (25/09/2026, table Disciplines et tarifs --
   demande de Bruno). Même forme/gabarit que .bouton-croix (carré 22x22px,
   place juste avant), mais coloration neutre (gris, --couleur-accent) au
   lieu du rouge d'erreur -- ce n'est pas une action destructive. */
.bouton-dupliquer-ligne {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; flex-shrink: 0;
  background: white; border: 1px solid var(--couleur-bordure); border-radius: 5px;
  color: var(--couleur-accent); cursor: pointer; font-size: 0.85rem; line-height: 1; padding: 0;
}
.bouton-dupliquer-ligne:hover { background: var(--couleur-fond); border-color: var(--couleur-accent-clair); }
.cellule-actions-ligne { display: flex; gap: 6px; justify-content: center; }

/* Champ date + bouton d'effacement (05/09/2026) : sur mobile, il est
   difficile voire impossible de vider un champ <input type="date"> déjà
   rempli via le clavier/sélecteur natif — un petit bouton dédié à côté
   règle ça simplement, sans alourdir le champ lui-même. */
.groupe-date { display: flex; align-items: center; gap: 6px; }
.groupe-date input[type="date"] { flex: 1; min-width: 0; }

/* width:100% seul ne suffit pas à déclencher le défilement horizontal de
   .table-scroll (overflow:auto) sur petit écran : sans butée basse, le
   navigateur écrase les colonnes jusqu'à l'illisibilité plutôt que de
   forcer le scroll — c'est ce qui rendait Disciplines/Paiements invisibles
   en pratique sur mobile (signalé par Bruno, 31/08/2026). min-width par
   tableau (nombre de colonnes différent selon le tableau) résout ça : au
   lieu de s'écraser, le tableau garde une largeur lisible et le conteneur
   scrolle horizontalement. */
.table-lignes { width: 100%; border-collapse: collapse; font-size: 0.82rem; }
#table-prestations { min-width: 420px; }
#table-paiements { min-width: 440px; }
.table-lignes th { text-align: left; padding: 5px 6px; background: #EEF0EA; border-bottom: 1px solid var(--couleur-bordure); font-weight: 700; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.02em; color: var(--couleur-texte-att); }
.table-lignes tbody tr:nth-child(even) { background: #FAFBF8; }
.table-lignes tbody tr:focus-within { background: rgba(22, 66, 60, 0.06); }
.table-lignes td { padding: 4px 6px; border-bottom: 1px solid var(--couleur-bordure); text-align: center; }

/* Ligne d'ajout en pied de tableau (25/09/2026, refonte Configuration de
   saison en tableaux demandée par Bruno) : remplace le mini-formulaire
   séparé qui suivait chaque tableau -- réutilisée par les 4 tableaux de
   configuration_saison.php (Modes de paiement, Durées et coefficients,
   Disciplines et tarifs, Autres prestations). Fond légèrement teinté +
   bordure du haut plus marquée pour la distinguer visuellement des lignes
   de données, sans dépendre de :nth-child (qui alterne déjà pour le
   zébrage ci-dessus et ne doit pas être perturbé). */
.table-lignes tr.ligne-ajout-table { background: #F3F0E4; }
.table-lignes tr.ligne-ajout-table:nth-child(even) { background: #F3F0E4; }
.table-lignes tr.ligne-ajout-table td { border-top: 2px solid var(--couleur-bordure); }
.table-lignes tr.ligne-ajout-table input::placeholder { color: var(--couleur-texte-att); }

/* 25/09/2026 (ter) : largeur ajustée au contenu + alignement à droite pour
   Modes de paiement / Autres prestations (retour de Bruno après la
   livraison 199 relookée en tableaux) -- avec peu de colonnes, ces
   tableaux paraissaient disproportionnés en s'étirant sur toute la
   largeur de la page comme #table-disciplines-config (matriciel, beaucoup
   de colonnes) ou les tableaux Cours/Prestations/Paiements du Formulaire
   (plus riches). Écrasent le width:100% hérité de la classe partagée
   .table-lignes par un gabarit ajusté au contenu (width:auto + max-width),
   en gardant une réserve généreuse sur la colonne "libellé" (texte
   potentiellement long, ex. "Prélèvement automatique") plutôt qu'un simple
   pourcentage de la page. Uniquement en affichage PC : en dessous de
   700px, la bascule en mode "carte" (voir media query plus bas,
   .table-lignes { display:block }) reprend le dessus et ignore ces
   largeurs de colonnes, donc rien à adapter côté mobile.
   Alignement à droite des en-têtes et des valeurs (demande de Bruno,
   "justifier le nom des colonnes et les valeurs à droite"), petite marge
   unifiée -- à l'exception de la dernière colonne (case à cocher "Actif"
   ou bouton de suppression selon le tableau), purement interactive et donc
   laissée centrée : un interrupteur ou une icône n'a pas de sens "aligné à
   droite".
   25/09/2026 (quinquies, livraison 206, demande de Bruno) : Durées et
   coefficients SORT de ce groupe -- "reprendre la même mise en forme du
   tableau que celui du bloc Disciplines et tarifs" -- et rejoint au
   contraire #table-disciplines-config plus bas (gabarit pleine largeur,
   .table-scroll encapsulant, alignement par défaut de .table-lignes,
   ligne d'en-tête à la même couleur). Remplace l'alignement à droite +
   largeur ajustée qu'elle avait depuis la livraison 201 -- décision
   explicitement révisée par Bruno pour cette seule table (Modes de
   paiement et Autres prestations gardent leur formatage d'origine,
   inchangé). Voir aussi la balise <div class="table-scroll"> ajoutée
   autour de #table-durees dans configuration_saison.php. */
#liste-modes-paiement { width: auto; max-width: 460px; }
/* Autres prestations (25/09/2026, demande de Bruno) : colonne Libellé
   élargie x1,5 (240px -> 360px, voir min-width plus bas) -- la largeur
   max du tableau suit dans la même proportion (460px -> 690px) pour que
   la colonne Tarif garde une place comparable à avant, plutôt que de se
   faire écraser par l'élargissement de Libellé. */
#table-autres-prestations { width: auto; max-width: 690px; }

/* Modes de paiement est encapsulé dans .table-scroll (bordure +
   defilement horizontal) -- sans cette contrainte sur le conteneur
   lui-meme, sa bordure resterait etiree sur toute la largeur de la page
   meme apres avoir reduit la largeur du tableau ci-dessus. Autres
   prestations n'a pas ce conteneur, rien a faire pour elle. Durees a
   aussi SON PROPRE conteneur .table-scroll (comme Disciplines et
   tarifs), voir plus bas -- bordure/fond blanc/en-tête foncé/alignement
   par défaut acquis en livraison 206 CONSERVÉS.
   25/09/2026 (livraison 207, retour de Bruno) : .table-scroll-etroit
   réappliquée en PLUS sur le conteneur de Durées -- la livraison 206
   avait sorti #table-durees de ce fichier UNIQUEMENT pour sa largeur
   (voir plus haut, "Durées et coefficients SORT de ce groupe"), mais
   sans elle le tableau (2 colonnes utiles seulement) s'étirait sur toute
   la largeur de la page, ce que Bruno n'avait pas demandé -- restitue
   exactement la largeur qu'avait #table-durees avant la livraison 206
   (460px, comme Modes de paiement), sans rien changer au reste
   (bordure/fond/en-tête/alignement restent ceux de la livraison 206). */
.table-scroll-etroit { max-width: 460px; }

#liste-modes-paiement th,
#liste-modes-paiement td,
#table-autres-prestations th,
#table-autres-prestations td { text-align: right; padding-right: 12px; }

#liste-modes-paiement th:last-child,
#liste-modes-paiement td:last-child,
#table-autres-prestations th:last-child,
#table-autres-prestations td:last-child { text-align: center; padding-right: 6px; width: 1%; white-space: nowrap; }

#liste-modes-paiement td:not(:last-child) input,
#table-autres-prestations td:not(:last-child) input { text-align: right; }

#liste-modes-paiement th:first-child,
#liste-modes-paiement td:first-child { min-width: 240px; }

/* Autres prestations (25/09/2026) : colonne Libellé élargie x1,5 par
   rapport aux 240px partagés par Modes de paiement -- voir la note sur
   #table-autres-prestations plus haut. */
#table-autres-prestations th:first-child,
#table-autres-prestations td:first-child { min-width: 360px; }

/* 25/09/2026 (livraison 206, demande de Bruno, "foncer un peu la couleur
   de fond de la ligne de titre") : ligne d'en-tête (<thead>) légèrement
   plus foncée que le fond partagé par .table-lignes th (#EEF0EA, identique
   au fond du bloc -- devenu la référence commune à Disciplines et tarifs
   ET, depuis cette livraison, Durées et coefficients qui en reprend le
   même habillage). Scopé à ces 2 tables plutôt qu'à .table-lignes th en
   général, pour ne pas modifier l'apparence des tableaux des autres pages
   (Formulaire, Paye Professeurs...) qui réutilisent la même classe. */
#table-disciplines-config th,
#table-durees th { background: #E2E6DC; }

/* Bloc COURS non responsive (10/09/2026, signalé par Bruno après le
   calibrage définitif des largeurs de colonnes ci-dessous) : cause
   distincte de tout ce qui a été touché jusqu'ici — <fieldset> a, dans la
   feuille de style par défaut de tous les navigateurs, un min-width
   implicite égal au contenu le plus large qu'il contient ("min-content"),
   contrairement à une <div> classique dont le min-width par défaut vaut 0
   dans ce contexte. Ce comportement ignore totalement l'overflow:auto posé
   sur .table-scroll : au lieu de laisser le tableau défiler horizontalement
   dans son propre cadre sous 1096px de large, c'est le <fieldset> entier
   (et donc .corps-formulaire / .panneau-formulaire / .contenu-formulaire /
   toute la page) qui était poussé à s'élargir pour ne jamais descendre sous
   1096px. Les fieldsets Prestations/Paiements ne montraient pas le
   problème : leur contenu le plus large (tableaux à 420-440px, voir
   #table-prestations/#table-paiements plus haut) reste sous le seuil de
   rupture en pratique aux largeurs d'écran testées, alors que le tableau
   Cours (1096px) le dépasse largement. #fieldset-cours { min-width: 0; }
   neutralise ce min-width implicite du navigateur sans toucher aux
   largeurs de colonnes ni au seuil de défilement horizontal (inchangés
   ci-dessous), qui redeviennent ainsi pleinement responsives : le tableau
   défile dans .table-scroll entre 700px (bascule en cartes) et ~1096px de
   large utile, puis s'affiche pleine largeur au-delà, exactement comme les
   autres blocs du formulaire. */
#fieldset-cours { min-width: 0; }

/* Bloc COURS (09/09/2026, demande de Bruno — 3e essai, les deux
   précédents avec table-layout:auto + width:1%/max-width laissaient
   encore les valeurs de Tarif/Réduc/Total tronquées en pratique, pas
   seulement "un peu larges") : table-layout:fixed avec une largeur
   explicite par colonne, fixée UNE FOIS sur les <th> (le navigateur lit
   la largeur des cellules de la première ligne dès que table-layout:fixed
   est actif) — méthode déterministe, ne dépend plus d'un calcul
   automatique du navigateur qui peut mal évaluer le contenu réel. Cours/
   Professeur nettement élargis (utile pour des noms comme "Atelier Play
   Adultes"), Tarif/Réduc/Total dimensionnés pour "9 999,99 €" au
   maximum réaliste, jamais plus.
   09/09/2026, réajustement précis d'après capture d'écran de Bruno :
   Début/Fin restaient tronqués (la date + le bouton ✕ effacer-date
   ont besoin de plus de place que prévu), alors que Tarif/Réduc/Total
   avaient encore de la marge inutilisée — largeur reprise à ces
   derniers et redonnée à Début/Fin, sans changer la largeur totale.
   Somme des largeurs = 1096px, d'où le min-width ci-dessous (sert de
   seuil de bascule vers le défilement horizontal sur écran étroit, voir
   .table-scroll). */
/* 28/09/2026 (SYNTHESE section 235) : 11e colonne "Séances" (56px) entre
   Fin et Tarif ; place prise sur Cours/Professeur (170 -> 160) et Groupe
   (110 -> 104). Somme des largeurs = 1126px ; bascule en cartes relevée
   de 1200 à 1230px en conséquence (même marge qu'avant). */
#table-disciplines { table-layout: fixed; min-width: 1126px; }
#table-disciplines th:nth-child(1), #table-disciplines td:nth-child(1) { width: 160px; }
#table-disciplines th:nth-child(2), #table-disciplines td:nth-child(2) { width: 104px; }
#table-disciplines th:nth-child(3), #table-disciplines td:nth-child(3) { width: 70px; }
#table-disciplines th:nth-child(4), #table-disciplines td:nth-child(4) { width: 160px; }
#table-disciplines th:nth-child(5), #table-disciplines td:nth-child(5) { width: 142px; white-space: nowrap; }
#table-disciplines th:nth-child(6), #table-disciplines td:nth-child(6) { width: 142px; white-space: nowrap; }
#table-disciplines th:nth-child(7), #table-disciplines td:nth-child(7) { width: 56px; white-space: nowrap; }
#table-disciplines th:nth-child(8), #table-disciplines td:nth-child(8) { width: 88px; white-space: nowrap; }
#table-disciplines th:nth-child(9), #table-disciplines td:nth-child(9) { width: 82px; white-space: nowrap; }
#table-disciplines th:nth-child(10), #table-disciplines td:nth-child(10) { width: 88px; white-space: nowrap; }
#table-disciplines th:nth-child(11), #table-disciplines td:nth-child(11) { width: 34px; }
#table-disciplines .d-seances { text-align: center; -moz-appearance: textfield; }
#table-disciplines .d-seances::-webkit-inner-spin-button,
#table-disciplines .d-seances::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
/* Bascule anticipée en cartes pour le bloc COURS spécifiquement
   (10/09/2026, demande de Bruno : un vrai retour à la ligne plutôt
   qu'un défilement horizontal — la scrollbar ajoutée juste avant ne
   suffisait pas, restée invisible ou peu perceptible dans la pratique
   sur son poste). Contrairement à Prestations (420px)/Paiements
   (440px), qui tiennent confortablement jusqu'au seuil habituel de
   700px et gardent donc leur bascule commune plus bas dans ce fichier,
   le tableau Cours a besoin de 1096px de large utile (10 colonnes
   calibrées en v154). Mesure précise (Playwright, navigateur réel) :
   le tableau cesse de déborder à partir de 1186px de fenêtre — 1200px
   choisi comme seuil avec une petite marge de sécurité. Duplique les
   règles génériques ".table-lignes -> cartes" plus bas dans ce
   fichier, mais SCOPÉES au seul #table-disciplines, pour ne rien
   changer au comportement de Prestations/Paiements. */
@media (max-width: 1230px) {
  #table-disciplines { min-width: 0; table-layout: auto; }
  #table-disciplines th, #table-disciplines td { width: auto; white-space: normal; }

  #table-disciplines thead { display: none; }
  #table-disciplines, #table-disciplines tbody, #table-disciplines tr { display: block; width: 100%; }
  #table-disciplines tr {
    border: 1px solid var(--couleur-bordure);
    border-radius: 8px;
    padding: 8px 10px;
    margin-bottom: 8px;
    background: var(--couleur-surface);
  }
  #table-disciplines tr:last-child { margin-bottom: 0; }
  #table-disciplines td {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    padding: 5px 0;
    border: none;
  }
  #table-disciplines td[data-label]::before {
    content: attr(data-label);
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    color: var(--couleur-texte-att);
  }
  #table-disciplines td select,
  #table-disciplines td input:not([type="checkbox"]) {
    width: 100%;
  }
  #table-disciplines td .groupe-date { width: 100%; }
  #table-disciplines td:last-child {
    flex-direction: row;
    justify-content: flex-end;
    padding-top: 8px;
    margin-top: 4px;
    border-top: 1px solid var(--couleur-bordure);
  }
}

.table-lignes input, .table-lignes select { padding: 4px 5px; font-size: 0.81rem; border: 1px solid var(--couleur-bordure); border-radius: 4px; width: 100%; background: white; }
.table-lignes input[readonly] {
  background: #EEF0EA; color: var(--couleur-texte-att); font-variant-numeric: tabular-nums;
  text-align: right; cursor: default;
}
/* 25/09/2026 (livraison 206, verrouillage généralisé, demande de Bruno) :
   grisage des champs déjà utilisés par une inscription (nom/seuil/profs
   rémunérés/tarifs de Disciplines et tarifs, Coefficient de Durées --
   voir chargerDisciplines()/chargerDurees() dans
   assets/configuration_saison.js). Distinct de .table-lignes
   input[readonly] ci-dessus (qui force l'alignement à droite, pensé pour
   des valeurs numériques calculées) : ces champs restent alignés comme
   n'importe quel champ actif de leur table (texte à gauche pour un nom,
   par exemple), seule l'opacité et le curseur signalent le verrouillage.
   Scopé à ces 2 tables précisément (pas .table-lignes input:disabled en
   général) : la classe .table-lignes est partagée avec d'autres tableaux
   de l'appli (Formulaire...) qui ont leurs propres champs `disabled` avec
   un tout autre sens (ex. case "Payée" -- inutile, et risqué, d'en changer
   l'apparence ici). */
#table-disciplines-config input:disabled,
#table-durees input:disabled {
  background: #EEF0EA; color: var(--couleur-texte-att); cursor: not-allowed; opacity: 0.75;
}
.table-lignes input:focus-visible, .table-lignes select:focus-visible {
  outline: none; border-color: var(--couleur-primaire-clair); box-shadow: 0 0 0 2px rgba(22, 66, 60, 0.15);
}

.boutons-ligne { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }

.total-ligne {
  font-size: 0.85rem; color: var(--couleur-texte-att); margin: 8px 0;
}
.total-ligne strong { color: var(--couleur-texte); font-variant-numeric: tabular-nums; }
.total-ligne-droite { text-align: right; }

.aide-champ { font-size: 0.78rem; color: var(--couleur-texte-att); margin: 4px 0 10px; font-style: italic; }

/* Icônes DANS les champs de contact (email, téléphones, adresse) — même
   principe visuel que l'icône native du sélecteur de date d'un
   <input type="date"> : discrète, à l'intérieur du champ, et non un bouton
   séparé à côté. Ouvrent l'appli mail/téléphone/carte du système — utile
   dès maintenant sur ordinateur, et pensé pour un usage futur sur
   smartphone. Mises à jour en direct pendant la saisie par
   actualiserLiensContact() dans adherents.js. */
.champ-avec-action { position: relative; }
.champ-avec-action input { padding-right: 32px; }
.lien-action-champ {
  position: absolute; top: 50%; right: 6px; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 4px;
  text-decoration: none; line-height: 1;
  color: var(--couleur-texte-att); /* gris, homogène pour email/téléphone/adresse — les icônes sont
                                        des SVG (fill="currentColor"), pas des emojis qui ignoreraient cette couleur */
}
.lien-action-champ:hover { background: var(--couleur-fond); color: var(--couleur-primaire); }
.lien-action-champ[aria-disabled="true"] { opacity: 0.35; pointer-events: none; }
/* Icône d'adresse (pin) : légèrement plus grosse, façon repère de carte (Google Maps). */
.lien-action-champ-pin { width: 26px; height: 26px; }

/* Champs moins prioritaires que l'identité de l'élève (ex. nom/prénom/lien
   de parenté du responsable) : taille réduite pour marquer la hiérarchie. */
.champ-secondaire label { font-size: 0.7rem; }
.champ-secondaire input { font-size: 0.8rem; padding: 5px 7px; }

/* Liste extensible de responsables (familles recomposées, 30/08/2026) —
   même mécanisme que les lignes Disciplines/Autres prestations (+/✕) :
   chaque responsable tient sur une seule ligne compacte (30/08/2026), avec
   une recherche de personne existante affichée UNIQUEMENT juste après
   l'ajout d'une ligne (aide ponctuelle, disparaît ensuite — voir
   ajouterLigneResponsable() dans adherents.js). */
#liste-responsables { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.carte-responsable {
  border: 1px solid var(--couleur-bordure); border-radius: 6px;
  padding: 8px 10px; background: var(--couleur-fond);
}
.carte-responsable .champ-recherche-personne { margin: 0 0 8px; }

/* Tableau de bord (07/09/2026) : grille de cartes-liens vers les
   fonctionnalités accessibles, colonnes auto-adaptatives (une seule sur
   mobile, plusieurs sur PC selon la largeur disponible). Centrée dans la
   page (09/09/2026, demande de Bruno) — auto-fill+1fr étirait les cartes
   sur toute la largeur de .contenu-app (1600px depuis la v144), les
   rendant démesurément larges quand il n'y en a que 2 ou 3 ; minmax plafonné
   (220-280px) + justify-content:center regroupe les cartes à leur taille
   naturelle, centrées, plutôt que de les étirer bord à bord. */
.grille-tableau-bord {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 280px));
  justify-content: center;
  gap: 14px;
}
.carte-tableau-bord {
  border: 1px solid var(--couleur-bordure);
  border-radius: 8px;
  padding: 16px;
  background: var(--couleur-fond);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.carte-tableau-bord h3 { margin: 0; font-family: var(--police-affichage); color: var(--couleur-primaire); }
.carte-tableau-bord p { margin: 0; font-size: 0.85rem; color: var(--couleur-texte-att); flex: 1; }
.carte-tableau-bord .bouton-principal { align-self: flex-start; }

/* Icônes de contact d'un professeur affecté (07/09/2026, page d'accueil). */
.icone-contact { text-decoration: none; margin-left: 2px; }
.ligne-responsable { display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap; }
.ligne-responsable > div { flex: 1 1 120px; min-width: 0; }
.ligne-responsable .bouton-croix { margin-bottom: 1px; } /* aligné avec le bas des champs, sans label au-dessus */

.valeur-selectionnee {
  font-size: 0.82rem; color: var(--couleur-primaire-clair); font-weight: 600;
  margin: 4px 0 10px; display: flex; align-items: center; gap: 8px;
}

/* Champs calculés en lecture seule dans les fieldsets (ex. Prix de
   l'adhésion) : même gabarit que les autres champs, juste grisés. */
fieldset input[readonly] {
  background: #EEF0EA; color: var(--couleur-texte-att); cursor: default;
  font-size: 0.87rem; font-family: var(--police-texte); padding: 6px 8px;
}

/* Case à cocher grisée/verrouillée (ex. Référent famille quand un référent est désigné) */
.case-a-cocher.desactivee { opacity: 0.5; cursor: not-allowed; }
.case-a-cocher.desactivee input { cursor: not-allowed; }

.bouton-principal { background: var(--couleur-primaire); color: white; border: none; border-radius: 6px; padding: 8px 15px; font-weight: 600; font-size: 0.85rem; cursor: pointer; }
.bouton-principal:hover { background: var(--couleur-primaire-clair); }
/* Bouton "Enregistrer" grisé quand la fiche est déjà enregistrée et
   sans modification depuis (20/09/2026, demande de Bruno). */
.bouton-principal:disabled { opacity: 0.45; cursor: not-allowed; background: var(--couleur-primaire); }
.bouton-principal:disabled:hover { background: var(--couleur-primaire); }
/* Bouton "Enregistrer" grisé quand la fiche est déjà enregistrée et
   sans modification depuis (20/09/2026, demande de Bruno) — classe
   plutôt que l'attribut natif disabled (21/09/2026, correctif) : les
   navigateurs ne déclenchent pas les événements de survol sur un
   élément réellement désactivé, ce qui empêchait l'infobulle "dernier
   enregistrement par..." de s'afficher. */
.bouton-principal.bouton-non-modifie { opacity: 0.45; cursor: not-allowed; background: var(--couleur-primaire); }
.bouton-principal.bouton-non-modifie:hover { background: var(--couleur-primaire); }
/* 25/09/2026 (livraison 207, demande de Bruno, "le bouton Modifié devient
   Enregistrer") : Configuration de saison reprend les mêmes tons verts que
   #bouton-enregistrer sur Formulaire pour son bouton "Enregistrer" (état
   "Modifier" du bandeau, #bouton-creer-modifier-saison) -- vert dès qu'une
   modification est en attente sur les champs de Réglages, gris (via
   .bouton-non-modifie ci-dessus, déjà partagé) sinon. Scopé par id, pour
   ne pas repeindre les autres boutons .bouton-principal de l'application.
   Voir actualiserEtatBoutonCreerModifier()/signatureReglagesSaison() dans
   assets/configuration_saison.js -- ne s'applique jamais en mode brouillon
   ("Créer la saison" garde le fond .bouton-principal par défaut, cette
   action restant toujours pleinement actionnable). */
#bouton-creer-modifier-saison.bouton-reglages-modifiees { background: #1B7F4C; }
#bouton-creer-modifier-saison.bouton-reglages-modifiees:hover { background: #15693D; }
.bouton-secondaire { background: white; border: 1px solid var(--couleur-bordure); border-radius: 6px; padding: 6px 11px; font-size: 0.8rem; font-weight: 600; cursor: pointer; color: var(--couleur-texte); }
.bouton-secondaire:hover { background: var(--couleur-fond); border-color: var(--couleur-primaire-clair); }
.bouton-secondaire:disabled { opacity: 0.45; cursor: not-allowed; background: var(--couleur-fond); border-color: var(--couleur-bordure); }
.bouton-secondaire:disabled:hover { background: var(--couleur-fond); border-color: var(--couleur-bordure); }
/* Bouton "Facturation" grisé tant que la fiche n'est pas enregistrée
   (20/09/2026, demande de Bruno) — classe plutôt que l'attribut natif
   disabled (21/09/2026, même correctif qu'Enregistrer, section 150) :
   les navigateurs ne déclenchent pas les événements de survol sur un
   élément réellement désactivé, ce qui empêchait l'infobulle de
   s'afficher. */
.bouton-secondaire.bouton-non-enregistre { opacity: 0.45; cursor: not-allowed; background: var(--couleur-fond); border-color: var(--couleur-bordure); }
.bouton-secondaire.bouton-non-enregistre:hover { background: var(--couleur-fond); border-color: var(--couleur-bordure); }
/* 09/09/2026 (bug repéré par Bruno : "Nouvel adhérent"/"Dupliquer"/"Vider
   le formulaire"... n'étaient pas à la même taille qu'Enregistrer/
   Supprimer) — même cause que le correctif déjà fait pour .bouton-
   principal/.bouton-danger : cette règle .bouton-secondaire, plus bas
   dans le fichier que .bouton-action-fiche, l'emportait à spécificité
   égale. Sélecteur composé pour que la taille compacte gagne enfin ici
   aussi + fond gris clair (demande de Bruno), pour distinguer ces
   boutons de navigation d'Enregistrer (vert)/Supprimer (rouge). */
.bouton-secondaire.bouton-action-fiche {
  padding: 5px 10px;
  font-size: 0.76rem;
  background: #E5E7EB;
}
.bouton-secondaire.bouton-action-fiche:hover { background: #D5D8DC; }
/* « 📄 Générer le bulletin » (Configurateur, 01/10/2026, section 243) :
   lien présenté comme les autres boutons du bandeau. */
a.bouton-action-fiche { text-decoration: none; display: inline-block; color: var(--couleur-texte); }
/* "Ajouter"/"Dupliquer un paiement" marqués comme action encore
   nécessaire tant que le reste à engager n'est pas nul (09/09/2026,
   demande de Bruno) — ton ambre plutôt que la couleur "erreur" (rouge) du
   reste de l'appli : ce n'est pas une erreur, juste une action restante. */
.bouton-secondaire.action-requise {
  border-color: #B8860B;
  color: #8A6200;
  background: #FDF6E3;
}
.bouton-secondaire.action-requise:hover { background: #FBF0CE; }

/* État visuel accepté/refusé (06/09/2026) : le bouton correspondant à la
   réponse déjà donnée reste identifiable en couleur pleine — l'autre reste
   neutre, cliquable pour changer d'avis. */
.bouton-reponse-acceptee { background: #2E7D4F; border-color: #2E7D4F; color: white; }
.bouton-reponse-acceptee:hover { background: #256640; border-color: #256640; }
.bouton-reponse-refusee { background: var(--couleur-erreur); border-color: var(--couleur-erreur); color: white; }
.bouton-reponse-refusee:hover { background: #96201a; border-color: #96201a; }
.bouton-texte { background: transparent; border: none; color: var(--couleur-texte-att); font-size: 0.82rem; cursor: pointer; text-decoration: underline; }
.bouton-danger { background: var(--couleur-erreur-fond); color: var(--couleur-erreur); border: 1px solid rgba(179,38,30,0.25); border-radius: 6px; padding: 7px 13px; font-weight: 600; font-size: 0.82rem; cursor: pointer; }
.bouton-danger:hover:not(:disabled) { background: #f6d8d6; }
/* 23/09/2026, correctif (signalé par Bruno sur la suppression de saison) :
   .bouton-danger n'avait jamais d'état "désactivé" visuel -- le survol et
   le curseur restaient ceux d'un bouton actif même avec l'attribut HTML
   disabled posé (qui bloque bien le clic, mais ne se voyait pas), prêtant
   à confusion. Règle générique, bénéficie à tous les .bouton-danger de
   l'appli (Supprimer une fiche, une discipline, une saison...). */
.bouton-danger:disabled { opacity: 0.5; cursor: not-allowed; }

.barre-actions-formulaire { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }

/* Bloc "Fiches payées par cet adhérent" (paiements multiples) */
.bloc-paye-pour { margin-bottom: 14px; }
.bloc-paye-pour > label { font-size: 0.76rem; font-weight: 600; color: var(--couleur-texte-att); display: block; margin-bottom: 6px; }
.liste-payees { list-style: none; margin: 0 0 8px; padding: 0; display: flex; flex-direction: column; gap: 5px; }
.liste-payees li {
  display: flex; align-items: center; justify-content: space-between;
  background: white; border: 1px solid var(--couleur-bordure); border-radius: 6px;
  padding: 6px 10px; font-size: 0.85rem;
}

/* Message "payé par" et désactivation du bloc Paiements */
.message-paye-par {
  background: rgba(22, 66, 60, 0.06); border: 1px solid rgba(22, 66, 60, 0.15);
  border-radius: 6px; padding: 10px 12px; font-size: 0.85rem; margin: 0 0 10px;
}
.lien-fiche {
  background: none; border: none; padding: 0; color: var(--couleur-primaire);
  font-weight: 700; text-decoration: underline; cursor: pointer; font-size: inherit;
}
#contenu-paiements.desactive { opacity: 0.45; pointer-events: none; }

/* Verrouillage collaboratif (30/08/2026) : empêche deux opérateurs de
   modifier la même inscription en même temps — voir chargerFiche() et
   api/verrous.php. Trois variantes : bloqué (rouge, quelqu'un d'autre édite
   déjà), libéré (vert, l'opérateur en attente peut recharger), repris en
   cours d'édition (orange, cas rare où le verrou a expiré et a été repris
   pendant qu'on modifiait encore la fiche). */
.bandeau-verrou {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap;
  gap: 10px; padding: 12px 14px; border-radius: 8px; margin: 0 0 16px; font-size: 0.88rem;
}
.bandeau-verrou-bloque {
  background: var(--couleur-erreur-fond); border: 1px solid rgba(179,38,30,0.25); color: var(--couleur-erreur);
}
.bandeau-verrou-libre {
  background: rgba(22, 66, 60, 0.08); border: 1px solid rgba(22, 66, 60, 0.2); color: var(--couleur-primaire);
}
.bandeau-verrou-perdu { background: #FDF6E3; border: 1px solid #E9CE8A; color: #6B4A00; }
.bandeau-verrou .bouton-secondaire { flex-shrink: 0; }

/* Bloc FONCTIONS (04/09/2026) : cases à cocher cumulables, en grille pour
   ne pas s'étirer sur toute la largeur en PC — s'empile naturellement sur
   mobile grâce à minmax(). */
.grille-fonctions {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 8px 16px;
}


/* ---------------------------------------------------------------------
   Mobile (31/08/2026, suite) : cadres réduits, titre de page collé au
   bandeau du site — voir SYNTHESE section 9. Regroupé ici, en toute fin de
   fichier, PARCE QUE ces règles surchargent .contenu-formulaire/
   .contenu-liste-adherents/.panneau-formulaire/.panneau-liste/
   .entete-formulaire/.entete-liste/.bandeau-fiche, qui doivent donc être
   déjà définies plus haut dans le fichier pour que cette surcharge
   s'applique — une règle sans condition de media placée APRÈS un @media
   reprend le dessus à spécificité égale, même quand la condition du
   @media est vraie (piège identique à celui de .libelle-court, cause du
   même bug une deuxième fois dans cette même livraison v73).
   --------------------------------------------------------------------- */
@media (max-width: 700px) {
  /* 29/09/2026 (section 236) : pas d'écart entre bandeau du site et titre
     de page sur téléphone (titre collé au bandeau, comme avant). */
  :root { --ecart-bandeaux: 0px; }
  .entete-liste::before, .bandeau-fiche::before { display: none; }
  .contenu-formulaire, .contenu-liste-adherents {
    margin-top: 0;
    padding-left: 0;
    padding-right: 0;
  }
  .panneau-formulaire, .panneau-liste {
    border-left: none;
    border-right: none;
    border-top: none;
    border-radius: 0;
  }
  .bandeau-fiche, .entete-formulaire, .entete-liste {
    border-radius: 0;
  }

  /* Adresse/Ville/CP (31/08/2026) : sur PC, .grille-3 met les trois champs
     sur une ligne (2fr/1fr/1fr) — sur mobile, Adresse prend toute la
     largeur en première ligne, Ville et CP passent en dessous, CP étant
     nettement plus étroit (juste assez pour 5 chiffres) que Ville. */
  .grille-3 {
    grid-template-columns: 1fr 76px;
    grid-template-rows: auto auto;
  }
  .grille-3 > div:first-child { grid-column: 1 / -1; }

  /* .grille-3-egale/.grille-4-egale (09/09/2026) : une seule colonne sur
     mobile, la place manque pour 3-4 champs sur une ligne. */
  .grille-3-egale, .grille-4-egale {
    grid-template-columns: 1fr;
  }

  /* ---------------------------------------------------------------------
     Tableaux Disciplines/Prestations/Paiements -> cartes empilées
     (31/08/2026, sur demande de Bruno : le défilement horizontal, même
     fonctionnel, restait peu confortable sur mobile — trop de colonnes
     pour un usage tactile). Technique "responsive table" classique :
     l'entête est masqué, chaque ligne devient un bloc de champs
     étiquetés (via l'attribut data-label posé sur chaque <td> dans
     assets/formulaire.js), au lieu d'une ligne de tableau qu'il fallait
     faire défiler horizontalement. .table-scroll garde son défilement
     VERTICAL (max-height/overflow) pour les listes longues — seule la
     contrainte de largeur minimale (qui forçait le défilement horizontal)
     est neutralisée ici, elle n'a plus lieu d'être en mode carte.
     Scopé à .table-lignes, exclusive aux 3 tableaux du formulaire (la
     liste adhérents utilise .table-adherents, un nom différent — pas de
     risque de collision comme celle déjà rencontrée avec .table-scroll). */
  #table-disciplines, #table-prestations, #table-paiements { min-width: 0; }
  #table-disciplines { table-layout: auto; }
  #table-disciplines th, #table-disciplines td {
    width: auto;
    white-space: normal;
  }

  .table-lignes thead { display: none; }
  .table-lignes, .table-lignes tbody, .table-lignes tr { display: block; width: 100%; }
  .table-lignes tr {
    border: 1px solid var(--couleur-bordure);
    border-radius: 8px;
    padding: 8px 10px;
    margin-bottom: 8px;
    background: var(--couleur-surface);
  }
  .table-lignes tr:last-child { margin-bottom: 0; }
  .table-lignes td {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    padding: 5px 0;
    border: none;
  }
  .table-lignes td[data-label]::before {
    content: attr(data-label);
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    color: var(--couleur-texte-att);
  }
  .table-lignes td select,
  .table-lignes td input:not([type="checkbox"]) {
    width: 100%;
  }
  .table-lignes td .groupe-date {
    width: 100%;
  }
  /* Colonne "supprimer" (pas de data-label, juste le bouton ✕) : détachée
     visuellement en pied de carte plutôt que traitée comme un champ de
     plus. */
  .table-lignes td:last-child {
    flex-direction: row;
    justify-content: flex-end;
    padding-top: 8px;
    margin-top: 4px;
    border-top: 1px solid var(--couleur-bordure);
  }
}

/* Bloc "Le virement de NN,NN € doit s'effectuer en : NN fois" (08/09/2026,
   bascule vers Virement le 08/09/2026, correctifs le 09/09/2026) :
   - le champ est ciblé par ID (#i-nb-echeances-prelevement), PAS par
     attribut de type : la règle générale fieldset input:not(...):not(...)
     (width:100%, plus haut dans ce fichier) a une spécificité CSS
     supérieure à .bloc-prelevement-echeances input[type="number"] et
     l'emportait, gardant le champ pleine largeur malgré la demande de
     Bruno de le garder compact (2 chiffres max).
   - Plus de fond coloré sur tout le bloc (Bruno : "ce n'est pas tout le
     cadre qui doit être sur fond jaune") — seul le champ numérique porte
     une couleur, et seulement s'il est vide (voir .champ-erreur plus bas
     et actualiserBlocEcheancesPrelevement()/le listener "input" dans
     assets/formulaire.js).
   - Texte ("Le virement..."/"fois") aligné sur .case-a-cocher (ex.
     "Paiements multiples") — PAS "fieldset label" (libellé au-dessus
     d'un champ) : Bruno a précisé sa référence par capture d'écran. */
.bloc-prelevement-echeances {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 10px; padding: 4px 0;
}
.bloc-prelevement-echeances label { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.bloc-prelevement-echeances label,
.bloc-prelevement-echeances span {
  font-size: 0.84rem;
  font-weight: 600;
  color: var(--couleur-texte);
}
#i-nb-echeances-prelevement {
  width: 56px; padding: 4px 6px; border: 1px solid var(--couleur-bordure); border-radius: 4px;
  text-align: center; font-weight: 600;
}
#i-nb-echeances-prelevement.champ-erreur { border-color: var(--couleur-erreur); background: var(--couleur-erreur-fond); }

/* Popup de confirmation à l'enregistrement (08/09/2026, centrée + fermeture
   manuelle uniquement depuis le 09/09/2026, demande de Bruno : "je
   préfèrerais qu'il soit au milieu de l'écran, et qu'on doive cliquer en
   dehors ou sur un bouton fermer pour être certain qu'il a été vu avant de
   disparaître") — voir afficherToast() dans assets/formulaire.js. */
.toast-fond {
  position: fixed; inset: 0; background: rgba(27, 36, 32, 0.45);
  display: flex; align-items: center; justify-content: center;
  z-index: 1000; opacity: 0; transition: opacity 0.2s ease;
}
.toast-fond.toast-visible { opacity: 1; }
.toast {
  background: var(--couleur-primaire); color: white; padding: 18px 44px 18px 22px;
  border-radius: 10px; font-size: 0.95rem; box-shadow: 0 8px 28px rgba(0, 0, 0, 0.3);
  position: relative; max-width: min(90vw, 420px);
  transform: scale(0.94); transition: transform 0.2s ease;
}
.toast-fond.toast-visible .toast { transform: scale(1); }
.toast-fermer {
  position: absolute; top: 6px; right: 6px; width: 26px; height: 26px;
  border: none; background: transparent; color: white; opacity: 0.75;
  font-size: 0.9rem; line-height: 1; cursor: pointer; border-radius: 50%;
}
.toast-fermer:hover { opacity: 1; background: rgba(255,255,255,0.15); }
.toast-liste-erreurs { margin: 8px 0 0; padding-left: 18px; text-align: left; }
.toast-liste-erreurs li { margin-bottom: 3px; }

/* Page Paramètres (08/09/2026) — liste de réglages avec interrupteur on/off. */
.liste-parametres { display: flex; flex-direction: column; gap: 12px; margin-top: 14px; }
.carte-parametre {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  padding: 14px 16px; border: 1px solid var(--couleur-bordure); border-radius: 10px; background: white;
}
.carte-parametre-texte h3 { margin: 0 0 4px; font-size: 0.95rem; }
.carte-parametre-texte p { margin: 0; font-size: 0.83rem; color: var(--couleur-texte-att); line-height: 1.4; }
/* 25/09/2026, correctif (retour de Bruno, lignes "Modes de paiement"
   trop hautes sur Configuration de saison) : l'interrupteur est
   implémenté comme un <label> (voir markup ci-dessus/dans le JS), il
   hérite donc par défaut du margin:14px 0 6px du sélecteur générique
   "label" plus bas dans ce fichier -- pensé pour un texte de champ de
   formulaire, pas pour ce composant. C'est bien un MARGIN (pas un
   padding) qui ajoutait ~20px de hauteur à chaque ligne de tableau
   utilisant l'interrupteur (mesuré : 46px de haut contre 34px pour une
   ligne de texte comparable). margin:0 ici neutralise cet héritage pour
   TOUTES les utilisations de l'interrupteur (Paramètres, Modes de
   paiement...), sans toucher au sélecteur générique "label" lui-même. */
.interrupteur { position: relative; display: inline-block; width: 44px; height: 24px; flex-shrink: 0; margin: 0; }
.interrupteur input { opacity: 0; width: 0; height: 0; }
.interrupteur-curseur {
  position: absolute; cursor: pointer; inset: 0; background: #CCC; border-radius: 24px; transition: background 0.2s ease;
}
.interrupteur-curseur::before {
  content: ""; position: absolute; height: 18px; width: 18px; left: 3px; bottom: 3px;
  background: white; border-radius: 50%; transition: transform 0.2s ease;
}
.interrupteur input:checked + .interrupteur-curseur { background: var(--couleur-primaire); }
.interrupteur input:checked + .interrupteur-curseur::before { transform: translateX(20px); }
.interrupteur input:disabled + .interrupteur-curseur { opacity: 0.6; cursor: default; }
/* ---------------------------------------------------------------------
   Page Facturation (10/09/2026) — aperçu à l'écran du justificatif,
   reprend la maquette validée par Bruno (logo + charte noir/gris/blanc,
   bandeaux clairs économes en encre). La génération réelle du PDF est
   faite côté serveur (api/lib_facturation_pdf.php, FPDF) : ce CSS ne sert
   qu'à l'aperçu à l'écran, les deux rendus sont proches sans être
   pixel-identiques (contrainte assumée, voir SYNTHESE).
   --------------------------------------------------------------------- */
.panneau-facturation .entete-liste { align-items: center; }

.feuille-facture {
  background: white; border: 1px solid var(--couleur-bordure); border-radius: 4px;
  max-width: 720px; margin: 0 auto; padding: 28px 32px; font-size: 0.85rem; color: var(--couleur-texte);
}
.facture-entete { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 16px; }
.facture-logo { width: 150px; height: auto; display: block; }
.facture-entete-droite { text-align: right; }
.facture-type { font-size: 1.2rem; font-weight: 700; letter-spacing: 0.03em; color: var(--couleur-bandeau-app); }
.facture-saison { font-size: 0.85rem; font-weight: 600; color: var(--couleur-primaire); margin-top: 2px; }
.facture-date, .facture-numero { font-size: 0.72rem; color: var(--couleur-texte-att); margin-top: 6px; }
.facture-adresses { display: flex; justify-content: space-between; gap: 24px; margin-bottom: 16px; font-size: 0.75rem; line-height: 1.5; }
.facture-adresse-dest { text-align: right; }
.facture-nom-gras { font-weight: 700; color: var(--couleur-primaire); }

.facture-table { width: 100%; border-collapse: collapse; font-size: 0.75rem; margin-bottom: 6px; }
.facture-table thead tr { background: #EAEAEA; color: var(--couleur-primaire); }
.facture-table th { text-align: left; padding: 5px 8px; font-weight: 700; border-bottom: 1px solid var(--couleur-primaire); }
.facture-table .facture-col-montant { text-align: right; white-space: nowrap; width: 1%; }
.facture-table td { padding: 4px 8px; border-bottom: 1px solid #F0F0F0; }
.facture-nom-bloc { font-weight: 700; }

.facture-ligne-total { display: flex; justify-content: flex-end; margin: 6px 0 14px; }
.facture-ligne-total table { border-collapse: collapse; font-size: 0.8rem; }
.facture-total-libelle { background: #EAEAEA; font-weight: 700; padding: 5px 12px; border: 1px solid var(--couleur-primaire); }
.facture-total-montant { border: 1px solid var(--couleur-primaire); border-left: none; font-weight: 700; padding: 5px 12px; text-align: right; }

.facture-boite { border: 1px solid var(--couleur-bordure); margin-bottom: 12px; font-size: 0.72rem; }
.facture-boite-titre { background: #EAEAEA; color: var(--couleur-primaire); font-weight: 700; padding: 4px 8px; }
.facture-boite-corps { padding: 8px; line-height: 1.45; color: var(--couleur-primaire); }
.facture-boite-corps textarea {
  width: 100%; border: none; resize: vertical; font-family: inherit; font-size: 0.78rem;
  color: var(--couleur-texte); background: transparent; padding: 0;
}
.facture-boite-corps textarea:focus { outline: none; }

.facture-mentions { border-top: 1px solid var(--couleur-bordure); padding-top: 10px; font-size: 0.65rem; color: var(--couleur-texte-att); line-height: 1.55; }

.facture-actions { display: flex; gap: 10px; justify-content: center; margin: 20px auto 4px; max-width: 720px; flex-wrap: wrap; }

/* Bloc "Message d'envoi par email" éditable (12/09/2026, page Facturation). */
.facture-bloc-email {
  max-width: 720px; margin: 24px auto 0; padding: 18px 20px; background: var(--couleur-surface);
  border: 1px solid var(--couleur-bordure); border-radius: 4px;
}
.facture-bloc-email h2 { font-size: 1rem; margin: 0 0 12px; color: var(--couleur-primaire); }
.facture-bloc-email label { display: block; font-size: 0.8rem; font-weight: 600; color: var(--couleur-texte-att); margin: 10px 0 4px; }
/* Bat la spécificité de la règle ci-dessus pour les cases à cocher de
   mise en copie (22/09/2026, corrige un bug signalé par Bruno) —
   .case-a-cocher seule perdait face à .facture-bloc-email label (deux
   sélecteurs combinés), qui repassait la case en display:block. */
.facture-bloc-email .case-a-cocher { display: flex; }
.facture-bloc-email input,
.facture-bloc-email textarea {
  width: 100%; box-sizing: border-box; border: 1px solid var(--couleur-bordure); border-radius: 4px;
  padding: 8px 10px; font-family: inherit; font-size: 0.85rem; color: var(--couleur-texte);
}
.facture-bloc-email textarea { resize: vertical; line-height: 1.5; }

/* En-tête de statut de la page Facturation (12/09/2026). */
.facture-statut {
  max-width: 720px; margin: 0 auto 16px; padding: 10px 16px; background: var(--couleur-fond);
  border: 1px solid var(--couleur-bordure); border-radius: 4px; font-size: 0.8rem; color: var(--couleur-texte-att);
  display: flex; flex-wrap: wrap; gap: 6px 18px;
}
.facture-statut span:not(:empty)::before { content: '• '; color: var(--couleur-accent); }
.facture-statut span:first-child::before { content: ''; }

/* Boutons de résolution de doublon (12/09/2026) — remplacent temporairement
   "Générer et enregistrer sur Drive" quand un justificatif existe déjà. */
.facture-choix-doublon {
  max-width: 720px; margin: 0 auto; padding: 14px 16px; background: var(--couleur-erreur-fond);
  border: 1px solid var(--couleur-erreur); border-radius: 4px;
}
.facture-choix-doublon p { margin: 0 0 10px; font-size: 0.85rem; color: var(--couleur-texte); }
.facture-choix-doublon .facture-actions { margin: 0; justify-content: flex-start; }

/* Mise en évidence (12/09/2026, demande de Bruno) — "Reste dû" non nul et
   colonnes Facturé/Envoyée = "Non", dans la Liste adhérents (tableau ET
   cartes tactiles). */
.valeur-alerte {
  background: var(--couleur-erreur-fond); color: var(--couleur-erreur);
  border-radius: 3px; padding: 1px 6px; font-weight: 600;
}
td.valeur-alerte { padding: 8px 10px; border-radius: 0; }

/* Historique de facturation sur la fiche (12/09/2026, page Formulaire). */
.bloc-historique-facturation { margin: 0 0 16px; }
.historique-facturation-liste {
  list-style: none; margin: 0; padding: 0; font-size: 0.82rem; color: var(--couleur-texte-att);
}
.historique-facturation-liste li {
  padding: 4px 0; border-bottom: 1px solid var(--couleur-bordure);
}
.historique-facturation-liste li:last-child { border-bottom: none; }

/* Réglage SMTP facturation (13/09/2026) — carte "critique" avec mise en
   avant visuelle distincte des cartes de réglage habituelles (bordure et
   fond légèrement accentués), pour bien signaler l'importance de ce
   réglage sans pour autant recourir à la couleur d'erreur (rien n'est en
   défaut tant qu'il n'y a pas d'échec d'envoi). */
.carte-parametre-critique {
  border: 1px solid var(--couleur-accent-clair); background: var(--couleur-fond);
  padding: 16px 18px;
}
.carte-parametre-critique h3 { margin: 0 0 10px; font-size: 0.98rem; }
.carte-parametre-critique p { margin: 0 0 8px; font-size: 0.85rem; color: var(--couleur-texte); line-height: 1.5; }
.aide-champ-critique {
  background: white; border-left: 3px solid var(--couleur-accent);
  padding: 8px 12px; margin: 8px 0 !important; border-radius: 0 4px 4px 0;
  font-style: normal !important; font-size: 0.82rem !important;
}

/* Tableau des sauvegardes (14/09/2026, page Paramètres). */
.tableau-sauvegardes { width: 100%; border-collapse: collapse; font-size: 0.82rem; }
.tableau-sauvegardes th { text-align: left; padding: 6px 8px; border-bottom: 2px solid var(--couleur-bordure); color: var(--couleur-texte-att); }
.tableau-sauvegardes td { padding: 6px 8px; border-bottom: 1px solid var(--couleur-bordure); }

/* ---------------------------------------------------------------------
   Bandeau permanent du Mode test / usurpation d'identité (16/09/2026)
   Volontairement TRÈS visible (couleur distincte de tout le reste de
   l'appli) et non "sticky" — pas de superposition avec .barre-app
   (déjà sticky), reste simplement collé juste en dessous, visible tant
   qu'on n'a pas scrollé plus bas. Présent sur toutes les pages staff
   (partials/entete.php) et sur accueil.php (marquage dupliqué, voir
   commentaire dans ce fichier) — voir assets/entete.js::
   initialiserBandeauModeTest().
   --------------------------------------------------------------------- */
.bandeau-mode-test {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 24px;
  background: #fff3cd;
  color: #664d03;
  border-bottom: 2px solid #ffca2c;
  font-size: 0.85rem;
}
.bandeau-mode-test strong { font-weight: 600; }
.bandeau-mode-test button { flex-shrink: 0; }
/* 28/09/2026 (section 232) : "Changer d'usurpation" + "Quitter l'usurpation". */
.boutons-bandeau-mode-test { display: flex; flex-wrap: wrap; gap: 8px; }

/* ---------------------------------------------------------------------
   Composant de tri + filtres cumulatifs par colonne (17/09/2026, nouvelle
   phase "Remun Profs" — voir assets/tri_filtre_tableau.js). Utilisé sur
   Cours des élèves, Paye Professeurs, et Liste adhérents.
   19/09/2026 (retour de test) : refonte façon filtre de colonne Excel —
   un seul bouton par colonne, agrandi (cible de clic plus grande, il
   était trop petit) ; le clic sur le texte de l'en-tête ne trie plus
   (tris involontaires signalés) — seul ce bouton déclenche tri/filtre.
   --------------------------------------------------------------------- */
.entete-triable { position: relative; padding-right: 36px !important; }
/* Tri au clic sur le nom de colonne (29/09/2026, demande de Bruno —
   SYNTHESE section 239) : zone cliquable limitée au texte du titre, le
   bouton ▾ (tri/filtre) garde sa propre zone. */
.libelle-colonne-triable { cursor: pointer; border-radius: 3px; }
.libelle-colonne-triable:hover { text-decoration: underline; text-underline-offset: 3px; }

.bouton-menu-colonne {
  background: none; border: none; cursor: pointer; font-size: 1.2rem; font-weight: 700;
  color: var(--couleur-texte-att); line-height: 1;
  position: absolute; right: 2px; top: 50%; transform: translateY(-50%);
  width: 26px; height: 26px; display: flex; align-items: center; justify-content: center;
  border-radius: 4px;
}
/* Pas d'effet "pressé" (translateY) sur ce bouton précis (retour de
   test, 19/09/2026 — la règle générale button:active donnait
   l'impression que le bouton "s'enfonçait" avant que le menu apparaisse,
   perçu comme un délai). */
.bouton-menu-colonne:active { transform: translateY(-50%) !important; }
.bouton-menu-colonne:hover { background: rgba(0,0,0,0.08); color: var(--couleur-texte); }
.entete-sans-filtre { padding-right: 8px !important; } /* pas de bouton ▾ (colonne non filtrable) */
/* Colonne FILTRÉE (29/09/2026, demande de Bruno — SYNTHESE section 240) :
   bouton ▾ sur fond bleu clair, même bleu que « ← Retour » (.lien-retour-page). */
.entete-triable.filtre-actif .bouton-menu-colonne {
  background: #D9EBFB; color: #1B5E8C; box-shadow: inset 0 0 0 1px #A9CFEE;
}
.entete-triable.filtre-actif .bouton-menu-colonne:hover { background: #C3DFF6; }

/* Colonne TRIÉE (17/09/2026, demande de Bruno — le simple changement de
   couleur du texte passait inaperçu) : fond vert + liseré. 29/09/2026
   (section 240) : réservé au tri (le filtre a son propre repère bleu
   ci-dessus), avec une flèche ↑ / ↓ après le nom de la colonne. */
.entete-triable.tri-croissant, .entete-triable.tri-decroissant {
  background: #E3ECD9; padding-left: 12px !important;
}
.tri-croissant .libelle-colonne-triable::after { content: ' ↑'; color: var(--couleur-primaire); }
.tri-decroissant .libelle-colonne-triable::after { content: ' ↓'; color: var(--couleur-primaire); }
.entete-triable.tri-croissant::before, .entete-triable.tri-decroissant::before {
  content: ''; position: absolute; left: 2px; top: 6px; bottom: 6px; width: 3px;
  background: var(--couleur-primaire); border-radius: 2px;
}

/* Panneau façon filtre de colonne Excel : intervalle (nombres, dates),
   recherche, liste à cocher avec nombre de lignes, Supprimer le filtre /
   OK / Annuler (29/09/2026, section 240 — plus de boutons de tri). */
.panneau-filtre-colonne {
  position: fixed; z-index: 500;
  background: white; border: 1px solid var(--couleur-bordure); border-radius: 6px;
  box-shadow: 0 4px 14px rgba(0,0,0,0.15); padding: 8px; min-width: 240px;
  font-weight: 400; text-transform: none; cursor: default;
}
/* .panneau-filtre-tri / .bouton-tri-panneau retirés le 29/09/2026 (section 240). */
.separateur-panneau-filtre { border: none; border-top: 1px solid var(--couleur-bordure); margin: 6px 0; }
.champ-recherche-filtre {
  width: 100%; box-sizing: border-box; padding: 6px 8px; margin-bottom: 6px;
  border: 1px solid var(--couleur-bordure); border-radius: 4px; font-size: 0.82rem;
  font-family: var(--police-texte);
}
.case-tout-cocher { font-weight: 600; border-bottom: 1px solid var(--couleur-bordure); padding-bottom: 5px; margin-bottom: 3px; }
.panneau-filtre-liste { display: flex; flex-direction: column; gap: 0; max-height: 220px; overflow-y: auto; }
.case-filtre-colonne { font-size: 0.82rem; font-weight: 400; display: flex; align-items: center; gap: 6px; padding: 1px 0; margin: 0; line-height: 1.35; }
.panneau-filtre-pied { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--couleur-bordure); text-align: right; display: flex; gap: 8px; justify-content: flex-end; }
.bouton-valider-filtre, .bouton-annuler-filtre { padding: 5px 14px !important; font-size: 0.78rem !important; }
.bouton-valider-filtre:disabled { opacity: 0.4; cursor: not-allowed; }
/* Intervalle « Entre … et … » / « Du … au … » + raccourcis de dates
   (29/09/2026, section 240). */
.panneau-filtre-intervalle { margin-bottom: 8px; padding-bottom: 8px; border-bottom: 1px solid var(--couleur-bordure); }
.ligne-intervalle-filtre { display: flex; align-items: center; gap: 6px; font-size: 0.82rem; white-space: nowrap; }
.champ-intervalle-filtre {
  width: 74px; min-width: 0; box-sizing: border-box; padding: 5px 6px; font-size: 0.82rem !important;
  border: 1px solid var(--couleur-bordure); border-radius: 4px; font-family: var(--police-texte); background: white;
}
.champ-intervalle-filtre[type="date"] { width: 132px; }
.raccourcis-intervalle-filtre { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.bouton-raccourci-filtre {
  padding: 3px 8px !important; font-size: 0.74rem !important; font-weight: 600;
  background: var(--couleur-fond); color: var(--couleur-texte); border: 1px solid var(--couleur-bordure) !important; border-radius: 12px;
}
.bouton-raccourci-filtre:hover { background: #D9EBFB; border-color: #A9CFEE !important; }
.compte-valeur-filtre { color: var(--couleur-texte-att); font-size: 0.76rem; font-variant-numeric: tabular-nums; }
.bouton-supprimer-filtre-colonne { padding: 5px 10px !important; font-size: 0.78rem !important; margin-right: auto; }
/* Compteur au-dessus du tableau (29/09/2026, sections 240 et 242) :
   « Filtre inactif : M lignes » en gris, « Filtre actif : N lignes sur M »
   en bleu (même bleu que le bouton ▾ d'une colonne filtrée). */
.compteur-lignes-filtre {
  margin: 0 0 6px; font-size: 0.78rem; font-weight: 600; color: var(--couleur-texte-att);
}
.compteur-lignes-filtre.compteur-lignes-filtre-actif { color: #1B5E8C; }

/* Harmonisation des largeurs de colonnes (19/09/2026, demande de Bruno) :
   chaque colonne se dimensionne à son contenu plutôt que d'être étirée
   pour remplir toute la largeur — .table-scroll gère le défilement
   horizontal si besoin. Pas de retour à la ligne dans les cellules, pour
   des lignes de hauteur régulière. S'applique aux 3 tableaux (Liste
   adhérents, Cours des élèves, Paye Professeurs), via la classe de base. */
.table-adherents th, .table-adherents td { white-space: nowrap; }

/* Le regroupement des boutons d'entête de liste utilise désormais
   .groupe-boutons-entete (même classe que le Formulaire, 17/09/2026,
   demande de Bruno) — plus besoin de règle dédiée ici. */

/* Colonnes de calcul masquées par défaut (Cours des élèves). */
.table-cours-eleves .colonne-calcul { background: #F5F2E8; }

/* Tableau Paye Professeurs (17/09/2026, retour de test — "peu lisible",
   gagner en largeur) : même traitement "autofit" que Cours des élèves,
   police réduite pour ce tableau spécifiquement (dense, beaucoup de
   colonnes mensuelles). */
.table-paye-professeurs { width: auto; min-width: 100%; font-size: 0.82rem; }
.table-paye-professeurs th, .table-paye-professeurs td { white-space: nowrap; }
/* Colonnes 2 à 5 = Total Tarif/Total rénum/Payé/Reste dû (17/09/2026,
   retour de test) : resserrées pour laisser de la place aux colonnes
   mensuelles, qui doivent pouvoir accueillir des montants à 4 chiffres
   (>= 1000,00) sans casser la mise en page. */
.table-paye-professeurs th:nth-child(2), .table-paye-professeurs th:nth-child(3),
.table-paye-professeurs th:nth-child(4), .table-paye-professeurs th:nth-child(5),
.table-paye-professeurs td:nth-child(2), .table-paye-professeurs td:nth-child(3),
.table-paye-professeurs td:nth-child(4), .table-paye-professeurs td:nth-child(5) {
  width: 62px;
}

/* Cellules mensuelles éditables : montant saisi en texte normal, montant
   suggéré affiché en placeholder gris clair tant que rien n'a été saisi
   (confort déjà présent dans Excel via T_ResteApayer, le trésorier peut
   l'écraser à tout moment). Disposition en ligne flex (champ + bouton
   toujours côte à côte, jamais superposés) plutôt qu'un bouton en overlay
   positionné en absolu — retour de test : la coche était trop imprécise
   à cliquer, surtout dans la dernière colonne du tableau.
   IMPORTANT (17/09/2026, retour de test) : le sélecteur DOIT être préfixé
   par "input" (`input.input-mois-professeur`, pas juste `.input-mois-
   professeur`) pour battre en spécificité la règle générale `input[type=
   "text"]` plus haut dans ce fichier (gros padding/rayon/fond du
   Formulaire) — sans ce préfixe, ce champ hérite du look "pilule" du
   Formulaire au lieu de rester minimal, ce qui a cassé l'homogénéité de
   la page lors du passage de type="number" à type="text". */
.cellule-mois-professeur { padding: 2px 3px !important; }
.ligne-saisie-mois { display: flex; align-items: center; gap: 2px; }
input.input-mois-professeur {
  flex: 1 1 auto; width: 56px; min-width: 0; padding: 2px 3px; border: 1px solid var(--couleur-bordure);
  border-radius: 4px; font-size: 0.78rem; text-align: right;
  font-family: var(--police-texte); background: transparent;
}
input.input-mois-professeur::placeholder { color: #B7BBAE; }
input.input-mois-professeur:disabled { opacity: 0.6; }
/* Flèches incrémentales inutiles ici (demande de Bruno) — masquées sur
   tous les navigateurs. */
input.input-mois-professeur::-webkit-outer-spin-button,
input.input-mois-professeur::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
input.input-mois-professeur { -moz-appearance: textfield; }

/* Bouton "✓" (rien de fiable à afficher, valide le montant affiché) /
   "✕" (case remplie — y compris "0,00" non fiable, vide la case) — un
   seul bouton, action selon l'état (17/09/2026). */
.bouton-action-mois {
  flex: 0 0 auto; background: none; border: none; cursor: pointer;
  font-weight: 700; font-size: 0.8rem; padding: 0 2px; line-height: 1;
  color: var(--couleur-primaire);
}
.bouton-action-mois:hover { color: #2E7D4F; }
.bouton-action-mois[data-action="vider"] { color: var(--couleur-erreur); }
.bouton-action-mois[data-action="vider"]:hover { color: #8a1c17; }

/* Mois "responsables" d'un trop-perçu (Reste dû négatif) — 17/09/2026. */
.cellule-mois-excedent { background: var(--couleur-erreur-fond); }
.cellule-mois-excedent input.input-mois-professeur { border-color: var(--couleur-erreur); }

/* Cellule "Reste dû" (17/09/2026) : orange par défaut (comme un champ
   obligatoire — reste à régler), vert clair si soldé, rouge si trop-perçu
   (anomalie à corriger). */
.reste-du-positif { background: #FDEBD3 !important; }
.reste-du-nul { background: #E1F3E8 !important; color: #2E7D4F; font-weight: 600; }
.reste-du-negatif { background: var(--couleur-erreur-fond) !important; color: var(--couleur-erreur); font-weight: 700; }

/* Ligne "Totaux pour compta" (17/09/2026, équivalent de la ligne A3:Q3 de
   la feuille Excel "Remun Profs"), insérée au-dessus de l'en-tête —
   différenciée discrètement du reste du tableau. */
.ligne-totaux-compta th {
  background: #EFEAD9; color: var(--couleur-texte); font-weight: 700;
  font-size: 0.78rem; border-top: 2px solid var(--couleur-accent-clair);
  border-bottom: 1px solid var(--couleur-bordure); white-space: nowrap;
}

/* "← Retour à ..." (17/09/2026, demande de Bruno) — discret, au-dessus du
   bandeau de titre du Formulaire, visible seulement en arrivant depuis le
   clic sur une ligne de tableau/carte d'une autre page. */
/* "← Retour à ..." (17/09/2026, retour de test — trop discret, capture
   d'écran à l'appui) : agrandi, en gras, avec un léger fond en forme de
   puce pour bien ressortir au-dessus du bandeau de titre. */
.lien-retour-page {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 0.78rem; font-weight: 600; text-decoration: none;
  padding: 4px 10px; border-radius: 6px; flex: 0 0 auto;
  /* Bleu clair, couleur volontairement inhabituelle sur ce site (fond
     surtout vert/orange ailleurs), pour bien attirer l'œil (21/09/2026,
     demande de Bruno — même mécanisme que "🧹 Supprimer les filtres",
     replacé à droite du sélecteur de saison plutôt que pleine largeur). */
  background: #D9EBFB; color: #1B5E8C; border: 1px solid #A9CFEE;
}
.lien-retour-page:hover { background: #C3DFF6; text-decoration: underline; }

/* Champs éditables de l'aperçu de facture (17/09/2026, demande urgente
   du trésorier) — indication visuelle discrète au survol/focus, pour
   qu'on comprenne qu'on peut cliquer dedans, sans dénaturer le rendu
   fidèle au PDF le reste du temps. */
.feuille-facture [contenteditable="true"] {
  border-radius: 2px; cursor: text; transition: background-color 0.15s;
}
.feuille-facture [contenteditable="true"]:hover {
  background-color: rgba(66, 133, 244, 0.06);
}
.feuille-facture [contenteditable="true"]:focus {
  outline: 1px dashed rgba(66, 133, 244, 0.6); outline-offset: 1px;
  background-color: rgba(66, 133, 244, 0.08);
}
.feuille-facture td[contenteditable="true"] {
  display: table-cell;
}

/* Numéro de ligne façon Excel (19/09/2026, demande du trésorier — se
   repère aux n° de ligne du classeur pour compter). Colonne non triable,
   non filtrable, purement indicative — numérotée sur les lignes de
   données affichées (après tri/filtre), pas sur l'ordre brut. */
.colonne-numero-ligne {
  width: 34px; min-width: 34px; max-width: 34px;
  text-align: center; color: var(--couleur-texte-att);
  background: var(--couleur-fond); font-size: 0.78rem;
  border-right: 1px solid var(--couleur-bordure) !important;
  user-select: none;
}
th.colonne-numero-ligne { background: #EDEAE0; }

/* Lien du nom de professeur (Paye Professeurs → Cours des élèves,
   19/09/2026, demande de Bruno) : reste sobre, comme le reste du
   tableau, mais un vrai <a> pour permettre Ctrl/Cmd-clic et clic milieu
   (nouvel onglet) sur PC. */
.lien-professeur-cours { color: inherit; display: block; }

/* N° de dossier → fiche (19/09/2026, même principe, Cours des élèves et
   Liste adhérents) — même style de lien discret. Prénom/Nom (même
   demande) réutilisent la même classe .lien-nom-prenom. */
.lien-num-dossier, .lien-nom-prenom { color: inherit; display: block; }

/* Style commun des liens discrets sur les tableaux (professeur, n° de
   dossier, prénom, nom) : un soulignement permanent, un peu plus visible
   qu'au premier essai (retour de test, 19/09/2026 — "vraiment très peu
   visible"), plus marqué au survol. */
.lien-professeur-cours, .lien-num-dossier, .lien-nom-prenom {
  text-decoration: underline; text-decoration-color: var(--couleur-texte-att);
  text-underline-offset: 2px;
}
.lien-professeur-cours:hover, .lien-num-dossier:hover, .lien-nom-prenom:hover {
  text-decoration-color: currentColor;
}

/* Bouton "Supprimer les filtres" (19/09/2026, retour de test — le rendre
   plus visible) : sorti du groupe de boutons, collé au coin haut-droit du
   tableau (juste au-dessus), plus petit que les boutons standards mais
   avec une grande icône 🧹 et une couleur d'alerte pour attirer l'œil dès
   qu'il apparaît, plus un compteur du nombre de colonnes filtrées. */
.bouton-supprimer-filtres-flottant {
  display: inline-flex; align-items: center; gap: 6px;
  background: #FCEEDB; color: #8A5A16; border: 1px solid #E8C88A;
  border-radius: 6px; padding: 4px 10px 4px 6px; margin-bottom: 6px;
  font-size: 0.78rem; font-weight: 600;
}
.bouton-supprimer-filtres-flottant:hover { background: #F9E2BC; }
.bouton-supprimer-filtres-flottant .icone-balai { font-size: 1.3rem; line-height: 1; }
.bouton-supprimer-filtres-flottant .compteur-filtres { font-variant-numeric: tabular-nums; }

/* "Saison non active" (19/09/2026, demande de Bruno) — voir
   surveillerSelectSaisonActive() dans assets/entete.js. */
.select-saison-inactive { background: #FBDDE3 !important; border-color: #E8A8B5 !important; }
.bandeau-saison-inactive {
  display: inline-flex; align-items: center; gap: 5px;
  background: #FFF3CD; color: #664D03; border: 1px solid #997404;
  border-radius: 4px; padding: 3px 9px; font-size: 0.78rem; font-weight: 700;
  margin-left: 8px; vertical-align: middle;
}

/* Colonnes figées au défilement horizontal, façon volets Excel
   (19/09/2026, demande de Bruno) — voir figerColonnesTableau() dans
   assets/tri_filtre_tableau.js. Fond opaque obligatoire (sinon le
   contenu défilé apparaît par transparence dessous) ; hérite du
   zébrage pair/impair de la ligne grâce à background:inherit (la
   propriété n'est normalement pas héritée, "inherit" le force). */
.colonne-figee { position: sticky; z-index: 6; background: inherit; }
.entete-colonne-figee.colonne-figee { z-index: 7; background: var(--couleur-fond); }
/* 29/09/2026 (section 240) : repère de tri vert conservé aussi sur les
   colonnes figées (le fond opaque ci-dessus l'effaçait). */
.entete-colonne-figee.colonne-figee.tri-croissant,
.entete-colonne-figee.colonne-figee.tri-decroissant { background: #E3ECD9; }
.derniere-colonne-figee { box-shadow: 2px 0 4px -2px rgba(0,0,0,0.25); }

/* Ligne saison + bandeau "Attention" + "Supprimer les filtres" côte à
   côte (20/09/2026, demande de Bruno — occupent ensemble la largeur
   disponible plutôt que d'être chacun sur leur propre ligne). Le select
   grandit pour remplir l'espace restant ; le bandeau et le bouton
   gardent leur largeur naturelle et passent à la ligne si la place
   manque (mobile étroit).
   26/09/2026 (livraison 208, demande de Bruno -- "même mise en forme du
   sélecteur que Paye Professeurs, y compris les indications concernant
   la saison") : .bandeau-saison-a-risque (Configuration de saison, texte
   variable "saison non active"/"N inscription(s)"/les deux -- voir
   .bandeau-saison-a-risque plus bas) ajouté à ces 2 règles, pour que le
   bandeau de risque de Configuration de saison se comporte EXACTEMENT
   comme .bandeau-saison-inactive (Paye Professeurs et les autres pages)
   dans cette ligne flex -- jusqu'ici seul .bandeau-saison-inactive en
   bénéficiait, .bandeau-saison-a-risque héritait juste du flex par
   défaut (visuellement proche mais pas garanti identique). */
.ligne-select-saison { display: flex; flex-wrap: wrap; align-items: stretch; gap: 8px; margin-bottom: 6px; }
.ligne-select-saison select,
.ligne-select-saison .bandeau-saison-inactive,
.ligne-select-saison .bandeau-saison-a-risque,
.ligne-select-saison .bouton-supprimer-filtres-flottant {
  box-sizing: border-box; display: inline-flex; align-items: center;
}
.ligne-select-saison select { flex: 1 1 160px; margin: 0; }
.ligne-select-saison .bandeau-saison-inactive,
.ligne-select-saison .bandeau-saison-a-risque { margin-left: 0; flex: 0 0 auto; }
.ligne-select-saison .bouton-supprimer-filtres-flottant { margin-bottom: 0; flex: 0 0 auto; }

/* Loupe à gauche des champs de recherche (20/09/2026, demande de Bruno —
   pour bien les identifier comme des champs de recherche) : image de
   fond en CSS pur plutôt qu'un <svg> imbriqué dans un conteneur
   supplémentaire (retour de test, 20/09/2026 — cet enrobage perturbait
   la mise en forme héritée de .filtres-liste sur certaines pages,
   surdimensionnement/sous-dimensionnement). Ne touche donc à AUCUNE
   structure existante : une seule classe posée directement sur chaque
   <input>, exactement comme avant sur Liste adhérents. */
.filtre-recherche-avec-loupe {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='15' height='15' fill='none' stroke='%23767267' stroke-width='2'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5' stroke-linecap='round'/%3E%3C/svg%3E") !important;
  background-repeat: no-repeat !important;
  background-position: 9px center !important;
  padding-left: 30px !important;
}
/* Champ "Aller à une autre fiche" du Formulaire : vit dans .filtres-liste
   comme les autres pages (20/09/2026, demande de Bruno), mais reste
   imbriqué dans .champ-recherche-personne (nécessaire pour la liste de
   suggestions) — contrairement aux autres pages où l'input est un
   enfant direct de .filtres-liste (qui l'étire automatiquement), cet
   imbrication supplémentaire l'empêche d'hériter cet étirement : sans
   ceci, l'input restait à sa largeur intrinsèque (retour de test,
   20/09/2026 — trop étroit, plein d'espace vide à droite). */
.recherche-aller-fiche input { width: 100%; box-sizing: border-box; }


/* Espacements égaux entre bandeau-titre / saison / recherche / premier
   bloc du formulaire (20/09/2026, demande de Bruno) : valeur de
   référence mesurée précisément par Bruno au pixel (15px, capture
   zoomée) — mon calcul théorique initial (10px + 14px = 24px, déduit
   des paddings de .entete-liste/.corps-liste) ne correspondait pas au
   rendu réel, corrigé empiriquement sur sa mesure. Les marges internes
   qui s'ajoutaient au gap du conteneur flex (.ligne-select-saison et
   .champ-recherche-personne ont chacune leur propre margin-bottom,
   utilisée ailleurs — un gap de conteneur flex NE fusionne PAS avec la
   marge de ses propres enfants, contrairement aux marges en flux
   normal) restent neutralisées. */
.panneau-formulaire .filtres-liste { gap: 15px; margin-bottom: 0; }
.panneau-formulaire .ligne-select-saison { margin-bottom: 0; }
.panneau-formulaire .recherche-aller-fiche { margin-bottom: 0; }
.panneau-formulaire .corps-liste { padding-bottom: 0; }
.panneau-formulaire .corps-formulaire { padding-top: 15px; }

/* Bouton "Facturation" périmée (20/09/2026, demande de Bruno) : même
   orange que .champ-erreur (champ manquant) — la fiche est enregistrée
   mais aucune facture n'est à jour par rapport au dernier enregistrement. */
#bouton-facturation.bouton-facturation-perimee {
  background: #FDEBD3; border-color: #E0A339 !important; color: var(--couleur-texte);
}
#bouton-facturation.bouton-facturation-perimee:hover { background: #FBDFB8; }

/* Mise en copie des emails de facturation (22/09/2026) — case(s) à
   cocher via .case-a-cocher (déjà existante, ex. "Membre du CA" du
   formulaire) pour un rendu identique ; seul le champ email libre a
   besoin d'un style dédié. */
/* Bloc "Mise en copie" verrouillé à gauche (22/09/2026, demande de
   Bruno) — sélecteur d'ID pour ne plus jamais dépendre d'un rapport de
   spécificité fragile avec d'autres règles de classe (voir le
   feuilleton des sections 158/160/165). */
#facture-bloc-copies { text-align: left; }
#facture-bloc-copies .case-a-cocher { display: flex; justify-content: flex-start; width: 100%; }
#facture-bloc-copies .case-a-cocher input[type="checkbox"] { width: 16px; height: 16px; flex: 0 0 auto; }
.facture-bloc-copies { margin: 10px 0 4px; display: flex; flex-direction: column; gap: 6px; }
.facture-copie-libre { display: flex; flex-direction: column; gap: 4px; font-size: 0.85rem; }
.facture-copie-libre input { max-width: 320px; }

/* "Envoyer par email" mis en évidence sur fond vert (22/09/2026,
   demande de Bruno) — modificateur sur .bouton-secondaire, même
   principe que .action-requise juste au-dessus. */
.bouton-secondaire.bouton-envoi-email {
  border-color: #2E7D32;
  color: #1B5E20;
  background: #E8F5E9;
}
.bouton-secondaire.bouton-envoi-email:hover { background: #D3EDD4; }
.bouton-secondaire.bouton-envoi-email:disabled {
  border-color: var(--couleur-bordure);
  color: var(--couleur-texte);
  background: var(--couleur-fond);
}

/* Bandeau "danger" très visible (25/09/2026, demande de Bruno) — page
   Configuration de saison : rappelle en permanence que modifier ces
   réglages a un impact direct sur les formulaires et les calculs
   financiers en cours, pas seulement quand la saison sélectionnée
   n'est pas la saison active. Couleurs d'erreur (--couleur-erreur /
   --couleur-erreur-fond) plutôt que le jaune "Attention" de
   .bandeau-saison-inactive (voir plus haut) -- volontairement plus
   appuyé, pour bien le distinguer d'une simple signalisation
   contextuelle liée à la saison sélectionnée. */
.bandeau-danger-page {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--couleur-erreur-fond); border: 1px solid var(--couleur-erreur);
  border-radius: 6px; padding: 12px 16px; margin-bottom: 18px;
  color: var(--couleur-erreur); font-weight: 600; font-size: 0.88rem; line-height: 1.5;
}
.bandeau-danger-page .icone-danger { font-size: 1.3rem; flex-shrink: 0; line-height: 1.3; }
.bandeau-danger-page strong { font-weight: 700; }

/* Zone de suppression d'une saison (23/09/2026), page Configuration de
   saison -- même palette que .bandeau-danger-page ci-dessus, pour
   marquer visuellement qu'il s'agit d'une action définitive et
   irréversible, distincte des autres cartes de réglages de la page. */
.carte-zone-danger {
  border: 1px solid var(--couleur-erreur);
  background: var(--couleur-erreur-fond);
}
.carte-zone-danger h3 { color: var(--couleur-erreur); margin-top: 0; }
.carte-zone-danger #confirmation-suppression-saison {
  border: 1px solid var(--couleur-erreur); max-width: 220px;
}

/* Signalisation "saison à risque" spécifique à la page Configuration de
   saison (25/09/2026) : réutilise exactement .select-saison-inactive
   (fond rose) pour le select, mais avec un texte de bandeau variable
   selon la raison (saison non active / inscriptions déjà enregistrées /
   les deux) -- voir actualiserSignalisationSaisonConfiguration() dans
   assets/configuration_saison.js. Contrairement à .bandeau-saison-
   inactive (partagé, texte fixe "Saison non active"), ce bandeau-ci
   porte sa propre classe pour ne jamais interférer avec le mécanisme
   partagé de assets/entete.js -- même gabarit de badge que
   .bandeau-saison-inactive (padding/rayon/graisse identiques), seules
   les couleurs diffèrent (rose plutôt que jaune, pour rester cohérent
   avec le rose de .select-saison-inactive juste à côté). 26/09/2026 :
   participe désormais aussi à la ligne flex .ligne-select-saison (voir
   plus haut), comme .bandeau-saison-inactive -- comportement identique
   entre les deux dans cette ligne, indépendamment de la page. */
.bandeau-saison-a-risque {
  display: inline-flex; align-items: center; gap: 5px;
  background: #FBDDE3; color: #7A2438; border: 1px solid #E8A8B5;
  border-radius: 4px; padding: 3px 9px; font-size: 0.78rem; font-weight: 700;
  margin-left: 8px; vertical-align: middle;
}

/* Lignes "Modes de paiement" compactées au maximum (25/09/2026, demande
   de Bruno). #liste-modes-paiement est désormais l'id du <table>
   .table-lignes lui-même (voir configuration_saison.php et la refonte en
   tableaux documentée dans assets/configuration_saison.js) -- seule la
   compaction de l'interrupteur reste utile ici (.carte-parametre a
   disparu de cette section avec la carte à interrupteurs qu'elle stylait
   ; conservée UNIQUEMENT sous ce sélecteur pour ne rien changer à
   l'interrupteur partagé utilisé ailleurs, ex. Paramètres). */
#liste-modes-paiement .interrupteur { width: 32px; height: 17px; }
#liste-modes-paiement .interrupteur-curseur::before { height: 13px; width: 13px; left: 2px; bottom: 2px; }
#liste-modes-paiement .interrupteur input:checked + .interrupteur-curseur::before { transform: translateX(15px); }

/* 25/09/2026 : le catalogue "Disciplines et tarifs" (carte par discipline
   + mini-tableau de tarifs) est remplacé par un tableau matriciel unique
   -- voir #table-disciplines-config, .table-lignes et .ligne-ajout-table
   ci-dessus. Anciennes règles .carte-discipline/.entete-discipline/
   .table-tarifs-discipline/.ligne-ajout-tarif retirées (plus aucun
   élément ne les utilise, voir assets/configuration_saison.js). */

/* =====================================================================
   Page "Gestion des droits" (27/09/2026 — phase "Gestion des droits",
   lot 2, SYNTHESE section 218). Demande de Bruno : reprendre EXACTEMENT
   les styles et la disposition de Configuration de saison — la page
   réutilise telles quelles ses classes (.entete-liste, .filtres-liste >
   .ligne-select-saison, .bandeau-danger-page, .bloc-configuration-saison,
   .titre-bloc-configuration-saison, .table-lignes, .ligne-ajout-table,
   .interrupteur, .bouton-croix). Les règles ci-dessous ne font que
   reproduire, pour ses 3 tableaux, les réglages propres aux tableaux
   "Modes de paiement" / "Durées" (largeur ajustée, alignement,
   interrupteur compact, en-tête plus foncé), scopés par id comme les
   originaux pour ne rien changer ailleurs.
   ===================================================================== */
#bouton-enregistrer-gestion-droits.bouton-reglages-modifiees { background: #1B7F4C; }
#bouton-enregistrer-gestion-droits.bouton-reglages-modifiees:hover { background: #15693D; }

.table-scroll-droits { max-width: 560px; }
.table-scroll-fonctions { max-width: 680px; }
#table-droits-fonction th,
#table-fonctions th,
#table-synthese-droits th,
#table-synthese-statuts th { background: #E2E6DC; }

#table-droits-fonction th:first-child,
#table-droits-fonction td:first-child { text-align: left; min-width: 320px; }
#table-droits-fonction th:last-child,
#table-droits-fonction td:last-child { text-align: center; width: 1%; white-space: nowrap; }

#table-fonctions td:first-child,
#table-fonctions th:first-child { width: 1%; white-space: nowrap; }
#table-fonctions td:nth-child(2) { text-align: left; min-width: 280px; }
#table-fonctions th:nth-child(2) { text-align: left; }
#table-fonctions td:nth-child(n+3),
#table-fonctions th:nth-child(n+3) { width: 1%; white-space: nowrap; }
#table-fonctions tr.ligne-fonction-selectionnee { background: rgba(22, 66, 60, 0.08); }
#table-fonctions tr.ligne-fonction-selectionnee td:nth-child(2) input { font-weight: 600; }

/* Interrupteurs compacts, identiques à ceux de Modes de paiement. */
#table-droits-fonction .interrupteur,
#table-fonctions .interrupteur { width: 32px; height: 17px; }
#table-droits-fonction .interrupteur-curseur::before,
#table-fonctions .interrupteur-curseur::before { height: 13px; width: 13px; left: 2px; bottom: 2px; }
#table-droits-fonction .interrupteur input:checked + .interrupteur-curseur::before,
#table-fonctions .interrupteur input:checked + .interrupteur-curseur::before { transform: translateX(15px); }

/* Boutons ↑ ↓ : même gabarit que .bouton-croix (carré 22x22px). */
.bouton-ordre-fonction {
  width: 22px; height: 22px; padding: 0; margin: 0 1px;
  border: 1px solid var(--couleur-bordure); border-radius: 4px; background: white;
  color: var(--couleur-texte); font-size: 0.8rem; line-height: 1; cursor: pointer;
}
.bouton-ordre-fonction:hover { background: var(--couleur-fond); border-color: var(--couleur-primaire-clair); }
.bouton-ordre-fonction:disabled { opacity: 0.35; cursor: not-allowed; }
.bouton-ordre-fonction:active { transform: none; }

.nom-fonction-avec-cadenas { display: flex; align-items: center; gap: 6px; }
.nom-fonction-avec-cadenas input { flex: 1; min-width: 0; }
.cadenas-fonction { font-size: 0.8rem; cursor: help; }

/* Vue d'ensemble : noms de Fonction cliquables dans l'en-tête, coches centrées. */
/* #table-synthese-statuts (27/09/2026, section 223) : vue d'ensemble des
   Statuts, même présentation que celle des Fonctions. */
#table-synthese-droits td:first-child,
#table-synthese-droits th:first-child,
#table-synthese-statuts td:first-child,
#table-synthese-statuts th:first-child { text-align: left; min-width: 260px; }
#table-synthese-droits td:not(:first-child),
#table-synthese-statuts td:not(:first-child) { text-align: center; color: #1B7F4C; font-weight: 700; }
.lien-fonction-synthese {
  background: none; border: none; padding: 0; margin: 0; font: inherit; color: inherit;
  text-transform: inherit; letter-spacing: inherit; cursor: pointer;
  text-decoration: underline; text-decoration-color: var(--couleur-texte-att);
}
.lien-fonction-synthese:hover { color: var(--couleur-primaire); }
.lien-fonction-synthese:active { transform: none; }

/* Affichage mobile (cartes) des petits tableaux de Configuration de saison
   ET de Gestion des droits (27/09/2026, lot 2 droits) : les règles PC
   ci-dessus donnent à certaines colonnes "width: 1%" (interrupteur,
   boutons) ou un min-width large (libellé) — sans effet gênant en tableau,
   mais en mode carte (voir .table-lignes dans le @media plus haut) la
   cellule ne mesurait plus que 1% de la carte, et l'interrupteur débordait
   à GAUCHE hors de la carte (visible sur Modes de paiement depuis le
   25/09/2026). Neutralisé ici, en fin de fichier pour passer après toutes
   les règles qu'il corrige ; le libellé de la dernière colonne ("Actif",
   "Accordé") est aligné à gauche et l'interrupteur à droite. */
@media (max-width: 700px) {
  #liste-modes-paiement td, #liste-modes-paiement th,
  #table-autres-prestations td, #table-autres-prestations th,
  #table-droits-fonction td, #table-droits-fonction th,
  #table-fonctions td, #table-fonctions th,
  #table-synthese-droits td, #table-synthese-droits th,
  #table-synthese-statuts td, #table-synthese-statuts th {
    width: auto !important;
    min-width: 0 !important;
    white-space: normal;
    text-align: left;
  }
  #liste-modes-paiement td:last-child[data-label],
  #table-droits-fonction td:last-child[data-label] {
    justify-content: space-between;
    align-items: center;
  }
  #table-fonctions td[data-label="Ordre"],
  #table-fonctions td[data-label="Active"],
  #table-fonctions td[data-label="Saison active"] {
    flex-direction: row;
    align-items: center;
    gap: 8px;
  }
  #table-fonctions td[data-label="Ordre"]::before,
  #table-fonctions td[data-label="Active"]::before,
  #table-fonctions td[data-label="Saison active"]::before { min-width: 110px; }
  #table-synthese-droits td:not(:first-child),
  #table-synthese-statuts td:not(:first-child) {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
  }
  .table-scroll-droits, .table-scroll-fonctions, .table-scroll-etroit { max-width: none; }
  .nom-fonction-avec-cadenas { width: 100%; }
}

/* Gestion des droits (27/09/2026, retour de Bruno) : sélecteur de
   Fonction placé dans le bloc "Droits de la Fonction", libellé au-dessus. */
.selecteur-droits { margin: 2px 0 12px; max-width: 560px; }
.libelle-selecteur-droits { display: block; font-size: 0.85rem; font-weight: 600; margin-bottom: 4px; }

/* ---------------------------------------------------------------------
   Ligne de titres de colonnes figée au défilement, PC ET téléphone,
   façon volets figés Excel — 27/09/2026 sur téléphone (SYNTHESE section
   221), étendu au PC le 29/09/2026 (demande de Bruno, section 236).
   - .table-scroll-entete-figee : le conteneur du tableau prend au plus la
     hauteur visible sous les bandeaux figés (bandeau du site + écart +
     bandeau de titre de page, --decalage-haut-tableau mesurée par
     ajusterTableauxEnteteFigee() dans assets/entete.js) et défile
     lui-même dans les 2 sens : la ligne de titres (sticky top:0 dans ce
     conteneur) reste visible, la barre de défilement horizontale aussi.
     Plusieurs tableaux l'un sous l'autre : chacun a son propre conteneur,
     donc la ligne de titres visible est celle du tableau affiché. Un
     tableau plus court que l'écran garde sa hauteur naturelle.
   - .entete-figee-pc-seulement : tableaux .table-lignes, présentés en
     cartes sous 700 px (plus de ligne de titres) — pas de hauteur
     limitée sur téléphone.
   - z-index : titres au-dessus des cellules figées du corps (6), coin
     n° de ligne au-dessus de tout. top:-1px + ombre vers le haut :
     supprime le liseré d'1 à 2 px où le texte des lignes défilées restait
     visible au-dessus de l'en-tête (arrondi de position des cellules
     sticky en tableau border-collapse) ; si la page a défilé au-delà du
     haut d'un tableau (tableau suivi d'autres contenus), sa ligne de
     titres est décalée d'autant pour rester sous les bandeaux tant que le
     tableau est visible ; ombre intérieure en bas : la
     bordure basse de l'en-tête (qui ne suit pas une cellule sticky en
     border-collapse) reste visible au défilement.
   - .panneau-filtre-mobile : le panneau de tri/filtre de colonne s'ouvre
     en tiroir pleine largeur en bas de l'écran, cibles tactiles agrandies.
   --------------------------------------------------------------------- */
.titre-panneau-filtre { display: none; }
.table-scroll-entete-figee {
  max-height: calc(100dvh - var(--decalage-haut-tableau, 200px));
  overflow: auto;
}
.table-scroll-entete-figee thead th {
  position: sticky;
  z-index: 7;
  /* --decalage-entete-sticky : voir suivreEntetesTableauxAuDefilement()
     dans assets/entete.js (tableau dont le haut est passé sous les
     bandeaux, la ligne de titres descend d'autant). */
  top: calc(var(--decalage-entete-sticky, 0px) - 1px);
  box-shadow: 0 -2px 0 #EEF0EA, inset 0 -1px 0 var(--couleur-bordure);
}
.table-scroll-entete-figee thead th.entete-colonne-figee { z-index: 8; }
#table-disciplines-config th,
#table-durees th { box-shadow: 0 -2px 0 #E2E6DC, inset 0 -1px 0 var(--couleur-bordure); }
@media (max-width: 700px) {
  .table-scroll-entete-figee.entete-figee-pc-seulement { max-height: none; }
  /* 29/09/2026 (retour de Bruno, SYNTHESE section 241) : le bouton de
     32 px dépassait de la ligne de titres (27,5 px), visible depuis son
     fond bleu de colonne filtrée (§240) — ligne de titres un peu plus
     haute (plus facile à toucher), bouton de 28 px qui y tient, et 8 px
     d'écart entre le nom de la colonne et le bouton. */
  .table-scroll-entete-figee thead th.entete-triable { padding-top: 8px; padding-bottom: 8px; padding-right: 42px !important; }
  .table-scroll-entete-figee .bouton-menu-colonne { width: 30px; height: 28px; right: 4px; }

  .panneau-filtre-colonne.panneau-filtre-mobile {
    left: 0 !important; right: 0; top: auto !important; bottom: 0;
    min-width: 0; max-height: 85dvh; overflow-y: auto; box-sizing: border-box;
    border-radius: 14px 14px 0 0;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px));
    box-shadow: 0 -6px 24px rgba(0, 0, 0, 0.25);
  }
  .panneau-filtre-mobile .titre-panneau-filtre {
    display: block; margin: 0 0 6px; font-weight: 700; font-size: 1rem;
  }
  .panneau-filtre-mobile .ligne-intervalle-filtre { font-size: 0.95rem; }
  .panneau-filtre-mobile .champ-intervalle-filtre { font-size: 1rem !important; padding: 8px; width: 90px; }
  .panneau-filtre-mobile .champ-intervalle-filtre[type="date"] { width: auto; flex: 1 1 0; }
  .panneau-filtre-mobile .bouton-raccourci-filtre { font-size: 0.9rem !important; padding: 7px 12px !important; }
  .panneau-filtre-mobile .bouton-supprimer-filtre-colonne { padding: 10px 12px !important; font-size: 0.95rem !important; }
  .panneau-filtre-mobile .champ-recherche-filtre { font-size: 1rem; padding: 9px 10px; }
  .panneau-filtre-mobile .case-filtre-colonne { font-size: 0.95rem; padding: 7px 0; }
  .panneau-filtre-mobile .case-filtre-colonne input { width: 20px; height: 20px; }
  .panneau-filtre-mobile .panneau-filtre-liste { max-height: 38dvh; }
  .panneau-filtre-mobile .bouton-valider-filtre,
  .panneau-filtre-mobile .bouton-annuler-filtre { padding: 10px 22px !important; font-size: 0.95rem !important; }
}

/* ---------------------------------------------------------------------
   Menus ☰ sur téléphone — espacés et homogènes (27/09/2026, demande de
   Bruno, SYNTHESE section 223 : "veiller à respecter les mises en page de
   page en page"). S'applique à TOUS les menus déroulants mobiles :
   - le menu principal du site (.nav-app) ;
   - les menus d'actions des bandeaux de page (.menu-actions-fiche) :
     Formulaire, Configuration de saison, Gestion des droits, Cours des
     élèves, Liste adhérents — et toute future page qui reprend ces classes.
   Même largeur, même marge intérieure, même espacement entre les items,
   items de 44 px de haut (cible tactile confortable), même taille de
   texte, alignés à gauche. Les couleurs de sens (vert Enregistrer, rouge
   Supprimer, gris clair pour les autres) sont conservées.
   Placé en fin de fichier pour l'emporter sur les règles compactes PC
   (.bouton-secondaire.bouton-action-fiche etc., même spécificité).
   --------------------------------------------------------------------- */
@media (max-width: 700px) {
  .nav-app,
  .menu-actions-fiche {
    min-width: 250px;
    max-width: calc(100vw - 28px);
    padding: 8px;
    gap: 6px;
  }
  /* Menu du site (27/09/2026, retour de Bruno) : 1,5 fois la largeur des
     menus de page (250 px -> 375 px) pour bien les distinguer, dans la
     limite de l'écran ; même bord droit (14 px) que les menus de page. */
  .nav-app { min-width: min(375px, calc(100vw - 28px)); right: 14px; }
  /* Bouton ☰ du site aligné à droite exactement comme les boutons ☰ des
     pages (27/09/2026, retour de Bruno) : le bandeau du site avait 24 px
     de marge latérale, les bandeaux de page 14 px — le bouton du site
     paraissait décalé de 10 px vers la gauche. */
  .barre-app { padding-left: 14px; padding-right: 14px; }
  .nav-app a,
  .menu-actions-fiche .bouton-action-fiche {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 8px;
    min-height: 44px;
    box-sizing: border-box;
    padding: 10px 14px;
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.2;
    border-radius: 6px;
    text-align: left;
    white-space: nowrap; /* une ligne par item ; le menu s'élargit au besoin */
  }
  .menu-actions-fiche .bouton-action-fiche[hidden] { display: none; }
  /* Séparateurs : même trait, même respiration dans les deux menus. */
  .separateur-menu-actions-fiche { margin: 2px 4px; }
  .nav-app .lien-deconnexion-nav { margin-top: 2px; border-top: none; position: relative; }
  .nav-app .lien-deconnexion-nav::before {
    content: ''; position: absolute; left: 4px; right: 4px; top: -4px;
    height: 1px; background: rgba(255,255,255,0.25);
  }
  /* "Enregistrer" pas encore utile (rien de modifié) : même gris que
     celui de Formulaire (#bouton-enregistrer), au lieu du vert à 45 %
     d'opacité, presque invisible sur le fond sombre du menu. */
  .menu-actions-fiche .bouton-principal.bouton-non-modifie {
    opacity: 1; background: #9CA3AF; color: white;
  }
}

/* ---------------------------------------------------------------------
   Débordements horizontaux sur téléphone de 360 px (27/09/2026, relevés
   lors de la vérification des menus ☰ — SYNTHESE section 224) :
   - Configuration de saison : le bandeau "⚠️ N inscription(s) déjà
     enregistrée(s)" (flex: 0 0 auto, voir .ligne-select-saison) ne
     pouvait ni rétrécir ni passer à la ligne : la page débordait de 3 px.
   - Paramètres : dans .grille-2 (1fr 1fr), la largeur minimale d'un champ
     empêchait la colonne de rétrécir (page large de 509 px sur un écran
     de 360). minmax(0, 1fr) ne change rien tant qu'il y a la place.
   --------------------------------------------------------------------- */
.ligne-select-saison .bandeau-saison-inactive,
.ligne-select-saison .bandeau-saison-a-risque { flex-shrink: 1; max-width: 100%; box-sizing: border-box; }
.grille-2 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.grille-2 input, .grille-2 select { max-width: 100%; box-sizing: border-box; }
/* Messages d'aide / d'erreur : un mot très long (adresse, chemin, lien)
   passe à la ligne au lieu d'élargir la page sur téléphone. */
.aide-champ, .message-erreur, .message-succes { overflow-wrap: break-word; }

/* ---------------------------------------------------------------------
   Bandeau du site masqué au défilement sur téléphone (27/09/2026, demande
   de Bruno — SYNTHESE section 225) : classe posée sur <html> par
   initialiserMasquageBandeauMobile() (assets/entete.js), qui remet aussi
   --hauteur-bandeau-app à 0 pour que le bandeau de titre de la page
   remonte en haut de l'écran. Transform uniquement à l'état masqué (un
   transform permanent changerait le repère du menu ☰ du site, en
   position fixed à l'intérieur du bandeau).
   Environnement de TEST : le bandeau rayé cesse d'être collant pendant ce
   masquage, sinon il recouvrirait le titre de la page.
   --------------------------------------------------------------------- */
@media (max-width: 700px) {
  .barre-app { transition: transform 0.2s ease; }
  html.bandeau-app-masque .barre-app { transform: translateY(-100%); }
  .entete-liste, .bandeau-fiche { transition: top 0.2s ease; }
  html.bandeau-app-masque .bandeau-environnement-test { position: relative; }
}

/* ---------------------------------------------------------------------
   Formulaire en consultation seule (28/09/2026, lot 3 droits — SYNTHESE
   section 226) : classe posée sur <body> par appliquerModeLectureSeule()
   (assets/formulaire.js). Les boutons de modification disparaissent
   (!important : d'autres fonctions les ré-affichent au fil du
   chargement d'une fiche) ; les champs sont grisés par le fieldset
   #verrou-saison-precedente.
   --------------------------------------------------------------------- */
body.formulaire-lecture-seule #bouton-enregistrer,
body.formulaire-lecture-seule #bouton-vider,
body.formulaire-lecture-seule #bouton-supprimer,
body.formulaire-lecture-seule #bouton-dupliquer,
body.formulaire-lecture-seule #bouton-reinscrire,
body.formulaire-lecture-seule #bouton-valider-definitif,
body.formulaire-lecture-seule .separateur-menu-actions-fiche { display: none !important; }
.bandeau-lecture-seule {
  margin: 0 0 10px; padding: 8px 12px; border-radius: 6px;
  background: #E8F0F7; color: #1F4E79; border: 1px solid #B7CDE3;
  font-size: 0.85rem; font-weight: 600;
}
body.formulaire-sans-actions #bouton-actions-fiche { display: none !important; }

/* Cours des élèves : Groupe modifiable par un professeur (28/09/2026,
   lot 3 droits — voir assets/cours_eleves.js). */
.table-adherents .input-groupe-cours { width: 9em; max-width: 100%; padding: 2px 6px; font-size: 0.82rem; height: auto; min-height: 0; line-height: 1.3; box-sizing: border-box; }
.input-groupe-cours.input-groupe-enregistre { border-color: #1B7F4C; box-shadow: 0 0 0 2px rgba(27, 127, 76, 0.2); }

/* Mon formulaire (espace personnel), fiche Administratif (28/09/2026,
   lot 4) : rappel que seul l'administrateur modifie les Fonctions / types
   de cours enseignés. */
.message-seul-admin { margin: -4px 0 12px; font-style: italic; }

/* ---------------------------------------------------------------------
   Page d'accueil unique (28/09/2026, lot 4 droits — SYNTHESE section 229) :
   deux parties de tuiles, « Mon espace » puis « Gestion » (décision de
   Bruno), mêmes cartes que l'ancien Tableau de bord.
   --------------------------------------------------------------------- */
.section-accueil + .section-accueil { margin-top: 22px; }
.titre-section-accueil {
  margin: 0 0 10px; font-size: 0.8rem; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--couleur-texte-att);
}
.description-carte-accueil { flex: 1; display: flex; flex-direction: column; gap: 4px; }
.description-carte-accueil p { margin: 0; }
/* Les deux parties alignées à gauche, sous leur titre (sinon une partie
   d'une seule tuile se retrouvait centrée, décalée par rapport à l'autre). */
.section-accueil .grille-tableau-bord { justify-content: start; }
/* Téléphone : une tuile par ligne, sur toute la largeur. */
@media (max-width: 700px) {
  .section-accueil .grille-tableau-bord { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------
   Page Paramètres — harmonisation (28/09/2026, retour de Bruno, SYNTHESE
   section 235 : "débordements sur la droite au niveau de la sauvegarde
   de la base et quelques défauts d'alignement").
   - Cartes du bas (Drive, emails, sauvegarde, mode test) : même
     espacement que la liste des réglages (12px) et même retrait du texte
     (14px 16px) que les cartes à interrupteur.
   - Champs empilés (libellé au-dessus), même gabarit pour texte, email,
     mot de passe et nombre ; une seule colonne sur téléphone.
   - Boutons regroupés sur une ligne d'actions, espacement régulier.
   - Tableau des sauvegardes : le nom de fichier passe à la ligne, Date et
     Taille restent sur une ligne — plus de débordement sur téléphone.
   --------------------------------------------------------------------- */
.carte-parametre-bas { margin-top: 12px; }
.carte-parametre.carte-parametre-critique { display: block; padding: 14px 16px; }
.carte-parametre > .bouton-secondaire { flex-shrink: 0; white-space: nowrap; align-self: center; }
.grille-champs-parametre { margin: 14px 0 4px; gap: 12px 20px; }
.grille-champs-parametre label {
  display: flex; flex-direction: column; gap: 4px; margin: 0;
  font-size: 0.8rem; font-weight: 600; color: var(--couleur-texte-att);
}
.grille-champs-parametre input {
  width: 100%; box-sizing: border-box;
  font-family: var(--police-texte); font-size: 0.95rem; padding: 8px 10px;
  border: 1px solid var(--couleur-bordure); border-radius: 8px;
  background: white; color: var(--couleur-texte);
}
.actions-carte-parametre { display: flex; flex-wrap: wrap; gap: 10px; margin: 10px 0 6px; }
#sauvegarde-derniere { margin-top: 16px; }
.tableau-sauvegardes { margin-top: 12px; table-layout: auto; }
.tableau-sauvegardes td:first-child { overflow-wrap: anywhere; word-break: break-word; }
.tableau-sauvegardes td:nth-child(2), .tableau-sauvegardes td:nth-child(3),
.tableau-sauvegardes td:nth-child(4), .tableau-sauvegardes th { white-space: nowrap; }
@media (max-width: 600px) {
  .grille-champs-parametre { grid-template-columns: minmax(0, 1fr); }
  .tableau-sauvegardes { font-size: 0.76rem; }
  .tableau-sauvegardes th, .tableau-sauvegardes td { padding: 6px 4px; }
  .carte-parametre-bas:not(.carte-parametre-critique) { flex-wrap: wrap; }
}
