/* Jetons de design — vacances-comptes (spec Phase 1 §4, Partie 2).
   Registre Apple/Notion : neutre, un seul accent, bordures fines, ombres
   absentes ou imperceptibles. Point de rupture unique à 720px, mêmes
   gabarits pour toutes les tailles — jamais de feuille mobile séparée. */

:root {
  /* Police : pile système, rien à télécharger */
  --police: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* Neutres */
  --gris-000: #ffffff;
  --gris-050: #fafafa;
  --gris-100: #f2f2f2;
  --gris-300: #d8d8d8;
  --gris-500: #8a8a8a;
  --gris-700: #4a4a4a;
  --gris-900: #1c1c1c;

  /* Accent — SEUL endroit où ce hex apparaît dans ce fichier (voir
     tests/test_web_css.py::test_accent_hex_apparait_une_seule_fois).
     Tout le reste en dérive via var(--accent) : changer d'accent reste une
     modification d'une ligne. */
  --accent: #2f7d6e;
  --accent-texte: #ffffff;
  --accent-surface: color-mix(in srgb, var(--accent) 14%, var(--gris-000));
  /* Plus dilué que --accent-surface, et c'est la condition pour que la
     pastille du foyer COURANT (qui, elle, est en --accent-surface) reste
     visible posée dessus. La bande dit « nouveau groupe », pas « c'est
     toi » : deux messages, deux intensités. */
  --accent-bande: color-mix(in srgb, var(--accent) 6%, var(--gris-000));

  /* Sémantique — couleurs de TEXTE uniquement, jamais un aplat. Le signe
     ("+"/"−") porte l'information autant que la teinte. */
  --texte-creancier: #2f7d55;
  --texte-debiteur: #b3432b;
  --texte-anomalie: #b3432b;

  /* Bordures, rayons, ombres */
  --bordure: 0.5px solid var(--gris-300);
  --rayon: 10px;
  --rayon-lg: 12px;
  --ombre: none;

  /* Échelle typographique (px) */
  --taille-micro: 11px;
  --taille-petite: 12px;
  --taille-corps-sm: 13px;
  --taille-corps: 14px;
  --taille-corps-lg: 15px;
  --taille-titre: 24px;
  --taille-hero: 38px;

  /* Espacement */
  --espace-1: 4px;
  --espace-2: 8px;
  --espace-3: 12px;
  --espace-4: 16px;
  --espace-5: 24px;
  --espace-6: 32px;

  /* Tactile */
  --cible-min: 44px;
}

* {
  box-sizing: border-box;
}

/* `hidden` doit GAGNER, toujours. L'attribut ne pose que `display: none`
   dans la feuille du navigateur : n'importe quelle règle d'auteur qui donne
   un `display` à l'élément l'emporte, et l'élément reste visible pendant
   que le code le croit caché. Vécu sur le panneau des concernés — le JS
   masquait les exemptés des autres comptes, `.concernes-exemptes` était en
   `display: flex`, et l'écran proposait de cocher des cases sans effet.
   `!important` est ici à sa place : c'est l'attribut du DOM qui doit primer
   sur la mise en page, jamais l'inverse. */
[hidden] {
  display: none !important;
}

/* Icônes Lucide, inlinées côté serveur (voir web/icones.py). Elles
   n'apportent aucune couleur : `stroke: currentColor` les fait hériter du
   texte qui les entoure — accent, gris, ou --texte-anomalie. Aucun jeton
   de couleur importé d'ailleurs. La taille suit la typographie (1em), donc
   une icône ne dépasse jamais le texte auquel elle est accolée. */
.icone {
  width: 1em;
  height: 1em;
  flex: 0 0 auto;
  vertical-align: -0.125em;
}

/* Les icônes de compte portent l'essentiel du repérage sur l'écran le plus
   dense (liste des dépenses). Taille FIXE, pas relative : accolées à une
   étiquette de 11px en capitales, 1em donnait un verre à pied illisible.
   15px reste lisible partout, y compris dans les en-têtes de colonnes du
   tableau de bord. */
.icone-compte {
  width: 15px;
  height: 15px;
}

body {
  margin: 0;
  font-family: var(--police);
  font-size: var(--taille-corps-lg);
  color: var(--gris-900);
  background: var(--gris-050);
}

h1 {
  font-size: var(--taille-titre);
  margin: 0 0 var(--espace-4);
}

h2 {
  font-size: var(--taille-corps-lg);
  margin: var(--espace-5) 0 var(--espace-3);
}

/* Boutons — un seul accent (voir --accent ci-dessus), jamais un deuxième
   dérivé pour le bouton secondaire : il se distingue par la bordure, pas
   par une nouvelle teinte. */

.bouton-principal {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--espace-2);
  min-height: var(--cible-min);
  padding: var(--espace-2) var(--espace-4);
  background: var(--accent);
  color: var(--accent-texte);
  border: none;
  border-radius: var(--rayon);
  font-family: inherit;
  font-size: var(--taille-corps-lg);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}

.bouton-principal:hover,
.bouton-principal:focus-visible {
  opacity: 0.9;
  outline: none;
}

.bouton-secondaire {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--cible-min);
  padding: var(--espace-2) var(--espace-4);
  background: var(--gris-000);
  color: var(--gris-900);
  border: var(--bordure);
  border-radius: var(--rayon);
  font-family: inherit;
  font-size: var(--taille-corps);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}

.bouton-secondaire:hover,
.bouton-secondaire:focus-visible {
  border-color: var(--accent);
  outline: none;
}

.liste-vide {
  color: var(--gris-500);
  font-style: italic;
}

/* En-tête et navigation principale (Phase 2A, Partie 4) */

.entete {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-3);
  padding: var(--espace-3) var(--espace-4);
  background: var(--gris-000);
  border-bottom: var(--bordure);
}

.entete-droite {
  display: flex;
  align-items: center;
  gap: var(--espace-2);
}

.entete-sejour {
  font-size: var(--taille-corps);
  font-weight: 600;
  color: var(--gris-700);
}

.entete-foyer {
  display: flex;
  align-items: center;
  gap: var(--espace-2);
  text-decoration: none;
  color: var(--gris-900);
  min-height: var(--cible-min);
  padding: var(--espace-1) var(--espace-2);
  border-radius: var(--rayon);
}

.entete-foyer-nom {
  font-size: var(--taille-corps);
  font-weight: 600;
}

.entete-changer {
  font-size: var(--taille-micro);
  color: var(--gris-500);
}

.entete-parametres {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-2);
  min-height: var(--cible-min);
  padding: var(--espace-1) var(--espace-2);
  border-radius: var(--rayon);
  color: var(--gris-700);
  text-decoration: none;
  font-size: var(--taille-corps);
  font-weight: 600;
}

.entete-parametres .icone {
  width: 20px;
  height: 20px;
}

.entete-parametres--actif {
  color: var(--accent);
  background: var(--accent-surface);
}

/* En étroit, l'engrenage porte seul l'entrée : « Paramètres » en toutes
   lettres ne tient pas à côté du nom du foyer sur 375px. Le libellé reste
   dans le DOM (clip, pas display:none) — un lecteur d'écran lit toujours
   « Paramètres », l'icône seule ne dit rien. */
.entete-parametres-nom {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Barre principale. Troisième enfant de .entete : passe à la ligne en
   étroit (flex-basis: 100%), rejoint la rangée en large. Les marges
   négatives font filer sa bordure jusqu'aux bords, malgré le padding
   horizontal de l'en-tête — sans elles le trait s'arrête 16px trop tôt et
   ressemble à une erreur. */
.nav-principale {
  order: 3;
  flex-basis: 100%;
  display: flex;
  /* Pas de gouttière en étroit : cinq entrées à parts égales occupent la
     largeur, et chaque part EST la zone tactile — l'espacement entre elles
     se prendrait sur le pouce, pas sur le vide. Le padding horizontal
     disparaît pour la même raison ; la bordure, elle, file toujours d'un
     bord à l'autre grâce aux marges négatives. */
  gap: 0;
  margin: var(--espace-3) calc(-1 * var(--espace-4)) calc(-1 * var(--espace-3));
  padding: 0;
  border-top: var(--bordure);
}

/* CINQ entrées sur une ligne de 375px : icône au-dessus d'un libellé court.
   Les quatre d'origine tenaient en toutes lettres ; « Participants » a fait
   casser la barre en deux lignes, et ces 49px de haut se payaient sur TOUS
   les écrans. Toujours pas de défilement horizontal : une entrée qui sort du
   cadre d'un conteneur défilant est invisible, et une navigation dont on
   ignore la fin n'est pas une navigation. */
.nav-lien {
  display: flex;
  flex: 1 1 0; /* cinq parts égales : la barre se répartit, elle ne se replie plus */
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-width: 0;
  min-height: var(--cible-min);
  padding: var(--espace-1) 2px;
  color: var(--gris-700);
  text-decoration: none;
  font-size: var(--taille-petite);
  font-weight: 600;
  text-align: center;
  box-shadow: inset 0 -2px 0 transparent;
}

.nav-lien-icone {
  width: 22px;
  height: 22px;
}

/* Le libellé LONG reste dans le DOM, hors de vue : l'icône et « Régler » ne
   disent pas à eux seuls « Règlement » à un lecteur d'écran. Le court, lui,
   est décoratif (aria-hidden dans le gabarit) — sans quoi chaque entrée
   serait annoncée deux fois. */
.nav-lien-long {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* L'accent signale la SÉLECTION — exactement son rôle dans le système
   (spec Phase 1, Partie 2). Le soulignement est posé en ombre intérieure
   pour qu'aucune ligne ne bouge entre l'état actif et l'inactif. */
.nav-lien--actif {
  color: var(--accent);
  box-shadow: inset 0 -2px 0 var(--accent);
}

.nav-lien:focus-visible,
.entete-parametres:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--rayon);
}

/* Onglets des quatre écrans de paramétrage. Enroulés sur deux lignes en
   étroit : « Comptes de dépenses » et « Foyers et participants » sont longs
   parce qu'ils doivent l'être (voir web/navigation.py). */
/* Le titre nomme la SECTION, l'onglet actif nomme l'écran : les deux ne
   disent jamais la même chose. La marge basse est resserrée parce qu'il est
   collé à ses onglets — c'est un en-tête en deux étages, pas deux blocs. */
.titre-parametres {
  margin-bottom: var(--espace-3);
}

.onglets {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-1) var(--espace-4);
  margin-bottom: var(--espace-5);
  border-bottom: var(--bordure);
}

.onglet {
  display: inline-flex;
  align-items: center;
  min-height: var(--cible-min);
  color: var(--gris-700);
  text-decoration: none;
  font-size: var(--taille-corps-sm);
  font-weight: 600;
  box-shadow: inset 0 -2px 0 transparent;
}

.onglet--actif {
  color: var(--accent);
  box-shadow: inset 0 -2px 0 var(--accent);
}

.onglet:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--rayon);
}

.contenu {
  padding: var(--espace-5) var(--espace-4);
  max-width: 640px;
  margin: 0 auto;
}

/* Pastille foyer : monogramme, jamais une couleur d'identité. Le seul
   traitement différencié est celui du foyer courant (surface, pas
   identité) — voir --accent-surface ci-dessus. */

.pastille-foyer {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  min-width: 36px;
  border-radius: 50%;
  border: var(--bordure);
  background: var(--gris-100);
  color: var(--gris-700);
  font-size: var(--taille-petite);
  font-weight: 700;
  letter-spacing: 0.02em;
}

.pastille-foyer--courant {
  background: var(--accent-surface);
  border-color: var(--accent);
  color: var(--gris-900);
}

/* Écran "qui es-tu" */

.grille-foyers {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--espace-3);
}

/* Créer son foyer quand il n'est pas dans la liste. SÉPARÉE par un trait et
   en retrait : présentée comme une ligne de plus de la grille, elle serait
   choisie par erreur — et se déclarer un foyer qui n'est pas le sien est
   exactement ce qu'on veut éviter. Le bouton est de CONTOUR
   (`bouton-secondaire`), jamais d'accent : l'accent appartient au geste
   principal de l'écran, qui est de se reconnaître dans la liste. */
