/* =========================================================================
   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: #F5F6F2;
  --couleur-surface: #FFFFFF;
  --couleur-primaire: #16423C;
  --couleur-primaire-clair: #1F5750;
  --couleur-accent: #C9A227;
  --couleur-accent-clair: #E4C860;
  --couleur-texte: #1B2420;
  --couleur-texte-att: #5B6660;
  --couleur-bordure: #E1E4DD;
  --couleur-erreur: #B3261E;
  --couleur-erreur-fond: #FBEAEA;

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

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

.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"] {
  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;
}

/* ---------------------------------------------------------------------
   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;
  top: 0;
  z-index: 10;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 18px;
  row-gap: 10px;
  padding: 14px 24px;
  background: var(--couleur-primaire);
  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; }

.barre-app .logo-app {
  font-family: var(--police-affichage);
  font-weight: 600;
  font-size: 1.1rem;
}

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

.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 {
  max-width: 1100px;
  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: flex; flex-wrap: wrap; align-items: center; gap: 4px; row-gap: 4px; max-width: 100%; min-width: 0; }
.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; }

/* 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: center; padding: 6px 9px; }
.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: none; }
/* 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: none; }

/* Bouton "menu" (hamburger), mobile uniquement — voir @media plus bas.
   Masqué par défaut : sur PC, la nav reste affichée en ligne comme avant. */
.bouton-menu-mobile {
  display: none;
  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;
  max-width: 160px;
}
.bouton-menu-mobile span {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bouton-menu-mobile svg { flex-shrink: 0; }
.bouton-menu-mobile:hover { background: rgba(255,255,255,0.1); }

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

/* flex: 1 absorbe tout l'espace disponible entre le groupe de gauche et le
   groupe de droite — c'est ce qui pousse naturellement le bouton "Nouvel
   adhérent" et les infos utilisateur contre le bord droit, sans avoir besoin
   de justify-content sur le conteneur parent. max-width évite qu'elle ne
   s'étire de façon disproportionnée sur un très grand écran. */
.recherche-globale { position: relative; flex: 1; max-width: 320px; }
.recherche-globale input {
  width: 100%;
  padding: 7px 12px 7px 32px;
  border-radius: 6px;
  border: 1px solid rgba(255,255,255,0.3);
  background: rgba(255,255,255,0.14);
  color: white;
  font-size: 0.85rem;
  font-family: var(--police-texte);
}
.recherche-globale input::placeholder { color: rgba(255,255,255,0.65); }
.recherche-globale input:focus {
  background: white;
  color: var(--couleur-texte);
  outline: none;
  border-color: white;
}
.recherche-globale .icone-loupe {
  position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  color: rgba(255,255,255,0.75); pointer-events: none;
}
.recherche-globale:focus-within .icone-loupe { color: var(--couleur-texte-att); }

/* Réutilise le style de .liste-suggestions (dropdowns de recherche du
   formulaire) pour la cohérence visuelle — voir plus bas dans ce fichier.
   Correctif du 30/08/2026 : sans cette ligne, le texte (prénom/nom) hérite
   du "color: white" de .barre-app et devient invisible sur le fond blanc du
   dropdown — seul le sous-titre restait visible car lui fixait déjà sa
   propre couleur via .suggestion-details. */
.recherche-globale .liste-suggestions { top: calc(100% + 4px); color: var(--couleur-texte); }
.recherche-globale .suggestion-vide { padding: 7px 9px; font-size: 0.85rem; color: var(--couleur-texte-att); }
.recherche-globale .suggestion-details { display: block; font-size: 0.72rem; color: var(--couleur-texte-att); }

/* 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 / .recherche-globale / .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. Ce qui suit ne fait qu'améliorer la mise en page une fois le
   wrap actif : la recherche prend sa propre ligne pleine largeur (plus
   lisible qu'une largeur minimale écrasée), et le nom/rôle affiché
   ("Administrateur · admin") est masqué faute de place — le bouton
   "Se déconnecter" seul suffit à cette largeur. */
@media (max-width: 780px) {
  .recherche-globale { order: 3; flex-basis: 100%; max-width: none; }
  .infos-utilisateur #nom-utilisateur { display: none; }
}

/* ---------------------------------------------------------------------
   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) {
  .bouton-menu-mobile {
    display: inline-flex;
    /* position:absolute avec right identique au padding droit de .barre-app
       (24px) — aligne exactement sur le bord droit de .recherche-globale en
       dessous (flex-basis:100%, bornée par ce même padding). Plus fiable
       qu'un margin-left:auto en layout flex multi-lignes avec order. */
    position: absolute;
    top: 14px;
    right: 24px;
  }
  .libelle-nav-mobile { display: inline; margin-left: 8px; }
  /* position:fixed (plutôt qu'absolute) : nav-app reste dans .barre-app-gauche
     dans le DOM (pour ne rien changer à l'affichage PC, où il s'affiche en
     ligne à côté du logo comme avant) mais le bouton qui l'ouvre est
     maintenant à droite du bandeau — fixed, ancré au viewport via
     --hauteur-bandeau-app (même variable que .bandeau-fiche), permet de
     l'ouvrir sous CE bouton indépendamment de sa position réelle dans le DOM. */
  .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-primaire);
    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-icone-accueil { justify-content: flex-start; padding: 9px 12px; }
  /* "Se déconnecter" rejoint le menu mobile (31/08/2026, sur demande de
     Bruno) — le bouton autonome du bandeau (.infos-utilisateur) devient
     redondant dès que le menu hamburger apparaît, donc masqué ici. Léger
     séparateur au-dessus pour le distinguer visuellement des liens de
     navigation qui le précèdent dans le menu. */
  .infos-utilisateur #bouton-deconnexion { display: none; }
  .lien-deconnexion-nav {
    display: block;
    margin-top: 4px;
    padding-top: 13px;
    border-top: 1px solid rgba(255,255,255,0.15);
  }

  /* "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; }
}

/* ---------------------------------------------------------------------
   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: 980px;
  margin: 14px auto;
  padding: 0 14px 30px;
}

.contenu-liste-adherents {
  max-width: 820px;
  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; }

/* 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). */
.entete-liste {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  background: var(--couleur-primaire);
  border-radius: 8px 8px 0 0;
}
.entete-liste h1 {
  font-family: var(--police-texte);
  font-weight: 700;
  color: white;
  margin: 0;
  font-size: 1.15rem;
}
.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;
}
.filtres-liste .case-filtre {
  font-size: 0.78rem;
  color: var(--couleur-texte-att);
  padding: 2px 2px 0;
}