.arrivant {
  margin-top: var(--espace-6);
  padding-top: var(--espace-5);
  border-top: var(--bordure);
}

.arrivant-question {
  margin: 0 0 var(--espace-3);
  font-size: var(--taille-corps-lg);
  font-weight: 600;
  color: var(--gris-900);
}

.form-arrivant {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--espace-3);
}

/* Le champ prend la largeur, le bouton reste à sa taille : une rangée souple
   qui mélange un élément extensible et un élément fixe DOIT pouvoir se
   replier, sinon elle écrase le premier (défaut vécu en Partie 4 sur la
   carte d'un foyer). */
.form-arrivant .champ-parametre {
  flex: 1 1 220px;
  min-width: 0;
}

/* Annoncer la suite : sans cette phrase, on ignore si l'opération prend dix
   secondes ou dix minutes, et c'est ce doute qui fait refermer l'onglet. */
.arrivant-suite {
  margin: var(--espace-3) 0 0;
  font-size: var(--taille-corps-sm);
  color: var(--gris-500);
}

.form-premier-foyer {
  display: flex;
  flex-direction: column;
  gap: var(--espace-4);
  max-width: 420px;
}

.bouton-foyer {
  display: flex;
  align-items: center;
  gap: var(--espace-3);
  min-height: 56px;
  padding: var(--espace-3) var(--espace-4);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon-lg);
  box-shadow: var(--ombre);
  font-family: inherit;
  font-size: var(--taille-corps-lg);
  color: var(--gris-900);
  cursor: pointer;
  text-align: left;
}

.bouton-foyer:hover,
.bouton-foyer:focus-visible {
  border-color: var(--accent);
  outline: none;
}

.bouton-foyer--courant {
  border-color: var(--accent);
}

.bouton-foyer-nom {
  font-weight: 600;
}

.accueil-foyer {
  font-size: var(--taille-corps-lg);
}

/* Tableau de bord (Partie 4) */

.actions-principales {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-3);
  margin-bottom: var(--espace-5);
}

.bandeau-anomalies {
  margin-bottom: var(--espace-5);
  padding: var(--espace-3) var(--espace-4);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
}

.bandeau-anomalies-titre {
  display: flex;
  align-items: flex-start;
  gap: var(--espace-2);
  margin: 0 0 var(--espace-2);
  font-weight: 600;
  color: var(--texte-anomalie);
}

.bandeau-anomalies-liste {
  margin: 0;
  padding-left: var(--espace-4);
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
}

.bandeau-anomalies-liste li {
  margin-bottom: var(--espace-1);
}

.bandeau-anomalies-liste a {
  color: var(--accent);
  font-weight: 600;
}

.position-personnelle {
  margin: var(--espace-2) 0 var(--espace-5);
}

.position-montant {
  font-size: var(--taille-hero);
  font-weight: 700;
  margin: 0;
}

.position-personnelle--creancier .position-montant {
  color: var(--texte-creancier);
}

.position-personnelle--debiteur .position-montant {
  color: var(--texte-debiteur);
}

.table-soldes-conteneur {
  overflow-x: auto;
  margin: var(--espace-4) 0;
}

.table-soldes {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--taille-corps);
}

.table-soldes th,
.table-soldes td {
  padding: var(--espace-2) var(--espace-3);
  text-align: right;
  border-bottom: var(--bordure);
}

.table-soldes th {
  font-size: var(--taille-petite);
  font-weight: 600;
  color: var(--gris-500);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.cellule-foyer,
.cellule-foyer-entete {
  text-align: left;
}

.cellule-foyer-contenu {
  display: flex;
  align-items: center;
  gap: var(--espace-2);
  min-height: var(--cible-min);
}

.cellule-foyer-nom {
  font-weight: 600;
}

.ligne-foyer--courant {
  background: var(--accent-surface);
}

/* Ligne du foyer courant : chaque cellule est enveloppée dans le MÊME lien
   (pas un <tr> transformé en <a>, invalide en HTML table) — l'effet perçu
   est celui d'une ligne entièrement cliquable, tout en restant une table
   valide et accessible. Le libellé "Voir mon détail" est un texte visible,
   jamais une zone cliquable muette (piège vécu : le bouton de saisie
   manquant sur ce même écran). */
.ligne-lien {
  display: block;
  color: inherit;
  text-decoration: none;
}

.ligne-lien:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.voir-detail {
  display: block;
  margin-top: 2px;
  font-size: var(--taille-micro);
  font-weight: 600;
  color: var(--accent);
}

.ligne-lien:hover .voir-detail,
.ligne-lien:focus-visible .voir-detail {
  text-decoration: underline;
}

.montant {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.colonne-solde-total {
  font-weight: 600;
}

.texte-creancier {
  color: var(--texte-creancier);
}

.texte-debiteur {
  color: var(--texte-debiteur);
}

/* Décomposition par compte : repliée en étroit (un seul solde par foyer),
   colonnes en large — voir le point de rupture unique ci-dessous. */
.colonne-compte {
  display: none;
}

.table-soldes tfoot .ligne-total td {
  font-weight: 700;
  border-top: 1.5px solid var(--gris-700);
  border-bottom: none;
}

.depense-totale {
  font-size: var(--taille-corps-lg);
  margin: var(--espace-5) 0 var(--espace-3);
}

.lien-discret {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-1);
  font-size: var(--taille-corps-sm);
  color: var(--gris-500);
}

.liens-pied {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-2) var(--espace-5);
}

.lien-desactive {
  cursor: default;
}

/* Formulaire de saisie (Partie 3, passe CSS rétroactive) — l'écran qui
   décide si les gens saisissent ou rouvrent Excel. Le montant domine :
   seul champ obligatoire, seul en gros, tout en haut. Le reste est
   secondaire, et le panneau "concernés" reste replié pour qu'une course
   normale tienne sans défiler. */

/* Écart resserré (16px, pas 24) : la cible est que montant + libellé +
   date + compte + payeur + bouton tiennent sur UN écran de téléphone
   (375x667) panneau replié — la saisie en dix secondes se joue là. */
.formulaire-depense {
  display: flex;
  flex-direction: column;
  gap: var(--espace-4);
}

/* Libellé et date côte à côte : deux champs courts qui n'ont aucune raison
   d'occuper deux rangées pleines. */
.rangee-champs {
  display: flex;
  gap: var(--espace-3);
}

.rangee-champs > * {
  flex: 1 1 0;
  min-width: 0;
}

.formulaire-depense fieldset {
  margin: 0;
  padding: 0;
  border: none; /* les bordures natives de fieldset cassent le registre sobre */
}

.etiquette {
  display: flex;
  align-items: center;
  gap: var(--espace-1);
  padding: 0;
  margin-bottom: var(--espace-1);
  font-size: var(--taille-petite);
  font-weight: 600;
  color: var(--gris-500);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.erreur {
  margin: 0;
  padding: var(--espace-3) var(--espace-4);
  border: var(--bordure);
  border-radius: var(--rayon);
  background: var(--gris-000);
  color: var(--texte-anomalie);
  font-weight: 600;
}

/* Confirmation de la saisie précédente, en rafale. HORS DU FLUX
   (position: fixed) : dans le flux, elle poussait "Ajouter et saisir la
   suivante" sous la ligne de flottaison — exactement le lien dont on a
   besoin pour enchaîner. Elle s'efface seule en CSS, sans JS. Couleur de
   texte, pas d'aplat (même règle que créancier/débiteur) : la teinte
   confirme, elle n'alerte pas. */
.confirmation {
  position: fixed;
  top: 72px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 10;
  margin: 0;
  padding: var(--espace-2) var(--espace-4);
  border: var(--bordure);
  border-left: 3px solid var(--texte-creancier);
  border-radius: var(--rayon);
  background: var(--gris-000);
  color: var(--texte-creancier);
  font-size: var(--taille-corps);
  font-weight: 600;
  white-space: nowrap;
  animation: confirmation-disparait 3.5s forwards;
}

@keyframes confirmation-disparait {
  0%, 78% { opacity: 1; }
  100% { opacity: 0; visibility: hidden; }
}

/* Mouvement réduit : elle reste affichée plutôt que de disparaître par une
   animation qu'on a demandé de ne pas jouer. Toujours hors du flux, donc
   sans effet sur la cible "un seul écran". */
@media (prefers-reduced-motion: reduce) {
  .confirmation {
    animation: none;
  }
}

/* Montant — la hiérarchie de l'écran tient dans ce bloc. */

.champ-montant {
  text-align: center;
}

.montant-saisie {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--espace-2);
  padding: var(--espace-2) var(--espace-4);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon-lg);
}

.montant-saisie:focus-within {
  border-color: var(--accent);
}

.montant-saisie input {
  width: 100%;
  max-width: 260px;
  padding: 0;
  border: none;
  outline: none;
  background: transparent;
  font-family: inherit;
  font-size: var(--taille-hero);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--gris-900);
  text-align: right;
}

.montant-saisie input::placeholder {
  color: var(--gris-300);
}

.montant-devise {
  font-size: var(--taille-titre);
  font-weight: 600;
  color: var(--gris-500);
}

/* Calculatrice — un auxiliaire de saisie, discret tant qu'on ne l'ouvre pas.
   Le bouton vit DANS le cadre du montant, à droite ; il ne prend pas la
   place du chiffre, qui reste ce qu'on lit en premier sur cet écran. */
.montant-calculatrice {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--cible-min);
  min-height: var(--cible-min);
  padding: 0;
  background: none;
  border: none;
  border-radius: var(--rayon);
  color: var(--gris-500);
  cursor: pointer;
}

.montant-calculatrice .icone {
  width: 22px;
  height: 22px;
}

.montant-calculatrice:hover,
.montant-calculatrice:focus-visible {
  color: var(--accent);
  outline: none;
}

.montant-calculatrice[aria-expanded="true"] {
  background: var(--accent-surface);
  color: var(--accent);
}

.pave-calculatrice {
  margin-top: var(--espace-2);
}

/* Quatre colonnes : les quatre opérateurs sur une rangée, C / ⌫ / = sur la
   suivante, « = » à cheval sur deux colonnes parce que c'est la touche qu'on
   vise sans regarder. */
.pave-touches {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--espace-2);
}

.pave-touche {
  min-height: var(--cible-min);
  padding: var(--espace-2);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
  font-family: inherit;
  font-size: var(--taille-corps-lg);
  font-weight: 600;
  color: var(--gris-900);
  cursor: pointer;
}

.pave-touche:hover,
.pave-touche:focus-visible {
  border-color: var(--accent);
  outline: none;
}

.pave-touche--commande {
  color: var(--gris-700);
}

.pave-touche--egal {
  grid-column: span 2;
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-texte);
}

/* « — » quand l'expression ne se lit pas. Couleur d'anomalie, en TEXTE. */
.pave-etat {
  margin: var(--espace-2) 0 0;
  min-height: 1em;
  text-align: center;
  font-size: var(--taille-corps-sm);
  font-weight: 600;
  color: var(--texte-anomalie);
}

/* Radios compte / payeur : l'input natif est masqué, c'est le label qui
   porte l'état. :checked doit se voir au premier coup d'œil — surface
   accentuée ET bordure accent, jamais la seule bordure. */

.segmente {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-2);
}

.segmente-option,
.pastille-option {
  position: relative;
  flex: 1 1 auto;
  cursor: pointer;
}

.segmente-option input,
.pastille-option input,
.concernes-foyer input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.segmente-option-texte {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--espace-1);
  min-height: var(--cible-min);
  padding: var(--espace-2) var(--espace-3);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
  font-size: var(--taille-corps);
  font-weight: 600;
  text-align: center;
}

.segmente-option input:checked + .segmente-option-texte,
.pastille-option input:checked + .pastille-option-contenu {
  background: var(--accent-surface);
  border-color: var(--accent);
}

.segmente-option input:focus-visible + .segmente-option-texte,
.pastille-option input:focus-visible + .pastille-option-contenu {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.rangee-pastilles {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-2);
}

.pastille-option {
  flex: 0 0 auto;
}

/* Pastille compacte ICI seulement : cinq foyers sur deux rangées coûtaient
   123px de haut, contre ~84 ainsi — la différence entre "tient sur un
   écran" et "il faut défiler". On laisse le retour à la ligne plutôt que
   de forcer une rangée unique, qui casserait dès que les vrais noms de
   famille remplaceront les codes F1..F5. La zone tactile reste à 44px via
   le padding vertical du label. */
.pastille-option-contenu {
  display: flex;
  align-items: center;
  gap: var(--espace-2);
  min-height: 38px;
  padding: var(--espace-1) var(--espace-3) var(--espace-1) var(--espace-1);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: 999px;
}

.rangee-pastilles .pastille-foyer {
  width: 30px;
  height: 30px;
  min-width: 30px;
}

.pastille-option-nom {
  font-size: var(--taille-corps);
  font-weight: 600;
}

/* Panneau "concernés" : replié, résumé en une ligne cliquable. */

.champ-concernes {
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
}

.concernes-resume {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-3);
  min-height: var(--cible-min);
  padding: var(--espace-2) var(--espace-4);
  cursor: pointer;
  list-style: none; /* le triangle natif est remplacé par .concernes-chevron */
  font-size: var(--taille-corps);
}

.concernes-resume::-webkit-details-marker {
  display: none;
}

.concernes-resume:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-radius: var(--rayon);
}

.concernes-chevron {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-right: 1.5px solid var(--gris-500);
  border-bottom: 1.5px solid var(--gris-500);
  transform: rotate(-45deg);
  transition: transform 0.15s ease;
}

.champ-concernes[open] .concernes-chevron {
  transform: rotate(45deg);
}

.concernes-aide {
  margin: 0;
  padding: 0 var(--espace-4) var(--espace-2);
  font-size: var(--taille-corps-sm);
  color: var(--gris-500);
}

/* Une ligne par FOYER (Phase 2A, Partie 2). Le pavé de dix-huit cases a
   disparu : cinq lignes tiennent sans défilement sur 375px, ce que le
   sélecteur par participant ne faisait pas. */

.concernes-foyers {
  border-top: var(--bordure);
}

.concernes-foyer {
  display: block;
  position: relative; /* ancre le ::after de la coche */
  cursor: pointer;
}

.concernes-foyer + .concernes-foyer {
  border-top: var(--bordure);
}

.concernes-foyer-contenu {
  display: flex;
  align-items: center;
  gap: var(--espace-3);
  min-height: var(--cible-min);
  padding: var(--espace-1) var(--espace-4);
  font-size: var(--taille-corps);
}

.concernes-foyer-nom {
  font-weight: 600;
}

/* Le décompte des présents rend visible ce qui serait sinon une surprise :
   cocher un foyer absent ce jour-là ne coûte rien à personne (le calcul
   n'entend que les présents, voir depot/perimetre.py). */
.concernes-foyer-presents {
  margin-left: auto;
  font-size: var(--taille-petite);
  color: var(--gris-500);
}

.concernes-foyer--absent .concernes-foyer-nom {
  color: var(--gris-500);
}

/* Case dessinée : un carré qui se remplit d'accent une fois coché. Le
   pictogramme ✓ est en ::after pour rester lisible en noir et blanc. */
.concernes-foyer-contenu::before {
  content: "";
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  border: 1.5px solid var(--gris-300);
  border-radius: 6px;
  background: var(--gris-000);
}

.concernes-foyer input:checked + .concernes-foyer-contenu::before {
  background: var(--accent);
  border-color: var(--accent);
}

.concernes-foyer input:checked + .concernes-foyer-contenu::after {
  content: "";
  position: absolute;
  width: 5px;
  height: 10px;
  margin-left: 8px;
  border-right: 2px solid var(--accent-texte);
  border-bottom: 2px solid var(--accent-texte);
  transform: translateY(-2px) rotate(45deg);
}

/* ÉTAT INTERMÉDIAIRE : le foyer apporte une partie de ce qu'il peut. La
   case étant DESSINÉE (le carré natif est masqué), `:indeterminate` n'a
   aucun rendu par défaut ici — sans cette règle, « une partie » et « rien »
   se ressemblaient trait pour trait à l'écran alors qu'ils ne disent pas la
   même chose. Vu en capture, pas au test : aucune assertion sur le DOM ne
   pouvait le signaler.

   Un TIRET, jamais une coche pâle : le tiret est la convention des cases
   groupées, et il se lit en noir et blanc comme le ✓. Fond blanc et bordure
   d'accent — l'aplat plein reste réservé au « tout ». */
.concernes-foyer input:indeterminate + .concernes-foyer-contenu::before {
  border-color: var(--accent);
}

.concernes-foyer input:indeterminate + .concernes-foyer-contenu::after {
  content: "";
  position: absolute;
  width: 10px;
  height: 0;
  margin-left: 6px;
  border-top: 2px solid var(--accent);
}

.concernes-foyer input:focus-visible + .concernes-foyer-contenu {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/* Les exemptés d'un foyer, EN RETRAIT sous lui — un filet vertical plutôt
   qu'un aplat : le décalage dit « ceci dépend de la ligne du dessus » sans
   un mot de plus, et sans peser autant qu'un second niveau de carte.
   Décochés par défaut : l'exemption est la règle, la réinclusion l'exception
   d'une dépense. */
.concernes-exemptes {
  display: flex;
  flex-direction: column;
  gap: var(--espace-1);
  margin: 0 0 var(--espace-2) 34px; /* aligné sous le nom du foyer, pas sous sa case */
  padding-left: var(--espace-3);
  border-left: 2px solid var(--gris-300);
}

/* La raison, dite UNE FOIS pour le foyer : c'est une règle du foyer, pas
   une propriété de chacun de ses membres. Répétée sur chaque ligne, elle
   faisait un mur et donnait à lire une négation par personne. */
.concernes-exemptes-motif {
  margin: 0 0 var(--espace-1);
  font-size: var(--taille-petite);
  color: var(--gris-500);
}

.concernes-exempte {
  display: flex;
  align-items: center;
  gap: var(--espace-2);
  min-height: 36px;
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
  cursor: pointer;
}

.concernes-exempte input {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  accent-color: var(--accent);
}

/* Recoché = il compte à nouveau : la ligne reprend du poids, seul état de
   l'écran qui change un total sans changer une case de foyer. */
.concernes-exempte:has(input:checked) {
  color: var(--gris-900);
  font-weight: 600;
}

/* Libellé, date : champs secondaires, sobres. */

.champ-libelle input,
.champ-date input {
  width: 100%;
  min-height: var(--cible-min);
  padding: var(--espace-2) var(--espace-3);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
  font-family: inherit;
  font-size: var(--taille-corps-lg);
  color: var(--gris-900);
}

.champ-libelle input:focus,
.champ-date input:focus {
  outline: none;
  border-color: var(--accent);
}

.facultatif {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
}

.bouton-large {
  width: 100%;
  min-height: 52px;
  font-size: var(--taille-corps-lg);
}

/* Deux actions de poids TRÈS différents : "Ajouter la dépense" est le cas
   normal, "et saisir la suivante" le cas du retour de marché. Le second
   est un lien-bouton, pas un second bouton plein — sinon l'écran pose une
   question là où il devrait proposer une évidence. */
.actions-formulaire {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Pas d'écart : les 44px de zone tactile de .lien-action suffisent à
     séparer les deux actions, et les 8px économisés sont exactement ce qui
     fait tenir l'écran sans défilement sur un iPhone SE (667px). */
  gap: 0;
}

.lien-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--cible-min);
  padding: 0 var(--espace-3);
  background: none;
  border: none;
  font-family: inherit;
  font-size: var(--taille-corps-sm);
  font-weight: 600;
  color: var(--accent);
  text-decoration: underline;
  cursor: pointer;
}

.lien-action:hover,
.lien-action:focus-visible {
  text-decoration: none;
}

/* Liste des dépenses (Partie 3, même passe) */

.bouton-lien {
  text-decoration: none;
}

.liste-depenses {
  list-style: none;
  margin: var(--espace-4) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--espace-2);
}

/* Bandeau de totaux par compte : la valeur est le total, lisible sans
   clic. Pas de couleur d'identité par compte — le budget couleur reste
   réservé au sens (accent, créancier/débiteur, anomalie), comme pour les
   foyers en Partie 2. Un compte se distingue par son libellé. */

.bandeau-comptes {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--espace-2);
  margin: var(--espace-4) 0;
}

.carte-compte {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: var(--cible-min);
  padding: var(--espace-2) var(--espace-3);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
  text-decoration: none;
  color: var(--gris-900);
}

.carte-compte:hover,
.carte-compte:focus-visible {
  border-color: var(--accent);
  outline: none;
}

.carte-compte--actif {
  background: var(--accent-surface);
  border-color: var(--accent);
}

.carte-compte-libelle {
  display: flex;
  align-items: center;
  gap: var(--espace-1);
  font-size: var(--taille-micro);
  font-weight: 600;
  color: var(--gris-500);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.carte-compte-total {
  font-size: var(--taille-corps-lg);
  font-weight: 700;
}

/* "Supprimer" sur la MÊME rangée que le montant : lui donner sa propre
   rangée coûtait ~40px par carte, soit un écran entier de défilement sur
   douze dépenses. Le libellé s'ellipse si besoin — le montant, lui, n'est
   jamais tronqué, et la ligne entière reste cliquable pour l'édition. */
.ligne-depense {
  position: relative; /* ancre le lien étiré de .ligne-depense-lien */
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--espace-1) var(--espace-3);
  padding: var(--espace-2) var(--espace-4) var(--espace-3);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
}

/* La zone tactile de 44px de "Supprimer" impose la hauteur de la rangée :
   sans ce centrage, le montant flottait au-dessus du libellé de l'action. */
.ligne-depense-principal {
  grid-column: 1;
  align-self: center;
}

.ligne-depense-meta {
  grid-column: 1 / -1;
}

.ligne-depense:hover,
.ligne-depense:focus-within {
  border-color: var(--accent);
}

.ligne-depense--anomalie {
  border-color: var(--texte-anomalie);
}

.ligne-depense-principal {
  display: flex;
  align-items: baseline;
  gap: var(--espace-3);
  min-width: 0;
}

/* Lien étiré : cliquable sur toute la carte, tout en restant un vrai lien
   avec un libellé lisible pour le clavier et les lecteurs d'écran. */
.ligne-depense-lien {
  display: flex;
  align-items: baseline;
  gap: var(--espace-3);
  min-width: 0;
  color: inherit;
  text-decoration: none;
}

.ligne-depense-lien::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--rayon);
}

.ligne-depense-lien:focus-visible::after {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.etiquette-compte {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-1);
  padding: 2px var(--espace-2);
  border: var(--bordure);
  border-radius: 999px;
  font-size: var(--taille-micro);
  font-weight: 600;
  color: var(--gris-700);
}

.ligne-depense-payeur {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-1);
}

.ligne-depense-payeur .pastille-foyer {
  width: 22px;
  height: 22px;
  min-width: 22px;
  font-size: 9px;
}

.ligne-depense-anomalie {
  grid-column: 1 / -1;
  display: flex;
  align-items: flex-start;
  gap: var(--espace-1);
  margin: var(--espace-1) 0 0;
  font-size: var(--taille-corps-sm);
  font-weight: 600;
  color: var(--texte-anomalie);
}

.ligne-depense-montant {
  font-size: var(--taille-corps-lg);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.ligne-depense-libelle {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ligne-depense-meta {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-1) var(--espace-3);
  font-size: var(--taille-petite);
  color: var(--gris-500);
}

.ligne-depense-tracabilite {
  font-style: italic;
}

/* Au-dessus du lien étiré : la suppression doit rester atteignable sans
   déclencher l'ouverture de la dépense. */
.ligne-depense-actions {
  position: relative;
  z-index: 1;
  grid-column: 2;
  grid-row: 1;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--espace-2);
  margin-right: calc(var(--espace-2) * -1); /* aligne le texte, pas la zone tactile */
}

/* Actions en icône seule : cible tactile de 44px maintenue malgré la
   petite taille du dessin (le padding porte la zone, pas le glyphe). */
.action-icone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--cible-min);
  min-height: var(--cible-min);
  padding: 0;
  background: none;
  border: none;
  font-size: 18px;
  color: var(--gris-500);
  cursor: pointer;
}