.table-scroll { max-height: 66vh; overflow: auto; border: 1px solid var(--couleur-bordure); border-radius: 6px; }

.table-adherents { 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; }
.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; }
.etat-vide { text-align: center; color: var(--couleur-texte-att); padding: 20px 10px; font-size: 0.85rem; }

/* Rendu tactile de la liste (tablette/smartphone), 30/08/2026 — voir
   SYNTHESE section 9. Générées à partir des MÊMES données que le tableau
   ci-dessus (assets/liste_adherents.js remplit les deux en une passe) ;
   seul le basculement ci-dessous décide laquelle des deux s'affiche. On
   croise la largeur d'écran ET le type de pointeur : une tablette tactile en
   mode paysage peut avoir une largeur proche d'un PC portable, mais reste un
   usage au doigt qui a besoin de cibles larges — d'où (pointer: coarse) en
   plus du seuil de largeur, plutôt qu'un seul @media (max-width). */
.liste-cartes-adherents { display: none; flex-direction: column; gap: 8px; }
.carte-adherent {
  border: 1px solid var(--couleur-bordure);
  border-radius: 8px;
  padding: 12px 14px;
  min-height: 44px; /* cible tactile confortable, voir principe déjà appliqué au bouton-nouveau-bandeau */
  background: var(--couleur-surface);
  cursor: pointer;
}
.carte-adherent:active { background: #EFF3EC; }
.carte-adherent.carte-payeur-a-preciser { box-shadow: inset 3px 0 0 var(--couleur-accent); }
.carte-adherent-ligne1 { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.carte-adherent-nom { font-weight: 700; font-size: 0.92rem; }
.carte-adherent-montant { font-size: 0.85rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.carte-adherent-details { margin: 4px 0 0; font-size: 0.78rem; color: var(--couleur-texte-att); }

@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. */
  .panneau-liste .table-scroll { display: none; }
  .liste-cartes-adherents { display: flex; }
}

/* 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: #FCFCFA;
}
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;
}

/* 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;
  top: var(--hauteur-bandeau-app, 52px);
  z-index: 6;
  box-shadow: 0 2px 8px rgba(27, 36, 32, 0.1);
}

.entete-formulaire {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 14px;
  background: var(--couleur-primaire);
  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; }

/* 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; }

/* 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; }

@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-primaire);
    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; }
}

/* Calculatrice de paiements (Total dû / Montant engagé / Total payé / Reste dû)
   — volontairement discrète, à la différence du bandeau flottant */
.recapitulatif-totaux {
  display: grid; grid-template-columns: repeat(4, 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; }
.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, 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;
}
/* 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,
.recherche-globale 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; }
.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); }

/* 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); }

/* 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-disciplines { min-width: 700px; }
#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; }
.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;
}
.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; }
.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-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-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 { background: #f6d8d6; }

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

/* ---------------------------------------------------------------------
   Page Import (import.php / import.js) — ajouté en v52. La mise en page
   (.contenu-import dédiée) a été retirée en v74 : la page réutilise
   maintenant .contenu-liste-adherents/.panneau-liste/.entete-liste/
   .corps-liste (homogénéisation du bandeau de titre demandée par Bruno,
   voir SYNTHESE section 9) — pas besoin de règles séparées.
   --------------------------------------------------------------------- */

.groupe-radio { display: flex; flex-direction: column; gap: 6px; margin-top: 4px; }

.recapitulatif-import {
  grid-template-columns: repeat(4, 1fr);
  margin-top: 4px;
}
@media (max-width: 720px) {
  .recapitulatif-import { grid-template-columns: repeat(2, 1fr); }
}

.titre-section-rapport {
  font-family: var(--police-texte);
  font-size: 0.85rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin: 18px 0 8px;
}
.titre-section-rapport.titre-erreur { color: var(--couleur-erreur); }
.titre-section-rapport.titre-avertissement { color: #8A5A00; }

/* Purge des adhérents avant import (ajouté 29/08/2026) */
.bloc-purge-avant {
  margin-top: 14px;
  padding: 10px 12px;
  border: 1px solid var(--couleur-erreur);
  border-radius: 8px;
  background: var(--couleur-erreur-fond);
}
.bloc-purge-avant .case-a-cocher { font-weight: 600; color: var(--couleur-erreur); }
.bloc-purge-avant .aide-avertissement { margin: 6px 0 0; color: var(--couleur-erreur); }
#rapport-section-purge {
  padding: 10px 12px;
  border: 1px solid var(--couleur-erreur);
  border-radius: 8px;
  background: var(--couleur-erreur-fond);
  margin-bottom: 10px;
}
#rapport-purge-titre { margin-top: 0 !important; color: var(--couleur-erreur) !important; }

.liste-rapport {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 0.85rem;
}
.liste-rapport li {
  padding: 8px 10px;
  border-radius: 6px;
  border: 1px solid var(--couleur-bordure);
}
.liste-rapport-erreur li {
  background: var(--couleur-erreur-fond);
  border-color: rgba(179,38,30,0.25);
  color: var(--couleur-erreur);
}
.liste-rapport-avertissement li {
  background: #FDF6E3;
  border-color: #E9CE8A;
  color: #6B4A00;
}

/* ---------------------------------------------------------------------
   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) {
  .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;
  }
  .entete-formulaire, .entete-liste {
    background: var(--couleur-primaire-clair);
  }

  /* 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; }

  /* ---------------------------------------------------------------------
     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-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;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    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);
    flex-shrink: 0;
    width: 100px;
  }
  .table-lignes td select,
  .table-lignes td input:not([type="checkbox"]) {
    flex: 1;
    min-width: 0;
    width: auto;
  }
  /* 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 {
    justify-content: flex-end;
    padding-top: 8px;
    margin-top: 4px;
    border-top: 1px solid var(--couleur-bordure);
  }
}