.ligne-depense-actions a.action-icone {
  color: var(--accent);
}

.action-icone:hover,
.action-icone:focus-visible {
  color: var(--gris-900);
}

.ligne-depense-actions button.action-icone:hover,
.ligne-depense-actions button.action-icone:focus-visible {
  color: var(--texte-debiteur);
}

/* Écrans de paramétrage (Phase 2A, Partie 1) — édition du séjour et des
   comptes. Même registre que la saisie de dépense : bordures natives des
   fieldset neutralisées, groupes matérialisés par une carte. */

.formulaire-parametres {
  display: flex;
  flex-direction: column;
  gap: var(--espace-4);
}

.formulaire-parametres fieldset {
  margin: 0;
  padding: 0;
  border: none;
}

/* Plus spécifique que `.formulaire-parametres fieldset` (qui remet
   padding/bordure à zéro) plutôt qu'un !important — même choix que pour le
   panneau "concernés" du formulaire de dépense. */
.formulaire-parametres .groupe-parametres {
  padding: var(--espace-3) var(--espace-4) var(--espace-4);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
}

.groupe-parametres > .etiquette {
  padding: 0;
  margin-bottom: var(--espace-2);
}

.aide-parametre {
  margin: 0 0 var(--espace-3);
  font-size: var(--taille-corps-sm);
  color: var(--gris-500);
}

.aide-parametre:last-child {
  margin: var(--espace-2) 0 0;
}

.champ-parametre {
  display: block;
  min-width: 0; /* sans quoi un champ en flex refuse de se réduire et déborde */
}

.sous-etiquette {
  display: block;
  margin-bottom: var(--espace-1);
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
}

.champ-parametre input,
.champ-parametre select {
  width: 100%;
  min-height: var(--cible-min);
  padding: var(--espace-2) var(--espace-3);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
  font-family: inherit;
  font-size: var(--taille-corps-lg);
  color: var(--gris-900);
}

.champ-parametre input:focus,
.champ-parametre select:focus {
  outline: none;
  border-color: var(--accent);
}

/* Les trois poids ne tiennent pas côte à côte sur 375px : ils passent en
   colonne en étroit, en rangée dès qu'il y a la place. C'est ce qui
   supprime le débordement horizontal. */
.rangee-champs {
  flex-wrap: wrap;
}

.rangee-champs > * {
  flex: 1 1 140px;
}

/* Refus des bornes : la contrainte qui mord, pas la liste. */

.bloc-conflits {
  padding: var(--espace-3) var(--espace-4);
  background: var(--gris-000);
  border: var(--bordure);
  border-left: 3px solid var(--texte-anomalie);
  border-radius: var(--rayon);
}

.bloc-conflits-titre {
  display: flex;
  align-items: center;
  gap: var(--espace-2);
  margin: 0 0 var(--espace-2);
  font-weight: 600;
  color: var(--texte-anomalie);
}

.bloc-conflits-liste {
  margin: 0;
  padding-left: var(--espace-4);
  font-size: var(--taille-corps);
}

.bloc-conflits-liste li + li {
  margin-top: var(--espace-2);
}

.bloc-conflits-detail {
  display: block;
  margin-top: 2px;
  font-size: var(--taille-corps-sm);
  color: var(--gris-500);
}

.bloc-conflits-aide {
  margin: var(--espace-3) 0 0;
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
}

/* Avertissement de recalcul : lucide, pas alarmant — c'est une
   conséquence attendue, pas une erreur. Texte gris, icône seule en
   couleur d'alerte. */
.avertissement-recalcul {
  display: flex;
  align-items: flex-start;
  gap: var(--espace-2);
  margin: 0;
  padding: var(--espace-3) var(--espace-4);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
}

.avertissement-recalcul .icone {
  color: var(--texte-anomalie);
  margin-top: 2px;
}

/* Un avertissement collé au bouton qui l'exécute se lit comme sa légende, et
   il n'en est pas une : c'est ce qu'il faut avoir lu AVANT de cliquer. Le
   sélecteur d'adjacence vise exactement les trois écrans de suppression
   (foyer, participant, dépense), les seuls où l'avertissement précède
   directement les actions — ailleurs il est suivi de champs, et son
   `margin: 0` reste le bon. */
.avertissement-recalcul + .actions-formulaire {
  margin-top: var(--espace-5);
}

/* Écran des comptes : une carte par compte, chacune son formulaire. */

.liste-comptes-parametres {
  list-style: none;
  margin: var(--espace-4) 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--espace-3);
}

.carte-compte-parametre {
  padding: var(--espace-4);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon-lg);
}

.carte-compte-parametre form {
  display: flex;
  flex-direction: column;
  gap: var(--espace-3);
}

.carte-compte-entete {
  display: flex;
  align-items: flex-end;
  gap: var(--espace-3);
}

.carte-compte-entete .icone-compte {
  width: 22px;
  height: 22px;
  margin-bottom: var(--espace-3);
  color: var(--gris-500);
}

.champ-libelle-compte {
  flex: 1 1 auto;
}

.bascule {
  display: flex;
  align-items: center;
  gap: var(--espace-3);
  min-height: var(--cible-min);
  cursor: pointer;
}

.bascule input {
  width: 22px;
  height: 22px;
  accent-color: var(--accent);
}

/* Écran "ton compte" (Partie 5) */

.compte-resume {
  font-size: var(--taille-corps-lg);
  margin: 0 0 var(--espace-2);
}

.compte-position {
  font-size: var(--taille-titre);
  font-weight: 700;
  margin: 0 0 var(--espace-3);
}

.compte-presence {
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
  margin: 0 0 var(--espace-5);
}

.liste-comptes-detail {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--espace-3);
}

.compte-detail {
  padding: var(--espace-3) var(--espace-4);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
}

.compte-detail-entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-3);
  margin-bottom: var(--espace-1);
}

.compte-detail-titre {
  font-weight: 600;
}

.compte-detail-lignes {
  margin: 0;
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
}

.compte-liens {
  display: flex;
  flex-direction: column;
  gap: var(--espace-1);
  margin-top: var(--espace-5);
}

.compte-liens a {
  display: flex;
  align-items: center;
  min-height: var(--cible-min);
  color: var(--accent);
  font-weight: 600;
}

/* Plan de règlement (Partie 5) */

.liste-filtre {
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
  margin: var(--espace-3) 0;
}

.liste-filtre a {
  color: var(--accent);
  font-weight: 600;
}

.liste-reglement,
.liste-historique {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--espace-3);
}

.ligne-reglement {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--espace-3);
  padding: var(--espace-3) var(--espace-4);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
}

.ligne-reglement-phrase {
  margin: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--espace-2);
}

.ligne-historique {
  padding: var(--espace-2) var(--espace-4);
  border-bottom: var(--bordure);
}

.ligne-historique-phrase {
  margin: 0;
  color: var(--gris-700);
}

.ligne-historique-meta {
  margin: var(--espace-1) 0 0;
  font-size: var(--taille-micro);
  color: var(--gris-500);
}

/* Poids des repas : saisie en pourcentages entiers, total en direct */

.champ-pourcentage {
  position: relative;
  display: block;
}

.champ-pourcentage input {
  width: 100%;
  padding-right: 2rem; /* laisse la place au % sans le chevaucher */
}

.champ-pourcentage-unite {
  position: absolute;
  right: var(--espace-3);
  top: 50%;
  transform: translateY(-50%);
  color: var(--gris-500);
  font-size: var(--taille-corps);
  pointer-events: none;
}

/* Le total est une information de saisie, pas une alerte : neutre quand il
   tombe juste, signalé — en TEXTE, comme les soldes — quand il s'en écarte.
   Pas d'aplat rouge : le budget couleur reste réservé au sens. */
.total-poids {
  margin: var(--espace-2) 0 0;
  font-size: var(--taille-corps-sm);
  font-weight: 600;
  color: var(--gris-700);
}

.total-poids--ecart {
  color: var(--texte-debiteur);
}

.bouton-principal:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Foyers et participants (Phase 2A, Partie 2) */

.liste-foyers {
  list-style: none;
  margin: 0 0 var(--espace-5);
  padding: 0;
  display: grid;
  gap: var(--espace-4);
}

.carte-foyer {
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon-lg);
  overflow: hidden;
}

/* En étroit : la pastille à gauche sur toute la hauteur, puis DEUX rangées —
   le nom sur sa propre ligne pleine largeur, les actions en dessous. La
   version d'origine (une seule rangée : étiquette, champ, « Renommer », deux
   flèches) réduisait le champ à ~80px sur 375px, faisait passer « Nom du
   foyer » sur deux lignes et tronquait « Famille Bernard » à « Famill ».
   Écran de la Partie 2, jamais regardé en 375px avant que la Partie 4 ne le
   ramène dans le parcours. */
.carte-foyer-entete {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: var(--espace-2) var(--espace-3);
  padding: var(--espace-3) var(--espace-4);
  border-bottom: var(--bordure);
}

.carte-foyer-entete > .pastille-foyer {
  grid-row: 1 / span 2;
}

.form-renommer {
  grid-column: 2;
  min-width: 0; /* sans quoi le champ pousse la carte hors de l'écran en 375px */
}

/* « Renommer » et les flèches sur la même rangée, aux deux bouts : le geste
   fréquent à gauche sous le pouce, le réordonnancement à droite. */
.carte-foyer-commandes {
  grid-column: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-3);
}

.carte-foyer-ordre {
  display: flex;
  gap: var(--espace-1);
}

.bouton-icone {
  min-width: var(--cible-min);
  min-height: var(--cible-min);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
  font-size: var(--taille-corps-lg);
  color: var(--gris-700);
  cursor: pointer;
}

.bouton-icone:disabled {
  color: var(--gris-300);
  cursor: default;
}

.bouton-icone:not(:disabled):hover,
.bouton-icone:focus-visible {
  border-color: var(--accent);
  outline: none;
}

.liste-participants {
  list-style: none;
  margin: 0;
  padding: 0;
}

.ligne-participant + .ligne-participant {
  border-top: var(--bordure);
}

.ligne-participant-lien {
  display: flex;
  align-items: center;
  gap: var(--espace-3);
  min-height: var(--cible-min);
  padding: var(--espace-2) var(--espace-4);
  color: inherit;
  text-decoration: none;
}

.ligne-participant-lien:hover,
.ligne-participant-lien:focus-visible {
  background: var(--gris-050);
  outline: none;
}

.ligne-participant-nom {
  font-weight: 600;
}

.ligne-participant-qualite {
  margin-left: auto;
  font-size: var(--taille-petite);
  color: var(--gris-500);
}

.ligne-participant-surcharge {
  color: var(--accent);
}

.icone-chevron {
  color: var(--gris-500);
}

.carte-foyer-vide {
  margin: 0;
  padding: var(--espace-3) var(--espace-4);
  color: var(--gris-500);
  font-style: italic;
}

/* Le champ d'ajout, DANS la carte du foyer. En 375px il se replie en deux
   rangées : le prénom seul sur la première (c'est lui qu'on remplit dix-huit
   fois), la qualité et le bouton sur la seconde. Une seule rangée dès 720px.
   `flex-basis` explicite sur les trois enfants, jamais une rangée souple +
   fixes sans wrap : c'est ce défaut-là qui avait tronqué « Famille Bernard »
   en « Famill » sur la rangée d'en-tête. */
.form-ajout-participant {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--espace-2) var(--espace-3);
  padding: var(--espace-3) var(--espace-4);
  background: var(--gris-050);
  border-top: var(--bordure);
}

.form-ajout-participant .champ-parametre {
  flex: 1 1 100%;
}

.form-ajout-participant .segmente {
  flex: 1 1 180px;
}

.form-ajout-participant .bouton-secondaire {
  flex: 0 0 auto;
}

/* Une ligne discrète, pas un bloc : l'exemption est rare, mais quand elle
   existe elle doit se lire sans ouvrir quoi que ce soit — c'est elle qui
   explique un solde plus léger que prévu. Rangée souple (jamais de flex
   sans wrap qui mélange souple et fixe, cf. Partie 4). */
.carte-foyer-exemptions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-2);
  padding: var(--espace-2) var(--espace-4);
  border-top: var(--bordure);
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
}

.carte-foyer-exemptions .lien-action {
  margin-left: auto;
}

/* Case à cocher de paramétrage : une ligne entière est cliquable, et l'état
   coché se voit à la SURFACE (le traitement réservé à la sélection), pas à
   une couleur d'identité. */
.case-a-cocher {
  display: flex;
  align-items: center;
  gap: var(--espace-3);
  min-height: var(--cible-min);
  padding: var(--espace-2) var(--espace-3);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
  font-size: var(--taille-corps);
  cursor: pointer;
}

.case-a-cocher + .case-a-cocher {
  margin-top: var(--espace-2);
}

.case-a-cocher input {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  accent-color: var(--accent);
}

.case-a-cocher:has(input:checked) {
  background: var(--accent-surface);
  border-color: var(--accent);
}

.case-a-cocher-texte {
  font-weight: 600;
}

.case-a-cocher-note {
  margin-left: auto;
  font-size: var(--taille-petite);
  font-weight: 400;
  color: var(--gris-500);
}

/* Réglé au foyer : coché, mais gris et non cliquable — le traitement de
   surface accentué est réservé à ce que CET écran décide. Une case grisée
   qui s'explique vaut mieux qu'une case absente, qui se lirait « il
   participe ». */
.case-a-cocher--herite,
.case-a-cocher--herite:has(input:checked) {
  background: var(--gris-050);
  border-color: var(--gris-300);
  color: var(--gris-500);
  cursor: default;
}

.carte-foyer-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-3);
  padding: var(--espace-2) var(--espace-4);
  border-top: var(--bordure);
}

.form-nouveau-foyer {
  display: flex;
  align-items: flex-end;
  gap: var(--espace-3);
  flex-wrap: wrap;
  padding: var(--espace-4);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon-lg);
  margin-bottom: var(--espace-4);
}

.form-nouveau-foyer .champ-parametre {
  flex: 1 1 220px;
  min-width: 0;
}

.sous-titre-foyer {
  display: flex;
  align-items: center;
  gap: var(--espace-2);
  margin: calc(-1 * var(--espace-3)) 0 var(--espace-4);
  font-weight: 600;
  color: var(--gris-700);
}

/* Suppression : le rouge sémantique existant (--texte-debiteur), en TEXTE
   pour les liens. Le bouton de confirmation est le seul aplat rouge de
   l'app — il est l'action irréversible d'un écran qui ne sert qu'à ça. */
.lien-danger {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-2);
  min-height: var(--cible-min);
  color: var(--texte-debiteur);
  font-size: var(--taille-corps);
  font-weight: 600;
  text-decoration: none;
}

.lien-danger:hover,
.lien-danger:focus-visible {
  text-decoration: underline;
}

.bouton-danger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--cible-min);
  padding: var(--espace-2) var(--espace-4);
  background: var(--texte-debiteur);
  color: var(--gris-000);
  border: none;
  border-radius: var(--rayon);
  font-family: inherit;
  font-size: var(--taille-corps-lg);
  font-weight: 600;
  cursor: pointer;
}

.bouton-danger:hover,
.bouton-danger:focus-visible {
  opacity: 0.9;
  outline: none;
}

.bloc-consequences {
  padding: var(--espace-4);
  margin-bottom: var(--espace-4);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon-lg);
}

.bloc-consequences-titre {
  margin: 0 0 var(--espace-2);
  font-size: var(--taille-micro);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--gris-500);
}

.bloc-consequences ul {
  margin: 0 0 var(--espace-4);
  padding-left: var(--espace-5);
  color: var(--gris-700);
  font-size: var(--taille-corps);
}

.bloc-consequences ul:last-child {
  margin-bottom: 0;
}

.bloc-consequences li + li {
  margin-top: var(--espace-2);
}

/* « supprimé » : une mention, jamais une couleur d'identité — le foyer
   garde son monogramme et sa place dans les soldes. */
.mention-supprime {
  font-size: var(--taille-micro);
  font-weight: 400;
  color: var(--gris-500);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Frise de présence (Phase 2A, Partie 3)
   --------------------------------------
   DEUX écrans, pas deux tailles : `.frise-edition` et `.frise-consultation`
   ne montrent ni le même contenu ni les mêmes possibilités. Le basculement
   se fait au point de rupture unique de l'app (720px), plus bas dans ce
   fichier — `display: none` retire vraiment le bloc caché de l'arbre
   d'accessibilité, ce qui rend « pas d'édition sur mobile » vrai aussi pour
   un lecteur d'écran. */

.frise-edition {
  display: none; /* rétabli au-dessus de 720px */
}

.frise {
  --largeur-etiquette: 128px;
  overflow-x: auto; /* un séjour de trois mois ne casse pas la page */
  padding-bottom: var(--espace-2);
}

.frise-rangee,
.frise-ligne {
  display: grid;
  grid-template-columns: var(--largeur-etiquette) minmax(420px, 1fr);
  align-items: center;
  gap: var(--espace-3);
}

.frise-etiquette {
  display: flex;
  align-items: center;
  gap: var(--espace-2);
  min-width: 0;
  font-size: var(--taille-corps-sm);
}

.frise-etiquette-texte {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}

/* La piste porte TROIS colonnes par jour : la barre se dessine au repas,
   alors que le glisser reste à la journée. Une frise au jour plein
   mentirait sur une interruption qui commence à midi. */
.frise-piste {
  position: relative;
  display: grid;
  grid-template-columns: repeat(var(--nb-creneaux), 1fr);
  align-items: center;
  min-height: 34px;
}

.frise-piste--jours {
  grid-template-columns: repeat(var(--nb-jours), 1fr);
  min-height: 0;
}

.frise-jour {
  padding: 0 0 var(--espace-1);
  text-align: center;
  font-size: var(--taille-micro);
  color: var(--gris-500);
  line-height: 1.2;
}

.frise-jour-mois {
  display: block;
  font-weight: 600;
  color: var(--gris-700);
}

.frise-jour--aujourdhui .frise-jour-numero {
  font-weight: 700;
  color: var(--accent);
}

/* Trait d'aujourd'hui : une règle verticale, pas un aplat — le budget
   couleur reste réservé au sens, et « aujourd'hui » en est un. */
.frise-aujourdhui {
  position: absolute;
  top: 0;
  bottom: 0;
  grid-row: 1;
  border-left: 2px solid var(--accent);
  opacity: 0.45;
  pointer-events: none;
}

.frise-segment {
  grid-row: 1;
  height: 18px;
  background: var(--accent-surface);
  border: 1px solid var(--accent);
  border-radius: 3px;
}

.frise-ligne--detachee .frise-segment {
  height: 12px;
  background: var(--gris-100);
  border-color: var(--gris-500);
}

.frise-ligne--detachee .frise-etiquette-texte {
  font-weight: 400;
  color: var(--gris-700);
}

.frise-poignee {
  grid-row: 1;
  justify-self: center;
  width: 14px;
  height: 26px;
  padding: 0;
  background: var(--gris-000);
  border: 1.5px solid var(--accent);
  border-radius: 4px;
  cursor: ew-resize;
  touch-action: none; /* sans quoi le navigateur fait défiler au lieu de glisser */
}

.frise-poignee:focus-visible,
.frise-poignee--active {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.frise-legende {
  margin: var(--espace-3) 0 0;
  font-size: var(--taille-petite);
  color: var(--gris-500);
}

/* Le formulaire de repli. Ce n'est pas un chemin de secours : c'est le seul
   chemin d'écriture, le glisser ne fait que remplir ses champs.

   Toute la mise en page tient sur DEUX grilles alignées — celle des bornes
   et celle des interruptions — de sorte que « Début » et « Fin » tombent au
   même endroit d'une rangée à l'autre. Aucun fieldset n'est lui-même une
   grille : un <legend> y deviendrait un élément de grille et disloquerait
   l'alignement (même piège que le <p> en flex de la Partie 1). */

.frise-details {
  margin: 0 0 var(--espace-2) var(--largeur-etiquette);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
}

.frise-details[open] {
  margin-bottom: var(--espace-4);
  border-color: var(--accent);
}

/* DÉFAUT DE CLASSE, à ne pas réintroduire : un <summary> en `display: flex`
   (ou grid) cesse, dans WebKit, d'être la commande d'ouverture de son
   <details> — le clic n'ouvre plus rien, et sur un séjour neuf où chaque
   présence se saisit dans un de ces panneaux, plus rien n'est saisissable.
   Le summary reste donc en `block` et la mise en page vit dans un enfant.
   Jumeau du <legend> en flex (Partie 3) et du <p> en flex (Partie 1) :
   certains éléments perdent leur comportement natif en devenant conteneurs. */
.frise-details-resume {
  display: block;
  padding: var(--espace-2) var(--espace-3);
  cursor: pointer;
  list-style: none; /* le triangle natif est remplacé par .frise-details-chevron */
  font-size: var(--taille-corps-sm);
}

.frise-details-rangee {
  display: flex;
  flex-wrap: wrap;
  /* `center` depuis que l'en-tête porte le monogramme : en `baseline`, une
     pastille de 28px s'aligne sur le texte et dépasse vers le haut. */
  align-items: center;
  gap: var(--espace-2);
  min-height: var(--cible-min);
}

/* Plus petite que sur les cartes : ici elle rattache la ligne à sa famille,
   elle n'est pas le sujet — et une ligne détachée ne porte qu'un prénom,
   c'est le seul rappel du foyer. */
.frise-details-resume .pastille-foyer {
  width: 28px;
  height: 28px;
  min-width: 28px;
  font-size: var(--taille-micro);
}

.frise-details-resume::-webkit-details-marker {
  display: none;
}

.frise-details-resume:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-radius: var(--rayon);
}

.frise-details-qui {
  font-weight: 600;
}

.frise-details-quand {
  color: var(--gris-500);
}

/* Le chevron dit que la ligne s'ouvre ET se referme — sans lui, le résumé
   ne se lisait pas comme une bascule. Même dessin que celui du panneau
   « concernés » de la saisie : une seule idée visuelle dans l'app. */
.frise-details-chevron {
  flex: 0 0 auto;
  margin-left: auto;
  width: 8px;
  height: 8px;
  border-right: 1.5px solid var(--gris-500);
  border-bottom: 1.5px solid var(--gris-500);
  transform: rotate(-45deg);
  transition: transform 0.15s ease;
}

/* `>` obligatoire : le panneau contient maintenant des <details> imbriqués
   (les sections repliées). Sans lui, ouvrir la ligne retournerait AUSSI les
   chevrons de ses sections, qui sont pourtant restées fermées. */
.frise-details[open] > .frise-details-resume .frise-details-chevron {
  transform: rotate(45deg);
}

/* Même gouttière que les sections repliées en dessous : les étiquettes
   « Arrivée », « Qui part de ces dates ? » et « Début » s'alignent toutes
   sur le même bord gauche, d'un bloc à l'autre. */
.form-presence {
  padding: var(--espace-4);
  border-top: var(--bordure);
}

/* AUCUN cadre natif dans ce panneau : ni bordure de fieldset, ni légende
   posée sur le trait. Un `<fieldset>` reste le bon élément (il groupe des
   contrôles pour un lecteur d'écran, et `<legend>` est son intitulé), mais il
   se présente comme les autres blocs de l'app — étiquette AU-DESSUS, pas de
   cadre. La règle porte sur le PANNEAU, pas sur `.form-presence` : depuis la
   refonte, la section « détacher » a son propre formulaire, et le cadre natif
   y réapparaissait. */
.frise-details fieldset {
  min-width: 0;
  margin: 0 0 var(--espace-4);
  padding: 0;
  border: none;
}

.frise-details fieldset:last-of-type {
  margin-bottom: var(--espace-3);
}

.frise-details legend {
  padding: 0;
  margin-bottom: var(--espace-1);
}

/* Bornes : deux colonnes égales tant que la place le permet, une seule
   ensuite. Les deux fieldsets restent en display: block (cf. le legend). */
.rangee-bornes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: var(--espace-3) var(--espace-4);
  margin-bottom: var(--espace-4);
}

.borne-champs {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, auto);
  align-items: center;
  gap: var(--espace-2);
}

.borne--active {
  outline: 2px solid var(--accent);
  outline-offset: 6px;
  border-radius: var(--rayon);
}

/* Infobulle de la borne active : « arrivée · 22 juil au dîner ». Vide sans
   JS, donc invisible — le champ date et le select disent déjà tout. */
.borne-etat {
  display: block;
  margin-top: var(--espace-1);
  font-size: var(--taille-petite);
  color: var(--accent);
  font-weight: 600;
}

.borne-etat:empty {
  display: none;
}

/* TOUS les champs de la carte de présence d'un coup — jamais bloc par bloc.
   La règle ciblait `.form-presence` : les dates des sections repliées
   (détachement, repas non pris) restaient donc au rendu NATIF du navigateur,
   bordure épaisse comprise, à trois centimètres de champs identiques. Une
   règle par bloc, c'est un bloc oublié au prochain ajout — celle-ci porte sur
   le panneau, quel que soit le formulaire (ou l'absence de formulaire : les
   interruptions ne sont rattachées au leur que par `form=`). */
.frise-details input[type="date"],
.frise-details select,
.select-repas {
  width: 100%;
  min-height: 38px;
  padding: var(--espace-1) var(--espace-2);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
  font-family: inherit;
  font-size: var(--taille-corps-sm);
  color: var(--gris-900);
}

.frise-details input[type="date"]:focus-visible,
.frise-details select:focus-visible,
.select-repas:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}

/* Interruptions : l'en-tête et chaque rangée partagent EXACTEMENT les mêmes
   colonnes, c'est ce qui met « Début » et « Fin » d'aplomb. */
.interruptions-entete,
.interruption {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 5.5rem;
  align-items: center;
  gap: var(--espace-2) var(--espace-3);
}

.interruptions-entete {
  margin-bottom: var(--espace-1);
  font-size: var(--taille-micro);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--gris-500);
}

.interruption + .interruption {
  margin-top: var(--espace-2);
}

.interruption-borne {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, auto);
  align-items: center;
  gap: var(--espace-2);
}

.interruption-retirer {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-1);
  font-size: var(--taille-petite);
  color: var(--gris-500);
  cursor: pointer;
}

.interruption--vierge .interruption-borne {
  opacity: 0.7; /* la rangée d'ajout s'efface tant qu'elle est vide */
}

.interruption--vierge:focus-within .interruption-borne {
  opacity: 1;
}

.detacher {
  margin: 0 var(--espace-3) var(--espace-3);
}

/* Confirmation détaillée : elle ÉNUMÈRE ce qui a changé (voir
   web/presences.py). Plus longue qu'un « enregistré », donc alignée à
   gauche et pas centrée comme une pastille de statut. */
.confirmation--detaillee {
  text-align: left;
}

/* Consultation — mobile. Une liste, aucune barre, aucun formulaire. */

.aujourdhui-bloc {
  padding: var(--espace-3) var(--espace-4);
  margin-bottom: var(--espace-4);
  background: var(--accent-surface);
  border: 1px solid var(--accent);
  border-radius: var(--rayon-lg);
}

.aujourdhui-titre {
  margin: 0 0 var(--espace-1);
  font-size: var(--taille-micro);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--gris-700);
}

.aujourdhui-qui {
  margin: 0;
  font-size: var(--taille-corps-lg);
  font-weight: 600;
}

.aujourdhui-compte {
  display: block;
  font-size: var(--taille-petite);
  font-weight: 400;
  color: var(--gris-700);
}

.carte-presence {
  padding: var(--espace-3) var(--espace-4);
  margin-bottom: var(--espace-3);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon-lg);
}

.carte-presence-titre {
  display: flex;
  align-items: center;
  gap: var(--espace-2);
  margin: 0 0 var(--espace-2);
  font-size: var(--taille-corps-lg);
}

.presence-ligne + .presence-ligne {
  margin-top: var(--espace-3);
  padding-top: var(--espace-3);
  border-top: var(--bordure);
}

.presence-qui {
  margin: 0;
  font-weight: 600;
  font-size: var(--taille-corps);
}

/* Une exception se décale : elle se lit comme une note sous la ligne du
   foyer, pas comme un second foyer. */
.presence-ligne--exception {
  padding-left: var(--espace-3);
  border-left: 2px solid var(--gris-300);
}

/* La phrase de portée : qui cette barre couvre, et ce que le bouton fera.
   Discrète (elle se lit une fois), jamais alarmante — le rouge d'anomalie
   est réservé au tableau de bord, ici on est à l'endroit où l'on corrige. */
.form-presence-portee {
  margin: 0 0 var(--espace-3);
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
}

/* --- Sections repliées du panneau (détacher, repas non pris) -------------
   Deux gestes rares sous le geste fréquent. Fermées par défaut, annoncées
   par une icône, un titre et ce qu'elles permettent : un titre seul
   (« Interruptions ») ne dit pas s'il faut ouvrir. */

.section-repliee {
  border-top: var(--bordure);
}

/* display: block, JAMAIS flex — dans WebKit un <summary> devenu conteneur
   cesse d'ouvrir son <details> (bug bloquant vécu, garde-fou dans
   test_web_css.py). La mise en page vit dans .section-rangee. */
.section-resume {
  display: block;
  padding: var(--espace-3) var(--espace-4);
  cursor: pointer;
  list-style: none;
}

.section-resume::-webkit-details-marker {
  display: none;
}

.section-resume:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.section-rangee {
  display: flex;
  align-items: center;
  gap: var(--espace-3);
  min-height: var(--cible-min);
}

.section-icone {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  color: var(--accent);
}

.section-textes {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.section-titre {
  font-size: var(--taille-corps-sm);
  font-weight: 600;
  color: var(--gris-900);
}

.section-sous-titre {
  font-size: var(--taille-petite);
  color: var(--gris-500);
}

.section-repliee[open] > .section-resume .frise-details-chevron {
  transform: rotate(45deg);
}

.section-repliee[open] > .section-resume {
  border-bottom: var(--bordure);
}

/* Le contenu déplié respire, et s'aligne sur le formulaire du dessus. */
.section-repliee > .form-detacher,
.section-repliee > .interruptions {
  padding: var(--espace-4);
}

/* Les membres à détacher : des pastilles cochables, pas des champs. L'état
   sélectionné se voit d'un coup d'œil (surface accentuée ET bordure accent,
   règle du design system) — l'input natif est masqué, c'est l'étiquette qui
   porte l'état et la zone tactile. */
.choix-membres {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-2);
}

.choix-membres .pastille-option-contenu {
  min-height: var(--cible-min);
  padding: var(--espace-2) var(--espace-4);
  font-size: var(--taille-corps-sm);
  font-weight: 600;
}

.presence-quand {
  margin: var(--espace-1) 0 0;
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
}

.presence-quand--manquante {
  color: var(--texte-anomalie);
}

.presence-trou {
  margin: var(--espace-1) 0 0;
  font-size: var(--taille-petite);
  color: var(--gris-500);
}

/* Synthèse des participants. DEUX MISES EN PAGE, UN SEUL GABARIT : liste en
   étroit, matrice en large. La matrice exige de la largeur par NATURE — une
   colonne par compte — et le sticky rendait son défilement supportable sans
   le supprimer (253px hors cadre en 375px). En dessous de 720px, les mêmes
   cellules se relisent donc en liste, et la liste ne montre QUE les
   exceptions. Ce sont bien les mêmes `<td>` : deux gabarits, ou deux jeux de
   données, auraient divergé au premier changement de règle.

   Aucune couleur sémantique ici — le budget couleur du projet est réservé
   au sens créancier/débiteur, et une exemption est un état parfaitement
   normal, pas un avertissement. Elle se marque donc par une surface neutre
   et une icône, comme un foyer se marque par un monogramme et jamais par
   une teinte qui lui serait propre. */
.sous-titre {
  margin: calc(-1 * var(--espace-3)) 0 var(--espace-4);
  font-size: var(--taille-corps-sm);
  color: var(--gris-500);
}

/* « Seules les exceptions sont indiquées » : la phrase porte ce que les
   coches disaient en large. Sans elle, une ligne muette se lirait comme une
   donnée manquante. */
.aide-liste {
  margin: 0 0 var(--espace-4);
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
}

.table-defilante {
  margin: var(--espace-4) 0;
  border: var(--bordure);
  border-radius: var(--rayon);
  background: var(--gris-000);
}

/* --- Liste (étroit) ------------------------------------------------------
   Les éléments de tableau redeviennent des blocs : plus de colonnes, donc
   plus rien à faire déborder. AUCUN défilement horizontal ne subsiste. */
.table-synthese {
  display: block;
  width: 100%;
}

.table-synthese thead {
  display: none; /* des en-têtes de colonnes sans colonnes ne disent rien */
}

.table-synthese tbody {
  display: block;
}

.table-synthese th,
.table-synthese td {
  display: block;
  padding: 0;
  border: none;
  text-align: left;
}

/* Une ligne = un participant : le nom à gauche, les coefficients à droite,
   et les exceptions dessous, chacune sur sa ligne. */
.table-synthese tbody tr {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--espace-1) var(--espace-2);
  padding: var(--espace-2) var(--espace-4);
  border-top: var(--bordure);
}

.table-synthese tbody tr:first-child {
  border-top: none;
}

.cellule-nom {
  flex: 1 1 auto;
  min-width: 0;
  font-weight: 600;
  color: var(--gris-900);
}

.synthese-foyer-nom a,
.cellule-nom a {
  color: inherit;
  text-decoration: none;
}

.synthese-foyer-nom a:hover,
.cellule-nom a:hover {
  text-decoration: underline;
}

/* « repas 1,00 · nuitée 1,00 » : sans l'en-tête de colonnes, une valeur nue
   ne dit plus de quoi elle est le coefficient. L'étiquette vient de
   `data-libelle`, donc de la donnée déjà présente, pas d'un second gabarit. */
.col-coef {
  font-size: var(--taille-petite);
  color: var(--gris-500);
  white-space: nowrap;
  /* Chiffres de largeur fixe : « 0,60 » et « 1,00 » doivent tomber l'un
     sous l'autre, sinon la colonne ondule et on ne compare plus rien. */
  font-variant-numeric: tabular-nums;
}

.col-coef::before {
  content: attr(data-libelle) " ";
}

.col-coef + .col-coef::before {
  content: "· " attr(data-libelle) " ";
}

/* SEULES LES EXCEPTIONS. Une personne sans mention participe à tout — c'est
   ce que dit la phrase d'introduction, et c'est ce qui rend la liste
   lisible : sur dix-huit participants, trois lignes portent une mention. */
.col-compte {
  flex-basis: 100%;
}

/* Sélecteur préfixé par `.table-synthese` À DESSEIN : `.table-synthese td`
   (0,1,1) l'emporterait sinon sur `.col-compte--participe` (0,1,0), et la
   coche resterait affichée sous chaque nom — vu à la capture. */
.table-synthese .col-compte--participe {
  display: none;
}

.mention-sans-objet {
  font-size: var(--taille-petite);
  color: var(--gris-500);
}

.col-compte--sans_objet .cellule-sans-objet {
  display: none; /* le tiret est un signe de tableau, pas une phrase */
}

/* En-tête de foyer : même rôle qu'en large, en tête de groupe. La ligne
   reste un BLOC — en flex comme les lignes de participants, sa cellule
   unique se dimensionnerait sur son contenu et la bande grise s'arrêterait
   au milieu de l'écran (vu à la capture). */
.table-synthese tbody tr.synthese-foyer-entete {
  display: block;
  padding: 0;
}

.synthese-foyer-entete th {
  padding: var(--espace-3) var(--espace-4);
  background: var(--gris-050);
  border-top: var(--bordure);
}

.synthese-foyer-rangee {
  display: flex;
  flex-wrap: wrap; /* la marque passe SOUS le nom plutôt que de l'écraser */
  align-items: center;
  gap: var(--espace-2);
}

.synthese-foyer-nom {
  display: flex;
  align-items: center;
  gap: var(--espace-2);
  font-size: var(--taille-corps);
  font-weight: 600;
  color: var(--gris-900);
  text-transform: none;
  letter-spacing: 0;
}

/* Un coefficient PERSONNALISÉ : trait d'accent sous la valeur, et rien
   d'autre. Le mot « propre » a disparu de l'écran — un marqueur visuel n'a
   pas besoin d'être traduit ligne à ligne, la légende le fait une fois.
   `box-shadow` plutôt que `border-bottom` : le trait ne déplace aucune
   ligne de base, donc les colonnes de chiffres restent alignées. */
.col-coef--propre .valeur-coef {
  /* Valeur STANDARD en gris, valeur choisie en texte normal : la
     différence de densité fait la moitié du travail, le trait fait le
     reste. Deux signaux discrets valent mieux qu'un mot. */
  color: var(--gris-900);
  box-shadow: inset 0 -2px 0 var(--accent);
}

.valeur-coef--exemple {
  font-variant-numeric: tabular-nums;
  box-shadow: inset 0 -2px 0 var(--accent);
}

.mention-discrete {
  margin-left: var(--espace-1);
  font-size: var(--taille-micro);
  font-weight: 400;
  color: var(--gris-500);
}

/* La pastille d'exemption : NEUTRE. Les deux grains portent le même mot et
   ne se distinguent que par leur icône (une silhouette, un groupe) — d'où
   la légende, obligatoire, aux deux largeurs. */
.marque-exemption {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-1);
  padding: 2px var(--espace-2);
  background: var(--gris-100);
  border: var(--bordure);
  border-radius: 999px;
  font-size: var(--taille-micro);
  font-weight: 600;
  color: var(--gris-700);
  text-transform: none;
  letter-spacing: 0;
  white-space: nowrap;
}

/* La coche « participe » et le tiret « ne s'applique pas » sont le cas de
   LOIN le plus fréquent : ils ne disent rien d'autre que « normal », et
   restent donc EN RETRAIT derrière les pastilles d'exemption. Mais en
   retrait n'est pas illisible : à la teinte de bordure (`--gris-300`) on ne
   les voyait qu'à peine. Ils prennent la teinte de TEXTE atténué —
   `--gris-500`, celle des mentions secondaires comme « enfant » — et un
   pixel de plus. La hiérarchie tient toujours : une pastille porte un fond,
   une bordure et un mot ; eux n'ont qu'un trait gris. Jamais de texte à
   côté d'eux — le seul mot d'une cellule doit être une exception. */
.icone-participe {
  width: 16px;
  height: 16px;
  color: var(--gris-500);
}

.cellule-sans-objet {
  color: var(--gris-500);
}

/* Visible pour un lecteur d'écran, invisible à l'œil. Une cellule qui ne
   contiendrait qu'une icône (`aria-hidden`) serait VIDE à l'oreille : sur
   cet écran, « participe » et « ne s'applique pas » ne se disent que par
   ce texte-là. `clip-path`, jamais `display: none` — ce dernier retire
   aussi de l'arbre d'accessibilité. */
.lecteur-ecran {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.legende-synthese {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-2) var(--espace-4);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--taille-petite);
  color: var(--gris-500);
}

.legende-synthese li {
  display: flex;
  align-items: center;
  gap: var(--espace-1);
}

/* La coche et le tiret n'existent pas dans la liste : les décrire serait
   pire que pas de légende du tout. Sélecteur préfixé pour la même raison que
   la coche — `.legende-synthese li` (0,1,1) l'emporterait sinon. */
.legende-synthese .legende-large {
  display: none;
}

/* Point de rupture unique : même gabarit HTML, layout élargi en CSS. */
@media (min-width: 720px) {
  /* La barre rejoint la rangée de l'en-tête : séjour, navigation, puis
     l'engrenage et le foyer poussés à droite par `margin-right: auto`.
     Mêmes entrées qu'en étroit — seul le pliage change. */
  .nav-principale {
    order: 2;
    flex-basis: auto;
    flex-wrap: wrap;
    gap: var(--espace-1) var(--espace-4);
    margin: 0 auto 0 var(--espace-5);
    padding: 0;
    border-top: none;
  }

  /* La place existe : on retrouve EXACTEMENT la barre d'avant — libellés
     longs seuls, sur une rangée, sans icône. Les icônes ne sont pas un
     ornement qu'on garderait « aussi » : à côté d'un mot entier elles
     doubleraient un libellé déjà limpide (même arbitrage que l'étiquette
     « Payé par » de la saisie). */
  .nav-lien {
    display: inline-flex;
    flex: 0 0 auto;
    flex-direction: row;
    padding: 0;
    font-size: var(--taille-corps);
  }

  .nav-lien-icone,
  .nav-lien-court {
    display: none;
  }

  .nav-lien-long {
    position: static;
    width: auto;
    height: auto;
    clip-path: none;
  }

  /* La place existe : l'engrenage reprend son libellé. */
  .entete-parametres-nom {
    position: static;
    width: auto;
    height: auto;
    clip-path: none;
  }

  /* Prénom, qualité et bouton d'ajout tiennent sur une rangée. */
  .form-ajout-participant .champ-parametre {
    flex: 1 1 200px;
  }

  /* La carte foyer retrouve sa rangée unique : pastille, nom, actions. */
  .carte-foyer-entete {
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: end;
  }

  .carte-foyer-entete > .pastille-foyer {
    grid-row: auto;
    align-self: center;
  }

  .form-renommer {
    grid-column: 2;
    grid-row: 1;
  }

  .carte-foyer-commandes {
    grid-column: 3;
    grid-row: 1;
    justify-content: flex-end;
  }

  /* La bascule des deux vues de la frise. Pas une frise rétrécie d'un côté
     et étirée de l'autre : deux écrans, dont un seul existe à la fois. */
  .frise-edition {
    display: block;
  }

  .frise-consultation {
    display: none;
  }
  .contenu {
    padding: var(--espace-6);
  }

  .grille-foyers {
    grid-template-columns: repeat(2, 1fr);
  }

  .colonne-compte {
    display: table-cell;
  }

  /* Le tableau des soldes a besoin de plus de largeur que les 640px du
     gabarit étroit (formulaires, listes) une fois les 3 colonnes de compte
     visibles — ciblé via :has() pour ne pas élargir les autres écrans. */
  .contenu:has(.table-soldes) {
    max-width: 960px;
  }

  /* La frise a besoin de plus que les 640px du gabarit étroit : vingt et un
     jours au repas près ne se lisent pas dans une colonne de formulaire. */
  .contenu:has(.frise) {
    max-width: 1100px;
  }

  /* La synthèse est LARGE par vocation : une colonne par compte, et elle se
     consulte surtout sur PC. Exception déclarée ici, avec les deux autres —
     jamais une largeur écrite dans un gabarit, sans quoi trois écrans
     décideraient chacun de leur mise en page. */
  .contenu:has(.table-synthese) {
    max-width: 1240px;
  }

  /* --- Matrice (large) ---------------------------------------------------
     La liste redevient un tableau, et le tableau retrouve son sticky en
     croix. Tout ce qui suit ne vaut QUE ≥720px : en dessous il n'y a plus
     de colonnes, donc rien à figer et rien à faire défiler. */

  /* Cet écran est un CADRE : la page ne défile pas, le tableau si. C'est la
     seule disposition qui rende le collage vrai — une hauteur bornée « à la
     louche » laissait le cadre déborder par le bas, et la page se remettait
     à défiler en emportant l'en-tête collé. */
  body:has(.table-synthese) {
    display: flex;
    flex-direction: column;
    /* Hauteur DÉFINIE, et c'est indispensable : sans elle il n'y a pas
       d'espace libre à répartir, `flex: 1` ne contraint plus le cadre, et
       c'est la PAGE qui se remet à défiler (mesuré : cadre de 917px). Pas
       d'`overflow: hidden` pour autant — sur un écran trop court, le cadre
       garde son plancher et la page reprend son défilement plutôt que de
       coincer le tableau dans une fente de 65px. */
    height: 100vh;
    height: 100dvh; /* iOS : `vh` fige la hauteur d'avant la rétraction de la barre d'adresse */
  }

  body:has(.table-synthese) .contenu {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0; /* sans quoi un enfant qui déborde pousse le cadre hors de l'écran */
    /* `width: 100%` n'est pas une redondance : `.contenu` porte `margin: 0
       auto` pour se centrer, et une marge automatique dans l'axe transverse
       ANNULE l'étirement d'un élément flex — il retombe alors sur sa largeur
       de contenu (mesuré : 628px dans un écran de 375). */
    width: 100%;
  }

  .table-defilante {
    /* `position: relative` n'est PAS décoratif : sans ancêtre positionné, le
       débordement du tableau collant remonte jusqu'au document — la page
       gagnait 468px de vide sous la légende, dans lesquels elle défilait
       pour de bon (mesuré en fenêtre réelle, pas seulement en émulation).
       Le cadre devient le bloc conteneur, et le débordement reste dedans. */
    position: relative;
    overflow: auto;
    flex: 1;
    min-height: 12rem;
  }

  /* `border-collapse: collapse` FAIT DISPARAÎTRE les bordures des cellules
     collantes (les bords fusionnés appartiennent alors au tableau, qui
     défile, pas à la cellule qui reste). D'où `separate` + `border-spacing:
     0`, et des bordures portées par les cellules elles-mêmes. */
  .table-synthese {
    --h-entete: 34px; /* la hauteur de l'en-tête de colonnes, d'où part celui des foyers */
    display: table;
    border-collapse: separate;
    border-spacing: 0;
    font-size: var(--taille-corps-sm);
    white-space: nowrap;
  }

  .table-synthese thead {
    display: table-header-group;
  }

  .table-synthese tbody {
    display: table-row-group;
  }

  .table-synthese tbody tr {
    display: table-row;
    padding: 0;
    border: none;
    gap: 0;
  }

  /* RÉGRESSION CORRIGÉE (introduite avec la liste mobile) : la règle
     `.table-synthese tbody tr.synthese-foyer-entete { display: block }`
     compte DEUX classes, celle juste au-dessus une seule — elle l'emportait
     donc jusqu'ici, et la ligne de foyer restait un bloc en large. Sa
     cellule à `colspan` se dimensionnait alors sur son contenu (354px au
     lieu de 1159) et élargissait la colonne des noms d'autant. Invisible
     tant que la bande était grise sur fond blanc ; flagrant dès qu'on la
     teinte. Troisième fois que ce piège de spécificité mord sur cet écran :
     ici on répond avec la MÊME spécificité, la requête média tranchant par
     l'ordre. */
  .table-synthese tbody tr.synthese-foyer-entete {
    display: table-row;
    padding: 0;
  }

  /* AUCUN trait entre les lignes de participants : c'est ce qui donnait
     l'aspect « grille administrative ». Les seules bordures horizontales
     restantes encadrent les bandes de foyer — elles séparent des GROUPES,
     ce qui est une information ; un trait sous chaque personne n'en était
     pas une. */
  .table-synthese th,
  .table-synthese td {
    display: table-cell;
    padding: var(--espace-2) var(--espace-3);
    text-align: left;
    border-bottom: none;
  }

  /* Le sticky est posé sur les CELLULES, jamais sur `thead`/`tr` : WebKit ne
     suit pas sur les conteneurs de lignes — la règle serait ignorée sur
     iPhone et sur personne d'autre, donc invisible en développement. */
  .table-synthese thead th {
    position: sticky;
    top: 0;
    z-index: 3;
    height: var(--h-entete);
    border-bottom: var(--bordure); /* la seule ligne que le retrait ci-dessus ne doit pas emporter */
    background: var(--gris-000); /* opaque, sinon le tableau défile en transparence dessous */
    font-size: var(--taille-petite);
    font-weight: 600;
    color: var(--gris-500);
    text-transform: uppercase;
    letter-spacing: 0.02em;
  }

  /* La colonne des noms : sans elle, défiler vers Alcool laissait des lignes
     d'« Exempté » sans savoir de qui il s'agit. */
  /* La bordure DROITE reste, seule bordure conservée hors des bandes :
     elle n'est pas décorative, c'est la couture de la colonne figée — sans
     elle, les noms se confondent avec les colonnes qui défilent dessous dès
     qu'on rétrécit la fenêtre. */
  .table-synthese th[scope="row"] {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--gris-000);
    border-right: var(--bordure);
  }

  /* Le coin : il croise les deux, il passe donc au-dessus des deux. */
  .table-synthese thead th:first-child {
    left: 0;
    z-index: 4;
    border-right: var(--bordure);
  }

  .table-synthese .col-coef,
  .table-synthese .col-compte {
    text-align: center;
  }

  .col-coef {
    font-size: inherit;
    color: inherit;
    white-space: normal;
  }

  /* Les étiquettes « repas »/« nuitée » appartiennent à la liste : ici c'est
     l'en-tête de colonne qui le dit. */
  .col-coef::before,
  .col-coef + .col-coef::before {
    content: none;
  }

  /* En matrice, toutes les cellules sont montrées — c'est la lecture en
     colonne qui fait l'écran. */
  .table-synthese .col-compte--participe {
    display: table-cell;
  }

  .col-compte--sans_objet .cellule-sans-objet {
    display: inline;
  }

  /* Le compte est déjà nommé par l'en-tête de colonne : la mention reste
     LUE (elle sert au lecteur d'écran) mais quitte l'affichage. */
  .mention-compte,
  .mention-sans-objet {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* La bande de foyer : accent DILUÉ et liseré à gauche, IDENTIQUES pour
     tous. C'est de la structure — « ici commence un autre groupe » — pas de
     l'identité : une couleur par foyer reviendrait sur la règle du
     monogramme (le budget couleur est réservé au sens). Le fond reste plus
     pâle que `--accent-surface` pour que la pastille du foyer COURANT, qui
     l'utilise, se détache encore posée dessus. */
  .synthese-foyer-entete th {
    position: sticky;
    top: var(--h-entete); /* juste sous l'en-tête de colonnes, jamais dessus */
    z-index: 2;
    /* Padding SYMÉTRIQUE. Il y avait `padding-top: var(--espace-4)` seul,
       hérité de l'époque où la bande n'était qu'un fond gris et devait
       s'écarter du groupe précédent : 16px en haut contre 8 en bas, le nom
       et sa pastille tombaient visiblement bas dans la bande (mesuré).
       Maintenant qu'elle porte un liseré et une teinte, elle se sépare
       toute seule — la respiration n'a plus à être payée par un décentrage. */
    padding-top: var(--espace-3);
    padding-bottom: var(--espace-3);
    background: var(--accent-bande); /* opaque : c'est ce qui masque les lignes qui passent dessous */
    border-top: var(--bordure);
    border-bottom: var(--bordure);
    border-left: 3px solid var(--accent);
  }

  /* La première bande touche l'en-tête de colonnes, qui porte déjà sa
     ligne : deux traits collés se verraient. */
  .synthese-foyer:first-of-type .synthese-foyer-entete th {
    border-top: none;
  }

  .synthese-foyer-rangee {
    /* Collant à GAUCHE dans sa cellule : celle-ci fait toute la largeur du
       tableau (colspan), donc sans ça le nom du foyer partirait à droite dès
       qu'on défile vers les comptes — une bande grise anonyme entre deux
       groupes. La cellule colle en haut, son contenu colle à gauche : c'est
       la croix, sur une ligne qui n'a qu'une cellule. */
    position: sticky;
    left: 0;
    width: fit-content;
    max-width: 100%;
  }

  .legende-synthese .legende-large {
    display: flex;
  }

  /* En matrice, TOUT est indiqué — coche comprise. La phrase de la liste y
     serait fausse, pas seulement inutile. */
  .aide-liste {
    display: none;
  }

  /* La liste garde la même structure en large : une seule mise en page à
     maintenir, elle tient déjà des deux côtés du point de rupture. */
}

/* --- Mise en route : la bannière et l'écran d'avancement ------------------
   NI ORANGE NI ROUGE, et ce n'est pas une préférence : une configuration
   incomplète est un état NORMAL au début du séjour, pas un défaut. Le
   bandeau d'anomalies (--texte-anomalie) dit « un calcul est faux » ; celle-
   ci dit « il reste quelque chose à faire ». Les confondre apprendrait à
   ignorer le premier.

   Deux poids délibérément différents : l'action porte l'accent dilué et un
   liseré, l'information reste sur la bordure neutre des cartes ordinaires. */
.banniere-config {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--espace-3);
  margin-bottom: var(--espace-5);
  padding: var(--espace-3) var(--espace-4);
  border-radius: var(--rayon);
}

.banniere-config--action {
  background: var(--accent-surface);
  border: 1px solid var(--accent);
}

.banniere-config--info {
  background: var(--gris-000);
  border: var(--bordure);
}

/* Le texte pousse le bouton en bout de rangée, et passe seul à la ligne en
   étroit : `flex: 1 1 200px`, jamais une largeur fixe — le nom d'un foyer
   est libre et la phrase de conséquence est longue. */
.banniere-config-texte {
  flex: 1 1 200px;
}

/* Alignée sur le TITRE et non sur le bloc de texte : la sous-ligne passe à
   deux lignes en étroit, et une icône centrée verticalement se retrouve
   alors en face du vide entre les phrases. */
.banniere-config-icone {
  flex: none;
  align-self: flex-start;
  margin-top: 2px;
  color: var(--gris-700);
}

.banniere-config--action .banniere-config-icone {
  color: var(--accent);
}

.banniere-config-titre {
  margin: 0;
  font-size: var(--taille-corps-lg);
  font-weight: 600;
}

/* LA sous-ligne : elle énonce la conséquence. Sans elle, la bannière dit
   qu'il manque quelque chose sans dire ce que ça coûte — or ce que ça coûte
   est un zéro parfaitement crédible dans les comptes. */
.banniere-config-suite {
  margin: var(--espace-1) 0 0;
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
}

.banniere-config-bouton {
  flex: none;
}

.liste-avancement {
  list-style: none;
  margin: 0;
  padding: 0;
  border: var(--bordure);
  border-radius: var(--rayon);
  overflow: hidden;
}

.avancement {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--espace-2) var(--espace-5);
  padding: var(--espace-3) var(--espace-4);
  border-bottom: var(--bordure);
}

.avancement:last-child {
  border-bottom: none;
}

/* ATTÉNUER CE QUI EST NORMAL, LAISSER RESSORTIR CE QUI DIFFÈRE — même
   principe que l'écran Participants. Un foyer complet est le cas attendu :
   son état part en gris clair. Le manque, lui, reste en pleine encre. Pas
   d'aplat teinté sur la rangée : le budget couleur est réservé au sens
   (sélection, créancier/débiteur), et « pas encore rempli » n'est pas un
   avertissement. */
.avancement--complet .avancement-etat {
  color: var(--gris-500);
}

.avancement--incomplet .avancement-etat {
  color: var(--gris-900);
  font-weight: 600;
}

/* Le nom prend la place restante ; l'état et l'action se rangent à droite et
   passent à la ligne ensemble en étroit. Une rangée flex sans `flex-wrap`
   qui mêle un élément souple et des éléments à largeur fixe écrase le
   souple au lieu de se replier (défaut vécu sur .carte-foyer-entete). */
.avancement-foyer {
  display: flex;
  align-items: center;
  gap: var(--espace-2);
  flex: 1 1 160px;
  font-weight: 600;
}

/* Même traitement que les noms de l'écran Participants : un nom de foyer
   reste du TEXTE, souligné au survol seulement. Le bleu natif d'un <a>
   introduirait une couleur que la charte n'a pas. */
.avancement-foyer a {
  color: inherit;
  text-decoration: none;
}

.avancement-foyer a:hover {
  text-decoration: underline;
}

.avancement-etat {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-1);
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
}

/* En texte AUSSI, jamais en couleur seule : « Complet » se lit en noir et
   blanc, la coche ne fait que le confirmer. */
.avancement-coche {
  color: var(--texte-creancier);
}

.avancement-action {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-1);
  min-height: var(--cible-min);
}

.avancement-fini {
  margin-top: var(--espace-4);
  font-size: var(--taille-corps-sm);
  color: var(--gris-500);
}

/* En étroit, le nom prend TOUTE la rangée et l'état passe dessous avec son
   action : sinon la mise en page dépend de la longueur du libellé d'état
   (« Aucun membre » tient à côté du nom, « Aucune date de présence » non),
   et deux foyers voisins ne se lisent pas de la même façon. */
@media (max-width: 719px) {
  .avancement-foyer {
    flex: 1 1 100%;
  }

  .avancement-action {
    margin-left: auto;
  }
}

/* --- Le parcours organisateur et l'écran d'invitation --------------------- */

.banniere-config-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--espace-3);
}

.etapes-parcours {
  list-style: none;
  margin: 0 0 var(--espace-6);
  padding: 0;
}

.etape {
  display: flex;
  align-items: flex-start;
  gap: var(--espace-3);
  padding: var(--espace-3) 0;
  border-bottom: var(--bordure);
}

.etape:last-child {
  border-bottom: none;
}

/* Le numéro porte l'ordre, donc le sens de lecture — pas une décoration.
   `flex: none` : sans lui, un cercle se déforme en ovale dès que le résumé
   pousse la rangée. */
.etape-numero {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 28px;
  height: 28px;
  border: var(--bordure);
  border-radius: 50%;
  font-size: var(--taille-corps-sm);
  font-weight: 600;
  color: var(--gris-700);
}

.etape--faite .etape-numero {
  background: var(--accent-surface);
  border-color: var(--accent);
  color: var(--accent);
}

.etape-corps {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 160px;
}

.etape-titre {
  font-weight: 600;
  color: var(--gris-900);
  text-decoration: none;
}

.etape-titre:hover {
  text-decoration: underline;
}

.etape-resume {
  font-size: var(--taille-corps-sm);
  color: var(--gris-500);
}

.etape-etat {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-1);
  font-size: var(--taille-corps-sm);
  color: var(--gris-500);
}

.etape-coche {
  color: var(--texte-creancier);
}

.titre-section {
  margin: 0 0 var(--espace-3);
  font-size: var(--taille-corps-lg);
}

/* Le fil du parcours, en bas d'écran : il conclut, il ne surplombe pas.
   Un bandeau en haut concurrencerait la bannière de mise en route et
   repousserait le contenu — or ce contenu est précisément ce qu'on est venu
   remplir. */
.fil-parcours {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--espace-3);
  margin-top: var(--espace-6);
  padding-top: var(--espace-4);
  border-top: var(--bordure);
}

.fil-parcours-etape {
  flex: 1 1 160px;
  margin: 0;
  font-size: var(--taille-corps-sm);
  color: var(--gris-500);
}

.fil-parcours-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--espace-3);
}

.bloc-lien {
  margin-bottom: var(--espace-5);
  padding: var(--espace-4);
  background: var(--gris-000);
  border: var(--bordure);
  border-radius: var(--rayon);
}

/* Monospace : ce qu'on vérifie ici n'est PAS le jeton — quarante-trois
   caractères aléatoires ne se relisent pas — c'est l'HÔTE, au début, qui dit
   si le lien marchera depuis un autre appareil (`192.168.1.56` et non
   `localhost`). Le jeton peut donc dépasser à droite sans que ça coûte
   quoi que ce soit : personne ne le copie à la main, c'est tout le propos
   des deux boutons. */
.champ-lien {
  width: 100%;
  margin: var(--espace-2) 0 var(--espace-3);
  padding: var(--espace-2) var(--espace-3);
  background: var(--gris-050);
  border: var(--bordure);
  border-radius: var(--rayon);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
}

.actions-lien {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-3);
}

/* Le retour de copie : `hidden` tant que rien n'a été tenté, jamais une
   ligne vide qui réserverait sa place et ferait sauter le bloc. */
.retour-copie {
  margin: var(--espace-3) 0 0;
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
}

.avertissement-lien {
  display: flex;
  align-items: flex-start;
  gap: var(--espace-2);
  margin: 0 0 var(--espace-5);
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
}

.rappel-avancement {
  padding: var(--espace-3) var(--espace-4);
  background: var(--gris-050);
  border-radius: var(--rayon);
}

.rappel-avancement-titre {
  margin: 0;
}

.rappel-avancement-suite {
  margin: var(--espace-1) 0 var(--espace-2);
  font-size: var(--taille-corps-sm);
  color: var(--gris-700);
}
